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
40 changes: 40 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,9 @@ import { LnavDriver } from './lnav/LnavDriver';
import { FlightPlanManager, FlightPlans } from '../flightplanning/FlightPlanManager';
import { GuidanceManager } from './GuidanceManager';
import { VnavDriver } from './vnav/VnavDriver';
import { Leg } from './lnav/legs/Leg';
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 @@ -112,6 +115,8 @@ export class GuidanceController {

verticalProfileComputationParametersObserver: VerticalProfileComputationParametersObserver;

lastActiveLeg: Leg | null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this used for?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is used to update efis with the data based on the active leg computed by the LnavDriver.
If there's no more active leg, ETA, bearing and distance will be updated not to appear on the ND.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, my apologies, I missed that somehow 😄. Nevertheless, I think the property is redundant because we already store activeGeometry and activeLegIdx in the GuidanceController, so we can just derive the active leg there, rather than having it set in LnavDriver. This is just a minor thing though, so let me know if you have a different opinion.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no worries, probably you're right on this one.
I've made the change, have a look.


private listener = RegisterViewListener('JS_LISTENER_SIMVARS', null, true);

private windProfileFactory: WindProfileFactory;
Expand Down Expand Up @@ -209,6 +214,39 @@ export class GuidanceController {
}
}

private updateEfisData(activeLeg: Leg) {
const gs = SimVar.GetSimVarValue('GPS GROUND SPEED', 'Knots');
const flightPhase = getFlightPhaseManager().phase;
const etaComputable = flightPhase >= FmgcFlightPhase.Takeoff && gs > 100;
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 +379,8 @@ export class GuidanceController {
console.error(e);
}

this.updateEfisData(this.lastActiveLeg);

try {
this.vnavDriver.update(deltaTime);
} catch (e) {
Expand Down
46 changes: 4 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,7 @@ export class LnavDriver implements GuidanceComponent {
if (LnavConfig.DEBUG_GUIDANCE) {
console.log('[FMS/LNAV] No leg at activeLegIdx!');
}

this.guidanceController.lastActiveLeg = null;
return;
}

Expand All @@ -120,6 +119,7 @@ export class LnavDriver implements GuidanceComponent {
this.guidanceController.activeLegDtg = dtg;
this.guidanceController.activeLegCompleteLegPathDtg = completeLegPathDtg;
this.guidanceController.displayActiveLegCompleteLegPathDtg = completeDisplayLegPathDtg;
this.guidanceController.lastActiveLeg = activeLeg;

// Update activeTransIndex in GuidanceController
if (inboundTrans && inboundTrans.isAbeam(this.ppos)) {
Expand Down Expand Up @@ -347,14 +347,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 +396,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