more radiostack updates
[fg:toms-fgdata.git] / Aircraft / Citation-Bravo / Nasal / flightdirector.nas
1 #############################################################################
2 # Flight Director/Autopilot controller.
3 # Syd Adams
4 #
5 # HDG:
6 # Heading Bug hold - Low Bank can be selected
7 # NAV:
8 # Arm & Capture VOR , LOC or FMS
9 # APR : (ILS approach)
10 # Arm & Capture VOR APR , LOC or BC
11 # Also arm and capture GS
12 # BC :
13 # Arm & capture localizer backcourse
14 # Nav also illuminates
15 # VNAV:
16 # Arm and capture VOR/DME or FMS vertical profile
17 # profile entered in MFD VNAV menu
18 # ALT:
19 # Hold current Altitude or PFD preset altitude
20 # VS:
21 # Hold current vertical speed
22 # adjustable with pitch wheel
23 # SPD :
24 # Hold current speed 
25 # adjustable with pitch wheel
26 #
27 #############################################################################
28 # lnav 
29 #0=W-LVL , 1=HDG , 2=NAV Arm ,3=NAV Cap , 4=LOC arm , 5=LOC Cap , 6=FMS
30 # vnav
31 # 0=PITCH,  1=VNAV, 2=ALT hold , 3=VS , 4=GS arm ,5 = GS cap
32 #FlightDirector/Autopilot 
33 # ie: var fltdir = flightdirector.new(property);
34
35 var flightdirector = {
36     new : func(fdprop){
37         m = {parents : [flightdirector]};
38         m.lnav_text=["wing-leveler","dg-heading-hold","dg-heading-hold","nav1-hold","dg-heading-hold","nav1-hold","true-heading-hold"];
39         m.vnav_text=["pitch-hold","altitude-hold","altitude-hold","vertical-speed-hold","vertical-speed-hold","gs1-hold"];
40         m.spd_text=["","speed-with-throttle","speed-with-pitch"];
41         m.LAT=["ROL","HDG","HDG","VOR","HDG","LOC","LNAV"];
42     m.subLAT=["   ","   ","VOR","   ","LOC","   ","   "];
43         m.VRT=["PIT","VNAV","ALT","VS","   ","GS"];
44     m.subVRT=["   ","GS"];
45     m.node = props.globals.getNode(fdprop,1);
46         m.yawdamper = props.globals.getNode("autopilot/locks/yaw-damper",1);
47         m.yawdamper.setBoolValue(0);
48         m.lnav = m.node.getNode("lnav",1);
49         m.lnav.setIntValue(0);
50         m.vnav = m.node.getNode("vnav",1);
51         m.vnav.setIntValue(0);
52         m.gs_arm = m.node.getNode("gs-arm",1);
53         m.gs_arm.setBoolValue(0);
54         m.asel = m.node.getNode("Asel",1);
55         m.asel.setDoubleValue(0);
56         m.speed = m.node.getNode("spd",1);
57         m.DH = props.globals.getNode("autopilot/route-manager/min-lock-altitude-agl-ft",1);
58         m.Defl = props.globals.getNode("instrumentation/nav/heading-needle-deflection");
59         m.GSDefl = props.globals.getNode("instrumentation/nav/gs-needle-deflection");
60         m.NavLoc = props.globals.getNode("instrumentation/nav/nav-loc");
61         m.hasGS = props.globals.getNode("instrumentation/nav/has-gs");
62     m.Valid = props.globals.getNode("instrumentation/nav/in-range");
63         m.FMS = props.globals.getNode("instrumentation/primus1000/dc550/fms",1);
64
65         m.AP_hdg = props.globals.getNode("/autopilot/locks/heading",1);
66         m.AP_hdg.setValue(m.lnav_text[0]);
67         m.AP_hdg_setting = props.globals.getNode("/autopilot/settings/heading",1);
68         m.AP_alt = props.globals.getNode("/autopilot/locks/altitude",1);
69         m.AP_alt.setValue(m.vnav_text[0]);
70         m.AP_spd = props.globals.getNode("/autopilot/locks/speed",1);
71         m.AP_spd.setValue(m.spd_text[0]);
72         m.AP_off = props.globals.getNode("/autopilot/locks/passive-mode",1);
73         m.AP_off.setBoolValue(1);
74     
75     m.AP_lat_annun = m.node.getNode("LAT-annun",1);
76         m.AP_lat_annun.setValue(" ");
77     m.AP_sublat_annun = m.node.getNode("LAT-arm-annun",1);
78         m.AP_sublat_annun.setValue(" ");
79     m.AP_vert_annun = m.node.getNode("VRT-annun",1);
80         m.AP_vert_annun.setValue(" ");
81     m.AP_subvert_annun = m.node.getNode("VRT-arm-annun",1);
82         m.AP_subvert_annun.setValue(" ");
83
84         m.pitch_active=props.globals.getNode("/autopilot/locks/pitch-active",1);
85         m.pitch_active.setBoolValue(1);
86         m.roll_active=props.globals.getNode("/autopilot/locks/roll-active",1);
87         m.roll_active.setBoolValue(1);
88         m.bank_limit=m.node.getNode("bank-limit-switch",1);
89         m.bank_limit.setBoolValue(0);
90
91         m.max_pitch=m.node.getNode("pitch-max",1);
92         m.max_pitch.setDoubleValue(10);
93         m.min_pitch=m.node.getNode("pitch-min",1);
94         m.min_pitch.setDoubleValue(-10);
95         m.max_roll=m.node.getNode("roll-max",1);
96         m.max_roll.setDoubleValue(27);
97         m.min_roll=m.node.getNode("roll-min",1);
98         m.min_roll.setDoubleValue(-27);
99     return m;
100     },
101     ############################
102     set_lateral_mode : func(lnv){
103     var tst =me.lnav.getValue();
104     if(lnv ==tst)lnv=0;
105         if(lnv==4){
106             if(!me.NavLoc.getBoolValue()){
107                 lnv=2;
108             }else{
109                 if(me.hasGS.getBoolValue())me.gs_arm.setBoolValue(1);
110             }
111         }
112         if(lnv==2){
113             if(me.FMS.getBoolValue())lnv = 6;
114             }
115         me.lnav.setValue(lnv);
116         me.AP_hdg.setValue(me.lnav_text[lnv]);
117     },
118 ###########################
119     set_vertical_mode : func(vnv){
120     var tst =me.vnav.getValue();
121     if(vnv ==tst)vnv=0;
122         if(vnv==1){
123             if(!me.FMS.getBoolValue()){
124                 vnv = 0;
125             }else{
126                 var tmpalt =getprop("autopilot/route-manager/route/wp/altitude-ft");
127                 if(tmpalt < 0)tmpalt=30000;
128                 setprop("autopilot/settings/target-altitude-ft",tmpalt);
129             }
130         }
131         if(vnv==2){
132         var asel=getprop("instrumentation/altimeter/indicated-altitude-ft");
133         asel = int(asel * 0.01) * 100;
134         setprop("autopilot/settings/target-altitude-ft",asel);
135         }
136         me.vnav.setValue(vnv);
137         me.AP_alt.setValue(me.vnav_text[vnv]);
138     },
139 #### button press handler####
140     set_mode : func(mode){
141         if(mode=="hdg"){
142             me.set_lateral_mode(1);
143         }elsif(mode=="nav"){
144             me.set_lateral_mode(2);
145         }elsif(mode=="apr"){
146             me.set_lateral_mode(4);
147         }elsif(mode=="bc"){
148             var tst=me.lnav.getValue();
149             var bcb = getprop("instrumentation/nav/back-course-btn");
150             bcb = 1-bcb;
151             if(tst <2 and tst >5)bcb = 0;
152             setprop("instrumentation/nav/back-course-btn",bcb);
153         }elsif(mode=="vnav"){
154             me.set_vertical_mode(1);
155         }elsif(mode=="alt"){
156             me.set_vertical_mode(2);
157         }elsif(mode=="vs"){
158             me.set_vertical_mode(3);
159         }
160     },
161 #### check AP errors####
162     check_AP_limits : func(){
163         var apmode = me.AP_off.getBoolValue();
164         var agl=getprop("/position/altitude-agl-ft");
165         if(!apmode){
166             var maxroll = getprop("/orientation/roll-deg");
167             var maxpitch = getprop("/orientation/pitch-deg");
168             if(maxroll > 65 or maxroll < -65){
169                 apmode = 1;
170             }
171             if(maxpitch > 30 or maxpitch < -20){
172                 apmode = 1;
173                 setprop("controls/flight/elevator-trim",0);
174             }
175             if(agl < 180)apmode = 1;
176             me.AP_off.setBoolValue(apmode);
177         }
178         if(agl < 50)me.yawdamper.setBoolValue(0);
179         return apmode;
180     },
181 #### update lnav####
182     update_lnav : func(){
183         var lnv = me.lnav.getValue();
184         if(lnv   >1 and lnv<6){
185         if(me.FMS.getBoolValue())lnv=6;
186     }
187     if(lnv==2){
188         var defl = me.Defl.getValue();
189         if(me.Valid.getBoolValue()){
190             if(defl <= 9 and defl >= -9)lnv=3;
191         }
192     }elsif(lnv==4){
193         var defl = me.Defl.getValue();
194         if(me.Valid.getBoolValue()){
195             if(defl <= 9 and defl >= -9)lnv=5;
196         }
197     }
198     me.lnav.setValue(lnv);
199         me.AP_hdg.setValue(me.lnav_text[lnv]);
200     me.AP_lat_annun.setValue(me.LAT[lnv]);
201     me.AP_sublat_annun.setValue(me.subLAT[lnv]);
202     },
203 #### update vnav####
204     update_vnav : func(){
205         var vnv = me.vnav.getValue();
206         if(me.gs_arm.getBoolValue()){
207             var defl = me.GSDefl.getValue();
208             if(defl < 1 and defl > -1){
209         vnv=5;
210         me.gs_arm.setBoolValue(0);
211         }
212         }
213     me.vnav.setValue(vnv);
214         me.AP_alt.setValue(me.vnav_text[vnv]);
215     me.AP_vert_annun.setValue(me.VRT[vnv]);
216     me.AP_subvert_annun.setValue(me.subVRT[me.gs_arm.getValue()]);
217     },
218 #### autopilot engage####
219     toggle_autopilot : func(apmd){
220         var md1=0;
221         if(apmd=="ap"){
222             md1 = me.AP_off.getBoolValue();
223             md1=1-md1;
224             if(getprop("/position/altitude-agl-ft") < 180)md1=1;
225             me.AP_off.setBoolValue(md1);
226             if(md1==0)me.yawdamper.setBoolValue(1);
227         }elsif(apmd=="yd"){
228             md1 = me.yawdamper.getBoolValue();
229             md1=1-md1;
230             me.yawdamper.setBoolValue(md1);
231             if(md1==0)me.AP_off.setBoolValue(1);
232         }elsif(apmd=="bank"){
233             md1 = me.bank_limit.getBoolValue();
234             md1=1-md1;
235             me.bank_limit.setBoolValue(md1);
236             if(md1==1){
237                 me.max_roll.setValue(14);
238                 me.min_roll.setValue(-14);
239             }else{
240                 me.max_roll.setValue(27);
241                 me.min_roll.setValue(-27);
242             }
243         }
244     },
245 #### pitch wheel####
246     pitch_wheel : func(amt){
247         var factor=amt;
248         var vmd = me.vnav.getValue();
249         if(vmd==0){
250         
251         }elsif(vmd==3){
252         }
253     }
254 };
255
256 var FlDr=flightdirector.new("instrumentation/flightdirector");
257
258 ######################################
259
260 setlistener("/sim/signals/fdm-initialized", func {
261     setprop("autopilot/settings/target-altitude-ft",0);
262     settimer(update_fd, 5);
263     print("Flight Director ...Check");
264 });
265
266 var update_fd = func {
267 var APoff = FlDr.check_AP_limits();
268 FlDr.update_lnav();
269 FlDr.update_vnav();
270 settimer(update_fd, 0); 
271 }