Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: fix ETA of TO waypoint display on ND #8252

Merged
merged 11 commits into from
Feb 14, 2024
2 changes: 2 additions & 0 deletions .github/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

## 0.12.0

1. [ND] Fix ND ETA of TO waypoint display prior to takeoff and after landing. - Alex Milshtein (@alexm1987 on Discord)

## 0.11.0

1. [FMS] Implement vertical navigation functions - @BlueberryKing (BlueberryKing)
Expand Down
38 changes: 38 additions & 0 deletions fbw-a32nx/src/systems/fmgc/src/guidance/GuidanceController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import { LnavDriver } from './lnav/LnavDriver';
import { FlightPlanManager, FlightPlans } from '../flightplanning/FlightPlanManager';
import { GuidanceManager } from './GuidanceManager';
import { VnavDriver } from './vnav/VnavDriver';
import { XFLeg } from './lnav/legs/XF';
import { VMLeg } from './lnav/legs/VM';

// How often the (milliseconds)
const GEOMETRY_RECOMPUTATION_TIMER = 5_000;
Expand Down Expand Up @@ -209,6 +211,40 @@ export class GuidanceController {
}
}

private updateEfisData() {
const gs = SimVar.GetSimVarValue('GPS GROUND SPEED', 'Knots');
const flightPhase = getFlightPhaseManager().phase;
const etaComputable = flightPhase >= FmgcFlightPhase.Takeoff && gs > 100;
const activeLeg = this.activeGeometry.legs.get(this.activeLegIndex);
alexmilshtein marked this conversation as resolved.
Show resolved Hide resolved
if (activeLeg) {
const termination = activeLeg instanceof XFLeg ? activeLeg.fix.infos.coordinates : activeLeg.getPathEndPoint();
const ppos = this.lnavDriver.ppos;
const efisTrueBearing = termination ? Avionics.Utils.computeGreatCircleHeading(ppos, termination) : -1;
const efisBearing = termination ? A32NX_Util.trueToMagnetic(
efisTrueBearing,
Facilities.getMagVar(ppos.lat, ppos.long),
) : -1;

// Don't compute distance and ETA for XM legs
const efisDistance = activeLeg instanceof VMLeg ? -1 : Avionics.Utils.computeGreatCircleDistance(ppos, termination);
const efisEta = activeLeg instanceof VMLeg || !etaComputable ? -1 : LnavDriver.legEta(ppos, gs, termination);

// FIXME should be NCD if no FM position
this.updateEfisVars(efisBearing, efisTrueBearing, efisDistance, efisEta, 'L');
this.updateEfisVars(efisBearing, efisTrueBearing, efisDistance, efisEta, 'R');
} else {
this.updateEfisVars(-1, -1, -1, -1, 'L');
this.updateEfisVars(-1, -1, -1, -1, 'R');
}
}

private updateEfisVars(bearing: number, trueBearing: number, distance: number, eta: number, side: string): void {
SimVar.SetSimVarValue(`L:A32NX_EFIS_${side}_TO_WPT_BEARING`, 'Degrees', bearing);
SimVar.SetSimVarValue(`L:A32NX_EFIS_${side}_TO_WPT_TRUE_BEARING`, 'Degrees', trueBearing);
SimVar.SetSimVarValue(`L:A32NX_EFIS_${side}_TO_WPT_DISTANCE`, 'Number', distance);
SimVar.SetSimVarValue(`L:A32NX_EFIS_${side}_TO_WPT_ETA`, 'Seconds', eta);
}

constructor(flightPlanManager: FlightPlanManager, guidanceManager: GuidanceManager, fmgc: Fmgc) {
this.flightPlanManager = flightPlanManager;
this.guidanceManager = guidanceManager;
Expand Down Expand Up @@ -341,6 +377,8 @@ export class GuidanceController {
console.error(e);
}

this.updateEfisData();

try {
this.vnavDriver.update(deltaTime);
} catch (e) {
Expand Down
44 changes: 2 additions & 42 deletions fbw-a32nx/src/systems/fmgc/src/guidance/lnav/LnavDriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import { FixedRadiusTransition } from '@fmgc/guidance/lnav/transitions/FixedRadi
import { PathCaptureTransition } from '@fmgc/guidance/lnav/transitions/PathCaptureTransition';
import { CourseCaptureTransition } from '@fmgc/guidance/lnav/transitions/CourseCaptureTransition';
import { GuidanceConstants } from '@fmgc/guidance/GuidanceConstants';
import { VMLeg } from '@fmgc/guidance/lnav/legs/VM';
import { XFLeg } from '@fmgc/guidance/lnav/legs/XF';
import { Coordinates } from '@fmgc/flightplanning/data/geo';
import { FmgcFlightPhase } from '@shared/flightphase';
Expand Down Expand Up @@ -94,7 +93,6 @@ export class LnavDriver implements GuidanceComponent {
if (LnavConfig.DEBUG_GUIDANCE) {
console.log('[FMS/LNAV] No leg at activeLegIdx!');
}

return;
}

Expand Down Expand Up @@ -347,14 +345,10 @@ export class LnavDriver implements GuidanceComponent {

SimVar.SetSimVarValue('L:A32NX_GPS_WP_DISTANCE', 'nautical miles', dtg ?? 0);

// Update EFIS active waypoint info

this.updateEfisData(activeLeg, gs);
const flightPhase = SimVar.GetSimVarValue('L:A32NX_FMGC_FLIGHT_PHASE', 'Enum') as FmgcFlightPhase;

// Sequencing

const flightPhase = SimVar.GetSimVarValue('L:A32NX_FMGC_FLIGHT_PHASE', 'Enum') as FmgcFlightPhase;

const canSequence = !activeLeg.disableAutomaticSequencing && flightPhase >= FmgcFlightPhase.Takeoff;

let withinSequencingArea = true;
Expand Down Expand Up @@ -400,41 +394,7 @@ export class LnavDriver implements GuidanceComponent {
}
}

/**
* Updates the EFIS TO WPT data
*
* @param activeLeg currently active display leg
* @param gs current ground speed in knots
*
* @private
*/
private updateEfisData(activeLeg: Leg, gs: Knots) {
const termination = activeLeg instanceof XFLeg ? activeLeg.fix.infos.coordinates : activeLeg.getPathEndPoint();

const efisTrueBearing = termination ? Avionics.Utils.computeGreatCircleHeading(this.ppos, termination) : -1;
const efisBearing = termination ? A32NX_Util.trueToMagnetic(
efisTrueBearing,
Facilities.getMagVar(this.ppos.lat, this.ppos.long),
) : -1;

// Don't compute distance and ETA for XM legs
const efisDistance = activeLeg instanceof VMLeg ? -1 : Avionics.Utils.computeGreatCircleDistance(this.ppos, termination);
const efisEta = activeLeg instanceof VMLeg ? -1 : LnavDriver.legEta(this.ppos, gs, termination);

// FIXME should be NCD if no FM position

SimVar.SetSimVarValue('L:A32NX_EFIS_L_TO_WPT_BEARING', 'Degrees', efisBearing);
SimVar.SetSimVarValue('L:A32NX_EFIS_L_TO_WPT_TRUE_BEARING', 'Degrees', efisTrueBearing);
SimVar.SetSimVarValue('L:A32NX_EFIS_L_TO_WPT_DISTANCE', 'Number', efisDistance);
SimVar.SetSimVarValue('L:A32NX_EFIS_L_TO_WPT_ETA', 'Seconds', efisEta);

SimVar.SetSimVarValue('L:A32NX_EFIS_R_TO_WPT_BEARING', 'Degrees', efisBearing);
SimVar.SetSimVarValue('L:A32NX_EFIS_R_TO_WPT_TRUE_BEARING', 'Degrees', efisTrueBearing);
SimVar.SetSimVarValue('L:A32NX_EFIS_R_TO_WPT_DISTANCE', 'Number', efisDistance);
SimVar.SetSimVarValue('L:A32NX_EFIS_R_TO_WPT_ETA', 'Seconds', efisEta);
}

private static legEta(ppos: Coordinates, gs: Knots, termination: Coordinates): number {
public static legEta(ppos: Coordinates, gs: Knots, termination: Coordinates): number {
// FIXME use a more accurate estimate, calculate in predictions

const UTC_SECONDS = Math.floor(SimVar.GetGlobalVarValue('ZULU TIME', 'seconds'));
Expand Down
3 changes: 2 additions & 1 deletion fbw-a32nx/src/systems/instruments/src/ND/ND.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,8 @@ class ToWaypointIndicator extends DisplayComponent<ToWaypointIndicatorProps> {

private readonly bearingContainerVisible = MappedSubject.create(
([trueRef, bearing, trueBearing, isNormalOperation]) => {
return isNormalOperation && Number.isFinite(trueRef ? trueBearing : bearing);
const activeBearing = trueRef ? trueBearing : bearing;
return isNormalOperation && Number.isFinite(activeBearing) && activeBearing !== -1;
},
this.trueRefActive,
this.bearing,
Expand Down
Loading