Canvas ND framework: Difference between revisions

From FlightGear wiki
Jump to navigation Jump to search
Line 32: Line 32:


If you are facing problems with the steps outlined above, please get in touch via the article's talk page or the forum, so that the instructions can be improved accordingly. Thank you!
If you are facing problems with the steps outlined above, please get in touch via the article's talk page or the forum, so that the instructions can be improved accordingly. Thank you!
More detailed instruction. See if it could help.
ND integration: How it was done on the mirage 2000 :
The integration is simple :
0) Have a update compiled version of flightgear.
1) Have the 3D model in this way :
3D MFD ->
  - a) 3D Border (border of the screen, with scew etc)
  - b) 3D Button/swith, molette, turnable button
  - c) A 3D Screen object, with :
    - perfect size
    - Single texture, -> with perfect size
    - Perfect size of the UVmap
2) Copy pasta ND.nas
2.1)Add the ND.nas in your basis xml file at Nasal part.
3) Edit ND.nas :
  -a) Rename the screen to match with the object in 1)c)
  -b) If it a single mfd, you do not need another object, so suppress the line (when it's calling the object itself)
  -c) Keep the properties name -> it's just ok. We just need to input it with xml button in 1)b)
4) Code the xml itself.
Really simple, it's just playing with properties : for example this for airport property :
  <!--######################## Airports ############################-->
  <animation>
    <type>pick</type>
    <object-name>bt-h1</object-name>
    <visible>true</visible>
    <action>
        <button>0</button>
        <binding>
        <command>property-toggle</command>
        <property>/instrumentation/efis/inputs/arpt</property>
        </binding>
    </action>
  </animation>
Or here again for the range selection :
  <animation>
    <type>pick</type>
    <object-name>trim1</object-name>
    <action>
      <button>4</button>
      <!--  scroll up -->
      <repeatable>false</repeatable> 
      <binding>
                <command>property-cycle</command>
                <property>/instrumentation/efis/inputs/range-nm</property>
                <value>10</value>
                <value>20</value>
                <value>40</value>
                <value>80</value>
                <value>160</value>
                <value>320</value>
      </binding> 
    </action>
  </animation>
  <animation>
    <type>pick</type>
    <object-name>trim1</object-name>
    <action>
      <button>3</button>
      <!--  scroll up -->
      <repeatable>false</repeatable>
 
      <binding>
                <command>property-cycle</command>
                <property>/instrumentation/efis/inputs/range-nm</property>
                <value>320</value>
                <value>160</value>
                <value>80</value>
                <value>40</value>
                <value>20</value>
                <value>10</value>             
      </binding> 
    </action>
  </animation>
5) Then you can optionnaly put this :
  <animation>
  <type>pick</type>
  <object-name>blackbkd</object-name>
  <action>
      <button>0</button>
      <repeatable>false</repeatable>
      <binding>
        <command>nasal</command>
        <script>mirage2000.showNd();</script>
      </binding>
  </action>
  </animation>
Where 'blackbkd' is the screen 1)c). This last thing allow you to open a dialog box with what the actual canvas should display in your 1)c) screen. This is very usefull to check all the differents step when something isn't working well.
Normally following these step, you should have a working Mfd.


=== Cockpit switches ===
=== Cockpit switches ===

Revision as of 15:33, 19 February 2014

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 (unknown). 10}% completed

If you'd like to learn more about getting your own ideas into FlightGear, check out Implementing new features for FlightGear.

Canvasready.png
NavDisplay
MAP mode with a SID from Eindhoven Airport
MAP mode with a SID from Eindhoven Airport
Started in 11/2013
Description Canvas/Nasal driven NDs
Maintainer(s) Gijs, Hyde, Hooray, Philosopher
Contributor(s) User:Gijs (since 11/2013)
Status Under active development as of 12/2013

The navigation display (ND) is a display in a glass cockpit, providing information about an aircraft's lateral situation. As of late 2013, a new ND (Navigation display being the old) is in development for FlightGear using the new MapStructure back-end for charting purposes, and SVG symbols animated via Nasal functions for any non-mapping aspects. Thanks to Canvas, much more complex and sophisticated graphics are possible now, without having to know any C++, and without having to rebuild FlightGear from source. Anybody able to run FlightGear and a text editor, can now easily use and extend the ND framework.

It can be found on Git in fgdata/master (2.99). The main source is located in [1].

Adding the navigation display to your aircraft

The new ND is available in FlightGear 3.0 as of February 2014.

Note that the latest ND code is currently only available in Git and not in the latest stable release.

  1. Add a surface object to your 3D model and apply a place holder texture to it. You can refer to the 747-400 and 777 for examples.
  2. Copy the ND.nas file of the Boeing 777 into your own aircraft directory ([2]).
  3. Add the file to the <nasal> block in your aircraft's -set.xml file.
  4. In order to customize the ND for your specific aircraft, change a few options in your ND.nas file:
    1. the node behind addPlacement is the name of the object in your 3D model. For multiple independent NDs, each ND should have its own object (and thus placement node). The 777 for example has a "ndScreenL" and a "ndScreenR".
    2. Rename the properties in the "myCockpit_switches" hash at the top of the ND.nas file to match your own properties (range selector, mode selector etc.), see [3] You're advised to use the defaults (and change other systems of your aircraft accordingly). For an overview of switches, see #Cockpit switches.
  5. Add knobs/buttons to the 3D model of your cockpit to control the various options of the ND. See [4] for an example.
  6. Add a binding to your screen(s) to open the ND in a popup dialog. See [5] for an example.

That's the only thing you need to do right now. future changes will be in navdisplay.mfd and will be automatically available to you once they're committed/merged, no changes needed in your ND.nas at all, except for additional switches/buttons that may be created, and which would obviously need to be mapped to your cockpit hot spots.

If you are facing problems with the steps outlined above, please get in touch via the article's talk page or the forum, so that the instructions can be improved accordingly. Thank you!

More detailed instruction. See if it could help. ND integration: How it was done on the mirage 2000 : The integration is simple :

0) Have a update compiled version of flightgear.

1) Have the 3D model in this way :

3D MFD ->
  - a) 3D Border (border of the screen, with scew etc)
  - b) 3D Button/swith, molette, turnable button
  - c) A 3D Screen object, with :
    - perfect size
    - Single texture, -> with perfect size
    - Perfect size of the UVmap

2) Copy pasta ND.nas 2.1)Add the ND.nas in your basis xml file at Nasal part.

3) Edit ND.nas :

 -a) Rename the screen to match with the object in 1)c) 
 -b) If it a single mfd, you do not need another object, so suppress the line (when it's calling the object itself)
 -c) Keep the properties name -> it's just ok. We just need to input it with xml button in 1)b)

4) Code the xml itself. Really simple, it's just playing with properties : for example this for airport property :


 <animation>
   <type>pick</type>
   <object-name>bt-h1</object-name>
   <visible>true</visible>
   <action>
       <button>0</button>
       <binding>
        <command>property-toggle</command>
        <property>/instrumentation/efis/inputs/arpt</property>
       </binding>
   </action>
 </animation>


Or here again for the range selection :

 <animation>
   <type>pick</type>
   <object-name>trim1</object-name>
   <action>
     <button>4</button>
     <repeatable>false</repeatable>   
     <binding>
               <command>property-cycle</command>
               <property>/instrumentation/efis/inputs/range-nm</property>
               <value>10</value>
               <value>20</value>
               <value>40</value>
               <value>80</value>
               <value>160</value>
               <value>320</value>
     </binding>   
   </action>
 </animation>
 <animation>
   <type>pick</type>
   <object-name>trim1</object-name>
   <action>
     <button>3</button>
     <repeatable>false</repeatable>
 
     <binding>
               <command>property-cycle</command>
               <property>/instrumentation/efis/inputs/range-nm</property>
               <value>320</value>
               <value>160</value>
               <value>80</value>
               <value>40</value>
               <value>20</value>
               <value>10</value>              
     </binding>   
   </action>
 </animation>


5) Then you can optionnaly put this :

 <animation>
  <type>pick</type>
  <object-name>blackbkd</object-name>
  <action>
     <button>0</button>
     <repeatable>false</repeatable>
     <binding>
        <command>nasal</command>
        <script>mirage2000.showNd();</script>
     </binding>
  </action>
 </animation>


Where 'blackbkd' is the screen 1)c). This last thing allow you to open a dialog box with what the actual canvas should display in your 1)c) screen. This is very usefull to check all the differents step when something isn't working well.


Normally following these step, you should have a working Mfd.


Cockpit switches

Note  The default property is relative to the root location of your ND, it is NOT an absolute path. Boolean values (true/false) can also be just 1/0. The list of switches below is correct for FG 3.0 - future versions may support additional switches. In the future, we're also going to make the ND style-able this way, so that colors, fonts, size (LOD) and symbols can be customized easily via ND.nas
Switch Description Default property Accepted values
toggle_airports Display airports on the map /inputs/arpt true, false
toggle_centered Center ND modes /inputs/nd-centered true, false
toggle_data Display way point data on the map /inputs/data true, false
toggle_display_mode Change display mode /mfd/display-mode APP, MAP, PLAN, VOR
toggle_display_type Change display type /mfd/display-type CRT, LCD
toggle_position Display position data on the map (currently unused) /inputs/pos true, false
toggle_range Range of the maps in nautical miles /inputs/range-nm Any positive number
toggle_terrain Terrain radar (currently unused) /inputs/terr true, false
toggle_traffic Display TCAS data /inputs/tfc true, false
toggle_true_north Toggle true or magnetic north /mfd/true-north true, false
toggle_waypoints Display way points (fixes) on the map /inputs/wpt true, false
toggle_weather Weather radar /inputs/wxr true, false

Aircraft Support

For the framework to become sufficiently generalized and aircraft-agnostic, we need many different aircraft to adopt it and aircraft developers to provide feedback regarding missing features. We are looking for people interested in integrating the new system, so that it can be better developed with different requirements in mind.

The 747 and 777 are the primary reference examples for now. The following people/aircraft are currently in the process of adopting the new NavDisplay (please add any related efforts here):

  • 01/2014: Gijs (747-400) 100}% completed
  • 01/2014: Hyde (777-200) 100}% completed
  • 02/2014: mueko (A320) 90}% completed [6]
  • 02/2014: Soitanen (737-300) 80}% completed [7]
  • 02/2014: Sascha (A310) 10}% completed
  • 02/2014: drdavid (DC10) 30}% completed
  • 02/2014: 5H1N0B1 (m2000-5) 100}% completed

If you are finding yourself having problems integrating the framework, please refer to already integrated aircraft as reference/example, or get in touch with their maintainers - ideally, via the forum, so that everybody can contribute and benefit.

Note that this will initially just give you a Boeing-centric ND, because it is currently being developed by the 747/777 maintainers primarily - please use the issue tracker to file feature requests for missing features. Over time, the framework will grow and become more flexible,so that also specifics of non-Boeing aircraft can be properly emulated. But obviously this will take a while. We invite aircraft developers to help extend and refine the framework accordingly.

Gallery

Adding new features

Note  Please get in touch with User:Gijs before touching navdisplay.mfd

If you are primarily interested in porting/adding new mapping layers (such as e.g. waypoints, route, weather etc), please see the MapStructure article for details. Otherwise, this section is focused on dealing with non-mapping aspects, i.e. ND-specific SVG symbols and animating them via properties and calculations. Typically, a new symbol will require 10-20 lines of code added to navdisplay.mfd - it will typically take 5-10 minutes to add a new animated symbol to the ND.

If you want to add new features to the navdisplay.mfd code, you need to open that file and map an SVG element to a callback routine - that's how everything is working currently.

There's a "configuration hash" called "NDStyles" at the top of the file. Each aircraft can have its own entry in NDStyles, such as NDStyles["B747-400"] or NavDisplay["777"]. Then, all the required canvas callbacks are listed there, i.e. the font mapper etc.

There's also an entry for a custom SVG filename. However, we encourage people to get in touch with Gijs and Hyde to help coordinate all ND development a little - so that a common (and shared) SVG file can be used, this is already the case for the B744 and B777 - we're hoping to get other aircraft developers involved, to help generalize the SVG file, instead of having dozens of different files and symbols. Most features should be identical or at least very similar. Which is why it's a good idea to get in touch with other people working on the ND code.

Lines 52-131 set up existing layers, which are now shared with the GUI code - so that is where new layers are added. Aircraft specific SVG elements are added at the end, after line 132

For now, we suggest to directly use the 747-400 ND - but the framework is now prepared to easily style & customize it for different aircraft, we will probably add a tutorial to the wiki to explain how things are hanging together there. The constructor and init methods may still need some work to generalize things there, because they are basically still the original code.

So to replace the 747 ND and customize it, these are the steps:

  • add a new entry to the NDStyles hash, for example "777-200"
  • you can simply copy the configuration stuff from the 747 to get started
  • start customizing things there
  • open the SVG file in inkscape and change it as required, save it
  • change the SVG filename in your NDStyles["777-200"] hash entry to match your own file name
  • provide animation callbacks for any 777 specific elements
  • open your own copy of ND.nas
  • change the constructor call .new() to specify the name of your new NDStyles entry
  • by default, this is 747-400 for the time being, for example:
var NDCpt = ND.new("instrumentation/efis", myCockpit_switches, "777-200" );

the "777-200" part needs to match the identifier used in the NDStyles hash.

To get started, just copy the whole 747-400 section in NDStyles and rename it to match your needs. Once that is working (getting a 747-400 ND via the 777-200 identifier), you can simply replace the SVG file name and add your own update handlers to incrementally come up with your own ND.

Development

mapping vs. SVG animation

It would be really nice to have two sides to navdisplay.mfd: a map (your/my area) and svg ui (Gijs' and aircraft devs' responsibility) 0.o.

am all for supporting the two use-cases you mentioned - then again, the old code is fragile enough, so I wouldn't add to it - the main thing the old code was all about was establishing the MVC separation so that draw routines can be reused - and that's basically done, so no need to keep the old cruft around ...
Regarding the navdisplay stuff itself - well, it's pretty much the original code still, i.e. the design is only just evolving - algorithmically, it's still not very optimized - MapStructure only helps with mapping aspects obviously.
I was going to suggest the "SVG/element animation" separation too - but I think Gijs etc already need to handle quite a bit of re-thinking, because things are no longer as straightforward. In the long run, it will probably happen over time - especially once other things are generalized, especially for generic PFD/EICAS/CDU/EFB functionality - these would all benefit from a corresponding "symbol animation" abstraction eventually like TheTom mentioned on the forum: PFD: A common framework in the background
Honestly, it would have been great to have such a framework to implement MapStructure on top of it - but obviously, it's a chicken/egg issue :-)
Currently, the main danger here is that people are going to start using copy & paste again to adopt things like Gijs' PFD, like mentioned by Zakalawe: if someone provides a 'system' I'll use it but I'm not interested in writing it myself
So the real question is if people can be convinced to team up and come up with a generic and reusable design, or follow the original PFD/ND approach instead - interestingly, most of TheTom's work in this area (MCDU/EICAS) seems pretty reusable, also outside aircraft, i.e. usable via the GUI.

After having looked at navdisplay.mfd, I think we only need to separate a few things using io.include() to make this happen automatically over time - all the 747/Boeing-specific stuff would be moved into "config" hashes and factored out of navdisplay.mfd - into something like "boeing747.nd" that would leave us with very little code remaining in navdisplay - basically a single class and a few methods with foreach loops.

So we would end up with a layered design like this:

  • boeing.nd (config hashes via io.include)
  • navdisplay (down-stripped code, aircraft-agnostic)
  • MapStructure (needs no changes)
  • Symbol/Animation Layer (shared with PFD, ND, CDU, EFB, would be developed/grown over time)
  • canvas APIs (as is)
  • canvas subsystem (as is)
  • OSG / Shiva (as is)

Misc

  • use switches hash to procedurally create a GUI dialog with buttons for each toggle_action (TFC,CTR,WXR etc) Not done Not done
  • make sure that the frameworks with properly with time-warp, sim-rate speed-up and replay Not done Not done
  • remove (old) disabled layers
  • make the timer update interval configurable via constructor Not done Not done
  • consider adding hooks to generalize those huge conditionals in update() some more Not done Not done
  • use foreach() to hide()/show() or setVisible() groups of symbols Not done Not done
  • make this more aircraft agnostic by getting rid of 747/Boeing specific assumptions Not done Not done
  • unify switch/case|default handling (again, huge conditionals in there) Not done Not done
  • on_update() helper should probably support global listeners and timers, too - i.e. via a hash spec ? Not done Not done
  • the whole symbol lookup needs to cleaned up (getElementById etc) Not done Not done
  • introduce a common "compute" field in the update/predicate hash and make its results available to is_true/false etc Not done Not done
  • use io.include to include boeing specific stuffNot done Not done
  • NDSoruceDriver should be generalized and combined with MapStructure's aircraftpos.controller Not done Not done
  • the radio/autopilot listeners need to be set up in the lcontroller file, they're just empty stubs for now Not done Not done
  • there are 3 foreach loops in newMFD() setting up symbols currently-we only need ONE: loop 2+3 should be removed and use the loop #1 method Not done Not done
  • clean up the ctor and generalize the newMFD() method Not done Not done
  • move stuff out of the update() method into the aircraft-specific configuration hash Not done Not done
  • generalize/extend on_update() method to support other (global) properties and/or listeners/timers to run predicates Not done Not done
  • identify opportunities for improving the framework Not done Not done
  • support multiple routes (WPT/RTE), as per the Nasal Flightplan API (Hooray) Not done Not done
  • move the config hash out of the navdisplay.mfd file and use io.include instead Not done Not done
  • document SVG symbols currently assumed to be available in the ctor Not done Not done
  • consider using some of the SGCondition/StateMachine stuff in SG Not done Not done

Bugs

Feature Requests