... | ... |
@@ -152,6 +152,7 @@ var displayClass = { |
152 | 152 |
'PFD-Map', |
153 | 153 |
'PFD-Multilines', |
154 | 154 |
'WindData', 'WindData-OPTN1', 'WindData-OPTN2', 'WindData-OPTN1-HDG', 'WindData-OPTN2-symbol', 'WindData-OPTN2-headwind', 'WindData-OPTN2-crosswind', 'WindData-NODATA', |
155 |
+ 'AOA', 'AOA-needle', |
|
155 | 156 |
); |
156 | 157 |
append(groups.clip, |
157 | 158 |
'SpeedLint1', |
... | ... |
@@ -186,6 +187,8 @@ var displayClass = { |
186 | 187 |
'AltSmallD' ~ place |
187 | 188 |
); |
188 | 189 |
} |
190 |
+ me.device.data.aoa = 0; |
|
191 |
+ me.device.data['aoa-auto'] = 0; |
|
189 | 192 |
} |
190 | 193 |
else { |
191 | 194 |
if (contains(me.parents[0], 'showEIS')) |
... | ... |
@@ -1146,6 +1149,28 @@ var displayClass = { |
1146 | 1149 |
_winddata_optn : 0, |
1147 | 1150 |
#}}} |
1148 | 1151 |
|
1152 |
+ updateAOA : func { |
|
1153 |
+# update Angle Of Attack {{{ |
|
1154 |
+ if (me.device.data.aoa == 0) |
|
1155 |
+ return; |
|
1156 |
+ var color = [1,1,1]; |
|
1157 |
+ var norm = data.aoa / data['stall-aoa']; |
|
1158 |
+ if (norm > 1) norm = 1; |
|
1159 |
+ if (norm > 0.9) |
|
1160 |
+ color = [1,0,0]; |
|
1161 |
+ elsif (norm > 0.7) |
|
1162 |
+ color = [1,1,0]; |
|
1163 |
+ elsif (norm < 0) { |
|
1164 |
+ norm = 0; |
|
1165 |
+ color = [1,0,0]; |
|
1166 |
+ } |
|
1167 |
+ me.screenElements['AOA-needle'] |
|
1168 |
+ .setRotation(-norm * math.pi) |
|
1169 |
+ .setColor(color); |
|
1170 |
+ settimer(func me.updateAOA(), 0.1); |
|
1171 |
+ }, |
|
1172 |
+# }}} |
|
1173 |
+ |
|
1149 | 1174 |
updateBRG : func { |
1150 | 1175 |
# displays and update BRG1/2 {{{ |
1151 | 1176 |
foreach (var brg; [1, 2]) { |
... | ... |
@@ -1306,4 +1331,6 @@ var keyMap = { |
1306 | 1331 |
}, |
1307 | 1332 |
}, |
1308 | 1333 |
}; |
1334 |
+if (data['stall-aoa'] == 9999) |
|
1335 |
+ keyMap.PFD.PFD['AOA/WIND'].texts = ['', 'WIND']; |
|
1309 | 1336 |
#}}} |
... | ... |
@@ -63,6 +63,50 @@ var softkeysClass = { |
63 | 63 |
}, |
64 | 64 |
PFD: { |
65 | 65 |
'AOA/WIND' : { |
66 |
+ AOA : { |
|
67 |
+ 'AOA ON' : func { |
|
68 |
+ if (me.device.data['aoa-auto']) |
|
69 |
+ return; |
|
70 |
+ me.device.data.aoa = ! me.device.data.aoa; |
|
71 |
+ me.device.display.screenElements['AOA'] |
|
72 |
+ .setVisible(me.device.data.aoa); |
|
73 |
+ me.device.display.screenElements['AOA-needle'] |
|
74 |
+ .setVisible(me.device.data.aoa); |
|
75 |
+ me.device.display.updateAOA(); |
|
76 |
+ me.device.display.setSoftKeyColor(5 ,me.device.data.aoa); |
|
77 |
+ if (me.device.data.aoa) |
|
78 |
+ me.colored['PFDAOA/WINDAOAAOA ON'] = 1; |
|
79 |
+ else |
|
80 |
+ delete(me.colored, 'PFDAOA/WINDAOAAOA ON'); |
|
81 |
+ }, |
|
82 |
+ 'AOA AUTO' : func { |
|
83 |
+ if (me.device.data.aoa) |
|
84 |
+ return; |
|
85 |
+ me.device.data['aoa-auto'] = ! me.device.data['aoa-auto']; |
|
86 |
+ me.device.display.setSoftKeyColor(6 ,me.device.data['aoa-auto']); |
|
87 |
+ if (me.device.data['aoa-auto']) { |
|
88 |
+ me.colored['PFDAOA/WINDAOAAOA AUTO'] = 1; |
|
89 |
+ if (!contains(me.device.timers, 'aoa')) |
|
90 |
+ me.device.timers.aoa = maketimer(1, |
|
91 |
+ func { |
|
92 |
+ var v = getprop('/gear/gear/position-norm') == 1 |
|
93 |
+ and getprop('/surfaces-positions/flap-pos-norm') != 0; |
|
94 |
+ me.device.display.screenElements['AOA'] |
|
95 |
+ .setVisible(v); |
|
96 |
+ me.device.display.screenElements['AOA-needle'] |
|
97 |
+ .setVisible(v); |
|
98 |
+ }, me); |
|
99 |
+ me.device.timers.aoa.start(); |
|
100 |
+ } |
|
101 |
+ else { |
|
102 |
+ delete(me.colored, 'PFDAOA/WINDAOAAOA AUTO'); |
|
103 |
+ me.device.timers.aoa.stop(); |
|
104 |
+ me.device.data.aoa = 0; |
|
105 |
+ me.device.display.screenElements['AOA'] |
|
106 |
+ .hide(); |
|
107 |
+ } |
|
108 |
+ }, |
|
109 |
+ }, |
|
66 | 110 |
WIND : { |
67 | 111 |
OPTN1 : func { |
68 | 112 |
me.device.display._winddata_optn = 1; |
... | ... |
@@ -75,6 +75,7 @@ Please report bug at <seb.marque@free.fr>. |
75 | 75 |
* EIS: separation for aircraft specifics (selected by the zkv1000 config) |
76 | 76 |
* ![][90%] |
77 | 77 |
* TMR/REF Timer ![][done], Vspeeds ![][done], minimums ![][pending] (don't understand the role of this) |
78 |
+ * angle of attack display (not sure about calculation): specific for each airplane (see Installation instructions below) |
|
78 | 79 |
* Bearing needs some checks to be sure it shows the correct information |
79 | 80 |
* XPDR: emergency code depending of the country (eg.: 1200 for US, 7700 for Europe), should be set in settings |
80 | 81 |
* ![][80%] |
... | ... |
@@ -95,7 +96,6 @@ Please report bug at <seb.marque@free.fr>. |
95 | 96 |
* ![][0%] (TODO list, unsorted) |
96 | 97 |
* CDI/GPS: scale depending of the flight phase |
97 | 98 |
* recenter the MFD depending of EIS width |
98 |
- * angle of attack display |
|
99 | 99 |
* Alerts |
100 | 100 |
* Flight planning (MFD) |
101 | 101 |
* Inset Map (PFD) |
... | ... |
@@ -106,6 +106,8 @@ Please report bug at <seb.marque@free.fr>. |
106 | 106 |
* VNAV |
107 | 107 |
* scrolling lift in menus |
108 | 108 |
* tutorials |
109 |
+ * make any Vspeed available (not only Vx, Vy, Vr and Vglide), depending of their presence in aircraft config |
|
110 |
+ * [touchable screen](http://wiki.flightgear.org/Canvas_Event_Handling) |
|
109 | 111 |
* many more... |
110 | 112 |
|
111 | 113 |
# Installation |
... | ... |
@@ -144,6 +146,15 @@ To tells the zkv1000 which kind of engines equip your aircraft, and the associat |
144 | 146 |
Defaults to `none`, available entries are the `.nas` files located in `Nasal/EIS/` directory. |
145 | 147 |
If you want to add yours, just copy the `Systems/EIS/single-engine.svg`, modify it to fit your needs, and refer to it in a function named `displayClass.showEIS`, another very important function is `displayClass.updateEIS` (example in [zkv1000/Nasal/EIS/single-engine.nas](Nasal/EIS/single-engine.nas)) |
146 | 148 |
|
149 |
+### Angle Of Attack (AOA) |
|
150 |
+You can specify the stall AoA in order to display it in the dedicated display. |
|
151 |
+ |
|
152 |
+ <alerts> |
|
153 |
+ <stall-aoa>15</stall-aoa> |
|
154 |
+ </alerts> |
|
155 |
+ |
|
156 |
+If not specified or equals to 0 (zero) the AOA display won't be accessible. |
|
157 |
+ |
|
147 | 158 |
## 3D models |
148 | 159 |
In the definition of your flightdeck (here are the values for the installation in the Lancair 235 in which I develop the device) |
149 | 160 |
put it everywhere you want to |
... | ... |
@@ -7106,6 +7106,43 @@ |
7106 | 7106 |
id="Annunciation-bg" |
7107 | 7107 |
style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:#ffffff;stroke-width:1.01803744;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> |
7108 | 7108 |
</g> |
7109 |
+ <g |
|
7110 |
+ id="AOA" |
|
7111 |
+ inkscape:label="AOA"> |
|
7112 |
+ <rect |
|
7113 |
+ style="opacity:1;fill:#020000;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" |
|
7114 |
+ id="AOA-bg" |
|
7115 |
+ width="75.831932" |
|
7116 |
+ height="71.529388" |
|
7117 |
+ x="158.11763" |
|
7118 |
+ y="325.3782" |
|
7119 |
+ inkscape:label="AOA-bg" /> |
|
7120 |
+ <text |
|
7121 |
+ inkscape:label="AOA-text" |
|
7122 |
+ id="AOA-text" |
|
7123 |
+ y="345.68497" |
|
7124 |
+ x="159.34264" |
|
7125 |
+ style="font-style:normal;font-weight:normal;font-size:16px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" |
|
7126 |
+ xml:space="preserve"><tspan |
|
7127 |
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';fill:#ffffff;fill-opacity:1" |
|
7128 |
+ y="345.68497" |
|
7129 |
+ x="159.34264" |
|
7130 |
+ id="tspan5885" |
|
7131 |
+ sodipodi:role="line">AOA</tspan></text> |
|
7132 |
+ <path |
|
7133 |
+ inkscape:label="AOA-needle" |
|
7134 |
+ inkscape:transform-center-y="17.435497" |
|
7135 |
+ inkscape:transform-center-x="-0.303765" |
|
7136 |
+ inkscape:connector-curvature="0" |
|
7137 |
+ id="AOA-needle" |
|
7138 |
+ d="m 191.3807,360.58563 0.63375,34.70574 v 0 0" |
|
7139 |
+ style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:2.97909927;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> |
|
7140 |
+ <path |
|
7141 |
+ 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;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;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;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;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;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;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" |
|
7142 |
+ d="m 192.45312,325.95312 v 1 c 12.21842,0 23.48918,6.57015 29.51172,17.20118 6.02255,10.63103 5.86335,23.67799 -0.41796,34.1582 -6.28132,10.48021 -17.71104,16.77019 -29.92579,16.4707 l -0.0254,1 c 12.57316,0.30828 24.34297,-6.1693 30.8086,-16.95703 6.46562,-10.78773 6.6309,-24.22109 0.43164,-35.16406 -6.19926,-10.94297 -17.80588,-17.70899 -30.38282,-17.70899 z" |
|
7143 |
+ id="AOA-circle" |
|
7144 |
+ inkscape:connector-curvature="0" /> |
|
7145 |
+ </g> |
|
7109 | 7146 |
<g |
7110 | 7147 |
id="Reversionnary" |
7111 | 7148 |
inkscape:label="Reversionnary"> |
... | ... |
@@ -30,6 +30,7 @@ var data = { # set of data common to all devices |
30 | 30 |
wow : 1, |
31 | 31 |
lat : 0, |
32 | 32 |
lon : 0, |
33 |
+ aoa : 0, |
|
33 | 34 |
timers : { |
34 | 35 |
'20Hz': maketimer ( |
35 | 36 |
0.05, |
... | ... |
@@ -40,6 +41,7 @@ var data = { # set of data common to all devices |
40 | 41 |
data.ias = getprop('/velocities/airspeed-kt'); |
41 | 42 |
data.alt = getprop('/instrumentation/altimeter/indicated-altitude-ft'); |
42 | 43 |
data.hdg = getprop('/orientation/heading-deg'); |
44 |
+ data.aoa = getprop('/orientation/alpha-deg'); |
|
43 | 45 |
} |
44 | 46 |
), |
45 | 47 |
'1Hz': maketimer ( |
... | ... |
@@ -100,6 +102,8 @@ var init_props = func { |
100 | 102 |
var speed = getprop('/instrumentation/zkv1000/alerts/' ~ v); |
101 | 103 |
data[v] = speed != nil ? speed : 9999; |
102 | 104 |
} |
105 |
+ var aoa = getprop('/instrumentation/zkv1000/alerts/stall-aoa'); |
|
106 |
+ data['stall-aoa'] = (aoa == nil or aoa == 0) ? 9999 : aoa; |
|
103 | 107 |
|
104 | 108 |
afcs = zkv.getNode('afcs',1); |
105 | 109 |
afcs.getNode('fd-bars-visible',1).setBoolValue(0); |
... | ... |
@@ -184,8 +188,8 @@ var load_multikey = func { |
184 | 188 |
var zkv1000_init = func { |
185 | 189 |
removelistener(init); |
186 | 190 |
load_multikey(); |
187 |
- load_nasal(); |
|
188 | 191 |
init_props(); |
192 |
+ load_nasal(); |
|
189 | 193 |
print('zkv1000 loaded'); |
190 | 194 |
} |
191 | 195 |
|