diff --git a/A350-common.xml b/A350-common.xml index bfa9264..b85ec39 100644 --- a/A350-common.xml +++ b/A350-common.xml @@ -278,9 +278,8 @@ - nasal - + dialog-show + autopilot @@ -425,6 +424,7 @@ + @@ -459,13 +459,14 @@ 30 0.95 0.02 + 0 0 1 - 0.7 + 0.645 50 1500 1 - 50 + 20 160 @@ -539,24 +540,6 @@ - - - - - - kts - 6.0 - -4.0 - 35 - - - - 0.00 - 6.0 - -4.0 - - - diff --git a/Nasal/it-autoflight.nas b/Nasal/it-autoflight.nas index 2efd271..f15a727 100644 --- a/Nasal/it-autoflight.nas +++ b/Nasal/it-autoflight.nas @@ -114,6 +114,7 @@ var Internal = { altPredicted: props.globals.initNode("/it-autoflight/internal/altitude-predicted", 0, "DOUBLE"), bankLimit: props.globals.initNode("/it-autoflight/internal/bank-limit", 30, "INT"), bankLimitAuto: 30, + bankLimitMax: [30, 5, 10, 15, 20, 25, 30], captVs: 0, driftAngle: props.globals.initNode("/it-autoflight/internal/drift-angle-deg", 0, "DOUBLE"), flchActive: 0, @@ -159,10 +160,11 @@ var Text = { vertTemp: "T/O CLB", }; -var Setting = { +var Settings = { autoBankMaxDeg: props.globals.getNode("/it-autoflight/settings/auto-bank-max-deg", 1), autolandWithoutAp: props.globals.getNode("/it-autoflight/settings/autoland-without-ap", 1), autolandWithoutApTemp: 0, + customFMA: props.globals.getNode("/it-autoflight/settings/custom-fma", 1), disableFinal: props.globals.getNode("/it-autoflight/settings/disable-final", 1), latAglFt: props.globals.getNode("/it-autoflight/settings/lat-agl-ft", 1), landingFlap: props.globals.getNode("/it-autoflight/settings/land-flap", 1), @@ -197,29 +199,37 @@ var Gain = { }; var ITAF = { - init: func() { - Input.ktsMach.setBoolValue(0); + init: func(t) { # Not everything should be reset if the reset is type 1 + if (t != 1) { + Input.alt.setValue(10000); + Input.bankLimitSW.setValue(0); + Input.hdg.setValue(360); + Input.ktsMach.setBoolValue(0); + Input.kts.setValue(250); + Input.mach.setValue(0.5); + Input.trk.setBoolValue(0); + Input.trueCourse.setBoolValue(0); + Input.useNav2Radio.setBoolValue(0); + } Input.ap1.setBoolValue(0); Input.ap2.setBoolValue(0); Input.athr.setBoolValue(0); - Input.fd1.setBoolValue(0); - Input.fd2.setBoolValue(0); - Input.hdg.setValue(360); - Input.alt.setValue(10000); + if (t != 1) { + Input.fd1.setBoolValue(0); + Input.fd2.setBoolValue(0); + } Input.vs.setValue(0); Input.fpa.setValue(0); Input.lat.setValue(5); Input.vert.setValue(7); - Input.trk.setBoolValue(0); - Input.trueCourse.setBoolValue(0); Input.toga.setBoolValue(0); - Input.bankLimitSW.setValue(0); - Input.useNav2Radio.setBoolValue(0); Output.ap1.setBoolValue(0); Output.ap2.setBoolValue(0); Output.athr.setBoolValue(0); - Output.fd1.setBoolValue(0); - Output.fd2.setBoolValue(0); + if (t != 1) { + Output.fd1.setBoolValue(0); + Output.fd2.setBoolValue(0); + } Output.hdgInHld.setBoolValue(0); Output.lnavArm.setBoolValue(0); Output.locArm.setBoolValue(0); @@ -229,16 +239,15 @@ var ITAF = { Output.vert.setValue(7); Internal.minVs.setValue(-500); Internal.maxVs.setValue(500); - Internal.bankLimit.setValue(30); - Internal.bankLimitAuto = 30; Internal.alt.setValue(10000); Internal.altCaptureActive = 0; - Input.kts.setValue(250); - Input.mach.setValue(0.5); Text.thr.setValue("PITCH"); Text.arm.setValue(" "); - Text.lat.setValue("T/O"); - Text.vert.setValue("T/O CLB"); + if (Settings.customFMA.getBoolValue()) { + updateFMA.arm(); + } + me.updateLatText("T/O"); + me.updateVertText("T/O CLB"); loopTimer.start(); slowLoopTimer.start(); }, @@ -247,10 +256,10 @@ var ITAF = { Output.vertTemp = Output.vert.getValue(); Output.ap1Temp = Output.ap1.getBoolValue(); Output.ap2Temp = Output.ap2.getBoolValue(); - Setting.autolandWithoutApTemp = Setting.autolandWithoutAp.getBoolValue(); + Settings.autolandWithoutApTemp = Settings.autolandWithoutAp.getBoolValue(); # Kill Autoland if the system should not autoland without AP, and AP is off - if (Setting.autolandWithoutApTemp) { # Only evaluate the rest if this setting is on + if (Settings.autolandWithoutApTemp) { # Only evaluate the rest if this setting is on if (!Output.ap1Temp and !Output.ap2Temp) { if (Output.latTemp == 4) { me.activateLOC(); @@ -312,35 +321,35 @@ var ITAF = { # Autoland Logic if (Output.latTemp == 2) { if (Position.gearAglFtTemp <= 150) { - if (Output.ap1Temp or Output.ap2Temp or Setting.autolandWithoutApTemp) { + if (Output.ap1Temp or Output.ap2Temp or Settings.autolandWithoutApTemp) { me.setLatMode(4); } } } if (Output.vertTemp == 2) { if (Position.gearAglFtTemp <= 100 and Position.gearAglFtTemp >= 5) { - if (Output.ap1Temp or Output.ap2Temp or Setting.autolandWithoutApTemp) { + if (Output.ap1Temp or Output.ap2Temp or Settings.autolandWithoutApTemp) { me.setVertMode(6); } } } else if (Output.vertTemp == 6) { - if (!Output.ap1Temp and !Output.ap2Temp and !Setting.autolandWithoutApTemp) { + if (!Output.ap1Temp and !Output.ap2Temp and !Settings.autolandWithoutApTemp) { me.activateLOC(); me.activateGS(); } else { - if (Position.gearAglFtTemp <= 50 and Position.gearAglFtTemp >= 5) { - Text.vert.setValue("FLARE"); + if (Position.gearAglFtTemp <= 50 and Position.gearAglFtTemp >= 5 and Text.vert.getValue() != "FLARE") { + me.updateVertText("FLARE"); } - if (Gear.wow1Temp and Gear.wow2Temp) { - Text.lat.setValue("RLOU"); - Text.vert.setValue("ROLLOUT"); + if (Gear.wow1Temp and Gear.wow2Temp and Text.vert.getValue() != "ROLLOUT") { + me.updateLatText("RLOU"); + me.updateVertText("ROLLOUT"); } } } # FLCH Engagement if (Text.vertTemp == "T/O CLB") { - me.checkFLCH(Setting.reducAglFt.getValue()); + me.checkFLCH(Settings.reducAglFt.getValue()); } # Altitude Capture/Sync Logic @@ -363,14 +372,14 @@ var ITAF = { # Altitude Hold Min/Max Reset if (Internal.altCaptureActive) { - if (abs(Internal.altDiff) <= 25) { + if (abs(Internal.altDiff) <= 25 and Text.vert.getValue() != "ALT HLD") { me.resetClimbRateLim(); - Text.vert.setValue("ALT HLD"); + me.updateVertText("ALT HLD"); } } # Thrust Mode Selector - if (Output.athr.getBoolValue() and Output.vertTemp != 7 and Setting.retardEnable.getBoolValue() and Position.gearAglFt.getValue() <= Setting.retardAltitude.getValue() and Misc.flapNorm.getValue() >= Setting.landingFlap.getValue() - 0.001) { + if (Output.athr.getBoolValue() and Output.vertTemp != 7 and Settings.retardEnable.getBoolValue() and Position.gearAglFt.getValue() <= Settings.retardAltitude.getValue() and Misc.flapNorm.getValue() >= Settings.landingFlap.getValue() - 0.001) { Output.thrMode.setValue(1); Text.thr.setValue("RETARD"); if (Gear.wow1Temp or Gear.wow2Temp) { # Disconnect A/THR on either main gear touch @@ -388,14 +397,14 @@ var ITAF = { if (Internal.altTemp >= Position.indicatedAltitudeFtTemp) { Output.thrMode.setValue(2); Text.thr.setValue("PITCH"); - if (Internal.flchActive) { # Set before mode change to prevent it from overwriting by mistake - Text.vert.setValue("SPD CLB"); + if (Internal.flchActive and Text.vert.getValue() != "SPD CLB") { # Set before mode change to prevent it from overwriting by mistake + me.updateVertText("SPD CLB"); } } else { Output.thrMode.setValue(1); Text.thr.setValue("PITCH"); - if (Internal.flchActive) { # Set before mode change to prevent it from overwriting by mistake - Text.vert.setValue("SPD DES"); + if (Internal.flchActive and Text.vert.getValue() != "SPD DES") { # Set before mode change to prevent it from overwriting by mistake + me.updateVertText("SPD DES"); } } } else if (Output.vertTemp == 7) { @@ -421,22 +430,11 @@ var ITAF = { } else { Internal.bankLimitAuto = 30; } - math.clamp(Internal.bankLimitAuto, 15, Setting.autoBankMaxDeg.getValue()); # Limit to max degree - if (Input.bankLimitSWTemp == 0) { + if (Internal.bankLimitAuto > Internal.bankLimitMax[Input.bankLimitSWTemp]) { + Internal.bankLimit.setValue(Internal.bankLimitMax[Input.bankLimitSWTemp]); + } else { Internal.bankLimit.setValue(Internal.bankLimitAuto); - } else if (Input.bankLimitSWTemp == 1) { - Internal.bankLimit.setValue(5); - } else if (Input.bankLimitSWTemp == 2) { - Internal.bankLimit.setValue(10); - } else if (Input.bankLimitSWTemp == 3) { - Internal.bankLimit.setValue(15); - } else if (Input.bankLimitSWTemp == 4) { - Internal.bankLimit.setValue(20); - } else if (Input.bankLimitSWTemp == 5) { - Internal.bankLimit.setValue(25); - } else if (Input.bankLimitSWTemp == 6) { - Internal.bankLimit.setValue(30); } # If in LNAV mode and route is not longer active, switch to HDG HLD @@ -488,11 +486,11 @@ var ITAF = { # Reset system once flight complete if (!Output.ap1.getBoolValue() and !Output.ap2.getBoolValue() and Gear.wow0.getBoolValue() and Velocities.groundspeedKt.getValue() < 60 and Output.vert.getValue() != 7) { # Not in T/O or G/A - me.init(); + me.init(1); } # Calculate Roll and Pitch Rate Kp - if (!Setting.disableFinal.getBoolValue()) { + if (!Settings.disableFinal.getBoolValue()) { Gain.rollKpLowTemp = Gain.rollKpLow.getValue(); Gain.rollKpHighTemp = Gain.rollKpHigh.getValue(); Gain.pitchKpLowTemp = Gain.pitchKpLow.getValue(); @@ -558,7 +556,7 @@ var ITAF = { }, apOffFunction: func() { if (!Output.ap1.getBoolValue() and !Output.ap2.getBoolValue()) { # Only do if both APs are off - if (!Setting.disableFinal.getBoolValue()) { + if (!Settings.disableFinal.getBoolValue()) { Controls.aileron.setValue(0); Controls.elevator.setValue(0); Controls.rudder.setValue(0); @@ -608,11 +606,11 @@ var ITAF = { setLatMode: func(n) { Output.vertTemp = Output.vert.getValue(); if (n == 0) { # HDG SEL - Output.lnavArm.setBoolValue(0); - Output.locArm.setBoolValue(0); - Output.apprArm.setBoolValue(0); + me.updateLnavArm(0); + me.updateLocArm(0); + me.updateApprArm(0); Output.lat.setValue(0); - Text.lat.setValue("HDG"); + me.updateLatText("HDG"); if (Output.vertTemp == 2 or Output.vertTemp == 6) { # Also cancel G/S or FLARE if active me.setVertMode(1); } else { @@ -621,16 +619,16 @@ var ITAF = { } else if (n == 1) { # LNAV me.checkLNAV(0); } else if (n == 2) { # VOR/LOC - Output.lnavArm.setBoolValue(0); + me.updateLnavArm(0); me.armTextCheck(); me.checkLOC(0, 0); } else if (n == 3) { # HDG HLD - Output.lnavArm.setBoolValue(0); - Output.locArm.setBoolValue(0); - Output.apprArm.setBoolValue(0); + me.updateLnavArm(0); + me.updateLocArm(0); + me.updateApprArm(0); me.syncHdg(); Output.lat.setValue(0); - Text.lat.setValue("HDG"); + me.updateLatText("HDG"); Internal.hdgHldValue = Input.hdg.getValue(); Output.hdgInHld.setBoolValue(1); if (Output.vertTemp == 2 or Output.vertTemp == 6) { # Also cancel G/S or FLARE if active @@ -639,33 +637,33 @@ var ITAF = { me.armTextCheck(); } } else if (n == 4) { # ALIGN - Output.lnavArm.setBoolValue(0); - Output.locArm.setBoolValue(0); - Output.apprArm.setBoolValue(0); + me.updateLnavArm(0); + me.updateLocArm(0); + me.updateApprArm(0); Output.lat.setValue(4); - Text.lat.setValue("ALGN"); + me.updateLatText("ALGN"); me.armTextCheck(); } else if (n == 5) { # T/O - Output.lnavArm.setBoolValue(0); - Output.locArm.setBoolValue(0); - Output.apprArm.setBoolValue(0); + me.updateLnavArm(0); + me.updateLocArm(0); + me.updateApprArm(0); Output.lat.setValue(5); - Text.lat.setValue("T/O"); + me.updateLatText("T/O"); me.armTextCheck(); } }, setLatArm: func(n) { if (n == 0) { - Output.lnavArm.setBoolValue(0); + me.updateLnavArm(0); me.armTextCheck(); } else if (n == 1) { if (FPLN.num.getValue() > 0 and FPLN.active.getBoolValue()) { - Output.lnavArm.setBoolValue(1); + me.updateLnavArm(1); me.armTextCheck(); } } else if (n == 3) { me.syncHdg(); - Output.lnavArm.setBoolValue(0); + me.updateLnavArm(0); me.armTextCheck(); } }, @@ -674,23 +672,23 @@ var ITAF = { if (n == 0) { # ALT HLD Internal.flchActive = 0; Internal.altCaptureActive = 0; - Output.apprArm.setBoolValue(0); + me.updateApprArm(0); Output.vert.setValue(0); me.resetClimbRateLim(); - Text.vert.setValue("ALT HLD"); + me.updateVertText("ALT HLD"); me.syncAlt(); me.armTextCheck(); } else if (n == 1) { # V/S if (abs(Input.altDiff) >= 25) { Internal.flchActive = 0; Internal.altCaptureActive = 0; - Output.apprArm.setBoolValue(0); + me.updateApprArm(0); Output.vert.setValue(1); - Text.vert.setValue("V/S"); + me.updateVertText("V/S"); me.syncVs(); me.armTextCheck(); } else { - Output.apprArm.setBoolValue(0); + me.updateApprArm(0); me.armTextCheck(); } } else if (n == 2) { # G/S @@ -701,14 +699,14 @@ var ITAF = { Output.vert.setValue(0); me.setClimbRateLim(); Internal.altCaptureActive = 1; - Text.vert.setValue("ALT CAP"); + me.updateVertText("ALT CAP"); } else if (n == 4) { # FLCH - Output.apprArm.setBoolValue(0); + me.updateApprArm(0); if (abs(Input.altDiff) >= 125) { # SPD CLB or SPD DES if (Input.alt.getValue() >= Position.indicatedAltitudeFt.getValue()) { # Usually set Thrust Mode Selector, but we do it now due to timer lag - Text.vert.setValue("SPD CLB"); + me.updateVertText("SPD CLB"); } else { - Text.vert.setValue("SPD DES"); + me.updateVertText("SPD DES"); } Internal.altCaptureActive = 0; Output.vert.setValue(4); @@ -718,44 +716,44 @@ var ITAF = { Internal.alt.setValue(Input.alt.getValue()); Internal.altCaptureActive = 1; Output.vert.setValue(0); - Text.vert.setValue("ALT CAP"); + me.updateVertText("ALT CAP"); } me.armTextCheck(); } else if (n == 5) { # FPA if (abs(Input.altDiff) >= 25) { Internal.flchActive = 0; Internal.altCaptureActive = 0; - Output.apprArm.setBoolValue(0); + me.updateApprArm(0); Output.vert.setValue(5); - Text.vert.setValue("FPA"); + me.updateVertText("FPA"); me.syncFpa(); me.armTextCheck(); } else { - Output.apprArm.setBoolValue(0); + me.updateApprArm(0); me.armTextCheck(); } } else if (n == 6) { # FLARE/ROLLOUT Internal.flchActive = 0; Internal.altCaptureActive = 0; - Output.apprArm.setBoolValue(0); + me.updateApprArm(0); Output.vert.setValue(6); - Text.vert.setValue("G/S"); + me.updateVertText("G/S"); me.armTextCheck(); } else if (n == 7) { # T/O CLB or G/A CLB, text is set by TOGA selector Internal.flchActive = 0; Internal.altCaptureActive = 0; - Output.apprArm.setBoolValue(0); + me.updateApprArm(0); Output.vert.setValue(7); me.armTextCheck(); } }, activateLNAV: func() { if (Output.lat.getValue() != 1) { - Output.lnavArm.setBoolValue(0); - Output.locArm.setBoolValue(0); - Output.apprArm.setBoolValue(0); + me.updateLnavArm(0); + me.updateLocArm(0); + me.updateApprArm(0); Output.lat.setValue(1); - Text.lat.setValue("LNAV"); + me.updateLatText("LNAV"); if (Output.vertTemp == 2 or Output.vertTemp == 6) { # Also cancel G/S or FLARE if active me.setVertMode(1); } else { @@ -765,10 +763,10 @@ var ITAF = { }, activateLOC: func() { if (Output.lat.getValue() != 2) { - Output.lnavArm.setBoolValue(0); - Output.locArm.setBoolValue(0); + me.updateLnavArm(0); + me.updateLocArm(0); Output.lat.setValue(2); - Text.lat.setValue("LOC"); + me.updateLatText("LOC"); me.armTextCheck(); } }, @@ -776,17 +774,17 @@ var ITAF = { if (Output.vert.getValue() != 2) { Internal.flchActive = 0; Internal.altCaptureActive = 0; - Output.apprArm.setBoolValue(0); + me.updateApprArm(0); Output.vert.setValue(2); - Text.vert.setValue("G/S"); + me.updateVertText("G/S"); me.armTextCheck(); } }, checkLNAV: func(t) { - if (FPLN.num.getValue() > 0 and FPLN.active.getBoolValue() and Position.gearAglFt.getValue() >= Setting.latAglFt.getValue()) { + if (FPLN.num.getValue() > 0 and FPLN.active.getBoolValue() and Position.gearAglFt.getValue() >= Settings.latAglFt.getValue()) { me.activateLNAV(); } else if (FPLN.active.getBoolValue() and Output.lat.getValue() != 1 and t != 1) { - Output.lnavArm.setBoolValue(1); + me.updateLnavArm(1); me.armTextCheck(); } }, @@ -804,8 +802,8 @@ var ITAF = { me.activateLOC(); } else if (t != 1) { # Do not do this if loop calls it if (Output.lat.getValue() != 2) { - Output.lnavArm.setBoolValue(0); - Output.locArm.setBoolValue(1); + me.updateLnavArm(0); + me.updateLocArm(1); if (a != 1) { # Don't call this if arming with G/S me.armTextCheck(); } @@ -823,7 +821,7 @@ var ITAF = { me.activateGS(); } else if (t != 1) { # Do not do this if loop calls it if (Output.vert.getValue() != 2) { - Output.apprArm.setBoolValue(1); + me.updateApprArm(1); } me.armTextCheck(); } @@ -864,7 +862,7 @@ var ITAF = { if ((Output.vertTemp == 2 or Output.vertTemp == 6) and Velocities.indicatedAirspeedKt.getValue() >= 80) { me.setLatMode(3); me.setVertMode(7); # Must be before kicking AP off - Text.vert.setValue("G/A CLB"); + me.updateVertText("G/A CLB"); Input.ktsMach.setBoolValue(0); me.syncKtsGa(); if (Gear.wow1.getBoolValue() or Gear.wow2.getBoolValue()) { @@ -877,7 +875,7 @@ var ITAF = { me.setLatMode(5); } me.setVertMode(7); - Text.vert.setValue("T/O CLB"); + me.updateVertText("T/O CLB"); } }, armTextCheck: func() { @@ -895,7 +893,7 @@ var ITAF = { Input.kts.setValue(math.clamp(math.round(Velocities.indicatedAirspeedKt.getValue()), 100, 350)); }, syncKtsGa: func() { # Same as syncKts, except doesn't go below TogaSpd - Input.kts.setValue(math.clamp(math.round(Velocities.indicatedAirspeedKt.getValue()), Setting.togaSpd.getValue(), 350)); + Input.kts.setValue(math.clamp(math.round(Velocities.indicatedAirspeedKt.getValue()), Settings.togaSpd.getValue(), 350)); }, syncMach: func() { Input.mach.setValue(math.clamp(math.round(Velocities.indicatedMach.getValue(), 0.001), 0.5, 0.9)); @@ -913,6 +911,37 @@ var ITAF = { syncFpa: func() { Input.fpa.setValue(math.clamp(math.round(Internal.fpa.getValue(), 0.1), -9.9, 9.9)); }, + # Allows custom FMA behavior if desired + updateLatText: func(t) { + Text.lat.setValue(t); + if (Settings.customFMA.getBoolValue()) { + updateFMA.lat(); + } + }, + updateVertText: func(t) { + Text.vert.setValue(t); + if (Settings.customFMA.getBoolValue()) { + updateFMA.vert(); + } + }, + updateLnavArm: func(n) { + Output.lnavArm.setBoolValue(n); + if (Settings.customFMA.getBoolValue()) { + updateFMA.arm(); + } + }, + updateLocArm: func(n) { + Output.locArm.setBoolValue(n); + if (Settings.customFMA.getBoolValue()) { + updateFMA.arm(); + } + }, + updateApprArm: func(n) { + Output.apprArm.setBoolValue(n); + if (Settings.customFMA.getBoolValue()) { + updateFMA.arm(); + } + }, }; setlistener("/it-autoflight/input/ap1", func { @@ -1006,7 +1035,7 @@ setlistener("/it-autoflight/input/trk", func { }, 0, 0); setlistener("/sim/signals/fdm-initialized", func { - ITAF.init(); + ITAF.init(0); }); # For Canvas Nav Display. diff --git a/Nasal/system.nas b/Nasal/system.nas index 25c9f07..b9e7132 100644 --- a/Nasal/system.nas +++ b/Nasal/system.nas @@ -20,10 +20,5 @@ setlistener("controls/gear/gear-down", func }); setlistener("/sim/signals/fdm-initialized", func { - itaf.ap_init(); - var autopilot = gui.Dialog.new("sim/gui/dialogs/autopilot/dialog", "Aircraft/A350-family/Systems/autopilot-dlg.xml"); - setprop("/it-autoflight/settings/retard-enable", 1); # Enable or disable automatic autothrottle retard. - setprop("/it-autoflight/settings/retard-ft", 20); # Add this to change the retard altitude, default is 50ft AGL. - setprop("/it-autoflight/settings/land-flap", 0.645); # Define the landing flaps here. This is needed for autoland, and retard. - setprop("/it-autoflight/settings/land-enable", 0); # Enable or disable automatic landing. + itaf.ITAF.init(); }); diff --git a/Systems/it-autoflight.xml b/Systems/it-autoflight.xml index ed85330..dfd8928 100644 --- a/Systems/it-autoflight.xml +++ b/Systems/it-autoflight.xml @@ -1476,7 +1476,7 @@ /orientation/pitch-deg 5 - -10 + -15 @@ -1502,7 +1502,7 @@ /orientation/pitch-deg 5 - 25 + 30 diff --git a/Systems/autopilot-dlg.xml b/gui/dialogs/it-autoflight-dlg.xml similarity index 100% rename from Systems/autopilot-dlg.xml rename to gui/dialogs/it-autoflight-dlg.xml