diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index ef85c014418..c4c0e908173 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -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 diff --git a/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/CDU/A320_Neo_CDU_AvailableDeparturesPage.js b/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/CDU/A320_Neo_CDU_AvailableDeparturesPage.js index b7a92180a95..a67b3f9b928 100644 --- a/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/CDU/A320_Neo_CDU_AvailableDeparturesPage.js +++ b/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/CDU/A320_Neo_CDU_AvailableDeparturesPage.js @@ -175,7 +175,7 @@ class CDUAvailableDeparturesPage { mcdu.onRightInput[i + 1] = () => { mcdu.setDepartureTransitionIndex(transIndex, () => { CDUAvailableDeparturesPage.ShowPage(mcdu, airport, pageCurrent, true); - }).catch(console.error); + }); }; } } diff --git a/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/CDU/A320_Neo_CDU_FlightPlanPage.js b/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/CDU/A320_Neo_CDU_FlightPlanPage.js index c7aa5e7456a..d46435891af 100644 --- a/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/CDU/A320_Neo_CDU_FlightPlanPage.js +++ b/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/CDU/A320_Neo_CDU_FlightPlanPage.js @@ -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)}`; @@ -419,6 +421,7 @@ class CDUFlightPlanPage { ident: ident, color: color, distance: distance, + gp, spdColor: spdColor, speedConstraint: speedConstraint, altColor: altColor, @@ -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`, ]; } diff --git a/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/FlightElements/A32NX_Waypoint.js b/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/FlightElements/A32NX_Waypoint.js index 5c10918d58f..0519d9ec0cd 100644 --- a/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/FlightElements/A32NX_Waypoint.js +++ b/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/FlightElements/A32NX_Waypoint.js @@ -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); @@ -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; @@ -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); } } } diff --git a/src/fmgc/src/flightplanning/LegsProcedure.ts b/src/fmgc/src/flightplanning/LegsProcedure.ts index 5cfa8b9b462..62daa2fff9e 100644 --- a/src/fmgc/src/flightplanning/LegsProcedure.ts +++ b/src/fmgc/src/flightplanning/LegsProcedure.ts @@ -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++; @@ -620,78 +621,4 @@ export class LegsProcedure { return waypoint; } - - public async calculateApproachData(runway: OneWayRunway): Promise { - 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; - } - } - } } diff --git a/src/fmgc/src/flightplanning/ManagedFlightPlan.ts b/src/fmgc/src/flightplanning/ManagedFlightPlan.ts index 33f2ea549e0..24a199964d9 100644 --- a/src/fmgc/src/flightplanning/ManagedFlightPlan.ts +++ b/src/fmgc/src/flightplanning/ManagedFlightPlan.ts @@ -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()) { diff --git a/src/fmgc/src/flightplanning/RawDataMapper.ts b/src/fmgc/src/flightplanning/RawDataMapper.ts index 7aa0c33c4d1..6a260d65777 100644 --- a/src/fmgc/src/flightplanning/RawDataMapper.ts +++ b/src/fmgc/src/flightplanning/RawDataMapper.ts @@ -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; @@ -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) { @@ -153,8 +153,8 @@ 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); } /** @@ -162,7 +162,7 @@ export class RawDataMapper { * @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); } } diff --git a/src/fmgc/src/types/fstypes/FSTypes.d.ts b/src/fmgc/src/types/fstypes/FSTypes.d.ts index 73ae165aea6..c762d628fca 100644 --- a/src/fmgc/src/types/fstypes/FSTypes.d.ts +++ b/src/fmgc/src/types/fstypes/FSTypes.d.ts @@ -189,6 +189,8 @@ declare global { trueDegrees: boolean; turnDirection: TurnDirection; type: LegType; + /** glide path angle + 360 */ + verticalAngle?: number; __Type: 'JS_Leg'; }