1
0
Fork 0

FG1000: GFC700 Autopilot Integration

Support for GFC700 autopilot.  Current modes that work: AP, FD, ROL, PIT, HDG, VS
This commit is contained in:
Stuart Buchanan 2019-02-10 22:06:31 +00:00
parent 0abb7201f1
commit 9d353a3266
18 changed files with 1846 additions and 79 deletions

View file

@ -284,6 +284,7 @@
<command>FG1000HardKeyPushed</command>
<device>1</device>
<notification>AP</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -304,6 +305,7 @@
<command>FG1000HardKeyPushed</command>
<device>1</device>
<notification>HDG</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -324,6 +326,7 @@
<command>FG1000HardKeyPushed</command>
<device>1</device>
<notification>NAV</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -344,6 +347,7 @@
<command>FG1000HardKeyPushed</command>
<device>1</device>
<notification>APR</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -364,6 +368,7 @@
<command>FG1000HardKeyPushed</command>
<device>1</device>
<notification>VS</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -384,6 +389,7 @@
<command>FG1000HardKeyPushed</command>
<device>1</device>
<notification>FLC</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -404,6 +410,7 @@
<command>FG1000HardKeyPushed</command>
<device>1</device>
<notification>FD</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -424,6 +431,7 @@
<command>FG1000HardKeyPushed</command>
<device>1</device>
<notification>ALT</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -444,6 +452,7 @@
<command>FG1000HardKeyPushed</command>
<device>1</device>
<notification>VNV</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -464,6 +473,7 @@
<command>FG1000HardKeyPushed</command>
<device>1</device>
<notification>BC</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -484,6 +494,7 @@
<command>FG1000HardKeyPushed</command>
<device>1</device>
<notification>NOSE_UP</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -504,6 +515,7 @@
<command>FG1000HardKeyPushed</command>
<device>1</device>
<notification>NOSE_DOWN</notification>
<offset>1</offset>
</binding>
</action>
<hovered>

View file

@ -284,6 +284,7 @@
<command>FG1000HardKeyPushed</command>
<device>2</device>
<notification>AP</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -304,6 +305,7 @@
<command>FG1000HardKeyPushed</command>
<device>2</device>
<notification>HDG</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -324,6 +326,7 @@
<command>FG1000HardKeyPushed</command>
<device>2</device>
<notification>NAV</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -344,6 +347,7 @@
<command>FG1000HardKeyPushed</command>
<device>2</device>
<notification>APR</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -364,6 +368,7 @@
<command>FG1000HardKeyPushed</command>
<device>2</device>
<notification>VS</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -384,6 +389,7 @@
<command>FG1000HardKeyPushed</command>
<device>2</device>
<notification>FLC</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -404,6 +410,7 @@
<command>FG1000HardKeyPushed</command>
<device>2</device>
<notification>FD</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -424,6 +431,7 @@
<command>FG1000HardKeyPushed</command>
<device>2</device>
<notification>ALT</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -444,6 +452,7 @@
<command>FG1000HardKeyPushed</command>
<device>2</device>
<notification>VNV</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -464,6 +473,7 @@
<command>FG1000HardKeyPushed</command>
<device>2</device>
<notification>BC</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -484,6 +494,7 @@
<command>FG1000HardKeyPushed</command>
<device>2</device>
<notification>NOSE_UP</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -504,6 +515,7 @@
<command>FG1000HardKeyPushed</command>
<device>2</device>
<notification>NOSE_DOWN</notification>
<offset>1</offset>
</binding>
</action>
<hovered>

View file

@ -284,6 +284,7 @@
<command>FG1000HardKeyPushed</command>
<device>3</device>
<notification>AP</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -304,6 +305,7 @@
<command>FG1000HardKeyPushed</command>
<device>3</device>
<notification>HDG</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -324,6 +326,7 @@
<command>FG1000HardKeyPushed</command>
<device>3</device>
<notification>NAV</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -344,6 +347,7 @@
<command>FG1000HardKeyPushed</command>
<device>3</device>
<notification>APR</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -364,6 +368,7 @@
<command>FG1000HardKeyPushed</command>
<device>3</device>
<notification>VS</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -384,6 +389,7 @@
<command>FG1000HardKeyPushed</command>
<device>3</device>
<notification>FLC</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -404,6 +410,7 @@
<command>FG1000HardKeyPushed</command>
<device>3</device>
<notification>FD</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -424,6 +431,7 @@
<command>FG1000HardKeyPushed</command>
<device>3</device>
<notification>ALT</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -444,6 +452,7 @@
<command>FG1000HardKeyPushed</command>
<device>3</device>
<notification>VNV</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -464,6 +473,7 @@
<command>FG1000HardKeyPushed</command>
<device>3</device>
<notification>BC</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -484,6 +494,7 @@
<command>FG1000HardKeyPushed</command>
<device>3</device>
<notification>NOSE_UP</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -504,6 +515,7 @@
<command>FG1000HardKeyPushed</command>
<device>3</device>
<notification>NOSE_DOWN</notification>
<offset>1</offset>
</binding>
</action>
<hovered>

View file

@ -284,6 +284,7 @@
<command>FG1000HardKeyPushed</command>
<device>4</device>
<notification>AP</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -304,6 +305,7 @@
<command>FG1000HardKeyPushed</command>
<device>4</device>
<notification>HDG</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -324,6 +326,7 @@
<command>FG1000HardKeyPushed</command>
<device>4</device>
<notification>NAV</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -344,6 +347,7 @@
<command>FG1000HardKeyPushed</command>
<device>4</device>
<notification>APR</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -364,6 +368,7 @@
<command>FG1000HardKeyPushed</command>
<device>4</device>
<notification>VS</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -384,6 +389,7 @@
<command>FG1000HardKeyPushed</command>
<device>4</device>
<notification>FLC</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -404,6 +410,7 @@
<command>FG1000HardKeyPushed</command>
<device>4</device>
<notification>FD</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -424,6 +431,7 @@
<command>FG1000HardKeyPushed</command>
<device>4</device>
<notification>ALT</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -444,6 +452,7 @@
<command>FG1000HardKeyPushed</command>
<device>4</device>
<notification>VNV</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -464,6 +473,7 @@
<command>FG1000HardKeyPushed</command>
<device>4</device>
<notification>BC</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -484,6 +494,7 @@
<command>FG1000HardKeyPushed</command>
<device>4</device>
<notification>NOSE_UP</notification>
<offset>1</offset>
</binding>
</action>
<hovered>
@ -504,6 +515,7 @@
<command>FG1000HardKeyPushed</command>
<device>4</device>
<notification>NOSE_DOWN</notification>
<offset>1</offset>
</binding>
</action>
<hovered>

View file

@ -0,0 +1,60 @@
<PropertyList>
<!-- GFC 700 Autopilot Finite State Machine for switching OFF the AP.
This is rather odd. This handles switching on/off the autopilot, which reverts
to Flight Director mode, by simply setting the passive-mode flag.
-->
<branch>/autopilot/GFC700/FSM/AP-off</branch>
<state>
<name>OFF</name>
<enter>
<!-- Reset button to avoid triggering next transition immediately -->
<command>property-assign</command>
<property>/autopilot/AP-mode-button</property>
<value></value>
</enter>
<enter>
<command>property-assign</command>
<property>/autopilot/locks/passive-mode</property>
<value>1</value>
</enter>
</state>
<state>
<name>ON</name>
<enter>
<!-- Reset button to avoid triggering next transition immediately -->
<command>property-assign</command>
<property>/autopilot/AP-mode-button</property>
<value></value>
</enter>
<enter>
<command>property-assign</command>
<property>/autopilot/locks/passive-mode</property>
<value>0</value>
</enter>
</state>
<transition>
<name>OFF-ON</name>
<source>OFF</source>
<target>ON</target>
<exclude-target>true</exclude-target>
<condition>
<equals><property>/autopilot/AP-mode-button</property><value>AP</value></equals>
</condition>
</transition>
<transition>
<name>ON-OFF</name>
<source>ON</source>
<target>OFF</target>
<exclude-target>false</exclude-target>
<condition>
<equals><property>/autopilot/AP-mode-button</property><value>AP</value></equals>
</condition>
</transition>
</PropertyList>

View file

@ -0,0 +1,268 @@
<PropertyList>
<!-- GFC 700 Autopilot Finite State Machine for LATERAL mode-->
<branch>/autopilot/GFC700/FSM/lateral</branch>
<state>
<name>OFF</name>
<enter>
<command>property-assign</command>
<property>/autopilot/locks/heading</property>
<value></value>
</enter>
<enter>
<command>property-assign</command>
<property>/autopilot/annunciator/lateral-mode</property>
<value></value>
</enter>
<enter>
<command>property-assign</command>
<property>/autopilot/annunciator/lateral-mode-armed</property>
<value></value>
</enter>
<enter>
<!-- Reset button to avoid triggering next transition immediately -->
<command>property-assign</command>
<property>/autopilot/lateral-mode-button</property>
<value></value>
</enter>
</state>
<state>
<!-- Roll mode. Either set wings level (if roll < 6.0), or set to current roll -->
<name>ROL</name>
<enter>
<command>property-assign</command>
<property>/autopilot/annunciator/lateral-mode</property>
<value>ROL</value>
</enter>
<enter>
<!-- Reset button to avoid triggering next transition immediately -->
<command>property-assign</command>
<property>/autopilot/lateral-mode-button</property>
<value></value>
</enter>
</state>
<transition>
<!-- Go to wings level mode if roll [-6.0,6.0] -->
<name>ROL-ROL-WL</name>
<source>ROL</source>
<target>ROL-WL</target>
<condition>
<less-than>
<property>/autopilot/internal/filtered-roll-deg</property>
<value>6.0</value>
</less-than>
<greater-than>
<property>/autopilot/internal/filtered-roll-deg</property>
<value>-6.0</value>
</greater-than>
</condition>
</transition>
<transition>
<!-- Otherwise, just got to ROLL with the set roll value -->
<name>ROL-ROL-SET</name>
<source>ROL</source>
<target>ROL-SET</target>
<condition>
<or>
<greater-than>
<property>/autopilot/internal/filtered-roll-deg</property>
<value>6.0</value>
</greater-than>
<less-than>
<property>/autopilot/internal/filtered-roll-deg</property>
<value>-6.0</value>
</less-than>
</or>
</condition>
</transition>
<state>
<name>ROL-SET</name>
<!-- Roll hold mode. We assign a filtered value, which limits to to [-22.0, 20.0] -->
<enter>
<command>property-assign</command>
<property n="0">/autopilot/settings/target-roll-deg</property>
<property n="1">/autopilot/internal/filtered-roll-deg</property>
</enter>
<enter>
<command>property-assign</command>
<property>/autopilot/locks/heading</property>
<value>roll-hold</value>
</enter>
</state>
<state>
<name>ROL-WL</name>
<!-- Roll hold mode - wings level. Used if the roll value when enabled is [-6,6]-->
<enter>
<command>property-assign</command>
<property>/autopilot/settings/target-roll-deg</property>
<value>0.0</value>
</enter>
<enter>
<command>property-assign</command>
<property>/autopilot/locks/heading</property>
<value>roll-hold</value>
</enter>
</state>
<state>
<name>GA</name>
<!-- GA mode - Wings level -->
<enter>
<command>property-assign</command>
<property n="0">/autopilot/settings/target-roll-deg</property>
<value>0.0</value>
</enter>
<enter>
<command>property-assign</command>
<property>/autopilot/locks/heading</property>
<value>roll-hold</value>
</enter>
<enter>
<command>property-assign</command>
<property>/autopilot/annunciator/lateral-mode</property>
<value>GA</value>
</enter>
<enter>
<!-- Reset button to avoid triggering next transition immediately -->
<command>property-assign</command>
<property>/autopilot/lateral-mode-button</property>
<value></value>
</enter>
</state>
<state>
<name>HDG</name>
<enter>
<command>property-assign</command>
<property>/autopilot/locks/heading</property>
<value>dg-heading-hold</value>
</enter>
<enter>
<command>property-assign</command>
<property>/autopilot/annunciator/lateral-mode</property>
<value>HDG</value>
</enter>
<enter>
<!-- Reset button to avoid triggering next transition immediately -->
<command>property-assign</command>
<property>/autopilot/lateral-mode-button</property>
<value></value>
</enter>
</state>
<!-- From the OFF state, pressing any of FD, AP, CWS, NAV, BC, APR, changes to ROL mode -->
<transition>
<name>OFF-ROL</name>
<source>OFF</source>
<target>ROL</target>
<exclude-target>true</exclude-target>
<condition>
<or>
<equals><property>/autopilot/lateral-mode-button</property><value>FD</value></equals>
<equals><property>/autopilot/lateral-mode-button</property><value>CWS</value></equals>
<equals><property>/autopilot/lateral-mode-button</property><value>NAV</value></equals>
<equals><property>/autopilot/lateral-mode-button</property><value>BC</value></equals>
<equals><property>/autopilot/lateral-mode-button</property><value>APR</value></equals>
<equals><property>/autopilot/lateral-mode-button</property><value>HDG</value></equals>
</or>
</condition>
</transition>
<transition>
<name>OFF-HDG</name>
<source>OFF</source>
<target>HDG</target>
<exclude-target>true</exclude-target>
<condition>
<or>
<equals><property>/autopilot/lateral-mode-button</property><value>HDG</value></equals>
</or>
</condition>
</transition>
<!-- AP/FD logic is somewhat complex:
1) Pressing AP toggles the autopilot on/off
a) OFF to ON : OFF-AP-ROL transition below
b) ON to OFF : Handled by a separate FSM. We could use a series of transitions
to the same states below, but that would result in entry bindings being repeated, which would be bad
2) When the AP is enabled, the FD button is disabled. (Easy - no transition!)
3) Pressing the FD button when the FD is enabled switches off the FD : Switch-off transition below
-->
<!-- From the OFF state, pressing AP changes to ROL mode, with the AP enabled (e.g. not passive mode) -->
<transition>
<name>OFF-AP-ROL</name>
<source>OFF</source>
<target>ROL</target>
<exclude-target>true</exclude-target>
<condition>
<equals><property>/autopilot/lateral-mode-button</property><value>AP</value></equals>
</condition>
<binding>
<command>property-assign</command>
<property>/autopilot/locks/passive-mode</property>
<value>0</value>
</binding>
</transition>
<!-- From any state pressing FD when FD is ON switches off the FD -->
<transition>
<name>FD-Switch-off</name>
<target>OFF</target>
<exclude-target>true</exclude-target>
<condition>
<equals><property>/autopilot/lateral-mode-button</property><value>FD</value></equals>
<equals><property>/autopilot/locks/passive-mode</property><value>1</value></equals>
</condition>
</transition>
<!-- Series of transitions to handle case where disabling the AP. Need to remain in existing state -->
<!-- From any state, pressing GA goes to GA mode, and returns to ROL mode when pressed again -->
<transition>
<name>To GA</name>
<target>GA</target>
<exclude-target>true</exclude-target>
<condition>
<equals><property>/autopilot/lateral-mode-button</property><value>GA</value></equals>
</condition>
</transition>
<transition>
<name>From GA</name>
<source>GA</source>
<target>ROL</target>
<exclude-target>true</exclude-target>
<condition>
<equals><property>/autopilot/lateral-mode-button</property><value>GA</value></equals>
</condition>
</transition>
<!-- From any state, pressing HDG goes to HDG mode, and returns to ROL mode when pressed again -->
<transition>
<name>To HDG</name>
<target>HDG</target>
<exclude-target>true</exclude-target>
<condition>
<equals><property>/autopilot/lateral-mode-button</property><value>HDG</value></equals>
</condition>
</transition>
<transition>
<name>From HDG</name>
<source>HDG</source>
<target>ROL</target>
<exclude-target>true</exclude-target>
<condition>
<equals><property>/autopilot/lateral-mode-button</property><value>HDG</value></equals>
</condition>
</transition>
</PropertyList>

View file

@ -0,0 +1,374 @@
<PropertyList>
<!-- GFC 700 Autopilot Finite State Machine for vertical mode. Also handles AP and FD toggling -->
<branch>/autopilot/GFC700/FSM/vertical</branch>
<state>
<name>OFF</name>
<enter>
<command>property-assign</command>
<property>/autopilot/locks/altitude</property>
<value></value>
</enter>
<enter>
<command>property-assign</command>
<property>/autopilot/annunciator/vertical-mode</property>
<value></value>
</enter>
<enter>
<command>property-assign</command>
<property>/autopilot/annunciator/vertical-mode-armed</property>
<value></value>
</enter>
<enter>
<command>property-assign</command>
<property>/autopilot/annunciator/vertical-mode-target</property>
<value></value>
</enter>
<enter>
<command>property-assign</command>
<property>/autopilot/locks/speed</property>
<value></value>
</enter>
<enter>
<command>property-assign</command>
<property>/autopilot/locks/passive-mode</property>
<value>1</value>
</enter>
<enter>
<!-- Reset button to avoid triggering next transition immediately -->
<command>property-assign</command>
<property>/autopilot/vertical-mode-button</property>
<value></value>
</enter>
</state>
<state>
<name>PIT</name>
<!-- Pitch hold mode. We assign a filtered value, which limits to to [-15.0, 20.0] -->
<enter>
<command>property-assign</command>
<property n="0">/autopilot/settings/target-pitch-deg</property>
<property n="1">/autopilot/internal/filtered-pitch-deg</property>
</enter>
<enter>
<command>property-assign</command>
<property>/autopilot/locks/altitude</property>
<value>pitch-hold</value>
</enter>
<enter>
<command>property-assign</command>
<property>/autopilot/annunciator/vertical-mode</property>
<value>PIT</value>
</enter>
<enter>
<command>property-assign</command>
<property>/autopilot/annunciator/vertical-mode-target</property>
<value></value>
</enter>
<enter>
<!-- Reset button to avoid triggering next transition immediately -->
<command>property-assign</command>
<property>/autopilot/vertical-mode-button</property>
<value></value>
</enter>
</state>
<state>
<name>GA</name>
<!-- GA mode - 7 degree pitch up-->
<enter>
<command>property-assign</command>
<property n="0">/autopilot/settings/target-pitch-deg</property>
<value>7.0</value>
</enter>
<enter>
<command>property-assign</command>
<property>/autopilot/locks/altitude</property>
<value>pitch-hold</value>
</enter>
<enter>
<command>property-assign</command>
<property>/autopilot/annunciator/vertical-mode</property>
<value>GA</value>
</enter>
<enter>
<command>property-assign</command>
<property>/autopilot/annunciator/vertical-mode-target</property>
<value></value>
</enter>
<enter>
<!-- Reset button to avoid triggering next transition immediately -->
<command>property-assign</command>
<property>/autopilot/vertical-mode-button</property>
<value></value>
</enter>
</state>
<state>
<name>VS</name>
<!-- VS mode -->
<enter>
<command>nasal</command>
<script>
<!-- Calculate the fpm value to the nearest 100fpm. -->
setprop("/autopilot/settings/vertical-speed-fpm",
math.round(getprop("/autopilot/internal/vert-speed-fpm"),100)
);
setprop("/autopilot/annunciator/vertical-mode-target",
sprintf("%+ifpm", getprop("/autopilot/settings/vertical-speed-fpm"))
);
</script>
</enter>
<enter>
<command>property-assign</command>
<property>/autopilot/locks/altitude</property>
<value>vertical-speed-hold</value>
</enter>
<enter>
<command>property-assign</command>
<property>/autopilot/annunciator/vertical-mode</property>
<value>VS</value>
</enter>
<enter>
<!-- Reset button to avoid triggering next transition immediately -->
<command>property-assign</command>
<property>/autopilot/vertical-mode-button</property>
<value></value>
</enter>
</state>
<state>
<name>ALTS-ARM</name>
<!-- Arm Altitude Capture Mode - ALTS -->
<enter>
<command>property-assign</command>
<property>/autopilot/annunciator/vertical-mode-armed</property>
<value>ALTS</value>
</enter>
<enter>
<!-- Reset button to avoid triggering next transition immediately -->
<command>property-assign</command>
<property>/autopilot/vertical-mode-button</property>
<value></value>
</enter>
</state>
<transition>
<name>ALTS Capture</name>
<!-- Altitude Capture Mode enabled when we get within 500ft of the selected altitude -->
<source>ALTS-ARM</source>
<target>ALTS</target>
<condition>
<less-than>
<property>/autopilot/internal/target-altitude-delta-ft</property>
<value>500</value>
</less-than>
<greater-than>
<property>/autopilot/internal/target-altitude-delta-ft</property>
<value>-500</value>
</greater-than>
</condition>
</transition>
<state>
<name>ALTS</name>
<enter>
<command>nasal</command>
<script>
<!-- Set up the 2nd target, so that it is independent of the Selected Altitude,
then annunciator to the reference value current target value, then enable
the altitude capture function -->
setprop("/autopilot/settings/target-altitude-ft-2", getprop("/autopilot/settings/target-altitude-ft"));
setprop("/autopilot/annunciator/vertical-mode-target",
sprintf("%ift", getprop("/autopilot/settings/target-altitude-ft-2"))
);
</script>
</enter>
<enter>
<command>property-assign</command>
<property>/autopilot/annunciator/vertical-mode</property>
<value>ALTS</value>
</enter>
<enter>
<command>property-assign</command>
<property>/autopilot/annunciator/vertical-mode-armed</property>
<value>ALT</value>
</enter>
<enter>
<command>property-assign</command>
<property>/autopilot/locks/altitude</property>
<value>altitude-hold2</value>
</enter>
<enter>
<!-- Reset button to avoid triggering next transition immediately -->
<command>property-assign</command>
<property>/autopilot/vertical-mode-button</property>
<value></value>
</enter>
</state>
<transition>
<!-- ALTS (Selected Altitude Capture) automatically armed from PIT, TO/GA, VS, VPTH, FLC modes -->
<name>ALTS-ARM</name>
<source>PIT</source>
<source>GA</source>
<source>VS</source>
<target>ALTS-ARM</target>
<!-- Transitions must have a condition element. So set it to True -->
<condition>
<not>
<property>/sim/time/elapsed-sec</property>
<value>0</value>
</not>
</condition>
</transition>
<transition>
<!-- Altitude Hold Mode enabled when we get within 50ft of the selected altitude -->
<name>ALTS-ALT</name>
<source>ALTS</source>
<target>ALT</target>
<condition>
<less-than>
<property>/autopilot/internal/ALTS-target-altitude-delta-ft</property>
<value>50</value>
</less-than>
<greater-than>
<property>/autopilot/internal/ALTS-target-altitude-delta-ft</property>
<value>-50</value>
</greater-than>
</condition>
</transition>
<state>
<name>ALT</name>
<enter>
<command>property-assign</command>
<property>/autopilot/annunciator/vertical-mode</property>
<value>ALT</value>
</enter>
<enter>
<command>property-assign</command>
<property>/autopilot/annunciator/vertical-mode-armed</property>
<value></value>
</enter>
<enter>
<command>nasal</command>
<script>
setprop("/autopilot/annunciator/vertical-mode-target",
sprintf("%ift", getprop("/autopilot/settings/target-altitude-ft-2"))
);
</script>
</enter>
<enter>
<command>property-assign</command>
<property>/autopilot/locks/altitude</property>
<value>altitude-hold2</value>
</enter>
<enter>
<!-- Reset button to avoid triggering next transition immediately -->
<command>property-assign</command>
<property>/autopilot/vertical-mode-button</property>
<value></value>
</enter>
</state>
<!-- From the OFF state, pressing any of FD, AP, CWS, NAV, BC, APR, HDG changes to PIT mode -->
<transition>
<name>OFF-PIT</name>
<source>OFF</source>
<target>PIT</target>
<exclude-target>true</exclude-target>
<condition>
<or>
<equals><property>/autopilot/vertical-mode-button</property><value>AP</value></equals>
<equals><property>/autopilot/vertical-mode-button</property><value>FD</value></equals>
<equals><property>/autopilot/vertical-mode-button</property><value>CWS</value></equals>
<equals><property>/autopilot/vertical-mode-button</property><value>NAV</value></equals>
<equals><property>/autopilot/vertical-mode-button</property><value>BC</value></equals>
<equals><property>/autopilot/vertical-mode-button</property><value>APR</value></equals>
<equals><property>/autopilot/vertical-mode-button</property><value>HDG</value></equals>
</or>
</condition>
</transition>
<!-- From most vertical modes, pressing the mode key again returns to PIT mode -->
<transition>
<name>VS-PIT</name>
<source>VS</source>
<target>PIT</target>
<condition>
<equals><property>/autopilot/vertical-mode-button</property><value>VS</value></equals>
</condition>
</transition>
<transition>
<name>GA-PIT</name>
<source>GA</source>
<target>PIT</target>
<condition>
<equals><property>/autopilot/vertical-mode-button</property><value>GA</value></equals>
</condition>
</transition>
<!-- AP/FD logic is somewhat complex:
1) Pressing AP toggles the autopilot on/off
Handled by a separate FSM. We could use a series of transitions
to the same states below, but that would result in entry bindings being repeated, which would be bad
2) When the AP is enabled, the FD button is disabled. (Easy - no transition!)
3) Pressing the FD button when the FD is enabled switches off the FD : Switch-off transition below
-->
<!-- From any state pressing FD when FD is ON switches off the FD -->
<transition>
<name>FD-Switch-off</name>
<target>OFF</target>
<exclude-target>true</exclude-target>
<condition>
<not><equals><property>/autopilot/annunciator/autopilot-enabled</property><value>1</value></equals></not>
<equals><property>/autopilot/vertical-mode-button</property><value>FD</value></equals>
<equals><property>/autopilot/locks/passive-mode</property><value>1</value></equals>
</condition>
</transition>
<!-- From any state pressing VS changes to VS mode -->
<transition>
<name>VS</name>
<target>VS</target>
<exclude-target>true</exclude-target>
<condition>
<equals><property>/autopilot/vertical-mode-button</property><value>VS</value></equals>
</condition>
</transition>
<!-- From any state, pressing GA goes to GA mode -->
<transition>
<name>GA</name>
<target>GA</target>
<exclude-target>true</exclude-target>
<condition>
<equals><property>/autopilot/vertical-mode-button</property><value>GA</value></equals>
</condition>
</transition>
<!-- From any state, pressing ALT goes to ALT mode -->
<transition>
<name>ALT</name>
<target>ALT</target>
<exclude-target>true</exclude-target>
<condition>
<equals><property>/autopilot/vertical-mode-button</property><value>ALT</value></equals>
</condition>
<binding>
<command>nasal</command>
<script>
<!-- Set up the 2nd target to the current altitude within 10ft-->
setprop("/autopilot/settings/target-altitude-ft-2",
math.round(getprop("/instrumentation/altimeter/indicated-altitude-ft"),10));
</script>
</binding>
</transition>
</PropertyList>

View file

@ -0,0 +1,656 @@
<?xml version="1.0"?>
<!-- GFC 700 Autopilot Configuration -->
<!-- Each component is evaluated in the order specified. You can make up -->
<!-- property names to pass the result of one component on to a subsequent -->
<!-- component. -->
<PropertyList>
<state-machine include="GFC700-vertical-FSM.xml"/>
<state-machine include="GFC700-lateral-FSM.xml"/>
<state-machine include="GFC700-AP-off-FSM.xml"/>
<filter>
<name>heading bug error computer/normalizer</name>
<debug>false</debug>
<type>gain</type>
<input>
<property>/autopilot/settings/heading-bug-deg</property>
<offset>
<property>/orientation/heading-magnetic-deg</property>
<scale>-1.0</scale>
</offset>
</input>
<output>/autopilot/internal/heading-bug-error-deg</output>
<output>/autopilot/internal/fdm-heading-bug-error-deg</output>
<period>
<min>-180</min>
<max>180</max>
</period>
<gain>1.0</gain>
</filter>
<filter>
<name>true heading error computer/normalizer</name>
<debug>false</debug>
<type>gain</type>
<input>
<property>/autopilot/settings/true-heading-deg</property>
<offset>
<property>/orientation/heading-deg</property>
<scale>-1.0</scale>
</offset>
</input>
<output>/autopilot/internal/true-heading-error-deg</output>
<period>
<min>-180</min>
<max>180</max>
</period>
<gain>1.0</gain>
</filter>
<filter>
<name>nav1 heading error computer/normalizer</name>
<debug>false</debug>
<type>gain</type>
<input>
<property>/instrumentation/nav[0]/radials/target-auto-hdg-deg</property>
<offset>
<property>/orientation/heading-deg</property>
<scale>-1.0</scale>
</offset>
</input>
<output>/autopilot/internal/nav1-heading-error-deg</output>
<period>
<min>-180</min>
<max>180</max>
</period>
<gain>1.0</gain>
</filter>
<filter>
<name>nav1 selected course error computer/normalizer</name>
<debug>false</debug>
<type>gain</type>
<input>
<property>/instrumentation/nav[0]/radials/selected-deg</property>
<offset>
<property>/orientation/heading-magnetic-deg</property>
<scale>-1.0</scale>
</offset>
</input>
<output>/autopilot/internal/nav1-course-error</output>
<period>
<min>-180</min>
<max>180</max>
</period>
<gain>1.0</gain>
</filter>
<filter>
<name>vertical speed fpm computer</name>
<debug>false</debug>
<type>gain</type>
<input>/velocities/vertical-speed-fps</input>
<output>/autopilot/internal/vert-speed-fpm</output>
<gain>60.0</gain>
</filter>
<predict-simple>
<name>speed in 5 seconds predictor</name>
<debug>false</debug>
<input>/velocities/airspeed-kt</input>
<output>/autopilot/internal/lookahead-5-sec-airspeed-kt</output>
<seconds>5.0</seconds>
<filter-gain>0.0</filter-gain>
</predict-simple>
<predict-simple>
<name>speed in 10 seconds predictor</name>
<debug>false</debug>
<input>/velocities/airspeed-kt</input>
<output>/autopilot/internal/lookahead-10-sec-airspeed-kt</output>
<seconds>10.0</seconds>
<filter-gain>0.0</filter-gain>
</predict-simple>
<filter>
<name>static port pressure rate computer</name>
<debug>false</debug>
<type>derivative</type>
<input>/systems/static[0]/pressure-inhg</input>
<output>/autopilot/internal/pressure-rate</output>
<filter-time>1.0</filter-time>
</filter>
<filter>
<name>nav1 track error computer</name>
<debug>false</debug>
<type>gain</type>
<input>
<property>/instrumentation/nav[0]/radials/target-auto-hdg-deg</property>
<offset>
<property>orientation/track-deg</property>
<scale>-1.0</scale>
</offset>
</input>
<output>/autopilot/internal/nav1-track-error-deg</output>
<period>
<min>-180</min>
<max>180</max>
</period>
<gain>1.0</gain>
</filter>
<filter>
<name>limited-pitch</name>
<debug>false</debug>
<type>gain</type>
<input>
<property>/instrumentation/attitude-indicator/indicated-pitch-deg</property>
</input>
<gain>1.0</gain>
<output>/autopilot/internal/filtered-pitch-deg</output>
<min>-15.0</min>
<max>20.0</max>
</filter>
<filter>
<name>limited-roll</name>
<debug>false</debug>
<type>gain</type>
<input>
<property>/instrumentation/attitude-indicator/indicated-roll-deg</property>
</input>
<gain>1.0</gain>
<output>/autopilot/internal/filtered-roll-deg</output>
<min>-22.0</min>
<max>22.0</max>
</filter>
<filter>
<name>ALTS-delta</name>
<debug>false</debug>
<type>gain</type>
<input>
<property>/autopilot/settings/target-altitude-ft</property>
<offset>
<property>/instrumentation/altimeter/indicated-altitude-ft-2</property>
<scale>-1.0</scale>
</offset>
</input>
<gain>1.0</gain>
<output>/autopilot/internal/ALTS-target-altitude-delta-ft</output>
</filter>
<!-- Logic filters to show autopilot and Flight Director status -->
<logic>
<input>
<and>
<equals><property>/autopilot/locks/passive-mode</property><value>0</value></equals>
<or>
<not><equals><property>/autopilot/locks/heading</property><value></value></equals></not>
<not><equals><property>/autopilot/locks/altitude</property><value></value></equals></not>
</or>
</and>
</input>
<output>/autopilot/annunciator/autopilot-enabled</output>
</logic>
<logic>
<input>
<and>
<equals><property>/autopilot/locks/passive-mode</property><value>1</value></equals>
<or>
<not><equals><property>/autopilot/locks/heading</property><value></value></equals></not>
<not><equals><property>/autopilot/locks/altitude</property><value></value></equals></not>
</or>
</and>
</input>
<output>/autopilot/annunciator/flight-director-enabled</output>
</logic>
<!-- =============================================================== -->
<!-- Roll Axis Modes -->
<!-- =============================================================== -->
<!-- Aileron control, used by all lateral modes ROL/NAV/HDG -->
<pid-controller>
<name>Roll Hold</name>
<debug>false</debug>
<enable>
<condition>
<and>
<or>
<equals>
<property>/autopilot/locks/heading</property>
<value>roll-hold</value>
</equals>
<equals>
<property>/autopilot/locks/heading</property>
<value>dg-heading-hold</value>
</equals>
<equals>
<property>/autopilot/locks/heading</property>
<value>nav1-hold</value>
</equals>
</or>
<equals>
<property>/autopilot/locks/passive-mode</property>
<value>0</value>
</equals>
<not>
<equals>
<property>/autopilot/locks/control-wheel-steering</property>
<value>1</value>
</equals>
</not>
</and>
</condition>
</enable>
<input>
<prop>/orientation/roll-deg</prop>
</input>
<reference>
<prop>/autopilot/settings/target-roll-deg</prop>
</reference>
<output>
<prop>/controls/flight/aileron</prop>
</output>
<config>
<Kp>0.1</Kp> <!-- proportional gain -->
<beta>1.0</beta> <!-- input value weighing factor -->
<alpha>0.1</alpha> <!-- low pass filter weighing factor -->
<gamma>0.0</gamma> <!-- input value weighing factor for -->
<!-- unfiltered derivative error -->
<Ti>10.0</Ti> <!-- integrator time -->
<Td>0.00001</Td> <!-- derivator time -->
<u_min>-1.0</u_min> <!-- minimum output clamp -->
<u_max>1.0</u_max> <!-- maximum output clamp -->
</config>
</pid-controller>
<!-- Heading Bug Hold. 2 stage cascade controller. -->
<!-- Stage #1 sets target roll based on diff between current heading -->
<!-- and heading bug. -->
<pid-controller>
<name>Heading Bug Hold (DG based) Stage 1</name>
<debug>false</debug>
<enable>
<prop>/autopilot/locks/heading</prop>
<value>dg-heading-hold</value>
</enable>
<input>
<prop>/autopilot/internal/heading-bug-error-deg</prop>
</input>
<reference>
<value>0.0</value>
</reference>
<output>
<prop>/autopilot/settings/target-roll-deg</prop>
</output>
<config>
<Kp>-1.0</Kp> <!-- proportional gain -->
<beta>1.0</beta> <!-- input value weighing factor -->
<alpha>0.1</alpha> <!-- low pass filter weighing factor -->
<gamma>0.0</gamma> <!-- input value weighing factor for -->
<!-- unfiltered derivative error -->
<Ti>10.0</Ti> <!-- integrator time -->
<Td>0.00001</Td> <!-- derivator time -->
<u_min>-20.0</u_min> <!-- minimum output clamp -->
<u_max>20.0</u_max> <!-- maximum output clamp -->
</config>
</pid-controller>
<!-- True Heading hold. 2 stage cascade controller. -->
<!-- Stage #1 sets target roll based on diff between current heading -->
<!-- and target heading. -->
<pid-controller>
<name>True Heading Hold (DG based) Stage 1</name>
<debug>false</debug>
<enable>
<prop>/autopilot/locks/heading</prop>
<value>true-heading-hold</value>
</enable>
<input>
<prop>/autopilot/internal/true-heading-error-deg</prop>
</input>
<reference>
<value>0.0</value>
</reference>
<output>
<prop>/autopilot/settings/target-roll-deg</prop>
</output>
<config>
<Kp>-1.0</Kp> <!-- proportional gain -->
<beta>1.0</beta> <!-- input value weighing factor -->
<alpha>0.1</alpha> <!-- low pass filter weighing factor -->
<gamma>0.0</gamma> <!-- input value weighing factor for -->
<!-- unfiltered derivative error -->
<Ti>10.0</Ti> <!-- integrator time -->
<Td>0.00001</Td> <!-- derivator time -->
<u_min>-20.0</u_min> <!-- minimum output clamp -->
<u_max>20.0</u_max> <!-- maximum output clamp -->
</config>
</pid-controller>
<!-- Nav1 hold. 2 stage cascade controller. -->
<!-- Stage #1 sets target roll based on diff between current heading -->
<!-- and target heading. -->
<pid-controller>
<name>Nav1 Hold Stage 1</name>
<debug>false</debug>
<enable>
<prop>/autopilot/locks/heading</prop>
<value>nav1-hold</value>
</enable>
<input>
<prop>/autopilot/internal/nav1-heading-error-deg</prop>
</input>
<reference>
<value>0.0</value>
</reference>
<output>
<prop>/autopilot/internal/target-roll-deg</prop>
</output>
<config>
<Kp>-1.0</Kp> <!-- proportional gain -->
<beta>1.0</beta> <!-- input value weighing factor -->
<alpha>0.1</alpha> <!-- low pass filter weighing factor -->
<gamma>0.0</gamma> <!-- input value weighing factor for -->
<!-- unfiltered derivative error -->
<Ti>10.0</Ti> <!-- integrator time -->
<Td>0.00001</Td> <!-- derivator time -->
<u_min>-20.0</u_min> <!-- minimum output clamp -->
<u_max>20.0</u_max> <!-- maximum output clamp -->
</config>
</pid-controller>
<!-- =============================================================== -->
<!-- Pitch Axis Modes -->
<!-- =============================================================== -->
<!-- Simple pitch hold for PIT and FLC modes. -->
<pid-controller>
<name>Pitch hold</name>
<debug>false</debug>
<enable>
<condition>
<and>
<equals>
<property>/autopilot/locks/passive-mode</property>
<value>0</value>
</equals>
<not>
<equals>
<property>/autopilot/locks/control-wheel-steering</property>
<value>1</value>
</equals>
</not>
<or>
<not>
<equals>
<property>/autopilot/locks/altitude</property>
<value></value>
</equals>
</not>
<not>
<equals>
<property>/autopilot/locks/speed</property>
<value></value>
</equals>
</not>
</or>
</and>
</condition>
</enable>
<input>
<prop>/orientation/pitch-deg</prop>
</input>
<reference>
<prop>/autopilot/settings/target-pitch-deg</prop>
</reference>
<output>
<prop>/controls/flight/elevator-trim</prop>
</output>
<config>
<Kp>-0.05</Kp> <!-- proportional gain -->
<beta>1.0</beta> <!-- input value weighing factor -->
<alpha>0.1</alpha> <!-- low pass filter weighing factor -->
<gamma>0.0</gamma> <!-- input value weighing factor for -->
<!-- unfiltered derivative error -->
<Ti>1.0</Ti> <!-- integrator time -->
<Td>0.00001</Td> <!-- derivator time -->
<u_min>-1.0</u_min> <!-- minimum output clamp -->
<u_max>1.0</u_max> <!-- maximum output clamp -->
</config>
</pid-controller>
<!-- Common vertical speed controller for ALT/APR/VNV modes mode -->
<pid-controller>
<name>Altitude Hold (Altimeter based) Stage 2</name>
<debug>false</debug>
<enable>
<condition>
<and>
<not>
<equals>
<property>/autopilot/locks/control-wheel-steering</property>
<value>1</value>
</equals>
</not>
<or>
<equals>
<property>/autopilot/locks/altitude</property>
<value>altitude-hold</value>
</equals>
<equals>
<property>/autopilot/locks/altitude</property>
<value>altitude-hold2</value>
</equals>
</or>
</and>
</condition>
</enable>
<input>
<prop>/velocities/vertical-speed-fps</prop>
</input>
<reference>
<prop>/autopilot/internal/target-climb-rate-fps</prop>
</reference>
<output>
<prop>/autopilot/settings/target-pitch-deg</prop>
</output>
<config>
<Kp>-0.01</Kp> <!-- proportional gain -->
<beta>1.0</beta> <!-- input value weighing factor -->
<alpha>0.1</alpha> <!-- low pass filter weighing factor -->
<gamma>0.0</gamma> <!-- input value weighing factor for -->
<!-- unfiltered derivative error -->
<Ti>10.0</Ti> <!-- integrator time -->
<Td>0.00001</Td> <!-- derivator time -->
<u_min>-1.0</u_min> <!-- minimum output clamp -->
<u_max>1.0</u_max> <!-- maximum output clamp -->
</config>
</pid-controller>
<!-- Altitude hold. 2 stage cascade controller. -->
<!-- Stage #1 sets target rate of climb based on diff between current alt -->
<!-- and target altitude. -->
<pi-simple-controller>
<name>Altitude Hold (Altimeter based) Stage 1</name>
<debug>false</debug>
<enable>
<condition>
<equals>
<property>/autopilot/locks/altitude</property>
<value>altitude-hold</value>
</equals>
</condition>
</enable>
<input>
<prop>/position/altitude-ft</prop>
</input>
<reference>
<prop>/autopilot/settings/target-altitude-ft</prop>
</reference>
<output>
<prop>/autopilot/internal/target-climb-rate-fps</prop>
</output>
<config>
<Kp>0.3</Kp> <!-- proportional gain -->
<Ki>0.0</Ki> <!-- integral gain -->
<u_min>-16.67</u_min> <!-- minimum output clamp -->
<u_max>8.33</u_max> <!-- maximum output clamp -->
</config>
</pi-simple-controller>
<!-- Altitude hold2. 2 stage cascade controller. -->
<!-- Stage #1 sets target rate of climb based on diff between current alt -->
<!-- and target altitude. -->
<pi-simple-controller>
<name>Altitude Hold (Altimeter based) Stage 1</name>
<debug>false</debug>
<enable>
<condition>
<equals>
<property>/autopilot/locks/altitude</property>
<value>altitude-hold2</value>
</equals>
</condition>
</enable>
<input>
<prop>/position/altitude-ft</prop>
</input>
<reference>
<prop>/autopilot/settings/target-altitude-ft-2</prop>
</reference>
<output>
<prop>/autopilot/internal/target-climb-rate-fps</prop>
</output>
<config>
<Kp>0.3</Kp> <!-- proportional gain -->
<Ki>0.0</Ki> <!-- integral gain -->
<u_min>-16.67</u_min> <!-- minimum output clamp -->
<u_max>8.33</u_max> <!-- maximum output clamp -->
</config>
</pi-simple-controller>
<!-- Glideslope hold. -->
<!-- Stage #2 drives the elevator-trim to achieve the desired climb rate. -->
<pid-controller>
<name>Glideslope Hold</name>
<debug>false</debug>
<enable>
<condition>
<equals>
<property>/autopilot/locks/altitude</property>
<value>gs1-hold</value>
</equals>
</condition>
</enable>
<input>
<prop>/velocities/vertical-speed-fps</prop>
</input>
<reference>
<prop>/instrumentation/nav[0]/gs-rate-of-climb</prop>
</reference>
<output>
<prop>/autopilot/settings/target-pitch-deg</prop>
</output>
<config>
<Kp>-0.01</Kp> <!-- proportional gain -->
<beta>1.0</beta> <!-- input value weighing factor -->
<alpha>0.1</alpha> <!-- low pass filter weighing factor -->
<gamma>0.0</gamma> <!-- input value weighing factor for -->
<!-- unfiltered derivative error -->
<Ti>10.0</Ti> <!-- integrator time -->
<Td>0.00001</Td> <!-- derivator time -->
<u_min>-1.0</u_min> <!-- minimum output clamp -->
<u_max>1.0</u_max> <!-- maximum output clamp -->
</config>
</pid-controller>
<!-- vertical speed hold VS mode -->
<pid-controller>
<name>Vertical Speed Hold</name>
<debug>false</debug>
<enable>
<condition>
<equals>
<property>/autopilot/locks/altitude</property>
<value>vertical-speed-hold</value>
</equals>
</condition>
</enable>
<input>
<prop>/velocities/vertical-speed-fps</prop>
</input>
<reference>
<prop>/autopilot/settings/vertical-speed-fpm</prop>
<scale>0.01667</scale>
</reference>
<output>
<prop>/autopilot/settings/target-pitch-deg</prop>
</output>
<config>
<Kp>0.1</Kp> <!-- proportional gain -->
<beta>1.0</beta> <!-- input value weighing factor -->
<alpha>0.1</alpha> <!-- low pass filter weighing factor -->
<gamma>0.0</gamma> <!-- input value weighing factor for -->
<!-- unfiltered derivative error -->
<Ti>1.0</Ti> <!-- integrator time -->
<Td>0.00001</Td> <!-- derivator time -->
<u_min>-15.0</u_min><!-- minimum output clamp -->
<u_max>15.0</u_max> <!-- maximum output clamp -->
</config>
</pid-controller>
<!-- =============================================================== -->
<!-- Velocity Modes -->
<!-- =============================================================== -->
<!-- FLC mode - Hold speed by varying pitch trim (Two stage cascading controller) -->
<pid-controller>
<name>Speed hold (vary pitch trim) Stage #1</name>
<debug>false</debug>
<enable>
<condition>
<equals>
<property>/autopilot/locks/speed</property>
<value>speed-with-pitch-trim</value>
</equals>
</condition>
</enable>
<input>
<prop>/autopilot/internal/lookahead-5-sec-airspeed-kt</prop>
</input>
<reference>
<prop>/autopilot/settings/target-speed-kt</prop>
</reference>
<output>
<prop>/autopilot/settings/target-pitch-deg</prop>
</output>
<config>
<Kp>-1.0</Kp> <!-- proportional gain -->
<beta>1.0</beta> <!-- input value weighing factor -->
<alpha>0.1</alpha> <!-- low pass filter weighing factor -->
<gamma>0.0</gamma> <!-- input value weighing factor for -->
<!-- unfiltered derivative error -->
<Ti>1.0</Ti> <!-- integrator time -->
<Td>0.00001</Td> <!-- derivator time -->
<u_min>-15.0</u_min><!-- minimum output clamp -->
<u_max>15.0</u_max> <!-- maximum output clamp -->
</config>
</pid-controller>
</PropertyList>

View file

@ -24,11 +24,11 @@
borderopacity="1"
inkscape:pageopacity="1"
inkscape:pageshadow="2"
inkscape:zoom="3.7187502"
inkscape:cx="505.11063"
inkscape:cy="193.43835"
inkscape:zoom="2.6295535"
inkscape:cx="378.97168"
inkscape:cy="351.68237"
inkscape:document-units="px"
inkscape:current-layer="svg3140"
inkscape:current-layer="PFDInstrumentsBankPoint"
showgrid="false"
showguides="false"
inkscape:guide-bbox="true"
@ -2473,41 +2473,6 @@
style="display:inline;opacity:1"
inkscape:label="BankPoint"
id="PFDInstrumentsBankPoint">
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:none;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 459.5,96 c -67.34296,-10e-7 -129.57461,35.92928 -163.24609,94.25 -33.67148,58.32072 -33.67149,130.17928 0,188.5 C 329.92539,437.07072 392.15704,473 459.5,473 v -2 c -66.63164,0 -128.19785,-35.54531 -161.51367,-93.25 -33.31582,-57.70469 -33.31582,-128.79531 0,-186.5 C 331.30215,133.54531 392.86836,97.999999 459.5,98 Z"
id="bankPointerLineL"
inkscape:connector-curvature="0" />
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:none;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 459.5,96 v 2 C 562.51295,98.000002 646,181.48705 646,284.5 646,387.51295 562.51295,471 459.5,471 v 2 C 563.59383,473 648,388.59383 648,284.5 648,180.40617 563.59383,96.000002 459.5,96 Z"
id="PFDInstrumentsbankPointerLineR"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="PFDInstrumentsRollPointer"
d="m 459.5,98 -11.0288,22 h 22.05598 z"
style="display:inline;fill:#ffffff;fill-opacity:1;stroke:none"
sodipodi:nodetypes="cccc"
inkscape:label="RollPointer" />
<path
inkscape:connector-curvature="0"
id="PFDInstrumentsSlipSkid"
d="M 447.43093,122 444,129 h 30.87838 l -3.43093,-7 z"
style="display:inline;fill:#ffffff;fill-opacity:1;stroke:none"
inkscape:label="SlipSkid" />
<path
style="display:inline;fill:#ffde29;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 255.5,280.5 H 298 l 3.5,4 -3.5,4 h -42.5 z"
id="lWingTip"
inkscape:connector-curvature="0"
inkscape:label="lWingTip" />
<path
style="display:inline;opacity:1;fill:#ffde29;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 663.49738,280.5 h -42.5 l -3.5,4 3.5,4 h 42.5 z"
id="rWingTip"
inkscape:connector-curvature="0"
inkscape:label="rWingTip" />
<g
id="g5175"
transform="matrix(0.99913533,0,0,0.99999965,0.19473622,0.4851099)"
@ -2557,6 +2522,63 @@
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</g>
</g>
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:none;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 459.5,96 c -67.34296,-10e-7 -129.57461,35.92928 -163.24609,94.25 -33.67148,58.32072 -33.67149,130.17928 0,188.5 C 329.92539,437.07072 392.15704,473 459.5,473 v -2 c -66.63164,0 -128.19785,-35.54531 -161.51367,-93.25 -33.31582,-57.70469 -33.31582,-128.79531 0,-186.5 C 331.30215,133.54531 392.86836,97.999999 459.5,98 Z"
id="bankPointerLineL"
inkscape:connector-curvature="0" />
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:none;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 459.5,96 v 2 C 562.51295,98.000002 646,181.48705 646,284.5 646,387.51295 562.51295,471 459.5,471 v 2 C 563.59383,473 648,388.59383 648,284.5 648,180.40617 563.59383,96.000002 459.5,96 Z"
id="PFDInstrumentsbankPointerLineR"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="PFDInstrumentsRollPointer"
d="m 459.5,98 -11.0288,22 h 22.05598 z"
style="display:inline;fill:#ffffff;fill-opacity:1;stroke:none"
sodipodi:nodetypes="cccc"
inkscape:label="RollPointer" />
<path
inkscape:connector-curvature="0"
id="PFDInstrumentsSlipSkid"
d="M 447.43093,122 444,129 h 30.87838 l -3.43093,-7 z"
style="display:inline;fill:#ffffff;fill-opacity:1;stroke:none"
inkscape:label="SlipSkid" />
<path
style="display:inline;fill:#ffde29;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 255.5,280.5 H 298 l 3.5,4 -3.5,4 h -42.5 z"
id="lWingTip"
inkscape:connector-curvature="0"
inkscape:label="lWingTip" />
<path
style="display:inline;opacity:1;fill:#ffde29;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 663.49738,280.5 h -42.5 l -3.5,4 3.5,4 h 42.5 z"
id="rWingTip"
inkscape:connector-curvature="0"
inkscape:label="rWingTip" />
<g
style="display:inline;opacity:1"
id="PFDInstrumentsFlightDirector"
transform="matrix(0.99913533,0,0,0.99999965,-0.28003001,0.26394506)"
inkscape:label="aircraftSymbol">
<g
id="g5167-8"
transform="matrix(-1,0,0,1,919.54877,0.13445281)">
<path
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0"
id="path5173-7"
d="m 459.7033,284.01172 c -53.37666,7.54171 -90.53947,13.01083 -144.12286,18.81916 l -0.22371,10.3963 26.62394,0.26891 z"
style="fill:#ff00ff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
style="fill:#ff00ff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 460.09291,284.01172 c 53.37666,7.54171 90.53947,13.01083 144.12286,18.81916 l 0.22371,10.3963 -26.62394,0.26891 z"
id="path5456"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
</g>
</g>
</g>
<g
style="display:inline;opacity:1"

Before

Width:  |  Height:  |  Size: 468 KiB

After

Width:  |  Height:  |  Size: 469 KiB

View file

@ -23,11 +23,11 @@
borderopacity="0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.828427"
inkscape:cx="837.03116"
inkscape:cy="90.026882"
inkscape:zoom="1.4142135"
inkscape:cx="642.54405"
inkscape:cy="640.61088"
inkscape:document-units="px"
inkscape:current-layer="NrstPageGroup"
inkscape:current-layer="g57958"
showgrid="true"
inkscape:window-width="2495"
inkscape:window-height="1416"
@ -65,8 +65,7 @@
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Surround"
style="display:inline"
sodipodi:insensitive="true">
style="display:inline">
<g
id="NAV"
inkscape:label="NAV"
@ -885,14 +884,89 @@
x="397.90625"
id="tspan57988"
sodipodi:role="line">D</tspan></text>
<text
sodipodi:linespacing="125%"
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:21.33374929px;line-height:125%;font-family:FreeSans;letter-spacing:0px;word-spacing:0px;display:inline;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;-inkscape-font-specification:'FreeSans, Normal';font-stretch:normal;font-variant:normal;text-anchor:start;text-align:start;writing-mode:lr;"
x="269.76041"
y="47.697918"
id="SurroundHeaderAPLateralArmed"
inkscape:label="DATA-FIELD2-VAL-text"><tspan
sodipodi:role="line"
id="tspan7801">ARM</tspan></text>
<text
sodipodi:linespacing="125%"
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:21.33374929px;line-height:125%;font-family:FreeSans;letter-spacing:0px;word-spacing:0px;display:inline;fill:#00ff00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;-inkscape-font-specification:'FreeSans, Normal';font-stretch:normal;font-variant:normal;text-anchor:start;text-align:start;writing-mode:lr;"
x="344.76041"
y="47.697918"
id="SurroundHeaderAPLateralActive"
inkscape:label="DATA-FIELD2-VAL-text"><tspan
sodipodi:role="line"
id="tspan7803">ACT</tspan></text>
<text
sodipodi:linespacing="125%"
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:21.33374929px;line-height:125%;font-family:FreeSans;-inkscape-font-specification:'FreeSans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr;text-anchor:start;display:inline;fill:#00ff00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;"
x="404.32443"
y="48"
id="SurroundHeaderAPStatus"
inkscape:label="DATA-FIELD2-VAL-text"><tspan
sodipodi:role="line"
id="tspan7838">AP</tspan></text>
<text
sodipodi:linespacing="125%"
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:21.33374929px;line-height:125%;font-family:FreeSans;-inkscape-font-specification:'FreeSans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr;text-anchor:start;display:inline;fill:#00ff00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;"
x="497.86313"
y="48.000004"
id="SurroundHeaderAPVerticalActive"
inkscape:label="DATA-FIELD2-VAL-text"><tspan
sodipodi:role="line"
id="tspan7873">ACT</tspan></text>
<text
sodipodi:linespacing="125%"
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:21.33374977px;line-height:125%;font-family:FreeSans;-inkscape-font-specification:'FreeSans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;display:inline;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="659.67999"
y="48"
id="SurroundHeaderAPVerticalArmed"
inkscape:label="DATA-FIELD2-VAL-text"><tspan
sodipodi:role="line"
id="tspan7893"
x="659.67999"
y="48">ARM</tspan></text>
<text
sodipodi:linespacing="125%"
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:21.33374977px;line-height:125%;font-family:FreeSans;-inkscape-font-specification:'FreeSans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;display:inline;fill:#00ff00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="595.99384"
y="48.000008"
id="SurroundHeaderAPVerticalReference"
inkscape:label="DATA-FIELD2-VAL-text"><tspan
sodipodi:role="line"
id="tspan7913"
x="595.99384"
y="48.000008">5000ft</tspan></text>
</g>
<path
inkscape:connector-curvature="0"
id="path4617-5"
d="m 395.71032,56 0,-28"
style="display:inline;fill:none;stroke:#ffffff;stroke-width:1.42064464;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path4617-5-4"
d="m 489.28968,56 0,-28"
style="display:inline;fill:none;stroke:#ffffff;stroke-width:1.42064464;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
</g>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="PageGroup"
style="display:inline">
style="display:inline"
sodipodi:insensitive="true">
<g
style="display:inline"
id="WPTPageGroup"
@ -1162,7 +1236,7 @@
id="FPLPageGroup"
inkscape:label="#g5441">
<rect
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.752;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.75199997;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect5325"
width="257.24811"
height="70.710793"

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 79 KiB

View file

@ -0,0 +1,133 @@
# Copyright 2019 Stuart Buchanan
# This file is part of FlightGear.
#
# FlightGear is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# FlightGear is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with FlightGear. If not, see <http://www.gnu.org/licenses/>.
#
# Emesary interface to set autopilot configuration.
#
var GFC700Interface = {
new : func ()
{
var obj = { parents : [ GFC700Interface ] };
# Emesary
obj._recipient = nil;
obj._transmitter = emesary.GlobalTransmitter;
obj._registered = 0;
obj._vertical_mode = globals.props.getNode("/autopilot/annunciator/vertical-mode", 1);
obj._pitch_setting = globals.props.getNode("/autopilot/settings/target-pitch-deg", 1);
obj._climb_setting = globals.props.getNode("/autopilot/settings/vertical-speed-fpm", 1);
obj._speed_setting = globals.props.getNode("/autopilot/settings/target-speed-kt", 1);
# State variables
obj._vertical_mode_button = globals.props.getNode("/autopilot/vertical-mode-button", 1);
obj._lateral_mode_button = globals.props.getNode("/autopilot/lateral-mode-button", 1);
obj._ap_mode_button = globals.props.getNode("/autopilot/AP-mode-button", 1);
obj._ap_enabled = globals.props.getNode("/autopilot/annunciator/autopilot-enabled", 1);;
obj._fd_enabled = globals.props.getNode("/autopilot/annunciator/flight-director-enabled", 1);;
return obj;
},
# Under the covers there are 3 FSMs, two of which run in parallel, and need
# separate input channels.
sendModeChange : func(value) {
me._vertical_mode_button.setValue(value);
me._lateral_mode_button.setValue(value);
if (value == "AP") {
me._ap_mode_button.setValue("AP");
}
return emesary.Transmitter.ReceiptStatus_Finished;
},
handleNoseUpDown : func(value) {
var vertical_mode = me._vertical_mode.getValue();
if (vertical_mode == "PIT") {
me._pitch_setting.setValue(me._pitch_setting.getValue() + (value * 1));
}
if (vertical_mode == "VS") {
me._climb_setting.setValue(me._climb_setting.getValue() + (value * 100));
setprop("/autopilot/annunciator/vertical-mode-target",
sprintf("%+ifpm", me._climb_setting.getValue())
);
}
if (vertical_mode == "FLC") {
me._speed_setting.setValue(me._speed_setting.getValue() + (value * 1));
}
return emesary.Transmitter.ReceiptStatus_Finished;
},
RegisterWithEmesary : func()
{
if (me._recipient == nil){
me._recipient = emesary.Recipient.new("AutopilotInterface");
var controller = me;
# Note that unlike the various keys, this data isn't specific to a particular
# Device - it's shared by all. Hence we don't check for the notificaiton
# Device_Id.
me._recipient.Receive = func(notification)
{
if (notification.NotificationType == notifications.PFDEventNotification.DefaultType and
notification.Event_Id == notifications.PFDEventNotification.HardKeyPushed and
notification.EventParameter != nil)
{
var id = notification.EventParameter.Id;
var value = notification.EventParameter.Value;
if (id == fg1000.FASCIA.AP ) return controller.sendModeChange("AP");
if (id == fg1000.FASCIA.HDG) return controller.sendModeChange("HDG");
if (id == fg1000.FASCIA.NAV) return controller.sendModeChange("NAV");
if (id == fg1000.FASCIA.APR) return controller.sendModeChange("APR");
if (id == fg1000.FASCIA.VS ) return controller.sendModeChange("VS");
if (id == fg1000.FASCIA.FLC) return controller.sendModeChange("FLC");
if (id == fg1000.FASCIA.FD ) return controller.sendModeChange("FD");
if (id == fg1000.FASCIA.ALT) return controller.sendModeChange("ALT");
if (id == fg1000.FASCIA.VNV) return controller.sendModeChange("VNV");
if (id == fg1000.FASCIA.BC ) controller.sendModeChange("BC");
if (id == fg1000.FASCIA.NOSE_UP) return controller.handleNoseUpDown(1);
if (id == fg1000.FASCIA.NOSE_DOWN) return controller.handleNoseUpDown(-1);
}
return emesary.Transmitter.ReceiptStatus_NotProcessed;
};
}
me._transmitter.Register(me._recipient);
me._registered = 1;
},
DeRegisterWithEmesary : func()
{
# remove registration from transmitter; but keep the recipient once it is created.
if (me._registered == 1) me._transmitter.DeRegister(me._recipient);
me._registered = 0;
},
start : func() {
me.RegisterWithEmesary();
},
stop : func() {
me.DeRegisterWithEmesary();
},
};

View file

@ -0,0 +1,41 @@
# Copyright 2019 Stuart Buchanan
# This file is part of FlightGear.
#
# FlightGear is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# FlightGear is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with FlightGear. If not, see <http://www.gnu.org/licenses/>.
#
# Emesary interface to publish autopilot configuration.
#
var GFC700Publisher = {
new : func ()
{
var obj = { parents : [
GFC700Publisher,
TriggeredPropertyPublisher.new(notifications.PFDEventNotification.FMSData) ] };
obj.addPropMap("AutopilotEnabled", "/autopilot/annunciator/autopilot-enabled");
obj.addPropMap("AutopilotFDEnabled", "/autopilot/annunciator/flight-director-enabled");
obj.addPropMap("AutopilotHeadingMode", "/autopilot/annunciator/lateral-mode");
obj.addPropMap("AutopilotHeadingModeArmed", "/autopilot/annunciator/lateral-mode-armed");
obj.addPropMap("AutopilotAltitudeMode", "/autopilot/annunciator/vertical-mode");
obj.addPropMap("AutopilotAltitudeModeArmed", "/autopilot/annunciator/vertical-mode-armed");
obj.addPropMap("AutopilotTargetPitch", "/autopilot/settings/target-pitch-deg");
obj.addPropMap("AutopilotTargetRoll", "/autopilot/settings/target-roll-deg");
obj.addPropMap("AutopilotTargetVertical", "/autopilot/annunciator/vertical-mode-target");
return obj;
},
};

View file

@ -17,9 +17,9 @@
# Generic Interface controller.
var nasal_dir = getprop("/sim/fg-root") ~ "/Aircraft/Instruments-3d/FG1000/Nasal/";
io.load_nasal(nasal_dir ~ 'Interfaces/NavDataInterface.nas', "fg1000");
io.load_nasal(nasal_dir ~ 'Interfaces/PropertyPublisher.nas', "fg1000");
io.load_nasal(nasal_dir ~ 'Interfaces/PropertyUpdater.nas', "fg1000");
io.load_nasal(nasal_dir ~ 'Interfaces/NavDataInterface.nas', "fg1000");
io.load_nasal(nasal_dir ~ 'Interfaces/GenericEISPublisher.nas', "fg1000");
io.load_nasal(nasal_dir ~ 'Interfaces/GenericNavComPublisher.nas', "fg1000");
io.load_nasal(nasal_dir ~ 'Interfaces/GenericNavComUpdater.nas', "fg1000");
@ -28,11 +28,26 @@ io.load_nasal(nasal_dir ~ 'Interfaces/GenericFMSUpdater.nas', "fg1000");
io.load_nasal(nasal_dir ~ 'Interfaces/GenericADCPublisher.nas', "fg1000");
io.load_nasal(nasal_dir ~ 'Interfaces/GenericFuelInterface.nas', "fg1000");
io.load_nasal(nasal_dir ~ 'Interfaces/GenericFuelPublisher.nas', "fg1000");
io.load_nasal(nasal_dir ~ 'Interfaces/GFC700Interface.nas', "fg1000");
var GenericInterfaceController = {
_instance : nil,
INTERFACE_LIST : [
"NavDataInterface",
"GenericEISPublisher",
"GenericNavComPublisher",
"GenericNavComUpdater",
"GenericFMSPublisher",
"GenericFMSUpdater",
"GenericADCPublisher",
"GenericFuelInterface",
"GenericFuelPublisher",
"GFC700Publisher",
"GFC700Interface",
],
# Factory method
getOrCreateInstance : func() {
if (GenericInterfaceController._instance == nil) {
@ -48,42 +63,44 @@ var GenericInterfaceController = {
running : 0,
};
obj.eisPublisher = fg1000.GenericEISPublisher.new();
obj.navcomPublisher = fg1000.GenericNavComPublisher.new();
obj.navcomUpdater = fg1000.GenericNavComUpdater.new();
obj.navdataInterface = fg1000.NavDataInterface.new();
obj.gpsPublisher = fg1000.GenericFMSPublisher.new();
obj.gpsUpdater = fg1000.GenericFMSUpdater.new();
obj.adcPublisher = fg1000.GenericADCPublisher.new();
obj.fuelPublisher = fg1000.GenericFuelPublisher.new();
obj.fuelInterface = fg1000.GenericFuelInterface.new();
return obj;
},
start : func() {
if (me.running) return;
me.eisPublisher.start();
me.navcomPublisher.start();
me.navcomUpdater.start();
me.navdataInterface.start();
me.gpsPublisher.start();
me.gpsUpdater.start();
me.adcPublisher.start();
me.fuelPublisher.start();
me.fuelInterface.start();
# Reload the interfaces afresh to make development easier. In normal
# usage this interface will only be started once anyway.
foreach (var interface; GenericInterfaceController.INTERFACE_LIST) {
io.load_nasal(nasal_dir ~ 'Interfaces/' ~ interface ~ '.nas', "fg1000");
var code = sprintf("me.%sInstance = fg1000.%s.new();", interface, interface);
var instantiate = compile(code);
instantiate();
}
foreach (var interface; GenericInterfaceController.INTERFACE_LIST) {
io.load_nasal(nasal_dir ~ 'Interfaces/' ~ interface ~ '.nas', "fg1000");
var code = 'me.' ~ interface ~ 'Instance.start();';
var start_interface = compile(code);
start_interface();
}
me.running = 1;
},
stop : func() {
if (me.running == 0) return;
me.eisPublisher.stop();
me.navcomPublisher.stop();
me.navcomUpdater.stop();
me.navdataInterface.stop();
me.gpsPublisher.stop();
me.gpsUpdater.stop();
me.adcPublisher.stop();
me.fuelPublisher.stop();
me.fuelInterface.stop();
foreach (var interface; GenericInterfaceController.INTERFACE_LIST) {
io.load_nasal(nasal_dir ~ 'Interfaces/' ~ interface ~ '.nas', "fg1000");
var code = 'me.' ~ interface ~ 'Instance.stop();';
var stop_interface = compile(code);
stop_interface();
}
},
restart : func() {
me.stop();
me.start();
}
};

View file

@ -44,6 +44,7 @@ var PFDInstruments =
_OMI : "",
_Multiline : 0,
_annunciation : 0,
_fd_enabled : 1, # Mark the Flight Director as enabled, as it is visible in the SVG.
};
# Hide various elements for the moment. TODO - implement
@ -136,7 +137,7 @@ var PFDInstruments =
pg.clearMenu();
pg.resetMenuColors();
pg.addMenuItem(0, "OFF", pg, func(dev, pg, mi) { pg.setInsetMapVisible(0); }); # TODO
pg.addMenuItem(0, "OFF", pg, func(dev, pg, mi) { pg.setInsetMapVisible(0); pg.mfd.PFDInstruments.topMenu(dev, pg, mi); } );
pg.addMenuItem(1, "DCLTR", pg,
func(dev, pg, mi) { pg.insetMap.incrDCLTR(dev, mi); device.updateMenus(); },
func(svg, mi) { pg.displayDCLTR(svg, mi); },
@ -327,6 +328,25 @@ var PFDInstruments =
.setTranslation(slip * 10, 0);
},
updateFD : func(enabled, pitch, roll, fd_pitch, fd_roll) {
if (enabled) {
me.getElement("FlightDirector")
.setCenter(459,282.8)
.setRotation(-(roll - fd_roll) * D2R)
.setTranslation(0, -(fd_pitch - pitch) * 6.849)
.setVisible(1);
me._fd_enabled = 1;
} else if (me._fd_enabled == 1) {
me.getElement("FlightDirector").setVisible(0);
me._fd_enabled = 0;
}
# Overrides - command bars disappear if pitch exceeeds -20/+30, roll 65
if ((pitch < -20.0) or (pitch > 30.0) or (roll < -65.0) or (roll > 65.0)) {
me.getElement("FlightDirector").setVisible(0);
}
},
updateIAS: func (ias, ias_trend) {
if (ias >= 10) {
me.setTextElement("Speed110", sprintf("% 2u",num(math.floor(ias/10))));

View file

@ -1,4 +1,3 @@
# Copyright 2018 Stuart Buchanan
# This file is part of FlightGear.
#
@ -41,6 +40,11 @@ var PFDInstrumentsController =
_mag_var : 0,
_time_sec : 0,
_fd_pitch : 0,
_fd_roll : 0,
_fd_enabled : 0,
_ap_enabled : 0,
_fp_active : 0,
_fp_current_wp : 0,
_current_flightplan : nil,
@ -227,6 +231,7 @@ var PFDInstrumentsController =
var roll = data["ADCRollDeg"];
var slip = data["ADCSlipSkid"];
me.page.updateAI(pitch, roll, slip);
me.page.updateFD((me._fd_enabled or me._ap_enabled), pitch, roll, me._fd_pitch, me._fd_roll);
me.page.updateVSI(data["ADCVerticalSpeedFPM"]);
me.page.updateTAS(data["ADCTrueAirspeed"]);
@ -281,6 +286,12 @@ var PFDInstrumentsController =
if (data["FMSLegCourseError"] != nil) me._deflection_dots = data["FMSLegCourseError"] /2.0;
if (data["FMSLegCourseError"] != nil) me._leg_xtrk_nm = data["FMSLegCourseError"];
if (data["AutopilotFDEnabled"] != nil) me._fd_enabled = data["AutopilotFDEnabled"];
if (data["AutopilotEnabled"] != nil) me._ap_enabled = data["AutopilotEnabled"];
if (data["AutopilotTargetPitch"] != nil) me._fd_pitch = data["AutopilotTargetPitch"];
if (data["AutopilotTargetRoll"] != nil) me._fd_roll = data["AutopilotTargetRoll"];
var update_fp = 0;
if (data["FMSFlightPlanEdited"] != nil) {

View file

@ -75,6 +75,16 @@ var HEADER_MAPPING = {
"VSR" : { message : "FMSLegVerticalSpeedRequired", format : "%dfpm"}, # TODO
};
# Style element use for the AP Status indicator. This is normally green text
# on a black background, but is highlighted when disengaged as black text on a yellow
# background for 5 seconds.
var AP_STATUS_STYLE = {
CURSOR_BLINK_PERIOD : 0.5,
HIGHLIGHT_COLOR : "#ffff00",
HIGHLIGHT_TEXT_COLOR : "#000000",
NORMAL_TEXT_COLOR : "#00ff00",
};
var Surround =
{
new : func (mfd, myCanvas, device, svg, pfd=0)
@ -98,6 +108,9 @@ var Surround =
if (pfd) {
obj.addTextElements(["HeaderFrom", "HeaderTo", "LegDistance", "LegBRG"]);
obj.addTextElements(["HeaderAPLateralArmed", "HeaderAPLateralActive", "HeaderAPVerticalArmed", "HeaderAPVerticalActive", "HeaderAPVerticalReference"]);
obj._apStatus = PFD.TextElement.new(obj.pageName, svg, "HeaderAPStatus", "", AP_STATUS_STYLE);
obj._apStatusTimer = nil;
obj._dto = PFD.HighlightElement.new(obj.pageName, svg, "HeaderDTO", "DTO");
obj._leg = PFD.HighlightElement.new(obj.pageName, svg, "HeaderActiveLeg", "Leg");
} else {
@ -254,6 +267,35 @@ var Surround =
}
}
if (data["AutopilotHeadingMode"] != nil) me.setTextElement("HeaderAPLateralActive", data["AutopilotHeadingMode"]);
if (data["AutopilotHeadingModeArmed"] != nil) me.setTextElement("HeaderAPLateralArmed", data["AutopilotHeadingModeArmed"]);
if (data["AutopilotAltitudeMode"] != nil) me.setTextElement("HeaderAPVerticalActive", data["AutopilotAltitudeMode"]);
if (data["AutopilotAltitudeModeArmed"] != nil) me.setTextElement("HeaderAPVerticalArmed", data["AutopilotAltitudeModeArmed"]);
if (data["AutopilotEnabled"] != nil) {
if (data["AutopilotEnabled"] == 1) {
me._apStatus.setValue("AP");
if (me._apStatusTimer != nil) {
# We were previously flashing, so stop.
me._apStatusTimer.stop();
me._apStatusTimer = nil;
me._apStatus.unhighlightElement();
}
} else {
if ((me._apStatus.getValue() != "") and (me._apStatus.isHighlighted() == 0)) {
# We were previously enabled, so we want to make the AP Status element
# flash for 5 seconds before removing it. The highlightElement()
# starts it flashing, and we use a timer to stop it.
me._apStatus.highlightElement();
if (me._apStatusTimer == nil) me._apStatusTimer =
maketimer(5.0, me, func() { me._apStatus.unhighlightElement(); me._apStatus.setValue(""); } );
me._apStatusTimer.singleShot = 1;
me._apStatusTimer.restart(5.0);
}
}
}
if (data["AutopilotTargetVertical"] != nil) me.setTextElement("HeaderAPVerticalReference", data["AutopilotTargetVertical"]);
if (data["FMSLegDesiredTrack"]) me.setTextElement("LegBRG", sprintf("%i°", data["FMSLegDesiredTrack"]));
if (data["FMSLegDistanceNM"]) me.setTextElement("LegDistance", sprintf("%.1fnm", data["FMSLegDistanceNM"]));
} else {

View file

@ -254,7 +254,7 @@ var NavMap = {
{
var incr_or_decr = (val > 0) ? 1 : -1;
me.setZoom(me._current_zoom + incr_or_decr);
return emesary.Transmitter.ReceiptStatus_Finished;
return emesary.Transmitter.ReceiptStatus_OK;
},
getMap : func() {

View file

@ -63,6 +63,7 @@ var TextElement =
},
isEditable : func () { return 0; },
isInEdit : func() { return 0; },
isHighlighted : func() { return me._highlightEnabled; },
enterElement : func() { return me.getValue(); },
clearElement : func() { },
editElement : func() { },