zkv1000 / Nasal / afcs.nas /
Newer Older
247 lines | 8.872kb
commit initial
Sébastien MARQUE authored on 2017-03-07
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