The so called Property Tree is considered FlightGear's central nervous system and one of its greatest assets. It is the interface to low level, run time state variables via a very intuitive tree-like hierarchy, allowing for FlightGear's behavior to be easily controlled and manipulated at run time.
The concepts and mechanisms behind the Property Tree may not be immediately obvious to FlightGear beginners. This page is meant to help new users familiarize themselves with the FlightGear property tree.
The purpose of the Property Tree
The property system - or property tree - represents most of the internal state of all systems within FlightGear, like for example the flight dynamics model, or the weather simulation. The content of these internal state variables are presented in a hierarchically manner and can easily be accessed through a well known API. A system may present its current state to other systems and let them change its current state by allowing to write to its own properties.
One might think of the property system as a global, normalized communication platform, where subsystems may publish variables and access other subsystem's variables. In addition, callbacks can be registered to invoke code upon read/write access of properties, which serves as the backbone for a very simple, but powerful, signalling mechanism in FlightGear. Thus, the property system acts as a routing interface, both between different high-level FG sub-systems and the outside world. Data that is required by one FG sub-system can be exposed in the property tree, where it can then be read or modified, either by other internal FG sub-systems, or by & for external input/output.
Examples of use
For example, a left banking joystick input is exposed in the property tree where it is read by the FG FDM sub-system. The FG FDM subsystem then in turn outputs an aileron deflection back to the property tree where it is then read by the FG animation subsystem to animate the aileron deflection in the 3D model.
Alternatively the joystick input, once exposed in the property tree, can be read and modified by an external application via the FlightGear I/O subsystem, such as an external FDM. The output from the external FDM can then be fed back to FlightGear by writing its data back to the property tree, once again, via the FlightGear I/O subsystem.
There are several subsystems that implement a full API on top of the property tree, such as the AI traffic system, the multiplayer mode, but also Canvas - basically, setting certain properties (e.g. via Nasal's setprop()), triggering certain code (through listener callbacks) - with arguments and return values passed through the property tree, which in turn allows arbitrary 3D models to be placed, but also AI traffic to be created / controlled, as well as OpenGL textures to be created and modified and run-time, which is what we use to implement HUDs, GUIs, instruments, MFD avionics, and even liveries or scenery textures (VGDS).
The organization of the tree
Naming a property is very much like naming a file in a file system, with levels of hierarchy, e.g.:
/sim/aircraft = A333 /position/ /position/longitude-deg = '-122.3576677' (double) /position/latitude-deg = '37.61372424' (double) /position/altitude-ft = '28.24418581' (double) /position/altitude-agl-ft = '22.47049626' (double) /controls/seat/eject/initiate /controls/electric/APU-generator
Some of these variables are "calculated" within the sim (i.e. updated regularly, e.g. at frame rate), whilst others can be manipulated. Writing a variable is as easy as
/* Its my turn to play the sim */ set('/controls/seat/eject/initiate', 1)
What makes FG powerful is that a new aircraft can easily be designed with its unique set of properties that somehow affect the simulation. The Aircraft model has an xml file of properties within the property tree.
Customizing and manipulating the property tree
An important feature of the property tree interface is that it can be tailored and new entries added as required through Nasal scripts, without requiring C++ changes. If you wish to use a custom-written subsystem, such as your own Terrain Following and Avoidance subsystem, for example, and perhaps implemented in Nasal, adding new property tree branches and nodes to handle your unique data presents no problems.
The property tree is read, written, accessed and manipulated in a variety of ways, such as
- startup arguments via --prop:/sim/foo=bar
- XML files
- internal compiled code within FG - the c/c++ code
- Using native protocols, implemented in C++ (see $SG_SRC/Network. Property Tree/Sockets
- Using the generic protocol, either in/out/bi - this allows send/receive to the FG sim via the Generic Protocol
- telnet interface - query and fly the plane on the command line or using a scripted session (see Telnet usage)
- html interface - access the property tree using a conventional web browser like firefox/safari or chrome
- using the built in Property browser
- using other GUI dialogs
- using cockpit bindings
- using joystick bindings etc
So they can come from many places, thus there's no single source file where you'll find ALL properties/types. You will need to look at the corresponding subsystem/component. $FG_SRC/Network is the right pace to look for hardcoded protocols, make sure to also understand their inheritance (the interface being implemented).
XML and property lists
The property tree maps very nicely to XML. This is convenient for initializing the property tree and saving its state. Values in the tree are typed, but they can also be untyped strings which will be converted to a typed value when read.
PropertyList-encoded XML files are mapped to a/the property tree - typically, such XML files are not manually processed, they are "transparently" processed by FlightGear, loaded and mapped into a Property Tree.
Protocols to access the property tree
In addition to the protocols supported by the FlightGear I/O subsystem, other interfaces are provided by a built-in Property Tree/Web Server and a built-in Telnet server, which allow property tree data to be read and modified via these interfaces, i.e. using a telnet client or a conventional web browser, at run time.
Note that you can setup as many of these servers as you want, for instance, just to be obscene you could do:
fgfs --httpd=5400 --httpd=5401 --httpd=5402 --telnet=5403 --telnet=5404 --telnet=5405
Now there are six network interfaces running that you can access from anywhere ;-)
>> "can I borrow your ipod please?" "why?"
Usually the "best" way depends on your specific circumstances. Will the two applications be running on the same machine? If not, do the two machines have a high speed network connection or some slow radio modem type connection? How much data are you sending and at what rate? Do you need really tight timing or can you get by with some delays and sloppiness in the communication?
Reference documentation to the property tree
By what was said above, the property tree is not consistent with fixed variables, they are created dynamically, to represent a propeller plane vs Jumbo or even a "Caspian Sea Monster", or depending on which subsystems are active. Many properties availability may even depend on the startup/runtime settings you are using.
There are a bunch of "common" properties - especially among similar FDMs and aircraft. Obviously, different FDMs/aircraft will use different properties (single piston, helicopter, jet, twin turbine helicopter etc). You may want to have a look at $FG_ROOT/Docs/README.properties.
There are a couple ways that they are set, but a fair amount of them just "appear" without being documented anywhere. There are several places to look for properties; one is in the aircraft files, another is all Nasal files, and the last place (and often most useful!) is grepping (searching) through the C++ code. To determine how a property works and what it does often requires looking through any code that uses it. This is a part of FlightGear that we could certainly document better
Flight Dynamics Model (FDM)
FlightGear uses a few Flight Dynamics Models, such as
These flight dynamics models present themselves differently in the tree, using different variables, in different places. That is what an aircraft can be designed around. Most FDMs use so called tied properties, which are directly mapped to memory in C++, so that they cannot be written to - so that you would need to disable the FDM using the null FDM instead.