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

feat(fms): implement TOO STEEP PATH #9680

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,10 @@ class CDUFlightPlanPage {

waypointsAndMarkers.push({ wp, fpIndex: i, inAlternate: false, inMissedApproach, distanceFromLastLine, isActive: isActiveLeg && pseudoWaypointsOnLeg.length === 0 });

if (wp.calculated && wp.calculated.endsInTooSteepPath) {
waypointsAndMarkers.push({ marker: Markers.TOO_STEEP_PATH, fpIndex: i, inAlternate: false, inMissedApproach });
}

if (i === targetPlan.destinationLegIndex) {
destinationAirportOffset = Math.max(waypointsAndMarkers.length - 4, 0);
}
Expand Down Expand Up @@ -579,7 +583,12 @@ class CDUFlightPlanPage {
scrollWindow[rowI] = waypointsAndMarkers[winI];
addLskAt(rowI, 0, (value, scratchpadCallback) => {
if (value === FMCMainDisplay.clrValue) {
CDUFlightPlanPage.clearElement(mcdu, fpIndex, offset, forPlan, inAlternate, scratchpadCallback);
if (marker.marker === Markers.FPLN_DISCONTINUITY) {
CDUFlightPlanPage.clearElement(mcdu, fpIndex, offset, forPlan, inAlternate, scratchpadCallback);
} else {
mcdu.setScratchpadMessage(NXSystemMessages.notAllowed);
scratchpadCallback();
}
return;
} else if (value === "") {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ const WaypointConstraintType = Object.freeze({
DES: 2,
});

const TOO_STEEP_PATH_BEYOND_MESSAGE = "{amber}TOO STEEP PATH BEYOND{end}";

class CDUVerticalRevisionPage {
/**
* @param mcdu
Expand Down Expand Up @@ -142,10 +144,12 @@ class CDUVerticalRevisionPage {
}
}

const tooSteepPathInfo = waypoint.calculated.endsInTooSteepPath ? TOO_STEEP_PATH_BEYOND_MESSAGE : "";

mcdu.setTemplate([
["VERT REV {small}AT{end}{green} " + waypointIdent + "{end}"],
[],
[""],
["", "", tooSteepPathInfo],
[speedLimitTitle, ""],
[speedLimitCell, "RTA>[color]inop"],
[l3Title, r3Title],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { FmgcComponent } from '../FmgcComponent';
import { GpsPrimary } from './GpsPrimary';
import { GpsPrimaryLost } from './GpsPrimaryLost';
import { MapPartlyDisplayedLeft, MapPartlyDisplayedRight } from './MapPartlyDisplayed';
import { TooSteepPathAhead } from '@fmgc/components/fms-messages/TooSteepPathAhead';

/**
* This class manages Type II messages sent from the FMGC.
Expand Down Expand Up @@ -63,6 +64,7 @@ export class FmsMessages implements FmgcComponent {
new TdReached(),
new StepAhead(),
new StepDeleted(),
new TooSteepPathAhead(),
];

init(baseInstrument: BaseInstrument, flightPlanService: FlightPlanService): void {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright (c) 2021-2023 FlyByWire Simulations
//
// SPDX-License-Identifier: GPL-3.0

import { GuidanceController } from '@fmgc/guidance/GuidanceController';
import { FMMessageTypes } from '@flybywiresim/fbw-sdk';

import { FMMessageSelector, FMMessageUpdate } from './FmsMessages';

export class TooSteepPathAhead implements FMMessageSelector {
message = FMMessageTypes.TooSteepPathAhead;

private guidanceController: GuidanceController;

private lastState = false;

init(baseInstrument: BaseInstrument): void {
this.guidanceController = baseInstrument.guidanceController;
}

process(_: number): FMMessageUpdate {
const newState = this.guidanceController.vnavDriver.shouldShowTooSteepPathAhead();

if (newState !== this.lastState) {
this.lastState = newState;

return newState ? FMMessageUpdate.SEND : FMMessageUpdate.RECALL;
}

return FMMessageUpdate.NO_ACTION;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ export interface LegCalculations {
cumulativeDistanceWithTransitions: number;
/** The cumulative distance in nautical miles from this point to the missed approach point, with leg transition turns taken into account. */
cumulativeDistanceToEndWithTransitions: number;
/** Whether the leg terminates in a vertical discontinuity */
endsInTooSteepPath: boolean;
}

/**
Expand Down
19 changes: 19 additions & 0 deletions fbw-a32nx/src/systems/fmgc/src/flightplanning/plans/FlightPlan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -626,4 +626,23 @@ export class FlightPlan<P extends FlightPlanPerformanceData = FlightPlanPerforma

return false;
}

/**
* Check if there is a TOO STEEP PATH segment on a leg after the active leg
* @returns true if there is a TOO STEEP PATH segment
*/
hasTooSteepPathAhead(): boolean {
for (let i = this.activeLegIndex; i < this.firstMissedApproachLegIndex; i++) {
const element = this.maybeElementAt(i);
if (element?.isDiscontinuity === true) {
continue;
}

if (element?.calculated?.endsInTooSteepPath) {
return true;
}
}

return false;
}
}
19 changes: 11 additions & 8 deletions fbw-a32nx/src/systems/fmgc/src/guidance/Geometry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -557,14 +557,16 @@ export class Geometry {
cumulativeDistance += distance;
cumulativeDistanceWithTransitions += distanceWithTransitions;

flightPlanLeg.calculated = {
distance,
distanceWithTransitions,
cumulativeDistance,
cumulativeDistanceWithTransitions,
cumulativeDistanceToEnd: undefined,
cumulativeDistanceToEndWithTransitions: undefined,
};
if (!flightPlanLeg.calculated) {
this.initializeCalculatedDistances(flightPlanLeg, geometryLeg);
}

flightPlanLeg.calculated.distance = distance;
flightPlanLeg.calculated.distanceWithTransitions = distanceWithTransitions;
flightPlanLeg.calculated.cumulativeDistance = cumulativeDistance;
flightPlanLeg.calculated.cumulativeDistanceWithTransitions = cumulativeDistanceWithTransitions;
flightPlanLeg.calculated.cumulativeDistanceToEnd = undefined;
flightPlanLeg.calculated.cumulativeDistanceToEndWithTransitions = undefined;

geometryLeg.calculated = flightPlanLeg.calculated;
}
Expand All @@ -586,6 +588,7 @@ export class Geometry {
cumulativeDistanceWithTransitions: 0,
cumulativeDistanceToEnd: undefined,
cumulativeDistanceToEndWithTransitions: undefined,
endsInTooSteepPath: false,
};

if (geometryLeg) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ export class ConstraintReader {
this.descentAltitudeConstraints.push({
distanceFromStart: legDistanceFromStart,
constraint: altConstraint,
leg,
});
break;
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -747,14 +747,31 @@ export class VerticalProfileManager {
return managedClimbSpeedMach;
}
}

shouldShowTooSteepPathAhead(): boolean {
const isManagedLateralMode = this.fcuModes.isLatAutoControlActive();
const flightPhase = this.observer.get().flightPhase;
const isDesOrApprPhase = flightPhase === FmgcFlightPhase.Descent || flightPhase === FmgcFlightPhase.Approach;
const isCruisePhase = flightPhase === FmgcFlightPhase.Cruise;
const isCloseToDestination =
((this.constraintReader.distanceToEnd ?? Infinity) > 150 && isCruisePhase) || isDesOrApprPhase;

if (!isManagedLateralMode || !isCloseToDestination) {
return false;
}

return this.flightPlanService.active?.hasTooSteepPathAhead();
}
}

class FcuModeObserver {
private LAT_AUTO_CONTROL_MODES: LateralMode[] = [
LateralMode.NAV,
LateralMode.LOC_CPT,
LateralMode.LOC_TRACK,
LateralMode.LAND,
LateralMode.RWY,
LateralMode.GA_TRACK,
];

private VERT_CLIMB_MODES: VerticalMode[] = [
Expand Down
10 changes: 7 additions & 3 deletions fbw-a32nx/src/systems/fmgc/src/guidance/vnav/VnavDriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
} from './profile/NavGeometryProfile';
import { VMLeg } from '@fmgc/guidance/lnav/legs/VM';
import { FMLeg } from '@fmgc/guidance/lnav/legs/FM';
import { MathUtils } from '@flybywiresim/fbw-sdk';

export class VnavDriver implements GuidanceComponent {
version: number = 0;
Expand Down Expand Up @@ -288,11 +289,10 @@ export class VnavDriver implements GuidanceComponent {

const isPastCstrDeceleration =
checkpoint.reason === VerticalCheckpointReason.StartDecelerationToConstraint &&
currentDistanceFromStart - checkpoint.distanceFromStart > -1e-4;
MathUtils.isCloseToGreaterThan(currentDistanceFromStart, checkpoint.distanceFromStart);
const isPastLimitDeceleration =
checkpoint.reason === VerticalCheckpointReason.StartDecelerationToLimit &&
currentAltitude - checkpoint.altitude < 1e-4;

MathUtils.isCloseToLessThan(currentAltitude, checkpoint.altitude);
if (
isSpeedChangePoint(checkpoint) &&
checkpoint.targetSpeed >= decelPointSpeed &&
Expand Down Expand Up @@ -630,6 +630,10 @@ export class VnavDriver implements GuidanceComponent {
? completeLegAlongTrackPathDtg + referenceLeg.calculated.cumulativeDistanceToEndWithTransitions
: undefined;
}

shouldShowTooSteepPathAhead(): boolean {
return this.profileManager.shouldShowTooSteepPathAhead();
}
}

/// To check whether the value changed from old to new, but not if both values are NaN. (NaN !== NaN in JS)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
// SPDX-License-Identifier: GPL-3.0

import { VerticalProfileComputationParametersObserver } from '@fmgc/guidance/vnav/VerticalProfileComputationParameters';
import { DEFAULT_AIRCRAFT_CONTROL_SURFACE_CONFIG, DescentStrategy } from '@fmgc/guidance/vnav/descent/DescentStrategy';
import { DescentStrategy } from '@fmgc/guidance/vnav/descent/DescentStrategy';
import { WindComponent } from '@fmgc/guidance/vnav/wind';
import { AircraftConfiguration as AircraftCtlSurfcConfiguration } from '@fmgc/guidance/vnav/descent/ApproachPathBuilder';
import {
AircraftConfiguration as AircraftCtlSurfcConfiguration,
DEFAULT_AIRCRAFT_CONTROL_SURFACE_CONFIG,
} from '@fmgc/guidance/vnav/descent/ApproachPathBuilder';
import { MathUtils } from '@flybywiresim/fbw-sdk';
import { UnitType } from '@microsoft/msfs-sdk';
import { AircraftConfig, EngineModelParameters } from '@fmgc/flightplanning/AircraftConfigTypes';
Expand Down Expand Up @@ -341,7 +344,7 @@ export class ClimbThrustClimbStrategy implements ClimbStrategy {
tropoPause,
config.speedbrakesExtended,
config.flapConfig,
config.speedbrakesExtended,
config.gearExtended,
perfFactor,
);
}
Expand Down
Loading
Loading