Skip to content

Commit

Permalink
fix(a380x/fms): Fix mach crossover altitude & T/O perf characteristic…
Browse files Browse the repository at this point in the history
… speeds (#9769)

* use FL300 as crossover altitude

* fixes

* review comments

* fix(mathutils): remove machToKCas temperature dependency

(cherry picked from commit 3f77cd5)

* some updates

* remove comment

* Update CHANGELOG.md

---------

Co-authored-by: Michael Corcoran <[email protected]>
  • Loading branch information
flogross89 and tracernz authored Jan 18, 2025
1 parent c837ab1 commit 886180b
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 33 deletions.
1 change: 1 addition & 0 deletions .github/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@
1. [FMS] Improved nav database error handling, preserving as much valid data as possible - @tracernz (Mike)
1. [A32NX/FMS] Sort instrument procedures for display on the MCDU - @tracernz (Mike)
1. [A380X/ELEC] Various fixes in the electrical system (battery voltage indicator switchup, AC GND SVC BUS and correct behavior of battery contactors) - @Gurgel100 (Pascal)
1. [A380X/FMS] Use cruise mach above crossover altitude - @flogross89 (floridude)

## 0.12.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: GPL-3.0

import { ConsumerValue, EventBus, GameStateProvider, SimVarValueType, Subject, UnitType } from '@microsoft/msfs-sdk';
import { Arinc429SignStatusMatrix, Arinc429Word, FmsOansData } from '@flybywiresim/fbw-sdk';
import { Arinc429SignStatusMatrix, Arinc429Word, FmsOansData, MathUtils } from '@flybywiresim/fbw-sdk';
import { FlapConf } from '@fmgc/guidance/vnav/common';
import { FlightPlanService } from '@fmgc/index';
import { MmrRadioTuningStatus } from '@fmgc/navigation/NavaidTuner';
Expand Down Expand Up @@ -1170,17 +1170,16 @@ export class FmcAircraftInterface {
this.fmgc.data.approachFlapRetractionSpeed.set(Math.ceil(approachSpeeds.f3));
this.speedVapp.set(Math.round(approachSpeeds.vapp));

// Retrieve CAS and altitude from ADRs
const cas = this.fmc.navigation.getComputedAirspeed();
// Retrieve altitude from ADRs
const alt = this.fmc.navigation.getPressureAltitude();

if (cas !== null && alt !== null) {
// Only update speeds if ADR data valid
if (alt !== null) {
// Only update speeds if ADR altitude data valid.

const flapLever = SimVar.GetSimVarValue('L:A32NX_FLAPS_HANDLE_INDEX', 'Enum');
const speeds = new A380OperatingSpeeds(
grossWeight,
cas,
this.fmc.navigation.getComputedAirspeed() ?? 0, // CAS is NCD for low speeds/standstill, leading to null here
flapLever,
this.flightPhase.get(),
this.fmgc.getV2Speed(),
Expand Down Expand Up @@ -1612,10 +1611,21 @@ export class FmcAircraftInterface {
return SimVar.GetSimVarValue('AUTOPILOT ALTITUDE SLOT INDEX', 'number') === 2;
}

getManagedTargets(v: number, m: number) {
const alt = ADIRS.getBaroCorrectedAltitude();
const vM = SimVar.GetGameVarValue('FROM MACH TO KIAS', 'number', m);
return alt && alt.isNormalOperation() && alt.value > 20_000 && v > vM ? [vM, true] : [v, false];
getManagedTargets(v: number, m: number): [number, boolean] {
const sat = ADIRS.getStaticAirTemperature();
const press = ADIRS.getCorrectedAverageStaticPressure();

if (
sat !== undefined &&
(sat.isNormalOperation() || sat.isFunctionalTest()) &&
press !== undefined &&
(press.isNormalOperation() || press.isFunctionalTest())
) {
const vM = MathUtils.convertMachToKCas(m, press.value);
return v > vM ? [vM, true] : [v, false];
} else {
return [v, false];
}
}

// TODO/VNAV: Speed constraint
Expand Down
15 changes: 10 additions & 5 deletions fbw-a380x/src/systems/instruments/src/MFD/FMC/fmgc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ export enum ClimbDerated {
* Temporary place for data which is found nowhere else. Not associated to flight plans right now, which should be the case for some of these values
*/
export class FmgcData {
static fmcFormatSpeed(sub: Subscribable<number | null>) {
return sub.map((it) => (it !== null ? it.toFixed(0) : '---'));
}

public readonly cpnyFplnAvailable = Subject.create(false);

public readonly cpnyFplnUplinkInProgress = Subject.create(false);
Expand Down Expand Up @@ -217,11 +221,11 @@ export class FmgcData {

public readonly takeoffFlapsSetting = Subject.create<FlapConf>(FlapConf.CONF_1);

public readonly flapRetractionSpeed = Subject.create<Knots | null>(141);
public readonly flapRetractionSpeed = Subject.create<Knots | null>(null);

public readonly slatRetractionSpeed = Subject.create<Knots | null>(159);
public readonly slatRetractionSpeed = Subject.create<Knots | null>(null);

public readonly greenDotSpeed = Subject.create<Knots | null>(190);
public readonly greenDotSpeed = Subject.create<Knots | null>(null);

public readonly approachSpeed = Subject.create<Knots | null>(null);

Expand Down Expand Up @@ -454,10 +458,11 @@ export class FmgcDataService implements Fmgc {
return preSel;
}

if (this.flightPlanService.has(FlightPlanIndex.Active)) {
// FIXME need to rework the cost index based speed calculations
/* if (this.flightPlanService.has(FlightPlanIndex.Active)) {
const dCI = ((this.flightPlanService.active.performanceData.costIndex ?? 100) / 999) ** 2;
return 290 * (1 - dCI) + 330 * dCI;
}
}*/
return 310;
}

Expand Down
54 changes: 39 additions & 15 deletions fbw-a380x/src/systems/instruments/src/MFD/pages/FMS/MfdFmsPerf.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import { maxCertifiedAlt, Mmo, Vmo } from '@shared/PerformanceConstants';
import { ConfirmationDialog } from 'instruments/src/MFD/pages/common/ConfirmationDialog';
import { FmsPage } from 'instruments/src/MFD/pages/common/FmsPage';
import { FmgcFlightPhase } from '@shared/flightphase';
import { TakeoffDerated, TakeoffPowerSetting } from 'instruments/src/MFD/FMC/fmgc';
import { FmgcData, TakeoffDerated, TakeoffPowerSetting } from 'instruments/src/MFD/FMC/fmgc';
import { ConditionalComponent } from 'instruments/src/MFD/pages/common/ConditionalComponent';
import { MfdSimvars } from 'instruments/src/MFD/shared/MFDSimvarPublisher';
import { VerticalCheckpointReason } from '@fmgc/guidance/vnav/profile/NavGeometryProfile';
Expand Down Expand Up @@ -1055,7 +1055,9 @@ export class MfdFmsPerf extends FmsPage<MfdFmsPerfProps> {
</div>
<div class="mfd-label-value-container">
<div ref={this.vSpeedsConfirmationRef[0]}>
<span class="mfd-value tmpy">{this.props.fmcService.master.fmgc.data.v1ToBeConfirmed}</span>
<span class="mfd-value tmpy">
{FmgcData.fmcFormatSpeed(this.props.fmcService.master.fmgc.data.v1ToBeConfirmed)}
</span>
<span class="mfd-label-unit mfd-unit-trailing">KT</span>
</div>
</div>
Expand Down Expand Up @@ -1093,7 +1095,9 @@ export class MfdFmsPerf extends FmsPage<MfdFmsPerfProps> {
</div>
<div ref={this.flapSpeedsRef[0]} class="mfd-label-value-container">
<span class="mfd-label mfd-spacing-right">F</span>
<span class="mfd-value">{this.props.fmcService.master.fmgc.data.flapRetractionSpeed}</span>
<span class="mfd-value">
{FmgcData.fmcFormatSpeed(this.props.fmcService.master.fmgc.data.flapRetractionSpeed)}
</span>
<span class="mfd-label-unit mfd-unit-trailing">KT</span>
</div>
<div class="mfd-label-value-container">
Expand All @@ -1115,13 +1119,17 @@ export class MfdFmsPerf extends FmsPage<MfdFmsPerfProps> {
</div>
<div class="mfd-label-value-container">
<div ref={this.vSpeedsConfirmationRef[1]}>
<span class="mfd-value tmpy">{this.props.fmcService.master.fmgc.data.vrToBeConfirmed}</span>
<span class="mfd-value tmpy">
{FmgcData.fmcFormatSpeed(this.props.fmcService.master.fmgc.data.vrToBeConfirmed)}
</span>
<span class="mfd-label-unit mfd-unit-trailing">KT</span>
</div>
</div>
<div ref={this.flapSpeedsRef[1]} class="mfd-label-value-container">
<span class="mfd-label mfd-spacing-right">S</span>
<span class="mfd-value">{this.props.fmcService.master.fmgc.data.slatRetractionSpeed}</span>
<span class="mfd-value">
{FmgcData.fmcFormatSpeed(this.props.fmcService.master.fmgc.data.slatRetractionSpeed)}
</span>
<span class="mfd-label-unit mfd-unit-trailing">KT</span>
</div>
<div class="mfd-label-value-container">
Expand All @@ -1143,7 +1151,9 @@ export class MfdFmsPerf extends FmsPage<MfdFmsPerfProps> {
</div>
<div class="mfd-label-value-container">
<div ref={this.vSpeedsConfirmationRef[2]}>
<span class="mfd-value tmpy">{this.props.fmcService.master.fmgc.data.v2ToBeConfirmed}</span>
<span class="mfd-value tmpy">
{FmgcData.fmcFormatSpeed(this.props.fmcService.master.fmgc.data.v2ToBeConfirmed)}
</span>
<span class="mfd-label-unit mfd-unit-trailing">KT</span>
</div>
</div>
Expand All @@ -1153,7 +1163,9 @@ export class MfdFmsPerf extends FmsPage<MfdFmsPerfProps> {
<circle cx="6" cy="6" r="5" stroke="#00ff00" stroke-width="2" />
</svg>
</span>
<span class="mfd-value">{this.props.fmcService.master.fmgc.data.greenDotSpeed}</span>
<span class="mfd-value">
{FmgcData.fmcFormatSpeed(this.props.fmcService.master.fmgc.data.greenDotSpeed)}
</span>
<span class="mfd-label-unit mfd-unit-trailing">KT</span>
</div>
</div>
Expand Down Expand Up @@ -2557,26 +2569,30 @@ export class MfdFmsPerf extends FmsPage<MfdFmsPerfProps> {
<circle cx="6" cy="6" r="5" stroke="#00ff00" stroke-width="2" />
</svg>
</span>
<span class="mfd-value">{this.props.fmcService.master.fmgc.data.approachGreenDotSpeed}</span>
<span class="mfd-value">
{FmgcData.fmcFormatSpeed(this.props.fmcService.master.fmgc.data.approachGreenDotSpeed)}
</span>
<span class="mfd-label-unit mfd-unit-trailing">KT</span>
</div>
<div class="mfd-label-value-container">
<span class="mfd-label mfd-spacing-right mfd-fms-perf-appr-flap-speeds">S</span>
<span class="mfd-value">
{this.props.fmcService.master.fmgc.data.approachSlatRetractionSpeed}
{FmgcData.fmcFormatSpeed(this.props.fmcService.master.fmgc.data.approachSlatRetractionSpeed)}
</span>
<span class="mfd-label-unit mfd-unit-trailing">KT</span>
</div>
<div class="mfd-label-value-container">
<span class="mfd-label mfd-spacing-right mfd-fms-perf-appr-flap-speeds">F</span>
<span class="mfd-value">
{this.props.fmcService.master.fmgc.data.approachFlapRetractionSpeed}
{FmgcData.fmcFormatSpeed(this.props.fmcService.master.fmgc.data.approachFlapRetractionSpeed)}
</span>
<span class="mfd-label-unit mfd-unit-trailing">KT</span>
</div>
<div class="mfd-label-value-container" style="padding-top: 15px;">
<span class="mfd-label mfd-spacing-right mfd-fms-perf-appr-flap-speeds">VREF</span>
<span class="mfd-value">{this.props.fmcService.master.fmgc.data.approachVref}</span>
<span class="mfd-value">
{FmgcData.fmcFormatSpeed(this.props.fmcService.master.fmgc.data.approachVref)}
</span>
<span class="mfd-label-unit mfd-unit-trailing">KT</span>
</div>
</div>
Expand All @@ -2594,7 +2610,9 @@ export class MfdFmsPerf extends FmsPage<MfdFmsPerfProps> {
/>
<div class="mfd-label-value-container" style="margin-top: 10px;">
<span class="mfd-label mfd-spacing-right">VLS</span>
<span class="mfd-value">{this.props.fmcService.master.fmgc.data.approachVls}</span>
<span class="mfd-value">
{FmgcData.fmcFormatSpeed(this.props.fmcService.master.fmgc.data.approachVls)}
</span>
<span class="mfd-label-unit mfd-unit-trailing">KT</span>
</div>
</div>
Expand Down Expand Up @@ -2653,12 +2671,16 @@ export class MfdFmsPerf extends FmsPage<MfdFmsPerfProps> {
<div style="margin: 60px 0px 100px 200px; display: flex; flex-direction: column;">
<div class="mfd-label-value-container">
<span class="mfd-label mfd-spacing-right">F</span>
<span class="mfd-value">{this.props.fmcService.master.fmgc.data.approachFlapRetractionSpeed}</span>
<span class="mfd-value">
{FmgcData.fmcFormatSpeed(this.props.fmcService.master.fmgc.data.approachFlapRetractionSpeed)}
</span>
<span class="mfd-label-unit mfd-unit-trailing">KT</span>
</div>
<div class="mfd-label-value-container">
<span class="mfd-label mfd-spacing-right">S</span>
<span class="mfd-value">{this.props.fmcService.master.fmgc.data.approachSlatRetractionSpeed}</span>
<span class="mfd-value">
{FmgcData.fmcFormatSpeed(this.props.fmcService.master.fmgc.data.approachSlatRetractionSpeed)}
</span>
<span class="mfd-label-unit mfd-unit-trailing">KT</span>
</div>
<div class="mfd-label-value-container">
Expand All @@ -2667,7 +2689,9 @@ export class MfdFmsPerf extends FmsPage<MfdFmsPerfProps> {
<circle cx="6" cy="6" r="5" stroke="#00ff00" stroke-width="2" />
</svg>
</span>
<span class="mfd-value">{this.props.fmcService.master.fmgc.data.approachGreenDotSpeed}</span>
<span class="mfd-value">
{FmgcData.fmcFormatSpeed(this.props.fmcService.master.fmgc.data.approachGreenDotSpeed)}
</span>
<span class="mfd-label-unit mfd-unit-trailing">KT</span>
</div>
</div>
Expand Down
17 changes: 17 additions & 0 deletions fbw-a380x/src/systems/instruments/src/MFD/shared/Adirs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,35 +31,52 @@ export class ADIRS {
);
}

/** in degrees */
static getLatitude() {
return ADIRS.getFromAnyAdiru('IR', 'LATITUDE');
}

/** in degrees */
static getLongitude() {
return ADIRS.getFromAnyAdiru('IR', 'LONGITUDE');
}

/** in degrees */
static getTrueTrack() {
return ADIRS.getFromAnyAdiru('IR', 'TRUE_TRACK');
}

/** in knots */
static getTrueAirspeed() {
return ADIRS.getFromAnyAdiru('ADR', 'TRUE_AIRSPEED');
}

/** in knots */
static getCalibratedAirspeed() {
return ADIRS.getFromAnyAdiru('ADR', 'COMPUTED_AIRSPEED');
}

/** in knots */
static getGroundSpeed() {
return ADIRS.getFromAnyAdiru('IR', 'GROUND_SPEED');
}

// FIXME there should be baro corrected altitude 1 (capt) and 2 (f/o)
/** in feet */
static getBaroCorrectedAltitude() {
return ADIRS.getFromAnyAdiru('ADR', 'ALTITUDE');
}

/** in degrees celsius */
static getStaticAirTemperature() {
return ADIRS.getFromAnyAdiru('ADR', 'STATIC_AIR_TEMPERATURE');
}

/** in hPa */
static getCorrectedAverageStaticPressure() {
return ADIRS.getFromAnyAdiru('ADR', 'CORRECTED_AVERAGE_STATIC_PRESSURE');
}

/**
*
* @param type IR or ADR
Expand Down
6 changes: 4 additions & 2 deletions fbw-a380x/src/systems/shared/src/OperatingSpeeds.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { MathUtils } from '@flybywiresim/fbw-sdk';
import { Mmo, VfeF1, VfeF1F, VfeF2, VfeF3, VfeFF, Vmcl, Vmo } from '@shared/PerformanceConstants';
import { FmgcFlightPhase } from '@shared/flightphase';
import { LerpLookupTable } from '@microsoft/msfs-sdk';
import { ADIRS } from 'instruments/src/MFD/shared/Adirs';

export enum ApproachConf {
CONF_1 = 1,
Expand Down Expand Up @@ -408,8 +409,9 @@ function getVfeNIdx(fi: number): number {
* @private
*/
function getVmo() {
// FIXME use ADR corrected average static pressure
return Math.min(Vmo, MathUtils.convertMachToKCas(Mmo, SimVar.GetSimVarValue('AMBIENT PRESSURE', 'millibar')));
const adrPressure = ADIRS.getCorrectedAverageStaticPressure();
const ambientPressure = adrPressure !== undefined ? adrPressure.valueOr(1013.25) : 1013.25;
return Math.min(Vmo, MathUtils.convertMachToKCas(Mmo, ambientPressure));
}

export class A380OperatingSpeeds {
Expand Down
1 change: 0 additions & 1 deletion fbw-common/src/systems/shared/src/MathUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,6 @@ export class MathUtils {
/**
* Convert Mach to Calibrated Air Speed
* @param mach Mach
* @param oat Kelvin
* @param pressure current pressure hpa
* @returns Calibrated Air Speed
*/
Expand Down

0 comments on commit 886180b

Please sign in to comment.