Skip to content

Commit

Permalink
fix(a380): Fix T/D prediction in PERF CRZ & add T/D reached (#9284)
Browse files Browse the repository at this point in the history
* fix(mfd/perf): ETA format on PERF page

* change mfd dest eta to utils

* feat(mfd/pfd) add TD reached message

* fix ETA on perf page and display TD distance

* hide TD eta prediction if neg dist. Fix TD reached vars

* Create FMS MFD publisher

* fix tdReached MFD subscription

* change spelling of speed MFD messages

* clear td reached scratchpad if simvar changes

* docs: update changelog

* fix lint errors

* remove leftover code

* fix(mfd): update no fuel fields to 3 dashes when no data
  • Loading branch information
BravoMike99 authored Nov 13, 2024
1 parent deab770 commit 0a7db45
Show file tree
Hide file tree
Showing 11 changed files with 117 additions and 48 deletions.
3 changes: 3 additions & 0 deletions .github/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
1. [A32NX/CAMERA] Improved default camera position for Virtual Reality (VR) - @aguther (Andreas Guther)
1. [A380X/EFB] Fixed doors automatically opening in flight - @saschl (saschl)
1. [A380X/FMS] Fixed layouting issue on FMS/ACTIVE/PERF/T.O page for some users - @flogross89 (floridude)
1. [A380X/TELEX] Added popup for telex consent @saschl (saschl) @Maximilian-Reuter (\_chaoz)
1. [A380X/MFD] Fix ETA and add TOD prediction in PERF page - @BravoMike99 (bruno_pt99)
1. [A380/PFD] Add T/D Reached PFD message - @BravoMike99 (bruno_pt99)
1. [A380X/TELEX] Added popup for telex consent - @saschl (saschl) @Maximilian-Reuter (\_chaoz)
1. [ND] Fix memory leak when using TERR ON ND - @Nufflee (nufflee)
1. [A380X/OVHD] Fix RCDR GND CTL button/logic - @flogross89 (floridude)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { FmcInterface } from 'instruments/src/MFD/FMC/FmcInterface';
import { FlightPhaseManagerEvents } from '@fmgc/flightphase';
import { FGVars } from 'instruments/src/MsfsAvionicsCommon/providers/FGDataPublisher';
import { VerticalMode } from '@shared/autopilot';
import { FmsMfdVars } from 'instruments/src/MsfsAvionicsCommon/providers/FmsMfdPublisher';

/**
* Interface between FMS and rest of aircraft through SimVars and ARINC values (mostly data being sent here)
Expand Down Expand Up @@ -93,6 +94,21 @@ export class FmcAircraftInterface {
private readonly speedVfeNext = Subject.create(0);
private readonly speedVapp = Subject.create(0);
private readonly speedShortTermManaged = Subject.create(0);

private readonly tdReached = this.bus
.getSubscriber<FmsMfdVars>()
.on('tdReached')
.whenChanged()
.handle((v) => {
if (v) {
this.fmc.addMessageToQueue(NXSystemMessages.tdReached, undefined, () => {
SimVar.SetSimVarValue('L:A32NX_PFD_MSG_TD_REACHED', 'Bool', false);
});
} else {
this.fmc.removeMessageFromQueue(NXSystemMessages.tdReached.text);
}
});

private readonly flightPhase = ConsumerValue.create(
this.bus.getSubscriber<FlightPhaseManagerEvents>().on('fmgc_flight_phase').whenChanged(),
FmgcFlightPhase.Preflight,
Expand Down
5 changes: 5 additions & 0 deletions fbw-a380x/src/systems/instruments/src/MFD/instrument.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { MfdSimvarPublisher } from './shared/MFDSimvarPublisher';
import { FailuresConsumer } from '@flybywiresim/fbw-sdk';
import { A380Failure } from '@failures';
import { FGDataPublisher } from '../MsfsAvionicsCommon/providers/FGDataPublisher';
import { FmsMfdPublisher } from '../MsfsAvionicsCommon/providers/FmsMfdPublisher';

class MfdInstrument implements FsInstrument {
private readonly bus = new EventBus();
Expand All @@ -24,6 +25,8 @@ class MfdInstrument implements FsInstrument {

private readonly fgDataPublisher: FGDataPublisher;

private readonly fmsDataPublisher: FmsMfdPublisher;

private readonly clockPublisher = new ClockPublisher(this.bus);

private readonly hEventPublisher = new HEventPublisher(this.bus);
Expand All @@ -40,11 +43,13 @@ class MfdInstrument implements FsInstrument {
this.simVarPublisher = new MfdSimvarPublisher(this.bus);
this.hEventPublisher = new HEventPublisher(this.bus);
this.fgDataPublisher = new FGDataPublisher(this.bus);
this.fmsDataPublisher = new FmsMfdPublisher(this.bus);

this.backplane.addPublisher('mfd', this.simVarPublisher);
this.backplane.addPublisher('hEvent', this.hEventPublisher);
this.backplane.addPublisher('clock', this.clockPublisher);
this.backplane.addPublisher('fg', this.fgDataPublisher);
this.backplane.addPublisher('fms', this.fmsDataPublisher);

this.fmcService = new FmcService(this.bus, this.mfdCaptRef.getOrDefault(), this.failuresConsumer);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,9 @@ export class MfdFmsFpln extends FmsPage<MfdFmsFplnProps> {

private destTimeLabel = Subject.create<string>('--:--');

private destEfob = Subject.create<string>('--.-');
private destEfob = Subject.create<string>('---.-');

private destDistanceLabel = Subject.create<string>('---');
private destDistanceLabel = Subject.create<string>('----');

private displayFplnFromLineIndex = Subject.create<number>(0);

Expand Down Expand Up @@ -167,11 +167,11 @@ export class MfdFmsFpln extends FmsPage<MfdFmsFplnProps> {
if (destEfob) {
this.destEfob.set(Math.max(0, Units.poundToKilogram(destEfob) / 1_000).toFixed(1));
} else {
this.destEfob.set('--.-');
this.destEfob.set('---.-');
}

this.destDistanceLabel.set(
Number.isFinite(destPred.distanceFromAircraft) ? destPred.distanceFromAircraft.toFixed(0) : '---',
Number.isFinite(destPred.distanceFromAircraft) ? destPred.distanceFromAircraft.toFixed(0) : '----',
);
}
this.checkScrollButtons();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,15 @@ export class MfdFmsFuelLoad extends FmsPage<MfdFmsFuelLoadProps> {

private destEta = Subject.create<string>('--:--');

private destEfob = Subject.create<string>('--.-');
private destEfob = Subject.create<string>('---.-');

private destEfobBelowMin = Subject.create(false);

private altnIcao = Subject.create<string>('----');

private altnEta = Subject.create<string>('--:--');

private altnEfob = Subject.create<string>('--.-');
private altnEfob = Subject.create<string>('---.-');

private altnEfobBelowMin = Subject.create(false);

Expand Down Expand Up @@ -111,7 +111,7 @@ export class MfdFmsFuelLoad extends FmsPage<MfdFmsFuelLoadProps> {
);
}
const destEfob = this.props.fmcService.master.fmgc.getDestEFOB(true);
this.destEfob.set(destEfob !== null ? destEfob.toFixed(1) : '--.-');
this.destEfob.set(destEfob !== null ? destEfob.toFixed(1) : '---.-');
this.destEfobBelowMin.set(
destEfob * 1_000 < (this.props.fmcService.master.fmgc.data.minimumFuelAtDestination.get() ?? 0),
);
Expand All @@ -120,12 +120,12 @@ export class MfdFmsFuelLoad extends FmsPage<MfdFmsFuelLoadProps> {
if (this.loadedFlightPlan.alternateDestinationAirport) {
this.altnIcao.set(this.loadedFlightPlan.alternateDestinationAirport.ident);
this.altnEta.set('--:--');
this.altnEfob.set('--.-');
this.altnEfob.set('---.-');
this.altnEfobBelowMin.set(false);
} else {
this.altnIcao.set('NONE');
this.altnEta.set('--:--');
this.altnEfob.set('--.-');
this.altnEfob.set('---.-');
this.altnEfobBelowMin.set(false);
}
}
Expand Down Expand Up @@ -525,7 +525,7 @@ export class MfdFmsFuelLoad extends FmsPage<MfdFmsFuelLoadProps> {
<div style="display: flex; flex-direction: row; justify-content: center; align-items: center;">
<div class="mfd-label-value-container" style="margin-right: 20px;">
<span class="mfd-value">
{this.extraFuelWeight.map((it) => (it ? (it / 1000).toFixed(1) : '--.-'))}
{this.extraFuelWeight.map((it) => (it ? (it / 1000).toFixed(1) : '---.-'))}
</span>
<span class="mfd-label-unit mfd-unit-trailing">T</span>
</div>
Expand Down
33 changes: 22 additions & 11 deletions fbw-a380x/src/systems/instruments/src/MFD/pages/FMS/MfdFmsPerf.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import {
SpeedKnotsFormat,
SpeedMachFormat,
TemperatureFormat,
TimeHHMMFormat,
WindDirectionFormat,
WindSpeedFormat,
} from 'instruments/src/MFD/pages/common/DataEntryFormats';
Expand All @@ -36,7 +35,7 @@ import { MfdSimvars } from 'instruments/src/MFD/shared/MFDSimvarPublisher';
import { VerticalCheckpointReason } from '@fmgc/guidance/vnav/profile/NavGeometryProfile';
import { A380SpeedsUtils } from '@shared/OperatingSpeeds';
import { NXSystemMessages } from '../../shared/NXSystemMessages';
import { getApproachName } from '../../shared/utils';
import { getEtaFromUtcOrPresent as getEtaUtcOrFromPresent, getApproachName } from '../../shared/utils';
import { ApproachType } from '@flybywiresim/fbw-sdk';
import { FlapConf } from '@fmgc/guidance/vnav/common';

Expand Down Expand Up @@ -809,30 +808,35 @@ export class MfdFmsPerf extends FmsPage<MfdFmsPerfProps> {
this.crzPredStepAheadRef.instance.style.display = 'none';
this.crzPredWaypoint.set('N/A'); // Where to get this from?
this.crzPredAltitudeTarget.set(0); // Where to get this from?
this.crzTablePredLine1.set(null);
}
}
}

if (crzPred?.secondsFromPresent !== undefined && crzPred?.distanceFromPresentPosition !== undefined) {
const timePrediction = getEtaUtcOrFromPresent(
crzPred.distanceFromPresentPosition < 0 ? null : crzPred.secondsFromPresent,
this.activeFlightPhase.get() == FmgcFlightPhase.Preflight,
);
if (this.activeFlightPhase.get() < FmgcFlightPhase.Cruise) {
if (
this.props.fmcService.master?.fmgc.data.cruisePreSelSpeed.get() ||
this.props.fmcService.master?.fmgc.data.cruisePreSelMach.get()
) {
this.crzTablePredLine1.set(
`${new TimeHHMMFormat().format(crzPred.secondsFromPresent / 60)}${crzPred.distanceFromPresentPosition.toFixed(0).padStart(6, ' ')}`,
`${timePrediction}${crzPred.distanceFromPresentPosition.toFixed(0).padStart(6, ' ')}`,
);
this.crzTablePredLine2.set('');
} else {
// Managed
this.crzTablePredLine1.set('');
this.crzTablePredLine2.set(
`${new TimeHHMMFormat().format(crzPred.secondsFromPresent / 60)}${crzPred.distanceFromPresentPosition.toFixed(0).padStart(6, ' ')}`,
`${timePrediction}${crzPred.distanceFromPresentPosition.toFixed(0).padStart(6, ' ')}`,
);
}
} else {
this.crzTablePredLine1.set(
`${new TimeHHMMFormat().format(crzPred.secondsFromPresent / 60)}${crzPred.distanceFromPresentPosition.toFixed(0).padStart(6, ' ')}`,
`${timePrediction}${crzPred.distanceFromPresentPosition.toFixed(0).padStart(6, ' ')}`,
);
this.crzTablePredLine2.set('');
}
Expand All @@ -848,7 +852,6 @@ export class MfdFmsPerf extends FmsPage<MfdFmsPerfProps> {
this.crzTableModeLine1.set('PRESEL');
this.crzTableSpdLine1.set(null);
this.crzTableMachLine1.set(null);
this.crzTablePredLine1.set(null);
this.crzTableModeLine2.set('MANAGED');
this.crzTableSpdLine2.set('---');
this.crzTableMachLine2.set(
Expand All @@ -870,7 +873,6 @@ export class MfdFmsPerf extends FmsPage<MfdFmsPerfProps> {
);

// TODO add predictions
this.crzTablePredLine1.set('--:-- ----');
this.crzTableModeLine2.set(null);
this.crzTableSpdLine2.set(null);
this.crzTableMachLine2.set(null);
Expand All @@ -879,7 +881,6 @@ export class MfdFmsPerf extends FmsPage<MfdFmsPerfProps> {
this.crzTableModeLine1.set('SELECTED');
this.crzTableSpdLine1.set(obs && obs.fcuSpeed < 1 ? '---' : obs?.fcuSpeed.toFixed(0) ?? null);
this.crzTableMachLine1.set(obs && obs.fcuSpeed < 1 ? `.${obs.fcuSpeed.toFixed(2).split('.')[1]}` : null);
this.crzTablePredLine1.set(null);

this.crzTableModeLine2.set('MANAGED');
// TODO add speed restriction (ECON, SPD LIM, ...) in smaller font
Expand All @@ -898,10 +899,15 @@ export class MfdFmsPerf extends FmsPage<MfdFmsPerfProps> {

// Update CRZ DEST predictions
const destPred = this.props.fmcService.master?.guidanceController?.vnavDriver?.getDestinationPrediction();
let destEta = '--:--';
if (destPred?.secondsFromPresent !== undefined) {
this.destEta.set(new TimeHHMMFormat().format(destPred.secondsFromPresent / 60)[0] ?? '--:--');
this.destEfob.set(this.props.fmcService.master?.fmgc.getDestEFOB(true).toFixed(1) ?? '--.-');
destEta = getEtaUtcOrFromPresent(
destPred.secondsFromPresent,
this.activeFlightPhase.get() == FmgcFlightPhase.Preflight,
);
}
this.destEta.set(destEta);
this.destEfob.set(this.props.fmcService.master?.fmgc.getDestEFOB(true).toFixed(1) ?? '---.-');

// Update DES speed table
if (this.activeFlightPhase.get() < FmgcFlightPhase.Descent) {
Expand Down Expand Up @@ -2068,7 +2074,12 @@ export class MfdFmsPerf extends FmsPage<MfdFmsPerfProps> {
}
/>
</div>
<div class="mfd-fms-perf-speed-table-cell" />
<div class="mfd-fms-perf-speed-table-cell">
<span class="mfd-value">{this.crzTablePredLine1}</span>
<span class="mfd-label-unit mfd-unit-trailing">
{this.crzTablePredLine1.map((it) => (it ? 'NM' : ''))}
</span>
</div>
<div class="mfd-fms-perf-speed-presel-managed-table-cell">
<div
class={{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export const NXSystemMessages = {
awyWptMismatch: new TypeIMessage('AWY/WPT MISMATCH'),
cancelAtisUpdate: new TypeIMessage('CANCEL UPDATE BEFORE'),
checkMinDestFob: new TypeIIMessage('CHECK MIN DEST FOB'),
checkSpeedMode: new TypeIIMessage('CHECK SPEED MODE'),
checkSpeedMode: new TypeIIMessage('CHECK SPD MODE'),
checkToData: new TypeIIMessage('CHECK TAKE OFF DATA', true),
comUnavailable: new TypeIMessage('COM UNAVAILABLE'),
cstrDelUpToWpt: new TypeIIMessage('CONSTRAINTS BEFORE WWWWW : DELETED', false, 'WWWWW'),
Expand Down Expand Up @@ -98,7 +98,8 @@ export const NXSystemMessages = {
notInDatabase: new TypeIMessage('NOT IN DATABASE'),
rwyLsMismatch: new TypeIIMessage('RWY/LS MISMATCH', true),
selectDesiredSystem: new TypeIMessage('SELECT DESIRED SYSTEM'),
setHoldSpeed: new TypeIIMessage('SET HOLD SPEED'),
setHoldSpeed: new TypeIIMessage('SET HOLD SPD'),
tdReached: new TypeIIMessage('T/D REACHED'),
spdLimExceeded: new TypeIIMessage('SPD LIM EXCEEDED', true),
systemBusy: new TypeIMessage('SYSTEM BUSY-TRY LATER'),
toSpeedTooLow: new TypeIIMessage('TO SPEEDS TOO LOW', true),
Expand Down
10 changes: 10 additions & 0 deletions fbw-a380x/src/systems/instruments/src/MFD/shared/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@

import { Approach, ApproachType } from '@flybywiresim/fbw-sdk';

export function getEtaFromUtcOrPresent(seconds: number | null, fromPresent: boolean) {
if (seconds === null) {
return '--:--';
}

const secondsEta = fromPresent ? seconds : seconds + SimVar.GetGlobalVarValue('ZULU TIME', 'seconds');
const eta = new Date(secondsEta * 1000);
return `${eta.getUTCHours().toString().padStart(2, '0')}:${eta.getUTCMinutes().toString().padStart(2, '0')}`;
}

export function secondsToHHmmString(seconds: number) {
const minutesTotal = seconds / 60;
const hours = Math.abs(Math.floor(minutesTotal / 60))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { SimVarPublisher, EventBus, SimVarValueType } from '@microsoft/msfs-sdk';

export interface FmsMfdVars {
tdReached: boolean;
}

export class FmsMfdPublisher extends SimVarPublisher<FmsMfdVars> {
constructor(bus: EventBus) {
super(new Map([['tdReached', { name: 'L:A32NX_PFD_MSG_TD_REACHED', type: SimVarValueType.Bool }]]), bus);
}
}
Loading

0 comments on commit 0a7db45

Please sign in to comment.