1
0
Fork 0

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.

This commit is contained in:
Jonathan Redpath 2022-01-17 11:43:31 +00:00
parent b6775f61d3
commit 4c36bca545
14 changed files with 529 additions and 316 deletions

View file

@ -4796,6 +4796,7 @@
<file>Aircraft/A320-family/Nasal/Panels/efis.nas</file>
</fcu>
<fmgc>
<file>Aircraft/A320-family/Nasal/FMGC/flightplan-delegates.nas</file>
<file>Aircraft/A320-family/Nasal/FMGC/flightplan-waypoints.nas</file>
<file>Aircraft/A320-family/Nasal/FMGC/flightplan.nas</file>
<file>Aircraft/A320-family/Nasal/FMGC/FMGC.nas</file>

View file

@ -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("----");

View file

@ -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
}
});

View file

@ -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) {

View file

@ -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);

View file

@ -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();

View file

@ -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();

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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;
}

View file

@ -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"];
}

View file

@ -376,6 +376,24 @@
</period>
</filter>
<filter>
<name>Get Back on Magenta</name>
<type>gain</type>
<gain>
<expression>
<table>
<property>/fdm/jsbsim/velocities/vc-kts</property>
<entry><ind>140</ind><dep>50</dep></entry>
<entry><ind>360</ind><dep>20</dep></entry>
</table>
</expression>
</gain>
<input>/instrumentation/gps/wp/wp[1]/course-error-nm</input>
<output>/it-autoflight/internal/course-error-deg</output>
<min>-45</min>
<max>45</max>
</filter>
<filter>
<name>Heading Error Deg</name>
<debug>false</debug>
@ -428,7 +446,8 @@
</condition>
<expression>
<sum>
<property>/FMGC/flightplan[2]/current-leg-course</property>
<property>/instrumentation/gps/wp/leg-true-course-deg</property>
<property>/it-autoflight/internal/course-error-deg</property>
<product>
<property>/it-autoflight/internal/drift-angle-deg</property>
<value>-1.0</value>