Skip to content

Commit

Permalink
feat(fmgc): transition names and final approach slope (#7637)
Browse files Browse the repository at this point in the history
* fix(fmgc): use transition names

* fix(fmgc): use vertical angles

* fix(fmgc): no promise returned here

* doc: changelog
  • Loading branch information
tracernz authored Dec 7, 2022
1 parent 976585f commit 5697964
Show file tree
Hide file tree
Showing 8 changed files with 28 additions and 92 deletions.
1 change: 1 addition & 0 deletions .github/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
## 0.10.0

1. [ADIRU] Implemented wind speed computation from TAS/GS/HDG - @tracernz (Mike)
1. [FMGC] Show proper transition names and final approach slope from AAU1 - @tracernz (Mike)

## 0.9.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ class CDUAvailableDeparturesPage {
mcdu.onRightInput[i + 1] = () => {
mcdu.setDepartureTransitionIndex(transIndex, () => {
CDUAvailableDeparturesPage.ShowPage(mcdu, airport, pageCurrent, true);
}).catch(console.error);
});
};
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,8 @@ class CDUFlightPlanPage {
}
distance = distance.toString();

const gp = wp.additionalData.verticalAngle ? `${wp.additionalData.verticalAngle.toFixed(1)}°` : undefined;

let speedConstraint = "---";
if (wp.speedConstraint > 10 && ident !== "MANUAL") {
speedConstraint = `{magenta}*{end}${wp.speedConstraint.toFixed(0)}`;
Expand Down Expand Up @@ -419,6 +421,7 @@ class CDUFlightPlanPage {
ident: ident,
color: color,
distance: distance,
gp,
spdColor: spdColor,
speedConstraint: speedConstraint,
altColor: altColor,
Expand Down Expand Up @@ -782,10 +785,11 @@ function renderFixTableHeader(isFlying) {
}

function renderFixHeader(rowObj, showNm = false, showDist = true, showFix = true) {
const { fixAnnotation, color, distance, bearingTrack } = rowObj;
const { fixAnnotation, color, distance, gp, bearingTrack } = rowObj;
const distUnit = showNm && !gp;
return [
`${(showFix) ? fixAnnotation.padEnd(7, "\xa0").padStart(8, "\xa0") : ""}`,
`${ showDist ? (showNm ? distance + "NM" : distance) : ''}${'\xa0'.repeat(showNm ? 3 : 5)}[color]${color}`,
`${ showDist ? (distUnit ? distance + "NM" : distance) : ''}{white}${(gp ? gp : '').padStart(distUnit ? 3 : 5, '\xa0')}{end}[color]${color}`,
`{${color}}${bearingTrack}{end}\xa0`,
];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,9 @@ class AirportInfo extends WayPointInfo {
approach.transitions = [];
for (let i = 0; i < approachData.transitions.length; i++) {
const transition = new Transition();
transition.name = approachData.transitions[i].legs[0].fixIcao.substr(7, 5);
transition.name = approachData.transitions[i].name.trim().length > 0
? approachData.transitions[i].name
: WayPoint.formatIdentFromIcao(approachData.transitions[i].legs[0].fixIcao);
transition.waypoints = [];
for (let j = 0; j < approachData.transitions[i].legs.length; j++) {
const wp = new WayPoint(this.instrument);
Expand Down Expand Up @@ -592,7 +594,9 @@ class AirportInfo extends WayPointInfo {
}
for (let j = 0; j < this.departures[i].enRouteTransitions.length; j++) {
const legsCount = this.departures[i].enRouteTransitions[j].legs.length;
this.departures[i].enRouteTransitions[j].name = this.departures[i].enRouteTransitions[j].legs[legsCount - 1].fixIcao.substr(7, 5);
this.departures[i].enRouteTransitions[j].name = this.departures[i].enRouteTransitions[j].name.trim().length > 0
? this.departures[i].enRouteTransitions[j].name
: WayPoint.formatIdentFromIcao(this.departures[i].enRouteTransitions[j].legs[legsCount - 1].fixIcao);
}
}
this.arrivals = data.arrivals;
Expand All @@ -612,7 +616,9 @@ class AirportInfo extends WayPointInfo {
}
}
for (let j = 0; j < this.arrivals[i].enRouteTransitions.length; j++) {
this.arrivals[i].enRouteTransitions[j].name = this.arrivals[i].enRouteTransitions[j].legs[0].fixIcao.substr(7, 5);
this.arrivals[i].enRouteTransitions[j].name = this.arrivals[i].enRouteTransitions[j].name.trim().length > 0
? this.arrivals[i].enRouteTransitions[j].name
: WayPoint.formatIdentFromIcao(this.arrivals[i].enRouteTransitions[j].legs[0].fixIcao);
}
}
}
Expand Down
75 changes: 1 addition & 74 deletions src/fmgc/src/flightplanning/LegsProcedure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ export class LegsProcedure {
mappedLeg.additionalData.theta = currentLeg.theta;
mappedLeg.additionalData.thetaTrue = A32NX_Util.magneticToTrue(currentLeg.theta, magCorrection);
mappedLeg.additionalData.annotation = currentAnnotation;
mappedLeg.additionalData.verticalAngle = currentLeg.verticalAngle ? currentLeg.verticalAngle - 360 : undefined;
}

this._currentIndex++;
Expand Down Expand Up @@ -620,78 +621,4 @@ export class LegsProcedure {

return waypoint;
}

public async calculateApproachData(runway: OneWayRunway): Promise<void> {
await this.ensureFacilitiesLoaded();

// our fallback for threshold crossing altitude is threshold + 50 feet
let threshCrossAlt = runway.thresholdElevation + 15.24;

// see if we have a runway fix, to give us coded TCH
// it can either be the MAP, or be before the MAP (MAP must be last leg of final approach)
// TCH altitude must be coded in altitude1 according to ARINC
for (let i = this._legs.length - 1; i > 0; i--) {
const leg = this._legs[i];
// TODO check it's the same runway for robustness?
if (leg.fixIcao.charAt(0) === 'R') {
threshCrossAlt = leg.altitude1;
break;
}
}

// MSFS does not give the coded descent angle
// we do our best to calculate one...
let fafAlt;
let fafIndex;
let fafToTcaDist = 0;
let lastLegPoint;

for (let i = 0; i < this._legs.length; i++) {
const leg = this._legs[i];
let termPoint;
if (leg.fixIcao.charAt(0) === 'R') {
termPoint = runway.thresholdCoordinates;
} else {
const fix = this._facilities.get(leg.fixIcao);
termPoint = new LatLongAlt(fix.lat, fix.lon);
}

if (leg.fixTypeFlags & FixTypeFlags.FAF) {
if (leg.altDesc === AltitudeDescriptor.Empty) {
// this is illegal by ARINC
break;
}

fafIndex = i;
// MSFS codes the wrong altDesc... but the right data...
fafAlt = leg.altitude2 > 0 ? leg.altitude2 : leg.altitude1;
} else if (fafIndex !== undefined) {
if (leg.distance > 0) {
fafToTcaDist += leg.distance;
} else {
// assume a straight leg
fafToTcaDist += 1852 * Avionics.Utils.computeGreatCircleDistance(lastLegPoint, termPoint);
}
}

if (leg.fixIcao.charAt(0) === 'R') {
break;
}

lastLegPoint = termPoint;
}

if (fafIndex !== undefined && fafAlt > 0 && fafToTcaDist > 0) {
let glideAngle = Math.atan((fafAlt - threshCrossAlt) / fafToTcaDist) * 180 / Math.PI;
// arinc specifics < 3 degrees is rounded up to 3 degrees when calculating glide angle from alt sources
// we do the same if we have invalid data..
if (!Number.isFinite(glideAngle) || glideAngle < 3 || glideAngle > 10) {
glideAngle = 3;
}

for (let i = fafIndex + 1; i < this._legs.length; i++) {
this._legs[i].verticalAngle = glideAngle;
}
}
}
}
4 changes: 0 additions & 4 deletions src/fmgc/src/flightplanning/ManagedFlightPlan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1150,10 +1150,6 @@ export class ManagedFlightPlan {

const procedure = new LegsProcedure(legs, this.getWaypoint(_startIndex - 1), this._parentInstrument, airportMagVar, this.procedureDetails.approachType, legAnnotations);

if (runway) {
procedure.calculateApproachData(runway);
}

let waypointIndex = _startIndex;
// console.log('MFP: buildApproach - ADDING WAYPOINTS ------------------------');
while (procedure.hasNext()) {
Expand Down
16 changes: 8 additions & 8 deletions src/fmgc/src/flightplanning/RawDataMapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,16 @@ export class RawDataMapper {

info.approaches = facility.approaches;
info.approaches.forEach((approach) => approach.name = normaliseApproachName(approach.name));
info.approaches.forEach((approach) => approach.transitions.forEach((trans) => trans.name = trans.legs[0].fixIcao.substring(7, 12).trim()));
info.approaches.forEach((approach) => approach.transitions.forEach((trans) => trans.name.trim().length === 0 && (trans.name = WayPoint.formatIdentFromIcao(trans.legs[0].fixIcao))));
info.approaches.forEach((approach) => approach.runway = approach.runway.trim());

info.departures = facility.departures;
info.departures.forEach((departure) => departure.runwayTransitions.forEach((trans) => trans.name = RawDataMapper.generateRunwayTransitionName(trans)));
info.departures.forEach((departure) => departure.enRouteTransitions.forEach((trans) => trans.name = RawDataMapper.generateDepartureEnRouteTransitionName(trans)));
info.departures.forEach((departure) => departure.enRouteTransitions.forEach((trans) => trans.name.trim().length === 0 && (trans.name = RawDataMapper.generateDepartureEnRouteTransitionName(trans))));

info.arrivals = facility.arrivals;
info.arrivals.forEach((arrival) => arrival.runwayTransitions.forEach((trans) => trans.name = RawDataMapper.generateRunwayTransitionName(trans)));
info.arrivals.forEach((arrival) => arrival.enRouteTransitions.forEach((trans) => trans.name = RawDataMapper.generateArrivalTransitionName(trans)));
info.arrivals.forEach((arrival) => arrival.enRouteTransitions.forEach((trans) => trans.name.trim().length === 0 && (trans.name = RawDataMapper.generateArrivalTransitionName(trans))));

info.runways = facility.runways;

Expand Down Expand Up @@ -130,7 +130,7 @@ export class RawDataMapper {
* @param runwayTransition The runway transition to generate the name for.
* @returns The runway transition name.
*/
public static generateRunwayTransitionName(runwayTransition: RunwayTransition): string {
public static generateRunwayTransitionName(runwayTransition: RawRunwayTransition): string {
let name = `RW${runwayTransition.runwayNumber}`;

switch (runwayTransition.runwayDesignation) {
Expand All @@ -153,16 +153,16 @@ export class RawDataMapper {
* @param enrouteTransition The enroute transition to generate a name for.
* @returns The generated transition name.
*/
public static generateArrivalTransitionName(enrouteTransition: EnrouteTransition): string {
return enrouteTransition.legs[0].fixIcao.substring(7, 12).trim();
public static generateArrivalTransitionName(enrouteTransition: RawEnRouteTransition): string {
return WayPoint.formatIdentFromIcao(enrouteTransition.legs[0].fixIcao);
}

/**
* Generates a departure transition name from a provided departure enroute transition.
* @param enrouteTransition The enroute transition to generate a name for.
* @returns The generated transition name.
*/
public static generateDepartureEnRouteTransitionName(enrouteTransition: EnrouteTransition): string {
return enrouteTransition.legs[enrouteTransition.legs.length - 1].fixIcao.substring(7, 12).trim();
public static generateDepartureEnRouteTransitionName(enrouteTransition: RawEnRouteTransition): string {
return WayPoint.formatIdentFromIcao(enrouteTransition.legs[enrouteTransition.legs.length - 1].fixIcao);
}
}
2 changes: 2 additions & 0 deletions src/fmgc/src/types/fstypes/FSTypes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ declare global {
trueDegrees: boolean;
turnDirection: TurnDirection;
type: LegType;
/** glide path angle + 360 */
verticalAngle?: number;
__Type: 'JS_Leg';
}

Expand Down

0 comments on commit 5697964

Please sign in to comment.