Difference between revisions of "Autopilot configuration reference"
|Line 372:||Line 372:|
=== reciprocal ===
=== reciprocal ===
== pid-controller ==
== pid-controller ==
Revision as of 16:18, 27 May 2010
| Work in progress|
This article or section will be worked on in the upcoming hours or days.
See for the latest developments.
This page serves as a reference for the elements of FlightGear xml autopilot configuration files. It describes all elements available within the autopilot configuration file supported in the bleeding edge CVS sources. Some of the elements may not be available in the current release version of FlightGear. Refer to Howto: Design an autopilot as a guide how to use these elements.
- 1 Structure Of a Configuration File
- 2 Adding a Autopilot Configuration to Aircraft
- 3 Available Elements
- 4 Common Elements Used By All Elements
- 4.1 Name
- 4.2 Feedback if disabled
- 4.3 Debug
- 4.4 Input and Reference
- 4.5 Output
- 4.6 Enable
- 4.7 Input Values
- 4.8 Output Values
- 5 logic
- 6 Flip Flop
- 7 filter
- 8 pid-controller
- 9 pi-simple-controller
- 10 predict-simple
- 11 Proposed extensions
Structure Of a Configuration File
Autopilot configurations live in a separate file, formatted using the well known XML syntax like so many other FlightGear files with a PropertyList node as a root element. A basic skeleton file looks like this:
<?xml version="1.0" encoding="utf8"?> <PropertyList> <params> <controls> <aileron>controls/flight/aileron</aileron> <rudder>controls/flight/rudder</rudder> <elevator>controls/flight/elevator</elevator> </controls> </params> <!-- Place your components here --> <!-- <filter> <name>Myfilter</name> <input>/foo</input> <output>/bar</output> </filter> --> </PropertyList>
Note: Using aliased property names is good style and makes the configuration file more readable. For complex autopilot systems spread over multiple autopilot configuration files, the params section may be included from an external file using <params include="my-params.xml"/> to avoid duplication of code.
The location and the name of the configuration file is up to the developer. A descriptive name like 'autopilot.xml' might be a good choice. Most developers put these files into the Systems folder of the aircraft.
Adding a Autopilot Configuration to Aircraft
Autopilot configuration files are added to the aircraft by adding
<autopilot> <path>Aircraft/MyAircraft/Systems/my-autopilot.xml</path> </autopilot>
<sim> <systems> <!-- many other elements live here --> <autopilot> <path>Aircraft/MyAircraft/Systems/my-autopilot.xml</path> </autopilot> </systems> </sim>
node of your aircraft-set.xml file. Note, that more than one <autopilot> node may be present, each will create a new instance of the autopilot subsystem when running FlightGear. They run in the order of appearance under <systems>. For example, lateral and vertical autopilot modes could live in separate files, as could a yaw-damper system.
All elements may contain the attributes "include" and "alias". The "include" property takes a file name as a parameter. This can be used to read the document tree of an external XML file into the node containing the "include" attribute. The included file must have a PropertyList node as the root node. All nodes under this PropertyList node will be added to the node containing the "include" attribute. The "alias" attribute refers to an element defined elsewhere in this XMl document. Alias references are in a path-style syntax, either as a relative or absolute path. Absolute paths start with a slash, like <foo alias="/params/bar/baz"/>. Use the colon to move through the document tree, similar to file system paths like <foo alias="../../bar/baz"/>.
Any top-level element can appear in an autopilot XML file, but only the following elements will be recognised and used:
Common Elements Used By All Elements
The <name> element is optional, but should be added to give the controller a distinct name. It is only used in debug output.
Feedback if disabled
The <feedback-if-disabled> element advises the controller to feed back the output property value to the active input property if the condition defined in the <enable> tag evaluates to false. This is usually required for controllers like servo drivers behind a PID-controller to give that PID-controller a valid starting value when it becomes enabled. The absence of this element or anything but the word true within this element results in feedback disabled.
If the <debug> element is present and if it contains the word true, the containing controller prints out some diagnostic information on the console for each processing loop.
Input and Reference
Each controller has two input "lines", denoted by the tags <input> and <reference>. The arithmetic difference of these two values is used by the respective controller to compute it's output. Unfortunately due to historical reasons, the sign of input and reference is not consistent for all controllers. While the pid-controller and the pi-simple-controller compute "reference-input", the filter controller computes "input-reference". Each element is optional with a default value of zero. These elements are made of so called Input Values described further down in this document. Example for a simple differential amplifier, computing output = (input-reference)*2
<filter> <type>gain</type> <gain>1.0</gain> <input>/some/input</input> <reference>/some/output</reference> <output>/some/output</output> </filter>
The <outptu> element names the properties, the computed value should be written to. More than one <output> may be present, each named property will be assigned the computed value.
Controllers can be enabled or disabled using property values. This element <enable> may contain a <prop> and a <value> element. The controller is enabled, if the value of the named property equals the given value. This feature is considered deprecated and might go away in future releases. The preferred way of defining the enable-condition is by adding a <condition> element to the <enable> element. This <condition> follows the same syntactical rules as the one used in model animations and can model complex expression trees. To enable a wing leveler only if the current bank angle does not exceed 30° of bank, use this condition
<enable> <condition> <less-than> <property>orientation/bank-angle-deg</property> <value>30.0</value> </less-than> <greater-than> <property>orientation/bank-angle-deg</property> <value>-30.0</value> </greater-than> </condition> </enable>
Input values for controllers may be specified in several notations. Values may be supplied as constants, from properties or by means of simple linear transformations. Conditions allow the selection of one of multiple input sources. The following text will use the reference element as an example but it may be substituted by any other input element like Kp, gain etc. Input values will be interpreted as double values.
A constant value
A constant value is defined by just adding the value as text to the input element:
<reference> <value>3.5</value> </reference>
The shortcut syntax is also valid:
If the text can be parsed by strtod() to a double value, it will be used as a constant value, otherwise it will be interpreted as a property value (see next paragraph)
A property value
To evaluate the value of a property, place the name of the property into the text element:
<reference> <property>/my/property</property> </reference>
The shortcut syntax is also valid:
Note: the shortcut syntax is only valid, if neither <property> nor <value> element exists. If both, <property> and <value> element exist, the property will be initialized with the given value with scale and offset applied correctly. Properties don't have to exist, the will be created as needed.
Note: for backward compatibility, the notation <prop> instead of <property> is also valid but considered deprecated and might go away in future releases.
Linear transformation of the input value
Input values may be scaled and shifted before they are processed by the controller using the formula y = value * scale + offset To use a celsius temperature property in a controller which expects the temperature in fahrenheit you might use
<reference> <property>/environment/temperature-degc</property> <scale>1.8</scale> <offset>32</offset> </reference>
Periodical transformation of the input value
Periodical (like angular) input values can be transformed to appear in the correct phase before they are processed by the controller by adding or substracting multiples of the period to the input value until the values is in the requested periods interval. The following example converts the heading which comes in the range of [0..360] into the range of [-180..+180]. This will cause a heading of 270 to be processed as a value of -90.
<reference> <property>/orientation/heading-deg</property> <period> <min>-180.0</min> <max>180.0</max> </period> </reference>
To clamp the input to a minimum value, maximum value or both, the tags <min> and <max> can be used. Clamping will occur after the linear transformation has been applied. Note the difference of input clamping to output clamping. While input clamping is applied before the signal reaches the controller, output clamping will be applied to the output signal after it has been processed. The following code will keep the input to the controller in the range of 60 to 80 degrees Fahrenheit:
<reference> <property>/environment/temperature-degc</property> <scale>1.8</scale> <offset>32</offset> <min>60</min> <max>80</max> </reference>
To use the absolute (unsigned) value of the input, add <abs type="bool">true</abs>.
<reference> <property>/autopilot/internal/course-error-deg</property> <abs type="bool">true</abs> </reference>
The elements <scale>, <offset>, <min> and <max> itself can be defined as input values. This code uses as reference the value of course-error-deg, scaled by two and an offset applied which is calculated as the product of the bank-angle-de and the property some/property which itself is limited within the range of -1.5 .. +1.5.
<reference> <property>/autopilot/internal/course-error-deg</property> <scale>2.0</scale> <offset> <property>orientation/bank-angle-deg</property> <scale> <property>some/property <min>-1.5</min> <max>1.5</max> </scale> </offset> </reference>
Conditional input values
The direct inputs of controller and filter elements support so called input value lists. This is useful, if the input should be connected to one of many separate inputs like autopilots connected to NAV1, NAV2 or the GPS. The well known <condition> element is allowed within an input value element. The input value list will be traversed until the first input value with a successful condition is found. The behavior is much like the switch statement in programming languages.
<reference> <condition> <property>/autopilot/coupled-to-gps</property> </condition> <property>instrumentation/gps/desired-track-deg</property> </reference> <reference> <condition> <property>/autopilot/coupled-to-nav2</property> </condition> <property>instrumentation/nav/radials/selected-deg</property> </reference> <reference>instrumentation/nav/radials/selected-deg</reference>
Note the unconditional last <reference<> element which acts as an "if all others fail, use NAV1" anchor. If no input value return with a successful condition, the input value is undefined.
The <scale>, <offset>, <min> and <max> elements of input values itself currently don't support input value lists.
After processing of a component, the resulting value passes a transformation stage where it can be clipped or normalized into a given period. Periodic values such as angular properties may be normalized into a given period by adding a <period> element, defining the lower and upper bounds of the period. Additionally, a maximun and a minimum value may be given which will guarantee that the output value will ever exceed a defined value.
Note: Both, periodical normalization and clipping may be defined. If both are given, the value will be normalized first and the clipping will be applied to the normalized value.
The following example shifts the computed value into the interval of [-180..180] thereafter being limited into the interval of [-30..30]. The following table contains some computed values and the resulting written value:
<output>/some/property</output> <period> <min>-180</min> <max>180</max> </period> <min>-30</min> <max>30</max>
The logic controller provides a simple way of creating property values from the result of the condition expression in the <input> element. The condition expression is evaluated once per iteration and the result is written as a boolean value to the named output property or properties. An optional <inverted> element inverts the logic. The default is "not inverted".
Example: output = not( ( a is true ) or ( ( b greater than c ) and ( d is true ) )
<logic> <inverted>true</inverted> <input> <property>a</property> <or> <greater-than> <property>b</property> <property>c</property> <greater-than> <property>d</property> </or> </input> <output>output</output> </logic>
A flip flop is a controller that has two stable states so it can be used as a one bit memory. Four types of flip flops are implemented: RS, JK, D and T. All use positive logic and operate on the raising edge of the clock signal if a clock is used. All input lines, including the clock line, are encoded as condition constructs. If negative logic for the input line is required, wrap the condition into a <not> tag to invert the logic.
RS Flip Flop
This flip flop sets its output according to the set (S) or reset (R) input lines. If the set line is set, the output gets set. If the reset line is set, the output gets reset. If no line is set, the output stays unchanged. For the special case where set and reset lines are both set, two types of RS flip flops exist: for the RS flip flop (<type>RS</type>), the reset line is dominant and the output is reset. Alternatively, a SR flip flop (<type>SR</type>) has a dominant set line and the output gets set if set and reset line are set.
Example: simple RS flip flop
<flipflop> <type>RS</type> <!-- or SR --> <S> <property>/myflipflop/set</property> <R> <property>/myflipflop/reset</property> </R> <output>/myflipflop/output</output> </flipflop>
JK Flip Flop
The JK flip flop is an extension of the RS flip flop. The J line serves as the set input while the K line does the reset job. Optionally, a clock input may be provided. State changes do not occour immediately, but on the next raising edge of the clock signal. The state of set=reset=true is allowed here. This state causes the output to toggle it's current state on the next raising edge of the clock signal. If no clock signal is provided, the frame rate serves as the clock input.
Example: simple JK flip flop with negative edge clock
<flipflop> <type>JK</type> <J> <property>/myflipflop/set</property> </J> <K> <property>/myflipflop/reset</property> </K> <clock> <not> <property>/myflipflop/clock</property> </not> </clock> <output>/myflipflop/output</output> </flipflop>
D Flip Flop
The D flip flop transfers the state of the input signal D to the output line at the next raising edge of the clock signal, which is mandatory for this flip flop.
Example: simple D flip flop with inverted output
<flipflop> <type>D</type> <D> <property>/myflipflop/data</property> </D> <clock> <property>/myflipflop/clock</property> </clock> <output>/myflipflop/output</output> <inverted type="bool">true</inverted> </flipflop>
T Flip Flop
The T flip flop toggles the state of the output signal at the next raising edge of the clock signal, which is mandatory for this flip flop.
Example: simple T flip flop
<flipflop> <type>T</type> <clock> <property>/myflipflop/clock</property> </clock> <output>/myflipflop/output</output> </flipflop>
A gain filter multiplies the difference between the <input> and <output> values by a given factor. The multiplier or gain is specified by the <gain> element. More than one <gain> element formatted as in Input Values may be present. The first with a <condition> element evaluating as true will define the used gain.
<filter> <type>gain</type> <gain>6.28</gain> <input>radius</input> <output>circumfence</output> </filter>
The exponential filter is a typical low pass filter. The magic euler number and the associated mathematical funtion exp() plays a major role here. As the name implies, lower frequencies can pass this filter while higher frequencies are cut. The frequency where only half of the input signal reaches the output is called cutoff frequency. This cutoff frequency is defined by the parameter <filter-time> and resolves as cutoff-frequency = 1/(2*pi*cutoff-frequency). Example: a 1Hz first order low pass filter
<filter> <type>exponential</type> <filter-time>0.16</filter-time> <input>/some/input</input> <output>/some/output/<output> </filter>
The double exponential filter is a low pass filter like the exponential filter with a steeper slope of the filter diagram. It acts basically like two chained exponential filters and it is some times called second order filter.
The configuration is the same for exponential and double-exponential filters, just the type entry differs
<filter> <type>double-exponential</type> <filter-time>0.16</filter-time> <input>/some/input</input> <output>/some/output/<output> </filter>
A better name for a noise spike filter would probably have been "rate limit filter". This is exactly what it does: limit the rate of change of the output value. The relevant configuration element is <max-rate-of-change> setting the maximum rate of change of the output property per second.
Example: A transition from 0 to 4 at the input property results in a linear increase of the output property over 8 seconds from 0 to 4 at a rate of 0.5/sec.
<filter> <type>noise-spike</type> <max-rate-of-change>0.5</max-rate-of-change> <input>/some/input</input> <output>/some/output</output> </filter>
Compute the reciprocal (1/x) value of the input property. If x is zero, no computation is performed. The optional <gain> element may be used to scale the value. Output computes as gain divided by input.
Example: compute the flight time per pound of burned fuel from the fuel flow
<filter> <type>reciprocal</type> <gain>1.0</gain> <input>/engines/engine/fuel-flow-pph</input> <output>/engines/engine/fuel-flow-hpp</output> </filter>
The PID controller is the swiss army knife of automation and this implementation is suitable for most situations. It has a builtin anti-windup logic, and usage of <max> and <min> elements for clamping the output is mandatory. The most important thing to know is that this controller 'does not' compute absolute output values but an offset from the current value of the output property. This can lead to unexpected behavior if the current value of the output property is unknown when the controller is enabled. This behavior is different to that of the pi-simple-controller. The xml element creating a pid controller is <pid-controller>.
Legal elements are:
|Kp||the overall gain for the proportional, integral and derivative part|
|Ts||sampling interval (default: sample at frame rate)|
|alpha||scaling factor for Td (defaults to 0.1)|
|beta||reference weighing factor for the proportional component (defaults to 1.0)|
|gamma||reference weighing factor for the derivate component (defaults to 0.0)|
This controller implements a PI controller. Other than the PID controller, it computes absolute output values, regardless of the value of the output property. It can by configured as an I-only, P-only or PI-controller. It has anti windup logic if <min> and <max> elements are present. The xml element creating a PI controller is <pi-simple-controller> Legal elements are:
|Kp||gain of the proportional component|
|Ki||gain of the integrator component|
This sections contains new features for the autopilot to be implemented. Nobody knows if and when this will happen. Consider this as a collection of ideas as a base for discussion on the mailing list, the forum or IRC.