commit initial
|
1 |
var pitModes = { |
2 |
'PIT': 'pitch-hold', |
|
3 |
'ALT': 'altitude-hold', |
|
4 |
'VS': 'vertical-speed-hold', |
|
5 |
'FLC': 'flight-level-change', |
|
6 |
'GS': 'gs1-hold', |
|
7 |
'GP': '', |
|
8 |
'VPTH': 'vertical-path', |
|
9 |
'GA': 'go-around' |
|
10 |
}; |
|
11 |
var pitMode = ''; |
|
12 | ||
13 |
var rollModes = { |
|
14 |
'ROL': 'wing-leveler', |
|
15 |
'HDG': 'dg-heading-hold', |
|
16 |
'GA': 'go-around', |
|
17 |
'GPS': '', |
|
18 |
'VOR': 'nav1-hold', |
|
19 |
'LOC': '', |
|
20 |
'VAPP': '', |
|
21 |
}; |
|
22 |
var rollMode = ''; |
|
23 | ||
24 |
var AFCS = { |
|
25 |
nose_inc : 0, |
|
26 |
nose_node : '', |
|
27 |
nose_max : 0, |
|
28 |
nose_min : 0, |
|
29 |
AP : func { |
|
30 |
getprop('/instrumentation/zkv1000/status') or return; |
|
31 |
if (getPitchMode() == '') setPitchMode('PIT'); |
|
32 |
setprop('/autopilot/locks/passive-mode', getprop('/autopilot/locks/passive-mode')? 0 : 1); |
|
33 |
}, |
|
34 |
FD : func { |
|
35 |
getprop('/instrumentation/zkv1000/status') or return; |
|
36 |
setPitchMode(getPitchMode() == '' ? 'PIT' : ''); |
|
37 |
}, |
|
38 |
ROL : func { |
|
39 |
setRollMode('ROL'); |
|
40 |
settings.getNode('heading-bug-deg').unalias(); |
|
41 |
afcs.getNode('roll-armed').setBoolValue(0); |
|
42 |
setprop('/autopilot/internal/target-roll-deg', 0); |
|
43 |
}, |
|
44 |
HDG : func { |
|
45 |
settings.getNode('heading-bug-deg').alias(afcs.getNode('heading-bug-deg')); |
|
46 |
}, |
|
47 |
NAV : func { |
|
48 |
settings.getNode('heading-bug-deg').unalias(); |
|
49 |
afcs.getNode('roll-armed').setBoolValue(0); |
|
50 |
checkRollAcquisition = checkNavAcquisition; |
|
51 |
}, |
|
52 |
PIT : func { |
|
53 |
AFCS.nose_inc = 0.5; |
|
54 |
AFCS.nose_node = '/autopilot/internal/target-pitch-deg'; |
|
55 |
AFCS.nose_min = -15; |
|
56 |
AFCS.nose_max = 20; |
|
57 |
setprop(AFCS.nose_node, round(pitch)); |
|
58 |
}, |
|
59 |
VS : func { |
|
60 |
AFCS.nose_node = '/autopilot/settings/vertical-speed-fpm'; |
|
61 |
AFCS.nose_inc = 100; |
|
62 |
AFCS.nose_min = -3000; |
|
63 |
AFCS.nose_max = 1500; |
|
64 |
setprop(AFCS.nose_node, round(vs, AFCS.nose_inc)); |
|
65 |
setprop('/autopilot/settings/target-altitude-ft', getprop(afcs.getNode('selected-alt-ft').getPath())); |
|
66 |
checkPitchAcquisition = checkSelectedAltAcquisition; |
|
67 |
}, |
|
68 |
ALT : func { |
|
69 |
setprop('/autopilot/settings/target-altitude-ft', getprop(afcs.getNode('selected-alt-ft').getPath())); |
|
70 |
checkPitchAcquisition = checkSelectedAltAcquisition; |
|
71 |
}, |
|
72 |
FLC : func { |
|
73 |
AFCS.nose_node = '/autopilot/settings/target-speed-kt'; |
|
74 |
AFCS.nose_inc = 1; |
|
75 |
AFCS.nose_min = 70; |
|
76 |
AFCS.nose_max = 165; |
|
77 |
computeAirspeedDiff = _computeAirspeedDiff; |
|
78 |
checkPitchAcquisition = checkSelectedAltAcquisition; |
|
79 |
setprop(AFCS.nose_node, round(ias, AFCS.nose_inc)); |
|
80 |
setprop('/autopilot/settings/target-altitude-ft', getprop(afcs.getNode('selected-alt-ft').getPath())); |
|
81 |
FLCcomputation = _FLCcomputation; |
|
82 |
}, |
|
83 |
NOSEUP : func { |
|
84 |
AFCS.nose_inc or return; |
|
85 |
var s = getprop(AFCS.nose_node) + AFCS.nose_inc; |
|
86 |
s <= AFCS.nose_max or return; |
|
87 |
setprop(AFCS.nose_node, getprop(AFCS.nose_node) + AFCS.nose_inc); |
|
88 |
}, |
|
89 |
NOSEDOWN : func { |
|
90 |
AFCS.nose_inc or return; |
|
91 |
var s = getprop(AFCS.nose_node) - AFCS.nose_inc; |
|
92 |
s >= AFCS.nose_min or return; |
|
93 |
setprop(AFCS.nose_node, getprop(AFCS.nose_node) - AFCS.nose_inc); |
|
94 |
}, |
|
95 |
VNV : func { |
|
96 |
nyi('VNV'); |
|
97 |
}, |
|
98 |
APR : func { |
|
99 |
nyi('APR'); |
|
100 |
}, |
|
101 |
APDISC : void, |
|
102 |
CWS : void, |
|
103 |
GA : void |
|
104 |
}; |
|
105 | ||
106 |
var checkNavAcquisition = func { |
|
107 |
var r = getprop('/instrumentation/zkv1000/cdi/radial'); |
|
108 |
var h = getprop('/orientation/heading-deg'); |
|
109 |
var d = getprop('/instrumentation/zkv1000/cdi/course-deflection'); |
|
110 |
if (d < 0.5) { |
|
111 |
rollBlinking.switch(0); |
|
112 |
setprop('/instrumentation/zkv1000/afcs/roll-armed-mode', 0); |
|
113 |
} |
|
114 |
elsif (d > 1) { |
|
115 |
rollBlinking.switch(0); |
|
116 |
setprop('/instrumentation/zkv1000/afcs/roll-armed-mode', pitMode); |
|
117 |
} |
|
118 |
else { |
|
119 |
getprop('/instrumentation/zkv1000/afcs/roll-armed') or rollBlinking.switch(1); |
|
120 |
setprop('/instrumentation/zkv1000/afcs/roll-armed-mode', rollMode); |
|
121 |
} |
|
122 |
} |
|
123 | ||
124 |
var checkSelectedAltAcquisition = func { |
|
125 |
var s = getprop('/autopilot/settings/target-altitude-ft'); |
|
126 |
var diff = abs(alt - s); |
|
127 |
var climb = (alt - s > 0); |
|
128 |
if (diff < 50) { |
|
129 |
pitchBlinking.switch(0); |
|
130 |
setPitchMode('ALT'); |
|
131 |
} |
|
132 |
elsif (diff > 400) { |
|
133 |
setprop('/instrumentation/zkv1000/vertical-speed-fpm', (climb and !getPitchMode('VS'))? 1000 : -500); |
|
134 |
if (!getPitchMode('FLC')) setPitchMode('VS', 0); |
|
135 |
pitchBlinking.switch(0); |
|
136 |
} |
|
137 |
else { |
|
138 |
setprop('/instrumentation/zkv1000/vertical-speed-fpm', climb? 100 : -100); |
|
139 |
setPitchMode('VS'); |
|
140 |
getprop('/instrumentation/zkv1000/afcs/pitch-armed') or pitchBlinking.switch(1); |
|
141 |
} |
|
142 |
} |
|
143 | ||
144 |
# Note: use SetPitchMode('') to exit the Flight Director mode |
|
145 |
var setPitchMode = func (m, s=1) { |
|
146 |
checkPitchAcquisition = void; |
|
147 |
FLCcomputation = void; |
|
148 |
computeAirspeedDiff = void; |
|
149 |
AFCS.nose_inc = 0; |
|
150 |
if (pitMode == m and s) pitMode = 'PIT'; |
|
151 |
else pitMode = m; |
|
152 |
setprop('/autopilot/locks/pitch', pitMode != '' ? pitModes[pitMode] : pitMode); |
|
153 |
setprop('/instrumentation/zkv1000/afcs/pit-active-mode', pitMode); |
|
154 |
setprop('/instrumentation/zkv1000/afcs/pit-armed-mode', pitMode); |
|
155 |
setprop('/instrumentation/zkv1000/afcs/pit-armed-mode-text', pitMode); |
|
156 |
setprop('/instrumentation/zkv1000/afcs/pit-active-mode-text', pitMode); |
|
157 |
setprop('/instrumentation/zkv1000/afcs/pit-active-mode-blink', 0); |
|
158 |
if (pitMode != '') { |
|
159 |
computeAltitudeDiff = _computeAltitudeDiff; |
|
160 |
setprop('/instrumentation/zkv1000/afcs/alt-bug-visible', 1); |
|
161 |
if (getRollMode() == '') setRollMode('ROL'); |
|
162 |
} |
|
163 |
else { |
|
164 |
setprop('/instrumentation/zkv1000/afcs/alt-bug-visible', 0); |
|
165 |
rollBlinking.switch(0); |
|
166 |
computeAltitudeDiff = void; |
|
167 |
computeAirspeedDiff = void; |
|
168 |
setRollMode('', 0); |
|
169 |
} |
|
170 |
init_main_loop(); |
|
171 |
} |
|
172 | ||
173 |
var setRollMode = func (m, s=1) { |
|
174 |
checkRollAcquisition = void; |
|
175 |
if (rollMode == m and s) rollMode = 'ROL'; |
|
176 |
else rollMode = m; |
|
177 |
setprop('/autopilot/locks/roll', (rollMode != '')? rollModes[rollMode] : rollMode); |
|
178 |
setprop('/instrumentation/zkv1000/afcs/roll-active-mode', rollMode); |
|
179 |
setprop('/instrumentation/zkv1000/afcs/roll-armed-mode', rollMode); |
|
180 |
setprop('/instrumentation/zkv1000/afcs/roll-armed-mode-text', rollMode); |
|
181 |
setprop('/instrumentation/zkv1000/afcs/roll-active-mode-text', rollMode); |
|
182 |
setprop('/instrumentation/zkv1000/afcs/roll-active-mode-blink', 0); |
|
183 |
if (rollMode != '') { |
|
184 |
setprop('/instrumentation/zkv1000/afcs/fd-bars-visible', 1); |
|
185 |
if (getPitchMode() == '') setPitchMode('PIT'); |
|
186 |
} |
|
187 |
else { |
|
188 |
setprop('/instrumentation/zkv1000/afcs/fd-bars-visible', 0); |
|
189 |
settings.getNode('heading-bug-deg').unalias(); |
|
190 |
rollBlinking.switch(0); |
|
191 |
} |
|
192 |
init_main_loop(); |
|
193 |
} |
|
194 | ||
195 |
var getPitchMode = func (mode = nil) { |
|
196 |
var m = getprop('/autopilot/locks/pitch'); |
|
197 |
if (mode) |
|
198 |
return (m == mode); |
|
199 |
else |
|
200 |
return m; |
|
201 |
} |
|
202 | ||
203 |
var getRollMode = func (mode = nil) { |
|
204 |
var m = getprop('/autopilot/locks/roll'); |
|
205 |
if (mode) |
|
206 |
return (m == mode); |
|
207 |
else |
|
208 |
return m; |
|
209 |
} |
|
210 | ||
211 | ||
212 |
var _FLCcomputation = func { |
|
213 |
var t1 = getprop('/autopilot/internal/flc-airspeed-pitch-deg'); |
|
214 |
var t2 = getprop('/autopilot/internal/flc-altitude-pitch-deg'); |
|
215 |
setprop('/autopilot/internal/target-pitch-deg', (t1 + t2) / 2); |
|
216 |
} |
|
217 | ||
218 |
var _computeAltitudeDiff = func { |
|
219 |
var sel = getprop('/instrumentation/zkv1000/afcs/selected-alt-ft'); |
|
220 |
setprop('/instrumentation/zkv1000/afcs/selected-alt-ft-diff', sel - alt); |
|
221 |
} |
|
222 | ||
223 |
var _computeAirspeedDiff = func { |
|
224 |
var sel = getprop('/autopilot/settings/target-speed-kt'); |
|
225 |
setprop('/instrumentation/zkv1000/afcs/selected-ias-kt-diff', sel - ias); |
|
226 |
} |
|
227 | ||
228 |
var settings = props.globals.getNode('/autopilot/settings'); |
|
229 | ||
230 |
var pitchBlinking = nil; |
|
231 |
var rollBlinking = nil; |
|
232 | ||
233 |
var init_AFCS = func { |
|
234 |
pitchBlinking = aircraft.light.new(afcs.getNode('pit-active-mode-blink').getPath(), |
|
235 |
[0.5, 0.5], |
|
236 |
afcs.getNode('pitch-armed').getPath()); |
|
237 |
pitchBlinking.switch(0); |
|
238 | ||
239 |
rollBlinking = aircraft.light.new(afcs.getNode('roll-active-mode-blink').getPath(), |
|
240 |
[0.5, 0.5], |
|
241 |
afcs.getNode('roll-armed').getPath()); |
|
242 |
rollBlinking.switch(0); |
|
243 |
if (getprop('/sim/systems/autopilot/path') == 'Aircraft/Generic/generic-autopilot.xml') { |
|
244 |
setprop('/sim/systems/autopilot/path', 'Aircraft/Instruments-3d/zkv1000/Systems/autopilot.xml'); |
|
245 |
} |
|
246 |
} |
|
247 |