From 4c36bca5452512edffc7c243a194054447da9a63 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Mon, 17 Jan 2022 11:43:31 +0000 Subject: [PATCH 01/52] Re-create new-flightplan-for-2020 branch, with various extra fixes. The DECEL / pseudo waypoints will no longer be within the flightplan object, but only within the FPLN item. --- A320-main.xml | 1 + Models/Instruments/MCDU/MCDU.nas | 13 +- .../Instruments/ND/canvas/map/RTE.lcontroller | 6 +- .../ND/canvas/map/WPT-airbus.symbol | 2 +- Models/Instruments/ND/canvas/style.nas | 45 +- Models/Instruments/PFD/PFD.nas | 2 +- Nasal/FMGC/FMGC-b.nas | 35 +- Nasal/FMGC/FMGC.nas | 25 +- Nasal/FMGC/flightplan-delegates.nas | 210 +++++++++ Nasal/FMGC/flightplan.nas | 428 ++++++++---------- Nasal/Libraries/libraries.nas | 4 +- Nasal/MCDU/DIRTO.nas | 2 +- Nasal/MCDU/F-PLN.nas | 51 ++- Systems/fmgc-drivers.xml | 21 +- 14 files changed, 529 insertions(+), 316 deletions(-) create mode 100644 Nasal/FMGC/flightplan-delegates.nas diff --git a/A320-main.xml b/A320-main.xml index 02e4a583..bdd27bd2 100644 --- a/A320-main.xml +++ b/A320-main.xml @@ -4796,6 +4796,7 @@ Aircraft/A320-family/Nasal/Panels/efis.nas + Aircraft/A320-family/Nasal/FMGC/flightplan-delegates.nas Aircraft/A320-family/Nasal/FMGC/flightplan-waypoints.nas Aircraft/A320-family/Nasal/FMGC/flightplan.nas Aircraft/A320-family/Nasal/FMGC/FMGC.nas diff --git a/Models/Instruments/MCDU/MCDU.nas b/Models/Instruments/MCDU/MCDU.nas index 14e88beb..f0bb3abd 100644 --- a/Models/Instruments/MCDU/MCDU.nas +++ b/Models/Instruments/MCDU/MCDU.nas @@ -2885,9 +2885,9 @@ var canvas_MCDU_base = { degrees = getprop("/FMGC/internal/align-ref-lat-degrees"); minutes = getprop("/FMGC/internal/align-ref-lat-minutes"); sign = getprop("/FMGC/internal/align-ref-lat-sign"); - dms_lat = getprop("/FMGC/flightplan[2]/wp[0]/lat"); - degrees_lat = int(dms_lat); - minutes_lat = sprintf("%.1f",abs((dms_lat - degrees_lat) * 60)); + apt = airportinfo(FMGCInternal.depApt); + degrees_lat = int(apt.lat); + minutes_lat = sprintf("%.1f",abs((apt.lat - degrees_lat) * 60)); sign_lat = degrees_lat >= 0 ? "N" : "S"; lat_same = degrees_lat == degrees and minutes_lat == minutes and sign_lat == sign; me["Simple_L1"].setText(abs(sprintf("%.0f", degrees)) ~ "°" ~ sprintf("%.1f", minutes) ~ sign); @@ -2895,15 +2895,14 @@ var canvas_MCDU_base = { degrees = getprop("/FMGC/internal/align-ref-long-degrees"); minutes = getprop("/FMGC/internal/align-ref-long-minutes"); sign = getprop("/FMGC/internal/align-ref-long-sign"); - dms_long = getprop("/FMGC/flightplan[2]/wp[0]/lon"); - degrees_long = int(dms_long); - minutes_long = sprintf("%.1f",abs((dms_long - degrees_long) * 60)); + degrees_long = int(apt.lon); + minutes_long = sprintf("%.1f",abs((apt.lon - degrees_long) * 60)); sign_long = degrees_long >= 0 ? "E" : "W"; long_same = degrees_long == degrees and minutes_long == minutes and sign_long == sign; me["Simple_R1"].setText(abs(sprintf("%.0f", degrees)) ~ "°" ~ sprintf("%.1f", minutes) ~ sign); if (lat_same and long_same) { - me["Simple_C1"].setText(getprop("/FMGC/flightplan[2]/wp[0]/id")); + me["Simple_C1"].setText(getprop("/autopilot/route-manager/route/wp[0]/id")); me["Simple_C1"].setColor(GREEN); } else { me["Simple_C1"].setText("----"); diff --git a/Models/Instruments/ND/canvas/map/RTE.lcontroller b/Models/Instruments/ND/canvas/map/RTE.lcontroller index 42343196..4e22ea44 100644 --- a/Models/Instruments/ND/canvas/map/RTE.lcontroller +++ b/Models/Instruments/ND/canvas/map/RTE.lcontroller @@ -12,9 +12,9 @@ SymbolLayer.add(name, { type: name, # Symbol type df_controller: __self__, # controller to use by default -- this one df_options: { # default configuration options - active_node: "/FMGC/flightplan[2]/active", - current_wp_node: "/FMGC/flightplan[2]/current-wp", - wp_num: "/FMGC/flightplan[2]/num", + active_node: "/autopilot/route-manager/active", + current_wp_node: "/autopilot/route-manager/current-wp", + wp_num: "/autopilot/route-manager/route/num", display_inactive_rte: 0 } }); diff --git a/Models/Instruments/ND/canvas/map/WPT-airbus.symbol b/Models/Instruments/ND/canvas/map/WPT-airbus.symbol index 8320f312..472dd1a2 100644 --- a/Models/Instruments/ND/canvas/map/WPT-airbus.symbol +++ b/Models/Instruments/ND/canvas/map/WPT-airbus.symbol @@ -79,7 +79,7 @@ var init = func { } var draw = func{ - if (me.model.wp.hidden == 1 or me.model.name == "(DECEL)" or me.model.name == "(T/C)" or me.model.name == "(T/D)" or me.model.name == "(LIM)") { + if (me.model.wp.hidden == 1) { me.wp_sym.hide(); me.text_wps.hide(); if (me.text_alt != nil) { diff --git a/Models/Instruments/ND/canvas/style.nas b/Models/Instruments/ND/canvas/style.nas index 14c46d34..7d000859 100644 --- a/Models/Instruments/ND/canvas/style.nas +++ b/Models/Instruments/ND/canvas/style.nas @@ -56,12 +56,12 @@ canvas.NDStyles["Airbus"] = { # that the lateral flight mode is managed. # You can easily override these options before creating the ND, example: # canvas.NDStyles["Airbus"].options.defaults.fplan_active = "my/autpilot/f-plan/active" - fplan_active: "/FMGC/flightplan[2]/active", + fplan_active: "/autopilot/route-manager/active", lat_ctrl: "/it-autoflight/output/lat", managed_val: 1, ver_ctrl: "/it-autoflight/output/vert", spd_ctrl: "/it-autoflight/input/spd-managed", - current_wp: "/FMGC/flightplan[2]/current-wp", + current_wp: "/autopilot/route-manager/current-wp", ap1: "/it-autoflight/output/ap1", ap2: "/it-autoflight/output/ap2", nav1_frq: "/instrumentation/nav[0]/frequencies/selected-mhz", @@ -72,7 +72,7 @@ canvas.NDStyles["Airbus"] = { adf2_frq: "/instrumentation/adf[1]/frequencies/selected-khz", dep_rwy: "/autopilot/route-manager/departure/runway", dest_rwy: "/autopilot/route-manager/destination/runway", - wp_count: "/FMGC/flightplan[2]/num", + wp_count: "/autopilot/route-manager/route/num", level_off_alt: "/autopilot/route-manager/vnav/level-off-alt", athr: "/it-autoflight/output/athr", app_mode: "/instrumentation/nd/app-mode", @@ -806,11 +806,10 @@ canvas.NDStyles["Airbus"] = { id: "wpActiveId", impl: { init: func(nd,symbol), - predicate: func(nd) getprop("/FMGC/flightplan[2]/current-leg") != nil and - getprop("/FMGC/flightplan[2]/active") and + predicate: func(nd) getprop("/autopilot/route-manager/wp[0]/id") != nil and getprop("/autopilot/route-manager/active") and nd.in_mode("toggle_display_mode", ["MAP", "PLAN"]) and (nd.adirs_property.getValue() == 1 or (adirs_3.getValue() == 1 and att_switch.getValue() == nd.attitude_heading_setting)), is_true: func(nd) { - nd.symbols.wpActiveId.setText(getprop("/FMGC/flightplan[2]/current-leg")); + nd.symbols.wpActiveId.setText(getprop("/autopilot/route-manager/wp[0]/id")); nd.symbols.wpActiveId.show(); }, is_false: func(nd) nd.symbols.wpActiveId.hide(), @@ -820,16 +819,14 @@ canvas.NDStyles["Airbus"] = { id: "wpActiveCrs", impl: { init: func(nd,symbol), - predicate: func(nd) getprop("/FMGC/flightplan[2]/current-leg") != nil and - getprop("/FMGC/flightplan[2]/active") and + predicate: func(nd) getprop("/autopilot/route-manager/wp[0]/id") != nil and getprop("/autopilot/route-manager/active") and nd.in_mode("toggle_display_mode", ["MAP", "PLAN"]) and (nd.adirs_property.getValue() == 1 or (adirs_3.getValue() == 1 and att_switch.getValue() == nd.attitude_heading_setting)), is_true: func(nd) { - #var cur_wp = getprop("/autopilot/route-manager/current-wp"); var deg = nil; if (nd.get_switch("toggle_true_north")) { - var deg = math.round(getprop("/FMGC/flightplan[2]/current-leg-course")) or 0; + var deg = math.round(getprop("/autopilot/route-manager/wp[0]/true-bearing-deg") or 0); } else { - var deg = math.round(getprop("/FMGC/flightplan[2]/current-leg-course-mag")) or 0; + var deg = math.round(getprop("/autopilot/route-manager/wp[0]/bearing-deg") or 0); } if (deg != nil) { nd.symbols.wpActiveCrs.setText(sprintf("%03.0f", deg) ~ "°"); @@ -845,13 +842,11 @@ canvas.NDStyles["Airbus"] = { id: "wpActiveDist", impl: { init: func(nd,symbol), - predicate: func(nd) (getprop("/FMGC/flightplan[2]/current-leg-dist") != nil and - getprop("/FMGC/flightplan[2]/active") and + predicate: func(nd) (getprop("/autopilot/route-manager/wp[0]/dist") != nil and getprop("/autopilot/route-manager/active") and nd.in_mode("toggle_display_mode", ["MAP", "PLAN"]) and (nd.adirs_property.getValue() == 1 or (adirs_3.getValue() == 1 and att_switch.getValue() == nd.attitude_heading_setting))), is_true: func(nd) { - var dst = getprop("/FMGC/flightplan[2]/current-leg-dist"); - nd.symbols.wpActiveDist.setText(sprintf("%3.01f",dst)); + nd.symbols.wpActiveDist.setText(sprintf("%3.01f", getprop("/autopilot/route-manager/wp[0]/dist"))); nd.symbols.wpActiveDist.show(); }, is_false: func(nd) nd.symbols.wpActiveDist.hide(), @@ -861,11 +856,11 @@ canvas.NDStyles["Airbus"] = { id: "wpActiveDistLbl", impl: { init: func(nd,symbol), - predicate: func(nd) getprop("/FMGC/flightplan[2]/current-leg-dist") != nil and getprop("/FMGC/flightplan[2]/active") and nd.in_mode("toggle_display_mode", ["MAP", "PLAN"]) - and (nd.adirs_property.getValue() == 1 or (adirs_3.getValue() == 1 and att_switch.getValue() == nd.attitude_heading_setting)), + predicate: func(nd) getprop("/autopilot/route-manager/wp[0]/dist") != nil and getprop("/autopilot/route-manager/active") and + nd.in_mode("toggle_display_mode", ["MAP", "PLAN"]) and (nd.adirs_property.getValue() == 1 or (adirs_3.getValue() == 1 and att_switch.getValue() == nd.attitude_heading_setting)), is_true: func(nd) { nd.symbols.wpActiveDistLbl.show(); - if(getprop("/FMGC/flightplan[2]/current-leg-dist") > 1000) + if(getprop("/autopilot/route-manager/wp[0]/dist") > 1000) nd.symbols.wpActiveDistLbl.setText(" NM"); }, is_false: func(nd) nd.symbols.wpActiveDistLbl.hide(), @@ -875,8 +870,8 @@ canvas.NDStyles["Airbus"] = { id: "eta", impl: { init: func(nd,symbol), - predicate: func(nd) getprop("/autopilot/route-manager/wp/eta") != nil and getprop("/FMGC/flightplan[2]/active") and nd.in_mode("toggle_display_mode", ["MAP", "PLAN"]) - and (nd.adirs_property.getValue() == 1 or (adirs_3.getValue() == 1 and att_switch.getValue() == nd.attitude_heading_setting)), + predicate: func(nd) getprop("/autopilot/route-manager/wp/eta") != nil and getprop("/autopilot/route-manager/active") + and nd.in_mode("toggle_display_mode", ["MAP", "PLAN"]) and (nd.adirs_property.getValue() == 1 or (adirs_3.getValue() == 1 and att_switch.getValue() == nd.attitude_heading_setting)), is_true: func(nd) { var etaSec = getprop("/sim/time/utc/day-seconds")+ getprop("/autopilot/route-manager/wp/eta-seconds"); @@ -1904,7 +1899,7 @@ canvas.NDStyles["Airbus"] = { init: func(nd,symbol), predicate: func(nd) (nd.get_switch("toggle_display_mode") == "MAP" and !nd.get_switch("toggle_centered")), is_true: func(nd){ - var active = getprop("/FMGC/flightplan[2]/active"); + var active = getprop("/autopilot/route-manager/active"); var lat_ctrl = getprop(nd.options.defaults.lat_ctrl); var managed_v = nd.options.defaults.managed_val; var is_managed = (lat_ctrl == managed_v); @@ -1933,7 +1928,7 @@ canvas.NDStyles["Airbus"] = { init: func(nd,symbol), predicate: func(nd) (nd.get_switch("toggle_display_mode") == "MAP" and !nd.get_switch("toggle_centered")), is_true: func(nd){ - var active = getprop("/FMGC/flightplan[2]/active"); + var active = getprop("/autopilot/route-manager/active"); var lat_ctrl = getprop(nd.options.defaults.lat_ctrl); var managed_v = nd.options.defaults.managed_val; var is_managed = (lat_ctrl == managed_v); @@ -1962,7 +1957,7 @@ canvas.NDStyles["Airbus"] = { init: func(nd,symbol), predicate: func(nd) (nd.get_switch("toggle_display_mode") == "MAP" and nd.get_switch("toggle_centered")), is_true: func(nd){ - var active = getprop("/FMGC/flightplan[2]/active"); + var active = getprop("/autopilot/route-manager/active"); var lat_ctrl = getprop(nd.options.defaults.lat_ctrl); var managed_v = nd.options.defaults.managed_val; var is_managed = (lat_ctrl == managed_v); @@ -1991,7 +1986,7 @@ canvas.NDStyles["Airbus"] = { init: func(nd,symbol), predicate: func(nd) (nd.get_switch("toggle_display_mode") == "MAP" and nd.get_switch("toggle_centered")), is_true: func(nd){ - var active = getprop("/FMGC/flightplan[2]/active"); + var active = getprop("/autopilot/route-manager/active"); var lat_ctrl = getprop(nd.options.defaults.lat_ctrl); var managed_v = nd.options.defaults.managed_val; var is_managed = (lat_ctrl == managed_v); @@ -2020,7 +2015,7 @@ canvas.NDStyles["Airbus"] = { init: func(nd,symbol), predicate: func(nd) (nd.in_mode("toggle_display_mode", ["MAP", "PLAN"])), is_true: func(nd){ - var active = getprop("/FMGC/flightplan[2]/active"); + var active = getprop("/autopilot/route-manager/active"); var lat_ctrl = getprop(nd.options.defaults.lat_ctrl); var managed_v = nd.options.defaults.managed_val; var is_managed = (lat_ctrl == managed_v); diff --git a/Models/Instruments/PFD/PFD.nas b/Models/Instruments/PFD/PFD.nas index 8cfcf2ab..0e55ca74 100644 --- a/Models/Instruments/PFD/PFD.nas +++ b/Models/Instruments/PFD/PFD.nas @@ -1490,7 +1490,7 @@ var canvas_pfd = { } } - if (fmgc.FMGCInternal.phase < 3 or fmgc.flightPlanController.arrivalDist >= 250) { + if (fmgc.FMGCInternal.phase < 3 or fmgc.flightPlanController.arrivalDist.getValue() >= 250) { me["FMA_dh"].hide(); me["FMA_dhn"].hide(); me["FMA_nodh"].hide(); diff --git a/Nasal/FMGC/FMGC-b.nas b/Nasal/FMGC/FMGC-b.nas index 4d80baf0..fa0bf517 100644 --- a/Nasal/FMGC/FMGC-b.nas +++ b/Nasal/FMGC/FMGC-b.nas @@ -11,21 +11,21 @@ var Controls = { }; var FPLN = { - active: props.globals.getNode("/FMGC/flightplan[2]/active", 1), + active: props.globals.getNode("/autopilot/route-manager/active", 1), activeTemp: 0, currentCourse: 0, - currentWp: props.globals.getNode("/FMGC/flightplan[2]/current-wp", 1), - currentWpTemp: 0, + currentWP: props.globals.getNode("/autopilot/route-manager/current-wp", 1), + currentWPTemp: 0, deltaAngle: 0, deltaAngleRad: 0, distCoeff: 0, maxBank: 0, maxBankLimit: 0, nextCourse: 0, - R: 0, radius: 0, + R: 0, turnDist: 0, - wp0Dist: props.globals.getNode("/FMGC/flightplan[2]/current-leg-dist", 1), + wp0Dist: props.globals.getNode("/autopilot/route-manager/wp[0]/dist", 1), wpFlyFrom: 0, wpFlyTo: 0, }; @@ -381,7 +381,7 @@ var ITAF = { slowLoop: func() { Velocities.trueAirspeedKtTemp = Velocities.trueAirspeedKt.getValue(); FPLN.activeTemp = FPLN.active.getValue(); - FPLN.currentWpTemp = FPLN.currentWp.getValue(); + FPLN.currentWPTemp = FPLN.currentWP.getValue(); # Bank Limit if (Velocities.trueAirspeedKtTemp >= 420) { @@ -396,22 +396,17 @@ var ITAF = { # If in LNAV mode and route is not longer active, switch to HDG HLD if (Output.lat.getValue() == 1) { # Only evaulate the rest of the condition if we are in LNAV mode - if (flightPlanController.num[2].getValue() == 0 or !FPLN.active.getBoolValue()) { + if (flightPlanController.num[2].getValue() == 0 or !FPLN.activeTemp) { me.setLatMode(3); } } # Waypoint Advance Logic - if (flightPlanController.num[2].getValue() > 0 and FPLN.activeTemp == 1) { - if ((FPLN.currentWpTemp + 1) < flightPlanController.num[2].getValue()) { - Velocities.groundspeedMps = Velocities.groundspeedKt.getValue() * 0.5144444444444; - FPLN.wpFlyFrom = FPLN.currentWpTemp; - if (FPLN.wpFlyFrom < 0) { - FPLN.wpFlyFrom = 0; - } - FPLN.currentCourse = fmgc.wpCourse[2][FPLN.wpFlyFrom].getValue(); - FPLN.wpFlyTo = FPLN.currentWpTemp + 1; - FPLN.nextCourse = fmgc.wpCourse[2][FPLN.wpFlyTo].getValue(); + if (flightPlanController.num[2].getValue() > 0 and FPLN.activeTemp == 1 and FPLN.currentWPTemp != -1) { + if ((FPLN.currentWPTemp + 1) < flightPlanController.num[2].getValue()) { + Velocities.groundspeedMps = pts.Velocities.groundspeed.getValue() * 0.5144444444444; + FPLN.currentCourse = getprop("/autopilot/route-manager/route/wp[" ~ FPLN.currentWPTemp ~ "]/leg-bearing-true-deg"); + FPLN.nextCourse = getprop("/autopilot/route-manager/route/wp[" ~ (FPLN.currentWPTemp + 1) ~ "]/leg-bearing-true-deg"); FPLN.maxBankLimit = Internal.bankLimit.getValue(); FPLN.deltaAngle = math.abs(geo.normdeg180(FPLN.currentCourse - FPLN.nextCourse)); @@ -430,9 +425,11 @@ var ITAF = { if (Gear.wow0.getBoolValue() and FPLN.turnDist < 1) { FPLN.turnDist = 1; } - Internal.lnavAdvanceNm.setValue(FPLN.turnDist); - if (FPLN.wp0Dist.getValue() <= FPLN.turnDist and !Gear.wow1.getBoolValue() and fmgc.flightPlanController.flightplans[2].getWP(FPLN.currentWpTemp).fly_type == "flyBy") { + # This is removed because sequencing is done by the flightplan controller + # Internal.lnavAdvanceNm.setValue(FPLN.turnDist); + + if (FPLN.wp0Dist.getValue() <= FPLN.turnDist and !Gear.wow1.getBoolValue() and fmgc.flightPlanController.flightplans[2].getWP(FPLN.currentWPTemp).fly_type == "flyBy") { flightPlanController.autoSequencing(); } elsif (FPLN.wp0Dist.getValue() <= 0.15) { flightPlanController.autoSequencing(); diff --git a/Nasal/FMGC/FMGC.nas b/Nasal/FMGC/FMGC.nas index d5c42f84..2b6d3d2f 100644 --- a/Nasal/FMGC/FMGC.nas +++ b/Nasal/FMGC/FMGC.nas @@ -31,6 +31,8 @@ var mng_alt_spd = 0; var mng_alt_mach = 0; var altsel = 0; var crzFl = 0; +var xtrkError = 0; +var courseDistanceDecel = 0; var windHdg = 0; var windSpeed = 0; var windsDidChange = 0; @@ -404,7 +406,7 @@ var updateFuel = func { if (FMGCInternal.toFromSet and FMGCInternal.crzSet and FMGCInternal.crzTempSet and FMGCInternal.zfwSet) { crz = FMGCInternal.crzFl; temp = FMGCInternal.crzTemp; - dist = flightPlanController.arrivalDist; + dist = flightPlanController.arrivalDist.getValue(); trpWind = FMGCInternal.tripWind; wind_value = FMGCInternal.tripWindValue; @@ -418,7 +420,7 @@ var updateFuel = func { trip_fuel = math.clamp(trip_fuel, 400, 80000); # cruize temp correction - trip_fuel = trip_fuel + (0.033 * (temp - 15 + (2 * crz / 10)) * flightPlanController.arrivalDist); + trip_fuel = trip_fuel + (0.033 * (temp - 15 + (2 * crz / 10)) * flightPlanController.arrivalDist.getValue()); trip_time = 9.095e-02 + (dist*-3.968e-02) + (dist*dist*4.302e-04) + (dist*dist*dist*2.005e-07) + (dist*dist*dist*dist*-6.876e-11) + (dist*dist*dist*dist*dist*1.432e-14) + (dist*dist*dist*dist*dist*dist*-1.177e-18) + (crz*7.348e-01) + (dist*crz*3.310e-03) + (dist*dist*crz*-8.700e-06) + (dist*dist*dist*crz*-4.214e-10) + (dist*dist*dist*dist*crz*5.652e-14) + (dist*dist*dist*dist*dist*crz*-6.379e-18) + (crz*crz*-1.449e-02) + (dist*crz*crz*-7.508e-06) + (dist*dist*crz*crz*4.529e-08) + (dist*dist*dist*crz*crz*3.699e-13) + (dist*dist*dist*dist*crz*crz*8.466e-18) + (crz*crz*crz*1.108e-04) + (dist*crz*crz*crz*-4.126e-08) + (dist*dist*crz*crz*crz*-9.645e-11) + (dist*dist*dist*crz*crz*crz*-1.544e-16) + (crz*crz*crz*crz*-4.123e-07) + (dist*crz*crz*crz*crz*1.831e-10) + (dist*dist*crz*crz*crz*crz*7.438e-14) + (crz*crz*crz*crz*crz*7.546e-10) + (dist*crz*crz*crz*crz*crz*-1.921e-13) + (crz*crz*crz*crz*crz*crz*-5.453e-13); trip_time = math.clamp(trip_time, 10, 480); @@ -602,12 +604,12 @@ var masterFMGC = maketimer(0.2, func { } } elsif (FMGCInternal.phase == 3) { if (FMGCInternal.crzFl >= 200) { - if ((flightPlanController.arrivalDist <= 200 and altSel < 20000)) { + if ((flightPlanController.arrivalDist.getValue() <= 200 or altSel < 20000)) { newphase = 4; systems.PNEU.pressMode.setValue("DE"); } } else { - if ((flightPlanController.arrivalDist <= 200 and altSel < (FMGCInternal.crzFl * 100))) { # todo - not sure about crzFl condition, investigate what happens! + if ((flightPlanController.arrivalDist.getValue() <= 200 or altSel < (FMGCInternal.crzFl * 100))) { # todo - not sure about crzFl condition, investigate what happens! newphase = 4; systems.PNEU.pressMode.setValue("DE"); } @@ -627,15 +629,20 @@ var masterFMGC = maketimer(0.2, func { newphase = 2; } } + + xtrkError = getprop("/instrumentation/gps/wp/wp[1]/course-error-nm"); - if (flightPlanController.num[2].getValue() > 0 and getprop("/FMGC/flightplan[2]/active") == 1 and - flightPlanController.arrivalDist <= 15 and (modelat == "NAV" or modelat == "LOC" or modelat == "LOC*") and pts.Position.gearAglFt.getValue() < 9500) { #todo decel pseudo waypoint - FMGCInternal.decel = 1; - } elsif (FMGCInternal.decel and (FMGCInternal.phase == 0 or FMGCInternal.phase == 6)) { + if (flightPlanController.decelPoint != nil) { + courseDistanceDecel = courseAndDistance(flightPlanController.decelPoint.lat, flightPlanController.decelPoint.lon); + if (flightPlanController.num[2].getValue() > 0 and fmgc.flightPlanController.active.getBoolValue() and flightPlanController.decelPoint != nil and (courseDistanceDecel[1] <= 5 and (math.abs(courseDistanceDecel[0] - pts.Orientation.heading.getValue()) >= 90 and xtrkError <= 5) or courseDistanceDecel[1] <= 0.1) and (modelat == "NAV" or modelat == "LOC" or modelat == "LOC*") and pts.Position.gearAglFt.getValue() < 9500) { + FMGCInternal.decel = 1; + } elsif (FMGCInternal.decel and (FMGCInternal.phase == 0 or FMGCInternal.phase == 6)) { + FMGCInternal.decel = 0; + } + } else { FMGCInternal.decel = 0; } - tempOverspeed = systems.ADIRS.overspeedVFE.getValue(); if (tempOverspeed != 1024) { FMGCInternal.maxspeed = tempOverspeed - 4; diff --git a/Nasal/FMGC/flightplan-delegates.nas b/Nasal/FMGC/flightplan-delegates.nas new file mode 100644 index 00000000..5eb1b3de --- /dev/null +++ b/Nasal/FMGC/flightplan-delegates.nas @@ -0,0 +1,210 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# NOTE! This copyright does *not* cover user models that use these Nasal +# services by normal function calls - this is merely considered normal use +# of the code, and does *not* fall under the heading of "derived work." +# +# Copyright (C) 2012-202 by James Turner + +# route_manager.nas - FlightPlan delegate(s) corresponding to the built- +# in route-manager dialog and GPS. Intended to provide a sensible default behaviour, +# but can be disabled by an aircraft-specific FMS / GPS system. + +# This delegate corresponds to functionality of the built-in route-manager dialog. +# if you disable it, the built-in route-manager dialog may not work as expected. +# Especially, this dialog is responsible for building departure, approach and +# arrival waypoints corresponding to the requested SID/STAR/approach, +# and replacing them when the inputs change (eg, user seelcted a different +# destination or STAR while enroute) +# +# You can disable the default GPS behaviour *without* touching this delegate : they are +# kept seperate since this first one is less likely to need changes + +var GPSPath = "/instrumentation/gps"; + +# this delegate corresponds to the default behaviour of the built-in GPS. +# depending on the real GPS/FMS you are modelling, you probably need to +# replace this with your own. +# +# To do that, just set /autopilot/route-manager/disable-fms to true, which +# will block creation of this delegate. +# +# Of course you are then responsible for many basic FMS functions, such as +# route sequencing and activation +# + +var A320GPSDeleagte = { + new: func(fp) { + var m = { parents: [A320GPSDeleagte], flightplan:fp, landingCheck:nil }; + + logprint(LOG_INFO, 'creating A320 GPS FPDelegate'); + + # tell the GPS C++ code we will do sequencing ourselves, so it can disable + # its legacy logic for this + setprop(GPSPath ~ '/config/delegate-sequencing', 1); + + # enable 2020.2 C++ turn anticipation + setprop(GPSPath ~ '/config/enable-fly-by', 0); + + # Set maximum lateral deviation for sequencing to 5 miles + setprop(GPSPath ~ '/config/over-flight-arm-distance', 5); + + # make FlightPlan behaviour match GPS config state + fp.followLegTrackToFix = getprop(GPSPath ~ '/config/follow-leg-track-to-fix') or 0; + + # similarly, make FlightPlan follow the performance category settings + fp.aircraftCategory = getprop('/autopilot/settings/icao-aircraft-category') or 'A'; + + m._modeProp = props.globals.getNode(GPSPath ~ '/mode'); + return m; + }, + + _landingCheckTimeout: func + { + var wow = getprop('gear/gear[0]/wow'); + var gs = getprop('velocities/groundspeed-kt'); + if (wow and (gs < 25)) { + logprint(LOG_INFO, 'GPS saw speed < 25kts on destination runway, end of route.'); + me.landingCheck.stop(); + # record touch-down time? + me.flightplan.finish(); + } + }, + + _captureCurrentCourse: func + { + var crs = getprop(GPSPath ~ "/desired-course-deg"); + setprop(GPSPath ~ "/selected-course-deg", crs); + }, + + _selectOBSMode: func + { + setprop(GPSPath ~ "/command", "obs"); + }, + + waypointsChanged: func + { + }, + + activated: func + { + if (!me.flightplan.active) + return; + + logprint(LOG_INFO,'flightplan activated, default GPS to LEG mode'); + setprop(GPSPath ~ "/command", "leg"); + + if (getprop(GPSPath ~ '/wp/wp[1]/from-flag')) { + logprint(LOG_INFO, '\tat GPS activation, already passed active WP, sequencing'); + me.sequence(); + } + }, + + deactivated: func + { + if (me._modeProp.getValue() == 'leg') { + logprint(LOG_INFO, 'flightplan deactivated, default GPS to OBS mode'); + me._captureCurrentCourse(); + me._selectOBSMode(); + } + }, + + endOfFlightPlan: func + { + if (me._modeProp.getValue() == 'leg') { + logprint(LOG_INFO, 'end of flight-plan, switching GPS to OBS mode'); + me._captureCurrentCourse(); + me._selectOBSMode(); + } + }, + + cleared: func + { + if (!me.flightplan.active) + return; + + if (me._modeProp.getValue() == 'leg') { + logprint(LOG_INFO, 'flight-plan cleared, switching GPS to OBS mode'); + me._captureCurrentCourse(); + me._selectOBSMode(); + } + }, + + sequence: func + { + if (!me.flightplan.active) + return; + #flightPlanController.autoSequencing(); + var mode = me._modeProp.getValue(); + if (mode == 'dto') { + # direct-to is done, check if we should resume the following leg + var index = me.flightplan.indexOfWP(getprop(GPSPath ~ '/wp/wp[1]/latitude-deg'), + getprop(GPSPath ~ '/wp/wp[1]/longitude-deg')); + if (index >= 0) { + logprint(LOG_INFO, "default GPS reached Direct-To, resuming FP leg at " ~ index); + me.flightplan.current = index + 1; + setprop(GPSPath ~ "/command", "leg"); + } else { + # revert to OBS mode + logprint(LOG_INFO, "default GPS reached Direct-To, resuming to OBS"); + + me._captureCurrentCourse(); + me._selectOBSMode(); + } + } else if (mode == 'leg') { + # standard leq sequencing + var nextIndex = me.flightplan.current + 1; + if (nextIndex < me.flightplan.numWaypoints() and me.flightplan.nextWP().id == '(DECEL)') { + nextIndex += 1; + logprint(LOG_INFO, "default GPS reached DECEL, going to next waypoint"); + } + + if (nextIndex >= me.flightplan.numWaypoints()) { + logprint(LOG_INFO, "default GPS sequencing, finishing flightplan"); + me.flightplan.finish(); + } elsif (me.flightplan.nextWP().wp_type == 'discontinuity') { + logprint(LOG_INFO, "default GPS sequencing DISCONTINUITY in flightplan, switching to OBS mode"); + + me._captureCurrentCourse(); + me._selectOBSMode(); + } else { + logprint(LOG_INFO, "default GPS sequencing to next WP"); + me.flightplan.current = nextIndex; + } + } else { + # OBS, do nothing + } + + }, + + currentWaypointChanged: func + { + if (!me.flightplan.active) + return; + + if (me.landingCheck != nil) { + me.landingCheck.stop(); + me.landingCheck = nil; # delete timer + } + + var active = me.flightplan.currentWP(); + if (active == nil) return; + + var activeRunway = active.runway(); + # this check is needed to avoid problems with circular routes; when + # activating the FP we end up here, and without this check, immediately + # detect that we've 'landed' and finish the FP again. + var wow = getprop('gear/gear[0]/wow'); + + if (!wow and + (activeRunway != nil) and (me.flightplan.destination_runway != nil) and + (activeRunway.id == me.flightplan.destination_runway.id)) + { + me.landingCheck = maketimer(2.0, me, A320GPSDeleagte._landingCheckTimeout); + me.landingCheck.start(); + } + } +}; + +registerFlightPlanDelegate(A320GPSDeleagte.new); + diff --git a/Nasal/FMGC/flightplan.nas b/Nasal/FMGC/flightplan.nas index 426457a0..8ffe08fb 100644 --- a/Nasal/FMGC/flightplan.nas +++ b/Nasal/FMGC/flightplan.nas @@ -1,5 +1,5 @@ # A3XX FMGC Flightplan Driver -# Copyright (c) 2020 Josh Davidson (Octal450) and Jonathan Redpath (legoboyvdlp) +# Copyright (c) 2022 Josh Davidson (Octal450) and Jonathan Redpath (legoboyvdlp) var wpDep = nil; var wpArr = nil; @@ -17,50 +17,41 @@ var DEBUG_DISCONT = 0; var magHDG = props.globals.getNode("/orientation/heading-magnetic-deg", 1); var trueHDG = props.globals.getNode("/orientation/heading-deg", 1); -# Props.initNode -var wpID = [[props.globals.initNode("/FMGC/flightplan[0]/wp[0]/id", "", "STRING")], [props.globals.initNode("/FMGC/flightplan[1]/wp[0]/id", "", "STRING")], [props.globals.initNode("/FMGC/flightplan[2]/wp[0]/id", "", "STRING")]]; -var wpLat = [[props.globals.initNode("/FMGC/flightplan[0]/wp[0]/lat", 0, "DOUBLE")], [props.globals.initNode("/FMGC/flightplan[1]/wp[0]/lat", 0, "DOUBLE")], [props.globals.initNode("/FMGC/flightplan[2]/wp[0]/lat", 0, "DOUBLE")]]; -var wpLon = [[props.globals.initNode("/FMGC/flightplan[0]/wp[0]/lon", 0, "DOUBLE")], [props.globals.initNode("/FMGC/flightplan[1]/wp[0]/lon", 0, "DOUBLE")], [props.globals.initNode("/FMGC/flightplan[2]/wp[0]/lon", 0, "DOUBLE")]]; -var wpCourse = [[props.globals.initNode("/FMGC/flightplan[0]/wp[0]/course", 0, "DOUBLE")], [props.globals.initNode("/FMGC/flightplan[1]/wp[0]/course", 0, "DOUBLE")], [props.globals.initNode("/FMGC/flightplan[2]/wp[0]/course", 0, "DOUBLE")]]; -var wpDistance = [[props.globals.initNode("/FMGC/flightplan[0]/wp[0]/distance", 0, "DOUBLE")], [props.globals.initNode("/FMGC/flightplan[1]/wp[0]/distance", 0, "DOUBLE")], [props.globals.initNode("/FMGC/flightplan[2]/wp[0]/distance", 0, "DOUBLE")]]; -var wpCoursePrev = [[props.globals.initNode("/FMGC/flightplan[0]/wp[0]/course-from-prev", 0, "DOUBLE")], [props.globals.initNode("/FMGC/flightplan[1]/wp[0]/course-from-prev", 0, "DOUBLE")], [props.globals.initNode("/FMGC/flightplan[2]/wp[0]/course-from-prev", 0, "DOUBLE")]]; -var wpDistancePrev = [[props.globals.initNode("/FMGC/flightplan[0]/wp[0]/distance-from-prev", 0, "DOUBLE")], [props.globals.initNode("/FMGC/flightplan[1]/wp[0]/distance-from-prev", 0, "DOUBLE")], [props.globals.initNode("/FMGC/flightplan[2]/wp[0]/distance-from-prev", 0, "DOUBLE")]]; - var flightPlanController = { flightplans: [createFlightplan(), createFlightplan(), createFlightplan(), nil], temporaryFlag: [0, 0], # These flags are only for the main flgiht-plan - active: props.globals.initNode("/FMGC/flightplan[2]/active", 0, "BOOL"), - - changed: props.globals.initNode("/FMGC/flightplan[2]/changed", 0, "BOOL"), + active: props.globals.initNode("/autopilot/route-manager/active", 0, "BOOL"), + changed: props.globals.initNode("/autopilot/route-manager/flightplan-changed", 0, "BOOL"), currentToWpt: nil, # container for the current TO waypoint ghost - currentToWptIndex: props.globals.initNode("/FMGC/flightplan[2]/current-wp", 0, "INT"), + currentToWptIndex: props.globals.initNode("/autopilot/route-manager/current-wp", 1, "INT"), currentToWptIndexTemp: 0, - currentToWptID: props.globals.initNode("/FMGC/flightplan[2]/current-leg", "", "STRING"), - courseToWpt: props.globals.initNode("/FMGC/flightplan[2]/current-leg-course", 0, "DOUBLE"), - courseMagToWpt: props.globals.initNode("/FMGC/flightplan[2]/current-leg-course-mag", 0, "DOUBLE"), - distToWpt: props.globals.initNode("/FMGC/flightplan[2]/current-leg-dist", 0, "DOUBLE"), + currentToWptIndexTemp2: 0, + currentToWptID: props.globals.initNode("/autopilot/route-manager/wp[0]/id", "", "STRING"), + courseToWpt: props.globals.initNode("/autopilot/route-manager/wp[0]/true-bearing-deg", 0, "DOUBLE"), + courseMagToWpt: props.globals.initNode("/autopilot/route-manager/wp[0]/bearing-deg", 0, "DOUBLE"), + distToWpt: props.globals.initNode("/autopilot/route-manager/wp[0]/dist", 0, "DOUBLE"), wptType: nil, wptTypeNoAdvanceDelete: 0, - distanceToDest: [0, 0, 0], - num: [props.globals.initNode("/FMGC/flightplan[0]/num", 0, "INT"), props.globals.initNode("/FMGC/flightplan[1]/num", 0, "INT"), props.globals.initNode("/FMGC/flightplan[2]/num", 0, "INT")], + # Temporary flightplan will use flightplan[0] and flightplan[1] + num: [props.globals.initNode("/FMGC/flightplan[0]/num", 0, "INT"), props.globals.initNode("/FMGC/flightplan[1]/num", 0, "INT"), props.globals.initNode("/autopilot/route-manager/route/num", 0, "INT")], arrivalIndex: [0, 0, 0], - arrivalDist: 0, - _arrivalDist: 0, + arrivalDist: props.globals.getNode("/autopilot/route-manager/distance-remaining-nm"), fromWptTime: nil, fromWptAlt: nil, _timeTemp: nil, _altTemp: nil, + decelPoint: nil, init: func() { me.resetFlightplan(2); me.insertPPOS(2); me.addDiscontinuity(1, 2, 1); - me.currentToWptIndex.setValue(0); me.flightPlanChanged(2); + me.flightplans[2].activate(); }, reset: func() { @@ -69,6 +60,9 @@ var flightPlanController = { me.resetFlightplan(0); me.resetFlightplan(1); me.resetFlightplan(2); + me.decelPoint = nil; + setprop("/instrumentation/nd/symbols/decel/show", 0); + me.flightplans[2].activate(); }, resetFlightplan: func(n) { @@ -80,6 +74,7 @@ var flightPlanController = { mcdu.isNoSid[n] = 0; mcdu.isNoStar[n] = 0; mcdu.isNoVia[n] = 0; + me.arrivalIndex[n] = 0; # reset arrival index calculations }, createTemporaryFlightPlan: func(n) { @@ -108,12 +103,12 @@ var flightPlanController = { me.destroyTemporaryFlightPlan(3, 1); }, - destroyTemporaryFlightPlan: func(n, a) { # a = 1 activate, a = 0 erase + destroyTemporaryFlightPlan: func(n, a) { # a = 1 activate, a = 0 erase, s = 0 don't call flightplan changed if (a == 1) { flightPlanTimer.stop(); me.resetFlightplan(2); me.flightplans[2] = me.flightplans[n].clone(); - + me.flightplans[2].activate(); if (n != 3) { if (mcdu.isNoSid[n] == 1) { mcdu.isNoSid[2] = 1; @@ -145,13 +140,16 @@ var flightPlanController = { mcdu.isNoTransArr[2] = 0; } } - me.flightPlanChanged(2); flightPlanTimer.start(); } - if (n == 3) { return; } - me.resetFlightplan(n); + if (n == 3) { + me.flightPlanChanged(n); + return; + } me.temporaryFlag[n] = 0; + me.flightPlanChanged(2); + me.resetFlightplan(n); if (canvas_mcdu.myDirTo[n] != nil) { canvas_mcdu.myDirTo[n].updateTmpy(); } @@ -164,9 +162,8 @@ var flightPlanController = { me.flightplans[plan].departure = airportinfo(dep); me.flightplans[plan].destination = airportinfo(arr); if (plan == 2) { - me.destroyTemporaryFlightPlan(0, 0); - me.destroyTemporaryFlightPlan(1, 0); - me.currentToWptIndex.setValue(0); + if (me.temporaryFlag[0]) { me.destroyTemporaryFlightPlan(0, 0); } + if (me.temporaryFlag[1]) { me.destroyTemporaryFlightPlan(1, 0); } me.arrivalIndex = [0, 0, 0]; # reset arrival index calculations } me.addDiscontinuity(1, plan); @@ -177,7 +174,6 @@ var flightPlanController = { if (canvas_mcdu.myArrival[1] != nil) { canvas_mcdu.myArrival[1].reset(); } if (canvas_mcdu.myDeparture[0] != nil) { canvas_mcdu.myDeparture[0].reset(); } if (canvas_mcdu.myDeparture[1] != nil) { canvas_mcdu.myDeparture[1].reset(); } - #todo if plan = 2, kill any tmpy flightplan me.flightPlanChanged(plan); }, @@ -201,45 +197,17 @@ var flightPlanController = { }, autoSequencing: func() { + if (!me.active.getBoolValue()) { return; } me.calculateTimeAltitudeOnSequence(); - # todo setlistener on sim/time/warp to recompute predictions - # Advancing logic me.currentToWptIndexTemp = me.currentToWptIndex.getValue(); - if (me.currentToWptIndexTemp < 1) { - me.currentToWptIndex.setValue(1); - } else if (me.num[2].getValue() > 2) { - if (me.currentToWptIndexTemp == 2) { # Clean up after a no-sequence waypoint - me.currentToWptIndex.setValue(1); # MUST be set first - # TODO: Add support for deleting multiple waypoints at once, this will do for now - if (me.temporaryFlag[0] == 1 and wpID[0][0] == wpID[2][0]) { - me.deleteWP(0, 0); - } - if (me.temporaryFlag[1] == 1 and wpID[1][0] == wpID[2][0]) { - me.deleteWP(0, 1); - } - me.deleteWP(0, 2, 0, 1); - if (me.temporaryFlag[0] == 1 and wpID[0][0] == wpID[2][0]) { - me.deleteWP(0, 0); - } - if (me.temporaryFlag[1] == 1 and wpID[1][0] == wpID[2][0]) { - me.deleteWP(0, 1); - } - me.deleteWP(0, 2, 0, 1); - } else { - me.wptType = me.flightplans[2].getWP(me.currentToWptIndexTemp).wp_type; - me.wptTypeNoAdvanceDelete = me.wptType == "radialIntercept" or me.wptType == "vectors" or me.wptType == "dmeIntercept" or me.wptType == "hdgToAlt"; - if (me.wptTypeNoAdvanceDelete) { - me.currentToWptIndex.setValue(2); - } else { - if (me.temporaryFlag[0] == 1 and wpID[0][0] == wpID[2][0]) { - me.deleteWP(0, 0); - } - if (me.temporaryFlag[1] == 1 and wpID[1][0] == wpID[2][0]) { - me.deleteWP(0, 1); - } - me.deleteWP(0, 2, 0, 1); + me.currentToWptIndex.setValue(me.currentToWptIndexTemp + 1); + + if (me.num[2].getValue() > 2 and me.currentToWptIndexTemp >= 1) { + for (var i = 0; i <= 2; i += 1) { + if (i == 2 or me.temporaryFlag[i]) { + me.flightplans[i].getWP(me.currentToWptIndexTemp - 1).hidden = 1; } } } @@ -262,8 +230,8 @@ var flightPlanController = { # addDiscontinuity - insert discontinuity at passed index # args: index, plan - # index: index to add at - # plan: plan to add to + # index: index to add at + # plan: plan to add to # Check if a discontinuity already exists either immediately before or at that index # If it does, don't add another one # Optional flag DEBUG_DISCONT to disable discontinuities totally @@ -288,18 +256,16 @@ var flightPlanController = { me.flightplans[plan].insertWP(createDiscontinuity(), index); } } else { # both are nil?? - print("Possible error in discontinuities!"); - me.flightplans[plan].insertWP(createDiscontinuity(), index); + debug.dump("Error in discontinuities; won't try to add one"); } }, # insertTP - insert PPOS waypoint denoted "T-P" at specified index # args: n, index - # n: flightplan to which the PPOS waypoint will be inserted - # index: optional argument, defaults to 1, index which the waypoint will be at. - # Default to one, as direct to will insert TP, then create leg to DIRTO waypoint, then delete waypoint[0] + # n: flightplan to which the PPOS waypoint will be inserted + # index: index which the waypoint will be at. - insertTP: func(n, index = 1) { + insertTP: func(n, index) { me.flightplans[n].insertWP(createWP(geo.aircraft_position(), "T-P"), index); fmgc.windController.insertWind(n, index, 0, "T-P"); }, @@ -309,13 +275,19 @@ var flightPlanController = { fmgc.windController.insertWind(n, index, 0, "PPOS"); }, + insertDecel: func(n, pos, index) { + me.flightplans[n].insertWP(createWP(pos, "(DECEL)"), index); + #me.flightplans[n].getWP(index).hidden = 1; + fmgc.windController.insertWind(n, index, 0, "(DECEL)"); + }, + # childWPBearingDistance - return waypoint at bearing and distance from specified waypoint ghost # args: wpt, bearing, dist, name, typeStr - # wpt: waypoint ghost - # bearing: bearing of waypoint to be created from specified waypoint - # distance: distance of waypoint to be created from specified waypoint, nautical miles - # name: name of waypoint to be created - # typeStr: optional argument to be passed to createWP, must be one of "sid", "star" "approach" "missed" or "pseudo" + # wpt: waypoint ghost + # bearing: bearing of waypoint to be created from specified waypoint + # distance: distance of waypoint to be created from specified waypoint, nautical miles + # name: name of waypoint to be created + # typeStr: optional argument to be passed to createWP, must be one of "sid", "star" "approach" "missed" or "pseudo" childWPBearingDistance: func(wpt, bearing, dist) { var coordinates = greatCircleMove(wpt.lat, wpt.lon, num(bearing), num(dist)); @@ -335,7 +307,8 @@ var flightPlanController = { } # fudge the altitude since we cannot create a hdgtoAlt from nasal. Assume 600 feet per mile - 2.5 miles - me.flightplans[n].insertWP(createWP(me.childWPBearingDistance(wptStore, me.flightplans[n].departure_runway.heading, 2.5), "1500", "sid"), 1); + me.flightplans[n].insertWP(createWP(me.childWPBearingDistance(wptStore, me.flightplans[n].departure_runway.heading, 2.5 + (me.flightplans[n].departure_runway.length * M2NM)), "1500", "sid"), 1); + me.flightplans[n].getWP(1).fly_type = "flyOver"; fmgc.windController.insertWind(n, 1, 0, "1500"); } me.flightPlanChanged(n); @@ -357,6 +330,7 @@ var flightPlanController = { hdg = hdg - 360; } me.flightplans[n].insertWP(createWP(me.childWPBearingDistance(wptStore, hdg, 5), "CF", "star"), me.arrivalIndex[n]); + me.flightplans[n].getWP(me.arrivalIndex[n]).fly_type = "flyOver"; fmgc.windController.insertWind(n, me.arrivalIndex[n], 0, "CF"); } me.flightPlanChanged(n); @@ -364,8 +338,8 @@ var flightPlanController = { # directTo - create leg direct from present position to a specified waypoint # args: waypointGhost, plan - # waypointGost: waypoint ghost of the waypoint - # plan: plan on which the direct to leg will be created + # waypointGost: waypoint ghost of the waypoint + # plan: plan on which the direct to leg will be created # We first insert a PPOS waypoint at index 1 # We check if the flightplan already contains the waypoint passed to the function # If it exists, we delete intermediate waypoints @@ -375,35 +349,44 @@ var flightPlanController = { directTo: func(waypointGhost, plan) { if (me.flightplans[plan].indexOfWP(waypointGhost) == -1) { - me.insertTP(plan, 1); + me.insertTP(plan, me.currentToWptIndex.getValue()); # use createWP here as createWPFrom doesn't accept waypoints # createWPFrom worked before... but be sure! - me.flightplans[plan].insertWP(createWP(waypointGhost, waypointGhost.id), 2); - fmgc.windController.insertWind(plan, 2, 0, waypointGhost.id); - me.addDiscontinuity(3, plan); + me.flightplans[plan].insertWP(createWP(waypointGhost, waypointGhost.id), me.currentToWptIndex.getValue() + 1); + fmgc.windController.insertWind(plan, me.currentToWptIndex.getValue() + 1, 0, waypointGhost.id); + me.addDiscontinuity(me.currentToWptIndex.getValue() + 2, plan); + print(me.currentToWptIndex.getValue()); + me.currentToWptIndex.setValue(me.currentToWptIndex.getValue() + 1); } else { # we want to delete the intermediate waypoints up to but not including the waypoint. Leave index 0, we delete it later. # example - waypoint dirto is index 5, we want to delete indexes 1 -> 4. 5 - 1 = 4. # so four individual deletions. Delete index 1 four times. - var timesToDelete = me.flightplans[plan].indexOfWP(waypointGhost); - while (timesToDelete > 1) { - me.deleteWP(1, plan, 1); - timesToDelete -= 1; + var indexWP = me.flightplans[plan].indexOfWP(waypointGhost); + + print(indexWP); + + me.insertTP(plan, indexWP - 1); + for (var i = 0; i < indexWP - 1; i = i + 1) { + if (me.temporaryFlag[0]) { + me.deleteWP(i, 0, 1); + } + if (me.temporaryFlag[1]) { + me.deleteWP(i, 0, 1); + } + me.deleteWP(i, 2, 1); } - # Add TP afterwards, this is essential - me.insertTP(plan, 1); } var curAircraftPosDirTo = geo.aircraft_position(); - canvas_mcdu.myDirTo[plan].updateDist(me.flightplans[plan].getWP(2).courseAndDistanceFrom(curAircraftPosDirTo)[1]); - me.deleteWP(0, plan); + canvas_mcdu.myDirTo[plan].updateDist(me.flightplans[plan].getWP(me.currentToWptIndex.getValue() + 1).courseAndDistanceFrom(curAircraftPosDirTo)[1]); me.flightPlanChanged(plan); }, deleteWP: func(index, n, a = 0, s = 0) { # a = 1, means adding a waypoint via deleting intermediate. s = 1, means autosequencing - var wp = wpID[n][index].getValue(); - if (((s == 0 and left(wp, 4) != FMGCInternal.depApt and left(wp, 4) != FMGCInternal.arrApt) or (s == 1)) and me.flightplans[n].getPlanSize() > 2) { + var wp = me.flightplans[n].getWP(index); + if (((s == 0 and left(wp.wp_name, 4) != FMGCInternal.depApt and left(wp.wp_name, 4) != FMGCInternal.arrApt) or (s == 1)) and me.flightplans[n].getPlanSize() > 2) { + if (me.flightplans[n].getWP(index).id != "DISCONTINUITY" and a == 0) { # if it is a discont, don't make a new one me.flightplans[n].deleteWP(index); fmgc.windController.deleteWind(n, index); @@ -416,7 +399,9 @@ var flightPlanController = { me.flightplans[n].deleteWP(index); fmgc.windController.deleteWind(n, index); } - me.flightPlanChanged(n); + + # if n = 2, then we are clearing a discontinuity. Don't recalculate decel. + me.flightPlanChanged(n, n == 2 ? 0 : 1); canvas_nd.A3XXRouteDriver.triggerSignal("fp-removed"); return 2; } else { @@ -473,7 +458,7 @@ var flightPlanController = { } var indexPresent = me.flightplans[plan].indexOfWP(airport[indexToInsert]); - if (me.flightplans[plan].indexOfWP(airport[indexToInsert]) == -1) { + if (indexPresent == -1 or indexPresent > me.arrivalIndex[plan]) { me.flightplans[plan].insertWP(createWPFrom(airport[indexToInsert]), index); fmgc.windController.insertWind(plan, index, 0, text); me.addDiscontinuity(index + 1, plan); @@ -507,7 +492,7 @@ var flightPlanController = { } var indexPresent = me.flightplans[plan].indexOfWP(fix[indexToInsert]); - if (me.flightplans[plan].indexOfWP(fix[indexToInsert]) == -1) { + if (indexPresent == -1 or indexPresent > me.arrivalIndex[plan]) { me.flightplans[plan].insertWP(createWPFrom(fix[indexToInsert]), index); fmgc.windController.insertWind(plan, index, 1, text); me.addDiscontinuity(index + 1, plan); @@ -541,7 +526,7 @@ var flightPlanController = { } var indexPresent = me.flightplans[plan].indexOfWP(navaid[indexToInsert]); - if (me.flightplans[plan].indexOfWP(navaid[indexToInsert]) == -1) { + if (indexPresent == -1 or indexPresent > me.arrivalIndex[plan]) { me.flightplans[plan].insertWP(createWPFrom(navaid[indexToInsert]), index); fmgc.windController.insertWind(plan, index, 1, text); me.addDiscontinuity(index + 1, plan); @@ -561,7 +546,8 @@ var flightPlanController = { return 1; } - if (me.flightplans[plan].indexOfWP(wpGhost) == -1) { + var indexCurr = me.flightplans[plan].indexOfWP(wpGhost); + if (indexCurr == -1 or indexCurr > me.arrivalIndex[plan]) { # use createWP here as createWPFrom doesn't accept waypoints me.flightplans[plan].insertWP(createWP(wpGhost, wpGhost.wp_name), index); fmgc.windController.insertWind(plan, index, 1, wpGhost.wp_name); @@ -602,13 +588,13 @@ var flightPlanController = { # getWPforPBD - parse scratchpad text to find waypoint ghost for PBD # args: text, index, plan - # text: scratchpad text - # index: index at which waypoint will be inserted - # plan: plan to which waypoint will be inserted + # text: scratchpad text + # index: index at which waypoint will be inserted + # plan: plan to which waypoint will be inserted # return: - # 0: not in database - # 1: notAllowed - # 2: o.k. + # 0: not in database + # 1: notAllowed + # 2: o.k. getWPforPBD: func(text, index, plan, override = 0, overrideIndex = -1) { if (index == 0) { @@ -669,7 +655,6 @@ var flightPlanController = { getNavCount: func(plan) { var count = 0; for (var wpt = 0; wpt < me.flightplans[plan].getPlanSize(); wpt += 1) { - #print(me.flightplans[plan].getWP(wpt).wp_type); if (me.flightplans[plan].getWP(wpt).wp_type == "navaid") { count += 1; } @@ -680,7 +665,6 @@ var flightPlanController = { getDepartureCount: func(plan) { var count = 0; for (var wpt = 0; wpt < me.flightplans[plan].getPlanSize(); wpt += 1) { - #print(me.flightplans[plan].getWP(wpt).wp_role); if (me.flightplans[plan].getWP(wpt).wp_role == "sid") { count += 1; } @@ -698,12 +682,86 @@ var flightPlanController = { return count; }, + getPlanSizeNoDiscont: func(plan) { + var count = 0; + for (var wpt = 0; wpt < me.flightplans[plan].getPlanSize(); wpt += 1) { + if (me.flightplans[plan].getWP(wpt).wp_name != "DISCONTINUITY") { + count += 1; + } + } + return count; + }, + + getIndexOfFirstDecel: func(plan) { + for (var wpt = 0; wpt < me.flightplans[plan].getPlanSize(); wpt += 1) { + if (me.flightplans[plan].getWP(wpt).wp_name == "(DECEL)") { + return wpt; + } + } + return -99; + }, + + calculateDecelPoint: func(n) { + if (me.getPlanSizeNoDiscont(n) <= 1 or fmgc.FMGCInternal.decel) { + setprop("/instrumentation/nd/symbols/decel/show", 0); + return; + } + + me.indexDecel = me.getIndexOfFirstDecel(n); + if (me.indexDecel != -99) { + me.flightplans[n].deleteWP(me.indexDecel); + fmgc.windController.deleteWind(n, me.indexDecel); + me.flightPlanChanged(n,0); + } + + me.indexDecel = 0; + + for (var wpt = 0; wpt < me.flightplans[n].getPlanSize(); wpt += 1) { + if (me.flightplans[n].getWP(wpt).wp_role == "approach") { + me.indexDecel = wpt; + break; + } + if (wpt == me.flightplans[n].getPlanSize()) { + me.indexDecel = me.arrivalIndex - 2; + break; + } + } + + me.dist = me.flightplans[n].getWP(me.indexDecel).leg_distance - 7; + if (me.dist < 0) { + me.dist = 0.1; + } + me.decelPoint = me.flightplans[n].pathGeod(me.indexDecel - 1, me.dist); + + if (n == 2) { + setprop("/instrumentation/nd/symbols/decel/latitude-deg", me.decelPoint.lat); + setprop("/instrumentation/nd/symbols/decel/longitude-deg", me.decelPoint.lon); + setprop("/instrumentation/nd/symbols/decel/show", 1); + } + + me.indexTemp = me.indexDecel; + me.distTemp = 7; + + if (me.flightplans[n].getWP(me.indexTemp).leg_distance < 7) { + while (me.distTemp > 0 and me.indexTemp > 0) { + me.distTemp -= me.flightplans[n].getWP(me.indexTemp).leg_distance; + me.indexTemp -= 1; + } + me.indexTemp += 1; + } + + # todo add to FPLN list + setprop("/instrumentation/nd/symbols/decel/index", me.indexTemp); + # me.insertDecel(n,{lat: me.decelPoint.lat, lon: me.decelPoint.lon}, me.indexTemp); + me.flightPlanChanged(n,0); + }, + # insertPlaceBearingDistance - insert PBD waypoint at specified index, # at some specified bearing, distance from a specified location # args: wp, index, plan - # wpt: waypoint ghost - # index: index to insert at in plan - # plan: plan to insert to + # wpt: waypoint ghost + # index: index to insert at in plan + # plan: plan to insert to insertPlaceBearingDistance: func(wp, bearing, distance, index, plan) { var waypoint = pilotWaypoint.new(me.childWPBearingDistance(wp, bearing, distance), "PBD"); @@ -724,7 +782,7 @@ var flightPlanController = { return 3; } - if (!fmgc.flightPlanController.temporaryFlag[plan]) { + if (!me.temporaryFlag[plan]) { if (text == "CLR" and me.flightplans[2].getWP(index).wp_name == "DISCONTINUITY") { var thePlan = 2; } else { @@ -760,21 +818,11 @@ var flightPlanController = { } }, - flightPlanChanged: func(n) { - sizeWP = size(wpID[n]); - for (var counter = sizeWP; counter < me.flightplans[n].getPlanSize(); counter += 1) { # create new properties if they are required - append(wpID[n], props.globals.initNode("/FMGC/flightplan[" ~ n ~ "]/wp[" ~ counter ~ "]/text", "", "STRING")); - append(wpLat[n], props.globals.initNode("/FMGC/flightplan[" ~ n ~ "]/wp[" ~ counter ~ "]/lat", 0, "DOUBLE")); - append(wpLon[n], props.globals.initNode("/FMGC/flightplan[" ~ n ~ "]/wp[" ~ counter ~ "]/lon", 0, "DOUBLE")); - append(wpCourse[n], props.globals.initNode("/FMGC/flightplan[" ~ n ~ "]/wp[" ~ counter ~ "]/course", 0, "DOUBLE")); - append(wpDistance[n], props.globals.initNode("/FMGC/flightplan[" ~ n ~ "]/wp[" ~ counter ~ "]/distance", 0, "DOUBLE")); - append(wpCoursePrev[n], props.globals.initNode("/FMGC/flightplan[" ~ n ~ "]/wp[" ~ counter ~ "]/course-from-prev", 0, "DOUBLE")); - append(wpDistancePrev[n], props.globals.initNode("/FMGC/flightplan[" ~ n ~ "]/wp[" ~ counter ~ "]/distance-from-prev", 0, "DOUBLE")); - } - - me.updatePlans(); + # callDecel - a variable that gets passed from the calling function. Used to prevent recalculating decel after discontinuity clearing + flightPlanChanged: func(n, callDecel = 1) { + me.updatePlans(1, callDecel); fmgc.windController.updatePlans(); - + # push update to fuel if (fmgc.FMGCInternal.blockConfirmed) { fmgc.FMGCInternal.fuelCalculating = 0; @@ -788,47 +836,30 @@ var flightPlanController = { canvas_nd.A3XXRouteDriver.triggerSignal("fp-added"); }, - updatePlans: func() { - me.updateCurrentWaypoint(); - me._arrivalDist = 0; + # runDecel - used to ensure that only flightplanchanged will update the decel point + updatePlans: func(runDecel = 0, callDecel = 1) { + if (fmgc.FMGCInternal.toFromSet and me.flightplans[2].departure != nil and me.flightplans[2].destination != nil) { # check if flightplan exists + if (!me.active.getBoolValue()) { + if (me.currentToWptIndex.getValue() < 1) { + var errs = []; + call(func { + me.currentToWptIndex.setValue(1); + }, nil, nil, nil,errs); + if (size(errs) != 0) { debug.printerror(errs); } + } + me.active.setValue(1); + } + } elsif (me.active.getBoolValue()) { + me.active.setValue(0); + } + for (var n = 0; n <= 2; n += 1) { for (var wpt = 0; wpt < me.flightplans[n].getPlanSize(); wpt += 1) { # Iterate through the waypoints and update their data - var curAircraftPos = geo.aircraft_position(); # don't want to get this corrupted so make sure it is a local variable var waypointHashStore = me.flightplans[n].getWP(wpt); - courseDistanceFrom = waypointHashStore.courseAndDistanceFrom(curAircraftPos); - wpID[n][wpt].setValue(waypointHashStore.wp_name); - wpLat[n][wpt].setValue(waypointHashStore.wp_lat); - wpLon[n][wpt].setValue(waypointHashStore.wp_lon); - - wpCourse[n][wpt].setValue(waypointHashStore.courseAndDistanceFrom(curAircraftPos)[0]); - wpDistance[n][wpt].setValue(waypointHashStore.courseAndDistanceFrom(curAircraftPos)[1]); - - if (wpt == 1) { - if (me.flightplans[n].getWP(wpt).wp_name != "DISCONTINUITY" and me.flightplans[n].getWP(wpt).wp_type != "vectors" and me.flightplans[n].getWP(wpt).wp_type != "hdgToAlt" and wpt <= me.arrivalIndex[n]) { - # print("Adding " ~ courseDistanceFrom[1] ~ " miles for waypoint " ~ me.flightplans[n].getWP(wpt).wp_name); - me._arrivalDist += courseDistanceFrom[1]; # distance to next waypoint, therafter to end of flightplan - } - } - - if (wpt > 0) { - wpCoursePrev[n][wpt].setValue(me.flightplans[n].getWP(wpt).leg_bearing); - wpDistancePrev[n][wpt].setValue(me.flightplans[n].getWP(wpt).leg_distance); - #if (wpt > 1) { - # if (me.flightplans[n].getWP(wpt - 1).wp_name != "DISCONTINUITY" and me.flightplans[n].getWP(wpt).wp_name != "DISCONTINUITY" and me.flightplans[n].getWP(wpt - 1).wp_type != "vectors" and me.flightplans[n].getWP(wpt - 1).wp_type != "hdgToAlt" and me.flightplans[n].getWP(wpt).wp_type != "vectors" and me.flightplans[n].getWP(wpt).wp_type != "hdgToAlt" and wpt <= me.arrivalIndex[n]) { - # me._arrivalDist += courseDistanceFromPrev[1]; - # } - #} - } else { - # use PPOS for the first waypoint - wpCoursePrev[n][wpt].setValue(courseDistanceFrom[0]); - wpDistancePrev[n][wpt].setValue(courseDistanceFrom[1]); - } - - if (left(wpID[n][wpt].getValue(), 4) == fmgc.FMGCInternal.arrApt and wpt != 0) { + if (left(waypointHashStore.wp_name, 4) == fmgc.FMGCInternal.arrApt and wpt != 0) { if (me.arrivalIndex[n] != wpt) { me.arrivalIndex[n] = wpt; - if (canvas_mcdu.myFpln[0] != nil) { canvas_mcdu.myFpln[0].destInfo(); } @@ -837,74 +868,13 @@ var flightPlanController = { } } } + } + + if (runDecel and callDecel) { + me.calculateDecelPoint(n); } } - if (me.flightplans[2].getWP(me.arrivalIndex[2]) == nil or me.flightplans[2].getWP(1) == nil) { - me.arrivalDist = 9999; - #print(me.arrivalIndex[2]); - } else { - me.arrivalDist = me.flightplans[2].getWP(me.arrivalIndex[2]).distance_along_route - me.flightplans[2].getWP(1).leg_distance + me._arrivalDist; - } - - me.updateMCDUDriver(n); - }, - - updateCurrentWaypoint: func() { - for (var india = 0; india <= 2; india += 1) { - if (FMGCInternal.toFromSet and me.flightplans[india].departure != nil and me.flightplans[india].destination != nil) { # check if flightplan exists - var curAircraftPos = geo.aircraft_position(); # don't want to get this corrupted so make sure it is a local variable - - if (india == 2) { # main plan - if (!me.active.getBoolValue()) { - me.active.setValue(1); - } - - if (me.currentToWptIndex.getValue() > me.flightplans[india].getPlanSize()) { - me.currentToWptIndex.setValue(me.flightplans[india].getPlanSize()); - } - - me.currentToWpt = me.flightplans[india].getWP(me.currentToWptIndex.getValue()); - - if (me.currentToWptID.getValue() != me.currentToWpt.wp_name) { - me.currentToWptID.setValue(me.currentToWpt.wp_name); - } - me.courseToWpt.setValue(me.currentToWpt.courseAndDistanceFrom(curAircraftPos)[0]); - me.distToWpt.setValue(me.currentToWpt.courseAndDistanceFrom(curAircraftPos)[1]); - - magTrueError = magHDG.getValue() - trueHDG.getValue(); - - storeCourse = me.courseToWpt.getValue() + magTrueError; - if (storeCourse >= 360) { - storeCourse -= 360; - } elsif (storeCourse < 0) { - storeCourse += 360; - } - - me.courseMagToWpt.setValue(storeCourse); - } - - if (me.num[india].getValue() != me.flightplans[india].getPlanSize()) { - me.num[india].setValue(me.flightplans[india].getPlanSize()); - } - } else { - if (india == 2) { - if (me.active.getBoolValue()) { - me.active.setValue(0); - } - if (me.currentToWptID.getValue() != "") { - me.currentToWptID.setValue(""); - } - } - - if (me.num[india].getValue() != 0) { - me.num[india].setValue(0); - } - } - } - }, - - updateMCDUDriver: func() { for (var i = 0; i <= 1; i += 1) { if (canvas_mcdu.myFpln[i] != nil) { canvas_mcdu.myFpln[i].updatePlan(); @@ -916,4 +886,4 @@ var flightPlanController = { }, }; -var flightPlanTimer = maketimer(0.1, flightPlanController, flightPlanController.updatePlans); +var flightPlanTimer = maketimer(0.1, flightPlanController, flightPlanController.updatePlans); \ No newline at end of file diff --git a/Nasal/Libraries/libraries.nas b/Nasal/Libraries/libraries.nas index fbe52f13..df7522a7 100644 --- a/Nasal/Libraries/libraries.nas +++ b/Nasal/Libraries/libraries.nas @@ -7,11 +7,13 @@ print("------------------------------------------------"); print("Copyright (c) 2016-2020 Josh Davidson (Octal450)"); print("------------------------------------------------"); +# setprop("/autopilot/route-manager/disable-route-manager", 1); +setprop("/autopilot/route-manager/disable-fms", 1); + # Disable specific menubar items setprop("/sim/menubar/default/menu[0]/item[0]/enabled", 0); setprop("/sim/menubar/default/menu[2]/item[0]/enabled", 0); setprop("/sim/menubar/default/menu[2]/item[2]/enabled", 0); -setprop("/sim/menubar/default/menu[3]/enabled", 0); setprop("/sim/menubar/default/menu[5]/item[9]/enabled", 0); setprop("/sim/menubar/default/menu[5]/item[10]/enabled", 0); setprop("/sim/menubar/default/menu[5]/item[11]/enabled", 0); diff --git a/Nasal/MCDU/DIRTO.nas b/Nasal/MCDU/DIRTO.nas index b4c89c49..b44c2a72 100644 --- a/Nasal/MCDU/DIRTO.nas +++ b/Nasal/MCDU/DIRTO.nas @@ -80,7 +80,7 @@ var dirTo = { var x = 0; me.vector = []; for (var i = 1 + (me.scroll); i < size(canvas_mcdu.myFpln[me.computer].planList) - 2; i = i + 1) { - if (canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_name == "DISCONTINUITY" or canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_name == "VECTORS" or canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_name == "T-P" or canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_type == "hdgToAlt") { continue; } # can't ever have tmpy with dir to + if (canvas_mcdu.myFpln[me.computer].planList[i].wp == "PSEUDO" or canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_name == "DISCONTINUITY" or canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_name == "VECTORS" or canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_name == "T-P" or canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_type == "hdgToAlt") { continue; } # can't ever have tmpy with dir to if (canvas_mcdu.myFpln[me.computer].planList[i].index > fmgc.flightPlanController.arrivalIndex[2]) { continue; } diff --git a/Nasal/MCDU/F-PLN.nas b/Nasal/MCDU/F-PLN.nas index 296b8d11..88ad8256 100644 --- a/Nasal/MCDU/F-PLN.nas +++ b/Nasal/MCDU/F-PLN.nas @@ -93,17 +93,16 @@ var fplnItem = { } }, getBrg: func() { - me.brg = fmgc.wpCourse[me.plan][me.index].getValue() - magvar(); + var wp = fmgc.flightPlanController.flightplans[me.plan].getWP(me.index); + var courseDistanceFrom = courseAndDistance(wp); + me.brg = courseDistanceFrom[0] - magvar(); if (me.brg < 0) { me.brg += 360; } if (me.brg > 360) { me.brg -= 360; } return sprintf("%03.0f", math.round(me.brg)); }, getTrack: func() { - if (me.index > (size(fmgc.wpCoursePrev[me.plan]) - 1)) { - me.trk = me.wp.leg_bearing - magvar(me.wp.lat, me.wp.lon); - } else { - me.trk = fmgc.wpCoursePrev[me.plan][me.index].getValue() - magvar(me.wp.lat, me.wp.lon); - } + var wp = fmgc.flightPlanController.flightplans[me.plan].getWP(me.index); + me.trk = me.wp.leg_bearing - magvar(wp.lat, wp.lon); if (me.trk < 0) { me.trk += 360; } if (me.trk > 360) { me.trk -= 360; } return sprintf("%03.0f", math.round(me.trk)); @@ -141,14 +140,12 @@ var fplnItem = { } }, getDist: func() { - if (me.index > size(fmgc.wpDistancePrev[me.plan]) - 1) { - return math.round(me.wp.leg_distance); + var wp = fmgc.flightPlanController.flightplans[me.plan].getWP(me.index); + if (me.index == fmgc.flightPlanController.currentToWptIndex.getValue()) { + var courseDistanceFrom = courseAndDistance(wp); + return math.round(courseDistanceFrom[1]); } else { - if (me.index == fmgc.flightPlanController.currentToWptIndex.getValue()) { - return math.round(fmgc.wpDistance[me.plan][me.index].getValue()); - } else { - return math.round(fmgc.wpDistancePrev[me.plan][me.index].getValue()); - } + return math.round(wp.leg_distance); } }, pushButtonLeft: func() { @@ -160,7 +157,7 @@ var fplnItem = { if (me.wp.wp_name == "DISCONTINUITY") { canvas_mcdu.myLatRev[me.computer] = latRev.new(4, me.wp, me.index, me.computer); } elsif (fmgc.flightPlanController.temporaryFlag[me.computer]) { - if (me.wp.wp_name == "PPOS" or me.index == (fmgc.flightPlanController.currentToWptIndex.getValue() - 1)) { + if (me.wp.wp_name == "PPOS") { canvas_mcdu.myLatRev[me.computer] = latRev.new(2, me.wp, me.index, me.computer); } elsif (me.index == fmgc.flightPlanController.arrivalIndex[me.computer]) { canvas_mcdu.myLatRev[me.computer] = latRev.new(1, me.wp, me.index, me.computer); @@ -170,7 +167,7 @@ var fplnItem = { canvas_mcdu.myLatRev[me.computer] = latRev.new(3, me.wp, me.index, me.computer); } } else { - if (me.wp.wp_name == "PPOS" or me.index == (fmgc.flightPlanController.currentToWptIndex.getValue() - 1)) { + if (me.wp.wp_name == "PPOS") { canvas_mcdu.myLatRev[me.computer] = latRev.new(2, me.wp, me.index, me.computer); } elsif (me.index == fmgc.flightPlanController.arrivalIndex[2]) { canvas_mcdu.myLatRev[me.computer] = latRev.new(1, me.wp, me.index, me.computer); @@ -291,11 +288,12 @@ var staticText = { }; var pseudoItem = { - new: func(computer, text) { + new: func(computer, text, colour) { var pI = {parents:[pseudoItem]}; pI.computer = computer; pI.text = text; pI.colour = colour; + pI.wp = "PSEUDO"; return pI; }, updateLeftText: func() { @@ -384,13 +382,28 @@ var fplnPage = { # this one is only created once, and then updated - remember th } else { colour = "grn"; } - for (var i = 0; i < me.plan.getPlanSize(); i += 1) { + + + var decelIndex = -9; + if (fmgc.flightPlanController.decelPoint != nil) { + decelIndex = getprop("/instrumentation/nd/symbols/decel/index") or -9; + } + + var startingIndex = fmgc.flightPlanController.currentToWptIndex.getValue() == -1 ? 0 : fmgc.flightPlanController.currentToWptIndex.getValue() - 1; + for (var i = startingIndex; i < me.plan.getPlanSize(); i += 1) { + if (!me.temporaryFlagFpln and decelIndex != -9) { + if (i == decelIndex) { + append(me.planList, pseudoItem.new(me.computer, me.getText("decel"), colour)); + } + } + if (!me.temporaryFlagFpln and i > fmgc.flightPlanController.arrivalIndex[me.planIndex] and fmgc.FMGCInternal.phase != 6) { append(me.planList, fplnItem.new(me.plan.getWP(i), i, me.planIndex, me.computer, "blu")); } else { append(me.planList, fplnItem.new(me.plan.getWP(i), i, me.planIndex, me.computer, colour)); } } + append(me.planList, staticText.new(me.computer, me.getText("fplnEnd"))); if (!fmgc.FMGCInternal.altAirportSet) { append(me.planList, staticText.new(me.computer, me.getText("noAltnFpln"))); @@ -478,8 +491,8 @@ var fplnPage = { # this one is only created once, and then updated - remember th me.L6 = ["----", " DEST", "wht"]; } me.C6 = ["---- ", "TIME ", "wht"]; - if (fmgc.flightPlanController.arrivalDist != nil) { - me.R6 = [sprintf("%4.0f", int(fmgc.flightPlanController.arrivalDist)) ~ " --.-", "DIST EFOB", "wht"]; + if (fmgc.flightPlanController.arrivalDist.getValue() != nil) { + me.R6 = [sprintf("%4.0f", int(fmgc.flightPlanController.arrivalDist.getValue())) ~ " --.-", "DIST EFOB", "wht"]; } else { me.R6 = ["---- --.-", "DIST EFOB", "wht"]; } diff --git a/Systems/fmgc-drivers.xml b/Systems/fmgc-drivers.xml index f36c3a0e..b644f5e4 100644 --- a/Systems/fmgc-drivers.xml +++ b/Systems/fmgc-drivers.xml @@ -376,6 +376,24 @@ + + Get Back on Magenta + gain + + + + /fdm/jsbsim/velocities/vc-kts + 14050 + 36020 +
+
+
+ /instrumentation/gps/wp/wp[1]/course-error-nm + /it-autoflight/internal/course-error-deg + -45 + 45 +
+ Heading Error Deg false @@ -428,7 +446,8 @@ - /FMGC/flightplan[2]/current-leg-course + /instrumentation/gps/wp/leg-true-course-deg + /it-autoflight/internal/course-error-deg /it-autoflight/internal/drift-angle-deg -1.0 From 9befc5ce0298145ad546929b1df114223394bd54 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Mon, 17 Jan 2022 12:55:37 +0000 Subject: [PATCH 02/52] ND: fix bug --- Models/Instruments/ND/canvas/framework/navdisplay.nas | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Models/Instruments/ND/canvas/framework/navdisplay.nas b/Models/Instruments/ND/canvas/framework/navdisplay.nas index 757757cb..931bd27d 100644 --- a/Models/Instruments/ND/canvas/framework/navdisplay.nas +++ b/Models/Instruments/ND/canvas/framework/navdisplay.nas @@ -638,8 +638,8 @@ canvas.NavDisplay.update = func() # FIXME: This stuff is still too aircraft spec } # Hide heading bug 45 secs after change - var vhdg_bug = getprop("/it-autoflight/input/hdg") or 0; - var hdg_bug_active = getprop("/it-autoflight/custom/show-hdg") or 1; + var vhdg_bug = fmgc.Input.hdg.getValue(); + var hdg_bug_active = fmgc.Custom.showHdg.getBoolValue(); if((me.in_mode("toggle_display_mode", ["MAP"]) and me.get_switch("toggle_display_type") == "CRT") or (me.get_switch("toggle_track_heading") and me.get_switch("toggle_display_type") == "LCD")) From 40a8e85d0b59ce770933cc99466cba7a93a12156 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Mon, 17 Jan 2022 14:44:39 +0000 Subject: [PATCH 03/52] The flightplan should return to the great circle path - set flag to true Change the decel code so that it only works for active flightplan. --- A320-main.xml | 3 ++ Nasal/FMGC/flightplan-delegates.nas | 29 ++++-------- Nasal/FMGC/flightplan.nas | 71 +++++++++-------------------- 3 files changed, 34 insertions(+), 69 deletions(-) diff --git a/A320-main.xml b/A320-main.xml index bdd27bd2..21e790f2 100644 --- a/A320-main.xml +++ b/A320-main.xml @@ -590,6 +590,9 @@ S + + E 4500 4500 diff --git a/Nasal/FMGC/flightplan-delegates.nas b/Nasal/FMGC/flightplan-delegates.nas index 5eb1b3de..579c436e 100644 --- a/Nasal/FMGC/flightplan-delegates.nas +++ b/Nasal/FMGC/flightplan-delegates.nas @@ -41,29 +41,24 @@ var A320GPSDeleagte = { # tell the GPS C++ code we will do sequencing ourselves, so it can disable # its legacy logic for this + setprop(GPSPath ~ '/config/delegate-sequencing', 1); # enable 2020.2 C++ turn anticipation setprop(GPSPath ~ '/config/enable-fly-by', 0); - # Set maximum lateral deviation for sequencing to 5 miles + # flyOver maximum distance setprop(GPSPath ~ '/config/over-flight-arm-distance', 5); - - # make FlightPlan behaviour match GPS config state - fp.followLegTrackToFix = getprop(GPSPath ~ '/config/follow-leg-track-to-fix') or 0; - - # similarly, make FlightPlan follow the performance category settings - fp.aircraftCategory = getprop('/autopilot/settings/icao-aircraft-category') or 'A'; - + + fp.followLegTrackToFix = 1; + fp.aircraftCategory = 'C'; m._modeProp = props.globals.getNode(GPSPath ~ '/mode'); return m; }, _landingCheckTimeout: func { - var wow = getprop('gear/gear[0]/wow'); - var gs = getprop('velocities/groundspeed-kt'); - if (wow and (gs < 25)) { + if (pts.Gear.wow[0].getValue() and pts.Velocities.groundspeed.getValue() < 25) { logprint(LOG_INFO, 'GPS saw speed < 25kts on destination runway, end of route.'); me.landingCheck.stop(); # record touch-down time? @@ -73,8 +68,7 @@ var A320GPSDeleagte = { _captureCurrentCourse: func { - var crs = getprop(GPSPath ~ "/desired-course-deg"); - setprop(GPSPath ~ "/selected-course-deg", crs); + setprop(GPSPath ~ "/selected-course-deg", getprop(GPSPath ~ "/desired-course-deg")); }, _selectOBSMode: func @@ -154,17 +148,13 @@ var A320GPSDeleagte = { } else if (mode == 'leg') { # standard leq sequencing var nextIndex = me.flightplan.current + 1; - if (nextIndex < me.flightplan.numWaypoints() and me.flightplan.nextWP().id == '(DECEL)') { - nextIndex += 1; - logprint(LOG_INFO, "default GPS reached DECEL, going to next waypoint"); - } if (nextIndex >= me.flightplan.numWaypoints()) { logprint(LOG_INFO, "default GPS sequencing, finishing flightplan"); me.flightplan.finish(); } elsif (me.flightplan.nextWP().wp_type == 'discontinuity') { logprint(LOG_INFO, "default GPS sequencing DISCONTINUITY in flightplan, switching to OBS mode"); - + # TODO - revert autopilot to hdg / vs me._captureCurrentCourse(); me._selectOBSMode(); } else { @@ -194,9 +184,8 @@ var A320GPSDeleagte = { # this check is needed to avoid problems with circular routes; when # activating the FP we end up here, and without this check, immediately # detect that we've 'landed' and finish the FP again. - var wow = getprop('gear/gear[0]/wow'); - if (!wow and + if (!pts.Gear.wow[0].getValue() and (activeRunway != nil) and (me.flightplan.destination_runway != nil) and (activeRunway.id == me.flightplan.destination_runway.id)) { diff --git a/Nasal/FMGC/flightplan.nas b/Nasal/FMGC/flightplan.nas index 8ffe08fb..4bc322e6 100644 --- a/Nasal/FMGC/flightplan.nas +++ b/Nasal/FMGC/flightplan.nas @@ -95,7 +95,9 @@ var flightPlanController = { }, loadFlightPlan: func(path) { - call(func {me.flightplans[3] = createFlightplan(path);}, nil, var err = []); + call(func { + me.flightplans[3] = createFlightplan(path); + }, nil, var err = []); if (size(err) or me.flightplans[3] == nil) { print(err[0]); print("Load failed."); @@ -275,11 +277,6 @@ var flightPlanController = { fmgc.windController.insertWind(n, index, 0, "PPOS"); }, - insertDecel: func(n, pos, index) { - me.flightplans[n].insertWP(createWP(pos, "(DECEL)"), index); - #me.flightplans[n].getWP(index).hidden = 1; - fmgc.windController.insertWind(n, index, 0, "(DECEL)"); - }, # childWPBearingDistance - return waypoint at bearing and distance from specified waypoint ghost # args: wpt, bearing, dist, name, typeStr @@ -400,8 +397,7 @@ var flightPlanController = { fmgc.windController.deleteWind(n, index); } - # if n = 2, then we are clearing a discontinuity. Don't recalculate decel. - me.flightPlanChanged(n, n == 2 ? 0 : 1); + me.flightPlanChanged(n); canvas_nd.A3XXRouteDriver.triggerSignal("fp-removed"); return 2; } else { @@ -692,68 +688,46 @@ var flightPlanController = { return count; }, - getIndexOfFirstDecel: func(plan) { - for (var wpt = 0; wpt < me.flightplans[plan].getPlanSize(); wpt += 1) { - if (me.flightplans[plan].getWP(wpt).wp_name == "(DECEL)") { - return wpt; - } - } - return -99; - }, - - calculateDecelPoint: func(n) { - if (me.getPlanSizeNoDiscont(n) <= 1 or fmgc.FMGCInternal.decel) { + calculateDecelPoint: func() { + if (me.getPlanSizeNoDiscont(2) <= 1 or fmgc.FMGCInternal.decel) { setprop("/instrumentation/nd/symbols/decel/show", 0); return; } - me.indexDecel = me.getIndexOfFirstDecel(n); - if (me.indexDecel != -99) { - me.flightplans[n].deleteWP(me.indexDecel); - fmgc.windController.deleteWind(n, me.indexDecel); - me.flightPlanChanged(n,0); - } - me.indexDecel = 0; - - for (var wpt = 0; wpt < me.flightplans[n].getPlanSize(); wpt += 1) { - if (me.flightplans[n].getWP(wpt).wp_role == "approach") { + for (var wpt = 0; wpt < me.flightplans[2].getPlanSize(); wpt += 1) { + if (me.flightplans[2].getWP(wpt).wp_role == "approach") { me.indexDecel = wpt; break; } - if (wpt == me.flightplans[n].getPlanSize()) { + if (wpt == me.flightplans[2].getPlanSize()) { me.indexDecel = me.arrivalIndex - 2; break; } } - me.dist = me.flightplans[n].getWP(me.indexDecel).leg_distance - 7; + me.dist = me.flightplans[2].getWP(me.indexDecel).leg_distance - 7; if (me.dist < 0) { me.dist = 0.1; } - me.decelPoint = me.flightplans[n].pathGeod(me.indexDecel - 1, me.dist); + me.decelPoint = me.flightplans[2].pathGeod(me.indexDecel - 1, me.dist); - if (n == 2) { - setprop("/instrumentation/nd/symbols/decel/latitude-deg", me.decelPoint.lat); - setprop("/instrumentation/nd/symbols/decel/longitude-deg", me.decelPoint.lon); - setprop("/instrumentation/nd/symbols/decel/show", 1); - } + setprop("/instrumentation/nd/symbols/decel/latitude-deg", me.decelPoint.lat); + setprop("/instrumentation/nd/symbols/decel/longitude-deg", me.decelPoint.lon); + setprop("/instrumentation/nd/symbols/decel/show", 1); me.indexTemp = me.indexDecel; me.distTemp = 7; - if (me.flightplans[n].getWP(me.indexTemp).leg_distance < 7) { + if (me.flightplans[2].getWP(me.indexTemp).leg_distance < 7) { while (me.distTemp > 0 and me.indexTemp > 0) { - me.distTemp -= me.flightplans[n].getWP(me.indexTemp).leg_distance; + me.distTemp -= me.flightplans[2].getWP(me.indexTemp).leg_distance; me.indexTemp -= 1; } me.indexTemp += 1; } - # todo add to FPLN list setprop("/instrumentation/nd/symbols/decel/index", me.indexTemp); - # me.insertDecel(n,{lat: me.decelPoint.lat, lon: me.decelPoint.lon}, me.indexTemp); - me.flightPlanChanged(n,0); }, # insertPlaceBearingDistance - insert PBD waypoint at specified index, @@ -818,9 +792,8 @@ var flightPlanController = { } }, - # callDecel - a variable that gets passed from the calling function. Used to prevent recalculating decel after discontinuity clearing - flightPlanChanged: func(n, callDecel = 1) { - me.updatePlans(1, callDecel); + flightPlanChanged: func(n) { + me.updatePlans(1); fmgc.windController.updatePlans(); # push update to fuel @@ -837,7 +810,7 @@ var flightPlanController = { }, # runDecel - used to ensure that only flightplanchanged will update the decel point - updatePlans: func(runDecel = 0, callDecel = 1) { + updatePlans: func(runDecel = 0) { if (fmgc.FMGCInternal.toFromSet and me.flightplans[2].departure != nil and me.flightplans[2].destination != nil) { # check if flightplan exists if (!me.active.getBoolValue()) { if (me.currentToWptIndex.getValue() < 1) { @@ -869,10 +842,10 @@ var flightPlanController = { } } } + } - if (runDecel and callDecel) { - me.calculateDecelPoint(n); - } + if (runDecel) { + me.calculateDecelPoint(); } for (var i = 0; i <= 1; i += 1) { From bdd69e51a4c760a1bb582f7cf0367718a28fe8ff Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Mon, 17 Jan 2022 15:59:47 +0000 Subject: [PATCH 04/52] Disallow left select key for pseudo waypoints --- Nasal/MCDU/F-PLN.nas | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Nasal/MCDU/F-PLN.nas b/Nasal/MCDU/F-PLN.nas index 88ad8256..11ecd46a 100644 --- a/Nasal/MCDU/F-PLN.nas +++ b/Nasal/MCDU/F-PLN.nas @@ -548,14 +548,18 @@ var fplnPage = { # this one is only created once, and then updated - remember th setprop("MCDU[" ~ me.computer ~ "]/page", "LATREV"); } } else { - if (size(me.outputList) >= index and !mcdu_scratchpad.scratchpads[me.computer].showTypeIMsg and !mcdu_scratchpad.scratchpads[me.computer].showTypeIIMsg) { + if (me.outputList[index - 1 + me.scroll].wp != "PSEUDO" and size(me.outputList) >= index and !mcdu_scratchpad.scratchpads[me.computer].showTypeIMsg and !mcdu_scratchpad.scratchpads[me.computer].showTypeIIMsg) { if (size(mcdu_scratchpad.scratchpads[me.computer].scratchpad) > 0) { - if (mcdu_scratchpad.scratchpads[me.computer].scratchpad == "CLR") { - if (me.outputList[index - 1 + me.scroll].wp.wp_name == "(DECEL)") { - mcdu_message(me.computer, "NOT ALLOWED"); - return; + if (!me.temporaryFlagFpln) { + var decelIndex = 9999; + if (fmgc.flightPlanController.decelPoint != nil) { + decelIndex = getprop("/instrumentation/nd/symbols/decel/index"); + } + if ((index - 1 + me.scroll) > decelIndex) { + index = index - 1; } } + var returny = fmgc.flightPlanController.scratchpad(mcdu_scratchpad.scratchpads[me.computer].scratchpad, (index - 1 + me.scroll), me.computer); if (returny == 3) { mcdu_message(me.computer, "DIR TO IN PROGRESS"); From bb622b661d9d0512402e539859c53a071a5279ac Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Tue, 18 Jan 2022 11:51:22 +0000 Subject: [PATCH 05/52] Dirto : improve --- Nasal/FMGC/flightplan.nas | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Nasal/FMGC/flightplan.nas b/Nasal/FMGC/flightplan.nas index 4bc322e6..97cd4156 100644 --- a/Nasal/FMGC/flightplan.nas +++ b/Nasal/FMGC/flightplan.nas @@ -155,6 +155,11 @@ var flightPlanController = { if (canvas_mcdu.myDirTo[n] != nil) { canvas_mcdu.myDirTo[n].updateTmpy(); } + if (me.DirToIndex != nil) { + me.currentToWptIndex.setValue(me.DirToIndex); + me.DirToIndex = nil; + } + fmgc.windController.destroyTemporaryWinds(n, a); me.flightPlanChanged(n); }, @@ -344,6 +349,7 @@ var flightPlanController = { # In either case, we delete the current FROM waypoint, index 0, and call flightPlanChanged to recalculate # We attempt to get the distance from the aircraft current position to the chosen waypoint and update mcdu with it + DirToIndex: nil, directTo: func(waypointGhost, plan) { if (me.flightplans[plan].indexOfWP(waypointGhost) == -1) { me.insertTP(plan, me.currentToWptIndex.getValue()); @@ -353,8 +359,7 @@ var flightPlanController = { me.flightplans[plan].insertWP(createWP(waypointGhost, waypointGhost.id), me.currentToWptIndex.getValue() + 1); fmgc.windController.insertWind(plan, me.currentToWptIndex.getValue() + 1, 0, waypointGhost.id); me.addDiscontinuity(me.currentToWptIndex.getValue() + 2, plan); - print(me.currentToWptIndex.getValue()); - me.currentToWptIndex.setValue(me.currentToWptIndex.getValue() + 1); + me.DirToIndex = me.currentToWptIndex.getValue() + 1; } else { # we want to delete the intermediate waypoints up to but not including the waypoint. Leave index 0, we delete it later. # example - waypoint dirto is index 5, we want to delete indexes 1 -> 4. 5 - 1 = 4. @@ -362,8 +367,6 @@ var flightPlanController = { var indexWP = me.flightplans[plan].indexOfWP(waypointGhost); - print(indexWP); - me.insertTP(plan, indexWP - 1); for (var i = 0; i < indexWP - 1; i = i + 1) { if (me.temporaryFlag[0]) { From 28b7d17dfc1b50d2851bf25c0700f849a6bd2346 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Tue, 18 Jan 2022 12:25:01 +0000 Subject: [PATCH 06/52] Prevent flightgear crash when clearing discontinuity in empty plan --- Nasal/FMGC/flightplan.nas | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Nasal/FMGC/flightplan.nas b/Nasal/FMGC/flightplan.nas index 97cd4156..c9cc2e91 100644 --- a/Nasal/FMGC/flightplan.nas +++ b/Nasal/FMGC/flightplan.nas @@ -761,6 +761,9 @@ var flightPlanController = { if (!me.temporaryFlag[plan]) { if (text == "CLR" and me.flightplans[2].getWP(index).wp_name == "DISCONTINUITY") { + if (me.flightplans[2].getPlanSize() == 3 and me.flightplans[2].departure_runway == nil and me.flightplans[2].destination_runway == nil and index == 1) { + return 1; + } var thePlan = 2; } else { fmgc.flightPlanController.createTemporaryFlightPlan(plan); From 1fbabe8fe27478176857b58e56a2b854b93ce54b Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Tue, 18 Jan 2022 12:46:08 +0000 Subject: [PATCH 07/52] Distance tracker - account for discontinuity, decel, format width --- Nasal/MCDU/F-PLN.nas | 45 ++++++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/Nasal/MCDU/F-PLN.nas b/Nasal/MCDU/F-PLN.nas index 11ecd46a..cd992750 100644 --- a/Nasal/MCDU/F-PLN.nas +++ b/Nasal/MCDU/F-PLN.nas @@ -47,9 +47,9 @@ var fplnItem = { } if (me.index == fmgc.flightPlanController.currentToWptIndex.getValue()) { - me.assembledStr[1] = "BRG" ~ me.getBrg() ~ " "; + me.assembledStr[1] = "BRG" ~ me.getBrg() ~ "° "; } elsif (me.index == (fmgc.flightPlanController.currentToWptIndex.getValue() + 1) or me.index == (fmgc.flightPlanController.arrivalIndex[me.plan] + 1)) { - me.assembledStr[1] = "TRK" ~ me.getTrack() ~ " "; + me.assembledStr[1] = "TRK" ~ me.getTrack() ~ "° "; } else { me.assembledStr[1] = nil; } @@ -67,7 +67,6 @@ var fplnItem = { if (me.wp.wp_name != "DISCONTINUITY") { me.spd = me.getSpd(); me.alt = me.getAlt(); - me.dist = me.getDist(); if (me.colour != "yel") { # not temporary flightplan me._colour = "wht"; #if (me.spd[1] != "wht" or me.alt[1] != "wht") { @@ -84,7 +83,7 @@ var fplnItem = { } else { # temporary flightplan me._colour = "yel"; } - return [me.spd[0] ~ "/" ~ me.alt[0], " " ~ me.dist ~ "NM ", me._colour]; + return [me.spd[0] ~ "/" ~ me.alt[0], me.getDist() ~ "NM ", me._colour]; } else { return [nil, nil, "ack"]; } @@ -140,12 +139,20 @@ var fplnItem = { } }, getDist: func() { + decelIndex = getprop("/instrumentation/nd/symbols/decel/index") or -9; var wp = fmgc.flightPlanController.flightplans[me.plan].getWP(me.index); + var prevwp = fmgc.flightPlanController.flightplans[me.plan].getWP(me.index -1); + if (me.index == fmgc.flightPlanController.currentToWptIndex.getValue()) { - var courseDistanceFrom = courseAndDistance(wp); - return math.round(courseDistanceFrom[1]); + return sprintf("%3.0f", math.round(courseAndDistance(wp)[1]));; } else { - return math.round(wp.leg_distance); + if (decelIndex != 9 and me.index == decelIndex + 1 and fmgc.flightPlanController.decelPoint != nil) { + return sprintf("%3.0f", courseAndDistance(fmgc.flightPlanController.decelPoint, wp)[1]); + } else if (prevwp != nil and prevwp.wp_name != "DISCONTINUITY") { + return sprintf("%3.0f", math.round(wp.leg_distance)); + } else { + return " --"; + } } }, pushButtonLeft: func() { @@ -300,10 +307,21 @@ var pseudoItem = { return [me.text, nil, me.colour]; }, updateCenterText: func() { - return ["----", nil, "wht"]; + return ["---- ", nil, "wht"]; + }, + getDist: func() { + decelIndex = getprop("/instrumentation/nd/symbols/decel/index") or -9; + if (decelIndex != -9) { + var prevWP = fmgc.flightPlanController.flightplans[2].getWP(decelIndex - 1); + if (prevWP != nil and prevWP.wp_name != "DISCONTINUITY" and fmgc.flightPlanController.decelPoint != nil) { + return sprintf("%3.0f", courseAndDistance(prevWP, fmgc.flightPlanController.decelPoint)[1]); + } else { + return " --"; + } + } }, updateRightText: func() { - return ["---/------", " --NM ", "wht"]; + return ["---/------", me.getDist() ~ "NM ", "wht"]; }, pushButtonLeft: func() { mcdu_message(me.computer, "NOT ALLOWED"); @@ -383,7 +401,6 @@ var fplnPage = { # this one is only created once, and then updated - remember th colour = "grn"; } - var decelIndex = -9; if (fmgc.flightPlanController.decelPoint != nil) { decelIndex = getprop("/instrumentation/nd/symbols/decel/index") or -9; @@ -400,7 +417,11 @@ var fplnPage = { # this one is only created once, and then updated - remember th if (!me.temporaryFlagFpln and i > fmgc.flightPlanController.arrivalIndex[me.planIndex] and fmgc.FMGCInternal.phase != 6) { append(me.planList, fplnItem.new(me.plan.getWP(i), i, me.planIndex, me.computer, "blu")); } else { - append(me.planList, fplnItem.new(me.plan.getWP(i), i, me.planIndex, me.computer, colour)); + if (i == fmgc.flightPlanController.currentToWptIndex.getValue() and !me.temporaryFlagFpln) { + append(me.planList, fplnItem.new(me.plan.getWP(i), i, me.planIndex, me.computer, "wht")); + } else { + append(me.planList, fplnItem.new(me.plan.getWP(i), i, me.planIndex, me.computer, colour)); + } } } @@ -548,7 +569,7 @@ var fplnPage = { # this one is only created once, and then updated - remember th setprop("MCDU[" ~ me.computer ~ "]/page", "LATREV"); } } else { - if (me.outputList[index - 1 + me.scroll].wp != "PSEUDO" and size(me.outputList) >= index and !mcdu_scratchpad.scratchpads[me.computer].showTypeIMsg and !mcdu_scratchpad.scratchpads[me.computer].showTypeIIMsg) { + if ((index - 1 + me.scroll) <= size(me.outputList) and me.outputList[index - 1 + me.scroll].wp != nil and me.outputList[index - 1 + me.scroll].wp != "PSEUDO" and !mcdu_scratchpad.scratchpads[me.computer].showTypeIMsg and !mcdu_scratchpad.scratchpads[me.computer].showTypeIIMsg) { if (size(mcdu_scratchpad.scratchpads[me.computer].scratchpad) > 0) { if (!me.temporaryFlagFpln) { var decelIndex = 9999; From 96737107b95ea9ccb1ddc437c325fec982bd3482 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Tue, 18 Jan 2022 16:05:27 +0000 Subject: [PATCH 08/52] Fix DECEL distance prompt --- Models/Instruments/MCDU/MCDU.nas | 18 +++--------------- Nasal/MCDU/F-PLN.nas | 9 ++++----- 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/Models/Instruments/MCDU/MCDU.nas b/Models/Instruments/MCDU/MCDU.nas index f0bb3abd..9e60f520 100644 --- a/Models/Instruments/MCDU/MCDU.nas +++ b/Models/Instruments/MCDU/MCDU.nas @@ -201,11 +201,13 @@ var canvas_MCDU_base = { me["Simple_L6S"].setFont("HoneywellMCDUSmall.ttf"); me["Simple_C1S"].setFont("HoneywellMCDUSmall.ttf"); me["Simple_C2S"].setFont("HoneywellMCDUSmall.ttf"); + me["Simple_C3S"].setFont("HoneywellMCDUSmall.ttf"); me["Simple_C4S"].setFont("HoneywellMCDUSmall.ttf"); me["Simple_C5S"].setFont("HoneywellMCDUSmall.ttf"); me["Simple_C6S"].setFont("HoneywellMCDUSmall.ttf"); me["Simple_R1S"].setFont("HoneywellMCDUSmall.ttf"); me["Simple_R2S"].setFont("HoneywellMCDUSmall.ttf"); + me["Simple_R3S"].setFont("HoneywellMCDUSmall.ttf"); me["Simple_R4S"].setFont("HoneywellMCDUSmall.ttf"); me["Simple_R5S"].setFont("HoneywellMCDUSmall.ttf"); me["Simple_R6S"].setFont("HoneywellMCDUSmall.ttf"); @@ -491,9 +493,7 @@ var canvas_MCDU_base = { me.hideAllArrows(); - me.fontSizeLeft(normal, normal, normal, normal, normal, normal); - me.fontSizeCenter(normal, normal, normal, normal, normal, normal); - me.fontSizeRight(normal, normal, normal, normal, normal, normal); + me.standardFontSize(); pageSwitch[i].setBoolValue(1); } @@ -3539,18 +3539,6 @@ var canvas_MCDU_base = { me["Simple_L2"].setText(fmgc.FMGCInternal.altAirport); } - me["Simple_L1S"].setFont("HoneywellMCDUSmall.ttf"); - me["Simple_L3S"].setFont("HoneywellMCDUSmall.ttf"); - me["Simple_L4S"].setFont("HoneywellMCDUSmall.ttf"); - me["Simple_L5S"].setFont("HoneywellMCDUSmall.ttf"); - me["Simple_L6S"].setFont("HoneywellMCDUSmall.ttf"); - me["Simple_C1S"].setFont("HoneywellMCDUSmall.ttf"); - me["Simple_R1S"].setFont("HoneywellMCDUSmall.ttf"); - me["Simple_R3S"].setFont("HoneywellMCDUSmall.ttf"); - me["Simple_R4S"].setFont("HoneywellMCDUSmall.ttf"); - me["Simple_R5S"].setFont("HoneywellMCDUSmall.ttf"); - me["Simple_R6S"].setFont("HoneywellMCDUSmall.ttf"); - me["Simple_L1S"].setText("AT"); me["Simple_L3S"].setText("RTE RSV/%"); me["Simple_L4S"].setText("ALTN /TIME"); diff --git a/Nasal/MCDU/F-PLN.nas b/Nasal/MCDU/F-PLN.nas index cd992750..9b777ea7 100644 --- a/Nasal/MCDU/F-PLN.nas +++ b/Nasal/MCDU/F-PLN.nas @@ -140,16 +140,15 @@ var fplnItem = { }, getDist: func() { decelIndex = getprop("/instrumentation/nd/symbols/decel/index") or -9; - var wp = fmgc.flightPlanController.flightplans[me.plan].getWP(me.index); var prevwp = fmgc.flightPlanController.flightplans[me.plan].getWP(me.index -1); if (me.index == fmgc.flightPlanController.currentToWptIndex.getValue()) { - return sprintf("%3.0f", math.round(courseAndDistance(wp)[1]));; + return sprintf("%3.0f", math.round(courseAndDistance(me.wp)[1]));; } else { - if (decelIndex != 9 and me.index == decelIndex + 1 and fmgc.flightPlanController.decelPoint != nil) { - return sprintf("%3.0f", courseAndDistance(fmgc.flightPlanController.decelPoint, wp)[1]); + if (decelIndex != 9 and me.index == decelIndex and fmgc.flightPlanController.decelPoint != nil) { + return sprintf("%3.0f", courseAndDistance(fmgc.flightPlanController.decelPoint, me.wp)[1]); } else if (prevwp != nil and prevwp.wp_name != "DISCONTINUITY") { - return sprintf("%3.0f", math.round(wp.leg_distance)); + return sprintf("%3.0f", math.round(me.wp.leg_distance)); } else { return " --"; } From f2e3cf2cad1649336ca1ffdac3f5d4385977e180 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Tue, 18 Jan 2022 19:54:27 +0000 Subject: [PATCH 09/52] Decel: fix plan index --- Nasal/MCDU/F-PLN.nas | 49 +++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/Nasal/MCDU/F-PLN.nas b/Nasal/MCDU/F-PLN.nas index 9b777ea7..3b4b5e51 100644 --- a/Nasal/MCDU/F-PLN.nas +++ b/Nasal/MCDU/F-PLN.nas @@ -139,13 +139,14 @@ var fplnItem = { } }, getDist: func() { - decelIndex = getprop("/instrumentation/nd/symbols/decel/index") or -9; + decelIndex = getprop("/instrumentation/nd/symbols/decel/index"); + decelShow = getprop("/instrumentation/nd/symbols/decel/show"); var prevwp = fmgc.flightPlanController.flightplans[me.plan].getWP(me.index -1); if (me.index == fmgc.flightPlanController.currentToWptIndex.getValue()) { return sprintf("%3.0f", math.round(courseAndDistance(me.wp)[1]));; } else { - if (decelIndex != 9 and me.index == decelIndex and fmgc.flightPlanController.decelPoint != nil) { + if (decelShow and me.index == decelIndex and fmgc.flightPlanController.decelPoint != nil) { return sprintf("%3.0f", courseAndDistance(fmgc.flightPlanController.decelPoint, me.wp)[1]); } else if (prevwp != nil and prevwp.wp_name != "DISCONTINUITY") { return sprintf("%3.0f", math.round(me.wp.leg_distance)); @@ -309,10 +310,11 @@ var pseudoItem = { return ["---- ", nil, "wht"]; }, getDist: func() { - decelIndex = getprop("/instrumentation/nd/symbols/decel/index") or -9; - if (decelIndex != -9) { + decelIndex = getprop("/instrumentation/nd/symbols/decel/index"); + decelShow = getprop("/instrumentation/nd/symbols/decel/show"); + if (decelShow) { var prevWP = fmgc.flightPlanController.flightplans[2].getWP(decelIndex - 1); - if (prevWP != nil and prevWP.wp_name != "DISCONTINUITY" and fmgc.flightPlanController.decelPoint != nil) { + if (prevWP != nil and prevWP.wp_name != "DISCONTINUITY") { return sprintf("%3.0f", courseAndDistance(prevWP, fmgc.flightPlanController.decelPoint)[1]); } else { return " --"; @@ -400,14 +402,12 @@ var fplnPage = { # this one is only created once, and then updated - remember th colour = "grn"; } - var decelIndex = -9; - if (fmgc.flightPlanController.decelPoint != nil) { - decelIndex = getprop("/instrumentation/nd/symbols/decel/index") or -9; - } + decelIndex = getprop("/instrumentation/nd/symbols/decel/index"); + decelShow = getprop("/instrumentation/nd/symbols/decel/show"); var startingIndex = fmgc.flightPlanController.currentToWptIndex.getValue() == -1 ? 0 : fmgc.flightPlanController.currentToWptIndex.getValue() - 1; for (var i = startingIndex; i < me.plan.getPlanSize(); i += 1) { - if (!me.temporaryFlagFpln and decelIndex != -9) { + if (!me.temporaryFlagFpln and decelShow) { if (i == decelIndex) { append(me.planList, pseudoItem.new(me.computer, me.getText("decel"), colour)); } @@ -520,15 +520,26 @@ var fplnPage = { # this one is only created once, and then updated - remember th update: func() { #me.basePage(); }, + planIndexFunc: func() { + decelIndex = getprop("/instrumentation/nd/symbols/decel/index"); + decelShow = getprop("/instrumentation/nd/symbols/decel/show"); + if (me.scroll < me.plan.getPlanSize()) { + if (decelShow) { + var decelOffset = 0; + if (me.scroll > decelIndex) { + decelOffset = 1; + } + setprop("/instrumentation/efis[" ~ me.computer ~ "]/inputs/plan-wpt-index", me.scroll - decelOffset); + } + } + }, scrollUp: func() { if (size(me.planList) > 1) { me.scroll += 1; if (me.scroll > size(me.planList) - 3) { me.scroll = 0; } - if (me.scroll < me.plan.getPlanSize()) { - setprop("/instrumentation/efis[" ~ me.computer ~ "]/inputs/plan-wpt-index", me.scroll); - } + me.planIndexFunc(); } else { me.scroll = 0; setprop("/instrumentation/efis[" ~ me.computer ~ "]/inputs/plan-wpt-index", -1); @@ -540,9 +551,7 @@ var fplnPage = { # this one is only created once, and then updated - remember th if (me.scroll < 0) { me.scroll = size(me.planList) - 3; } - if (me.scroll < me.plan.getPlanSize()) { - setprop("/instrumentation/efis[" ~ me.computer ~ "]/inputs/plan-wpt-index", me.scroll); - } + me.planIndexFunc(); } else { me.scroll = 0; setprop("/instrumentation/efis[" ~ me.computer ~ "]/inputs/plan-wpt-index", -1); @@ -571,11 +580,9 @@ var fplnPage = { # this one is only created once, and then updated - remember th if ((index - 1 + me.scroll) <= size(me.outputList) and me.outputList[index - 1 + me.scroll].wp != nil and me.outputList[index - 1 + me.scroll].wp != "PSEUDO" and !mcdu_scratchpad.scratchpads[me.computer].showTypeIMsg and !mcdu_scratchpad.scratchpads[me.computer].showTypeIIMsg) { if (size(mcdu_scratchpad.scratchpads[me.computer].scratchpad) > 0) { if (!me.temporaryFlagFpln) { - var decelIndex = 9999; - if (fmgc.flightPlanController.decelPoint != nil) { - decelIndex = getprop("/instrumentation/nd/symbols/decel/index"); - } - if ((index - 1 + me.scroll) > decelIndex) { + decelIndex = getprop("/instrumentation/nd/symbols/decel/index"); + decelShow = getprop("/instrumentation/nd/symbols/decel/show"); + if (decelShow and (index - 1 + me.scroll) > decelIndex) { index = index - 1; } } From c87ab00335c35f028b01df1e060b2532b6f248c1 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Tue, 18 Jan 2022 20:11:31 +0000 Subject: [PATCH 10/52] Fix indices --- Nasal/MCDU/F-PLN.nas | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Nasal/MCDU/F-PLN.nas b/Nasal/MCDU/F-PLN.nas index 3b4b5e51..004f5769 100644 --- a/Nasal/MCDU/F-PLN.nas +++ b/Nasal/MCDU/F-PLN.nas @@ -275,6 +275,7 @@ var staticText = { var sT = {parents:[staticText]}; sT.computer = computer; sT.text = text; + sT.wp = "STATIC"; return sT; }, updateLeftText: func() { @@ -577,7 +578,7 @@ var fplnPage = { # this one is only created once, and then updated - remember th setprop("MCDU[" ~ me.computer ~ "]/page", "LATREV"); } } else { - if ((index - 1 + me.scroll) <= size(me.outputList) and me.outputList[index - 1 + me.scroll].wp != nil and me.outputList[index - 1 + me.scroll].wp != "PSEUDO" and !mcdu_scratchpad.scratchpads[me.computer].showTypeIMsg and !mcdu_scratchpad.scratchpads[me.computer].showTypeIIMsg) { + if ((index - 1 + me.scroll) < size(me.planList) and me.outputList[index - 1].wp != "STATIC" and me.outputList[index - 1].wp != "PSEUDO" and !mcdu_scratchpad.scratchpads[me.computer].showTypeIMsg and !mcdu_scratchpad.scratchpads[me.computer].showTypeIIMsg) { if (size(mcdu_scratchpad.scratchpads[me.computer].scratchpad) > 0) { if (!me.temporaryFlagFpln) { decelIndex = getprop("/instrumentation/nd/symbols/decel/index"); From 5dc44bbff39458c30c3c3cbea6ee488baefcc9ed Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Wed, 19 Jan 2022 11:04:37 +0000 Subject: [PATCH 11/52] Discontinuities: revert to HDG mode. Various TODO still. --- Nasal/FMGC/FCU.nas | 5 ++++- Nasal/FMGC/FMGC-b.nas | 4 ++++ Nasal/FMGC/flightplan-delegates.nas | 2 ++ Nasal/FMGC/flightplan.nas | 19 +++++++++++++------ 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/Nasal/FMGC/FCU.nas b/Nasal/FMGC/FCU.nas index 334c5c9c..f40183cf 100644 --- a/Nasal/FMGC/FCU.nas +++ b/Nasal/FMGC/FCU.nas @@ -263,7 +263,10 @@ var FCUController = { HDGPush: func() { if (me.FCUworking) { if (fmgc.Output.fd1.getBoolValue() or fmgc.Output.fd2.getBoolValue() or fmgc.Output.ap1.getBoolValue() or fmgc.Output.ap2.getBoolValue()) { - fmgc.Input.lat.setValue(1); + var wp = fmgc.flightPlanController.flightplans[2].getWP(fmgc.flightPlanController.currentToWptIndex.getValue() + 1); + if (wp != nil and wp.wp_type != "discontinuity") { + fmgc.Input.lat.setValue(1); + } } } }, diff --git a/Nasal/FMGC/FMGC-b.nas b/Nasal/FMGC/FMGC-b.nas index fa0bf517..4eb4aaad 100644 --- a/Nasal/FMGC/FMGC-b.nas +++ b/Nasal/FMGC/FMGC-b.nas @@ -429,6 +429,10 @@ var ITAF = { # This is removed because sequencing is done by the flightplan controller # Internal.lnavAdvanceNm.setValue(FPLN.turnDist); + # TODO - if the waypoint is the DEST waypoint, crosstrack error must be less than 0.5nm and course error less than 30 deg + # TODO - if in HDG mode, if no distance, then crosstrack error must be less than 5nm + # TODO - if in nav, no distance condition applies, but DEST course error must be less than 30 (CONFIRM) + if (FPLN.wp0Dist.getValue() <= FPLN.turnDist and !Gear.wow1.getBoolValue() and fmgc.flightPlanController.flightplans[2].getWP(FPLN.currentWPTemp).fly_type == "flyBy") { flightPlanController.autoSequencing(); } elsif (FPLN.wp0Dist.getValue() <= 0.15) { diff --git a/Nasal/FMGC/flightplan-delegates.nas b/Nasal/FMGC/flightplan-delegates.nas index 579c436e..5fa00820 100644 --- a/Nasal/FMGC/flightplan-delegates.nas +++ b/Nasal/FMGC/flightplan-delegates.nas @@ -126,6 +126,8 @@ var A320GPSDeleagte = { sequence: func { + return; + if (!me.flightplan.active) return; #flightPlanController.autoSequencing(); diff --git a/Nasal/FMGC/flightplan.nas b/Nasal/FMGC/flightplan.nas index c9cc2e91..94c4424f 100644 --- a/Nasal/FMGC/flightplan.nas +++ b/Nasal/FMGC/flightplan.nas @@ -209,12 +209,19 @@ var flightPlanController = { # Advancing logic me.currentToWptIndexTemp = me.currentToWptIndex.getValue(); - me.currentToWptIndex.setValue(me.currentToWptIndexTemp + 1); + # TODO - after sequencing discontinuity, FPLN should show PPOS then DISCONTINUITY + # Clearing that discontinuity is not allowed, you must exit using DIRTO, or else using NAV ARM and overfly + # TODO - triple click - confirm, is it only with DES disengage, or also with the NAV loss? - if (me.num[2].getValue() > 2 and me.currentToWptIndexTemp >= 1) { - for (var i = 0; i <= 2; i += 1) { - if (i == 2 or me.temporaryFlag[i]) { - me.flightplans[i].getWP(me.currentToWptIndexTemp - 1).hidden = 1; + if (me.flightplans[2].getWP(me.currentToWptIndexTemp + 1).wp_type == "discontinuity") { + fmgc.Input.lat.setValue(3); + } else { + me.currentToWptIndex.setValue(me.currentToWptIndexTemp + 1); + if (me.num[2].getValue() > 2 and me.currentToWptIndexTemp >= 1) { + for (var i = 0; i <= 2; i += 1) { + if (i == 2 or me.temporaryFlag[i]) { + me.flightplans[i].getWP(me.currentToWptIndexTemp - 1).hidden = 1; + } } } } @@ -823,7 +830,7 @@ var flightPlanController = { var errs = []; call(func { me.currentToWptIndex.setValue(1); - }, nil, nil, nil,errs); + }, nil, nil, nil, errs); if (size(errs) != 0) { debug.printerror(errs); } } me.active.setValue(1); From 1364fa304baee6e44b841779307a18faacd6f37e Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Wed, 19 Jan 2022 16:48:20 +0000 Subject: [PATCH 12/52] fix typo --- Nasal/FMGC/flightplan.nas | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Nasal/FMGC/flightplan.nas b/Nasal/FMGC/flightplan.nas index 94c4424f..5ee910ab 100644 --- a/Nasal/FMGC/flightplan.nas +++ b/Nasal/FMGC/flightplan.nas @@ -212,6 +212,7 @@ var flightPlanController = { # TODO - after sequencing discontinuity, FPLN should show PPOS then DISCONTINUITY # Clearing that discontinuity is not allowed, you must exit using DIRTO, or else using NAV ARM and overfly # TODO - triple click - confirm, is it only with DES disengage, or also with the NAV loss? + # TODO - I think that it only goes to VS when in DES mode if (me.flightplans[2].getWP(me.currentToWptIndexTemp + 1).wp_type == "discontinuity") { fmgc.Input.lat.setValue(3); @@ -380,7 +381,7 @@ var flightPlanController = { me.deleteWP(i, 0, 1); } if (me.temporaryFlag[1]) { - me.deleteWP(i, 0, 1); + me.deleteWP(i, 1, 1); } me.deleteWP(i, 2, 1); } From 1bf9e313f7804cef9f354d183a3cd8c0e35c86d0 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Thu, 20 Jan 2022 17:34:14 +0000 Subject: [PATCH 13/52] Prevent flyBy with courseDelta > 120. Todo confirm this. Among many other things. --- Nasal/FMGC/FMGC-b.nas | 8 ++++- Nasal/FMGC/flightplan-delegates.nas | 45 ----------------------------- Nasal/FMGC/flightplan.nas | 23 ++++----------- Nasal/MCDU/F-PLN.nas | 11 ++----- 4 files changed, 15 insertions(+), 72 deletions(-) diff --git a/Nasal/FMGC/FMGC-b.nas b/Nasal/FMGC/FMGC-b.nas index 4eb4aaad..02455aef 100644 --- a/Nasal/FMGC/FMGC-b.nas +++ b/Nasal/FMGC/FMGC-b.nas @@ -433,7 +433,13 @@ var ITAF = { # TODO - if in HDG mode, if no distance, then crosstrack error must be less than 5nm # TODO - if in nav, no distance condition applies, but DEST course error must be less than 30 (CONFIRM) - if (FPLN.wp0Dist.getValue() <= FPLN.turnDist and !Gear.wow1.getBoolValue() and fmgc.flightPlanController.flightplans[2].getWP(FPLN.currentWPTemp).fly_type == "flyBy") { + var enableFlyBy = 0; + var maxCourseDelta = 120; + if (abs(fmgc.flightPlanController.flightplans[2].getWP(FPLN.currentWPTemp).leg_bearing - fmgc.flightPlanController.flightplans[2].getWP(FPLN.currentWPTemp + 1).leg_bearing) < maxCourseDelta) { + enableFlyBy = 1; + } + + if (enableFlyBy and FPLN.wp0Dist.getValue() <= FPLN.turnDist and !Gear.wow1.getBoolValue() and fmgc.flightPlanController.flightplans[2].getWP(FPLN.currentWPTemp).fly_type == "flyBy") { flightPlanController.autoSequencing(); } elsif (FPLN.wp0Dist.getValue() <= 0.15) { flightPlanController.autoSequencing(); diff --git a/Nasal/FMGC/flightplan-delegates.nas b/Nasal/FMGC/flightplan-delegates.nas index 5fa00820..377e424f 100644 --- a/Nasal/FMGC/flightplan-delegates.nas +++ b/Nasal/FMGC/flightplan-delegates.nas @@ -87,11 +87,6 @@ var A320GPSDeleagte = { logprint(LOG_INFO,'flightplan activated, default GPS to LEG mode'); setprop(GPSPath ~ "/command", "leg"); - - if (getprop(GPSPath ~ '/wp/wp[1]/from-flag')) { - logprint(LOG_INFO, '\tat GPS activation, already passed active WP, sequencing'); - me.sequence(); - } }, deactivated: func @@ -127,46 +122,6 @@ var A320GPSDeleagte = { sequence: func { return; - - if (!me.flightplan.active) - return; - #flightPlanController.autoSequencing(); - var mode = me._modeProp.getValue(); - if (mode == 'dto') { - # direct-to is done, check if we should resume the following leg - var index = me.flightplan.indexOfWP(getprop(GPSPath ~ '/wp/wp[1]/latitude-deg'), - getprop(GPSPath ~ '/wp/wp[1]/longitude-deg')); - if (index >= 0) { - logprint(LOG_INFO, "default GPS reached Direct-To, resuming FP leg at " ~ index); - me.flightplan.current = index + 1; - setprop(GPSPath ~ "/command", "leg"); - } else { - # revert to OBS mode - logprint(LOG_INFO, "default GPS reached Direct-To, resuming to OBS"); - - me._captureCurrentCourse(); - me._selectOBSMode(); - } - } else if (mode == 'leg') { - # standard leq sequencing - var nextIndex = me.flightplan.current + 1; - - if (nextIndex >= me.flightplan.numWaypoints()) { - logprint(LOG_INFO, "default GPS sequencing, finishing flightplan"); - me.flightplan.finish(); - } elsif (me.flightplan.nextWP().wp_type == 'discontinuity') { - logprint(LOG_INFO, "default GPS sequencing DISCONTINUITY in flightplan, switching to OBS mode"); - # TODO - revert autopilot to hdg / vs - me._captureCurrentCourse(); - me._selectOBSMode(); - } else { - logprint(LOG_INFO, "default GPS sequencing to next WP"); - me.flightplan.current = nextIndex; - } - } else { - # OBS, do nothing - } - }, currentWaypointChanged: func diff --git a/Nasal/FMGC/flightplan.nas b/Nasal/FMGC/flightplan.nas index 5ee910ab..66965495 100644 --- a/Nasal/FMGC/flightplan.nas +++ b/Nasal/FMGC/flightplan.nas @@ -369,36 +369,23 @@ var flightPlanController = { me.addDiscontinuity(me.currentToWptIndex.getValue() + 2, plan); me.DirToIndex = me.currentToWptIndex.getValue() + 1; } else { - # we want to delete the intermediate waypoints up to but not including the waypoint. Leave index 0, we delete it later. - # example - waypoint dirto is index 5, we want to delete indexes 1 -> 4. 5 - 1 = 4. - # so four individual deletions. Delete index 1 four times. - var indexWP = me.flightplans[plan].indexOfWP(waypointGhost); - + me.deleteTillIndex(waypointGhost, me.currentToWptIndex.getValue(), plan); me.insertTP(plan, indexWP - 1); - for (var i = 0; i < indexWP - 1; i = i + 1) { - if (me.temporaryFlag[0]) { - me.deleteWP(i, 0, 1); - } - if (me.temporaryFlag[1]) { - me.deleteWP(i, 1, 1); - } - me.deleteWP(i, 2, 1); - } } var curAircraftPosDirTo = geo.aircraft_position(); canvas_mcdu.myDirTo[plan].updateDist(me.flightplans[plan].getWP(me.currentToWptIndex.getValue() + 1).courseAndDistanceFrom(curAircraftPosDirTo)[1]); me.flightPlanChanged(plan); }, - deleteWP: func(index, n, a = 0, s = 0) { # a = 1, means adding a waypoint via deleting intermediate. s = 1, means autosequencing + deleteWP: func(index, n, a = 0) { # a = 1, means adding a waypoint via deleting intermediate var wp = me.flightplans[n].getWP(index); - if (((s == 0 and left(wp.wp_name, 4) != FMGCInternal.depApt and left(wp.wp_name, 4) != FMGCInternal.arrApt) or (s == 1)) and me.flightplans[n].getPlanSize() > 2) { + if ((left(wp.wp_name, 4) != FMGCInternal.depApt and left(wp.wp_name, 4) != FMGCInternal.arrApt) and me.flightplans[n].getPlanSize() > 2) { if (me.flightplans[n].getWP(index).id != "DISCONTINUITY" and a == 0) { # if it is a discont, don't make a new one me.flightplans[n].deleteWP(index); fmgc.windController.deleteWind(n, index); - if (me.flightplans[n].getWP(index) != nil and s == 0) { + if (me.flightplans[n].getWP(index) != nil) { if (me.flightplans[n].getWP(index).id != "DISCONTINUITY") { # else, if the next one isn't a discont, add one me.addDiscontinuity(index, n); } @@ -767,6 +754,7 @@ var flightPlanController = { return 3; } + if (!me.temporaryFlag[plan]) { if (text == "CLR" and me.flightplans[2].getWP(index).wp_name == "DISCONTINUITY") { if (me.flightplans[2].getPlanSize() == 3 and me.flightplans[2].departure_runway == nil and me.flightplans[2].destination_runway == nil and index == 1) { @@ -780,6 +768,7 @@ var flightPlanController = { } else { var thePlan = plan; } + debug.dump(me.flightplans[thePlan].getWP(index).wp_name); # check waypoints database here var wpFromDB = WaypointDatabase.getWP(text); diff --git a/Nasal/MCDU/F-PLN.nas b/Nasal/MCDU/F-PLN.nas index 004f5769..4f77d6c1 100644 --- a/Nasal/MCDU/F-PLN.nas +++ b/Nasal/MCDU/F-PLN.nas @@ -580,15 +580,8 @@ var fplnPage = { # this one is only created once, and then updated - remember th } else { if ((index - 1 + me.scroll) < size(me.planList) and me.outputList[index - 1].wp != "STATIC" and me.outputList[index - 1].wp != "PSEUDO" and !mcdu_scratchpad.scratchpads[me.computer].showTypeIMsg and !mcdu_scratchpad.scratchpads[me.computer].showTypeIIMsg) { if (size(mcdu_scratchpad.scratchpads[me.computer].scratchpad) > 0) { - if (!me.temporaryFlagFpln) { - decelIndex = getprop("/instrumentation/nd/symbols/decel/index"); - decelShow = getprop("/instrumentation/nd/symbols/decel/show"); - if (decelShow and (index - 1 + me.scroll) > decelIndex) { - index = index - 1; - } - } - - var returny = fmgc.flightPlanController.scratchpad(mcdu_scratchpad.scratchpads[me.computer].scratchpad, (index - 1 + me.scroll), me.computer); + # Use outputList.index to correct the index the call goes to after sequencing + var returny = fmgc.flightPlanController.scratchpad(mcdu_scratchpad.scratchpads[me.computer].scratchpad, me.outputList[index - 1].index, me.computer); if (returny == 3) { mcdu_message(me.computer, "DIR TO IN PROGRESS"); } elsif (returny == 0) { From 2b2037df790dc39b446746faa4075c33b2c9d18f Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Fri, 21 Jan 2022 13:44:25 +0000 Subject: [PATCH 14/52] getDist() - fix for tmpy with DECEL. Crz FL temp - fix format --- Models/Instruments/MCDU/MCDU.nas | 48 ++++++++++++++++++-------------- Nasal/MCDU/F-PLN.nas | 2 +- Nasal/MCDU/MCDU.nas | 2 +- 3 files changed, 29 insertions(+), 23 deletions(-) diff --git a/Models/Instruments/MCDU/MCDU.nas b/Models/Instruments/MCDU/MCDU.nas index 9e60f520..b085cbd6 100644 --- a/Models/Instruments/MCDU/MCDU.nas +++ b/Models/Instruments/MCDU/MCDU.nas @@ -2685,6 +2685,19 @@ var canvas_MCDU_base = { me.colorRightS("wht", "amb", "wht", "wht", "wht", "wht"); me.colorRightArrow("wht", "wht", "wht", "wht", "wht", "wht"); + me["Simple_L1S"].setText("CO RTE"); + me["Simple_L2S"].setText("ALTN/CO RTE"); + me["Simple_L3S"].setText("FLT NBR"); + me["Simple_L5S"].setText("COST INDEX"); + me["Simple_L6S"].setText("CRZ FL/TEMP"); + me["Simple_R1S"].setText("FROM/TO "); + me["Simple_R2S"].setText("INIT "); + me["Simple_R5S"].setText("TROPO"); + me["Simple_R6S"].setText("GND TEMP"); + me["Simple_R2"].setText("REQUEST "); + me["Simple_R3"].setText("IRS INIT "); + me["Simple_R4"].setText("WIND "); + pageSwitch[i].setBoolValue(1); } @@ -2717,13 +2730,12 @@ var canvas_MCDU_base = { } else if (fmgc.FMGCInternal.crzSet and fmgc.FMGCInternal.crzTempSet) { me["INITA_CruiseFLTemp"].hide(); me["Simple_L6"].setColor(BLUE); - me["Simple_L6"].setText(sprintf("%s", "FL" ~ fmgc.FMGCInternal.crzFl) ~ sprintf("/%s°", fmgc.FMGCInternal.crzTemp)); + me["Simple_L6"].setText(sprintf("%s", "FL" ~ fmgc.FMGCInternal.crzFl) ~ sprintf("/%+3.0f°", fmgc.FMGCInternal.crzTemp)); } else if (fmgc.FMGCInternal.crzSet) { me["INITA_CruiseFLTemp"].hide(); me["Simple_L6"].setColor(BLUE); fmgc.FMGCInternal.crzTemp = 15 - (2 * fmgc.FMGCInternal.crzFl / 10); - fmgc.FMGCInternal.crzTempSet = 1; - me["Simple_L6"].setText(sprintf("%s", "FL" ~ fmgc.FMGCInternal.crzFl) ~ sprintf("/%s°", fmgc.FMGCInternal.crzTemp)); + me["Simple_L6"].setText(sprintf("%s", "FL" ~ fmgc.FMGCInternal.crzFl) ~ sprintf("/%+3.0f°", fmgc.FMGCInternal.crzTemp)); } else { me["INITA_CruiseFLTemp"].show(); me["Simple_L6"].setColor(AMBER); @@ -2768,6 +2780,7 @@ var canvas_MCDU_base = { me["INITA_InitRequest"].hide(); } } + if (ADIRSMCDUBTN.getValue() != 1) { me["INITA_AlignIRS"].show(); me["Simple_R3"].setColor(AMBER); @@ -2777,41 +2790,34 @@ var canvas_MCDU_base = { me["Simple_R3"].setColor(WHITE); showRightArrow(me,0, 0, 1, 0, 0, 0); } + if (fmgc.FMGCInternal.tropoSet) { me["Simple_R5"].setFontSize(normal); } else { me["Simple_R5"].setFontSize(small); } - me["Simple_R6S"].setText("GND TEMP"); - if (fmgc.FMGCInternal.phase == 0 and !fmgc.FMGCInternal.gndTempSet) { - fmgc.FMGCInternal.gndTemp = 15 - (2 * getprop("/position/gear-agl-ft") / 1000); - me["Simple_R6"].setText(sprintf("%.0f°", fmgc.FMGCInternal.gndTemp)); - me["Simple_R6"].setFontSize(small); - } else { + if (fmgc.FMGCInternal.phase == 0) { if (fmgc.FMGCInternal.gndTempSet) { + me["Simple_R6"].setText(sprintf("%.0f°", fmgc.FMGCInternal.gndTemp)); me["Simple_R6"].setFontSize(normal); + } else if (fmgc.FMGCInternal.toFromSet) { + fmgc.FMGCInternal.gndTemp = 15 - (2 * (fmgc.flightPlanController.flightplans[2].departure.elevation * 3.28084) / 1000); + me["Simple_R6"].setText(sprintf("%.0f°", fmgc.FMGCInternal.gndTemp)); + me["Simple_R6"].setFontSize(small); } else { + me["Simple_R6"].setText(sprintf("%.0f°", fmgc.FMGCInternal.gndTemp)); me["Simple_R6"].setFontSize(small); } - me["Simple_R6"].setText(sprintf("%.0f°", fmgc.FMGCInternal.gndTemp)); + } else { + me["Simple_R6"].setText("---"); + me["Simple_R6"].setFontSize(small); } - me["Simple_L1S"].setText("CO RTE"); - me["Simple_L2S"].setText("ALTN/CO RTE"); - me["Simple_L3S"].setText("FLT NBR"); - me["Simple_L5S"].setText("COST INDEX"); - me["Simple_L6S"].setText("CRZ FL/TEMP"); #me["Simple_L1"].setText("NONE"); # manage before (coRoute) me["Simple_L3"].setText(sprintf("%s", fmgc.FMGCInternal.flightNum)); - me["Simple_R1S"].setText("FROM/TO "); - me["Simple_R2S"].setText("INIT "); - me["Simple_R5S"].setText("TROPO"); me["Simple_R1"].setText(sprintf("%s", fmgc.FMGCInternal.depApt ~ "/" ~ fmgc.FMGCInternal.arrApt)); - me["Simple_R2"].setText("REQUEST "); - me["Simple_R3"].setText("IRS INIT "); - me["Simple_R4"].setText("WIND "); me["Simple_R5"].setText(sprintf("%5.0f", fmgc.FMGCInternal.tropo)); } else if (page == "IRSINIT") { if (!pageSwitch[i].getBoolValue()) { diff --git a/Nasal/MCDU/F-PLN.nas b/Nasal/MCDU/F-PLN.nas index 4f77d6c1..ebce7b4b 100644 --- a/Nasal/MCDU/F-PLN.nas +++ b/Nasal/MCDU/F-PLN.nas @@ -146,7 +146,7 @@ var fplnItem = { if (me.index == fmgc.flightPlanController.currentToWptIndex.getValue()) { return sprintf("%3.0f", math.round(courseAndDistance(me.wp)[1]));; } else { - if (decelShow and me.index == decelIndex and fmgc.flightPlanController.decelPoint != nil) { + if (me.plan == 2 and decelShow and me.index == decelIndex and fmgc.flightPlanController.decelPoint != nil) { return sprintf("%3.0f", courseAndDistance(fmgc.flightPlanController.decelPoint, me.wp)[1]); } else if (prevwp != nil and prevwp.wp_name != "DISCONTINUITY") { return sprintf("%3.0f", math.round(me.wp.leg_distance)); diff --git a/Nasal/MCDU/MCDU.nas b/Nasal/MCDU/MCDU.nas index 2ecd3c93..5992c2e3 100644 --- a/Nasal/MCDU/MCDU.nas +++ b/Nasal/MCDU/MCDU.nas @@ -68,7 +68,7 @@ var MCDU_reset = func(i) { fmgc.FMGCInternal.depApt = ""; fmgc.FMGCInternal.flightNum = ""; fmgc.FMGCInternal.flightNumSet = 0; - fmgc.FMGCInternal.gndTemp = -99; + fmgc.FMGCInternal.gndTemp = 15; fmgc.FMGCInternal.gndTempSet = 0; fmgc.FMGCInternal.toFromSet = 0; fmgc.FMGCNodes.toFromSet.setValue(0); From f04154206b93df441ba716765e69ca9e6058ccda Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Wed, 26 Jan 2022 12:10:27 +0000 Subject: [PATCH 15/52] Prevent f-pln crash on init, basic HOLD pattern page --- Nasal/FMGC/flightplan.nas | 4 +- Nasal/MCDU/HOLD.nas | 112 +++++++++++++++++++++++++++----------- 2 files changed, 84 insertions(+), 32 deletions(-) diff --git a/Nasal/FMGC/flightplan.nas b/Nasal/FMGC/flightplan.nas index 66965495..416cd00f 100644 --- a/Nasal/FMGC/flightplan.nas +++ b/Nasal/FMGC/flightplan.nas @@ -819,7 +819,9 @@ var flightPlanController = { if (me.currentToWptIndex.getValue() < 1) { var errs = []; call(func { - me.currentToWptIndex.setValue(1); + if (me.flightplans[2].getWP(1).id != "DISCONTINUITY") { + me.currentToWptIndex.setValue(1); + } }, nil, nil, nil, errs); if (size(errs) != 0) { debug.printerror(errs); } } diff --git a/Nasal/MCDU/HOLD.nas b/Nasal/MCDU/HOLD.nas index 1bb16b33..34894f07 100644 --- a/Nasal/MCDU/HOLD.nas +++ b/Nasal/MCDU/HOLD.nas @@ -39,38 +39,50 @@ var holdPage = { _setupPageWithData: func() { me.title = ["HOLD", " AT ", me.waypoint.wp_name]; me.titleColour = "wht"; - me.arrowsMatrix = [[0, 0, 0, 0, 0, 1], [1, 1, 0, 0, 0, 0]]; + me.arrowsMatrix = [[0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0]]; me.arrowsColour = [["ack", "ack", "ack", "ack", "ack", "wht"], ["blu", "blu", "ack", "ack", "ack", "ack"]]; + if (me.waypoint.fly_type == "Hold") { - me.makeTmpy(); - me.L1 = [sprintf("%03.0f°", me.waypoint.hold_inbound_radial), "INB CRS", "blu"]; - - if (me.waypoint.hold_is_left_handed) { - me.L2 = ["L", " TURN", "blu"]; - } else { - me.L2 = ["R", " TURN", "blu"]; - } - - if (me.waypoint.hold_is_distance) { - me.L3 = [" -.-/" ~ me.waypoint.hold_time_or_distance, "TIME/DIST", "blu"]; - } else { - me.L3 = [sprintf("%3.1f", (me.waypoint.hold_time_or_distance / 60)) ~ "/----", "TIME/DIST", "blu"]; - } - me.R1 = ["COMPUTED ", nil, "blu"]; - me.R2 = ["DATABASE ", nil, "yel"]; + me.R1 = ["COMPUTED ", nil, "wht"]; + me.R2 = ["DATABASE ", nil, "blu"]; + me.arrowsColour[1][0] = "wht"; + me.arrowsColour[1][1] = "blu"; + me.arrowsMatrix[1][0] = 1; me.arrowsMatrix[1][1] = 0; } else { - me.L1 = ["100°", "INB CRS", "blu"]; - me.L2 = ["R", " TURN", "blu"]; + # waypoint is a leg, figure out how to handle it + return; + me.waypoint.hold_count = 999; + me.waypoint.hold_is_left_handed = 0; + me.waypoint.hold_is_distance = 0; + me.waypoint.hold_inbound_radial = me.waypoint.leg_bearing; + if (pts.Instrumentation.Altimeter.indicatedFt.getValue() >= 14000) { - me.L3 = ["1.5/----", "TIME/DIST", "blu"]; + me.waypoint.hold_time_or_distance = 90; } else { - me.L3 = ["1.0/----", "TIME/DIST", "blu"]; + me.waypoint.hold_time_or_distance = 60; } - me.R1 = ["COMPUTED ", nil, "blu"]; - me.R2 = ["DATABASE ", nil, "blu"]; + + me.R1 = ["COMPUTED ", nil, "yel"]; + me.R2 = ["DATABASE ", nil, "wht"]; + me.arrowsColour[1][0] = "yel"; + me.arrowsColour[1][1] = "wht"; + me.arrowsMatrix[1][0] = 0; + me.arrowsMatrix[1][1] = 1; } - me.L6 = [" RETURN", nil, "wht"]; + + me.L1 = [sprintf("%03.0f°", me.waypoint.hold_inbound_radial), "INB CRS", "yel"]; + if (me.waypoint.hold_is_left_handed) { + me.L2 = ["L", " TURN", "blu"]; + } else { + me.L2 = ["R", " TURN", "blu"]; + } + if (me.waypoint.hold_is_distance) { + me.L3 = [" -.-/" ~ me.waypoint.hold_time_or_distance, "TIME/DIST", "blu"]; + } else { + me.L3 = [sprintf("%3.1f", (me.waypoint.hold_time_or_distance / 60)) ~ "/----", "TIME/DIST", "blu"]; + } + me.C4 = ["LAST EXIT", nil, "wht"]; me.C5 = ["---- ---.-", "UTC FUEL", "wht"]; canvas_mcdu.pageSwitch[me.computer].setBoolValue(0); @@ -82,23 +94,61 @@ var holdPage = { }, updateTmpy: func() { if (fmgc.flightPlanController.temporaryFlag[me.computer]) { - me.L1[2] = "yel"; - me.L2[2] = "yel"; - me.L3[2] = "yel"; me.L6 = [" F-PLN", " TMPY", "yel"]; me.R6 = ["INSERT ", " TMPY", "yel"]; me.arrowsColour[0][5] = "yel"; me.titleColour = "yel"; canvas_mcdu.pageSwitch[me.computer].setBoolValue(0); } else { - me.L1[2] = "blu"; - me.L2[2] = "blu"; - me.L3[2] = "blu"; me.L6 = [" RETURN", nil, "wht"]; me.R6 = [nil, nil, "ack"]; me.arrowsColour[0][5] = "wht"; me.titleColour = "wht"; canvas_mcdu.pageSwitch[me.computer].setBoolValue(0); } - } + }, + pushbuttonLeft: func(index) { + me.scratchpad = mcdu_scratchpad.scratchpads[me.computer].scratchpad; + if (index == 1) { + if (size(me.scratchpad) <= 3 and num(me.scratchpad) != nil) { + me.waypoint.hold_inbound_radial = me.scratchpad; + } else { + mcdu_message(me.computer, "NOT ALLOWED"); + } + } else if (index == 2) { + if (me.scratchpad == "L") { + me.waypoint.hold_is_left_handed = 1; + } elsif (me.scratchpad == "R") { + me.waypoint.hold_is_left_handed = 0; + } else { + mcdu_message(me.computer, "NOT ALLOWED"); + } + } elsif (index == 3) { + if (num(me.scratchpad) != nil) { + me.waypoint.hold_time_or_distance = me.scratchpad; + } else { + mcdu_message(me.computer, "NOT ALLOWED"); + } + } elsif (index == 6) { + if (fmgc.flightPlanController.temporaryFlag[me.computer]) { + setprop("/MCDU[" ~ me.computer ~ "]/page", "F-PLNA"); + } else { + setprop("/MCDU[" ~ me.computer ~ "]/page", "LATREV"); + } + } + }, + pushbuttonRight: func(index) { + me.scratchpad = mcdu_scratchpad.scratchpads[me.computer].scratchpad; + if (size(me.scratchpad) != 0) { + mcdu_message(me.computer, "NOT ALLOWED"); + } else { + if (index == 6) { + if (fmgc.flightPlanController.temporaryFlag[me.computer]) { + setprop("/MCDU[" ~ me.computer ~ "]/page", "F-PLNA"); + } else { + mcdu_message(me.computer, "NOT ALLOWED"); + } + } + } + }, }; \ No newline at end of file From 74eaf75477e33816d3a2a883d7fe1f41542cc4ba Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Wed, 26 Jan 2022 12:38:56 +0000 Subject: [PATCH 16/52] Add ID of procedure --- Nasal/MCDU/F-PLN.nas | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/Nasal/MCDU/F-PLN.nas b/Nasal/MCDU/F-PLN.nas index ebce7b4b..f22fff2c 100644 --- a/Nasal/MCDU/F-PLN.nas +++ b/Nasal/MCDU/F-PLN.nas @@ -1,3 +1,13 @@ +var getSubTextFunc = func(meRef) { + var subText = nil; + call(func { + subText = me.wp.wp_owner.id; + }, nil, meRef, nil, + var errs = [] + ); + return nil; +} + var fplnItem = { new: func(wp, index, plan, computer, colour = "grn") { var fI = {parents:[fplnItem]}; @@ -19,10 +29,14 @@ var fplnItem = { if (wptName[0] == "VECTORS") { return ["MANUAL", me.getSubText(), me.colour]; } else { - if (size(wptName) == 2) { - return[wptName[0] ~ wptName[1 ~ (me.wp.fly_type == "flyOver" ? "@" : "")], me.getSubText(), me.colour]; + if (me.wp.fly_type == "HOLD") { + return ["HOLD " ~ me.wp.hold_is_left_handed ? "L" : "R", me.getSubText(), me.colour]; } else { - return [me.wp.wp_name ~ (me.wp.fly_type == "flyOver" ? "@" : ""), me.getSubText(), me.colour]; + if (size(wptName) == 2) { + return[wptName[0] ~ wptName[1 ~ (me.wp.fly_type == "flyOver" ? "@" : "")], me.getSubText(), me.colour]; + } else { + return [me.wp.wp_name ~ (me.wp.fly_type == "flyOver" ? "@" : ""), me.getSubText(), me.colour]; + } } } } else { @@ -33,7 +47,11 @@ var fplnItem = { } }, getSubText: func() { - return nil; + if (me.wp.wp_parent_name != nil) { + return " " ~ me.wp.wp_parent_name; + } else { + return nil; + } }, updateCenterText: func() { if (me.wp != nil) { From 9b4fdcf5b52fe09d37750e42fac0637120fa23d7 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Wed, 26 Jan 2022 12:48:48 +0000 Subject: [PATCH 17/52] HOLD page - connect butons --- Nasal/MCDU/HOLD.nas | 8 +------- Nasal/MCDU/MCDU.nas | 6 ++++++ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Nasal/MCDU/HOLD.nas b/Nasal/MCDU/HOLD.nas index 34894f07..a4613ac6 100644 --- a/Nasal/MCDU/HOLD.nas +++ b/Nasal/MCDU/HOLD.nas @@ -71,7 +71,7 @@ var holdPage = { me.arrowsMatrix[1][1] = 1; } - me.L1 = [sprintf("%03.0f°", me.waypoint.hold_inbound_radial), "INB CRS", "yel"]; + me.L1 = [sprintf("%03.0f°", me.waypoint.hold_inbound_radial), "INB CRS", "blu"]; if (me.waypoint.hold_is_left_handed) { me.L2 = ["L", " TURN", "blu"]; } else { @@ -129,12 +129,6 @@ var holdPage = { } else { mcdu_message(me.computer, "NOT ALLOWED"); } - } elsif (index == 6) { - if (fmgc.flightPlanController.temporaryFlag[me.computer]) { - setprop("/MCDU[" ~ me.computer ~ "]/page", "F-PLNA"); - } else { - setprop("/MCDU[" ~ me.computer ~ "]/page", "LATREV"); - } } }, pushbuttonRight: func(index) { diff --git a/Nasal/MCDU/MCDU.nas b/Nasal/MCDU/MCDU.nas index eff2d9ca..c874cb00 100644 --- a/Nasal/MCDU/MCDU.nas +++ b/Nasal/MCDU/MCDU.nas @@ -353,6 +353,8 @@ var lskbutton = func(btn, i) { mcdu_scratchpad.scratchpads[i].empty(); } } + } else if (page == "HOLD") { + canvas_mcdu.myHold[i].pushbuttonLeft(1); } else if (page == "MCDUTEXT") { atsu.freeTexts[i].selection = 0; atsu.freeTexts[i].changed = 1; @@ -497,6 +499,8 @@ var lskbutton = func(btn, i) { } } else if (page == "VERTREV") { canvas_mcdu.myVertRev[i].pushButtonLeft(2); + } else if (page == "HOLD") { + canvas_mcdu.myHold[i].pushbuttonLeft(2); } else if (page == "MCDUTEXT") { atsu.freeTexts[i].selection = 1; atsu.freeTexts[i].changed = 1; @@ -624,6 +628,8 @@ var lskbutton = func(btn, i) { } } else if (page == "VERTREV") { canvas_mcdu.myVertRev[i].pushButtonLeft(3); + } else if (page == "HOLD") { + canvas_mcdu.myHold[i].pushbuttonLeft(3); } else if (page == "MCDUTEXT") { atsu.freeTexts[i].selection = 2; atsu.freeTexts[i].changed = 1; From d67ff09a79b804d66cf009fb3abece0cfd438a13 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Wed, 26 Jan 2022 12:56:15 +0000 Subject: [PATCH 18/52] HOLD fix --- Nasal/MCDU/F-PLN.nas | 4 ++-- Nasal/MCDU/HOLD.nas | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Nasal/MCDU/F-PLN.nas b/Nasal/MCDU/F-PLN.nas index f22fff2c..80b79ed3 100644 --- a/Nasal/MCDU/F-PLN.nas +++ b/Nasal/MCDU/F-PLN.nas @@ -29,8 +29,8 @@ var fplnItem = { if (wptName[0] == "VECTORS") { return ["MANUAL", me.getSubText(), me.colour]; } else { - if (me.wp.fly_type == "HOLD") { - return ["HOLD " ~ me.wp.hold_is_left_handed ? "L" : "R", me.getSubText(), me.colour]; + if (me.wp.fly_type == "Hold") { + return ["HOLD " ~ (me.wp.hold_is_left_handed ? "L" : "R"), me.getSubText(), me.colour]; } else { if (size(wptName) == 2) { return[wptName[0] ~ wptName[1 ~ (me.wp.fly_type == "flyOver" ? "@" : "")], me.getSubText(), me.colour]; diff --git a/Nasal/MCDU/HOLD.nas b/Nasal/MCDU/HOLD.nas index a4613ac6..287c00a6 100644 --- a/Nasal/MCDU/HOLD.nas +++ b/Nasal/MCDU/HOLD.nas @@ -112,20 +112,28 @@ var holdPage = { if (index == 1) { if (size(me.scratchpad) <= 3 and num(me.scratchpad) != nil) { me.waypoint.hold_inbound_radial = me.scratchpad; + mcdu_scratchpad.scratchpads[me.computer].empty(); + me._setupPageWithData(); } else { mcdu_message(me.computer, "NOT ALLOWED"); } } else if (index == 2) { if (me.scratchpad == "L") { me.waypoint.hold_is_left_handed = 1; + mcdu_scratchpad.scratchpads[me.computer].empty(); + me._setupPageWithData(); } elsif (me.scratchpad == "R") { me.waypoint.hold_is_left_handed = 0; + mcdu_scratchpad.scratchpads[me.computer].empty(); + me._setupPageWithData(); } else { mcdu_message(me.computer, "NOT ALLOWED"); } } elsif (index == 3) { if (num(me.scratchpad) != nil) { me.waypoint.hold_time_or_distance = me.scratchpad; + mcdu_scratchpad.scratchpads[me.computer].empty(); + me._setupPageWithData(); } else { mcdu_message(me.computer, "NOT ALLOWED"); } From 7a92a773c27b97d34afe30f9c86f002e085e8240 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Wed, 26 Jan 2022 15:28:19 +0000 Subject: [PATCH 19/52] Prevent sequencing on the ground. --- Nasal/FMGC/FMGC-b.nas | 9 ++++++++- Nasal/FMGC/flightplan.nas | 1 - Nasal/MCDU/F-PLN.nas | 2 ++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Nasal/FMGC/FMGC-b.nas b/Nasal/FMGC/FMGC-b.nas index b88b0291..06563963 100644 --- a/Nasal/FMGC/FMGC-b.nas +++ b/Nasal/FMGC/FMGC-b.nas @@ -442,7 +442,7 @@ var ITAF = { if (enableFlyBy and FPLN.wp0Dist.getValue() <= FPLN.turnDist and !Gear.wow1.getBoolValue() and fmgc.flightPlanController.flightplans[2].getWP(FPLN.currentWPTemp).fly_type == "flyBy") { flightPlanController.autoSequencing(); - } elsif (FPLN.wp0Dist.getValue() <= 0.15) { + } elsif (FPLN.wp0Dist.getValue() <= 0.15 and !Gear.wow1.getBoolValue()) { flightPlanController.autoSequencing(); } } @@ -962,6 +962,13 @@ var ITAF = { }, }; + +setlistener(Gear.wow1, func(val) { + if (!val.getBoolValue() and FPLN.currentWP.getValue() == 0) { + flightPlanController.autoSequencing(); + } +}); + setlistener("/it-autoflight/input/ap1", func { Input.ap1Temp = Input.ap1.getBoolValue(); if (Input.ap1Temp != Output.ap1.getBoolValue()) { diff --git a/Nasal/FMGC/flightplan.nas b/Nasal/FMGC/flightplan.nas index 416cd00f..c5547803 100644 --- a/Nasal/FMGC/flightplan.nas +++ b/Nasal/FMGC/flightplan.nas @@ -768,7 +768,6 @@ var flightPlanController = { } else { var thePlan = plan; } - debug.dump(me.flightplans[thePlan].getWP(index).wp_name); # check waypoints database here var wpFromDB = WaypointDatabase.getWP(text); diff --git a/Nasal/MCDU/F-PLN.nas b/Nasal/MCDU/F-PLN.nas index 80b79ed3..5c8f1c6c 100644 --- a/Nasal/MCDU/F-PLN.nas +++ b/Nasal/MCDU/F-PLN.nas @@ -425,6 +425,8 @@ var fplnPage = { # this one is only created once, and then updated - remember th decelShow = getprop("/instrumentation/nd/symbols/decel/show"); var startingIndex = fmgc.flightPlanController.currentToWptIndex.getValue() == -1 ? 0 : fmgc.flightPlanController.currentToWptIndex.getValue() - 1; + startingIndex == -1 ? 0 : startingIndex; + for (var i = startingIndex; i < me.plan.getPlanSize(); i += 1) { if (!me.temporaryFlagFpln and decelShow) { if (i == decelIndex) { From 26af612b7ebf60d3ce16c1de194255fce06b5c14 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Wed, 26 Jan 2022 15:34:38 +0000 Subject: [PATCH 20/52] Proper airport btn --- Nasal/MCDU/HOLD.nas | 4 ++++ Nasal/MCDU/MCDU.nas | 30 +++++++++++++++++++----------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/Nasal/MCDU/HOLD.nas b/Nasal/MCDU/HOLD.nas index 287c00a6..68ed4fbd 100644 --- a/Nasal/MCDU/HOLD.nas +++ b/Nasal/MCDU/HOLD.nas @@ -137,6 +137,8 @@ var holdPage = { } else { mcdu_message(me.computer, "NOT ALLOWED"); } + } else { + mcdu_message(me.computer, "NOT ALLOWED"); } }, pushbuttonRight: func(index) { @@ -150,6 +152,8 @@ var holdPage = { } else { mcdu_message(me.computer, "NOT ALLOWED"); } + } else { + mcdu_message(me.computer, "NOT ALLOWED"); } } }, diff --git a/Nasal/MCDU/MCDU.nas b/Nasal/MCDU/MCDU.nas index c874cb00..b0cac383 100644 --- a/Nasal/MCDU/MCDU.nas +++ b/Nasal/MCDU/MCDU.nas @@ -6,6 +6,7 @@ var pageNode = [props.globals.getNode("/MCDU[0]/page"), props.globals.getNode("/MCDU[1]/page")]; var page = nil; var msg = nil; +var airportPress = [0,0]; var scratchpadNode = [nil, nil]; var MCDU_init = func(i) { @@ -1460,25 +1461,32 @@ var pagebutton = func(btn, i) { #} mcdu_message(i, "SELECT DESIRED SYSTEM"); pageNode[i].setValue("MCDU"); - } else if (btn == "f-pln" or btn == "airport") { + } else if (btn == "f-pln") { if (canvas_mcdu.myFpln[i] == nil) { canvas_mcdu.myFpln[i] = fplnPage.new(2, i); } - if (btn == "airport") { - if (fmgc.FMGCInternal.phase == 0 or fmgc.FMGCInternal.phase == 1) { - canvas_mcdu.myFpln[i].scroll = 0; - } else { - if (fmgc.flightPlanController.temporaryFlag[i]) { - canvas_mcdu.myFpln[i].scroll = fmgc.flightPlanController.arrivalIndex[i]; + canvas_mcdu.myFpln[i].scroll = 0; + pageNode[i].setValue("F-PLNA"); + } else if (btn == "airport") { + if (airportPress[i] == 0 or fmgc.FMGCInternal.phase >= 1) { + if (fmgc.flightPlanController.temporaryFlag[i]) { + if (fmgc.flightPlanController.currentToWptIndex.getValue() == fmgc.flightPlanController.arrivalIndex[i]) { + canvas_mcdu.myFpln[i].scroll = (fmgc.flightPlanController.arrivalIndex[i] - fmgc.flightPlanController.currentToWptIndex.getValue()); } else { - canvas_mcdu.myFpln[i].scroll = fmgc.flightPlanController.arrivalIndex[2]; + canvas_mcdu.myFpln[i].scroll = (fmgc.flightPlanController.arrivalIndex[i] - fmgc.flightPlanController.currentToWptIndex.getValue()) - 1; + } + } else { + if (fmgc.flightPlanController.currentToWptIndex.getValue() == fmgc.flightPlanController.arrivalIndex[2]) { + canvas_mcdu.myFpln[i].scroll = (fmgc.flightPlanController.arrivalIndex[2] - fmgc.flightPlanController.currentToWptIndex.getValue()); + } else { + canvas_mcdu.myFpln[i].scroll = (fmgc.flightPlanController.arrivalIndex[2] - fmgc.flightPlanController.currentToWptIndex.getValue()) - 1; } } - } else { + airportPress[i] = 1; + } else if (fmgc.FMGCInternal.phase == 0 or fmgc.FMGCInternal.phase == 1) { canvas_mcdu.myFpln[i].scroll = 0; + airportPress[i] = 0; } - pageNode[i].setValue("F-PLNA"); - } else if (btn == "fuel-pred") { pageNode[i].setValue("FUELPRED"); } else if (btn == "dirto") { From 05d36c1c8956417c854c6f7ab9d926917e189954 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Thu, 27 Jan 2022 13:08:24 +0000 Subject: [PATCH 21/52] Fix missing namespace --- Models/Instruments/MCDU/MCDU.nas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Models/Instruments/MCDU/MCDU.nas b/Models/Instruments/MCDU/MCDU.nas index 9857d183..e422246b 100644 --- a/Models/Instruments/MCDU/MCDU.nas +++ b/Models/Instruments/MCDU/MCDU.nas @@ -2888,7 +2888,7 @@ var canvas_MCDU_base = { degrees = getprop("/FMGC/internal/align-ref-lat-degrees"); minutes = getprop("/FMGC/internal/align-ref-lat-minutes"); sign = getprop("/FMGC/internal/align-ref-lat-sign"); - apt = airportinfo(FMGCInternal.depApt); + apt = airportinfo(fmgc.FMGCInternal.depApt); degrees_lat = int(apt.lat); minutes_lat = sprintf("%.1f",abs((apt.lat - degrees_lat) * 60)); sign_lat = degrees_lat >= 0 ? "N" : "S"; From 5d857ec33883ecef60b3dd3ba66a48fd6d9524bb Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Thu, 27 Jan 2022 18:39:59 +0000 Subject: [PATCH 22/52] ALTN: case airport is missing --- Nasal/MCDU/F-PLN.nas | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/Nasal/MCDU/F-PLN.nas b/Nasal/MCDU/F-PLN.nas index 5c8f1c6c..9a5067bb 100644 --- a/Nasal/MCDU/F-PLN.nas +++ b/Nasal/MCDU/F-PLN.nas @@ -449,20 +449,24 @@ var fplnPage = { # this one is only created once, and then updated - remember th if (!fmgc.FMGCInternal.altAirportSet) { append(me.planList, staticText.new(me.computer, me.getText("noAltnFpln"))); } else { - var altnApt = findAirportsByICAO(fmgc.FMGCInternal.altAirport)[0]; - append(me.planList, fplnItem.new({ - alt_cstr: nil, - alt_cstr_type: nil, - fly_type: "flyBy", - lat: altnApt.lat, - leg_bearing: courseAndDistance(findAirportsByICAO(fmgc.FMGCInternal.arrApt)[0], altnApt)[0], - leg_distance: courseAndDistance(findAirportsByICAO(fmgc.FMGCInternal.arrApt)[0], altnApt)[1], - lon: altnApt.lon, - speed_cstr: nil, - speed_cstr_type: nil, - wp_name: fmgc.FMGCInternal.altAirport, - }, i, me.planIndex, me.computer, "blu")); - append(me.planList, staticText.new(me.computer, me.getText("altnFplnEnd"))); + var altnApt = findAirportsByICAO(fmgc.FMGCInternal.altAirport); + if (size(altnApt) > 0) { + append(me.planList, fplnItem.new({ + alt_cstr: nil, + alt_cstr_type: nil, + fly_type: "flyBy", + lat: altnApt.lat, + leg_bearing: courseAndDistance(findAirportsByICAO(fmgc.FMGCInternal.arrApt)[0], altnApt[0])[0], + leg_distance: courseAndDistance(findAirportsByICAO(fmgc.FMGCInternal.arrApt)[0], altnApt[0])[1], + lon: altnApt.lon, + speed_cstr: nil, + speed_cstr_type: nil, + wp_name: fmgc.FMGCInternal.altAirport, + }, i, me.planIndex, me.computer, "blu")); + append(me.planList, staticText.new(me.computer, me.getText("altnFplnEnd"))); + } else { + append(me.planList, staticText.new(me.computer, me.getText("noAltnFpln"))); + } } me.basePage(); From 56bab27f46fbf10744fa1b446eb5eb867cf45aa9 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Wed, 2 Feb 2022 12:05:42 +0000 Subject: [PATCH 23/52] Navdisplay: plan index - account for current waypoint index --- Nasal/MCDU/DIRTO.nas | 9 ++++++--- Nasal/MCDU/F-PLN.nas | 12 ++++++++++-- Nasal/MCDU/RECEIVEDMESSAGES.nas | 3 +++ 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/Nasal/MCDU/DIRTO.nas b/Nasal/MCDU/DIRTO.nas index e06a5061..eabb0e3f 100644 --- a/Nasal/MCDU/DIRTO.nas +++ b/Nasal/MCDU/DIRTO.nas @@ -1,3 +1,6 @@ +# A3XX MCDU Direct To Page +# Copyright (c) 2022 Jonathan Redpath (legoboyvdlp) + var dirToFlag = 0; var dirTo = { @@ -77,14 +80,14 @@ var dirTo = { canvas_mcdu.myFpln[me.computer] = fplnPage.new(2, me.computer); } - var x = 0; + var dirToLeftIndex = 0; me.vector = []; for (var i = 1 + (me.scroll); i < size(canvas_mcdu.myFpln[me.computer].planList) - 2; i = i + 1) { if (canvas_mcdu.myFpln[me.computer].planList[i].wp == "PSEUDO" or canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_name == "DISCONTINUITY" or canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_name == "VECTORS" or canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_name == "T-P" or canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_type == "hdgToAlt") { continue; } if (canvas_mcdu.myFpln[me.computer].planList[i].index > fmgc.flightPlanController.arrivalIndex[2]) { continue; } append(me.vector, canvas_mcdu.myFpln[me.computer].planList[i].wp); - x += 1; - if (x == 4) { break; } + dirToLeftIndex += 1; + if (dirToLeftIndex == 4) { break; } } if (size(me.vector) > 0) { diff --git a/Nasal/MCDU/F-PLN.nas b/Nasal/MCDU/F-PLN.nas index 9a5067bb..9628b21d 100644 --- a/Nasal/MCDU/F-PLN.nas +++ b/Nasal/MCDU/F-PLN.nas @@ -1,3 +1,11 @@ +# A3XX FMGC Flightplan Page +# Copyright (c) 2022 Josh Davidson (Octal450) and Jonathan Redpath (legoboyvdlp) + +# Local vars +var decelIndex = 0; +var decelShow = 0; +var destName = nil; + var getSubTextFunc = func(meRef) { var subText = nil; call(func { @@ -526,7 +534,7 @@ var fplnPage = { # this one is only created once, and then updated - remember th }, destInfo: func() { if (me.plan.getWP(fmgc.flightPlanController.arrivalIndex[me.planIndex]) != nil) { - var destName = split("-", me.plan.getWP(fmgc.flightPlanController.arrivalIndex[me.planIndex]).wp_name); + destName = split("-", me.plan.getWP(fmgc.flightPlanController.arrivalIndex[me.planIndex]).wp_name); if (size(destName) == 2) { me.L6 = [destName[0] ~ destName[1], " DEST", "wht"]; } else { @@ -554,8 +562,8 @@ var fplnPage = { # this one is only created once, and then updated - remember th if (me.scroll > decelIndex) { decelOffset = 1; } - setprop("/instrumentation/efis[" ~ me.computer ~ "]/inputs/plan-wpt-index", me.scroll - decelOffset); } + setprop("/instrumentation/efis[" ~ me.computer ~ "]/inputs/plan-wpt-index", (fmgc.flightPlanController.currentToWptIndex.getValue() - 1 + me.scroll - decelOffset)); } }, scrollUp: func() { diff --git a/Nasal/MCDU/RECEIVEDMESSAGES.nas b/Nasal/MCDU/RECEIVEDMESSAGES.nas index f2c683ba..63347196 100644 --- a/Nasal/MCDU/RECEIVEDMESSAGES.nas +++ b/Nasal/MCDU/RECEIVEDMESSAGES.nas @@ -1,3 +1,6 @@ +# A3XX MCDU Received Messages Page +# Copyright (c) 2022 Jonathan Redpath (legoboyvdlp) + var receivedMessagesPage = { title: nil, arrowsMatrix: [[0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0]], From 0af3d5bc4d3456913d9f958a91792e5017fc9e1e Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Wed, 2 Feb 2022 16:40:11 +0000 Subject: [PATCH 24/52] Fix ALTN --- Nasal/MCDU/F-PLN.nas | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Nasal/MCDU/F-PLN.nas b/Nasal/MCDU/F-PLN.nas index 9628b21d..51ec1a1c 100644 --- a/Nasal/MCDU/F-PLN.nas +++ b/Nasal/MCDU/F-PLN.nas @@ -463,10 +463,10 @@ var fplnPage = { # this one is only created once, and then updated - remember th alt_cstr: nil, alt_cstr_type: nil, fly_type: "flyBy", - lat: altnApt.lat, + lat: altnApt[0].lat, leg_bearing: courseAndDistance(findAirportsByICAO(fmgc.FMGCInternal.arrApt)[0], altnApt[0])[0], leg_distance: courseAndDistance(findAirportsByICAO(fmgc.FMGCInternal.arrApt)[0], altnApt[0])[1], - lon: altnApt.lon, + lon: altnApt[0].lon, speed_cstr: nil, speed_cstr_type: nil, wp_name: fmgc.FMGCInternal.altAirport, From 1264dd0a29264014d44af5096520a475ea4a7bc4 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Wed, 2 Feb 2022 16:46:35 +0000 Subject: [PATCH 25/52] Fix ALTN further --- Nasal/MCDU/F-PLN.nas | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Nasal/MCDU/F-PLN.nas b/Nasal/MCDU/F-PLN.nas index 51ec1a1c..90ae45f8 100644 --- a/Nasal/MCDU/F-PLN.nas +++ b/Nasal/MCDU/F-PLN.nas @@ -126,8 +126,7 @@ var fplnItem = { return sprintf("%03.0f", math.round(me.brg)); }, getTrack: func() { - var wp = fmgc.flightPlanController.flightplans[me.plan].getWP(me.index); - me.trk = me.wp.leg_bearing - magvar(wp.lat, wp.lon); + me.trk = me.wp.leg_bearing - magvar(me.wp.lat, me.wp.lon); if (me.trk < 0) { me.trk += 360; } if (me.trk > 360) { me.trk -= 360; } return sprintf("%03.0f", math.round(me.trk)); @@ -470,6 +469,7 @@ var fplnPage = { # this one is only created once, and then updated - remember th speed_cstr: nil, speed_cstr_type: nil, wp_name: fmgc.FMGCInternal.altAirport, + wp_parent_name: nil, }, i, me.planIndex, me.computer, "blu")); append(me.planList, staticText.new(me.computer, me.getText("altnFplnEnd"))); } else { From 165174f27653f2d65c6d2147c6e8aa13fe87059b Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Fri, 11 Feb 2022 20:37:05 +0000 Subject: [PATCH 26/52] Fix the direct to --- Nasal/FMGC/flightplan.nas | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Nasal/FMGC/flightplan.nas b/Nasal/FMGC/flightplan.nas index c5547803..602df868 100644 --- a/Nasal/FMGC/flightplan.nas +++ b/Nasal/FMGC/flightplan.nas @@ -279,7 +279,6 @@ var flightPlanController = { # args: n, index # n: flightplan to which the PPOS waypoint will be inserted # index: index which the waypoint will be at. - insertTP: func(n, index) { me.flightplans[n].insertWP(createWP(geo.aircraft_position(), "T-P"), index); fmgc.windController.insertWind(n, index, 0, "T-P"); @@ -372,10 +371,10 @@ var flightPlanController = { var indexWP = me.flightplans[plan].indexOfWP(waypointGhost); me.deleteTillIndex(waypointGhost, me.currentToWptIndex.getValue(), plan); me.insertTP(plan, indexWP - 1); + me.DirToIndex = indexWP; } var curAircraftPosDirTo = geo.aircraft_position(); canvas_mcdu.myDirTo[plan].updateDist(me.flightplans[plan].getWP(me.currentToWptIndex.getValue() + 1).courseAndDistanceFrom(curAircraftPosDirTo)[1]); - me.flightPlanChanged(plan); }, deleteWP: func(index, n, a = 0) { # a = 1, means adding a waypoint via deleting intermediate From a12b16ff457b8941cf4a16d86b5d9543969dbfad Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Sat, 12 Feb 2022 13:17:56 +0000 Subject: [PATCH 27/52] Direct to - finally and completely fix --- Nasal/FMGC/flightplan.nas | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/Nasal/FMGC/flightplan.nas b/Nasal/FMGC/flightplan.nas index 602df868..6cedd92d 100644 --- a/Nasal/FMGC/flightplan.nas +++ b/Nasal/FMGC/flightplan.nas @@ -369,8 +369,11 @@ var flightPlanController = { me.DirToIndex = me.currentToWptIndex.getValue() + 1; } else { var indexWP = me.flightplans[plan].indexOfWP(waypointGhost); - me.deleteTillIndex(waypointGhost, me.currentToWptIndex.getValue(), plan); - me.insertTP(plan, indexWP - 1); + me.insertTP(plan, indexWP); + me.deleteTillIndex(waypointGhost, me.currentToWptIndex.getValue(), plan, 1); + + indexWP = me.flightplans[plan].indexOfWP(waypointGhost); + me.hideTillIndex(indexWP - 2, plan); me.DirToIndex = indexWP; } var curAircraftPosDirTo = geo.aircraft_position(); @@ -405,8 +408,8 @@ var flightPlanController = { # deleteTillIndex - helper that deletes waypoints up to a passed waypoint already in flightplan # uses a while loop to delete a certain number of waypoints between passed index and # index of waypoint alredy in flightplan - deleteTillIndex: func(wpGhost, index, plan) { - var numToDel = me.flightplans[plan].indexOfWP(wpGhost) - index; + deleteTillIndex: func(wpGhost, index, plan, offset = 0) { + var numToDel = me.flightplans[plan].indexOfWP(wpGhost) - index - offset; while (numToDel > 0) { me.deleteWP(index, plan, 1); numToDel -= 1; @@ -414,6 +417,15 @@ var flightPlanController = { return 2; }, + hideTillIndex: func(index, plan) { + var numToDel = index; + while (numToDel >= 0) { + me.flightplans[plan].getWP(index - numToDel).hidden = 1; + numToDel -= 1; + } + return 2; + }, + # createDuplicateNames - helper to spawn DUPLICATENAMES page # args: ghostContainer, index, flag, plan # ghostContainer: vector of fgPositioned ghosts From de296916ed703006ff9d224b28f42bf36b34993e Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Sun, 13 Feb 2022 10:01:11 +0000 Subject: [PATCH 28/52] F-PLN page: fix index = 0 --- Nasal/MCDU/F-PLN.nas | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Nasal/MCDU/F-PLN.nas b/Nasal/MCDU/F-PLN.nas index 90ae45f8..c3c7df9a 100644 --- a/Nasal/MCDU/F-PLN.nas +++ b/Nasal/MCDU/F-PLN.nas @@ -432,7 +432,9 @@ var fplnPage = { # this one is only created once, and then updated - remember th decelShow = getprop("/instrumentation/nd/symbols/decel/show"); var startingIndex = fmgc.flightPlanController.currentToWptIndex.getValue() == -1 ? 0 : fmgc.flightPlanController.currentToWptIndex.getValue() - 1; - startingIndex == -1 ? 0 : startingIndex; + + # Situation where currentIndex is equal to 0 + startingIndex = (startingIndex == -1 ? 0 : startingIndex); for (var i = startingIndex; i < me.plan.getPlanSize(); i += 1) { if (!me.temporaryFlagFpln and decelShow) { From 96751117013e938946ba37fe7a94c1851caae81e Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Sun, 13 Feb 2022 10:02:40 +0000 Subject: [PATCH 29/52] Bugfix decel --- Nasal/MCDU/F-PLN.nas | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Nasal/MCDU/F-PLN.nas b/Nasal/MCDU/F-PLN.nas index c3c7df9a..149915cc 100644 --- a/Nasal/MCDU/F-PLN.nas +++ b/Nasal/MCDU/F-PLN.nas @@ -4,6 +4,7 @@ # Local vars var decelIndex = 0; var decelShow = 0; +var decelOffset = 0; var destName = nil; var getSubTextFunc = func(meRef) { @@ -559,8 +560,8 @@ var fplnPage = { # this one is only created once, and then updated - remember th decelIndex = getprop("/instrumentation/nd/symbols/decel/index"); decelShow = getprop("/instrumentation/nd/symbols/decel/show"); if (me.scroll < me.plan.getPlanSize()) { + decelOffset = 0; if (decelShow) { - var decelOffset = 0; if (me.scroll > decelIndex) { decelOffset = 1; } From b1683b770f880b0b14de8171ddd1646add2a29e0 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Sun, 13 Feb 2022 10:28:15 +0000 Subject: [PATCH 30/52] DeleteWP: don't allow deleting discontinuity that is just after a PPOS --- Nasal/FMGC/flightplan.nas | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Nasal/FMGC/flightplan.nas b/Nasal/FMGC/flightplan.nas index 6cedd92d..9e8cade1 100644 --- a/Nasal/FMGC/flightplan.nas +++ b/Nasal/FMGC/flightplan.nas @@ -393,8 +393,12 @@ var flightPlanController = { } } } else { - me.flightplans[n].deleteWP(index); - fmgc.windController.deleteWind(n, index); + if (me.flightplans[n].getWP(index).id == "DISCONTINUITY" and index > 0 and me.flightplans[n].getWP(index - 1).id == "PPOS") { + return 1; + } else { + me.flightplans[n].deleteWP(index); + fmgc.windController.deleteWind(n, index); + } } me.flightPlanChanged(n); From 888fbbe81efe51b471308e92f7914b17fb0e8218 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Sun, 13 Feb 2022 18:07:58 +0000 Subject: [PATCH 31/52] Prevent modifying the TO waypoint --- Nasal/FMGC/flightplan.nas | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Nasal/FMGC/flightplan.nas b/Nasal/FMGC/flightplan.nas index 9e8cade1..69f34220 100644 --- a/Nasal/FMGC/flightplan.nas +++ b/Nasal/FMGC/flightplan.nas @@ -769,6 +769,12 @@ var flightPlanController = { return 3; } + if (index == me.currentToWptIndex.getValue()) { + return 1; + # TODO - implement the PPOS - DISCONT feature + # me.insertPPOS(thePlan, index - 1); + # me.addDiscontinuity(index - 1, thePlan, 1); + } if (!me.temporaryFlag[plan]) { if (text == "CLR" and me.flightplans[2].getWP(index).wp_name == "DISCONTINUITY") { @@ -784,6 +790,7 @@ var flightPlanController = { var thePlan = plan; } + # check waypoints database here var wpFromDB = WaypointDatabase.getWP(text); if (wpFromDB != nil) { From 45fd29792ca26c9be8b3aabc464ec01d7c8ee98c Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Tue, 15 Feb 2022 23:37:44 +0000 Subject: [PATCH 32/52] findAirportsByICAO --- Nasal/MCDU/INITA.nas | 66 +++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/Nasal/MCDU/INITA.nas b/Nasal/MCDU/INITA.nas index 563618ab..9daaf399 100644 --- a/Nasal/MCDU/INITA.nas +++ b/Nasal/MCDU/INITA.nas @@ -79,20 +79,23 @@ var initInputA = func(key, i) { #setprop("MCDU[" ~ i ~ "]/page", "ROUTESELECTION"); } else if (fmgc.FMGCInternal.toFromSet) { if (!fmgc.flightPlanController.temporaryFlag[i]) { - var tfs = size(scratchpad); - if (tfs == 4) { - fmgc.FMGCInternal.altAirport = scratchpad; - fmgc.FMGCInternal.altAirportSet = 1; - atsu.ATISInstances[2].newStation(scratchpad); - fmgc.windController.updatePlans(); - if (fmgc.FMGCInternal.blockConfirmed) { - fmgc.FMGCInternal.fuelCalculating = 0; - fmgc.fuelCalculating.setValue(0); - fmgc.FMGCInternal.fuelCalculating = 1; - fmgc.fuelCalculating.setValue(1); + if (size(scratchpad) == 4) { + if (size(findAirportsByICAO(scratchpad)) > 0) { + fmgc.FMGCInternal.altAirport = scratchpad; + fmgc.FMGCInternal.altAirportSet = 1; + atsu.ATISInstances[2].newStation(scratchpad); + fmgc.windController.updatePlans(); + if (fmgc.FMGCInternal.blockConfirmed) { + fmgc.FMGCInternal.fuelCalculating = 0; + fmgc.fuelCalculating.setValue(0); + fmgc.FMGCInternal.fuelCalculating = 1; + fmgc.fuelCalculating.setValue(1); + } + mcdu_scratchpad.scratchpads[i].empty(); + fmgc.updateARPT(); + } else { + mcdu_message(i, "NOT IN DATA BASE"); } - mcdu_scratchpad.scratchpads[i].empty(); - fmgc.updateARPT(); #fmgc.FMGCInternal.altSelected = 1; #setprop("MCDU[" ~ i ~ "]/page", "ROUTESELECTION"); } else { @@ -249,25 +252,26 @@ var initInputA = func(key, i) { #setprop("MCDU[" ~ i ~ "]/page", "ROUTESELECTION"); } else { if (!fmgc.flightPlanController.temporaryFlag[i]) { - var tfs = size(scratchpad); - if (tfs == 9 and find("/", scratchpad) != -1) { + if (size(scratchpad) == 9 and find("/", scratchpad) != -1) { var fromto = split("/", scratchpad); - var froms = size(fromto[0]); - var tos = size(fromto[1]); - if (froms == 4 and tos == 4) { - resetFlightplan(i); - fmgc.FMGCInternal.depApt = fromto[0]; - fmgc.FMGCInternal.arrApt = fromto[1]; - atsu.ATISInstances[0].newStation(fromto[0]); - atsu.ATISInstances[1].newStation(fromto[1]); - fmgc.FMGCInternal.toFromSet = 1; - fmgc.FMGCNodes.toFromSet.setValue(1); - mcdu_scratchpad.scratchpads[i].empty(); - - fmgc.flightPlanController.updateAirports(fromto[0], fromto[1], 2); - fmgc.FMGCInternal.altSelected = 0; - fmgc.updateARPT(); - fmgc.updateArptLatLon(); + if (size(fromto[0]) == 4 and size(fromto[1]) == 4) { + if (size(findAirportsByICAO(fromto[0])) > 0 and size(findAirportsByICAO(fromto[1])) > 0) { + resetFlightplan(i); + fmgc.FMGCInternal.depApt = fromto[0]; + fmgc.FMGCInternal.arrApt = fromto[1]; + atsu.ATISInstances[0].newStation(fromto[0]); + atsu.ATISInstances[1].newStation(fromto[1]); + fmgc.FMGCInternal.toFromSet = 1; + fmgc.FMGCNodes.toFromSet.setValue(1); + mcdu_scratchpad.scratchpads[i].empty(); + + fmgc.flightPlanController.updateAirports(fromto[0], fromto[1], 2); + fmgc.FMGCInternal.altSelected = 0; + fmgc.updateARPT(); + fmgc.updateArptLatLon(); + } else { + mcdu_message(i, "NOT IN DATA BASE"); + } #setprop("MCDU[" ~ i ~ "]/page", "ROUTESELECTION"); } else { mcdu_message(i, "NOT ALLOWED"); From cfbe7bae2dddb0cdae2ff7b71695f9479b921c52 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Thu, 12 May 2022 19:48:33 +0100 Subject: [PATCH 33/52] Re-add thing that was removed accidentally, which caused trip fuel to always be zero unless cruise temperature was manually set --- Models/Instruments/MCDU/MCDU.nas | 1 + 1 file changed, 1 insertion(+) diff --git a/Models/Instruments/MCDU/MCDU.nas b/Models/Instruments/MCDU/MCDU.nas index 30b28bba..7bad67cf 100644 --- a/Models/Instruments/MCDU/MCDU.nas +++ b/Models/Instruments/MCDU/MCDU.nas @@ -2776,6 +2776,7 @@ var canvas_MCDU_base = { me["INITA_CruiseFLTemp"].hide(); me["Simple_L6"].setColor(BLUE); fmgc.FMGCInternal.crzTemp = 15 - (2 * fmgc.FMGCInternal.crzFl / 10); + fmgc.FMGCInternal.crzTempSet = 1; me["Simple_L6"].setText(sprintf("%s", "FL" ~ fmgc.FMGCInternal.crzFl) ~ sprintf("/%+3.0f°", fmgc.FMGCInternal.crzTemp)); } else { me["INITA_CruiseFLTemp"].show(); From ebfbb4b037df207cdb77a9fa711ce566d3d6f44d Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Thu, 12 May 2022 21:41:47 +0100 Subject: [PATCH 34/52] Temporary fix - sync current WP after temporary flightplan sequencing --- Nasal/FMGC/flightplan.nas | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Nasal/FMGC/flightplan.nas b/Nasal/FMGC/flightplan.nas index 69f34220..9c799e8d 100644 --- a/Nasal/FMGC/flightplan.nas +++ b/Nasal/FMGC/flightplan.nas @@ -77,6 +77,7 @@ var flightPlanController = { me.arrivalIndex[n] = 0; # reset arrival index calculations }, + oldCurrentWp: 0, createTemporaryFlightPlan: func(n) { me.resetFlightplan(n); me.flightplans[n] = me.flightplans[2].clone(); @@ -91,6 +92,9 @@ var flightPlanController = { canvas_mcdu.myAirways[n].updateTmpy(); } fmgc.windController.createTemporaryWinds(n); + + me.oldCurrentWp = FPLN.currentWP.getValue(); + me.flightPlanChanged(n); }, @@ -161,6 +165,12 @@ var flightPlanController = { } fmgc.windController.destroyTemporaryWinds(n, a); + + # TODO - handle changed wpt order + if (FPLN.currentWP.getValue() != me.oldCurrentWp) { + FPLN.currentWP.setValue(me.oldCurrentWp); + } + me.flightPlanChanged(n); }, From e62e08fef1482386c2765d632614d17e3b20a4b1 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Thu, 12 May 2022 22:06:41 +0100 Subject: [PATCH 35/52] Fix that turn anticipation wouldn't work when the bearing of the previous leg is greater than 180 degrees --- Nasal/FMGC/FMGC-b.nas | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Nasal/FMGC/FMGC-b.nas b/Nasal/FMGC/FMGC-b.nas index 06563963..69f9b655 100644 --- a/Nasal/FMGC/FMGC-b.nas +++ b/Nasal/FMGC/FMGC-b.nas @@ -434,13 +434,7 @@ var ITAF = { # TODO - if in HDG mode, if no distance, then crosstrack error must be less than 5nm # TODO - if in nav, no distance condition applies, but DEST course error must be less than 30 (CONFIRM) - var enableFlyBy = 0; - var maxCourseDelta = 120; - if (abs(fmgc.flightPlanController.flightplans[2].getWP(FPLN.currentWPTemp).leg_bearing - fmgc.flightPlanController.flightplans[2].getWP(FPLN.currentWPTemp + 1).leg_bearing) < maxCourseDelta) { - enableFlyBy = 1; - } - - if (enableFlyBy and FPLN.wp0Dist.getValue() <= FPLN.turnDist and !Gear.wow1.getBoolValue() and fmgc.flightPlanController.flightplans[2].getWP(FPLN.currentWPTemp).fly_type == "flyBy") { + if (abs(FPLN.deltaAngle) < 120 and FPLN.wp0Dist.getValue() <= FPLN.turnDist and !Gear.wow1.getBoolValue() and fmgc.flightPlanController.flightplans[2].getWP(FPLN.currentWPTemp).fly_type == "flyBy") { flightPlanController.autoSequencing(); } elsif (FPLN.wp0Dist.getValue() <= 0.15 and !Gear.wow1.getBoolValue()) { flightPlanController.autoSequencing(); From 533583ce3f6a9f8ebd6aac23fa4c87676f96c8c3 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Fri, 13 May 2022 14:41:33 +0100 Subject: [PATCH 36/52] Fix miscellaneous bugs, including: - RETURN did not operate on DUPLICATE NAMES - Formatting of DUPLICATE NAMES LAT / LON did not have leading zeroes - Default SID did not set altitude constraint - Sequencing would occur repeatedly when paused --- Nasal/FMGC/flightplan.nas | 3 +++ Nasal/MCDU/F-PLN.nas | 3 ++- Nasal/MCDU/MCDU.nas | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Nasal/FMGC/flightplan.nas b/Nasal/FMGC/flightplan.nas index 9c799e8d..eeb80e63 100644 --- a/Nasal/FMGC/flightplan.nas +++ b/Nasal/FMGC/flightplan.nas @@ -215,6 +215,8 @@ var flightPlanController = { autoSequencing: func() { if (!me.active.getBoolValue()) { return; } + if (pts.Sim.Pause.getBoolValue()) { return; } + me.calculateTimeAltitudeOnSequence(); # Advancing logic @@ -328,6 +330,7 @@ var flightPlanController = { # fudge the altitude since we cannot create a hdgtoAlt from nasal. Assume 600 feet per mile - 2.5 miles me.flightplans[n].insertWP(createWP(me.childWPBearingDistance(wptStore, me.flightplans[n].departure_runway.heading, 2.5 + (me.flightplans[n].departure_runway.length * M2NM)), "1500", "sid"), 1); me.flightplans[n].getWP(1).fly_type = "flyOver"; + me.flightplans[n].getWP(1).setAltitude(1500, "at"); fmgc.windController.insertWind(n, 1, 0, "1500"); } me.flightPlanChanged(n); diff --git a/Nasal/MCDU/F-PLN.nas b/Nasal/MCDU/F-PLN.nas index 149915cc..27d29162 100644 --- a/Nasal/MCDU/F-PLN.nas +++ b/Nasal/MCDU/F-PLN.nas @@ -665,8 +665,9 @@ var decimalToShortString = func(dms, type) { var degrees = split(".", sprintf(dms))[0]; if (type == "lat") { var sign = degrees >= 0 ? "N" : "S"; + return sprintf("%02d", abs(degrees)) ~ sign; } else { var sign = degrees >= 0 ? "E" : "W"; + return sprintf("%03d", abs(degrees)) ~ sign; } - return abs(degrees) ~ sign; } \ No newline at end of file diff --git a/Nasal/MCDU/MCDU.nas b/Nasal/MCDU/MCDU.nas index 13876702..7de16207 100644 --- a/Nasal/MCDU/MCDU.nas +++ b/Nasal/MCDU/MCDU.nas @@ -851,6 +851,8 @@ var lskbutton = func(btn, i) { } else { if (canvas_mcdu.myDuplicate[i] != nil and canvas_mcdu.myDuplicate[i].flagPROG) { pagebutton("prog",i); + } else { + pageNode[i].setValue("F-PLNA"); } } } else if (page == "ARRIVAL") { From 6cb990b8f6f5ba3f32d746e74b4fdea6ad8a9dd2 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Fri, 13 May 2022 14:58:44 +0100 Subject: [PATCH 37/52] Update DECEL always (before it would not disappear until range or mode was changed --- Models/Instruments/ND/canvas/style.nas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Models/Instruments/ND/canvas/style.nas b/Models/Instruments/ND/canvas/style.nas index bd58f97a..052bab9a 100644 --- a/Models/Instruments/ND/canvas/style.nas +++ b/Models/Instruments/ND/canvas/style.nas @@ -593,7 +593,7 @@ canvas.NDStyles["Airbus"] = { { name: "DECEL", isMapStructure: 1, - update_on: ["toggle_display_mode","toggle_range"], + update_on: [ {rate_hz: 1}, "toggle_display_mode","toggle_range"], predicate: func(nd, layer) { var visible = nd.in_mode("toggle_display_mode", ["MAP", "PLAN"]) and (nd.adirs_property.getValue() == 1 or (adirs_3.getValue() == 1 and att_switch.getValue() == nd.attitude_heading_setting)) and getprop("/instrumentation/nd/symbols/decel/show"); layer.group.setVisible( visible ); From e6e0679a8166323d8dee7e0140bb5980f831f3e4 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Fri, 13 May 2022 15:33:27 +0100 Subject: [PATCH 38/52] Hide the DECEL after the sequencing. Fix a nasal error where the static text broke the direct to --- Nasal/FMGC/FMGC.nas | 1 + Nasal/MCDU/DIRTO.nas | 3 ++- Nasal/MCDU/PERFCLB.nas | 1 + Nasal/MCDU/PERFCRZ.nas | 1 + Nasal/MCDU/PERFDES.nas | 1 + 5 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Nasal/FMGC/FMGC.nas b/Nasal/FMGC/FMGC.nas index 5a82d759..374bc26a 100644 --- a/Nasal/FMGC/FMGC.nas +++ b/Nasal/FMGC/FMGC.nas @@ -643,6 +643,7 @@ var masterFMGC = maketimer(0.2, func { courseDistanceDecel = courseAndDistance(flightPlanController.decelPoint.lat, flightPlanController.decelPoint.lon); if (flightPlanController.num[2].getValue() > 0 and fmgc.flightPlanController.active.getBoolValue() and flightPlanController.decelPoint != nil and (courseDistanceDecel[1] <= 5 and (math.abs(courseDistanceDecel[0] - pts.Orientation.heading.getValue()) >= 90 and xtrkError <= 5) or courseDistanceDecel[1] <= 0.1) and (modelat == "NAV" or modelat == "LOC" or modelat == "LOC*") and pts.Position.gearAglFt.getValue() < 9500) { FMGCInternal.decel = 1; + setprop("/instrumentation/nd/symbols/decel/show", 0); } elsif (FMGCInternal.decel and (FMGCInternal.phase == 0 or FMGCInternal.phase == 6)) { FMGCInternal.decel = 0; } diff --git a/Nasal/MCDU/DIRTO.nas b/Nasal/MCDU/DIRTO.nas index eabb0e3f..1421c4f6 100644 --- a/Nasal/MCDU/DIRTO.nas +++ b/Nasal/MCDU/DIRTO.nas @@ -83,7 +83,8 @@ var dirTo = { var dirToLeftIndex = 0; me.vector = []; for (var i = 1 + (me.scroll); i < size(canvas_mcdu.myFpln[me.computer].planList) - 2; i = i + 1) { - if (canvas_mcdu.myFpln[me.computer].planList[i].wp == "PSEUDO" or canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_name == "DISCONTINUITY" or canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_name == "VECTORS" or canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_name == "T-P" or canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_type == "hdgToAlt") { continue; } + debug.dump(canvas_mcdu.myFpln[me.computer].planList[i].wp); + if (canvas_mcdu.myFpln[me.computer].planList[i].wp == "PSEUDO" or canvas_mcdu.myFpln[me.computer].planList[i].wp == "STATIC" or canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_name == "DISCONTINUITY" or canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_name == "VECTORS" or canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_name == "T-P" or canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_type == "hdgToAlt") { continue; } if (canvas_mcdu.myFpln[me.computer].planList[i].index > fmgc.flightPlanController.arrivalIndex[2]) { continue; } append(me.vector, canvas_mcdu.myFpln[me.computer].planList[i].wp); dirToLeftIndex += 1; diff --git a/Nasal/MCDU/PERFCLB.nas b/Nasal/MCDU/PERFCLB.nas index ee45ead1..cbf4af0a 100644 --- a/Nasal/MCDU/PERFCLB.nas +++ b/Nasal/MCDU/PERFCLB.nas @@ -39,6 +39,7 @@ var perfCLBInput = func(key, i) { setprop("/FMGC/internal/activate-twice", 1); fmgc.FMGCInternal.phase = 5; fmgc.FMGCInternal.decel = 1; + setprop("/instrumentation/nd/symbols/decel/show", 0); setprop("MCDU[" ~ i ~ "]/page", "PERFAPPR"); } else { mcdu_message(i, "NOT ALLOWED"); diff --git a/Nasal/MCDU/PERFCRZ.nas b/Nasal/MCDU/PERFCRZ.nas index 87d041e7..801bdfb8 100644 --- a/Nasal/MCDU/PERFCRZ.nas +++ b/Nasal/MCDU/PERFCRZ.nas @@ -33,6 +33,7 @@ var perfCRZInput = func(key, i) { setprop("/FMGC/internal/activate-twice", 1); fmgc.FMGCInternal.phase = 5; fmgc.FMGCInternal.decel = 1; + setprop("/instrumentation/nd/symbols/decel/show", 0); setprop("MCDU[" ~ i ~ "]/page", "PERFAPPR"); } else { mcdu_message(i, "NOT ALLOWED"); diff --git a/Nasal/MCDU/PERFDES.nas b/Nasal/MCDU/PERFDES.nas index def27ef8..ab92bfc5 100644 --- a/Nasal/MCDU/PERFDES.nas +++ b/Nasal/MCDU/PERFDES.nas @@ -33,6 +33,7 @@ var perfDESInput = func(key, i) { setprop("/FMGC/internal/activate-twice", 1); fmgc.FMGCInternal.phase = 5; fmgc.FMGCInternal.decel = 1; + setprop("/instrumentation/nd/symbols/decel/show", 0); setprop("MCDU[" ~ i ~ "]/page", "PERFAPPR"); } else { mcdu_message(i, "NOT ALLOWED"); From be32f89d7d12ab40ece62b37c816fa4c7346f560 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Fri, 13 May 2022 15:41:46 +0100 Subject: [PATCH 39/52] Fix typo --- Nasal/FMGC/flightplan.nas | 2 +- Nasal/MCDU/DIRTO.nas | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Nasal/FMGC/flightplan.nas b/Nasal/FMGC/flightplan.nas index eeb80e63..191a069a 100644 --- a/Nasal/FMGC/flightplan.nas +++ b/Nasal/FMGC/flightplan.nas @@ -215,7 +215,7 @@ var flightPlanController = { autoSequencing: func() { if (!me.active.getBoolValue()) { return; } - if (pts.Sim.Pause.getBoolValue()) { return; } + if (pts.Sim.pause.getBoolValue()) { return; } me.calculateTimeAltitudeOnSequence(); diff --git a/Nasal/MCDU/DIRTO.nas b/Nasal/MCDU/DIRTO.nas index 1421c4f6..ba0194ef 100644 --- a/Nasal/MCDU/DIRTO.nas +++ b/Nasal/MCDU/DIRTO.nas @@ -83,7 +83,6 @@ var dirTo = { var dirToLeftIndex = 0; me.vector = []; for (var i = 1 + (me.scroll); i < size(canvas_mcdu.myFpln[me.computer].planList) - 2; i = i + 1) { - debug.dump(canvas_mcdu.myFpln[me.computer].planList[i].wp); if (canvas_mcdu.myFpln[me.computer].planList[i].wp == "PSEUDO" or canvas_mcdu.myFpln[me.computer].planList[i].wp == "STATIC" or canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_name == "DISCONTINUITY" or canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_name == "VECTORS" or canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_name == "T-P" or canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_type == "hdgToAlt") { continue; } if (canvas_mcdu.myFpln[me.computer].planList[i].index > fmgc.flightPlanController.arrivalIndex[2]) { continue; } append(me.vector, canvas_mcdu.myFpln[me.computer].planList[i].wp); From 3d1046c195e023f788cf1383712a385e51f28a0b Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Fri, 13 May 2022 16:41:09 +0100 Subject: [PATCH 40/52] Fix that it would occasionally go to waypoint index -1 --- Nasal/FMGC/flightplan.nas | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Nasal/FMGC/flightplan.nas b/Nasal/FMGC/flightplan.nas index 191a069a..e3f0ad24 100644 --- a/Nasal/FMGC/flightplan.nas +++ b/Nasal/FMGC/flightplan.nas @@ -78,6 +78,7 @@ var flightPlanController = { }, oldCurrentWp: 0, + lastSequencedCurrentWP: 0, createTemporaryFlightPlan: func(n) { me.resetFlightplan(n); me.flightplans[n] = me.flightplans[2].clone(); @@ -166,7 +167,6 @@ var flightPlanController = { fmgc.windController.destroyTemporaryWinds(n, a); - # TODO - handle changed wpt order if (FPLN.currentWP.getValue() != me.oldCurrentWp) { FPLN.currentWP.setValue(me.oldCurrentWp); } @@ -230,6 +230,8 @@ var flightPlanController = { fmgc.Input.lat.setValue(3); } else { me.currentToWptIndex.setValue(me.currentToWptIndexTemp + 1); + me.lastSequencedCurrentWP = me.currentToWptIndexTemp + 1; + if (me.num[2].getValue() > 2 and me.currentToWptIndexTemp >= 1) { for (var i = 0; i <= 2; i += 1) { if (i == 2 or me.temporaryFlag[i]) { @@ -865,6 +867,11 @@ var flightPlanController = { me.active.setValue(0); } + if (me.active.getBoolValue() and me.currentToWptIndex.getValue() == -1) { + print("Setting index to " ~ me.lastSequencedCurrentWP); + me.currentToWptIndex.setValue(me.lastSequencedCurrentWP); + } + for (var n = 0; n <= 2; n += 1) { for (var wpt = 0; wpt < me.flightplans[n].getPlanSize(); wpt += 1) { # Iterate through the waypoints and update their data var waypointHashStore = me.flightplans[n].getWP(wpt); From ab0f6de482742f795f1cdddb9d03818fcdf7c4be Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Fri, 13 May 2022 16:50:24 +0100 Subject: [PATCH 41/52] Remove debug info and comments --- Nasal/FMGC/flightplan.nas | 1 - Nasal/MCDU/F-PLN.nas | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Nasal/FMGC/flightplan.nas b/Nasal/FMGC/flightplan.nas index e3f0ad24..9fcc9309 100644 --- a/Nasal/FMGC/flightplan.nas +++ b/Nasal/FMGC/flightplan.nas @@ -868,7 +868,6 @@ var flightPlanController = { } if (me.active.getBoolValue() and me.currentToWptIndex.getValue() == -1) { - print("Setting index to " ~ me.lastSequencedCurrentWP); me.currentToWptIndex.setValue(me.lastSequencedCurrentWP); } diff --git a/Nasal/MCDU/F-PLN.nas b/Nasal/MCDU/F-PLN.nas index 27d29162..5ec16f8c 100644 --- a/Nasal/MCDU/F-PLN.nas +++ b/Nasal/MCDU/F-PLN.nas @@ -136,7 +136,7 @@ var fplnItem = { if (me.index == 0 and left(me.wp.wp_name, 4) == fmgc.FMGCInternal.depApt and fmgc.FMGCInternal.v1set) { return [sprintf("%3.0f", math.round(fmgc.FMGCInternal.v1)), "grn"]; # why "mag"? I think "grn" } elsif (me.wp.speed_cstr != nil and me.wp.speed_cstr > 0) { - var tcol = (me.wp.speed_cstr_type == "computed" or me.wp.speed_cstr_type == "computed_mach") ? "grn" : "mag"; # TODO - check if only computed + var tcol = (me.wp.speed_cstr_type == "computed" or me.wp.speed_cstr_type == "computed_mach") ? "grn" : "mag"; return [sprintf("%3.0f", me.wp.speed_cstr), tcol]; } else { return ["---", "wht"]; @@ -148,7 +148,7 @@ var fplnItem = { } elsif (me.index == (fmgc.flightPlanController.currentToWptIndex.getValue() - 1) and fmgc.flightPlanController.fromWptAlt != nil) { return [" " ~ fmgc.flightPlanController.fromWptAlt, "mag"]; } elsif (me.wp.alt_cstr != nil and me.wp.alt_cstr > 0) { - var tcol = (me.wp.alt_cstr_type == "computed" or me.wp.alt_cstr_type == "computed_mach") ? "grn" : "mag"; # TODO - check if only computed + var tcol = (me.wp.alt_cstr_type == "computed" or me.wp.alt_cstr_type == "computed_mach") ? "grn" : "mag"; var cstrAlt = ""; if (me.wp.alt_cstr > fmgc.FMGCInternal.transAlt) { From 30bbb196d37e1eaebb3b7aab163473ba9d362b21 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Sun, 15 May 2022 17:24:10 +0100 Subject: [PATCH 42/52] Spelling fix for GPS delegate --- Nasal/FMGC/flightplan-delegates.nas | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Nasal/FMGC/flightplan-delegates.nas b/Nasal/FMGC/flightplan-delegates.nas index 377e424f..aebe2bab 100644 --- a/Nasal/FMGC/flightplan-delegates.nas +++ b/Nasal/FMGC/flightplan-delegates.nas @@ -33,9 +33,9 @@ var GPSPath = "/instrumentation/gps"; # route sequencing and activation # -var A320GPSDeleagte = { +var A320GPSDelegate = { new: func(fp) { - var m = { parents: [A320GPSDeleagte], flightplan:fp, landingCheck:nil }; + var m = { parents: [A320GPSDelegate], flightplan:fp, landingCheck:nil }; logprint(LOG_INFO, 'creating A320 GPS FPDelegate'); @@ -44,7 +44,7 @@ var A320GPSDeleagte = { setprop(GPSPath ~ '/config/delegate-sequencing', 1); - # enable 2020.2 C++ turn anticipation + # disable turn anticipation setprop(GPSPath ~ '/config/enable-fly-by', 0); # flyOver maximum distance @@ -52,6 +52,7 @@ var A320GPSDeleagte = { fp.followLegTrackToFix = 1; fp.aircraftCategory = 'C'; + m._modeProp = props.globals.getNode(GPSPath ~ '/mode'); return m; }, @@ -146,11 +147,11 @@ var A320GPSDeleagte = { (activeRunway != nil) and (me.flightplan.destination_runway != nil) and (activeRunway.id == me.flightplan.destination_runway.id)) { - me.landingCheck = maketimer(2.0, me, A320GPSDeleagte._landingCheckTimeout); + me.landingCheck = maketimer(2.0, me, A320GPSDelegate._landingCheckTimeout); me.landingCheck.start(); } } }; -registerFlightPlanDelegate(A320GPSDeleagte.new); +registerFlightPlanDelegate(A320GPSDelegate.new); From 285da1f974bbfca8b222dada0d4d6ccffba59c50 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Sun, 15 May 2022 22:49:53 +0100 Subject: [PATCH 43/52] Re-enable delegate sequencing; which will handle radial intercepts through the GPS controller --- Nasal/FMGC/flightplan-delegates.nas | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Nasal/FMGC/flightplan-delegates.nas b/Nasal/FMGC/flightplan-delegates.nas index aebe2bab..2bf1709a 100644 --- a/Nasal/FMGC/flightplan-delegates.nas +++ b/Nasal/FMGC/flightplan-delegates.nas @@ -122,7 +122,20 @@ var A320GPSDelegate = { sequence: func { - return; + if (!me.flightplan.active) + return; + + if (me._modeProp.getValue() == 'leg') { + if (me.flightplan.nextWP().wp_type == 'discontinuity') { + logprint(LOG_INFO, "default GPS sequencing DISCONTINUITY in flightplan, switching to HDG"); + # set HDG mode + } else { + logprint(LOG_INFO, "default GPS sequencing to next WP"); + me.flightplan.current = me.flightplan.current + 1; + } + } else { + # OBS, do nothing + } }, currentWaypointChanged: func From ec1c5142ec46a13e82606b0c03751c91451d6a76 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Sun, 15 May 2022 22:58:12 +0100 Subject: [PATCH 44/52] Post-discontinuity - prevent GPS log spam --- Nasal/FMGC/flightplan-delegates.nas | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Nasal/FMGC/flightplan-delegates.nas b/Nasal/FMGC/flightplan-delegates.nas index 2bf1709a..89bf33c8 100644 --- a/Nasal/FMGC/flightplan-delegates.nas +++ b/Nasal/FMGC/flightplan-delegates.nas @@ -128,6 +128,8 @@ var A320GPSDelegate = { if (me._modeProp.getValue() == 'leg') { if (me.flightplan.nextWP().wp_type == 'discontinuity') { logprint(LOG_INFO, "default GPS sequencing DISCONTINUITY in flightplan, switching to HDG"); + me._captureCurrentCourse(); + me._selectOBSMode(); # set HDG mode } else { logprint(LOG_INFO, "default GPS sequencing to next WP"); From e45101b03fd23822bd58d5318a9b167bf98e9220 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Mon, 16 May 2022 15:31:27 +0100 Subject: [PATCH 45/52] Restore end of fpln behaviour --- Nasal/FMGC/flightplan-delegates.nas | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Nasal/FMGC/flightplan-delegates.nas b/Nasal/FMGC/flightplan-delegates.nas index 89bf33c8..50859277 100644 --- a/Nasal/FMGC/flightplan-delegates.nas +++ b/Nasal/FMGC/flightplan-delegates.nas @@ -125,9 +125,13 @@ var A320GPSDelegate = { if (!me.flightplan.active) return; - if (me._modeProp.getValue() == 'leg') { - if (me.flightplan.nextWP().wp_type == 'discontinuity') { + if (me._modeProp.getValue() == 'leg') { + if (me.flightplan.current + 1 >= me.flightplan.numWaypoints()) { + logprint(LOG_INFO, "default GPS sequencing, finishing flightplan"); + me.flightplan.finish(); + } elsif (me.flightplan.nextWP().wp_type == 'discontinuity') { logprint(LOG_INFO, "default GPS sequencing DISCONTINUITY in flightplan, switching to HDG"); + me._captureCurrentCourse(); me._selectOBSMode(); # set HDG mode From 763b12c26c914eddd5767317ff1388b53ee6c72b Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Mon, 16 May 2022 16:02:44 +0100 Subject: [PATCH 46/52] Fix FCU - it wouldn't engage NAV on the last waypoint --- Nasal/FMGC/FCU.nas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Nasal/FMGC/FCU.nas b/Nasal/FMGC/FCU.nas index 2f91c54c..87f0851c 100644 --- a/Nasal/FMGC/FCU.nas +++ b/Nasal/FMGC/FCU.nas @@ -263,7 +263,7 @@ var FCUController = { HDGPush: func() { if (me.FCUworking) { if (fmgc.Output.fd1.getBoolValue() or fmgc.Output.fd2.getBoolValue() or fmgc.Output.ap1.getBoolValue() or fmgc.Output.ap2.getBoolValue()) { - var wp = fmgc.flightPlanController.flightplans[2].getWP(fmgc.flightPlanController.currentToWptIndex.getValue() + 1); + var wp = fmgc.flightPlanController.flightplans[2].getWP(fmgc.flightPlanController.currentToWptIndex.getValue()); if (wp != nil and wp.wp_type != "discontinuity") { fmgc.Input.lat.setValue(1); } From 8bbe755c7c5dce28b7118d479714ebff0ea4e049 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Mon, 16 May 2022 17:13:14 +0100 Subject: [PATCH 47/52] Handle MANUAL legs properly --- Nasal/FMGC/flightplan-delegates.nas | 130 ++++++++++++++++++++++++++-- Nasal/FMGC/flightplan.nas | 7 +- Nasal/Libraries/libraries.nas | 2 +- Nasal/MCDU/F-PLN.nas | 14 +-- 4 files changed, 139 insertions(+), 14 deletions(-) diff --git a/Nasal/FMGC/flightplan-delegates.nas b/Nasal/FMGC/flightplan-delegates.nas index 50859277..4938c00b 100644 --- a/Nasal/FMGC/flightplan-delegates.nas +++ b/Nasal/FMGC/flightplan-delegates.nas @@ -20,6 +20,127 @@ # You can disable the default GPS behaviour *without* touching this delegate : they are # kept seperate since this first one is less likely to need changes + +var A320RouteManagerDelegate = { + new: func(fp) { + var m = { parents: [A320RouteManagerDelegate] }; + + logprint(LOG_INFO, 'creating A320 Route Manager FPDelegate'); + + m.flightplan = fp; + return m; + }, + + departureChanged: func + { + logprint(LOG_INFO, 'saw departure changed'); + me.flightplan.clearWPType('sid'); + if (me.flightplan.departure == nil) + return; + + if (me.flightplan.departure_runway == nil) { + # no runway, only an airport, use that + var wp = createWPFrom(me.flightplan.departure); + wp.wp_role = 'sid'; + me.flightplan.insertWP(wp, 0); + return; + } + # first, insert the runway itself + var wp = createWPFrom(me.flightplan.departure_runway); + wp.wp_role = 'sid'; + me.flightplan.insertWP(wp, 0); + if (me.flightplan.sid == nil) + return; + + # and we have a SID + var sid = me.flightplan.sid; + logprint(LOG_INFO, 'routing via SID ' ~ sid.id); + me.flightplan.insertWaypoints(sid.route(me.flightplan.departure_runway, me.flightplan.sid_trans), 1); + + for (var wpIdx = 0; wpIdx < me.flightplan.getPlanSize(); wpIdx = wpIdx + 1) { + if (me.flightplan.getWP(wpIdx).wp_type == "vectors" and (me.flightplan.getWP(wpIdx + 1) == nil or me.flightplan.getWP(wpIdx + 1).wp_type != "discontinuity")) { + me.flightplan.insertWP(createDiscontinuity(), wpIdx + 1); + } + } + }, + + arrivalChanged: func + { + me.flightplan.clearWPType('star'); + me.flightplan.clearWPType('approach'); + if (me.flightplan.destination == nil) + return; + + if (me.flightplan.destination_runway == nil) { + # no runway, only an airport, use that + var wp = createWPFrom(me.flightplan.destination); + wp.wp_role = 'approach'; + me.flightplan.appendWP(wp); + return; + } + + var initialApproachFix = nil; + if (me.flightplan.star != nil) { + logprint(LOG_INFO, 'routing via STAR ' ~ me.flightplan.star.id); + var wps = me.flightplan.star.route(me.flightplan.destination_runway, me.flightplan.star_trans); + if (wps != nil) { + me.flightplan.insertWaypoints(wps, -1); + initialApproachFix = wps[-1]; # final waypoint of STAR + } + } + + if (me.flightplan.approach != nil) { + var wps = nil; + var approachIdent = me.flightplan.approach.id; + + if (me.flightplan.approach_trans != nil) { + # if an approach transition was specified, let's use it explicitly + wps = me.flightplan.approach.route(me.flightplan.destination_runway, me.flightplan.approach_trans); + if (wps == nil) { + logprint(LOG_WARN, "couldn't route approach " ~ approachIdent ~ " based on specified transition:" ~ me.flightplan.approach_trans); + } + } else if (initialApproachFix != nil) { + # no explicit approach transition, let's use the IAF to guess one + wps = me.flightplan.approach.route(me.flightplan.destination_runway, initialApproachFix); + if (wps == nil) { + logprint(LOG_INFO, "couldn't route approach " ~ approachIdent ~ " based on IAF:" ~ initialApproachFix.wp_name); + } + } + + # depending on the order the user selects the approach or STAR, we might get into + # a mess here. If we failed to route so far, just try a direct to the approach + if (wps == nil) { + # route direct + wps = me.flightplan.approach.route(me.flightplan.destination_runway); + } + + if (wps == nil) { + logprint(LOG_WARN, 'routing via approach ' ~ approachIdent ~ ' failed entirely.'); + } else { + me.flightplan.insertWaypoints(wps, -1); + } + } else { + # no approach, just use the runway waypoint + var wp = createWPFrom(me.flightplan.destination_runway); + wp.wp_role = 'approach'; + me.flightplan.appendWP(wp); + } + }, + + cleared: func + { + logprint(LOG_INFO, "saw active flightplan cleared, deactivating"); + # see http://https://code.google.com/p/flightgear-bugs/issues/detail?id=885 + fgcommand("activate-flightplan", props.Node.new({"activate": 0})); + }, + + endOfFlightPlan: func + { + logprint(LOG_INFO, "end of flight-plan, deactivating"); + fgcommand("activate-flightplan", props.Node.new({"activate": 0})); + } +}; + var GPSPath = "/instrumentation/gps"; # this delegate corresponds to the default behaviour of the built-in GPS. @@ -129,13 +250,7 @@ var A320GPSDelegate = { if (me.flightplan.current + 1 >= me.flightplan.numWaypoints()) { logprint(LOG_INFO, "default GPS sequencing, finishing flightplan"); me.flightplan.finish(); - } elsif (me.flightplan.nextWP().wp_type == 'discontinuity') { - logprint(LOG_INFO, "default GPS sequencing DISCONTINUITY in flightplan, switching to HDG"); - - me._captureCurrentCourse(); - me._selectOBSMode(); - # set HDG mode - } else { + } elsif (me.flightplan.nextWP().wp_type != 'discontinuity' and me.flightplan.nextWP().wp_type != 'vectors') { logprint(LOG_INFO, "default GPS sequencing to next WP"); me.flightplan.current = me.flightplan.current + 1; } @@ -173,4 +288,5 @@ var A320GPSDelegate = { }; registerFlightPlanDelegate(A320GPSDelegate.new); +registerFlightPlanDelegate(A320RouteManagerDelegate.new); diff --git a/Nasal/FMGC/flightplan.nas b/Nasal/FMGC/flightplan.nas index 9fcc9309..f8d39444 100644 --- a/Nasal/FMGC/flightplan.nas +++ b/Nasal/FMGC/flightplan.nas @@ -229,6 +229,11 @@ var flightPlanController = { if (me.flightplans[2].getWP(me.currentToWptIndexTemp + 1).wp_type == "discontinuity") { fmgc.Input.lat.setValue(3); } else { + if (me.flightplans[2].getWP(me.currentToWptIndexTemp + 1).wp_type == "vectors") { + fmgc.Input.lat.setValue(3); + me.flightplans[2].deleteWP(me.currentToWptIndexTemp + 2); + } + me.currentToWptIndex.setValue(me.currentToWptIndexTemp + 1); me.lastSequencedCurrentWP = me.currentToWptIndexTemp + 1; @@ -408,7 +413,7 @@ var flightPlanController = { } } } else { - if (me.flightplans[n].getWP(index).id == "DISCONTINUITY" and index > 0 and me.flightplans[n].getWP(index - 1).id == "PPOS") { + if (me.flightplans[n].getWP(index).id == "DISCONTINUITY" and index > 0 and (me.flightplans[n].getWP(index - 1).id == "PPOS" or find(me.flightplans[n].getWP(index - 1).id, "VECTORS"))) { return 1; } else { me.flightplans[n].deleteWP(index); diff --git a/Nasal/Libraries/libraries.nas b/Nasal/Libraries/libraries.nas index 3fe23fac..ca600559 100644 --- a/Nasal/Libraries/libraries.nas +++ b/Nasal/Libraries/libraries.nas @@ -7,7 +7,7 @@ print("------------------------------------------------"); print("Copyright (c) 2016-2020 Josh Davidson (Octal450)"); print("------------------------------------------------"); -# setprop("/autopilot/route-manager/disable-route-manager", 1); +setprop("/autopilot/route-manager/disable-route-manager", 1); setprop("/autopilot/route-manager/disable-fms", 1); # Disable specific menubar items diff --git a/Nasal/MCDU/F-PLN.nas b/Nasal/MCDU/F-PLN.nas index 5ec16f8c..9b4d898d 100644 --- a/Nasal/MCDU/F-PLN.nas +++ b/Nasal/MCDU/F-PLN.nas @@ -120,10 +120,14 @@ var fplnItem = { }, getBrg: func() { var wp = fmgc.flightPlanController.flightplans[me.plan].getWP(me.index); - var courseDistanceFrom = courseAndDistance(wp); - me.brg = courseDistanceFrom[0] - magvar(); - if (me.brg < 0) { me.brg += 360; } - if (me.brg > 360) { me.brg -= 360; } + if (wp.wp_type == "vectors") { + me.brg = pts.Orientation.heading.getValue(); + } else { + var courseDistanceFrom = courseAndDistance(wp); + me.brg = courseDistanceFrom[0] - magvar(); + if (me.brg < 0) { me.brg += 360; } + if (me.brg > 360) { me.brg -= 360; } + } return sprintf("%03.0f", math.round(me.brg)); }, getTrack: func() { @@ -174,7 +178,7 @@ var fplnItem = { } else { if (me.plan == 2 and decelShow and me.index == decelIndex and fmgc.flightPlanController.decelPoint != nil) { return sprintf("%3.0f", courseAndDistance(fmgc.flightPlanController.decelPoint, me.wp)[1]); - } else if (prevwp != nil and prevwp.wp_name != "DISCONTINUITY") { + } else if (prevwp != nil and (prevwp.wp_name != "DISCONTINUITY" or find(prevwp.wp_name, "VECTORS"))) { return sprintf("%3.0f", math.round(me.wp.leg_distance)); } else { return " --"; From 252501a0cae17e30220904df1ee62f7190a06161 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Mon, 16 May 2022 21:09:36 +0100 Subject: [PATCH 48/52] Flightplan stringing: if the last waypoint of a SID is found en-route, then we delete all preceeding points according to the manual --- Nasal/FMGC/flightplan-delegates.nas | 21 ++++++++++++++++++++- Nasal/FMGC/flightplan.nas | 7 +++---- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/Nasal/FMGC/flightplan-delegates.nas b/Nasal/FMGC/flightplan-delegates.nas index 4938c00b..fff9b3d5 100644 --- a/Nasal/FMGC/flightplan-delegates.nas +++ b/Nasal/FMGC/flightplan-delegates.nas @@ -55,7 +55,26 @@ var A320RouteManagerDelegate = { # and we have a SID var sid = me.flightplan.sid; logprint(LOG_INFO, 'routing via SID ' ~ sid.id); - me.flightplan.insertWaypoints(sid.route(me.flightplan.departure_runway, me.flightplan.sid_trans), 1); + + var wps = sid.route(me.flightplan.departure_runway, me.flightplan.sid_trans); + var lastWP = wps[-1]; + var foundIdx = -999; + + for (var wptIdx = 0; wptIdx < me.flightplan.getPlanSize(); wptIdx = wptIdx + 1) { + if (me.flightplan.getWP(wptIdx).id == lastWP.id) { + foundIdx = wptIdx; + break; + } + } + + if (foundIdx != -999) { + while (foundIdx > 0) { + me.flightplan.deleteWP(1); + foundIdx -= 1; + } + } + + me.flightplan.insertWaypoints(wps, 1); for (var wpIdx = 0; wpIdx < me.flightplan.getPlanSize(); wpIdx = wpIdx + 1) { if (me.flightplan.getWP(wpIdx).wp_type == "vectors" and (me.flightplan.getWP(wpIdx + 1) == nil or me.flightplan.getWP(wpIdx + 1).wp_type != "discontinuity")) { diff --git a/Nasal/FMGC/flightplan.nas b/Nasal/FMGC/flightplan.nas index f8d39444..da218879 100644 --- a/Nasal/FMGC/flightplan.nas +++ b/Nasal/FMGC/flightplan.nas @@ -403,17 +403,16 @@ var flightPlanController = { deleteWP: func(index, n, a = 0) { # a = 1, means adding a waypoint via deleting intermediate var wp = me.flightplans[n].getWP(index); if ((left(wp.wp_name, 4) != FMGCInternal.depApt and left(wp.wp_name, 4) != FMGCInternal.arrApt) and me.flightplans[n].getPlanSize() > 2) { - - if (me.flightplans[n].getWP(index).id != "DISCONTINUITY" and a == 0) { # if it is a discont, don't make a new one + if (wp.id != "DISCONTINUITY" and a == 0) { # if it is a discont, don't make a new one me.flightplans[n].deleteWP(index); fmgc.windController.deleteWind(n, index); - if (me.flightplans[n].getWP(index) != nil) { + if (me.flightplans[n].getWP(index) != nil) { # This refers to the next one after the one we deleted if (me.flightplans[n].getWP(index).id != "DISCONTINUITY") { # else, if the next one isn't a discont, add one me.addDiscontinuity(index, n); } } } else { - if (me.flightplans[n].getWP(index).id == "DISCONTINUITY" and index > 0 and (me.flightplans[n].getWP(index - 1).id == "PPOS" or find(me.flightplans[n].getWP(index - 1).id, "VECTORS"))) { + if (wp.id == "DISCONTINUITY" and index > 0 and (me.flightplans[n].getWP(index - 1).id == "PPOS" or find("VECTORS", me.flightplans[n].getWP(index - 1).id) != -1)) { return 1; } else { me.flightplans[n].deleteWP(index); From ef17f979b8ba0e416f4e38207fe5de1087db1a31 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Mon, 16 May 2022 21:30:52 +0100 Subject: [PATCH 49/52] Fix C6S being blue after visiting ARRIVAL --- Models/Instruments/MCDU/MCDU.nas | 1 + 1 file changed, 1 insertion(+) diff --git a/Models/Instruments/MCDU/MCDU.nas b/Models/Instruments/MCDU/MCDU.nas index 7bad67cf..30ece379 100644 --- a/Models/Instruments/MCDU/MCDU.nas +++ b/Models/Instruments/MCDU/MCDU.nas @@ -578,6 +578,7 @@ var canvas_MCDU_base = { me.colorLeftS("wht", "wht", "wht", "wht", "wht", "wht"); me.colorLeftArrow("wht", "wht", "wht", "wht", "wht", "wht"); + me.colorCenterS("wht", "wht", "wht", "wht", "wht", "wht"); me.colorRightS("wht", "wht", "wht", "wht", "wht", "wht"); me.colorRightArrow("wht", "wht", "wht", "wht", "wht", "wht"); From c39fddb05b1a708b50b3cf2e6a8a39745df121a6 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Thu, 19 May 2022 21:37:19 +0100 Subject: [PATCH 50/52] Fix logic error in SID discontinuity logic --- Nasal/FMGC/flightplan-delegates.nas | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Nasal/FMGC/flightplan-delegates.nas b/Nasal/FMGC/flightplan-delegates.nas index fff9b3d5..2cecfa6b 100644 --- a/Nasal/FMGC/flightplan-delegates.nas +++ b/Nasal/FMGC/flightplan-delegates.nas @@ -75,9 +75,9 @@ var A320RouteManagerDelegate = { } me.flightplan.insertWaypoints(wps, 1); - + for (var wpIdx = 0; wpIdx < me.flightplan.getPlanSize(); wpIdx = wpIdx + 1) { - if (me.flightplan.getWP(wpIdx).wp_type == "vectors" and (me.flightplan.getWP(wpIdx + 1) == nil or me.flightplan.getWP(wpIdx + 1).wp_type != "discontinuity")) { + if (me.flightplan.getWP(wpIdx).wp_type == "vectors" and me.flightplan.getWP(wpIdx + 1) != nil and me.flightplan.getWP(wpIdx + 1).wp_type != "discontinuity") { me.flightplan.insertWP(createDiscontinuity(), wpIdx + 1); } } From ebfaa286378db61fb12a7f0133e645d8c6b6277e Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Thu, 19 May 2022 21:38:22 +0100 Subject: [PATCH 51/52] Revert "Fix logic error in SID discontinuity logic" This reverts commit c39fddb05b1a708b50b3cf2e6a8a39745df121a6. --- Nasal/FMGC/flightplan-delegates.nas | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Nasal/FMGC/flightplan-delegates.nas b/Nasal/FMGC/flightplan-delegates.nas index 2cecfa6b..fff9b3d5 100644 --- a/Nasal/FMGC/flightplan-delegates.nas +++ b/Nasal/FMGC/flightplan-delegates.nas @@ -75,9 +75,9 @@ var A320RouteManagerDelegate = { } me.flightplan.insertWaypoints(wps, 1); - + for (var wpIdx = 0; wpIdx < me.flightplan.getPlanSize(); wpIdx = wpIdx + 1) { - if (me.flightplan.getWP(wpIdx).wp_type == "vectors" and me.flightplan.getWP(wpIdx + 1) != nil and me.flightplan.getWP(wpIdx + 1).wp_type != "discontinuity") { + if (me.flightplan.getWP(wpIdx).wp_type == "vectors" and (me.flightplan.getWP(wpIdx + 1) == nil or me.flightplan.getWP(wpIdx + 1).wp_type != "discontinuity")) { me.flightplan.insertWP(createDiscontinuity(), wpIdx + 1); } } From 5e7d132c19cd1295130b3b956ecb1d017d7d7c8c Mon Sep 17 00:00:00 2001 From: Jonathan Redpath Date: Mon, 23 May 2022 17:34:54 +0100 Subject: [PATCH 52/52] Remove the MANUAL discontinuity; because it kept adding more discontinuities --- Nasal/FMGC/FCU.nas | 2 +- Nasal/FMGC/flightplan-delegates.nas | 12 ++++++------ Nasal/FMGC/flightplan.nas | 11 +++++------ 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/Nasal/FMGC/FCU.nas b/Nasal/FMGC/FCU.nas index 87f0851c..1c925f0f 100644 --- a/Nasal/FMGC/FCU.nas +++ b/Nasal/FMGC/FCU.nas @@ -264,7 +264,7 @@ var FCUController = { if (me.FCUworking) { if (fmgc.Output.fd1.getBoolValue() or fmgc.Output.fd2.getBoolValue() or fmgc.Output.ap1.getBoolValue() or fmgc.Output.ap2.getBoolValue()) { var wp = fmgc.flightPlanController.flightplans[2].getWP(fmgc.flightPlanController.currentToWptIndex.getValue()); - if (wp != nil and wp.wp_type != "discontinuity") { + if (wp != nil and wp.wp_type != "discontinuity" and wp.wp_type != "vectors") { fmgc.Input.lat.setValue(1); } } diff --git a/Nasal/FMGC/flightplan-delegates.nas b/Nasal/FMGC/flightplan-delegates.nas index fff9b3d5..553e45fe 100644 --- a/Nasal/FMGC/flightplan-delegates.nas +++ b/Nasal/FMGC/flightplan-delegates.nas @@ -75,12 +75,6 @@ var A320RouteManagerDelegate = { } me.flightplan.insertWaypoints(wps, 1); - - for (var wpIdx = 0; wpIdx < me.flightplan.getPlanSize(); wpIdx = wpIdx + 1) { - if (me.flightplan.getWP(wpIdx).wp_type == "vectors" and (me.flightplan.getWP(wpIdx + 1) == nil or me.flightplan.getWP(wpIdx + 1).wp_type != "discontinuity")) { - me.flightplan.insertWP(createDiscontinuity(), wpIdx + 1); - } - } }, arrivalChanged: func @@ -272,6 +266,12 @@ var A320GPSDelegate = { } elsif (me.flightplan.nextWP().wp_type != 'discontinuity' and me.flightplan.nextWP().wp_type != 'vectors') { logprint(LOG_INFO, "default GPS sequencing to next WP"); me.flightplan.current = me.flightplan.current + 1; + } else { + logprint(LOG_INFO, "default GPS sequencing to next WP (special)"); + fmgc.Input.lat.setValue(3); + if (me.flightplan.nextWP().wp_type == 'vectors') { + me.flightplan.current = me.flightplan.current + 2; + } } } else { # OBS, do nothing diff --git a/Nasal/FMGC/flightplan.nas b/Nasal/FMGC/flightplan.nas index da218879..1be9fe10 100644 --- a/Nasal/FMGC/flightplan.nas +++ b/Nasal/FMGC/flightplan.nas @@ -226,14 +226,11 @@ var flightPlanController = { # TODO - triple click - confirm, is it only with DES disengage, or also with the NAV loss? # TODO - I think that it only goes to VS when in DES mode - if (me.flightplans[2].getWP(me.currentToWptIndexTemp + 1).wp_type == "discontinuity") { + if (me.flightplans[2].getWP(me.currentToWptIndexTemp + 1).wp_type == "discontinuity" or me.flightplans[2].getWP(me.currentToWptIndexTemp + 1).wp_type == "vectors") { fmgc.Input.lat.setValue(3); + me.currentToWptIndex.setValue(me.currentToWptIndexTemp + 2); + me.lastSequencedCurrentWP = me.currentToWptIndexTemp + 2; } else { - if (me.flightplans[2].getWP(me.currentToWptIndexTemp + 1).wp_type == "vectors") { - fmgc.Input.lat.setValue(3); - me.flightplans[2].deleteWP(me.currentToWptIndexTemp + 2); - } - me.currentToWptIndex.setValue(me.currentToWptIndexTemp + 1); me.lastSequencedCurrentWP = me.currentToWptIndexTemp + 1; @@ -271,8 +268,10 @@ var flightPlanController = { # Optional flag DEBUG_DISCONT to disable discontinuities totally addDiscontinuity: func(index, plan, force = 0) { if (DEBUG_DISCONT) { return; } + if (force) { me.flightplans[plan].insertWP(createDiscontinuity(), index); + return; } if (me.flightplans[plan].getWP(index) != nil) { # index is not nil