Canvas Radar
This article is a stub. You can help the wiki by expanding it. |
This article describes content/features that may not yet be available in the latest stable version of FlightGear (2020.3). You may need to install some extra components, use the latest development (Git) version or even rebuild FlightGear from source, possibly from a custom topic branch using special build settings: .This feature is scheduled for FlightGear 4.x. If you'd like to learn more about getting your own ideas into FlightGear, check out Implementing new features for FlightGear. |
Started in | 02/2014 |
---|---|
Description | Radar Framework |
Maintainer(s) | 5H1N0B1, Hooray |
Contributor(s) | |
Status | Under active development as of 02/2014 |
Topic branches: | |
fgdata | canvas-hackers team clone (topics/canvas-radar) |
Subforum | http://forum.flightgear.org/viewforum.php?f=71 |
The FlightGear forum has a subforum related to: Canvas |
Canvas Radar is a MapStructure-layer for creating Radar displays in FlightGear using Nasal and Canvas, as of 02/2014 it is being actively developed by 5H1N0B1 with a focus on the Mirage 2000-5 fighter jet. The Radar implementation is heavily based on xiii's original code and will be further generalized and adapted to be usable in the MVC-centric design of Philosopher's MapStructure framework.
The Radar framework is being closely developed in conjunction with F-JYL's CanvasMFD framework to ensure that aircraft developers can easily adopt the framework in their own aircraft, without having to modify a ton of Nasal code.
Note Contributors wanting to check out the topics/canvas-radar fgdata branch, need to follow these 3 steps:
This will give you a local branch named canvas-radar, so that you can easily pull/push changes. When pulling, it makes sense to pull with --rebase |
Objective
Come up with a generic radar framework for MapStructure that is completely aircraft-agnostic, so that it can be easily adopted, integrated and customized by aircraft developers, but also by people doing ATC related projects, like ATC-FS or ATC-aircraft.
Currently, we're in touch with Adrian to see if his Radio Propagation could be rebased against git/next and exposed via Nasal/CppBind to provide a better option for radar modeling. This is something that we should probably discuss with xiii (developer of the original Nasal code) and vivian (agradar developer) at some point, vivian also expressed interest in updating the agradar to support the Radio Propagation code written by Adrian[4].
Also, i4dnf mentioned that we could benefit from making antenna profiles configurable for different aircraft. Adrian mentioned that he has access to the radar manual of the F16 and that he's familiar with the various operating modes.
The Flightgear Next Gen Radar would be able to (not sorted) :
- Be a lot faster as actual system (Using Canvas display and some C++ for high consuming function)
- Detect Heat/infrared
- Manage AESA radar. (Actually it's more complicated to manage non AESA radar -> cause of the sweep. -> No sweep for AESA)
- Manage DOPPLER radar DOPPLER (Actually, more complicated to manage "non doppler" radar. The purpose is to erase signature of airplane which are bellow us, and fly at low alt. We could even erase 0 kts aircraft -> The Pougatchev's Cobra should be able to make stall DOPPLER radar)
- BONUS : Terrain detection. Make an aircraft disapear if it's behind a mountain
- With the terrain detection : Allow to have a fast Terrain Following Mode
- Make it working with existing Radio Propagation code.
- Manage IFF/Transponder
- Display Radar on Nav Mfd
- Allow more than one radar on a plane, like AWACS or Russian aircraft which have a rear radar
- Manage laser targeting -> with a pod view and clicking (for non AI target like building)
- Allow simple re use of the radar on each aircraft military and also civilian
- Long term obj : Put a radar object in "each" missile on the missile.nas script
- More ?
Status
Currently, we're playing around with a modified version of the MapStructure TFC (traffic) layer, to use this in a standalone XML dialog and customize it as needed. Once that is working as expected, we will investigate adding xiii's radar modeling code and replace the traffic/TCAS functionality accordingly. Afterwards, we will need to integrate this with the Canvas MFD Framework to ensure that aircraft developers can easily use the framework in their cockpits.
At that point, it would then also make sense to check out the Category:Fighter aircraft and Category:Carrier-based aircraft categories to get in touch with the developers and maintainers of aircraft with RADAR, and ask them for adoption/integration feedback.
Subsequently, it would make sense to look at existing hard-coded displays, like the agradar, groundradar and wxradar to support these use-cases, too. Specifically, ATC-FS and ATC-aircraft could greatly benefit from this effort.
5H1N0B1 also mentioned that a properly-designed component would allow other uses, too - such as for example, equipping Scripted AI Missiles with a real RADAR, or adding radar support to Bombable - likewise, it would be possible to add such radar displays to AWACS aircraft, or even to vessels like the Nimitz.
- Mirage 2000-5 (5H1N0B1)
- Saab JA-37 Viggen (Necolatis)
- Mig-29 (Mercury) Not done
- Grumman F-14 Tomcat (xiii) Not done
Radar/ATC Requirements
These are primarily requirements for the Mirage2000 that is currently being revamped by 5H1N0B1[5], these changes could also be used to add ATC support to AWACS aircraft[6].
- Set up a dialog-based test bed Done
- Prototype a simple ATC/RADAR layer
- Terrain layer (elevation height maps using the terrain presampler) see: [7] and [8] Not done (by 5H1N0B1)
- Custom Controllers for:
- select and animate symbols (targets) Not done (by 5H1N0B1)
- TCAS/transponder awareness for symbol animation/styling Not done (by 5H1N0B1)
- explore integrating this with Adrian's Radio propagation system via cppbind (Hooray) Not done
Also see ATC-FS and ATC-aircraft
Development
Displaying Scenery Objects
Note If you are adapting an existing navaid layer (e.g. NDB), you may still want to change your lcontroller file to provide a custom layer.searcher._equals function, and make it inherit from MultiSymbolLayer instead of NavaidSymbolLayer. To change the SVG symbol, change the path in your .symbol file accordingly. |
diff --git a/Nasal/canvas/map/DEMO.lcontroller b/Nasal/canvas/map/DEMO.lcontroller
new file mode 100644
index 0000000..c8ea442
--- /dev/null
+++ b/Nasal/canvas/map/DEMO.lcontroller
@@ -0,0 +1,45 @@
+# See: http://wiki.flightgear.org/MapStructure
+# Class things:
+var name = 'DEMO';
+var parents = [SymbolLayer.Controller];
+var __self__ = caller(0)[0];
+SymbolLayer.Controller.add(name, __self__);
+SymbolLayer.add(name, {
+ parents: [MultiSymbolLayer],
+ type: name, # Symbol type
+ df_controller: __self__, # controller to use by default -- this one
+ df_style: {},
+});
+var new = func(layer) {
+ var m = {
+ parents: [__self__],
+ layer: layer,
+ map: layer.map,
+ listeners: [],
+ };
+ layer.searcher._equals = func(l,r) 0;
+ m.addVisibilityListener();
+
+ return m;
+};
+var del = func() {
+ foreach (var l; me.listeners)
+ removelistener(l);
+};
+
+var searchCmd = func() {
+ print("DEMO.lcontroller searchCmd():");
+ var offset_deg = 30;
+ var offset_distance = 9000;
+ var results = [];
+
+for(var i=0; i<360;i+=offset_deg) {
+
+ var pos = geo.aircraft_position();
+ pos.apply_course_distance(i, offset_distance);
+ append(results, geo.Coord.new(pos) );
+ # print("Looping:", i);
+ }
+return results;
+}
+
diff --git a/Nasal/canvas/map/DEMO.symbol b/Nasal/canvas/map/DEMO.symbol
new file mode 100644
index 0000000..7848330
--- /dev/null
+++ b/Nasal/canvas/map/DEMO.symbol
@@ -0,0 +1,7 @@
+# See: http://wiki.flightgear.org/MapStructure
+DotSym.makeinstance('DEMO', {
+ parents: [SVGSymbol],
+ svg_path: "/gui/dialogs/images/ndb_symbol.svg",
+ #cacheable: 1,
+});
+
diff --git a/gui/dialogs/map-canvas.xml b/gui/dialogs/map-canvas.xml
index 6475325..e1bd439 100644
--- a/gui/dialogs/map-canvas.xml
+++ b/gui/dialogs/map-canvas.xml
@@ -427,7 +427,7 @@
# TODO: introduce some meta NAV layer that handles both VORs and NDBs, can we instantiate those layers directly ?
var r = func(name,vis=1,zindex=nil) return caller(0)[0];
# TODO: we'll need some z-indexing here, right now it's just random
- foreach(var type; [r('TFC',0),r('APT'),r('DME'),r('VOR'),r('NDB'),r('FIX',0),r('RTE'),r('WPT'),r('FLT'),r('WXR',0),r('APS'), ] ) {
+ foreach(var type; [r('DEMO'), r('TFC',0),r('APT'),r('DME'),r('VOR'),r('NDB'),r('FIX',0),r('RTE'),r('WPT'),r('FLT'),r('WXR',0),r('APS'), ] ) {
if (1 and type.name != 'APS' and type.name != 'FLT') make_update_wrapper(type.name);
TestMap.addLayer(factory: canvas.SymbolLayer, type_arg: type.name,
visible: type.vis, priority: type.zindex,
Once this works, you can basically refine your searchCmd() method, i.e. by using actual data from the "ufo editor"
Assuming that you're using this method: Howto:Place_3D_objects_with_the_UFO#Loading_the_XML_file_as_part_of_FlightGear_scenery ... then, you only need to open the XML file to see where those objects end up when loaded into the property tree. |
Creating a custom ATC/RADAR Layer
People already having some Nasal experience (property tree, OOP), should be able to complete this 20-30 minutes, and you would end up with an ATC display and a custom symbol - next, you will want to "filter" traffic based on surrrounding features like terrain, altitude, radar settings and radio propagation etc.
If you find yourself getting stuck somewhere, look at some of the other .symbol/.lcontroller and .scontroller files - especially the shorter/simpler ones - and then read the wiki section about adding new layers a few times, and everything will start making sense
Basically, this should get you going quickly:
- copy an existing set of files (better TFC* instead of VOR*), but name it "TARGET" instead of TFC: TARGET.symbol, TARGET.lcontroller, TARGET.symbol (RADAR may be a more appropriate name)
- you need to change the name to TARGET inside the 3 new TARGET* files (see the top of the new files, where 'TFC' can be seen)
- start by opening TARGET.scontroller and replace TFC with TARGET
- next, open TARGET.symbol - this contains the draw() and update() callbacks to draw/update a single symbol and animate it accordingly, also replace TFC with TARGET
- next, open TARGET.lcontroller - this contains the layer management code, a layer manages a vector of symbols, replace TFC with TARGET
- now, add the new files to your instrument/display/dialog: there's typically a vector that contains the layer names to load, e.g. "VOR", "DME", and "TFC", and so you will need to add "TARGET" there as well. This is to tell the framework about your newly created layer files.
- once that is done, use the new "TARGET" identifier in the foreach vector in the Nasal section of the dialog seen above and its embedded canvas/nasal/load block
- this should give you a TCAS traffic (TFC) symbol using the TARGET handle when you run the dialog
(5H1N0B1 : I'm here)
- once that is working, you can customize the symbol by opening the TARGET.symbol file which contains the draw routine - for example by changing the color or using some custom font/label, or just using a SVG file via parsesevg() - see the NDB.draw file for an example on how to display a custom SVG file
- at this stage you should have a custom symbol rendered in all the places where MP/AI traffic is located, all driven via the TCAS function.
- so the next step is to make the code a bit smarter, especially look at the TFC.lcontroller and TFC.scontroller files
- it may even be a good idea to directly start with those, instead of the VOR files ...
- once that is working, i.e. 1) you have a custom symbol shown and see all the surrounding MP/AI traffic, you have already successfully created a simple ATC/radar screen!
- next, you would replace the data source (which is AI/MP traffic) with your own data source - for that, refer to the TARGET (TFC) files to see how the AI/MP traffic is added
- once you have added your own data source, you can change the heuristics accordingly - to handle terrain, radar range etc.
- your own objects should ideally be geo.nas Coord objects - that way, the system can directly support your traffic, you only need to derive from geo.Coord to make this happen:
var myPosition3D = {
new: func {
return {parents:[geo.Coord.new() ]};
},
};
Next, you will want to investigate the positionedSearch class, which provides a powerful means to do range-based filtering of positioned objects, these can in turn be filtered (searched) for other characteristics, i.e. based on range, terrain, radio propagation or heat etc. Take a look at TARGET.lcontroller and its searchCmd() helper.
If you need help doing this, please check out the canvas subforum, and also post some screen shots, so that we can better help you It would be a good idea to also start a fgdata topic branch so that we can better track your work and look at the code.
Custom Filtering
Once the previously outlined steps are working, I would consider customizing the searchCmd in your lcontroller file. At the moment, TFC.lcontoller works like this https://gitorious.org/fg/fgdata?p=fg:fgdata.git;a=blob;f=Nasal/canvas/map/TFC.lcontroller;hb=c78b2f936891bffad49e27d84d952a0d45540eef
- get a list of AI and MP traffic (two vectors)
- foreach list of AI and MP traffic
- determine if each aircraft is within the range specified via in_range: https://gitorious.org/fg/fgdata?p=fg:fgdata.git;a=blob;f=Nasal/canvas/map/TFC.lcontroller;hb=c78b2f936891bffad49e27d84d952a0d45540eef#l50
- PLACEHOLDER
- if it is in range, the aircraft will be appended to the result vector
- the result vector will be returned, and later on used to call the draw/update routines in the *.symbol file (e.g. TRAFFIC.symbol)
The line where I added PLACEHOLDER is where you could insert your own logic, i.e. the radar-specific stuff from xiii's code - such as checking distance, azimuth, altitude - radar profile/signature, terrain etc - and only append the aircraft if the whole check evaluates to true.
You will find that the whole lcontroller file uses a wrapper called "TrafficModel" - you can either extend this to use your "Target" class directly, or change your Target class accordingly. The main thing is that your class should be derived from a geo.Coord object, so that it has the lat/lon/alt methods available and can be directly processed by MapStructure without requiring further changes.
You will see that the TrafficModel class is used in a few places - so this would need some changes if you use some different approach, but it's still simple. The external interface is all about having lat/lon/alt (positions) and the .equals() method Overall, TrafficModel is just a dumb helper class that is a wrapper for geo.Coord() objects, so there's no reason why you shouldn't be able to extend your own Target class accordingly, you can use the TrafficModel as a template. I would just suggest to maintain the MVC separation at all times.
Analogous to the in_range() helper, you could add other functions for your own filtering needs (altitude, terrain-obstruction etc) - it's better to use separate functions for each, than inflating a single function unnecessarily. As you can see, the in_range() function is unaware of TrafficModel specifics -it deals directly with lat/lon pairs..
So it's simple to reuse as is. TrafficModel itself is typically directly used via the constructor call: .new()