From db6cb81dfee947f8a19e27c130db42c99f3426de Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 27 Dec 2022 02:41:04 +0000 Subject: [PATCH 01/39] build: update flyPadOS 3 localization (#7620) Co-authored-by: Create or Update Pull Request Action Co-authored-by: Frank Kopp Co-authored-by: Benjamin Dupont --- src/instruments/src/EFB/Localization/ar.json | 5 + src/instruments/src/EFB/Localization/cs.json | 5 + .../src/EFB/Localization/da-DK.json | 5 + src/instruments/src/EFB/Localization/de.json | 5 + src/instruments/src/EFB/Localization/el.json | 5 + src/instruments/src/EFB/Localization/en.json | 12 +-- src/instruments/src/EFB/Localization/es.json | 5 + src/instruments/src/EFB/Localization/eu.json | 5 + src/instruments/src/EFB/Localization/fi.json | 75 ++++++++------- src/instruments/src/EFB/Localization/fr.json | 93 ++++++++++--------- src/instruments/src/EFB/Localization/he.json | 19 ++-- src/instruments/src/EFB/Localization/hi.json | 5 + src/instruments/src/EFB/Localization/hr.json | 5 + src/instruments/src/EFB/Localization/hu.json | 5 + src/instruments/src/EFB/Localization/id.json | 5 + src/instruments/src/EFB/Localization/it.json | 15 ++- src/instruments/src/EFB/Localization/ja.json | 5 + src/instruments/src/EFB/Localization/ko.json | 5 + src/instruments/src/EFB/Localization/lt.json | 21 +++-- src/instruments/src/EFB/Localization/ms.json | 5 + src/instruments/src/EFB/Localization/nb.json | 5 + src/instruments/src/EFB/Localization/nl.json | 5 + src/instruments/src/EFB/Localization/pl.json | 5 + .../src/EFB/Localization/pt-BR.json | 5 + .../src/EFB/Localization/pt-PT.json | 5 + src/instruments/src/EFB/Localization/ro.json | 5 + src/instruments/src/EFB/Localization/ru.json | 5 + src/instruments/src/EFB/Localization/sk.json | 5 + src/instruments/src/EFB/Localization/sl.json | 5 + src/instruments/src/EFB/Localization/sv.json | 5 + src/instruments/src/EFB/Localization/th.json | 5 + src/instruments/src/EFB/Localization/tr.json | 5 + src/instruments/src/EFB/Localization/vi.json | 5 + .../src/EFB/Localization/zh-Hans-CN.json | 5 + .../src/EFB/Localization/zh-Hant-HK.json | 5 + .../src/EFB/Localization/zh-Hant-TW.json | 5 + 36 files changed, 280 insertions(+), 105 deletions(-) diff --git a/src/instruments/src/EFB/Localization/ar.json b/src/instruments/src/EFB/Localization/ar.json index e4412c3bdb9..b569aafe2b6 100644 --- a/src/instruments/src/EFB/Localization/ar.json +++ b/src/instruments/src/EFB/Localization/ar.json @@ -520,8 +520,12 @@ "SimOptions": { "Active": "نشط", "Auto": "تلقائي", + "Both": "Synchronized", "Calibrate": "تعيّر ", + "Captain": "Captain", + "CockpitSeatUsedToControl": "Cockpit Seat Used To Control", "ConesEnabled": "اقماع الامان", + "Copilot": "Copilot", "DefaultBarometerUnit": "وحدة البارومتر الافتراضية", "DynamicRegistrationDecal": "ملصق تسجيل ديناميكي", "EnableSimBridge": "تمكين اتصال خادم MCDU (إلغاء التنشيط التلقائي بعد 5 دقائق إذا لم يكن هناك اتصال ناجح)", @@ -533,6 +537,7 @@ "None": "لا شيء", "Off": "إيقاف", "Save": "حفظ", + "Side": "Side", "SimBridgePort": "منفذ خادم MCDU خارجي", "SyncMsfsFlightPlan": "مزامنة خطة رحلة MSFS", "ThrottleDetents": "محددات دفة تحكم النفاث ", diff --git a/src/instruments/src/EFB/Localization/cs.json b/src/instruments/src/EFB/Localization/cs.json index 4572501f22f..957e089e5c8 100644 --- a/src/instruments/src/EFB/Localization/cs.json +++ b/src/instruments/src/EFB/Localization/cs.json @@ -520,8 +520,12 @@ "SimOptions": { "Active": "Aktivní", "Auto": "Auto.", + "Both": "Synchronizováno", "Calibrate": "Kalibrovat", + "Captain": "Kapitán", + "CockpitSeatUsedToControl": "Sedadlo používané k ovládání", "ConesEnabled": "Výstražné kužely", + "Copilot": "Kopilot", "DefaultBarometerUnit": "Výchozí jednotky tlaku vzduchu", "DynamicRegistrationDecal": "Dynamická imatrikulace letadla", "EnableSimBridge": "Povolit připojení SimBridge (Bez úspěšného připojení se po 5 minutách automaticky vypne)", @@ -533,6 +537,7 @@ "None": "Žádné", "Off": "Vypnuto", "Save": "Uložit", + "Side": "Strana", "SimBridgePort": "Externí port SimBridge", "SyncMsfsFlightPlan": "Synchronizace letového plánu MSFS", "ThrottleDetents": "Zarážky plynu", diff --git a/src/instruments/src/EFB/Localization/da-DK.json b/src/instruments/src/EFB/Localization/da-DK.json index 45527a2b26d..4ffc5174c35 100644 --- a/src/instruments/src/EFB/Localization/da-DK.json +++ b/src/instruments/src/EFB/Localization/da-DK.json @@ -520,8 +520,12 @@ "SimOptions": { "Active": "Aktiv", "Auto": "Automatisk", + "Both": "Synchronized", "Calibrate": "Kalibrering", + "Captain": "Captain", + "CockpitSeatUsedToControl": "Cockpit Seat Used To Control", "ConesEnabled": "Sikkerhed kegler", + "Copilot": "Copilot", "DefaultBarometerUnit": "Standard Barometer enhed", "DynamicRegistrationDecal": "Dynamisk registrerings mærke", "EnableSimBridge": "Aktiver SimBridge server forbindelse (Deaktiveres automatisk efter 5 minutter, hvis der ikke oprettes succesfuld forbindelse)", @@ -533,6 +537,7 @@ "None": "Ingen", "Off": "Fra", "Save": "Gem", + "Side": "Side", "SimBridgePort": "Ekstern SimBridge serverport", "SyncMsfsFlightPlan": "Synkroniser MSFS-flyveplan", "ThrottleDetents": "Gashåndtagspositioner", diff --git a/src/instruments/src/EFB/Localization/de.json b/src/instruments/src/EFB/Localization/de.json index 4ae9abb1aee..a54b037d169 100644 --- a/src/instruments/src/EFB/Localization/de.json +++ b/src/instruments/src/EFB/Localization/de.json @@ -520,8 +520,12 @@ "SimOptions": { "Active": "Aktiv", "Auto": "Auto", + "Both": "Synchronisiert", "Calibrate": "Kalibrieren", + "Captain": "Kapitän", + "CockpitSeatUsedToControl": "Cockpit Seat Used To Control", "ConesEnabled": "Sicherheitskegel", + "Copilot": "Copilot", "DefaultBarometerUnit": "Standard Barometer-Einheit", "DynamicRegistrationDecal": "Flugzeugkennzeichen dynamisch darstellen", "EnableSimBridge": "SimBridge Serververbindung aktivieren (Wird nach 5 Minuten automatisch deaktiviert, wenn keine Verbindung zustande kommt)", @@ -533,6 +537,7 @@ "None": "Aus", "Off": "Aus", "Save": "Zurückspeichern bei Änderung", + "Side": "Seite", "SimBridgePort": "Externer SimBridge-Port", "SyncMsfsFlightPlan": "MSFS-Flugplan-Synchronisation", "ThrottleDetents": "Schubhebelkalibrierung", diff --git a/src/instruments/src/EFB/Localization/el.json b/src/instruments/src/EFB/Localization/el.json index 0a14ea85258..270497c521f 100644 --- a/src/instruments/src/EFB/Localization/el.json +++ b/src/instruments/src/EFB/Localization/el.json @@ -520,8 +520,12 @@ "SimOptions": { "Active": "Ενεργό", "Auto": "Αυτόματο", + "Both": "Synchronized", "Calibrate": "Βαθμονόμηση", + "Captain": "Captain", + "CockpitSeatUsedToControl": "Cockpit Seat Used To Control", "ConesEnabled": "Safety Cones", + "Copilot": "Copilot", "DefaultBarometerUnit": "Προκαθορισμένη Βαρομετρική Μονάδα", "DynamicRegistrationDecal": "Δυναμική Χαλκομανία Εγγραφής", "EnableSimBridge": "Ενεργοποίηση σύνδεσης διακομιστή MCDU (Αυτόματη απενεργοποίηση μετά από 5 λεπτά εάν δεν υπάρχει επιτυχής σύνδεση)", @@ -533,6 +537,7 @@ "None": "Κανένα", "Off": "Απενεργοποιημένο", "Save": "Αποθήκευση", + "Side": "Side", "SimBridgePort": "Εξωτερική Θύρα Διακομιστή MCDU", "SyncMsfsFlightPlan": "Συγχρονισμός του Σχεδίου Πτήσεως MSFS", "ThrottleDetents": "Αναστολέας Γκαζιού", diff --git a/src/instruments/src/EFB/Localization/en.json b/src/instruments/src/EFB/Localization/en.json index 668c8d91433..ce2cfb58d04 100644 --- a/src/instruments/src/EFB/Localization/en.json +++ b/src/instruments/src/EFB/Localization/en.json @@ -159,11 +159,6 @@ "LoadingTime": "Loading Time", "Passengers": "Passengers", "Planned": "Planned", - "DeboardConfirmationTitle": "Deboard all Passengers?", - "DeboardConfirmationBody":"Please confirm deboarding all passengers", - "DeboardConfirmationConfirm": "Deboard", - "DeboardConfirmationCancel":"Cancel", - "LoadingTime": "Loading Time", "TT": { "AircraftMustBeColdAndDarkToChangeBoardingTimes": "Aircraft Must Be On the Ground and Have Engines Shutdown to Change Boarding Duration", "FillPayloadFromSimbrief": "Fill Payload Information from Simbrief", @@ -525,8 +520,12 @@ "SimOptions": { "Active": "Active", "Auto": "Auto", + "Both": "Synchronized", "Calibrate": "Calibrate", + "Captain": "Captain", + "CockpitSeatUsedToControl": "Cockpit Seat Used To Control", "ConesEnabled": "Safety Cones", + "Copilot": "Copilot", "DefaultBarometerUnit": "Default Barometer Unit", "DynamicRegistrationDecal": "Dynamic Registration Decal", "EnableSimBridge": "Enable Simbridge Connection (Auto deactivates after 5 minutes if no successful connection)", @@ -538,6 +537,7 @@ "None": "None", "Off": "Off", "Save": "Save", + "Side": "Side", "SimBridgePort": "External SimBridge Port", "SyncMsfsFlightPlan": "Sync MSFS Flight Plan", "ThrottleDetents": "Throttle Detents", @@ -618,4 +618,4 @@ "Tue": "Tue", "Wed": "Wed" } -} +} \ No newline at end of file diff --git a/src/instruments/src/EFB/Localization/es.json b/src/instruments/src/EFB/Localization/es.json index 0b363d56420..1c7437cc964 100644 --- a/src/instruments/src/EFB/Localization/es.json +++ b/src/instruments/src/EFB/Localization/es.json @@ -520,8 +520,12 @@ "SimOptions": { "Active": "Activo", "Auto": "Auto", + "Both": "Synchronized", "Calibrate": "Calibrar", + "Captain": "Captain", + "CockpitSeatUsedToControl": "Cockpit Seat Used To Control", "ConesEnabled": "Conos de seguridad", + "Copilot": "Copilot", "DefaultBarometerUnit": "Unidad del barómetro predeterminado", "DynamicRegistrationDecal": "Calcomanía de registro dinámica", "EnableSimBridge": "Activar la conexión con el servidor MCDU (se desactivará automáticamente tras 5 minutos si no ha habido una conexión exitosa)", @@ -533,6 +537,7 @@ "None": "Ninguno", "Off": "Desactivado", "Save": "Guardar", + "Side": "Side", "SimBridgePort": "Puerto del servidor MCDU externo", "SyncMsfsFlightPlan": "Sincronizar plan de vuelo de MSFS", "ThrottleDetents": "Throttle Detents", diff --git a/src/instruments/src/EFB/Localization/eu.json b/src/instruments/src/EFB/Localization/eu.json index f0a6c2b792f..2884ed0b76f 100644 --- a/src/instruments/src/EFB/Localization/eu.json +++ b/src/instruments/src/EFB/Localization/eu.json @@ -520,8 +520,12 @@ "SimOptions": { "Active": "Active", "Auto": "Auto", + "Both": "Synchronized", "Calibrate": "Calibrate", + "Captain": "Captain", + "CockpitSeatUsedToControl": "Cockpit Seat Used To Control", "ConesEnabled": "Safety Cones", + "Copilot": "Copilot", "DefaultBarometerUnit": "Default Barometer Unit", "DynamicRegistrationDecal": "Dynamic Registration Decal", "EnableSimBridge": "Enable MCDU Server Connection (Auto deactivates after 5 minutes if no successful connection)", @@ -533,6 +537,7 @@ "None": "None", "Off": "Off", "Save": "Save", + "Side": "Side", "SimBridgePort": "External MCDU Server Port", "SyncMsfsFlightPlan": "Sync MSFS Flight Plan", "ThrottleDetents": "Throttle Detents", diff --git a/src/instruments/src/EFB/Localization/fi.json b/src/instruments/src/EFB/Localization/fi.json index ca1c11c230e..4709068555c 100644 --- a/src/instruments/src/EFB/Localization/fi.json +++ b/src/instruments/src/EFB/Localization/fi.json @@ -4,22 +4,22 @@ "ChangeATISATCSourceButton": "Vaihda ATIS/ATC lähde", "ConnectHoppieACARS": "Yhdistä Hoppien ACARSiin", "NoInformationAvailableForThisFrequency": "Tietoja ei ole saatavilla tälle taajuudelle", - "SearchPlaceholder": "Search", + "SearchPlaceholder": "Haku", "SelectCorrectATISATCSource": "Tämä sivu on saatavilla vain, kun IVAO tai VATSIM on valittuna ATIS/ATC lähteeksi asetuksista.", "SetActive": "Aseta aktiiviseksi", "SetStandby": "Aseta valmiustilaan", - "ShowAll": "All", - "ShowApproach": "Approach", + "ShowAll": "Kaikki", + "ShowApproach": "Saapuminen", "ShowAtis": "ATIS", - "ShowDelivery": "Delivery", - "ShowDeparture": "Departure", - "ShowGround": "Ground", - "ShowRadar": "Radar", - "ShowTower": "Tower", + "ShowDelivery": "Kuljetus", + "ShowDeparture": "Lähtö", + "ShowGround": "Maa", + "ShowRadar": "Tutka", + "ShowTower": "Torni", "Standby": "Valmiustila", "TT": { - "AtcCallSignSearch": "ATC Call-sign Search", - "AtcTypeFilter": "Filter for" + "AtcCallSignSearch": "ATC kutsukoodin haku", + "AtcTypeFilter": "Suodata" }, "Title": "Lennonjohto" }, @@ -151,11 +151,11 @@ "BoardingTime": "Koneeseen nousun kesto", "Cargo": "Cargo", "Current": "Current", - "DeboardConfirmationBody": "Please confirm deboarding all passengers", - "DeboardConfirmationCancel": "Cancel", - "DeboardConfirmationConfirm": "Deboard", - "DeboardConfirmationTitle": "Deboard all Passengers?", - "EstimatedDurationUnit": "minutes", + "DeboardConfirmationBody": "Vahvista kaikkien matkustajien poisto", + "DeboardConfirmationCancel": "Peruuta", + "DeboardConfirmationConfirm": "Poista matkustajat", + "DeboardConfirmationTitle": "Poista kaikki matkustajat?", + "EstimatedDurationUnit": "minuuttia", "LoadingTime": "Loading Time", "Passengers": "Passengers", "Planned": "Planned", @@ -169,7 +169,7 @@ "PerPaxBagWeight": "Per Passenger Bag Weight", "PerPaxWeight": "Per Passenger Weight", "StartBoarding": "Begin Boarding", - "StartDeboarding": "Begin Deboarding" + "StartDeboarding": "Aloita matkustajien poisto" }, "Title": "Payload", "ZFW": "ZFW", @@ -203,10 +203,10 @@ "Altn": "Vaihtoehtoinen", "ExitFullscreenMode": "Poistu kokoruuduntilasta", "From": "Mistä", - "LoadingImage": "Loading Image", - "LoadingImageFailed": "Loading Image failed", - "LoadingPdf": "Loading PDF", - "LoadingPdfFailed": "Loading PDF failed", + "LoadingImage": "Ladataan kuvaa", + "LoadingImageFailed": "Kuvan lataaminen epäonnistui", + "LoadingPdf": "Ladataan PDF-tiedostoa", + "LoadingPdfFailed": "PDF-tiedoston lataus epäonnistui", "LocalFiles": { "Both": "Molemmat", "EstablishingConnection": "Muodostetaan yhteyttä", @@ -366,7 +366,7 @@ "ConfirmationDialogMsg": "Vahvista esiasetuksen lataaminen.", "CurrentProcedureStep": "Nykyinen menettelytapa", "PleaseConfirmLoadingOfPreset": "Vahvista esiasetuksen lataaminen.", - "Powered": "Powered", + "Powered": "Kytketty virtaan", "ReadyPushback": "Valmiina työntöön", "ReadyTakeoff": "Selvä lentoonlähtöön", "ReadyTaxi": "Valmis rullaamaan", @@ -379,11 +379,11 @@ "InteriorLighting": { "AircraftNeedsToBePoweredToLoadPresets": "Esiasetusten lataamiseksi virta tulee olla kytketty.", "AircraftNeedsToBePoweredToSavePresets": "Esiasetusten tallentamiseksi virta tulee olla kytketty.", - "AutoLoadDawnDusk": "Dawn/Dusk:", - "AutoLoadDay": "Day:", - "AutoLoadLightingHelpTitle": "Automatic Preset Loading", - "AutoLoadLightingPreset": "Enable automatic loading of lighting presets:", - "AutoLoadNight": "Night:", + "AutoLoadDawnDusk": "Aamunsarastus/iltahämärä:", + "AutoLoadDay": "Päivä:", + "AutoLoadLightingHelpTitle": "Automaattinen esiasetusten lataus", + "AutoLoadLightingPreset": "Ota valaistuksen esiasetusten automaattinen lataus käyttöön:", + "AutoLoadNight": "Yö:", "AutoLoadNoneSelection": "Ei mitään", "LoadPreset": "Lataa esiasetus", "LoadingPreset": "Ladataan esiasetus", @@ -438,7 +438,7 @@ "SliderSpeed": "Siirrä haluttuun nopeuteen", "SystemEnabledOff": "Napsauta kytkeäksesi työntöjärjestelmä päälle.", "SystemEnabledOn": "Napsauta kytkeäksesi työntöjärjestelmän kokonaan pois päältä.", - "UseControllerInput": "Turn controller input from rudder and elevator on/off", + "UseControllerInput": "Vaihda ohjaimen syöte peräsimestä ja korkeusperäsimestä on/off", "ZoomIn": "Lähennä", "ZoomOut": "Loitonna" }, @@ -446,7 +446,7 @@ "TugDirection": "Työntöauton suunta", "TugInTransit": "Odotetaan työntöautoa", "TugSpeed": "Työntöauton nopeus", - "UseControllerInput": "Use Controller Input" + "UseControllerInput": "Käyttäjän ohjaimen syöte" }, "Settings": { "About": { @@ -506,25 +506,29 @@ "AutofillChecklists": "Tarkistuslistan täyttö automaattisesti", "BoardingTime": "Boarding-aika", "DmcSelfTestTime": "DMC itsenäisen testauksen aika", - "FirstOfficerAvatar": "Show First Officer Avatar", + "FirstOfficerAvatar": "Näytä perämiehen hahmo", "HomeCockpitMode": "Kotiohjaamo-tila", "McduFocusTimeout": "Lentotietokone poissa käytöstä tarkennuksen aikana (sekunteina)", "McduKeyboardInput": "MCDU näppäimistö syöttö", "PauseAtTod": "T/D Pause", "PauseAtTodDistance": "T/D Pause Distance (nm)", - "PilotAvatar": "Show Pilot Avatar", + "PilotAvatar": "Näytä lentäjän hahmo", "SeparateTillerFromRudderInputs": "Erota nokkapyörän ohjaus peräsimestä", - "SyncEfis": "Sync EFIS controls between Captain and FO", + "SyncEfis": "Synkronoi EFIS kapteenin ja perämiehen välillä", "Title": "Realismi" }, "SimOptions": { "Active": "Aktiivinen", "Auto": "Automaattinen", + "Both": "Synkronoitu", "Calibrate": "Kalibroi", + "Captain": "Kapteeni", + "CockpitSeatUsedToControl": "Cockpit Seat Used To Control", "ConesEnabled": "Varoituskartiot", + "Copilot": "Lentoperämies", "DefaultBarometerUnit": "Paineen oletusyksikkö", "DynamicRegistrationDecal": "Dynaaminen rekisteröintimerkintä", - "EnableSimBridge": "Ota lentotietokoneen palvelinyhteys käyttöön (yhdistysyritykset loppuvat 5 minuutin kuluttua, jos yhdistäminen ei onnistu)", + "EnableSimBridge": "Yhdistä SimBridgeen (yhdistysyritykset loppuvat 5 minuutin kuluttua, jos yhdistäminen ei onnistu)", "EnabledMcduServerConnectionAutoDeactivatesAfter5MinutesIfNoSuccessfulConnection": "Ota lentotietokoneen palvelinyhteys käyttöön (yhdistysyritykset loppuvat 5 minuutin kuluttua, jos yhdistäminen ei onnistu)", "ExternalMcduServerPort": "Ulkoinen lentotietokoneen palvelinyhteys", "Hpa": "hPa", @@ -533,7 +537,8 @@ "None": "Ei mitään", "Off": "Pois päältä", "Save": "Tallenna", - "SimBridgePort": "Ulkoinen lentotietokoneen palvelinyhteys", + "Side": "Puoli", + "SimBridgePort": "Ulkoinen SimBridge palvelinyhteys", "SyncMsfsFlightPlan": "Synkronoi MSFS lentosuunnitelma", "ThrottleDetents": "Kaasupykälät", "Title": "Sim -asetukset", @@ -605,8 +610,8 @@ "Sep": "Syys", "Sun": "su", "TT": { - "ConnectedToLocalApi": "Yhdistetty paikalliseen ohjelmointirajapintaan", - "DisconnectedFromLocalApi": "Lopeta yhteys paikalliseen ohjelmointirajapintaan", + "ConnectedToLocalApi": "Yhdistetty SimBridgeen", + "DisconnectedFromLocalApi": "Yhteys katkaistu SimBridgeen", "TurnOffOrShutdownEfb": "Sammuta tai sulje EFB" }, "Thu": "to", diff --git a/src/instruments/src/EFB/Localization/fr.json b/src/instruments/src/EFB/Localization/fr.json index 900ae53aa01..1773a5d6854 100644 --- a/src/instruments/src/EFB/Localization/fr.json +++ b/src/instruments/src/EFB/Localization/fr.json @@ -4,22 +4,22 @@ "ChangeATISATCSourceButton": "Modifier la source ATIS/ATC", "ConnectHoppieACARS": "Connecter l'ACARS Hoppie", "NoInformationAvailableForThisFrequency": "Aucune information disponible pour cette fréquence", - "SearchPlaceholder": "Search", + "SearchPlaceholder": "Rechercher", "SelectCorrectATISATCSource": "Cette page est uniquement disponible lorsque IVAO ou VATSIM est sélectionné comme source ATIS/ATC dans la page des paramètres.", "SetActive": "Activer", "SetStandby": "Passer en Standby", - "ShowAll": "All", - "ShowApproach": "Approach", + "ShowAll": "Tout", + "ShowApproach": "Approche", "ShowAtis": "ATIS", "ShowDelivery": "Delivery", - "ShowDeparture": "Departure", - "ShowGround": "Ground", + "ShowDeparture": "Départ", + "ShowGround": "Sol", "ShowRadar": "Radar", - "ShowTower": "Tower", + "ShowTower": "Tour", "Standby": "Veille", "TT": { - "AtcCallSignSearch": "ATC Call-sign Search", - "AtcTypeFilter": "Filter for" + "AtcCallSignSearch": "Recherche de l'indicatif d'appel ATC", + "AtcTypeFilter": "Filtre" }, "Title": "Contrôle du trafic aérien" }, @@ -148,30 +148,30 @@ "Unavailable": "Indisponible" }, "Payload": { - "BoardingTime": "Boarding Time", + "BoardingTime": "Heure d'embarquement", "Cargo": "Cargo", "Current": "Current", - "DeboardConfirmationBody": "Please confirm deboarding all passengers", - "DeboardConfirmationCancel": "Cancel", - "DeboardConfirmationConfirm": "Deboard", - "DeboardConfirmationTitle": "Deboard all Passengers?", + "DeboardConfirmationBody": "Confirmer le débarquement de tous les passagers ?", + "DeboardConfirmationCancel": "Annuler", + "DeboardConfirmationConfirm": "Débarquement", + "DeboardConfirmationTitle": "Débarquer tous les passagers?", "EstimatedDurationUnit": "minutes", "LoadingTime": "Loading Time", - "Passengers": "Passengers", - "Planned": "Planned", + "Passengers": "Passagers", + "Planned": "Planifié", "TT": { "AircraftMustBeColdAndDarkToChangeBoardingTimes": "Aircraft Must Be On the Ground and Have Engines Shutdown to Change Boarding Duration", "FillPayloadFromSimbrief": "Fill Payload Information from Simbrief", "MaxCargo": "Max Cargo", - "MaxPassengers": "Maximum Passengers", + "MaxPassengers": "Nombre maximum de passagers", "MaxZFW": "Maximum ZFW", "MaxZFWCG": "Maximum ZFWCG", "PerPaxBagWeight": "Per Passenger Bag Weight", "PerPaxWeight": "Per Passenger Weight", - "StartBoarding": "Begin Boarding", - "StartDeboarding": "Begin Deboarding" + "StartBoarding": "Commencer l'embarquement", + "StartDeboarding": "Commencer le débarquement" }, - "Title": "Payload", + "Title": "Charge utile", "ZFW": "ZFW", "ZFWCG": "ZFWCG" }, @@ -203,10 +203,10 @@ "Altn": "Altn", "ExitFullscreenMode": "Quitter le mode plein-écran", "From": "FROM", - "LoadingImage": "Loading Image", - "LoadingImageFailed": "Loading Image failed", - "LoadingPdf": "Loading PDF", - "LoadingPdfFailed": "Loading PDF failed", + "LoadingImage": "Chargement de l’image", + "LoadingImageFailed": "Échec du chargement de l'image", + "LoadingPdf": "Chargement du PDF", + "LoadingPdfFailed": "Échec du chargement du PDF", "LocalFiles": { "Both": "Les deux", "EstablishingConnection": "Connexion en cours", @@ -366,7 +366,7 @@ "ConfirmationDialogMsg": "Veuillez confirmer le chargement du préréglage.", "CurrentProcedureStep": "Étape de procédure en cours", "PleaseConfirmLoadingOfPreset": "Veuillez confirmer le chargement du préréglage.", - "Powered": "Powered", + "Powered": "Moteurs en route", "ReadyPushback": "Prêt pour le repoussage", "ReadyTakeoff": "Prêt pour le décollage", "ReadyTaxi": "Prêt pour le roulage", @@ -379,12 +379,12 @@ "InteriorLighting": { "AircraftNeedsToBePoweredToLoadPresets": "L'avion doit être alimenté pour charger des préréglages", "AircraftNeedsToBePoweredToSavePresets": "L'avion doit être alimenté pour enregistrer les préréglages", - "AutoLoadDawnDusk": "Dawn/Dusk:", - "AutoLoadDay": "Day:", - "AutoLoadLightingHelpTitle": "Automatic Preset Loading", - "AutoLoadLightingPreset": "Enable automatic loading of lighting presets:", - "AutoLoadNight": "Night:", - "AutoLoadNoneSelection": "None", + "AutoLoadDawnDusk": "Aube", + "AutoLoadDay": "Jour:", + "AutoLoadLightingHelpTitle": "Chargement automatique des préréglages", + "AutoLoadLightingPreset": "Activer le chargement automatique des préréglages d'éclairage:", + "AutoLoadNight": "Nuit:", + "AutoLoadNoneSelection": "Aucun", "LoadPreset": "Charger le préréglage", "LoadingPreset": "Chargement du préréglage", "NewNameConfirmationDialogMsg": "Veuillez confirmer le nouveau nom du préréglage d'éclairage", @@ -410,7 +410,7 @@ "CallTug": "Appeler le remorqueur", "DisableSystemMessageBody": "Êtes-vous sûr de désactiver le système de repoussage ? Cela retirera également le remorqueur.", "DisableSystemMessageTitle": "Désactiver le système de repoussage", - "EnableSystemMessageBody": "Le nouveau Système de Repoussage du FlyPadOS 3 n'est pas encore finalisé. Il est incompatible avec d'autres add-ons de Repoussage et peut entraîner d'autres problèmes.", + "EnableSystemMessageBody": "Le nouveau Système de Repoussage du FlyPadOS 3 peut provoquer des conflits avec d'autres add-ons de repoussage. Nous vous recommandons de ne pas activer ce système si vous pensez utiliser un autre add-on de repoussage.", "EnableSystemMessageTitle": "Activer le système de repoussage", "Forward": "Avancer", "Halt": "En pause", @@ -438,7 +438,7 @@ "SliderSpeed": "Déplacer pour la vitesse souhaitée", "SystemEnabledOff": "Cliquez pour démarrer le système de repoussage.", "SystemEnabledOn": "Cliquez pour éteindre complètement le système de repoussage.", - "UseControllerInput": "Turn controller input from rudder and elevator on/off", + "UseControllerInput": "Activer/désactiver l'entrée du contrôleur de direction et de profondeur", "ZoomIn": "Zoom avant", "ZoomOut": "Zoom arrière" }, @@ -446,7 +446,7 @@ "TugDirection": "Direction du remorqueur", "TugInTransit": "En attente du remorqueur/de la liaison", "TugSpeed": "Vitesse du remorqueur", - "UseControllerInput": "Use Controller Input" + "UseControllerInput": "Utiliser l'entrée du contrôleur" }, "Settings": { "About": { @@ -457,7 +457,7 @@ "EngineOutAccelerationHeight": "Engine-Out Acceleration Height (pi)", "IsisBaroUnit": "Unité Baromètre ISIS", "IsisMetricAltitude": "Altitude métrique ISIS", - "LatLonExtendedFormat": "Format de point de cheminement lat/long FMGC", + "LatLonExtendedFormat": "Format de waypoint dans le FMGC", "PaxSigns": "Voyants passagers", "RmpVhfSpacing": "Espacement VHF RMP", "Satcom": "Satcom", @@ -506,25 +506,29 @@ "AutofillChecklists": "Saisie automatique des check-lists", "BoardingTime": "Durée d'embarquement", "DmcSelfTestTime": "Temps d'auto-test DMC", - "FirstOfficerAvatar": "Show First Officer Avatar", + "FirstOfficerAvatar": "Afficher l'avatar du copilote", "HomeCockpitMode": "Mode home cockpit", "McduFocusTimeout": "Délai d'attente du focus MCDU (secondes)", "McduKeyboardInput": "Entrée clavier MCDU", - "PauseAtTod": "T/D Pause", - "PauseAtTodDistance": "T/D Pause Distance (nm)", - "PilotAvatar": "Show Pilot Avatar", + "PauseAtTod": "Pause au Top of Descent", + "PauseAtTodDistance": "Distance de pause au T/D (nm)", + "PilotAvatar": "Afficher l'avatar du Commandant", "SeparateTillerFromRudderInputs": "Séparer le tiller du palonnier", - "SyncEfis": "Sync EFIS controls between Captain and FO", + "SyncEfis": "Synchroniser les commandes EFIS entre le pilote et le copilote", "Title": "Réalisme" }, "SimOptions": { "Active": "Actif", "Auto": "Auto", + "Both": "Synchronisé", "Calibrate": "Calibrer", + "Captain": "Commandant", + "CockpitSeatUsedToControl": "Siège utilisé pour contrôler les instruments", "ConesEnabled": "Cônes de sécurité", + "Copilot": "Copilote", "DefaultBarometerUnit": "Unité baromètre par défaut", "DynamicRegistrationDecal": "Calque d'enregistrement dynamique", - "EnableSimBridge": "Activer la connexion au serveur MCDU (désactivation automatique après 5 minutes en cas d'échec de la connexion)", + "EnableSimBridge": "Activer la connexion à Simbridge (désactivation automatique après 5 minutes en cas d'échec de la connexion)", "EnabledMcduServerConnectionAutoDeactivatesAfter5MinutesIfNoSuccessfulConnection": "Activer la connexion au serveur MCDU (désactivation automatique après 5 minutes en cas d'échec de la connexion)", "ExternalMcduServerPort": "Port du serveur MCDU externe", "Hpa": "hPa", @@ -533,7 +537,8 @@ "None": "Aucun", "Off": "DÉSACTIVÉ", "Save": "Enregistrer", - "SimBridgePort": "Port du serveur MCDU externe", + "Side": "Side", + "SimBridgePort": "Port externe du serveur SimBridge", "SyncMsfsFlightPlan": "Synchroniser le plan de vol MSFS", "ThrottleDetents": "Encoches des manettes", "Title": "Options de simulation", @@ -567,7 +572,7 @@ "flyPad": { "AutoBrightness": "Luminosité automatique", "AutomaticallyShowOnscreenKeyboard": "Afficher automatiquement le clavier à l'écran", - "BatteryLifeEnabled": "Battery Life Simulated", + "BatteryLifeEnabled": "Simuler la décharge de batterie", "Blue": "Bleu", "Brightness": "Luminosité", "Dark": "Sombre", @@ -605,8 +610,8 @@ "Sep": "Sept", "Sun": "Dim", "TT": { - "ConnectedToLocalApi": "Connecté à l'API locale", - "DisconnectedFromLocalApi": "Déconnecté de l'API locale", + "ConnectedToLocalApi": "Connecté à SimBridge", + "DisconnectedFromLocalApi": "Déconnecté de SimBridge", "TurnOffOrShutdownEfb": "Éteindre ou arrêter l'EFB" }, "Thu": "Jeu", diff --git a/src/instruments/src/EFB/Localization/he.json b/src/instruments/src/EFB/Localization/he.json index 8057e13ce7a..e8c48383039 100644 --- a/src/instruments/src/EFB/Localization/he.json +++ b/src/instruments/src/EFB/Localization/he.json @@ -151,11 +151,11 @@ "BoardingTime": "זמן עלייה למטוס", "Cargo": "משא", "Current": "נוכחי", - "DeboardConfirmationBody": "Please confirm deboarding all passengers", - "DeboardConfirmationCancel": "Cancel", - "DeboardConfirmationConfirm": "Deboard", - "DeboardConfirmationTitle": "Deboard all Passengers?", - "EstimatedDurationUnit": "minutes", + "DeboardConfirmationBody": "אנא אשר הורדת כל הנוסעים", + "DeboardConfirmationCancel": "בטל", + "DeboardConfirmationConfirm": "הורד נוסעים", + "DeboardConfirmationTitle": "האם להוריד את כל הנוסעים?", + "EstimatedDurationUnit": "דקות", "LoadingTime": "Loading Time", "Passengers": "נוסעים", "Planned": "מתוכנן", @@ -169,7 +169,7 @@ "PerPaxBagWeight": "משקל תיק נוסעים", "PerPaxWeight": "משקל נוסע", "StartBoarding": "התחל עליה למטוס", - "StartDeboarding": "Begin Deboarding" + "StartDeboarding": "התחל הורדת נוסעים" }, "Title": "Payload", "ZFW": "משקל ללא דלק", @@ -366,7 +366,7 @@ "ConfirmationDialogMsg": "אנא אשר טעינת תבנית שמורה", "CurrentProcedureStep": "צעד הפעולה הנוכחי", "PleaseConfirmLoadingOfPreset": "אנא אשר טעינת תבנית שמורה", - "Powered": "Powered", + "Powered": "מחובר למתח", "ReadyPushback": "מוכן לדחיפה", "ReadyTakeoff": "מוכן להמריא", "ReadyTaxi": "מוכן להסעה", @@ -520,8 +520,12 @@ "SimOptions": { "Active": "פעיל", "Auto": "אוטומטי", + "Both": "Synchronized", "Calibrate": "ויסות", + "Captain": "Captain", + "CockpitSeatUsedToControl": "Cockpit Seat Used To Control", "ConesEnabled": "קונוס בטיחות", + "Copilot": "Copilot", "DefaultBarometerUnit": "יחידת ברומטר ברירת מחדל", "DynamicRegistrationDecal": "דִינָמִי מדבקת רישום", "EnableSimBridge": "אפשר חיבור Simbridge (נכבה אוטומטית לאחר חמש דקות אם לא היה חיבור מוצלח)", @@ -533,6 +537,7 @@ "None": "ללא", "Off": "כבוי", "Save": "שמור", + "Side": "Side", "SimBridgePort": "פורט SimBridge חיצוני", "SyncMsfsFlightPlan": "סנכרן את תוכנית הטיסה מ-MSFS", "ThrottleDetents": "מעצורי מצערת", diff --git a/src/instruments/src/EFB/Localization/hi.json b/src/instruments/src/EFB/Localization/hi.json index d4052831323..e225bdf8c83 100644 --- a/src/instruments/src/EFB/Localization/hi.json +++ b/src/instruments/src/EFB/Localization/hi.json @@ -520,8 +520,12 @@ "SimOptions": { "Active": "सक्रिय", "Auto": "ऑटो", + "Both": "Synchronized", "Calibrate": "कैलिब्रेट", + "Captain": "Captain", + "CockpitSeatUsedToControl": "Cockpit Seat Used To Control", "ConesEnabled": "सुरक्षा कोन", + "Copilot": "Copilot", "DefaultBarometerUnit": "डिफ़ॉल्ट बैरोमीटर यूनिट", "DynamicRegistrationDecal": "डायनामिक रजिस्ट्रेशन डिकल", "EnableSimBridge": "SimBridge कनेक्शन सक्षम करें (यदि कोई सफल कनेक्शन नहीं है तो 5 मिनट के बाद ऑटो निष्क्रिय हो जाता है)", @@ -533,6 +537,7 @@ "None": "कोई नहीं", "Off": "बंद", "Save": "सहेजें", + "Side": "Side", "SimBridgePort": "बाहरी सिमब्रिज पोर्ट", "SyncMsfsFlightPlan": "MSFS उड़ान योजना सिंक करें", "ThrottleDetents": "थ्रॉटल डिटेंट्स", diff --git a/src/instruments/src/EFB/Localization/hr.json b/src/instruments/src/EFB/Localization/hr.json index 5e5ddfc8296..b45e52097a7 100644 --- a/src/instruments/src/EFB/Localization/hr.json +++ b/src/instruments/src/EFB/Localization/hr.json @@ -520,8 +520,12 @@ "SimOptions": { "Active": "Aktivno", "Auto": "Auto", + "Both": "Synchronized", "Calibrate": "Calibrate", + "Captain": "Captain", + "CockpitSeatUsedToControl": "Cockpit Seat Used To Control", "ConesEnabled": "Safety Cones", + "Copilot": "Copilot", "DefaultBarometerUnit": "Default Barometer Unit", "DynamicRegistrationDecal": "Dynamic Registration Decal", "EnableSimBridge": "Enable MCDU Server Connection (Auto deactivates after 5 minutes if no successful connection)", @@ -533,6 +537,7 @@ "None": "Niti jedan", "Off": "Isključena", "Save": "Save", + "Side": "Side", "SimBridgePort": "External MCDU Server Port", "SyncMsfsFlightPlan": "Sync MSFS Flight Plan", "ThrottleDetents": "Throttle Detents", diff --git a/src/instruments/src/EFB/Localization/hu.json b/src/instruments/src/EFB/Localization/hu.json index 6de4ec65856..898a9244426 100644 --- a/src/instruments/src/EFB/Localization/hu.json +++ b/src/instruments/src/EFB/Localization/hu.json @@ -520,8 +520,12 @@ "SimOptions": { "Active": "Aktív", "Auto": "Automatikus", + "Both": "Szinkronizálva", "Calibrate": "Kalibrálás", + "Captain": "Kapitány", + "CockpitSeatUsedToControl": "Kabin ülés az irányításhoz", "ConesEnabled": "Biztonsági bóják", + "Copilot": "másodpilóta", "DefaultBarometerUnit": "Alap barométer mértékegység", "DynamicRegistrationDecal": "Dinamikus regisztrációs matrica", "EnableSimBridge": "SimBridge Csatlakozás engedélyezése (Automatikus kikapcsolás 5 perc után, ha nincs sikeres kapcsolat)", @@ -533,6 +537,7 @@ "None": "Nincs", "Off": "Ki", "Save": "Mentés", + "Side": "Side", "SimBridgePort": "Külső SimBridge port", "SyncMsfsFlightPlan": "MSFS Repülési terv szinkronizálása", "ThrottleDetents": "Gázkar állások", diff --git a/src/instruments/src/EFB/Localization/id.json b/src/instruments/src/EFB/Localization/id.json index 46b7f96c19a..2d104395004 100644 --- a/src/instruments/src/EFB/Localization/id.json +++ b/src/instruments/src/EFB/Localization/id.json @@ -520,8 +520,12 @@ "SimOptions": { "Active": "Aktif", "Auto": "Otomatis", + "Both": "Synchronized", "Calibrate": "Kalibrasi", + "Captain": "Captain", + "CockpitSeatUsedToControl": "Cockpit Seat Used To Control", "ConesEnabled": "Safety Cones", + "Copilot": "Copilot", "DefaultBarometerUnit": "Standar Satuan Barometer", "DynamicRegistrationDecal": "Nomor Registrasi Pesawat", "EnableSimBridge": "Aktifkan Koneksi Server MCDU (Otomatis dinonaktifkan setelah 5 menit jika tidak ada koneksi yang berhasil)", @@ -533,6 +537,7 @@ "None": "Tidak ada", "Off": "Mati", "Save": "Simpan", + "Side": "Side", "SimBridgePort": "Port Server MCDU Eksternal", "SyncMsfsFlightPlan": "Sinkronkan dengan Flight Plan MSFS", "ThrottleDetents": "Penahan Throttle", diff --git a/src/instruments/src/EFB/Localization/it.json b/src/instruments/src/EFB/Localization/it.json index 5dd221f0110..9fd9d7e97db 100644 --- a/src/instruments/src/EFB/Localization/it.json +++ b/src/instruments/src/EFB/Localization/it.json @@ -27,8 +27,8 @@ "AreYouSureYouWantToResetAllChecklists": "Sei sicuro di voler ripristinare tutte le checklist?", "AreYouSureYouWantToResetChecklists": "Sei sicuro di voler ripristinare tutte le checklist?", "ChecklistResetWarning": "Avviso Ripristino Checklist", - "MarkChecklistAsComplete": "Segna completamento checklist", - "MarkItemAsComplete": "Segna completamento campo", + "MarkChecklistAsComplete": "Segna checklist come completata", + "MarkItemAsComplete": "Segna campo come completato", "ProceedToNextChecklist": "Procedi alla prossima checklist", "ResetAll": "Ripristina Tutto", "ResetChecklist": "Ripristina Checklist", @@ -65,7 +65,7 @@ "NotAvailableShort": "N/D", "Raw": "Tecnica", "TT": { - "SwitchToIconView": "Passa alla Visualizzazione a Icone", + "SwitchToIconView": "Passa alla Visualizzazione Icone", "SwitchToRawMetarView": "Passa alla Visualizzazione Tecnica del METAR" }, "Temperature": "Temperatura", @@ -77,7 +77,7 @@ "YourFlight": { "Alternate": "Alternato", "AverageWind": "Velocità Vento Media", - "CompanyRoute": "Rotta Compagnia", + "CompanyRoute": "Rotta della Compagnia", "CostIndex": "Cost Index", "CruiseAlt": "Alt. Crociera", "ImportSimBriefData": "Importa Dati SimBrief", @@ -98,7 +98,7 @@ "YouHaveNotYetImportedAnySimBriefData": "Non hai ancora importato alcun dato SimBrief." }, "Overview": { - "ActualGW": "GW effettivo", + "ActualGW": "GW Effettivo", "Engines": "Motori", "MMO": "MMO", "MRW": "MRW", @@ -520,8 +520,12 @@ "SimOptions": { "Active": "Attivo", "Auto": "Auto", + "Both": "Sincronizzato", "Calibrate": "Calibra", + "Captain": "Comandante", + "CockpitSeatUsedToControl": "Posto Cockpit Da Utilizzare", "ConesEnabled": "Coni di Sicurezza", + "Copilot": "Primo Ufficiale", "DefaultBarometerUnit": "Unità Barometro Predefinita", "DynamicRegistrationDecal": "Decalco Registrazione Dinamico", "EnableSimBridge": "Abilita Connessione SimBridge (Disattivazione automatica dopo 5 minuti in caso di connessione non riuscita)", @@ -533,6 +537,7 @@ "None": "No", "Off": "Off", "Save": "Sì", + "Side": "Di Lato", "SimBridgePort": "Porta Esterna Server SimBridge", "SyncMsfsFlightPlan": "Sincronizza Piano di Volo MSFS", "ThrottleDetents": "Posizioni Manetta", diff --git a/src/instruments/src/EFB/Localization/ja.json b/src/instruments/src/EFB/Localization/ja.json index f67b7ea2fe5..8f5c4f119d2 100644 --- a/src/instruments/src/EFB/Localization/ja.json +++ b/src/instruments/src/EFB/Localization/ja.json @@ -520,8 +520,12 @@ "SimOptions": { "Active": "有効", "Auto": "自動", + "Both": "両方", "Calibrate": "調整", + "Captain": "機長", + "CockpitSeatUsedToControl": "操縦に使用するコックピットシート", "ConesEnabled": "セーフティコーン", + "Copilot": "副操縦士", "DefaultBarometerUnit": "デフォルトの気圧計単位", "DynamicRegistrationDecal": "登録番号デカールの表示", "EnableSimBridge": "SimBridge接続の有効化(接続が成功しなかった場合、5分後に自動的に非有効化)", @@ -533,6 +537,7 @@ "None": "なし", "Off": "オフ", "Save": "保存", + "Side": "Side", "SimBridgePort": "外部SimBridgeサーバーポート", "SyncMsfsFlightPlan": "MSFSのフライトプランと同期", "ThrottleDetents": "スロットルディテント", diff --git a/src/instruments/src/EFB/Localization/ko.json b/src/instruments/src/EFB/Localization/ko.json index dfdf54cc53b..224ec5373d7 100644 --- a/src/instruments/src/EFB/Localization/ko.json +++ b/src/instruments/src/EFB/Localization/ko.json @@ -520,8 +520,12 @@ "SimOptions": { "Active": "활성", "Auto": "자동", + "Both": "동기화", "Calibrate": "보정", + "Captain": "기장", + "CockpitSeatUsedToControl": "Cockpit Seat Used To Control", "ConesEnabled": "안전콘", + "Copilot": "부기장", "DefaultBarometerUnit": "기본 기압 단위", "DynamicRegistrationDecal": "다이나믹 등록 데칼", "EnableSimBridge": "SimBridge 연결 활성화 (5분동안 연결 실패 시 자동으로 비활성화)", @@ -533,6 +537,7 @@ "None": "없음", "Off": "끄기", "Save": "저장", + "Side": "위치", "SimBridgePort": "외부 SimBridge 포트", "SyncMsfsFlightPlan": "MSFS 비행계획 동기화", "ThrottleDetents": "쓰로틀 단계", diff --git a/src/instruments/src/EFB/Localization/lt.json b/src/instruments/src/EFB/Localization/lt.json index 7af45106c90..8fb7cd51116 100644 --- a/src/instruments/src/EFB/Localization/lt.json +++ b/src/instruments/src/EFB/Localization/lt.json @@ -151,11 +151,11 @@ "BoardingTime": "Laipinimo trukmė", "Cargo": "Krovinys", "Current": "Esamas", - "DeboardConfirmationBody": "Please confirm deboarding all passengers", - "DeboardConfirmationCancel": "Cancel", - "DeboardConfirmationConfirm": "Deboard", - "DeboardConfirmationTitle": "Deboard all Passengers?", - "EstimatedDurationUnit": "minutes", + "DeboardConfirmationBody": "Prašome patvirtinti visų keleivių išlaipinimą", + "DeboardConfirmationCancel": "Atšaukti", + "DeboardConfirmationConfirm": "Išlaipinimas", + "DeboardConfirmationTitle": "Išlaipinti visus keleivius?", + "EstimatedDurationUnit": "minutės", "LoadingTime": "Loading Time", "Passengers": "Keleiviai", "Planned": "Suplanuotas", @@ -169,7 +169,7 @@ "PerPaxBagWeight": "Keleivio bagažo svoris", "PerPaxWeight": "Keleivio svoris", "StartBoarding": "Pradėti laipinimą", - "StartDeboarding": "Begin Deboarding" + "StartDeboarding": "Pradėti išlaipinimą" }, "Title": "Krovinys", "ZFW": "ZFW", @@ -366,7 +366,7 @@ "ConfirmationDialogMsg": "Patvirtinkite išankstinio nustatymo įkėlimą.", "CurrentProcedureStep": "Dabartinis procedūros žingsnis", "PleaseConfirmLoadingOfPreset": "Patvirtinkite išankstinio nustatymo įkėlimą.", - "Powered": "Powered", + "Powered": "Maitinamas", "ReadyPushback": "Paruoštas išstumimui", "ReadyTakeoff": "Paruoštas pakilimui", "ReadyTaxi": "Paruoštas riedėjimui", @@ -438,7 +438,7 @@ "SliderSpeed": "Pasirinkite norimą greitį", "SystemEnabledOff": "Paspauskite norint įjungti išstumimo sistemą.", "SystemEnabledOn": "Paspauskite norint pilnai išjungti išstumimo sistemą.", - "UseControllerInput": "Turn controller input from rudder and elevator on/off", + "UseControllerInput": "Pakeisti valdiklio valdymą iš krypties į aukščio vairo įjungimą/išjungimą", "ZoomIn": "Priartinti", "ZoomOut": "Nutolinti" }, @@ -520,8 +520,12 @@ "SimOptions": { "Active": "Aktyvus", "Auto": "Automatinis", + "Both": "Sinchronizuotas", "Calibrate": "Kalibruoti", + "Captain": "Kapitonas", + "CockpitSeatUsedToControl": "Kabinos sėdynė, naudojama valdyti", "ConesEnabled": "Saugumo kūgiai", + "Copilot": "Antrasis pilotas", "DefaultBarometerUnit": "Numatyti barometro vienetai", "DynamicRegistrationDecal": "Dinaminis registracijos lipdukas", "EnableSimBridge": "Įjungti SimBridge prisijungimą (automatiškai išjungiama po 5 minučių, jei nepavyksta prisijungti)", @@ -533,6 +537,7 @@ "None": "Nėra", "Off": "Išjungta", "Save": "Išsaugoti", + "Side": "Side", "SimBridgePort": "Išorinis SimBridge serverio port", "SyncMsfsFlightPlan": "Sinchronizuoti MSFS Skrydžio Planą", "ThrottleDetents": "Droselio detentai", diff --git a/src/instruments/src/EFB/Localization/ms.json b/src/instruments/src/EFB/Localization/ms.json index df6341fbe9e..9833ea993fb 100644 --- a/src/instruments/src/EFB/Localization/ms.json +++ b/src/instruments/src/EFB/Localization/ms.json @@ -520,8 +520,12 @@ "SimOptions": { "Active": "Active", "Auto": "Auto", + "Both": "Synchronized", "Calibrate": "Calibrate", + "Captain": "Captain", + "CockpitSeatUsedToControl": "Cockpit Seat Used To Control", "ConesEnabled": "Safety Cones", + "Copilot": "Copilot", "DefaultBarometerUnit": "Default Barometer Unit", "DynamicRegistrationDecal": "Dynamic Registration Decal", "EnableSimBridge": "Enable MCDU Server Connection (Auto deactivates after 5 minutes if no successful connection)", @@ -533,6 +537,7 @@ "None": "None", "Off": "Off", "Save": "Save", + "Side": "Side", "SimBridgePort": "External MCDU Server Port", "SyncMsfsFlightPlan": "Sync MSFS Flight Plan", "ThrottleDetents": "Throttle Detents", diff --git a/src/instruments/src/EFB/Localization/nb.json b/src/instruments/src/EFB/Localization/nb.json index b0d8ac61134..68dcc5ee1cf 100644 --- a/src/instruments/src/EFB/Localization/nb.json +++ b/src/instruments/src/EFB/Localization/nb.json @@ -520,8 +520,12 @@ "SimOptions": { "Active": "Aktiv", "Auto": "Automatisk", + "Both": "Synchronized", "Calibrate": "Kalibrer", + "Captain": "Captain", + "CockpitSeatUsedToControl": "Cockpit Seat Used To Control", "ConesEnabled": "Sikkerhet kjegler", + "Copilot": "Copilot", "DefaultBarometerUnit": "Standard Barometerenhet", "DynamicRegistrationDecal": "Dynamisk registreringsdekal", "EnableSimBridge": "Aktiver SimBridge servertilkobling (Deaktiveres automatisk etter 5 minutter hvis tilkoblingen ikke er vellykket)", @@ -533,6 +537,7 @@ "None": "Ingen", "Off": "Av", "Save": "Lagre", + "Side": "Side", "SimBridgePort": "Ekstern SimBridge-port", "SyncMsfsFlightPlan": "Synkroniser MSFS-flyplan", "ThrottleDetents": "Gassperrer", diff --git a/src/instruments/src/EFB/Localization/nl.json b/src/instruments/src/EFB/Localization/nl.json index d11d28a7415..486a6649813 100644 --- a/src/instruments/src/EFB/Localization/nl.json +++ b/src/instruments/src/EFB/Localization/nl.json @@ -520,8 +520,12 @@ "SimOptions": { "Active": "Actief", "Auto": "Auto", + "Both": "Synchronized", "Calibrate": "Kalibreren", + "Captain": "Captain", + "CockpitSeatUsedToControl": "Cockpit Seat Used To Control", "ConesEnabled": "Veiligheidskegels", + "Copilot": "Copilot", "DefaultBarometerUnit": "Standaard barometer-eenheid", "DynamicRegistrationDecal": "Dynamische Registratie Sticker", "EnableSimBridge": "MCDU-serververbinding inschakelen (Deactiveert automatisch na 5 minuten als er geen succesvolle verbinding is)", @@ -533,6 +537,7 @@ "None": "Geen", "Off": "Uit", "Save": "Opslaan", + "Side": "Side", "SimBridgePort": "Externe MCDU Serverpoort", "SyncMsfsFlightPlan": "MSFS-vluchtplan synchroniseren", "ThrottleDetents": "Throttle Detents", diff --git a/src/instruments/src/EFB/Localization/pl.json b/src/instruments/src/EFB/Localization/pl.json index cfaad2c71fc..55e90af6ee9 100644 --- a/src/instruments/src/EFB/Localization/pl.json +++ b/src/instruments/src/EFB/Localization/pl.json @@ -520,8 +520,12 @@ "SimOptions": { "Active": "Aktywny", "Auto": "Automatycznie", + "Both": "Synchronized", "Calibrate": "Kalibruj", + "Captain": "Captain", + "CockpitSeatUsedToControl": "Cockpit Seat Used To Control", "ConesEnabled": "Pachołki Bezpieczeństwa", + "Copilot": "Copilot", "DefaultBarometerUnit": "Domyślna Jednostka Barometru", "DynamicRegistrationDecal": "Dynamiczny Numer Rejestracyjny", "EnableSimBridge": "Włącz połączenie z serwerem MCDU (Automatycznie dezaktywowane po 5 minutach bez połączenia)", @@ -533,6 +537,7 @@ "None": "Nie", "Off": "Wył.", "Save": "Tak", + "Side": "Side", "SimBridgePort": "Port Serwera MCDU", "SyncMsfsFlightPlan": "Synchronizacja Planu Lotu z MSFS", "ThrottleDetents": "Kalibracja Przepustnic", diff --git a/src/instruments/src/EFB/Localization/pt-BR.json b/src/instruments/src/EFB/Localization/pt-BR.json index 91322e35f98..5431c2a1132 100644 --- a/src/instruments/src/EFB/Localization/pt-BR.json +++ b/src/instruments/src/EFB/Localization/pt-BR.json @@ -520,8 +520,12 @@ "SimOptions": { "Active": "Ativo", "Auto": "Automático", + "Both": "Synchronized", "Calibrate": "Calibrar", + "Captain": "Captain", + "CockpitSeatUsedToControl": "Cockpit Seat Used To Control", "ConesEnabled": "Safety Cones", + "Copilot": "Copilot", "DefaultBarometerUnit": "Unidade padrão do barômetro", "DynamicRegistrationDecal": "Registro dinâmico do decalque", "EnableSimBridge": "Ativar conexão com o servidor MCDU (desativa automaticamente após 5 minutos se não houver conexão bem-sucedida)", @@ -533,6 +537,7 @@ "None": "Nenhum", "Off": "Desativado", "Save": "Salvar", + "Side": "Side", "SimBridgePort": "Porta externa de servidor MCDU", "SyncMsfsFlightPlan": "Sincronizar plano de voo do MSFS", "ThrottleDetents": "Manetes de potência", diff --git a/src/instruments/src/EFB/Localization/pt-PT.json b/src/instruments/src/EFB/Localization/pt-PT.json index ed59ebb77f5..61e45d0df56 100644 --- a/src/instruments/src/EFB/Localization/pt-PT.json +++ b/src/instruments/src/EFB/Localization/pt-PT.json @@ -520,8 +520,12 @@ "SimOptions": { "Active": "Ativo", "Auto": "Automático", + "Both": "Synchronized", "Calibrate": "Calibrar", + "Captain": "Captain", + "CockpitSeatUsedToControl": "Cockpit Seat Used To Control", "ConesEnabled": "Cones de segurança", + "Copilot": "Copilot", "DefaultBarometerUnit": "Unidade de Barómetro Padrão", "DynamicRegistrationDecal": "Decalque de Registro Dinâmico", "EnableSimBridge": "Ativar conexão SimBridge (desativa automaticamente após 5 minutos se não houver conexão bem-sucedida)", @@ -533,6 +537,7 @@ "None": "Nenhum", "Off": "Desativado", "Save": "Salvar", + "Side": "Side", "SimBridgePort": "Porta SimBridge externa", "SyncMsfsFlightPlan": "Sincronizar plano de voo do MSFS", "ThrottleDetents": "Retentores da Manete", diff --git a/src/instruments/src/EFB/Localization/ro.json b/src/instruments/src/EFB/Localization/ro.json index 1d06010b3cc..6dc79d1d1f7 100644 --- a/src/instruments/src/EFB/Localization/ro.json +++ b/src/instruments/src/EFB/Localization/ro.json @@ -520,8 +520,12 @@ "SimOptions": { "Active": "Activ", "Auto": "Automat", + "Both": "Synchronized", "Calibrate": "Calibrare", + "Captain": "Captain", + "CockpitSeatUsedToControl": "Cockpit Seat Used To Control", "ConesEnabled": "Safety Cones", + "Copilot": "Copilot", "DefaultBarometerUnit": "Unitate Barometrica Implicită", "DynamicRegistrationDecal": "Număr de înregistrare dinamic", "EnableSimBridge": "Activează conexiune server MCDU (Auto dezactivează după 5 minute dacă nu s-a stabilit conexiunea)", @@ -533,6 +537,7 @@ "None": "Niciunul", "Off": "Dezactivată", "Save": "Salvează", + "Side": "Side", "SimBridgePort": "Poartă exterioară server MCDU", "SyncMsfsFlightPlan": "Sincronizare plan de zbor MSFS", "ThrottleDetents": "Senzori accelerație", diff --git a/src/instruments/src/EFB/Localization/ru.json b/src/instruments/src/EFB/Localization/ru.json index b880e948efb..81dcb7f9ef1 100644 --- a/src/instruments/src/EFB/Localization/ru.json +++ b/src/instruments/src/EFB/Localization/ru.json @@ -520,8 +520,12 @@ "SimOptions": { "Active": "Активная", "Auto": "Авто", + "Both": "Synchronized", "Calibrate": "Калибровка", + "Captain": "Captain", + "CockpitSeatUsedToControl": "Cockpit Seat Used To Control", "ConesEnabled": "Предохранительные конусы", + "Copilot": "Copilot", "DefaultBarometerUnit": "Единица измерения барометра по умолчанию", "DynamicRegistrationDecal": "Наклейка с динамической регистрацией", "EnableSimBridge": "Подключение к серверу MCDU (автоматически деактивируется через 5 минут, если соединение не было успешным)", @@ -533,6 +537,7 @@ "None": "Нет", "Off": "Откл.", "Save": "Сохранить", + "Side": "Side", "SimBridgePort": "Порт внешнего сервера MCDU", "SyncMsfsFlightPlan": "Синхронизировать план полета MSFS", "ThrottleDetents": "Защелки рычагов", diff --git a/src/instruments/src/EFB/Localization/sk.json b/src/instruments/src/EFB/Localization/sk.json index e1ad47d2c72..c2b63189de5 100644 --- a/src/instruments/src/EFB/Localization/sk.json +++ b/src/instruments/src/EFB/Localization/sk.json @@ -520,8 +520,12 @@ "SimOptions": { "Active": "Aktívne", "Auto": "Automaticky", + "Both": "Synchronized", "Calibrate": "Skalibrovať", + "Captain": "Captain", + "CockpitSeatUsedToControl": "Cockpit Seat Used To Control", "ConesEnabled": "Safety Cones", + "Copilot": "Copilot", "DefaultBarometerUnit": "Štandardná jednotka barometra", "DynamicRegistrationDecal": "Dynamický registračný kód", "EnableSimBridge": "Povoliť pripojenie servera MCDU (automaticky sa deaktivuje po 5 minútach, ak nie je úspešné pripojenie)", @@ -533,6 +537,7 @@ "None": "Žiadne", "Off": "Vypnuté", "Save": "Uložiť", + "Side": "Side", "SimBridgePort": "Externý port servera MCDU", "SyncMsfsFlightPlan": "Synchronizácia letového plánu MSFS", "ThrottleDetents": "Detenty škrtiacej klapky", diff --git a/src/instruments/src/EFB/Localization/sl.json b/src/instruments/src/EFB/Localization/sl.json index 850cb8fd60a..2518b526862 100644 --- a/src/instruments/src/EFB/Localization/sl.json +++ b/src/instruments/src/EFB/Localization/sl.json @@ -520,8 +520,12 @@ "SimOptions": { "Active": "Aktivno", "Auto": "Samodejno", + "Both": "Synchronized", "Calibrate": "Kalibracija", + "Captain": "Captain", + "CockpitSeatUsedToControl": "Cockpit Seat Used To Control", "ConesEnabled": "Varnostni stožci", + "Copilot": "Copilot", "DefaultBarometerUnit": "Privzeta barometrična enota", "DynamicRegistrationDecal": "Dinamična registrska nalepka", "EnableSimBridge": "Omogoči povezavo s strežnikom MCDU (samodejna deaktivacija po 5 minutah, če ni uspešne povezave)", @@ -533,6 +537,7 @@ "None": "Brez", "Off": "Izklopljeno", "Save": "Shrani", + "Side": "Side", "SimBridgePort": "Zunanji SimBridge Port", "SyncMsfsFlightPlan": "Sinhroniziraj z MSFS načrtom leta", "ThrottleDetents": "Odkloni plinske ročke", diff --git a/src/instruments/src/EFB/Localization/sv.json b/src/instruments/src/EFB/Localization/sv.json index d2321861215..9911405d399 100644 --- a/src/instruments/src/EFB/Localization/sv.json +++ b/src/instruments/src/EFB/Localization/sv.json @@ -520,8 +520,12 @@ "SimOptions": { "Active": "Aktiv", "Auto": "Auto", + "Both": "Synchronized", "Calibrate": "Kalibrera", + "Captain": "Captain", + "CockpitSeatUsedToControl": "Cockpit Seat Used To Control", "ConesEnabled": "Säkerhetskoner", + "Copilot": "Copilot", "DefaultBarometerUnit": "Standardbarometerenhet", "DynamicRegistrationDecal": "Dynamisk registreringsdekal", "EnableSimBridge": "Aktivera SimBridge-serveranslutning (inaktiveras automatiskt efter 5 minuter om anslutningen inte lyckas).", @@ -533,6 +537,7 @@ "None": "Ingen", "Off": "Av", "Save": "Spara", + "Side": "Side", "SimBridgePort": "Extern SimBridge-port", "SyncMsfsFlightPlan": "Synkronisera MSFS-färdplan", "ThrottleDetents": "Kalibrering av tryckspaken", diff --git a/src/instruments/src/EFB/Localization/th.json b/src/instruments/src/EFB/Localization/th.json index a66e3cb42f5..287dff13369 100644 --- a/src/instruments/src/EFB/Localization/th.json +++ b/src/instruments/src/EFB/Localization/th.json @@ -520,8 +520,12 @@ "SimOptions": { "Active": "ใช้งานอยู่", "Auto": "อัตโนมัติ", + "Both": "Synchronized", "Calibrate": "Calibrate", + "Captain": "Captain", + "CockpitSeatUsedToControl": "Cockpit Seat Used To Control", "ConesEnabled": "กรวยนิรภัย", + "Copilot": "Copilot", "DefaultBarometerUnit": "หน่วย Barometer เริ่มต้น", "DynamicRegistrationDecal": "ทะเบียนเครื่องบินแบบไดนามิก", "EnableSimBridge": "เปิดใช้งานการเชื่อมต่อ SimBridge (ปิดการทำงานหลังจาก 5 นาทีอัตโนมัติ หากไม่มีการเชื่อมต่อที่สำเร็จ)", @@ -533,6 +537,7 @@ "None": "ไม่มี", "Off": "ปิด", "Save": "บันทึก", + "Side": "Side", "SimBridgePort": "พอร์ต SimBridge ภายนอก", "SyncMsfsFlightPlan": "ซิงค์แผนการบิน MSFS", "ThrottleDetents": "Throttle Detents", diff --git a/src/instruments/src/EFB/Localization/tr.json b/src/instruments/src/EFB/Localization/tr.json index 3ee5b36234b..53b01978f07 100644 --- a/src/instruments/src/EFB/Localization/tr.json +++ b/src/instruments/src/EFB/Localization/tr.json @@ -520,8 +520,12 @@ "SimOptions": { "Active": "Etkin", "Auto": "Otomatik", + "Both": "Synchronized", "Calibrate": "Kalibrasyon", + "Captain": "Captain", + "CockpitSeatUsedToControl": "Cockpit Seat Used To Control", "ConesEnabled": "Emniyet Konileri", + "Copilot": "Copilot", "DefaultBarometerUnit": "Varsayılan Barometre Birimi", "DynamicRegistrationDecal": "Dinamik Kayıt Çıkartması", "EnableSimBridge": "SimBridge Bağlantısını Etkinleştir (Başarılı bir bağlantı yoksa 5 dakika sonra otomatik olarak devre dışı bırakılır)", @@ -533,6 +537,7 @@ "None": "Hiçbiri", "Off": "Kapalı", "Save": "Kaydet", + "Side": "Side", "SimBridgePort": "Harici SimBridge Bağlantı Noktası", "SyncMsfsFlightPlan": "MSFS Uçuş Planını Eşitle", "ThrottleDetents": "Gaz Mandalları", diff --git a/src/instruments/src/EFB/Localization/vi.json b/src/instruments/src/EFB/Localization/vi.json index 220cb2d9164..ec29e69dd49 100644 --- a/src/instruments/src/EFB/Localization/vi.json +++ b/src/instruments/src/EFB/Localization/vi.json @@ -520,8 +520,12 @@ "SimOptions": { "Active": "Hoạt động", "Auto": "Tự động", + "Both": "Synchronized", "Calibrate": "Hiệu chỉnh", + "Captain": "Captain", + "CockpitSeatUsedToControl": "Cockpit Seat Used To Control", "ConesEnabled": "Chóp nón An toàn", + "Copilot": "Copilot", "DefaultBarometerUnit": "Đơn vị áp kế mặc định", "DynamicRegistrationDecal": "Đề-can đăng ký động", "EnableSimBridge": "Bật kết nối Simbridge (Tự động ngừng kích hoạt sau 5 phút nếu không có kết nối thành công)", @@ -533,6 +537,7 @@ "None": "Không", "Off": "Tắt", "Save": "Lưu", + "Side": "Side", "SimBridgePort": "Cổng SimBridge bên ngoài", "SyncMsfsFlightPlan": "Đồng bộ hóa Kế hoạch chuyến bay của MSFS", "ThrottleDetents": "Chốt cần ga", diff --git a/src/instruments/src/EFB/Localization/zh-Hans-CN.json b/src/instruments/src/EFB/Localization/zh-Hans-CN.json index e20db91f4cf..56dc9a95deb 100644 --- a/src/instruments/src/EFB/Localization/zh-Hans-CN.json +++ b/src/instruments/src/EFB/Localization/zh-Hans-CN.json @@ -520,8 +520,12 @@ "SimOptions": { "Active": "启用", "Auto": "自动", + "Both": "Synchronized", "Calibrate": "校准", + "Captain": "Captain", + "CockpitSeatUsedToControl": "Cockpit Seat Used To Control", "ConesEnabled": "安全锥", + "Copilot": "Copilot", "DefaultBarometerUnit": "默认气压单位", "DynamicRegistrationDecal": "动态注册号喷涂", "EnableSimBridge": "启用 MCDU 服务器 (5 分钟之内无连接将自动停用)", @@ -533,6 +537,7 @@ "None": "无", "Off": "关", "Save": "保存", + "Side": "Side", "SimBridgePort": "MCDU 服务器端口", "SyncMsfsFlightPlan": "同步 MSFS 内飞行计划", "ThrottleDetents": "油门卡位", diff --git a/src/instruments/src/EFB/Localization/zh-Hant-HK.json b/src/instruments/src/EFB/Localization/zh-Hant-HK.json index 8afc187168e..3e2735b69fc 100644 --- a/src/instruments/src/EFB/Localization/zh-Hant-HK.json +++ b/src/instruments/src/EFB/Localization/zh-Hant-HK.json @@ -520,8 +520,12 @@ "SimOptions": { "Active": "使用中", "Auto": "自動", + "Both": "Synchronized", "Calibrate": "校正", + "Captain": "Captain", + "CockpitSeatUsedToControl": "Cockpit Seat Used To Control", "ConesEnabled": "Safety Cones", + "Copilot": "Copilot", "DefaultBarometerUnit": "氣壓單位", "DynamicRegistrationDecal": "註冊印花隨機", "EnableSimBridge": "啟用 MCDU 伺服器 (5 分鐘之內無連接下會自動停用)", @@ -533,6 +537,7 @@ "None": "非同步", "Off": "關", "Save": "儲存", + "Side": "Side", "SimBridgePort": "MCDU 伺服器端口 (Port)", "SyncMsfsFlightPlan": "同步處理 MSFS 航線", "ThrottleDetents": "油門停點", diff --git a/src/instruments/src/EFB/Localization/zh-Hant-TW.json b/src/instruments/src/EFB/Localization/zh-Hant-TW.json index 6e5ccea3a83..4451bd9a856 100644 --- a/src/instruments/src/EFB/Localization/zh-Hant-TW.json +++ b/src/instruments/src/EFB/Localization/zh-Hant-TW.json @@ -520,8 +520,12 @@ "SimOptions": { "Active": "使用中", "Auto": "自動", + "Both": "Synchronized", "Calibrate": "校準", + "Captain": "Captain", + "CockpitSeatUsedToControl": "Cockpit Seat Used To Control", "ConesEnabled": "Safety Cones", + "Copilot": "Copilot", "DefaultBarometerUnit": "默認氣壓單位", "DynamicRegistrationDecal": "動態註冊號噴塗", "EnableSimBridge": "啟用 MCDU 伺服器 (5 分鐘之內無連接將自動停用)", @@ -533,6 +537,7 @@ "None": "無", "Off": "關", "Save": "儲存", + "Side": "Side", "SimBridgePort": "外部 MCDU 服務器端口", "SyncMsfsFlightPlan": "同步 MSFS 飛行計劃", "ThrottleDetents": "油門卡位", From 18f7db2c972568e7b27746ef6ed34667dfbb6022 Mon Sep 17 00:00:00 2001 From: crocket63 <38904654+crocket63@users.noreply.github.com> Date: Tue, 27 Dec 2022 09:13:46 +0100 Subject: [PATCH 02/39] feat(hyd): Simple hydraulic temperature simulation (#7573) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: lukecologne Co-authored-by: Benedict Etzel Co-authored-by: Pascal Störzbach --- .github/CHANGELOG.md | 1 + docs/a320-simvars.md | 15 + src/failures/src/a320.ts | 6 + src/instruments/src/Common/EWDMessages.tsx | 9 + .../EFB/failures-orchestrator-provider.tsx | 4 + .../src/EWD/elements/PseudoFWC.tsx | 58 +++ src/instruments/src/SD/Pages/Hyd/Hyd.tsx | 26 ++ .../src/main.rs | 12 +- src/systems/a320_systems/src/hydraulic/mod.rs | 187 +++++++- src/systems/a320_systems_wasm/src/lib.rs | 19 +- src/systems/a380_systems/src/hydraulic/mod.rs | 33 +- src/systems/systems/src/failures/mod.rs | 7 +- .../src/hydraulic/electrical_pump_physics.rs | 117 ++++- src/systems/systems/src/hydraulic/mod.rs | 438 ++++++++++++++++-- src/systems/systems/src/hydraulic/pumps.rs | 15 +- src/systems/systems/src/shared/mod.rs | 54 +++ 16 files changed, 920 insertions(+), 81 deletions(-) diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index 7e5f267f498..741d4e69d2b 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -13,6 +13,7 @@ 1. [ATSU] Fix LSK6L not returning to ATSU DATALINK page in ATC MENU - @BravoMike99 (Bruno_pt99#5802) 1. [HYD] Trimmable physical assemblies - @Crocket63 (crocket) 1. [HYD] Simulation of the rudder mechanical assembly and yaw dampers - @Crocket63 (crocket) +1. [HYD] Simple temperature simulation - @Crocket63 (crocket) 1. [FLIGHTMODEL] Reduced flap induced drag - @donstim (donbikes#4084) 1. [EFB] Fix and improve pushback system and add API documentation - @frankkopp (Frank Kopp) diff --git a/docs/a320-simvars.md b/docs/a320-simvars.md index 3989c608e45..7350203f716 100644 --- a/docs/a320-simvars.md +++ b/docs/a320-simvars.md @@ -809,6 +809,14 @@ - BLUE - YELLOW +- A32NX_HYD_{loop_name}_RESERVOIR_OVHT + - Boolean + - Reservoir of {loop_name} hydraulic circuit is overheating + - {loop_name} + - GREEN + - BLUE + - YELLOW + - A32NX_HYD_{loop_name}_EDPUMP_ACTIVE - Bool - Engine driven pump of {loop_name} hydraulic circuit is active @@ -888,6 +896,13 @@ - BLUE - YELLOW +- A32NX_HYD_{loop_name}_EPUMP_OVHT + - Bool + - Electric pump of {loop_name} hydraulic circuit is overheating + - {loop_name} + - BLUE + - YELLOW + - A32NX_HYD_{loop_name}_PUMP_1_FIRE_VALVE_OPENED - Bool - Engine driven pump of {loop_name} hydraulic circuit can receive hydraulic fluid diff --git a/src/failures/src/a320.ts b/src/failures/src/a320.ts index 96b50241570..90fa2fe1667 100644 --- a/src/failures/src/a320.ts +++ b/src/failures/src/a320.ts @@ -13,6 +13,7 @@ export const A320Failure = Object.freeze({ Sec3Failure: 27004, Fcdc1Failure: 27005, Fcdc2Failure: 27006, + GreenReservoirLeak: 29000, BlueReservoirLeak: 29001, YellowReservoirLeak: 29002, @@ -22,6 +23,11 @@ export const A320Failure = Object.freeze({ GreenReservoirReturnLeak: 29006, BlueReservoirReturnLeak: 29007, YellowReservoirReturnLeak: 29008, + GreenEdpOverheat: 29009, + BlueEpumpOverheat: 29010, + YellowEdpOverheat: 29011, + YellowEpumpOverheat: 29012, + LeftPfdDisplay: 31000, RightPfdDisplay: 31001, diff --git a/src/instruments/src/Common/EWDMessages.tsx b/src/instruments/src/Common/EWDMessages.tsx index fe534dab8e7..0fe9bad737b 100644 --- a/src/instruments/src/Common/EWDMessages.tsx +++ b/src/instruments/src/Common/EWDMessages.tsx @@ -232,6 +232,15 @@ const EWDMessages = { '270055701': '\x1b<4m\x1b4mF/CTL\x1bm FCDC 2 FAULT', '290031001': '\x1b<4m*HYD', '290031201': '\x1b<4m*HYD', + '290012601': '\x1b<4m\x1b4mHYD\x1bm B RSVR OVHT', + '290012602': '\x1b<5m -BLUE ELEC PUMP.....OFF', + '290012701': '\x1b<4m\x1b4mHYD\x1bm Y RSVR OVHT', + '290012702': '\x1b<5m -PTU................OFF', + '290012703': '\x1b<5m -YELLOW ENG 2 PUMP..OFF', + '290012704': '\x1b<5m -YELLOW ELEC PUMP...OFF', + '290012801': '\x1b<4m\x1b4mHYD\x1bm G RSVR OVHT', + '290012802': '\x1b<5m -PTU................OFF', + '290012803': '\x1b<5m -GREEN ENG 1 PUMP...OFF', '308118601': '\x1b<4m\x1b4mSEVERE ICE\x1bm DETECTED', '308118602': '\x1b5m -WING ANTI ICE.......ON', '308118603': '\x1b5m -ENG MOD SEL........IGN', diff --git a/src/instruments/src/EFB/failures-orchestrator-provider.tsx b/src/instruments/src/EFB/failures-orchestrator-provider.tsx index 46bdf27514b..f3c011e649c 100644 --- a/src/instruments/src/EFB/failures-orchestrator-provider.tsx +++ b/src/instruments/src/EFB/failures-orchestrator-provider.tsx @@ -35,6 +35,10 @@ const createOrchestrator = () => new FailuresOrchestrator('A32NX', [ [29, A320Failure.GreenReservoirReturnLeak, 'Green reservoir return leak'], [29, A320Failure.BlueReservoirReturnLeak, 'Blue reservoir return leak'], [29, A320Failure.YellowReservoirReturnLeak, 'Yellow reservoir return leak'], + [29, A320Failure.GreenEdpOverheat, 'Green engine pump overheat'], + [29, A320Failure.BlueEpumpOverheat, 'Blue electric pump overheat'], + [29, A320Failure.YellowEdpOverheat, 'Yellow engine pump overheat'], + [29, A320Failure.YellowEpumpOverheat, 'Yellow electric pump overheat'], [31, A320Failure.LeftPfdDisplay, 'Captain PFD display'], [31, A320Failure.RightPfdDisplay, 'F/O PFD display'], diff --git a/src/instruments/src/EWD/elements/PseudoFWC.tsx b/src/instruments/src/EWD/elements/PseudoFWC.tsx index 5ae38f09437..c70d63a7eed 100644 --- a/src/instruments/src/EWD/elements/PseudoFWC.tsx +++ b/src/instruments/src/EWD/elements/PseudoFWC.tsx @@ -193,11 +193,17 @@ const PseudoFWC: React.FC = () => { const [blueLP] = useSimVar('L:A32NX_HYD_BLUE_EDPUMP_LOW_PRESS', 'bool', 500); const [blueSysPressurised] = useSimVar('L:A32NX_HYD_BLUE_SYSTEM_1_SECTION_PRESSURE_SWITCH', 'bool', 500); const [blueRvrLow] = useSimVar('L:A32NX_HYD_BLUE_RESERVOIR_LEVEL_IS_LOW', 'bool', 500); + + const [yellowRvrOvht] = useSimVar('L:A32NX_HYD_YELLOW_RESERVOIR_OVHT', 'bool', 500); + const [greenRvrOvht] = useSimVar('L:A32NX_HYD_GREEN_RESERVOIR_OVHT', 'bool', 500); + const [blueRvrOvht] = useSimVar('L:A32NX_HYD_BLUE_RESERVOIR_OVHT', 'bool', 500); const [blueElecPumpPBAuto] = useSimVar('L:A32NX_OVHD_HYD_EPUMPB_PB_IS_AUTO', 'bool', 500); const [yellowLP] = useSimVar('L:A32NX_HYD_YELLOW_EDPUMP_LOW_PRESS', 'bool', 500); const [yellowSysPressurised] = useSimVar('L:A32NX_HYD_YELLOW_SYSTEM_1_SECTION_PRESSURE_SWITCH', 'bool', 500); const [eng1pumpPBisAuto] = useSimVar('L:A32NX_OVHD_HYD_ENG_1_PUMP_PB_IS_AUTO', 'bool', 500); const [eng2pumpPBisAuto] = useSimVar('L:A32NX_OVHD_HYD_ENG_2_PUMP_PB_IS_AUTO', 'bool', 500); + const [yepumpPBisAuto] = useSimVar('L:A32NX_OVHD_HYD_EPUMPY_PB_IS_AUTO', 'bool', 500); + const [ptuIsAuto] = useSimVar('L:A32NX_OVHD_HYD_PTU_PB_IS_AUTO', 'bool', 500); const [hydPTU] = useSimVar('L:A32NX_HYD_PTU_ON_ECAM_MEMO', 'bool', 500); const [ratDeployed] = useSimVar('L:A32NX_HYD_RAT_STOW_POSITION', 'percent over 100', 500); @@ -1181,6 +1187,51 @@ const PseudoFWC: React.FC = () => { sysPage: -1, side: 'LEFT', }, + 2900126: // *HYD - Blue reservoir overheat + { + flightPhaseInhib: [3, 4, 5, 7, 8], + simVarIsActive: blueRvrOvht, + whichCodeToReturn: [ + 0, + blueElecPumpPBAuto ? 1 : null, + ], + codesToReturn: ['290012601', '290012602'], + memoInhibit: false, + failure: 2, + sysPage: 4, + side: 'LEFT', + }, + 2900127: // *HYD - Yellow reservoir overheat + { + flightPhaseInhib: [3, 4, 5, 7, 8], + simVarIsActive: yellowRvrOvht, + whichCodeToReturn: [ + 0, + ptuIsAuto ? 1 : null, + eng2pumpPBisAuto ? 2 : null, + !yepumpPBisAuto ? 3 : null, + ], + codesToReturn: ['290012701', '290012702', '290012703', '290012704'], + memoInhibit: false, + failure: 2, + sysPage: 4, + side: 'LEFT', + }, + 2900128: // *HYD - Green reservoir overheat + { + flightPhaseInhib: [3, 4, 5, 7, 8], + simVarIsActive: greenRvrOvht, + whichCodeToReturn: [ + 0, + ptuIsAuto ? 1 : null, + eng1pumpPBisAuto ? 2 : null, + ], + codesToReturn: ['290012801', '290012802', '290012803'], + memoInhibit: false, + failure: 2, + sysPage: 4, + side: 'LEFT', + }, 2900310: // *HYD - Blue { flightPhaseInhib: [4, 5], @@ -1897,6 +1948,7 @@ const PseudoFWC: React.FC = () => { autoThrustStatus, blueElecPumpPBAuto, blueRvrLow, + blueRvrOvht, brakeFan, cabAltSetResetState1, cabAltSetResetState2, @@ -1933,10 +1985,12 @@ const PseudoFWC: React.FC = () => { eng1AntiIce, eng1FireTest, engine1State, + eng1pumpPBisAuto, eng2Agent1PB, eng2Agent2PB, eng2AntiIce, eng2FireTest, + eng2pumpPBisAuto, engine2State, engDualFault, engSelectorPosition, @@ -1958,6 +2012,7 @@ const PseudoFWC: React.FC = () => { gpwsFlaps3, gpwsTerrOff, greenHydEng1PBAuto, + greenRvrOvht, height1Failed, height2Failed, hydPTU, @@ -1984,6 +2039,7 @@ const PseudoFWC: React.FC = () => { packOffNotFailure2, parkBrake, predWSOn, + ptuIsAuto, ratDeployed, recallReset, rightOuterInnerValve, @@ -2008,6 +2064,8 @@ const PseudoFWC: React.FC = () => { usrStartRefueling, wingAntiIce, voiceVHF3, + yellowRvrOvht, + yepumpPBisAuto, ]); useEffect(() => { diff --git a/src/instruments/src/SD/Pages/Hyd/Hyd.tsx b/src/instruments/src/SD/Pages/Hyd/Hyd.tsx index a4b94a645cc..7050243bd55 100644 --- a/src/instruments/src/SD/Pages/Hyd/Hyd.tsx +++ b/src/instruments/src/SD/Pages/Hyd/Hyd.tsx @@ -44,6 +44,8 @@ export const HydPage = () => { const [ACBus1IsPowered] = useSimVar('L:A32NX_ELEC_AC_1_BUS_IS_POWERED', 'bool', 1000); + const [blueElecPumpOvht] = useSimVar('L:A32NX_HYD_BLUE_EPUMP_OVHT', 'bool', 1000); + const [engine1Running, setEngine1Running] = useState(false); const [engine2Running, setEngine2Running] = useState(false); @@ -111,6 +113,13 @@ export const HydPage = () => { > ELEC + + OVHT + @@ -255,6 +264,10 @@ const HydReservoir = ({ system, x, y, lowLevel } : HydReservoirProps) => { const [lowAirPress] = useSimVar(`L:A32NX_HYD_${system}_RESERVOIR_AIR_PRESSURE_IS_LOW`, 'boolean', 1000); + // The overheat indication should be computed by the EIS itself from the numerical temperature value, + // by applying a hysteresis logic. For now, we just use a boolean from the hydraulics directly. + const [overheat] = useSimVar(`L:A32NX_HYD_${system}_RESERVOIR_OVHT`, 'boolean', 1000); + const fluidLevelInLitres = fluidLevel * litersPerGallon; const values = levels[system]; @@ -282,6 +295,10 @@ const HydReservoir = ({ system, x, y, lowLevel } : HydReservoirProps) => { LO AIR PRESS + + { /* Not sure about the exact placement, have to wait for an IRL ref */ } + OVHT + ); }; @@ -295,6 +312,8 @@ type YellowElecPumpProps = { const YellowElecPump = ({ pumpPushbuttonOn, pressure, enginePumpPressureLowSwitch }: YellowElecPumpProps) => { const [ACBus2IsPowered] = useSimVar('L:A32NX_ELEC_AC_2_BUS_IS_POWERED', 'bool', 1000); + const [yellowElecPumpOvht] = useSimVar('L:A32NX_HYD_YELLOW_EPUMP_OVHT', 'bool', 1000); + let elecHorizontalLineFormat: string; let verticalLineFormat: string; let elecTriangleFill: number; @@ -326,6 +345,13 @@ const YellowElecPump = ({ pumpPushbuttonOn, pressure, enginePumpPressureLowSwitc > ELEC + + OVHT + diff --git a/src/systems/a320_hydraulic_simulation_graphs/src/main.rs b/src/systems/a320_hydraulic_simulation_graphs/src/main.rs index 6b1cee0745c..b1b15da5a19 100644 --- a/src/systems/a320_hydraulic_simulation_graphs/src/main.rs +++ b/src/systems/a320_hydraulic_simulation_graphs/src/main.rs @@ -10,8 +10,8 @@ use systems::hydraulic::*; use systems::{ electrical::{test::TestElectricitySource, ElectricalBus, Electricity}, shared::{ - update_iterator::FixedStepLoop, ElectricalBusType, HydraulicColor, PotentialOrigin, - ReservoirAirPressure, + update_iterator::FixedStepLoop, AirbusElectricPumpId, AirbusEngineDrivenPumpId, + ElectricalBusType, HydraulicColor, PotentialOrigin, ReservoirAirPressure, }, simulation::{ test::{SimulationTestBed, TestBed}, @@ -358,7 +358,7 @@ fn hydraulic_loop(context: &mut InitContext, loop_color: HydraulicColor) -> Hydr fn electric_pump(context: &mut InitContext) -> ElectricPump { ElectricPump::new( context, - "DEFAULT", + AirbusElectricPumpId::Green, ElectricalBusType::AlternatingCurrentGndFltService, ElectricCurrent::new::(45.), PumpCharacteristics::a320_electric_pump(), @@ -366,7 +366,11 @@ fn electric_pump(context: &mut InitContext) -> ElectricPump { } fn _engine_driven_pump(context: &mut InitContext) -> EngineDrivenPump { - EngineDrivenPump::new(context, "DEFAULT", PumpCharacteristics::a320_edp()) + EngineDrivenPump::new( + context, + AirbusEngineDrivenPumpId::Green, + PumpCharacteristics::a320_edp(), + ) } struct A320TestPneumatics { diff --git a/src/systems/a320_systems/src/hydraulic/mod.rs b/src/systems/a320_systems/src/hydraulic/mod.rs index 3969bfc891d..5c3f3518c9a 100644 --- a/src/systems/a320_systems/src/hydraulic/mod.rs +++ b/src/systems/a320_systems/src/hydraulic/mod.rs @@ -46,10 +46,10 @@ use systems::{ ManualPitchTrimController, PitchTrimActuatorController, TrimmableHorizontalStabilizerAssembly, }, - ElectricPump, EngineDrivenPump, HydraulicCircuit, HydraulicCircuitController, - HydraulicPressureSensors, PowerTransferUnit, PowerTransferUnitCharacteristics, - PowerTransferUnitController, PressureSwitch, PressureSwitchType, PumpController, - RamAirTurbine, RamAirTurbineController, Reservoir, + ElectricPump, EngineDrivenPump, HeatingElement, HydraulicCircuit, + HydraulicCircuitController, HydraulicPressureSensors, PowerTransferUnit, + PowerTransferUnitCharacteristics, PowerTransferUnitController, PressureSwitch, + PressureSwitchType, PumpController, RamAirTurbine, RamAirTurbineController, Reservoir, }, landing_gear::{GearSystemSensors, LandingGearControlInterfaceUnitSet}, overhead::{ @@ -60,11 +60,12 @@ use systems::{ low_pass_filter::LowPassFilter, random_from_normal_distribution, random_from_range, update_iterator::{FixedStepLoop, MaxStepLoop}, - AdirsDiscreteOutputs, DelayedFalseLogicGate, DelayedPulseTrueLogicGate, - DelayedTrueLogicGate, ElectricalBusType, ElectricalBuses, EmergencyElectricalRatPushButton, - EmergencyElectricalState, EmergencyGeneratorPower, EngineFirePushButtons, GearWheel, - HydraulicColor, HydraulicGeneratorControlUnit, LandingGearHandle, LgciuInterface, - LgciuWeightOnWheels, ReservoirAirPressure, SectionPressure, TrimmableHorizontalStabilizer, + AdirsDiscreteOutputs, AirbusElectricPumpId, AirbusEngineDrivenPumpId, + DelayedFalseLogicGate, DelayedPulseTrueLogicGate, DelayedTrueLogicGate, ElectricalBusType, + ElectricalBuses, EmergencyElectricalRatPushButton, EmergencyElectricalState, + EmergencyGeneratorPower, EngineFirePushButtons, GearWheel, HydraulicColor, + HydraulicGeneratorControlUnit, LandingGearHandle, LgciuInterface, LgciuWeightOnWheels, + ReservoirAirPressure, SectionPressure, TrimmableHorizontalStabilizer, }, simulation::{ InitContext, Read, Reader, SimulationElement, SimulationElementVisitor, SimulatorReader, @@ -1589,7 +1590,7 @@ impl A320Hydraulic { engine_driven_pump_1: EngineDrivenPump::new( context, - "GREEN", + AirbusEngineDrivenPumpId::Green, PumpCharacteristics::a320_edp(), ), engine_driven_pump_1_controller: A320EngineDrivenPumpController::new( @@ -1600,7 +1601,7 @@ impl A320Hydraulic { engine_driven_pump_2: EngineDrivenPump::new( context, - "YELLOW", + AirbusEngineDrivenPumpId::Yellow, PumpCharacteristics::a320_edp(), ), engine_driven_pump_2_controller: A320EngineDrivenPumpController::new( @@ -1614,7 +1615,7 @@ impl A320Hydraulic { blue_electric_pump: ElectricPump::new( context, - "BLUE", + AirbusElectricPumpId::Blue, Self::BLUE_ELEC_PUMP_SUPPLY_POWER_BUS, ElectricCurrent::new::(Self::ELECTRIC_PUMP_MAX_CURRENT_AMPERE), PumpCharacteristics::a320_electric_pump(), @@ -1626,7 +1627,7 @@ impl A320Hydraulic { yellow_electric_pump: ElectricPump::new( context, - "YELLOW", + AirbusElectricPumpId::Yellow, Self::YELLOW_ELEC_PUMP_SUPPLY_POWER_BUS, ElectricCurrent::new::(Self::ELECTRIC_PUMP_MAX_CURRENT_AMPERE), PumpCharacteristics::a320_electric_pump(), @@ -1835,6 +1836,7 @@ impl A320Hydraulic { self.power_transfer_unit_controller .has_air_pressure_low_fault() || self.power_transfer_unit_controller.has_low_level_fault() + || self.power_transfer_unit_controller.has_overheat_fault() } fn green_edp_has_fault(&self) -> bool { @@ -1844,6 +1846,7 @@ impl A320Hydraulic { .engine_driven_pump_1_controller .has_air_pressure_low_fault() || self.engine_driven_pump_1_controller.has_low_level_fault() + || self.engine_driven_pump_1_controller.has_overheat_fault() } fn yellow_epump_has_fault(&self) -> bool { @@ -1853,6 +1856,7 @@ impl A320Hydraulic { .yellow_electric_pump_controller .has_air_pressure_low_fault() || self.yellow_electric_pump_controller.has_low_level_fault() + || self.yellow_electric_pump_controller.has_overheat_fault() } fn yellow_edp_has_fault(&self) -> bool { @@ -1862,6 +1866,7 @@ impl A320Hydraulic { .engine_driven_pump_2_controller .has_air_pressure_low_fault() || self.engine_driven_pump_2_controller.has_low_level_fault() + || self.engine_driven_pump_2_controller.has_overheat_fault() } fn blue_epump_has_fault(&self) -> bool { @@ -1870,6 +1875,7 @@ impl A320Hydraulic { .blue_electric_pump_controller .has_air_pressure_low_fault() || self.blue_electric_pump_controller.has_low_level_fault() + || self.blue_electric_pump_controller.has_overheat_fault() } pub fn green_reservoir(&self) -> &Reservoir { @@ -2338,6 +2344,7 @@ impl A320Hydraulic { lgciu1, lgciu2, self.blue_circuit.reservoir(), + &self.blue_electric_pump, ); self.blue_electric_pump.update( context, @@ -2354,6 +2361,7 @@ impl A320Hydraulic { &self.aft_cargo_door_controller, &self.yellow_circuit, self.yellow_circuit.reservoir(), + &self.yellow_electric_pump, ); self.yellow_electric_pump.update( context, @@ -2476,6 +2484,7 @@ impl A320Hydraulic { > Pressure::new::(Self::HIGH_PITCH_PTU_SOUND_DELTA_PRESS_THRESHOLD_PSI) && is_ptu_rotating && !self.ptu_high_pitch_sound_active.output() + && !self.power_transfer_unit.is_in_continuous_mode() } pub fn gear_system(&self) -> &impl GearSystemSensors { @@ -2754,6 +2763,7 @@ struct A320EngineDrivenPumpController { has_air_pressure_low_fault: bool, has_low_level_fault: bool, is_pressure_low: bool, + has_overheat_fault: bool, } impl A320EngineDrivenPumpController { fn new( @@ -2777,6 +2787,8 @@ impl A320EngineDrivenPumpController { has_low_level_fault: false, is_pressure_low: true, + + has_overheat_fault: false, } } @@ -2844,6 +2856,8 @@ impl A320EngineDrivenPumpController { self.update_low_air_pressure(reservoir, overhead_panel); self.update_low_level(reservoir, overhead_panel); + + self.has_overheat_fault = reservoir.is_overheating(); } fn has_pressure_low_fault(&self) -> bool { @@ -2857,6 +2871,10 @@ impl A320EngineDrivenPumpController { fn has_low_level_fault(&self) -> bool { self.has_low_level_fault } + + fn has_overheat_fault(&self) -> bool { + self.has_overheat_fault + } } impl PumpController for A320EngineDrivenPumpController { fn should_pressurise(&self) -> bool { @@ -2889,6 +2907,7 @@ struct A320BlueElectricPumpController { has_air_pressure_low_fault: bool, has_low_level_fault: bool, is_pressure_low: bool, + has_overheat_fault: bool, } impl A320BlueElectricPumpController { fn new(context: &mut InitContext, powered_by: ElectricalBusType) -> Self { @@ -2904,6 +2923,8 @@ impl A320BlueElectricPumpController { has_low_level_fault: false, is_pressure_low: true, + + has_overheat_fault: false, } } @@ -2916,6 +2937,7 @@ impl A320BlueElectricPumpController { lgciu1: &impl LgciuInterface, lgciu2: &impl LgciuInterface, reservoir: &Reservoir, + elec_pump: &impl HeatingElement, ) { let mut should_pressurise_if_powered = false; if overhead_panel.blue_epump_push_button.is_auto() { @@ -2946,6 +2968,9 @@ impl A320BlueElectricPumpController { self.update_low_air_pressure(reservoir, overhead_panel); self.update_low_level(reservoir, overhead_panel); + + // Elec pump has temperature sensor so we check also pump overheating state + self.has_overheat_fault = elec_pump.is_overheating() || reservoir.is_overheating(); } fn update_low_pressure( @@ -3003,6 +3028,10 @@ impl A320BlueElectricPumpController { fn has_low_level_fault(&self) -> bool { self.has_low_level_fault } + + fn has_overheat_fault(&self) -> bool { + self.has_low_level_fault + } } impl PumpController for A320BlueElectricPumpController { fn should_pressurise(&self) -> bool { @@ -3035,6 +3064,8 @@ struct A320YellowElectricPumpController { should_pressurise_for_cargo_door_operation: bool, low_pressure_hystereris: bool, + + has_overheat_fault: bool, } impl A320YellowElectricPumpController { const DURATION_OF_YELLOW_PUMP_ACTIVATION_AFTER_CARGO_DOOR_OPERATION: Duration = @@ -3067,6 +3098,8 @@ impl A320YellowElectricPumpController { should_pressurise_for_cargo_door_operation: false, low_pressure_hystereris: false, + + has_overheat_fault: false, } } @@ -3078,6 +3111,7 @@ impl A320YellowElectricPumpController { aft_cargo_door_controller: &A320DoorController, hydraulic_circuit: &impl HydraulicPressureSensors, reservoir: &Reservoir, + elec_pump: &impl HeatingElement, ) { self.update_cargo_door_logic( context, @@ -3095,6 +3129,9 @@ impl A320YellowElectricPumpController { self.update_low_air_pressure(reservoir, overhead_panel); self.update_low_level(reservoir, overhead_panel); + + // Elec pump has temperature sensor so we check also pump overheating state + self.has_overheat_fault = elec_pump.is_overheating() || reservoir.is_overheating(); } fn update_low_pressure(&mut self, hydraulic_circuit: &impl HydraulicPressureSensors) { @@ -3172,6 +3209,10 @@ impl A320YellowElectricPumpController { self.has_low_level_fault } + fn has_overheat_fault(&self) -> bool { + self.has_overheat_fault + } + fn should_pressurise_for_cargo_door_operation(&self) -> bool { self.should_pressurise_for_cargo_door_operation } @@ -3210,6 +3251,7 @@ struct A320PowerTransferUnitController { has_air_pressure_low_fault: bool, has_low_level_fault: bool, + has_overheat_fault: bool, } impl A320PowerTransferUnitController { const DURATION_OF_PTU_INHIBIT_AFTER_CARGO_DOOR_OPERATION: Duration = Duration::from_secs(40); @@ -3235,6 +3277,7 @@ impl A320PowerTransferUnitController { has_air_pressure_low_fault: false, has_low_level_fault: false, + has_overheat_fault: false, } } @@ -3272,6 +3315,9 @@ impl A320PowerTransferUnitController { self.update_low_air_pressure(reservoir_left_side, reservoir_right_side, overhead_panel); self.update_low_level(reservoir_left_side, reservoir_right_side, overhead_panel); + + self.has_overheat_fault = + reservoir_left_side.is_overheating() || reservoir_right_side.is_overheating(); } fn update_low_air_pressure( @@ -3303,6 +3349,10 @@ impl A320PowerTransferUnitController { fn has_low_level_fault(&self) -> bool { self.has_low_level_fault } + + fn has_overheat_fault(&self) -> bool { + self.has_overheat_fault + } } impl PowerTransferUnitController for A320PowerTransferUnitController { fn should_enable(&self) -> bool { @@ -6509,6 +6559,14 @@ mod tests { self.read_by_name("OVHD_HYD_EPUMPY_PB_HAS_FAULT") } + fn yellow_reservoir_has_overheat_fault(&mut self) -> bool { + self.read_by_name("HYD_YELLOW_RESERVOIR_OVHT") + } + + fn green_reservoir_has_overheat_fault(&mut self) -> bool { + self.read_by_name("HYD_GREEN_RESERVOIR_OVHT") + } + fn ptu_has_fault(&mut self) -> bool { self.read_by_name("OVHD_HYD_PTU_PB_HAS_FAULT") } @@ -11206,5 +11264,108 @@ mod tests { assert!(test_bed.is_all_gears_really_up()); assert!(test_bed.is_all_doors_really_up()); } + + #[test] + fn empty_green_reservoir_causes_yellow_overheat_if_ptu_on() { + let mut test_bed = test_bed_in_flight_with() + .set_cold_dark_inputs() + .in_flight() + .run_waiting_for(Duration::from_secs_f64(1.)); + + test_bed.fail(FailureType::ReservoirLeak(HydraulicColor::Green)); + + test_bed = test_bed.run_waiting_for(Duration::from_secs_f64(120.)); + assert!(test_bed.yellow_reservoir_has_overheat_fault()); + } + + #[test] + fn green_edp_off_do_not_causes_ptu_overheat_if_ptu_on_and_cycling_gear() { + let mut test_bed = test_bed_in_flight_with() + .set_cold_dark_inputs() + .with_worst_case_ptu() + .in_flight() + .set_green_ed_pump(false) + .run_waiting_for(Duration::from_secs_f64(1.)); + + test_bed = test_bed + .set_gear_lever_down() + .run_waiting_for(Duration::from_secs_f64(35.)); + + assert!(!test_bed.ptu_has_fault()); + + test_bed = test_bed + .set_gear_lever_up() + .run_waiting_for(Duration::from_secs_f64(35.)); + + assert!(!test_bed.ptu_has_fault()); + + test_bed = test_bed + .set_gear_lever_down() + .run_waiting_for(Duration::from_secs_f64(35.)); + + assert!(!test_bed.ptu_has_fault()); + } + + #[test] + fn empty_yellow_reservoir_causes_green_overheat_if_ptu_on() { + let mut test_bed = test_bed_in_flight_with() + .set_cold_dark_inputs() + .in_flight() + .run_waiting_for(Duration::from_secs_f64(1.)); + + test_bed.fail(FailureType::ReservoirLeak(HydraulicColor::Yellow)); + + test_bed = test_bed.run_waiting_for(Duration::from_secs_f64(120.)); + assert!(test_bed.green_reservoir_has_overheat_fault()); + } + + #[test] + fn green_edp_overheat_failure_causes_green_reservoir_overheat() { + let mut test_bed = test_bed_in_flight_with() + .set_cold_dark_inputs() + .in_flight() + .run_waiting_for(Duration::from_secs_f64(1.)); + + test_bed.fail(FailureType::EnginePumpOverheat( + AirbusEngineDrivenPumpId::Green, + )); + + test_bed = test_bed.run_waiting_for(Duration::from_secs_f64(120.)); + assert!(test_bed.green_reservoir_has_overheat_fault()); + } + + #[test] + fn green_edp_overheat_failure_do_not_causes_green_reservoir_overheat_if_unpressurised() { + let mut test_bed = test_bed_in_flight_with() + .set_cold_dark_inputs() + .in_flight() + .run_waiting_for(Duration::from_secs_f64(1.)); + + test_bed.fail(FailureType::EnginePumpOverheat( + AirbusEngineDrivenPumpId::Green, + )); + + test_bed = test_bed + .set_green_ed_pump(false) + .run_waiting_for(Duration::from_secs_f64(120.)); + assert!(!test_bed.green_reservoir_has_overheat_fault()); + } + + #[test] + fn yellow_edp_overheat_failure_do_not_causes_yellow_reservoir_overheat_if_unpressurised() { + let mut test_bed = test_bed_in_flight_with() + .set_cold_dark_inputs() + .in_flight() + .run_waiting_for(Duration::from_secs_f64(1.)); + + test_bed.fail(FailureType::EnginePumpOverheat( + AirbusEngineDrivenPumpId::Yellow, + )); + + test_bed = test_bed + .set_yellow_ed_pump(false) + .run_waiting_for(Duration::from_secs_f64(120.)); + assert!(!test_bed.yellow_reservoir_has_overheat_fault()); + } } } diff --git a/src/systems/a320_systems_wasm/src/lib.rs b/src/systems/a320_systems_wasm/src/lib.rs index 8ccc01bfd93..bb07bf3430e 100644 --- a/src/systems/a320_systems_wasm/src/lib.rs +++ b/src/systems/a320_systems_wasm/src/lib.rs @@ -22,7 +22,8 @@ use spoilers::spoilers; use std::error::Error; use systems::failures::FailureType; use systems::shared::{ - ElectricalBusType, GearActuatorId, HydraulicColor, LgciuId, ProximityDetectorId, + AirbusElectricPumpId, AirbusEngineDrivenPumpId, ElectricalBusType, GearActuatorId, + HydraulicColor, LgciuId, ProximityDetectorId, }; use systems_wasm::aspects::ExecuteOn; use systems_wasm::{MsfsSimulationBuilder, Variable}; @@ -80,6 +81,22 @@ async fn systems(mut gauge: msfs::Gauge) -> Result<(), Box> { 29_008, FailureType::ReservoirReturnLeak(HydraulicColor::Yellow), ), + ( + 29_009, + FailureType::EnginePumpOverheat(AirbusEngineDrivenPumpId::Green), + ), + ( + 29_010, + FailureType::ElecPumpOverheat(AirbusElectricPumpId::Blue), + ), + ( + 29_011, + FailureType::EnginePumpOverheat(AirbusEngineDrivenPumpId::Yellow), + ), + ( + 29_012, + FailureType::ElecPumpOverheat(AirbusElectricPumpId::Yellow), + ), (32_000, FailureType::LgciuPowerSupply(LgciuId::Lgciu1)), (32_001, FailureType::LgciuPowerSupply(LgciuId::Lgciu2)), (32_002, FailureType::LgciuInternalError(LgciuId::Lgciu1)), diff --git a/src/systems/a380_systems/src/hydraulic/mod.rs b/src/systems/a380_systems/src/hydraulic/mod.rs index 7df54fa1ad0..f093da09f1e 100644 --- a/src/systems/a380_systems/src/hydraulic/mod.rs +++ b/src/systems/a380_systems/src/hydraulic/mod.rs @@ -49,10 +49,11 @@ use systems::{ overhead::{AutoOffFaultPushButton, AutoOnFaultPushButton}, shared::{ interpolation, low_pass_filter::LowPassFilter, random_from_range, - update_iterator::MaxStepLoop, AdirsDiscreteOutputs, DelayedFalseLogicGate, - DelayedPulseTrueLogicGate, DelayedTrueLogicGate, ElectricalBusType, ElectricalBuses, - EngineFirePushButtons, GearWheel, HydraulicColor, LandingGearHandle, LgciuInterface, - LgciuWeightOnWheels, ReservoirAirPressure, SectionPressure, + update_iterator::MaxStepLoop, AdirsDiscreteOutputs, AirbusElectricPumpId, + AirbusEngineDrivenPumpId, DelayedFalseLogicGate, DelayedPulseTrueLogicGate, + DelayedTrueLogicGate, ElectricalBusType, ElectricalBuses, EngineFirePushButtons, GearWheel, + HydraulicColor, LandingGearHandle, LgciuInterface, LgciuWeightOnWheels, + ReservoirAirPressure, SectionPressure, }, simulation::{ InitContext, Read, Reader, SimulationElement, SimulationElementVisitor, SimulatorReader, @@ -1615,7 +1616,7 @@ impl A380Hydraulic { engine_driven_pump_1a: EngineDrivenPump::new( context, - "GREEN_1A", + AirbusEngineDrivenPumpId::Edp1a, PumpCharacteristics::a380_edp(), ), engine_driven_pump_1a_controller: A380EngineDrivenPumpController::new( @@ -1626,7 +1627,7 @@ impl A380Hydraulic { engine_driven_pump_2a: EngineDrivenPump::new( context, - "GREEN_2A", + AirbusEngineDrivenPumpId::Edp2a, PumpCharacteristics::a380_edp(), ), engine_driven_pump_2a_controller: A380EngineDrivenPumpController::new( @@ -1637,7 +1638,7 @@ impl A380Hydraulic { engine_driven_pump_3a: EngineDrivenPump::new( context, - "YELLOW_3A", + AirbusEngineDrivenPumpId::Edp3a, PumpCharacteristics::a380_edp(), ), engine_driven_pump_3a_controller: A380EngineDrivenPumpController::new( @@ -1648,7 +1649,7 @@ impl A380Hydraulic { engine_driven_pump_4a: EngineDrivenPump::new( context, - "YELLOW_4A", + AirbusEngineDrivenPumpId::Edp4a, PumpCharacteristics::a380_edp(), ), engine_driven_pump_4a_controller: A380EngineDrivenPumpController::new( @@ -1659,7 +1660,7 @@ impl A380Hydraulic { engine_driven_pump_1b: EngineDrivenPump::new( context, - "GREEN_1B", + AirbusEngineDrivenPumpId::Edp1b, PumpCharacteristics::a380_edp(), ), engine_driven_pump_1b_controller: A380EngineDrivenPumpController::new( @@ -1670,7 +1671,7 @@ impl A380Hydraulic { engine_driven_pump_2b: EngineDrivenPump::new( context, - "GREEN_2B", + AirbusEngineDrivenPumpId::Edp2b, PumpCharacteristics::a380_edp(), ), engine_driven_pump_2b_controller: A380EngineDrivenPumpController::new( @@ -1681,7 +1682,7 @@ impl A380Hydraulic { engine_driven_pump_3b: EngineDrivenPump::new( context, - "YELLOW_3B", + AirbusEngineDrivenPumpId::Edp3b, PumpCharacteristics::a380_edp(), ), engine_driven_pump_3b_controller: A380EngineDrivenPumpController::new( @@ -1692,7 +1693,7 @@ impl A380Hydraulic { engine_driven_pump_4b: EngineDrivenPump::new( context, - "YELLOW_4B", + AirbusEngineDrivenPumpId::Edp4b, PumpCharacteristics::a380_edp(), ), engine_driven_pump_4b_controller: A380EngineDrivenPumpController::new( @@ -1703,7 +1704,7 @@ impl A380Hydraulic { yellow_electric_pump_a: ElectricPump::new( context, - "YELLOW_A", + AirbusElectricPumpId::YellowA, Self::YELLOW_ELEC_PUMP_SUPPLY_POWER_BUS, ElectricCurrent::new::(Self::ELECTRIC_PUMP_MAX_CURRENT_AMPERE), PumpCharacteristics::a380_electric_pump(), @@ -1717,7 +1718,7 @@ impl A380Hydraulic { yellow_electric_pump_b: ElectricPump::new( context, - "YELLOW_B", + AirbusElectricPumpId::YellowB, Self::YELLOW_ELEC_PUMP_SUPPLY_POWER_BUS, ElectricCurrent::new::(Self::ELECTRIC_PUMP_MAX_CURRENT_AMPERE), PumpCharacteristics::a380_electric_pump(), @@ -1731,7 +1732,7 @@ impl A380Hydraulic { green_electric_pump_a: ElectricPump::new( context, - "GREEN_A", + AirbusElectricPumpId::GreenA, Self::YELLOW_ELEC_PUMP_SUPPLY_POWER_BUS, ElectricCurrent::new::(Self::ELECTRIC_PUMP_MAX_CURRENT_AMPERE), PumpCharacteristics::a380_electric_pump(), @@ -1745,7 +1746,7 @@ impl A380Hydraulic { green_electric_pump_b: ElectricPump::new( context, - "GREEN_B", + AirbusElectricPumpId::GreenB, Self::YELLOW_ELEC_PUMP_SUPPLY_POWER_BUS, ElectricCurrent::new::(Self::ELECTRIC_PUMP_MAX_CURRENT_AMPERE), PumpCharacteristics::a380_electric_pump(), diff --git a/src/systems/systems/src/failures/mod.rs b/src/systems/systems/src/failures/mod.rs index 35f15d8d3bf..84f11a513bd 100644 --- a/src/systems/systems/src/failures/mod.rs +++ b/src/systems/systems/src/failures/mod.rs @@ -1,4 +1,7 @@ -use crate::shared::{GearActuatorId, HydraulicColor, LgciuId, ProximityDetectorId}; +use crate::shared::{ + AirbusElectricPumpId, AirbusEngineDrivenPumpId, GearActuatorId, HydraulicColor, LgciuId, + ProximityDetectorId, +}; use crate::simulation::SimulationElement; #[derive(Clone, Copy, PartialEq, Eq)] @@ -7,6 +10,8 @@ pub enum FailureType { ReservoirLeak(HydraulicColor), ReservoirAirLeak(HydraulicColor), ReservoirReturnLeak(HydraulicColor), + EnginePumpOverheat(AirbusEngineDrivenPumpId), + ElecPumpOverheat(AirbusElectricPumpId), LgciuPowerSupply(LgciuId), LgciuInternalError(LgciuId), GearProxSensorDamage(ProximityDetectorId), diff --git a/src/systems/systems/src/hydraulic/electrical_pump_physics.rs b/src/systems/systems/src/hydraulic/electrical_pump_physics.rs index 44d73d953b2..d7e9f29fb1e 100644 --- a/src/systems/systems/src/hydraulic/electrical_pump_physics.rs +++ b/src/systems/systems/src/hydraulic/electrical_pump_physics.rs @@ -6,17 +6,23 @@ use uom::si::{ f64::*, power::watt, pressure::psi, + ratio::ratio, torque::{newton_meter, pound_force_inch}, volume::cubic_inch, }; -use crate::hydraulic::SectionPressure; +use crate::hydraulic::{HeatingElement, HeatingProperties, SectionPressure}; use crate::shared::{ - low_pass_filter::LowPassFilter, pid::PidController, ConsumePower, ElectricalBusType, - ElectricalBuses, + low_pass_filter::LowPassFilter, pid::PidController, random_from_normal_distribution, + ConsumePower, ElectricalBusType, ElectricalBuses, }; use crate::simulation::{ - InitContext, SimulationElement, SimulatorWriter, UpdateContext, VariableIdentifier, Write, + InitContext, SimulationElement, SimulationElementVisitor, SimulatorWriter, UpdateContext, + VariableIdentifier, Write, +}; +use crate::{ + failures::{Failure, FailureType}, + shared::AirbusElectricPumpId, }; use std::time::Duration; @@ -43,6 +49,9 @@ pub(super) struct ElectricalPumpPhysics { current_controller: PidController, displacement_filtered: LowPassFilter, + + overheat_failure: Failure, + heat_state: HeatingProperties, } impl ElectricalPumpPhysics { const DEFAULT_INERTIA: f64 = 0.011; @@ -60,9 +69,17 @@ impl ElectricalPumpPhysics { const DEFAULT_P_GAIN: f64 = 0.1; const DEFAULT_I_GAIN: f64 = 0.45; + const HEATING_TIME_CONSTANT_MEAN_S: f64 = 30.; + const HEATING_TIME_CONSTANT_STD_S: f64 = 5.; + + const COOLING_TIME_CONSTANT: Duration = Duration::from_secs(60 * 2); + const DAMAGE_TIME_CONSTANT: Duration = Duration::from_secs(60 * 2); + + const MIN_SPEED_TO_REPORT_ACTIVE_RPM: f64 = 10.; + pub fn new( context: &mut InitContext, - id: &str, + id: AirbusElectricPumpId, bus_type: ElectricalBusType, max_current: ElectricCurrent, regulated_speed: AngularVelocity, @@ -97,6 +114,18 @@ impl ElectricalPumpPhysics { displacement_filtered: LowPassFilter::::new( Self::SPEED_DISPLACEMENT_FILTER_TIME_CONSTANT, ), + overheat_failure: Failure::new(FailureType::ElecPumpOverheat(id)), + heat_state: HeatingProperties::new( + Duration::from_secs_f64( + random_from_normal_distribution( + Self::HEATING_TIME_CONSTANT_MEAN_S, + Self::HEATING_TIME_CONSTANT_STD_S, + ) + .max(10.), + ), + Self::COOLING_TIME_CONSTANT, + Self::DAMAGE_TIME_CONSTANT, + ), } } @@ -106,6 +135,11 @@ impl ElectricalPumpPhysics { section: &impl SectionPressure, current_displacement: Volume, ) { + self.heat_state.update( + context, + self.overheat_failure.is_active() && self.speed().get::() > 100., + ); + self.displacement_filtered .update(context.delta(), current_displacement); @@ -155,11 +189,20 @@ impl ElectricalPumpPhysics { Torque::new::(Self::DEFAULT_RESISTANT_TORQUE_WHEN_OFF_NEWTON_METER) }; - self.resistant_torque = pumping_torque + dynamic_friction_torque; + let overheat_resistant_torque_factor = if !self.heat_state.is_overheating() { + 1. + } else if !self.heat_state.is_damaged() { + 50. * self.heat_state.overheat_ratio().get::() + } else { + 100. + }; + + self.resistant_torque = + pumping_torque + dynamic_friction_torque * overheat_resistant_torque_factor; } fn update_current_control(&mut self, context: &UpdateContext) { - self.output_current = if self.pump_should_run() { + self.output_current = if self.pump_should_run() && !self.is_damaged() { ElectricCurrent::new::(self.current_controller.next_control_output( self.speed_raw.get::(), Some(context.delta()), @@ -187,7 +230,7 @@ impl ElectricalPumpPhysics { self.update_electrical_power_consumption(); - if self.pump_should_run() { + if self.pump_should_run() && !self.is_damaged() { if self.speed_raw.get::() < 5. && self.output_current.get::() > 0. { @@ -217,8 +260,18 @@ impl ElectricalPumpPhysics { } } impl SimulationElement for ElectricalPumpPhysics { + fn accept(&mut self, visitor: &mut T) { + self.overheat_failure.accept(visitor); + visitor.visit(self); + } + fn write(&self, writer: &mut SimulatorWriter) { - writer.write(&self.active_id, self.is_active); + writer.write( + &self.active_id, + self.is_active + && self.speed().get::() + > Self::MIN_SPEED_TO_REPORT_ACTIVE_RPM, + ); writer.write(&self.rpm_id, self.speed()); } @@ -231,6 +284,15 @@ impl SimulationElement for ElectricalPumpPhysics { consumption.consume_from_bus(self.powered_by, self.consumed_power); } } +impl HeatingElement for ElectricalPumpPhysics { + fn is_damaged(&self) -> bool { + self.heat_state.is_damaged() + } + + fn is_overheating(&self) -> bool { + self.heat_state.is_overheating() + } +} #[cfg(test)] mod tests { @@ -437,10 +499,45 @@ mod tests { ); } + #[test] + fn pump_with_overheat_failure_overheats_and_fails() { + let mut test_bed = SimulationTestBed::new(TestAircraft::new); + + test_bed.command(|a| a.set_ac_1_power(true)); + test_bed.command(|a| a.pump.set_active(true)); + test_bed.command(|a| a.set_current_displacement(Volume::new::(0.))); + test_bed.command(|a| a.set_current_pressure(Pressure::new::(3000.))); + + test_bed.run_with_delta(Duration::from_secs_f64(1.)); + + assert!( + test_bed.query(|a| a.pump.speed()) + >= AngularVelocity::new::(7000.) + ); + + test_bed.fail(FailureType::ElecPumpOverheat(AirbusElectricPumpId::Yellow)); + + test_bed.run_with_delta(Duration::from_secs_f64( + ElectricalPumpPhysics::HEATING_TIME_CONSTANT_MEAN_S + + 4. * ElectricalPumpPhysics::HEATING_TIME_CONSTANT_STD_S, + )); + + assert!(test_bed.query(|a| a.pump.is_overheating())); + + test_bed.run_with_delta(ElectricalPumpPhysics::DAMAGE_TIME_CONSTANT); + + assert!(test_bed.query(|a| a.pump.is_damaged())); + + assert!( + test_bed.query(|a| a.pump.speed()) + <= AngularVelocity::new::(100.) + ); + } + fn physical_pump(context: &mut InitContext) -> ElectricalPumpPhysics { ElectricalPumpPhysics::new( context, - "YELLOW", + AirbusElectricPumpId::Yellow, ElectricalBusType::AlternatingCurrent(1), ElectricCurrent::new::(45.), AngularVelocity::new::(7600.), diff --git a/src/systems/systems/src/hydraulic/mod.rs b/src/systems/systems/src/hydraulic/mod.rs index 8064bf361c0..7f88975be94 100644 --- a/src/systems/systems/src/hydraulic/mod.rs +++ b/src/systems/systems/src/hydraulic/mod.rs @@ -4,10 +4,11 @@ use crate::hydraulic::{ electrical_pump_physics::ElectricalPumpPhysics, pumps::PumpCharacteristics, }; use crate::pneumatic::PressurizeableReservoir; + use crate::shared::{ interpolation, low_pass_filter::LowPassFilter, random_from_normal_distribution, - random_from_range, DelayedTrueLogicGate, ElectricalBusType, ElectricalBuses, HydraulicColor, - SectionPressure, + random_from_range, AirbusElectricPumpId, AirbusEngineDrivenPumpId, DelayedTrueLogicGate, + ElectricalBusType, ElectricalBuses, HydraulicColor, SectionPressure, }; use crate::simulation::{ InitContext, Read, SimulationElement, SimulationElementVisitor, SimulatorReader, @@ -75,15 +76,48 @@ pub trait PressureSource { pub struct Fluid { current_bulk: Pressure, + heat_state: HeatingProperties, } impl Fluid { + const HEATING_TIME_CONSTANT_MEAN_S: f64 = 40.; + const HEATING_TIME_CONSTANT_STD_S: f64 = 10.; + + const COOLING_TIME_CONSTANT: Duration = Duration::from_secs(60 * 3); + const DAMAGE_TIME_CONSTANT: Duration = Duration::from_secs(60 * 3); + pub fn new(bulk: Pressure) -> Self { - Self { current_bulk: bulk } + Self { + current_bulk: bulk, + heat_state: HeatingProperties::new( + Duration::from_secs_f64( + random_from_normal_distribution( + Self::HEATING_TIME_CONSTANT_MEAN_S, + Self::HEATING_TIME_CONSTANT_STD_S, + ) + .max(10.), + ), + Self::COOLING_TIME_CONSTANT, + Self::DAMAGE_TIME_CONSTANT, + ), + } } pub fn bulk_mod(&self) -> Pressure { self.current_bulk } + + fn update(&mut self, context: &UpdateContext, is_heating: bool) { + self.heat_state.update(context, is_heating); + } +} +impl HeatingElement for Fluid { + fn is_overheating(&self) -> bool { + self.heat_state.is_overheating() + } + + fn is_damaged(&self) -> bool { + self.heat_state.is_damaged() + } } #[derive(PartialEq, Eq, Clone, Copy)] @@ -174,6 +208,80 @@ impl LevelSwitch { } } +pub trait HeatingElement { + fn is_overheating(&self) -> bool { + false + } + fn is_damaged(&self) -> bool { + false + } +} + +pub trait HeatingPressureSource: PressureSource + HeatingElement {} + +pub struct HeatingProperties { + is_overheating: bool, + is_damaged_by_heat: bool, + + damaging_time: DelayedTrueLogicGate, + + heat_factor: LowPassFilter, + heat_time: Duration, + cool_time: Duration, +} +impl HeatingProperties { + const OVERHEATING_THRESHOLD: f64 = 0.5; + + fn new(heat_time: Duration, cool_time: Duration, damage_time: Duration) -> Self { + Self { + is_overheating: false, + is_damaged_by_heat: false, + damaging_time: DelayedTrueLogicGate::new(damage_time), + heat_factor: LowPassFilter::new(heat_time), + heat_time, + cool_time, + } + } + + fn update(&mut self, context: &UpdateContext, is_heating: bool) { + if is_heating { + self.heat_factor.set_time_constant(self.heat_time); + self.heat_factor + .update(context.delta(), Ratio::new::(1.)); + } else { + self.heat_factor.set_time_constant(self.cool_time); + self.heat_factor + .update(context.delta(), Ratio::new::(0.)); + }; + + self.is_overheating = + self.heat_factor.output().get::() > Self::OVERHEATING_THRESHOLD; + + self.damaging_time.update(context, self.is_overheating); + self.is_damaged_by_heat = self.is_damaged_by_heat || self.damaging_time.output(); + } + + /// When overheating, provides a ratio of the heating severity + /// Above OVERHEATING_THRESHOLD it will rise from 0 to 1, while always 0 under the threshold + fn overheat_ratio(&self) -> Ratio { + Ratio::new::( + ((self.heat_factor.output().get::() - Self::OVERHEATING_THRESHOLD) + / (1. - Self::OVERHEATING_THRESHOLD)) + .max(0.) + .min(1.), + ) + } +} +impl HeatingElement for HeatingProperties { + fn is_overheating(&self) -> bool { + self.is_overheating + } + + fn is_damaged(&self) -> bool { + self.is_damaged_by_heat + } +} + pub trait PowerTransferUnitController { fn should_enable(&self) -> bool; } @@ -224,6 +332,8 @@ pub struct PowerTransferUnit { has_stopped_since_last_write: bool, efficiency: Ratio, + + heat_state: HeatingProperties, } impl PowerTransferUnit { const MIN_SPEED_SIMULATION_RPM: f64 = 50.; @@ -258,6 +368,16 @@ impl PowerTransferUnit { const THRESHOLD_DELTA_TO_DECLARE_CONTINUOUS_RPM: f64 = 400.; const DURATION_BEFORE_CAPTURING_BARK_STRENGTH_SPEED: Duration = Duration::from_millis(133); + const HEATING_TIME_CONSTANT_MEAN_S: f64 = 20.; + const HEATING_TIME_CONSTANT_STD_S: f64 = 5.; + const COOLING_TIME_CONSTANT: Duration = Duration::from_secs(60 * 3); + const DAMAGE_TIME_CONSTANT: Duration = Duration::from_secs(60 * 3); + + const MAX_SPEED_BEFORE_HEATING_UP_RPM: f64 = 2000.; + + // We consider that ptu can't overheat if there's enough pressure on both side (it's cooled by hyd fluid) + const MIN_PRESSURE_ALLOWING_PTU_HEATING_UP_RPM: f64 = 500.; + pub fn new( context: &mut InitContext, characteristics: &impl PowerTransferUnitCharacteristics, @@ -304,6 +424,18 @@ impl PowerTransferUnit { has_stopped_since_last_write: false, efficiency: characteristics.efficiency(), + + heat_state: HeatingProperties::new( + Duration::from_secs_f64( + random_from_normal_distribution( + Self::HEATING_TIME_CONSTANT_MEAN_S, + Self::HEATING_TIME_CONSTANT_STD_S, + ) + .max(10.), + ), + Self::COOLING_TIME_CONSTANT, + Self::DAMAGE_TIME_CONSTANT, + ), } } @@ -338,6 +470,16 @@ impl PowerTransferUnit { self.update_continuous_state(context); self.capture_bark_strength(); self.update_flows(); + + self.heat_state.update( + context, + self.shaft_speed.get::().abs() + > Self::MAX_SPEED_BEFORE_HEATING_UP_RPM + && (loop_left_section.pressure().get::() + < Self::MIN_PRESSURE_ALLOWING_PTU_HEATING_UP_RPM + || loop_right_section.pressure().get::() + < Self::MIN_PRESSURE_ALLOWING_PTU_HEATING_UP_RPM), + ); } fn update_displacement( @@ -432,12 +574,16 @@ impl PowerTransferUnit { let left_side_torque = -Self::calc_generated_torque(left_pressure, self.left_displacement); let right_side_torque = Self::calc_generated_torque(right_pressure, self.right_displacement.output()); + let friction_torque = Torque::new::( Self::SHAFT_FRICTION * -self.shaft_speed.get::(), ); + let total_torque = friction_torque + left_side_torque + right_side_torque; - if self.is_rotating() || total_torque.abs().get::() > Self::BREAKOUT_TORQUE_NM + if !self.heat_state.is_damaged() + && (self.is_rotating() + || total_torque.abs().get::() > Self::BREAKOUT_TORQUE_NM) { let acc = total_torque.get::() / Self::SHAFT_INERTIA; self.shaft_speed += @@ -594,6 +740,15 @@ impl SimulationElement for PowerTransferUnit { self.has_stopped_since_last_write = false; } } +impl HeatingElement for PowerTransferUnit { + fn is_overheating(&self) -> bool { + self.heat_state.is_overheating() + } + + fn is_damaged(&self) -> bool { + self.heat_state.is_damaged() + } +} pub trait HydraulicCircuitController { fn should_open_fire_shutoff_valve(&self, pump_index: usize) -> bool; @@ -871,7 +1026,6 @@ impl HydraulicCircuit { } else { None }, - pump_sections_check_valves: pump_to_system_check_valves, pump_section_routed_to_auxiliary_section: pump_section_to_auxiliary, fluid: Fluid::new(Pressure::new::(Self::FLUID_BULK_MODULUS_PASCAL)), @@ -899,14 +1053,39 @@ impl HydraulicCircuit { pub fn update( &mut self, context: &UpdateContext, - main_section_pumps: &mut [&mut dyn PressureSource], - system_section_pump: Option<&mut impl PressureSource>, - auxiliary_section_pump: Option<&mut impl PressureSource>, + main_section_pumps: &mut [&mut dyn HeatingPressureSource], + system_section_pump: Option<&mut impl HeatingPressureSource>, + auxiliary_section_pump: Option<&mut impl HeatingPressureSource>, ptu: Option<&PowerTransferUnit>, controller: &impl HydraulicCircuitController, reservoir_pressure: Pressure, ) { - self.reservoir.update(context, reservoir_pressure); + let mut any_pump_is_overheating = false; + for pump in main_section_pumps.iter() { + if pump.flow().get::() > 0.01 && pump.is_overheating() { + any_pump_is_overheating = true; + } + } + + if let Some(pump) = system_section_pump.as_ref() { + if pump.flow().get::() > 0.01 && pump.is_overheating() { + any_pump_is_overheating = true; + } + } + + if let Some(pump) = auxiliary_section_pump.as_ref() { + if pump.flow().get::() > 0.01 && pump.is_overheating() { + any_pump_is_overheating = true; + } + } + + let ptu_overheats_fluid = ptu.map_or(false, |p| p.is_overheating() && p.is_rotating()); + + self.fluid + .update(context, ptu_overheats_fluid || any_pump_is_overheating); + + self.reservoir + .update(context, reservoir_pressure, &self.fluid); self.update_shutoff_valves(controller); self.update_leak_measurement_valves(context, controller); @@ -974,9 +1153,9 @@ impl HydraulicCircuit { fn update_pumps( &mut self, context: &UpdateContext, - main_section_pumps: &mut [&mut dyn PressureSource], - system_section_pump: Option<&mut impl PressureSource>, - auxiliary_section_pump: Option<&mut impl PressureSource>, + main_section_pumps: &mut [&mut dyn HeatingPressureSource], + system_section_pump: Option<&mut impl HeatingPressureSource>, + auxiliary_section_pump: Option<&mut impl HeatingPressureSource>, ) { for (pump_index, section) in self.pump_sections.iter_mut().enumerate() { section.update_pump_state(context, main_section_pumps[pump_index], &mut self.reservoir); @@ -1026,9 +1205,9 @@ impl HydraulicCircuit { fn update_maximum_pumping_capacities( &mut self, - main_section_pumps: &mut [&mut dyn PressureSource], - system_section_pump: &Option<&mut impl PressureSource>, - auxiliary_section_pump: &Option<&mut impl PressureSource>, + main_section_pumps: &mut [&mut dyn HeatingPressureSource], + system_section_pump: &Option<&mut impl HeatingPressureSource>, + auxiliary_section_pump: &Option<&mut impl HeatingPressureSource>, ) { for (pump_index, section) in self.pump_sections.iter_mut().enumerate() { section.update_maximum_pumping_capacity(main_section_pumps[pump_index]); @@ -1419,7 +1598,7 @@ impl Section { self.total_actuator_consumed_volume = Volume::new::(0.); } - pub fn update_maximum_pumping_capacity(&mut self, pump: &dyn PressureSource) { + pub fn update_maximum_pumping_capacity(&mut self, pump: &dyn HeatingPressureSource) { self.max_pumpable_volume = if self.fire_valve_is_open() { pump.delta_vol_max() } else { @@ -1440,7 +1619,7 @@ impl Section { pub fn update_pump_state( &mut self, context: &UpdateContext, - pump: &mut dyn PressureSource, + pump: &mut dyn HeatingPressureSource, reservoir: &mut Reservoir, ) { // Final volume target to reach target pressure is: @@ -1941,6 +2120,7 @@ pub struct Reservoir { level_id: VariableIdentifier, low_level_id: VariableIdentifier, low_air_press_id: VariableIdentifier, + overheating_id: VariableIdentifier, max_capacity: Volume, max_gaugeable: Volume, @@ -1956,6 +2136,11 @@ pub struct Reservoir { return_failure: Failure, fluid_physics: FluidPhysics, + + heat_state: HeatingProperties, + + total_return_flow: VolumeRate, + total_return_volume: Volume, } impl Reservoir { const MIN_USABLE_VOLUME_GAL: f64 = 0.2; @@ -1965,6 +2150,11 @@ impl Reservoir { // Part of the fluid lost instead of returning to reservoir const RETURN_FAILURE_LEAK_RATIO: f64 = 0.1; + const HEATING_TIME_CONSTANT_MEAN_S: f64 = 30.; + const HEATING_TIME_CONSTANT_STD_S: f64 = 5.; + const COOLING_TIME_CONSTANT: Duration = Duration::from_secs(60 * 3); + const DAMAGE_TIME_CONSTANT: Duration = Duration::from_secs(60 * 5); + pub fn new( context: &mut InitContext, hyd_loop_id: HydraulicColor, @@ -1980,6 +2170,7 @@ impl Reservoir { .get_identifier(format!("HYD_{}_RESERVOIR_LEVEL_IS_LOW", hyd_loop_id)), low_air_press_id: context .get_identifier(format!("HYD_{}_RESERVOIR_AIR_PRESSURE_IS_LOW", hyd_loop_id)), + overheating_id: context.get_identifier(format!("HYD_{}_RESERVOIR_OVHT", hyd_loop_id)), max_capacity, max_gaugeable, @@ -1991,12 +2182,34 @@ impl Reservoir { air_pressure_switches, level_switch: LevelSwitch::new(low_level_threshold), fluid_physics: FluidPhysics::new(), + + heat_state: HeatingProperties::new( + Duration::from_secs_f64( + random_from_normal_distribution( + Self::HEATING_TIME_CONSTANT_MEAN_S, + Self::HEATING_TIME_CONSTANT_STD_S, + ) + .max(10.), + ), + Self::COOLING_TIME_CONSTANT, + Self::DAMAGE_TIME_CONSTANT, + ), + total_return_flow: VolumeRate::default(), + total_return_volume: Volume::default(), } } - fn update(&mut self, context: &UpdateContext, air_pressure: Pressure) { + fn update( + &mut self, + context: &UpdateContext, + air_pressure: Pressure, + fluid: &impl HeatingElement, + ) { self.air_pressure = air_pressure; + self.update_return_flow(context); + self.update_heat(context, fluid); + self.fluid_physics.update(context); self.level_switch.update( @@ -2009,6 +2222,17 @@ impl Reservoir { self.update_leak_failure(context); } + fn update_return_flow(&mut self, context: &UpdateContext) { + self.total_return_flow = self.total_return_volume / context.delta_as_time(); + self.total_return_volume = Volume::default(); + } + + fn update_heat(&mut self, context: &UpdateContext, fluid: &impl HeatingElement) { + let has_fluid_return = self.total_return_flow.get::() > 0.01; + self.heat_state + .update(context, has_fluid_return && fluid.is_overheating()) + } + fn update_leak_failure(&mut self, context: &UpdateContext) { if self.leak_failure.is_active() { self.current_level -= @@ -2058,6 +2282,8 @@ impl Reservoir { }; self.current_level = (self.current_level + volume_actually_returned).min(self.max_capacity); + + self.total_return_volume += volume_actually_returned; } fn fluid_level_real(&self) -> Volume { @@ -2104,6 +2330,7 @@ impl SimulationElement for Reservoir { writer.write(&self.level_id, self.fluid_level_from_gauge()); writer.write(&self.low_level_id, self.is_low_level()); writer.write(&self.low_air_press_id, self.is_low_air_pressure()); + writer.write(&self.overheating_id, self.is_overheating()); } } impl PressurizeableReservoir for Reservoir { @@ -2111,6 +2338,15 @@ impl PressurizeableReservoir for Reservoir { self.max_capacity - self.fluid_level_real() } } +impl HeatingElement for Reservoir { + fn is_damaged(&self) -> bool { + self.heat_state.is_damaged() + } + + fn is_overheating(&self) -> bool { + self.heat_state.is_overheating() + } +} pub trait PumpController { fn should_pressurise(&self) -> bool; @@ -2180,8 +2416,10 @@ impl Pump { fn update_cavitation(&mut self, reservoir: &Reservoir) { self.cavitation_efficiency = if !reservoir.is_empty() { - self.pump_characteristics - .cavitation_efficiency(reservoir.air_pressure()) + self.pump_characteristics.cavitation_efficiency( + reservoir.air_pressure(), + reservoir.heat_state.overheat_ratio(), + ) } else { Ratio::new::(0.) }; @@ -2279,13 +2517,14 @@ impl PressureSource for Pump { pub struct ElectricPump { cavitation_id: VariableIdentifier, + overheat_id: VariableIdentifier, pump: Pump, pump_physics: ElectricalPumpPhysics, } impl ElectricPump { pub fn new( context: &mut InitContext, - id: &str, + id: AirbusElectricPumpId, bus_type: ElectricalBusType, max_current: ElectricCurrent, pump_characteristics: PumpCharacteristics, @@ -2293,6 +2532,7 @@ impl ElectricPump { let regulated_speed = pump_characteristics.regulated_speed(); Self { cavitation_id: context.get_identifier(format!("HYD_{}_EPUMP_CAVITATION", id)), + overheat_id: context.get_identifier(format!("HYD_{}_EPUMP_OVHT", id)), pump: Pump::new(pump_characteristics), pump_physics: ElectricalPumpPhysics::new( context, @@ -2376,8 +2616,19 @@ impl SimulationElement for ElectricPump { &self.cavitation_id, self.cavitation_efficiency().get::(), ); + writer.write(&self.overheat_id, self.is_overheating()); } } +impl HeatingElement for ElectricPump { + fn is_damaged(&self) -> bool { + self.pump_physics.is_damaged() + } + + fn is_overheating(&self) -> bool { + self.pump_physics.is_overheating() + } +} +impl HeatingPressureSource for ElectricPump {} pub struct EngineDrivenPump { active_id: VariableIdentifier, @@ -2385,11 +2636,22 @@ pub struct EngineDrivenPump { is_active: bool, speed: AngularVelocity, pump: Pump, + + overheat_failure: Failure, + heat_state: HeatingProperties, } impl EngineDrivenPump { + const HEATING_TIME_CONSTANT_MEAN_S: f64 = 30.; + const HEATING_TIME_CONSTANT_STD_S: f64 = 5.; + + const COOLING_TIME_CONSTANT: Duration = Duration::from_secs(60 * 2); + const DAMAGE_TIME_CONSTANT: Duration = Duration::from_secs(60 * 2); + + const MIN_SPEED_TO_REPORT_HEATING_RPM: f64 = 200.; + pub fn new( context: &mut InitContext, - id: &str, + id: AirbusEngineDrivenPumpId, pump_characteristics: PumpCharacteristics, ) -> Self { Self { @@ -2397,6 +2659,18 @@ impl EngineDrivenPump { is_active: false, speed: AngularVelocity::new::(0.), pump: Pump::new(pump_characteristics), + overheat_failure: Failure::new(FailureType::EnginePumpOverheat(id)), + heat_state: HeatingProperties::new( + Duration::from_secs_f64( + random_from_normal_distribution( + Self::HEATING_TIME_CONSTANT_MEAN_S, + Self::HEATING_TIME_CONSTANT_STD_S, + ) + .max(10.), + ), + Self::COOLING_TIME_CONSTANT, + Self::DAMAGE_TIME_CONSTANT, + ), } } @@ -2408,9 +2682,22 @@ impl EngineDrivenPump { pump_speed: AngularVelocity, controller: &impl PumpController, ) { - self.speed = pump_speed; + self.heat_state.update( + context, + self.overheat_failure.is_active() + && pump_speed.get::() + > Self::MIN_SPEED_TO_REPORT_HEATING_RPM, + ); + + self.speed = if !self.is_damaged() { + pump_speed + } else { + AngularVelocity::default() + }; + self.pump - .update(context, section, reservoir, pump_speed, controller); + .update(context, section, reservoir, self.speed, controller); + self.is_active = controller.should_pressurise(); } } @@ -2443,10 +2730,25 @@ impl PressureSource for EngineDrivenPump { } } impl SimulationElement for EngineDrivenPump { + fn accept(&mut self, visitor: &mut T) { + self.overheat_failure.accept(visitor); + visitor.visit(self); + } + fn write(&self, writer: &mut SimulatorWriter) { writer.write(&self.active_id, self.is_active); } } +impl HeatingElement for EngineDrivenPump { + fn is_damaged(&self) -> bool { + self.heat_state.is_damaged() + } + + fn is_overheating(&self) -> bool { + self.heat_state.is_overheating() + } +} +impl HeatingPressureSource for EngineDrivenPump {} struct WindTurbine { rpm_id: VariableIdentifier, @@ -2682,6 +2984,8 @@ impl SimulationElement for RamAirTurbine { writer.write(&self.stow_position_id, self.position); } } +impl HeatingElement for RamAirTurbine {} +impl HeatingPressureSource for RamAirTurbine {} #[cfg(test)] mod tests { @@ -2695,6 +2999,24 @@ mod tests { use super::*; + struct TestFluid { + is_hot: bool, + } + impl TestFluid { + fn overheat() -> Self { + Self { is_hot: true } + } + + fn nominal() -> Self { + Self { is_hot: false } + } + } + impl HeatingElement for TestFluid { + fn is_overheating(&self) -> bool { + self.is_hot + } + } + #[test] fn section_writes_its_state() { let mut test_bed = SimulationTestBed::from(ElementCtorFn(|context| { @@ -2820,7 +3142,7 @@ mod tests { })); test_bed.set_update_after_power_distribution(|reservoir, context| { - reservoir.update(context, Pressure::new::(50.)) + reservoir.update(context, Pressure::new::(50.), &TestFluid::nominal()) }); test_bed.fail(FailureType::ReservoirLeak(HydraulicColor::Green)); @@ -2843,7 +3165,7 @@ mod tests { })); test_bed.set_update_after_power_distribution(|reservoir, context| { - reservoir.update(context, Pressure::new::(50.)) + reservoir.update(context, Pressure::new::(50.), &TestFluid::nominal()) }); test_bed.fail(FailureType::ReservoirLeak(HydraulicColor::Green)); @@ -2866,7 +3188,7 @@ mod tests { })); test_bed.set_update_after_power_distribution(|reservoir, context| { - reservoir.update(context, Pressure::new::(50.)) + reservoir.update(context, Pressure::new::(50.), &TestFluid::nominal()) }); let is_low: bool = test_bed.read_by_name("HYD_GREEN_RESERVOIR_LEVEL_IS_LOW"); @@ -2892,7 +3214,7 @@ mod tests { })); test_bed.set_update_after_power_distribution(|reservoir, context| { - reservoir.update(context, Pressure::new::(50.)) + reservoir.update(context, Pressure::new::(50.), &TestFluid::nominal()) }); test_bed.run_multiple_frames(Duration::from_secs(2)); @@ -2919,7 +3241,7 @@ mod tests { ) })) .with_update_after_power_distribution(|el, context| { - el.update(context, Pressure::new::(50.)) + el.update(context, Pressure::new::(50.), &TestFluid::nominal()) }); test_bed.write_by_name("PLANE BANK DEGREES", 180.); @@ -2962,6 +3284,58 @@ mod tests { ); } + #[test] + fn reservoir_receiving_heating_fluid_overheats() { + let mut test_bed = SimulationTestBed::from(ElementCtorFn(|context| { + reservoir( + context, + HydraulicColor::Green, + Volume::new::(5.), + Volume::new::(2.), + Volume::new::(0.5), + ) + })); + + test_bed.set_update_after_power_distribution(|reservoir, context| { + reservoir.update(context, Pressure::new::(50.), &TestFluid::overheat()); + + reservoir.try_take_volume(Volume::new::(0.10)); + + reservoir.add_return_volume(Volume::new::(0.10)); + }); + + test_bed.run_multiple_frames(Duration::from_secs_f64( + Reservoir::HEATING_TIME_CONSTANT_MEAN_S + 4. * Reservoir::HEATING_TIME_CONSTANT_STD_S, + )); + + let is_overheating: bool = test_bed.read_by_name("HYD_GREEN_RESERVOIR_OVHT"); + assert!(is_overheating); + } + + #[test] + fn reservoir_receiving_zero_flow_of_heating_fluid_do_not_overheat() { + let mut test_bed = SimulationTestBed::from(ElementCtorFn(|context| { + reservoir( + context, + HydraulicColor::Green, + Volume::new::(5.), + Volume::new::(2.), + Volume::new::(0.5), + ) + })); + + test_bed.set_update_after_power_distribution(|reservoir, context| { + reservoir.update(context, Pressure::new::(50.), &TestFluid::overheat()); + }); + + test_bed.run_multiple_frames(Duration::from_secs_f64( + Reservoir::HEATING_TIME_CONSTANT_MEAN_S + 4. * Reservoir::HEATING_TIME_CONSTANT_STD_S, + )); + + let is_overheating: bool = test_bed.read_by_name("HYD_GREEN_RESERVOIR_OVHT"); + assert!(!is_overheating); + } + fn section( context: &mut InitContext, loop_id: HydraulicColor, @@ -3051,7 +3425,11 @@ mod tests { } fn engine_driven_pump(context: &mut InitContext) -> EngineDrivenPump { - EngineDrivenPump::new(context, "DEFAULT", PumpCharacteristics::a320_edp()) + EngineDrivenPump::new( + context, + AirbusEngineDrivenPumpId::Green, + PumpCharacteristics::a320_edp(), + ) } #[cfg(test)] diff --git a/src/systems/systems/src/hydraulic/pumps.rs b/src/systems/systems/src/hydraulic/pumps.rs index ffb189ab3c1..5095aa3f5bb 100644 --- a/src/systems/systems/src/hydraulic/pumps.rs +++ b/src/systems/systems/src/hydraulic/pumps.rs @@ -137,12 +137,15 @@ impl PumpCharacteristics { )) } - pub fn cavitation_efficiency(&self, air_pressure: Pressure) -> Ratio { - Ratio::new::(interpolation( - &self.air_pressure_map_breakpoints_psi, - &self.cavitation_map_ratio, - air_pressure.get::(), - )) + pub fn cavitation_efficiency(&self, air_pressure: Pressure, heat_factor: Ratio) -> Ratio { + Ratio::new::( + (1. - heat_factor.get::()) + * interpolation( + &self.air_pressure_map_breakpoints_psi, + &self.cavitation_map_ratio, + air_pressure.get::(), + ), + ) } pub fn regulated_speed(&self) -> AngularVelocity { diff --git a/src/systems/systems/src/shared/mod.rs b/src/systems/systems/src/shared/mod.rs index a541bf3ef15..89d4f881b46 100644 --- a/src/systems/systems/src/shared/mod.rs +++ b/src/systems/systems/src/shared/mod.rs @@ -241,6 +241,60 @@ impl Display for HydraulicColor { } } +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum AirbusEngineDrivenPumpId { + Edp1a, + Edp1b, + Edp2a, + Edp2b, + Edp3a, + Edp3b, + Edp4a, + Edp4b, + Green, + Yellow, +} +impl Display for AirbusEngineDrivenPumpId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + AirbusEngineDrivenPumpId::Edp1a => write!(f, "GREEN_1A"), + AirbusEngineDrivenPumpId::Edp1b => write!(f, "GREEN_1B"), + AirbusEngineDrivenPumpId::Edp2a => write!(f, "GREEN_2A"), + AirbusEngineDrivenPumpId::Edp2b => write!(f, "GREEN_2B"), + AirbusEngineDrivenPumpId::Edp3a => write!(f, "YELLOW_3A"), + AirbusEngineDrivenPumpId::Edp3b => write!(f, "YELLOW_3B"), + AirbusEngineDrivenPumpId::Edp4a => write!(f, "YELLOW_4A"), + AirbusEngineDrivenPumpId::Edp4b => write!(f, "YELLOW_4B"), + AirbusEngineDrivenPumpId::Green => write!(f, "GREEN"), + AirbusEngineDrivenPumpId::Yellow => write!(f, "YELLOW"), + } + } +} + +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum AirbusElectricPumpId { + GreenA, + GreenB, + YellowA, + YellowB, + Green, + Blue, + Yellow, +} +impl Display for AirbusElectricPumpId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + AirbusElectricPumpId::GreenA => write!(f, "GA"), + AirbusElectricPumpId::YellowA => write!(f, "YA"), + AirbusElectricPumpId::GreenB => write!(f, "GB"), + AirbusElectricPumpId::YellowB => write!(f, "YB"), + AirbusElectricPumpId::Green => write!(f, "GREEN"), + AirbusElectricPumpId::Blue => write!(f, "BLUE"), + AirbusElectricPumpId::Yellow => write!(f, "YELLOW"), + } + } +} + /// The common types of electrical buses within Airbus aircraft. /// These include types such as AC, DC, AC ESS, etc. #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] From dae734104cdc4b5e0211f4e21f86ffe0c9b9d042 Mon Sep 17 00:00:00 2001 From: Frank Kopp Date: Wed, 28 Dec 2022 11:16:07 +0100 Subject: [PATCH 03/39] fix: Fixed additional issues which prevented ACE to work (#7668) --- .../FlyByWire_A320_Neo/CDU/A320_Neo_CDU_MainDisplay.js | 6 +++--- src/simbridge-client/src/components/McduServerClient.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/CDU/A320_Neo_CDU_MainDisplay.js b/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/CDU/A320_Neo_CDU_MainDisplay.js index 362c1cce19c..d5695e0cd16 100644 --- a/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/CDU/A320_Neo_CDU_MainDisplay.js +++ b/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/Airliners/FlyByWire_A320_Neo/CDU/A320_Neo_CDU_MainDisplay.js @@ -185,7 +185,7 @@ class A320_Neo_CDU_MainDisplay extends FMCMainDisplay { mcduServerClientEventHandler(event) { switch (event.type) { case 'open': { - console.log(`[MCDU] Websocket connection to SimBridge opened. (${SimBridgeClient.McduServerClient.url})`); + console.log(`[MCDU] Websocket connection to SimBridge opened. (${SimBridgeClient.McduServerClient.url()})`); (new NXNotifManager).showNotification({title: "MCDU CONNECTED", message: "A32NX MCDU successfully connected to SimBridge MCDU Server.", timeout: 5000}); this.sendToMcduServerClient("mcduConnected"); @@ -193,11 +193,11 @@ class A320_Neo_CDU_MainDisplay extends FMCMainDisplay { break; } case 'close': { - console.log(`[MCDU] Websocket connection to SimBridge closed. (${SimBridgeClient.McduServerClient.url})`); + console.log(`[MCDU] Websocket connection to SimBridge closed. (${SimBridgeClient.McduServerClient.url()})`); break; } case 'error': { - console.log(`[MCDU] Websocket connection to SimBridge error. (${SimBridgeClient.McduServerClient.url}): ${event.get()}`); + console.log(`[MCDU] Websocket connection to SimBridge error. (${SimBridgeClient.McduServerClient.url()}): ${event.get()}`); break; } case 'message': { diff --git a/src/simbridge-client/src/components/McduServerClient.ts b/src/simbridge-client/src/components/McduServerClient.ts index 0159467f23c..972fec7f39d 100644 --- a/src/simbridge-client/src/components/McduServerClient.ts +++ b/src/simbridge-client/src/components/McduServerClient.ts @@ -8,9 +8,9 @@ import { ClientState } from './ClientState'; * Class to communicate with the SimBridge MCDU server */ export class McduServerClient { - public static port = () => NXDataStore.get('CONFIG_SIMBRIDGE_PORT', '8380'); + public static port = ():string => NXDataStore.get('CONFIG_SIMBRIDGE_PORT', '8380'); - public static url: string = `ws://127.0.0.1:${this.port()}/interfaces/v1/mcdu`.replace(/\s+/g, ''); + public static url = ():string => `ws://127.0.0.1:${this.port()}/interfaces/v1/mcdu`.replace(/\s+/g, ''); private state: ClientState = ClientState.getInstance(); @@ -32,7 +32,7 @@ export class McduServerClient { this.disconnect(); // Connect web socket - this.socket = new WebSocket(McduServerClient.url); + this.socket = new WebSocket(McduServerClient.url()); // Setup up event handler from the caller if (eventHandler && typeof (eventHandler) === 'function') { From 248fe738379b84cac723cf654474e6b8708cb219 Mon Sep 17 00:00:00 2001 From: crocket63 <38904654+crocket63@users.noreply.github.com> Date: Thu, 29 Dec 2022 10:47:38 +0100 Subject: [PATCH 04/39] feat(hyd): changed gear lever mechanism / added gear door drag (#7390) --- .github/CHANGELOG.md | 1 + docs/a320-simvars.md | 12 ++ .../FlyByWire_A320_NEO/Checklist/Library.xml | 10 +- .../AirPlanes/FlyByWire_A320_NEO/Climb.flt | 1 + .../AirPlanes/FlyByWire_A320_NEO/approach.FLT | 1 + .../AirPlanes/FlyByWire_A320_NEO/apron.FLT | 1 + .../AirPlanes/FlyByWire_A320_NEO/cruise.FLT | 1 + .../AirPlanes/FlyByWire_A320_NEO/final.FLT | 1 + .../AirPlanes/FlyByWire_A320_NEO/hangar.flt | 1 + .../model/A320_NEO_INTERIOR.xml | 10 +- .../AirPlanes/FlyByWire_A320_NEO/runway.FLT | 1 + .../FlyByWire_A320_NEO/sound/sound.xml | 4 +- .../AirPlanes/FlyByWire_A320_NEO/taxi.flt | 1 + .../Pages/A32NX_Core/A32NX_BrakeTemp.js | 6 +- .../html_ui/Pages/A32NX_Core/A32NX_FWC.js | 2 +- .../Pages/A32NX_Core/A32NX_LocalVarUpdater.js | 2 +- .../NavSystems/A320_Neo/A32NX_NavSystem.js | 2 +- src/behavior/src/A32NX_Interior_Handling.xml | 41 +++++ src/behavior/src/A32NX_Interior_Misc.xml | 46 ------ .../src/EWD/elements/PseudoFWC.tsx | 2 +- src/systems/a320_systems/src/hydraulic/mod.rs | 3 +- src/systems/a320_systems_wasm/src/gear.rs | 49 ++++-- src/systems/systems/src/landing_gear/mod.rs | 155 ++++++++++++++---- 23 files changed, 237 insertions(+), 116 deletions(-) diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index 741d4e69d2b..7b02db9f3c3 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -71,6 +71,7 @@ 1. [FMGC] Fix inbound leg time for holds - @tracernz (Mike) 1. [MCDU] Improved visuals of Init-A and Init-B page - @derl30n (Leon) 1. [MODEL] Added new animated gear gravity extension handle- @tyler58546 (tyler58546), @MoreRightRudder (Mike), @Crocket63 (crocket), @Lantarius +1. [HYD] Custom Lvar for gear lever to fix ground collision bug - @Crocket63 (crocket) 1. [HYD] Randomised per actuator flow restrictions at plane init - @Crocket63 (crocket) 1. [MCDU] Hide stored elements on A/C Status when there are none - @tracernz (Mike) 1. [FMGC] Fix ident for CD legs - @tracernz (Mike) diff --git a/docs/a320-simvars.md b/docs/a320-simvars.md index 7350203f716..1c6449e4992 100644 --- a/docs/a320-simvars.md +++ b/docs/a320-simvars.md @@ -3240,6 +3240,18 @@ In the variables below, {number} should be replaced with one item in the set: { - Indicates the position of the gear emergency extension crank handle from 0 to 300 (3 turns) - Percent +- A32NX_GEAR_LEVER_POSITION_REQUEST + - Indicates that the pilot tries to move the gear lever (1=down) + - Boolean + +- A32NX_GEAR_HANDLE_POSITION + - Indicates the actual position of the gear handle + - Percent over 100 + +- A32NX_GEAR_HANDLE_HITS_LOCK_SOUND + - Indicates that gear lever just hit the baulk lock mechanism + - Boolean + ## ATC (ATA 34) - A32NX_TRANSPONDER_MODE diff --git a/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/Checklist/Library.xml b/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/Checklist/Library.xml index 0fcc7777f0a..fea5b3479fc 100644 --- a/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/Checklist/Library.xml +++ b/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/Checklist/Library.xml @@ -65,7 +65,7 @@ - + @@ -1150,7 +1150,7 @@ - + @@ -1641,7 +1641,7 @@ - + @@ -1841,7 +1841,7 @@ - + @@ -2381,7 +2381,7 @@ - + diff --git a/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/Climb.flt b/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/Climb.flt index fcba78061fd..db8f8a0d8cf 100644 --- a/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/Climb.flt +++ b/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/Climb.flt @@ -153,6 +153,7 @@ A32NX_SEC_2_PUSHBUTTON_PRESSED=1 A32NX_SEC_3_PUSHBUTTON_PRESSED=1 A32NX_FAC_1_PUSHBUTTON_PRESSED=1 A32NX_FAC_2_PUSHBUTTON_PRESSED=1 +A32NX_GEAR_LEVER_POSITION_REQUEST = 0 [Gauges.0] KollsmanSetting=29.921342849731445313 diff --git a/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/approach.FLT b/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/approach.FLT index d427ec43102..79c59a385ac 100644 --- a/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/approach.FLT +++ b/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/approach.FLT @@ -264,6 +264,7 @@ A32NX_OVHD_PRESS_MODE_SEL_PB_IS_AUTO = 1 A32NX_OVHD_PRESS_MAN_VS_CTL_SWITCH = 1 A32NX_TRANSPONDER_MODE = 1 A32NX_SWITCH_ATC_ALT = 1 +A32NX_GEAR_LEVER_POSITION_REQUEST = 0 [Gauges.0] KollsmanSetting=29.921342849731445313 diff --git a/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/apron.FLT b/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/apron.FLT index 6887dcdf667..d19ef1cb9e1 100644 --- a/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/apron.FLT +++ b/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/apron.FLT @@ -272,6 +272,7 @@ A32NX_SWITCH_ATC_ALT = 1 A32NX_GEAR_CENTER_POSITION = 100 A32NX_GEAR_LEFT_POSITION = 100 A32NX_GEAR_RIGHT_POSITION = 100 +A32NX_GEAR_LEVER_POSITION_REQUEST = 1 [Gauges.0] KollsmanSetting=29.921342849731445313 diff --git a/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/cruise.FLT b/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/cruise.FLT index 684182ff2f5..20127bdb3d2 100644 --- a/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/cruise.FLT +++ b/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/cruise.FLT @@ -264,6 +264,7 @@ A32NX_OVHD_PRESS_MODE_SEL_PB_IS_AUTO = 1 A32NX_OVHD_PRESS_MAN_VS_CTL_SWITCH = 1 A32NX_TRANSPONDER_MODE = 1 A32NX_SWITCH_ATC_ALT = 1 +A32NX_GEAR_LEVER_POSITION_REQUEST = 0 [Gauges.0] KollsmanSetting=29.921342849731445313 diff --git a/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/final.FLT b/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/final.FLT index 7381cdba7d2..6fd82ea5fe1 100644 --- a/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/final.FLT +++ b/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/final.FLT @@ -266,6 +266,7 @@ A32NX_SWITCH_ATC_ALT = 1 A32NX_GEAR_CENTER_POSITION = 100 A32NX_GEAR_LEFT_POSITION = 100 A32NX_GEAR_RIGHT_POSITION = 100 +A32NX_GEAR_LEVER_POSITION_REQUEST = 1 [Gauges.0] KollsmanSetting=29.921342849731445313 diff --git a/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/hangar.flt b/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/hangar.flt index 95c1f41f7d7..47cf0077888 100644 --- a/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/hangar.flt +++ b/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/hangar.flt @@ -246,6 +246,7 @@ XMLVAR_A320_WeatherRadar_Sys=1 A32NX_GEAR_CENTER_POSITION = 100 A32NX_GEAR_LEFT_POSITION = 100 A32NX_GEAR_RIGHT_POSITION = 100 +A32NX_GEAR_LEVER_POSITION_REQUEST = 1 [Gauges.0] KollsmanSetting=29.921342849731445313 diff --git a/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/model/A320_NEO_INTERIOR.xml b/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/model/A320_NEO_INTERIOR.xml index 7b68f0dff02..f41259f2fd7 100644 --- a/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/model/A320_NEO_INTERIOR.xml +++ b/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/model/A320_NEO_INTERIOR.xml @@ -840,12 +840,12 @@ %((L:A32NX_BRAKE_FAN_BTN_PRESSED, Bool))%{if}Turn OFF brake fan%{else}Turn ON brake fan%{end} - + lever_landing_gear LEVER_LANDINGGEAR - gearleverclick - + 3 + PUSH_AUTOBKR_LDGGEAR_1 1 @@ -1777,7 +1777,7 @@ 5 - (A:GEAR HANDLE POSITION, Bool) (A:GEAR POSITION, percent) 99.9 > and (>O:_ShouldBeConnectedToPowerGrid) + (L:A32NX_LGCIU_2_NOSE_GEAR_DOWNLOCKED, Bool) 1 == (>O:_ShouldBeConnectedToPowerGrid) (O:_ShouldBeConnectedToPowerGrid) sp0 2 (>A:BUS LOOKUP INDEX, Number) (A:CIRCUIT CONNECTION ON:17, Bool) l0 != if{ 17 2 (>K:2:ELECTRICAL_BUS_TO_CIRCUIT_CONNECTION_TOGGLE) } @@ -1833,7 +1833,7 @@ - (A:GEAR CENTER POSITION, Percent over 100) 1 == (L:A32NX_PARK_BRAKE_LEVER_POS, bool) 1 == and + (L:A32NX_GEAR_CENTER_POSITION, Percent over 100) 1 == (L:A32NX_PARK_BRAKE_LEVER_POS, bool) 1 == and (L:A32NX_ELEC_DC_GND_FLT_SVC_BUS_IS_POWERED, Bool) 99 diff --git a/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/runway.FLT b/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/runway.FLT index cd993124da1..77863930792 100644 --- a/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/runway.FLT +++ b/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/runway.FLT @@ -274,6 +274,7 @@ A32NX_SWITCH_ATC_ALT = 1 A32NX_GEAR_CENTER_POSITION = 100 A32NX_GEAR_LEFT_POSITION = 100 A32NX_GEAR_RIGHT_POSITION = 100 +A32NX_GEAR_LEVER_POSITION_REQUEST = 1 [Gauges.0] KollsmanSetting=29.921342849731445313 diff --git a/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/sound/sound.xml b/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/sound/sound.xml index 986244a9301..815094c5623 100644 --- a/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/sound/sound.xml +++ b/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/sound/sound.xml @@ -642,11 +642,11 @@ - + - + diff --git a/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/taxi.flt b/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/taxi.flt index cc5788288a6..76bf3570d5e 100644 --- a/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/taxi.flt +++ b/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/taxi.flt @@ -257,6 +257,7 @@ A32NX_SWITCH_ATC_ALT = 1 A32NX_GEAR_CENTER_POSITION = 100 A32NX_GEAR_LEFT_POSITION = 100 A32NX_GEAR_RIGHT_POSITION = 100 +A32NX_GEAR_LEVER_POSITION_REQUEST = 1 [Gauges.0] KollsmanSetting=29.921342849731445313 diff --git a/flybywire-aircraft-a320-neo/html_ui/Pages/A32NX_Core/A32NX_BrakeTemp.js b/flybywire-aircraft-a320-neo/html_ui/Pages/A32NX_Core/A32NX_BrakeTemp.js index 8e8aca62c1a..3dc049e4d03 100644 --- a/flybywire-aircraft-a320-neo/html_ui/Pages/A32NX_Core/A32NX_BrakeTemp.js +++ b/flybywire-aircraft-a320-neo/html_ui/Pages/A32NX_Core/A32NX_BrakeTemp.js @@ -82,13 +82,13 @@ class A32NX_BrakeTemp { SimVar.GetSimVarValue("L:A32NX_REPORTED_BRAKE_TEMPERATURE_4", "celsius") ]; } - const GearLeftPosition = SimVar.GetSimVarValue("GEAR LEFT POSITION", "Percent Over 100"); + const GearLeftPosition = SimVar.GetSimVarValue("L:A32NX_GEAR_LEFT_POSITION", "Percent Over 100"); const GearLeftExtended = GearLeftPosition >= 0.25; - const GearRightExtended = SimVar.GetSimVarValue("GEAR RIGHT POSITION", "Percent Over 100") >= 0.25; + const GearRightExtended = SimVar.GetSimVarValue("L:A32NX_GEAR_RIGHT_POSITION", "Percent Over 100") >= 0.25; const currentBrakeFanState = SimVar.GetSimVarValue("L:A32NX_BRAKE_FAN", "Bool"); const brakeFanButtonIsPressed = SimVar.GetSimVarValue("L:A32NX_BRAKE_FAN_BTN_PRESSED", "Bool"); // if the fan button is pressed down and the left main gear is down and locked, the fan is on - const brakeFanIsOn = brakeFanButtonIsPressed && (GearLeftPosition == 1); + const brakeFanIsOn = brakeFanButtonIsPressed && (GearLeftPosition == 100); let fanMultiplier = 1; let fanDifferentialFactor = 1; if (brakeFanIsOn) { diff --git a/flybywire-aircraft-a320-neo/html_ui/Pages/A32NX_Core/A32NX_FWC.js b/flybywire-aircraft-a320-neo/html_ui/Pages/A32NX_Core/A32NX_FWC.js index 975e444ac03..ddb8b2fe63a 100644 --- a/flybywire-aircraft-a320-neo/html_ui/Pages/A32NX_Core/A32NX_FWC.js +++ b/flybywire-aircraft-a320-neo/html_ui/Pages/A32NX_Core/A32NX_FWC.js @@ -367,7 +367,7 @@ class A32NX_FWC { // - Glide slope captured // - Landing locked down - const landingGearIsDown = SimVar.GetSimVarValue("L:A32NX_FLAPS_HANDLE_INDEX", "Enum") >= 1 && SimVar.GetSimVarValue("GEAR HANDLE POSITION", "Boolean"); + const landingGearIsDown = SimVar.GetSimVarValue("L:A32NX_FLAPS_HANDLE_INDEX", "Enum") >= 1 && SimVar.GetSimVarValue("L:A32NX_GEAR_HANDLE_POSITION", "Percent over 100") > 0.5; const verticalMode = SimVar.GetSimVarValue("L:A32NX_FMA_VERTICAL_MODE", "Number"); const glideSlopeCaptured = verticalMode >= 30 && verticalMode <= 34; const landingGearIsLockedDown = SimVar.GetSimVarValue("GEAR POSITION:0", "Enum") > 0.9; diff --git a/flybywire-aircraft-a320-neo/html_ui/Pages/A32NX_Core/A32NX_LocalVarUpdater.js b/flybywire-aircraft-a320-neo/html_ui/Pages/A32NX_Core/A32NX_LocalVarUpdater.js index 7be23073f2b..c3386c7ab73 100644 --- a/flybywire-aircraft-a320-neo/html_ui/Pages/A32NX_Core/A32NX_LocalVarUpdater.js +++ b/flybywire-aircraft-a320-neo/html_ui/Pages/A32NX_Core/A32NX_LocalVarUpdater.js @@ -65,7 +65,7 @@ class A32NX_LocalVarUpdater { } _noSmokingMemoSelector() { - const gearPercent = SimVar.GetSimVarValue("GEAR CENTER POSITION", "Percent"); + const gearPercent = SimVar.GetSimVarValue("L:A32NX_GEAR_CENTER_POSITION", "Percent"); const noSmokingSwitch = SimVar.GetSimVarValue("L:XMLVAR_SWITCH_OVHD_INTLT_NOSMOKING_Position", "Position"); // Switch is ON diff --git a/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/NavSystems/A320_Neo/A32NX_NavSystem.js b/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/NavSystems/A320_Neo/A32NX_NavSystem.js index 93bca47db7e..73e07f550a5 100644 --- a/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/NavSystems/A320_Neo/A32NX_NavSystem.js +++ b/flybywire-aircraft-a320-neo/html_ui/Pages/VCockpit/Instruments/NavSystems/A320_Neo/A32NX_NavSystem.js @@ -2824,7 +2824,7 @@ class Warnings extends NavSystemElement { return this.linearMultiPointsEvaluation(this.pullUp_sinkRate_Points, descentRate, height) == 2; } landingGearCallback() { - const gear = !SimVar.GetSimVarValue("IS GEAR RETRACTABLE", "Boolean") || SimVar.GetSimVarValue("GEAR HANDLE POSITION", "Boolean"); + const gear = !SimVar.GetSimVarValue("IS GEAR RETRACTABLE", "Boolean") || SimVar.GetSimVarValue("L:A32NX_GEAR_HANDLE_POSITION", "Percent over 100") > 0.5; const throttle = SimVar.GetSimVarValue("L:A32NX_AUTOTHRUST_TLA:1", "number"); const flaps = SimVar.GetSimVarValue("L:A32NX_FLAPS_HANDLE_INDEX", "number"); return !gear && (flaps > 1 || (throttle == 0)); diff --git a/src/behavior/src/A32NX_Interior_Handling.xml b/src/behavior/src/A32NX_Interior_Handling.xml index 59f42599835..004d54bf8ea 100644 --- a/src/behavior/src/A32NX_Interior_Handling.xml +++ b/src/behavior/src/A32NX_Interior_Handling.xml @@ -542,6 +542,47 @@ + + + - - + + + + + @@ -301,9 +305,10 @@ let modeId = #MODE_ID, number#; alias toggleSwitch = (L:A32NX_RMP_#SIDE#_TOGGLE_SWITCH, bool); alias selectedMode = (L:A32NX_RMP_#SIDE#_SELECTED_MODE, number); + alias navButtonPressed = (L:A32NX_RMP_#SIDE#_NAV_BUTTON_SELECTED, bool); alias annunciatorLight = (L:A32NX_OVHD_INTLT_ANN, number); let emissiveDim = if annunciatorLight == 2 { 0.05 } else { 1 }; - (if ((!inop and toggleSwitch and (selectedMode == modeId)) or (annunciatorLight == 0)) and indicatorsPowered { + (if ((!inop and toggleSwitch and ((selectedMode == modeId) or (modeId == 12 and navButtonPressed))) or (annunciatorLight == 0)) and indicatorsPowered { 1 * emissiveDim } else { 0 diff --git a/src/fmgc/src/radionav/NavRadioManager.ts b/src/fmgc/src/radionav/NavRadioManager.ts index f3cc3cc22f0..60ae4b15763 100644 --- a/src/fmgc/src/radionav/NavRadioManager.ts +++ b/src/fmgc/src/radionav/NavRadioManager.ts @@ -8,19 +8,40 @@ export enum TuningMode { * This is a placeholder for the new radio nav tuning logic... coming soon to an A32NX near you */ export class NavRadioManager { - tuningMode1: TuningMode = TuningMode.Auto; + tuningMode: TuningMode = TuningMode.Auto; - tuningMode2: TuningMode = TuningMode.Auto; + manualTuned: boolean; - tuningMode3: TuningMode = TuningMode.Auto; + rmpTuned: boolean; constructor(public _parentInstrument: BaseInstrument) { - SimVar.SetSimVarValue('L:A32NX_FMGC_RADIONAV_1_TUNING_MODE', 'Enum', TuningMode.Manual); - SimVar.SetSimVarValue('L:A32NX_FMGC_RADIONAV_2_TUNING_MODE', 'Enum', TuningMode.Manual); - SimVar.SetSimVarValue('L:A32NX_FMGC_RADIONAV_3_TUNING_MODE', 'Enum', TuningMode.Manual); + SimVar.SetSimVarValue('L:A32NX_FMGC_RADIONAV_TUNING_MODE', 'Enum', TuningMode.Auto); } - update(_: number): void { - // Do nothing + public update(deltaTime: number, manualTuned: boolean, rmpTuned: boolean): void { + if (this.manualTuned !== manualTuned || this.rmpTuned !== rmpTuned) { + // too avoid SetSimVar too often + this.manualTuned = manualTuned; + this.rmpTuned = rmpTuned; + + if (manualTuned) { + this.tuningMode = TuningMode.Manual; + } else if (rmpTuned) { + this.tuningMode = TuningMode.Remote; + } else { + if (this.tuningMode === TuningMode.Remote) { + // Happens when NAV push button is pushed back + // It resets all the frequencies (real life behavior) + SimVar.SetSimVarValue('K:ADF_ACTIVE_SET', 'Frequency ADF BCD32', 0); + SimVar.SetSimVarValue('K:ADF2_ACTIVE_SET', 'Frequency ADF BCD32', 0); + SimVar.SetSimVarValue('K:NAV1_RADIO_SET_HZ', 'Hz', 0); + SimVar.SetSimVarValue('K:NAV2_RADIO_SET_HZ', 'Hz', 0); + SimVar.SetSimVarValue('K:NAV3_RADIO_SET_HZ', 'Hz', 0); + } + + this.tuningMode = TuningMode.Auto; + } + SimVar.SetSimVarValue('L:A32NX_FMGC_RADIONAV_TUNING_MODE', 'Enum', this.tuningMode); + } } } diff --git a/src/instruments/src/ND/elements/RadioNavInfo.tsx b/src/instruments/src/ND/elements/RadioNavInfo.tsx index 31439bcd2bc..470be92d558 100644 --- a/src/instruments/src/ND/elements/RadioNavInfo.tsx +++ b/src/instruments/src/ND/elements/RadioNavInfo.tsx @@ -11,11 +11,11 @@ export enum NavAidMode { export type RadioNavInfoProps = { index: 1 | 2, side: EfisSide } -const TuningModeIndicator: React.FC<{ index: 1 | 2, frequency: number }> = ({ index, frequency }) => { - const [tuningMode] = useSimVar(`L:A32NX_FMGC_RADIONAV_${index}_TUNING_MODE`, 'enum'); +const TuningModeIndicator: React.FC<{ index: 1 | 2 }> = ({ index }) => { + const [tuningMode] = useSimVar('L:A32NX_FMGC_RADIONAV_TUNING_MODE', 'enum'); return ( - frequency > 1 && tuningMode !== TuningMode.Auto && ( + tuningMode !== TuningMode.Auto && ( {tuningMode === TuningMode.Manual ? 'M' : 'R'} ) || null ); @@ -81,7 +81,7 @@ const VorInfo: React.FC<{index: 1 | 2}> = ({ index }) => { 20 ? x + 46 : x + 58} y={759} fontSize={24} fill="#00ff00" textAnchor="end">{dmeText} NM - + ); }; @@ -108,14 +108,13 @@ const AdfInfo: React.FC<{index: 1 | 2}> = ({ index }) => { ADF {index} - {adfAvailable ? adfIdent : adfFrequency.toFixed(0)} {adfAvailable && ( {adfIdent} )} - {!adfAvailable && ( + {!adfAvailable && adfFrequency > 0 && ( {Math.floor(adfFrequency).toFixed(0)} )} - + ); }; diff --git a/src/instruments/src/ND/pages/RoseMode.tsx b/src/instruments/src/ND/pages/RoseMode.tsx index cda40cec103..d1e28ac063f 100644 --- a/src/instruments/src/ND/pages/RoseMode.tsx +++ b/src/instruments/src/ND/pages/RoseMode.tsx @@ -778,7 +778,7 @@ const VorInfo: FC<{side: EfisSide}> = memo(({ side }) => { const [vorIdent] = useSimVar(`NAV IDENT:${index}`, 'string'); const [vorFrequency] = useSimVar(`NAV ACTIVE FREQUENCY:${index}`, 'megahertz'); const [vorCourse] = useSimVar(`NAV OBS:${index}`, 'degrees'); - const [tuningMode] = useSimVar(`L:A32NX_FMGC_RADIONAV_${index}_TUNING_MODE`, 'enum'); + const [tuningMode] = useSimVar('L:A32NX_FMGC_RADIONAV_TUNING_MODE', 'enum'); const [vorAvailable] = useSimVar(`NAV HAS NAV:${index}`, 'boolean'); const [freqInt, freqDecimal] = vorFrequency.toFixed(2).split('.', 2); @@ -808,7 +808,7 @@ const VorInfo: FC<{side: EfisSide}> = memo(({ side }) => { {vorCourse >= 0 ? (`${Math.round(vorCourse)}`).padStart(3, '0') : '---'} ° - { vorFrequency > 0 && {tuningModeLabel} } + {tuningModeLabel} {vorIdent} ); @@ -818,7 +818,7 @@ const IlsInfo: FC = memo(() => { const [ilsIdent] = useSimVar('NAV IDENT:3', 'string'); const [ilsFrequency] = useSimVar('NAV ACTIVE FREQUENCY:3', 'megahertz'); const [ilsCourse] = useSimVar('NAV LOCALIZER:3', 'degrees'); - const [tuningMode] = useSimVar('L:A32NX_FMGC_RADIONAV_3_TUNING_MODE', 'enum'); + const [tuningMode] = useSimVar('L:A32NX_FMGC_RADIONAV_TUNING_MODE', 'enum'); const [locAvailable] = useSimVar('L:A32NX_RADIO_RECEIVER_LOC_IS_VALID', 'number'); const [freqInt, freqDecimal] = ilsFrequency.toFixed(2).split('.', 2); @@ -845,7 +845,7 @@ const IlsInfo: FC = memo(() => { {locAvailable ? (`${Math.round(ilsCourse)}`).padStart(3, '0') : '---'} ° - { ilsFrequency > 0 && {tuningModeLabel} } + {tuningModeLabel} {ilsIdent} ); diff --git a/src/instruments/src/PFD/HeadingIndicator.tsx b/src/instruments/src/PFD/HeadingIndicator.tsx index f7d00bf78c5..5b6c9df264e 100644 --- a/src/instruments/src/PFD/HeadingIndicator.tsx +++ b/src/instruments/src/PFD/HeadingIndicator.tsx @@ -312,7 +312,8 @@ class QFUIndicator extends DisplayComponent<{ ILSCourse: Subscribable, h this.props.lsPressed.sub((ls) => { this.lsPressed = ls; - if (ls) { + // ilsCourse may be negative if tuned via the RMP then back to MCDU + if (ls && this.ilsCourse >= 0) { this.qfuContainer.instance.classList.remove('HiddenElement'); } else { this.qfuContainer.instance.classList.add('HiddenElement'); diff --git a/src/instruments/src/PFD/LandingSystemIndicator.tsx b/src/instruments/src/PFD/LandingSystemIndicator.tsx index 96c87d480d7..8aa7028d81c 100644 --- a/src/instruments/src/PFD/LandingSystemIndicator.tsx +++ b/src/instruments/src/PFD/LandingSystemIndicator.tsx @@ -118,6 +118,8 @@ class LandingSystemInfo extends DisplayComponent<{ bus: EventBus }> { private dme = 0; + private rmpTuned = false; + private dmeVisibilitySub = Subject.create('hidden'); private destRef = FSComponent.createRef(); @@ -157,6 +159,11 @@ class LandingSystemInfo extends DisplayComponent<{ bus: EventBus }> { this.dme = dme; this.updateContents(); }); + + sub.on('ilsRMPTuned').whenChanged().handle((rmpTuned) => { + this.rmpTuned = rmpTuned; + this.updateContents(); + }); } private updateContents() { @@ -170,7 +177,7 @@ class LandingSystemInfo extends DisplayComponent<{ bus: EventBus }> { let distLeading = ''; let distTrailing = ''; - if (this.hasDme) { + if (this.hasDme && !this.rmpTuned) { this.dmeVisibilitySub.set('display: inline'); const dist = Math.round(this.dme * 10) / 10; diff --git a/src/instruments/src/PFD/instrument.tsx b/src/instruments/src/PFD/instrument.tsx index 4fe0a880975..ebb0e90d689 100644 --- a/src/instruments/src/PFD/instrument.tsx +++ b/src/instruments/src/PFD/instrument.tsx @@ -133,6 +133,7 @@ class A32NX_PFD extends BaseInstrument { this.simVarPublisher.subscribe('selectedFpa'); this.simVarPublisher.subscribe('targetSpeedManaged'); this.simVarPublisher.subscribe('ilsCourse'); + this.simVarPublisher.subscribe('ilsRMPTuned'); this.simVarPublisher.subscribe('tla1'); this.simVarPublisher.subscribe('tla2'); this.simVarPublisher.subscribe('metricAltToggle'); diff --git a/src/instruments/src/PFD/shared/PFDSimvarPublisher.tsx b/src/instruments/src/PFD/shared/PFDSimvarPublisher.tsx index 356c160789d..97513bf9251 100644 --- a/src/instruments/src/PFD/shared/PFDSimvarPublisher.tsx +++ b/src/instruments/src/PFD/shared/PFDSimvarPublisher.tsx @@ -68,6 +68,7 @@ export interface PFDSimvars { groundTrackTrue: number; selectedFpa: number; ilsCourse: number; + ilsRMPTuned: boolean; metricAltToggle: boolean; tla1: number; tla2: number; @@ -214,6 +215,7 @@ export enum PFDVars { groundTrackTrue = 'GPS GROUND TRUE TRACK', selectedFpa = 'L:A32NX_AUTOPILOT_FPA_SELECTED', ilsCourse = 'L:A32NX_FM_LS_COURSE', + ilsRMPTuned = 'L:A32NX_RMP_ILS_TUNED', metricAltToggle = 'L:A32NX_METRIC_ALT_TOGGLE', tla1='L:A32NX_AUTOTHRUST_TLA:1', tla2='L:A32NX_AUTOTHRUST_TLA:2', @@ -361,6 +363,7 @@ export class PFDSimvarPublisher extends SimVarPublisher { ['groundTrackTrue', { name: PFDVars.groundTrackTrue, type: SimVarValueType.Degree }], ['selectedFpa', { name: PFDVars.selectedFpa, type: SimVarValueType.Degree }], ['ilsCourse', { name: PFDVars.ilsCourse, type: SimVarValueType.Number }], + ['ilsRMPTuned', { name: PFDVars.ilsRMPTuned, type: SimVarValueType.Bool }], ['metricAltToggle', { name: PFDVars.metricAltToggle, type: SimVarValueType.Bool }], ['tla1', { name: PFDVars.tla1, type: SimVarValueType.Number }], ['tla2', { name: PFDVars.tla2, type: SimVarValueType.Number }], diff --git a/src/instruments/src/RMP/Components/BaseRadioPanels.tsx b/src/instruments/src/RMP/Components/BaseRadioPanels.tsx index 7037175bd05..c9860e88961 100644 --- a/src/instruments/src/RMP/Components/BaseRadioPanels.tsx +++ b/src/instruments/src/RMP/Components/BaseRadioPanels.tsx @@ -1,7 +1,9 @@ -import React from 'react'; +import React, { useState } from 'react'; import { useSimVar, useInteractionSimVar } from '@instruments/common/simVars'; import { useInteractionEvent } from '@instruments/common/hooks'; +import { TransceiverType } from './StandbyFrequency'; import { VhfRadioPanel } from './VhfRadioPanel'; +import { NavRadioPanel } from './NavRadioPanel'; import { RadioPanelDisplay } from './RadioPanelDisplay'; interface Props { @@ -44,21 +46,90 @@ const UnpoweredRadioPanel = () => ( * Renders appropriate mode sub-component (e.g. VhfRadioPanel). */ const PoweredRadioPanel = (props: Props) => { + const [navTransceiverType, setNavTransceiverType] = useState(TransceiverType.RADIO_VHF); + + // Used to turn on the associated led const [panelMode, setPanelMode] = useSimVar(`L:A32NX_RMP_${props.side}_SELECTED_MODE`, 'Number', 250); + // Used to determine (in the FGMC for instance) if the system is in NAV backup mode. L and R simvars have to be checked + const [navButtonPressed, setNavButton] = useSimVar(`L:A32NX_RMP_${props.side}_NAV_BUTTON_SELECTED`, 'boolean', 250); + // Used to return to the selected VHF once NAV is pushed again + const [previousPanelMode, setPreviousPanelMode] = useState(panelMode); // Hook radio management panel mode buttons to set panelMode SimVar. - useInteractionEvent(`A32NX_RMP_${props.side}_VHF1_BUTTON_PRESSED`, () => setPanelMode(1)); - useInteractionEvent(`A32NX_RMP_${props.side}_VHF2_BUTTON_PRESSED`, () => setPanelMode(2)); - useInteractionEvent(`A32NX_RMP_${props.side}_VHF3_BUTTON_PRESSED`, () => setPanelMode(3)); + useInteractionEvent(`A32NX_RMP_${props.side}_VHF1_BUTTON_PRESSED`, () => { + setPanelMode(1); + setPreviousPanelMode(1); + setNavTransceiverType(TransceiverType.RADIO_VHF); + }); + + useInteractionEvent(`A32NX_RMP_${props.side}_VHF2_BUTTON_PRESSED`, () => { + setPanelMode(2); + setPreviousPanelMode(2); + setNavTransceiverType(TransceiverType.RADIO_VHF); + }); + + useInteractionEvent(`A32NX_RMP_${props.side}_VHF3_BUTTON_PRESSED`, () => { + setPanelMode(3); + setPreviousPanelMode(3); + setNavTransceiverType(TransceiverType.RADIO_VHF); + }); + + useInteractionEvent(`A32NX_RMP_${props.side}_NAV_BUTTON_PRESSED`, () => { + if (navButtonPressed) { + setPanelMode(previousPanelMode); + setNavTransceiverType(TransceiverType.RADIO_VHF); + } + + setNavButton(!navButtonPressed); + }); + + useInteractionEvent(`A32NX_RMP_${props.side}_VOR_BUTTON_PRESSED`, () => { + if (navButtonPressed) { + setPanelMode(6); + setNavTransceiverType(TransceiverType.VOR); + } + }); + + useInteractionEvent(`A32NX_RMP_${props.side}_ILS_BUTTON_PRESSED`, () => { + if (navButtonPressed) { + setPanelMode(7); + setNavTransceiverType(TransceiverType.ILS); + } + }); + + /** + * MLS IMPLEMENTED IN THE XML BEHAVIOURS + * BUT DISABLED HERE SINCE THERE IS NOT ENOUGH REFERENCES + */ + // useInteractionEvent(`A32NX_RMP_${props.side}_MLS_BUTTON_PRESSED`, () => { + // if (navButtonPressed) { + // setPanelMode(8); + // setNavTransceiverType(TransceiverType.ILS); + // } + // }); + + useInteractionEvent(`A32NX_RMP_${props.side}_ADF_BUTTON_PRESSED`, () => { + if (navButtonPressed) { + setPanelMode(9); + setNavTransceiverType(TransceiverType.ADF); + } + }); // This means we're in a VHF communications mode. - if (panelMode === 1 || panelMode === 2 || panelMode === 3) return (); - - // If we reach this block, something's gone wrong. We'll just render a broken panel. - return ( - - - - - ); + switch (navTransceiverType) { + case TransceiverType.RADIO_VHF: + return (); + case TransceiverType.VOR: + case TransceiverType.ILS: + case TransceiverType.ADF: + return (); + default: + // If we reach this block, something's gone wrong. We'll just render a broken panel. + return ( + + + + + ); + } }; diff --git a/src/instruments/src/RMP/Components/NavRadioPanel.tsx b/src/instruments/src/RMP/Components/NavRadioPanel.tsx new file mode 100644 index 00000000000..b6351eda774 --- /dev/null +++ b/src/instruments/src/RMP/Components/NavRadioPanel.tsx @@ -0,0 +1,163 @@ +import React, { useEffect, useState } from 'react'; + +import { StandbyFrequency, TransceiverType } from './StandbyFrequency'; +import { StandbyCourse } from './StandbyCourse'; +import { useSimVar } from '../../Common/simVars'; +import { RadioPanelDisplay } from './RadioPanelDisplay'; +import { useInteractionEvent } from '../../Common/hooks'; + +interface Props { + /** + * The RMP side (e.g. 'L' or 'R'). + */ + side: string, + + /** + * The NAV transceiver (VOR, ILS, ADF). + */ + transceiver: number, + +} + +enum Mode { + FREQUENCY = 0, + COURSE = 1 +} + +/* +* Had to use this simvars to save the frequencies set via the RMP +* In real life, if you tune a navaid via the MCDU and then press NAV, the frequency is not the same +/ + +/** + * + * @param transceiver The transceiver type (VOR, ADF or ILS) + * @param side Side on which the transceiver is (L or R) + * @returns a tuble simvar + */ +const useActiveFrequency = (transceiver: number, side: string) => { + switch (transceiver) { + case TransceiverType.VOR: + return useSimVar(`L:A32NX_RMP_${side}_SAVED_ACTIVE_FREQUENCY_VOR`, 'number'); + case TransceiverType.ADF: + return useSimVar(`L:A32NX_RMP_${side}_SAVED_ACTIVE_FREQUENCY_ADF`, 'number'); + default: + return useSimVar(`L:A32NX_RMP_${side}_SAVED_ACTIVE_FREQUENCY_ILS`, 'number'); + } +}; + +/** + * + * @param transceiver The transceiver type (VOR, ADF or ILS) + * @param side Side on which the transceiver is (L or R) + * @returns a tuble simvar + */ +const useStandbyFrequency = (transceiver: number, side: string) => { + switch (transceiver) { + case TransceiverType.VOR: + return useSimVar(`L:A32NX_RMP_${side}_SAVED_STANDBY_FREQUENCY_VOR`, 'number'); + case TransceiverType.ADF: + return useSimVar(`L:A32NX_RMP_${side}_SAVED_STANDBY_FREQUENCY_ADF`, 'number'); + default: + return useSimVar(`L:A32NX_RMP_${side}_SAVED_STANDBY_FREQUENCY_ILS`, 'number'); + } +}; + +/** + * + * @param transceiver The transceiver type (VOR, ADF or ILS) + * @param side Side on which the transceiver is (L or R) + * @returns a tuble simvar + */ +const useCourse = (transceiver: number, side: string) => { + switch (transceiver) { + case TransceiverType.VOR: + return useSimVar(`L:A32NX_RMP_${side}_SAVED_COURSE_VOR`, 'number'); + default: + return useSimVar(`L:A32NX_RMP_${side}_SAVED_COURSE_ILS`, 'number'); + } +}; + +const setActiveFrequencySimVar = (transceiver: number, index: number, frequency: number) => { + if (transceiver === TransceiverType.ADF) { + SimVar.SetSimVarValue(`K:ADF${index === 1 ? '' : index}_ACTIVE_SET`, 'Frequency ADF BCD32', Avionics.Utils.make_adf_bcd32(frequency)); + } + + SimVar.SetSimVarValue(`K:NAV${index}_RADIO_SET_HZ`, 'Hz', frequency); +}; + +/** + * NAV radio management panel React component. + * Hooks into the mode active and standby frequency SimVars and wires transfer button. + * Renders active frequency RadioPanelDisplay and appropriate StandbyFrequency sub-components. + */ +export const NavRadioPanel = (props: Props) => { + let standbyWindow: JSX.Element; + + let index = props.side === 'L' ? 1 : 2; + if (props.transceiver === TransceiverType.ILS) { + index = 3; // Both RMPs manage the same ILS + } + + const [mode, setMode] = useState(Mode.FREQUENCY); + + const [activeFrequency, setActiveFrequencySaved] = useActiveFrequency(props.transceiver, props.side); + const [standbyFrequency, setStandbyFrequencySaved] = useStandbyFrequency(props.transceiver, props.side); + const [course, setCourseSaved] = useCourse(props.transceiver, props.side); + + const [, setCourse] = useSimVar(props.transceiver === TransceiverType.VOR ? `K:VOR${index}_SET` : 'L:A32NX_FM_LS_COURSE', 'number', 100); + + const [APPR] = useSimVar('L:A32NX_FCU_APPR_MODE_ACTIVE', 'bool'); + const [AP] = useSimVar('L:A32NX_AUTOPILOT_ACTIVE', 'bool'); + const [RA1] = useSimVar('L:A32NX_RA_1_RADIO_ALTITUDE', 'number'); + const [RA2] = useSimVar('L:A32NX_RA_2_RADIO_ALTITUDE', 'number'); + + useInteractionEvent(`A32NX_RMP_${props.side}_TRANSFER_BUTTON_PRESSED`, () => { + // Inhibit RMP tuning if below 700 RA, APPR engaged, at least one AP/FD engaged (FCOM compliant) + if ((RA1 >= 700 && RA2 >= 700) || !APPR || !AP) { + if (mode === Mode.FREQUENCY) { + if (props.transceiver !== TransceiverType.ADF) { + setMode(Mode.COURSE); + } + + // FCOM compliant: Both RMPs must be in nav backup mode in order to tune the ILS + if (props.transceiver !== TransceiverType.ILS + || (SimVar.GetSimVarValue('L:A32NX_RMP_L_NAV_BUTTON_SELECTED', 'Bool') + && SimVar.GetSimVarValue('L:A32NX_RMP_R_NAV_BUTTON_SELECTED', 'Bool'))) { + setActiveFrequencySimVar(props.transceiver, index, standbyFrequency); + } + setActiveFrequencySaved(standbyFrequency); + + if (props.transceiver === TransceiverType.ILS) { + SimVar.SetSimVarValue('L:A32NX_RMP_ILS_TUNED', 'boolean', true); + } + } else { + setCourse(course); + setMode(Mode.FREQUENCY); + } + } + }); + + // This effect to display frequency mode instead of course mode when switching between receivers. + // After few debug sessions, it was noticed standbyFrequency was the first valuable sign of switch. + // I could have listened props.transceiver but this caused flickering (very fast display of previous frequency) due to sequential render + useEffect(() => { + // Performance purpose. Could set Frequency everytime but setMode fires a render + if (mode === Mode.COURSE) { + setMode(Mode.FREQUENCY); + } + }, [standbyFrequency]); + + if (mode === Mode.FREQUENCY) { + standbyWindow = ; + } else { + standbyWindow = ; + } + + return ( + + + {standbyWindow} + + ); +}; diff --git a/src/instruments/src/RMP/Components/RadioPanelDisplay.tsx b/src/instruments/src/RMP/Components/RadioPanelDisplay.tsx index a2ada050a57..e44f5be801a 100644 --- a/src/instruments/src/RMP/Components/RadioPanelDisplay.tsx +++ b/src/instruments/src/RMP/Components/RadioPanelDisplay.tsx @@ -15,7 +15,17 @@ const TEXT_DATA_MODE_VHF3 = 'DATA'; * @param frequency The given frequency number in Hz. * @returns The formated frequency string in 123.456 */ -const formatFrequency = (frequency: number): string => (frequency / 1000000).toFixed(3).padEnd(7, '0'); +const formatFrequency = (frequency: number): string => { + // VHF COM, VOR, ILS + if (frequency >= 108000000) { + return (frequency / 1000000).toFixed(3).padEnd(7, '0'); + } + + // HF HERE + + // ADF + return (frequency / 1000).toFixed(1); +}; /** * Radio management panel seven-segment frequency/course display. @@ -33,18 +43,16 @@ export function RadioPanelDisplay(props: Props) { 8.8.8.8.8.8 ); + } else if ((typeof props.value === 'string')) { + content = ( + + {props.value} + + ); } else if (props.value > 0) { - let value = ''; - // If the passed value prop is a number, we'll use formatFrequency to get string format. - if (typeof props.value === 'number') { - value = formatFrequency(props.value); - } else { - value = props.value; - } - content = ( - {value} + {formatFrequency(props.value)} ); } else { diff --git a/src/instruments/src/RMP/Components/StandbyCourse.tsx b/src/instruments/src/RMP/Components/StandbyCourse.tsx new file mode 100644 index 00000000000..e0d1bc9f5fb --- /dev/null +++ b/src/instruments/src/RMP/Components/StandbyCourse.tsx @@ -0,0 +1,44 @@ +import React, { useCallback, useRef } from 'react'; +import { RadioPanelDisplay } from './RadioPanelDisplay'; +import { useInteractionEvent } from '../../Common/hooks'; +import { RateMultiplierKnob, UpdateValueCallback } from '../../Common/RateMultiplierKnob'; + +interface Props { + /** + * The RMP side (e.g. 'L' or 'R'). + */ + side: string, + + /** + * The current standby frequency value in Hz. + */ + value: number, + + /** + * A callback to set the current standby frequency value in Hz. + */ + setValue: (x: any) => void, +} + +/** + * Standby frequency radio management panel React component. + * Hooks to outer and inner rotary encoder knobs. + * Renders standby frequency RadioPanelDisplay sub-component. + */ +export const StandbyCourse = (props: Props) => { + // Handle inner knob turned. + const innerKnobUpdateCallback: UpdateValueCallback = useCallback((offset) => { + const integer = Math.floor((props.value + offset) / 360); + props.setValue(props.value - (integer * 360) + offset); + }, [props.value]); + + // Used to change decimal value of freq. + const innerKnob = useRef(new RateMultiplierKnob(200, 1)); + innerKnob.current.updateValue = innerKnobUpdateCallback; + + // Hook rotation events from simulator to custom knob class methods. + useInteractionEvent(`A32NX_RMP_${props.side}_INNER_KNOB_TURNED_CLOCKWISE`, () => innerKnob.current.increase()); + useInteractionEvent(`A32NX_RMP_${props.side}_INNER_KNOB_TURNED_ANTICLOCKWISE`, () => innerKnob.current.decrease()); + + return (); +}; diff --git a/src/instruments/src/RMP/Components/StandbyFrequency.tsx b/src/instruments/src/RMP/Components/StandbyFrequency.tsx index 6b2e46fc21e..d3500811852 100644 --- a/src/instruments/src/RMP/Components/StandbyFrequency.tsx +++ b/src/instruments/src/RMP/Components/StandbyFrequency.tsx @@ -6,6 +6,13 @@ import { RateMultiplierKnob, UpdateValueCallback } from '../../Common/RateMultip declare const Utils; // this can also be replaced once /typings are available +export enum TransceiverType { + RADIO_VHF, + VOR, + ILS, + ADF +} + interface Props { /** * The RMP side (e.g. 'L' or 'R'). @@ -17,6 +24,11 @@ interface Props { */ value: number, + /** + * Type of transceiver (e.g VHF, HF, VOR, ILS, MLS, ADF) + */ + transceiver: TransceiverType, + /** * A callback to set the current standby frequency value in Hz. */ @@ -37,6 +49,7 @@ const findNearestInArray = (value: number, array: number[]): number => array.red * High Frequency communications use 10 kHz spacing. * Vatsim VHF communications use 25 kHz spacing. * VOR / ILS frequencies use 50 kHz spacing. + * ADF frequencies use 1kHz spacing. */ type ChannelSpacing = 8.33 | 10 | 25 | 50; @@ -63,7 +76,7 @@ const offsetFrequencyChannel = (spacing: ChannelSpacing, channel: number, offset // Special cases, such as ADF, do not use the ending algorithm to find frequencies. if (endings === null) { - return (Math.floor(channel / 100) + spacing * offset) * 100; + return (Math.floor(channel % 100) + spacing * offset); } // Reverse the channel order if we're going backwards. @@ -100,17 +113,47 @@ const offsetFrequencyChannel = (spacing: ChannelSpacing, channel: number, offset * Renders standby frequency RadioPanelDisplay sub-component. */ export const StandbyFrequency = (props: Props) => { - const spacing = usePersistentProperty('RMP_VHF_SPACING_25KHZ', '0')[0] === '0' ? 8.33 : 25; + let spacing: ChannelSpacing; + let toMhz = 1000; + + switch (props.transceiver) { + case TransceiverType.ILS: + spacing = 25; + break; + case TransceiverType.VOR: + spacing = 50; + break; + case TransceiverType.ADF: + toMhz = 1; + break; + default: + spacing = usePersistentProperty('RMP_VHF_SPACING_25KHZ', '0')[0] === '0' ? 8.33 : 25; + } + // Handle outer knob turned. const outerKnobUpdateCallback: UpdateValueCallback = useCallback((offset) => { if (props.value !== 0) { - const frequency = Math.round(props.value / 1000); - const integer = Math.floor(frequency / 1000); - const decimal = frequency % 1000; + let frequency = props.value; + + if (props.transceiver !== TransceiverType.ADF) { + frequency = Math.round(frequency / 1000); // To kHz + } + + const integer = Math.floor(frequency / 1000) + offset; + // @todo determine min/max depending on mode. - const maxInteger = decimal > 975 ? 135 : 136; - const newInteger = Utils.Clamp(integer + offset, 118, maxInteger); - props.setValue((newInteger * 1000 + decimal) * 1000); + let newInteger = 0; + if (props.transceiver === TransceiverType.RADIO_VHF) { + newInteger = Utils.Clamp(integer, 118, 136); + } else if (props.transceiver === TransceiverType.ILS) { + newInteger = Utils.Clamp(integer, 108, 111); + } else if (props.transceiver === TransceiverType.VOR) { + newInteger = Utils.Clamp(integer, 108, 117); + } else if (props.transceiver === TransceiverType.ADF) { + newInteger = Utils.Clamp(integer, 190, 1750); + } + + props.setValue((newInteger * 1000 + frequency % 1000) * toMhz); } else { props.setValue(0); } @@ -118,18 +161,25 @@ export const StandbyFrequency = (props: Props) => { // Handle inner knob turned. const innerKnobUpdateCallback: UpdateValueCallback = useCallback((offset) => { - const frequency = Math.round(props.value / 1000); if (props.value !== 0) { - const integer = Math.floor(frequency / 1000); - // @todo determine correct frequency spacing depending on mode. - const decimal = offsetFrequencyChannel(spacing, frequency % 1000, offset); - // @todo determine min/max depending on mode. + let frequency = props.value; + + if (props.transceiver !== TransceiverType.ADF) { + frequency = Math.round(frequency / 1000); // To kHz + } + // Tested in real life: // Integer cannot return to 118 from 136 to the right // Decimal can return to 0 from 975 to the right - // const maxDecimal = integer === 136 ? 975 : 1000; - const newDecimal = Utils.Clamp(decimal, 0, 1000); - props.setValue((integer * 1000 + newDecimal) * 1000); + const integer = Math.floor(frequency / 1000); + let decimal = 0; + + if (props.transceiver !== TransceiverType.ADF) { + decimal = offsetFrequencyChannel(spacing, frequency % 1000, offset); + } else { // offsetFrequencyChannel does not fit ADF needs + decimal = frequency % 1000 === 0 ? 500 : 0; + } + props.setValue((integer * 1000 + decimal % 1000) * toMhz); } else { props.setValue(0); } diff --git a/src/instruments/src/RMP/Components/VhfRadioPanel.tsx b/src/instruments/src/RMP/Components/VhfRadioPanel.tsx index 8e358d309b6..f1559cd09f0 100644 --- a/src/instruments/src/RMP/Components/VhfRadioPanel.tsx +++ b/src/instruments/src/RMP/Components/VhfRadioPanel.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { StandbyFrequency } from './StandbyFrequency'; +import { StandbyFrequency, TransceiverType } from './StandbyFrequency'; import { useSplitSimVar } from '../../Common/simVars'; import { RadioPanelDisplay } from './RadioPanelDisplay'; import { useInteractionEvent } from '../../Common/hooks'; @@ -13,7 +13,7 @@ interface Props { /** * The VHF transceiver mode (VHF 1, 2, or 3). */ - transceiver: number, + vhf: number, } /** @@ -56,15 +56,15 @@ const useStandbyVhfFrequency = (side: string, transceiver: number) => { * Renders active frequency RadioPanelDisplay and appropriate StandbyFrequency sub-components. */ export const VhfRadioPanel = (props: Props) => { - const [active, setActive] = useActiveVhfFrequency(props.transceiver); - const [standby, setStandby] = useStandbyVhfFrequency(props.side, props.transceiver); + const [active, setActive] = useActiveVhfFrequency(props.vhf); + const [standby, setStandby] = useStandbyVhfFrequency(props.side, props.vhf); const [, setValueOppositePanelStandby] = props.side === 'L' ? useStandbyVhfFrequency('R', 3) : useStandbyVhfFrequency('L', 3); // Handle Transfer Button Pressed. useInteractionEvent(`A32NX_RMP_${props.side}_TRANSFER_BUTTON_PRESSED`, () => { // Force the standby opposite side otherwise we would lose the frequency/data format // Otherwise it would become frequency/frequency - if (props.transceiver === 3) { + if (props.vhf === 3) { setValueOppositePanelStandby(active); } setActive(standby); @@ -74,7 +74,7 @@ export const VhfRadioPanel = (props: Props) => { return ( - + ); }; From 06731062e40c5e50e9911bac75d113e6cb9ffd83 Mon Sep 17 00:00:00 2001 From: lukecologne Date: Thu, 29 Dec 2022 21:41:22 +0100 Subject: [PATCH 06/39] feat(sec): ground spoiler logic improvements (#7653) * fix(sec): fix bug where gnd splrs would extend with only one thr lvr at idle * feat(sec): add partial gnd splr improper thr lvr condition * chore: add changelog --- .github/CHANGELOG.md | 1 + src/fbw_a320/src/model/SecComputer.cpp | 340 ++++++++++---------- src/fbw_a320/src/model/SecComputer.h | 7 +- src/fbw_a320/src/model/SecComputer_data.cpp | 16 +- 4 files changed, 179 insertions(+), 185 deletions(-) diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index 11a4ead3268..532ce5e4e6e 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -17,6 +17,7 @@ 1. [FLIGHTMODEL] Reduced flap induced drag - @donstim (donbikes#4084) 1. [EFB] Fix and improve pushback system and add API documentation - @frankkopp (Frank Kopp) 1. [RMP] RMPs navigation backup - Julian Sebline (Julian Sebline#8476 on Discord) +1. [SEC] Fix GND SPLR logic, add missing GND SPLR partial extension condition - @lukecologne (luke) ## 0.9.0 diff --git a/src/fbw_a320/src/model/SecComputer.cpp b/src/fbw_a320/src/model/SecComputer.cpp index 7116180223b..cbc22b5c148 100644 --- a/src/fbw_a320/src/model/SecComputer.cpp +++ b/src/fbw_a320/src/model/SecComputer.cpp @@ -171,25 +171,25 @@ void SecComputer::step() real_T rtb_handleIndex; real_T rtb_zeta_deg; real_T u0; - real32_T rtb_y_fp; - real32_T rtb_y_h; + real32_T rtb_y_e; + real32_T rtb_y_fn; uint32_T rtb_DataTypeConversion1; uint32_T rtb_Switch7_c; uint32_T rtb_Switch9_c; uint32_T rtb_y; uint32_T rtb_y_af; - uint32_T rtb_y_mx; + uint32_T rtb_y_m; boolean_T rtb_VectorConcatenate[19]; boolean_T rtb_AND1_h; boolean_T rtb_AND4_a; boolean_T rtb_NOT_bl; boolean_T rtb_OR; - boolean_T rtb_OR6; - boolean_T rtb_y_am; - boolean_T rtb_y_b; - boolean_T rtb_y_k4; + boolean_T rtb_y_ei; + boolean_T rtb_y_f5; + boolean_T rtb_y_j; boolean_T rtb_y_l; - boolean_T rtb_y_m; + boolean_T rtb_y_la; + boolean_T rtb_y_ls; if (SecComputer_U.in.sim_data.computer_running) { real_T pair1RollCommand; real_T pair2SpdBrkCommand; @@ -210,14 +210,15 @@ void SecComputer::step() boolean_T abnormalCondition; boolean_T canEngageInPitch; boolean_T hasPriorityInPitch; - boolean_T leftElevatorAvail; boolean_T rightElevatorAvail; boolean_T rtb_AND2_j; + boolean_T rtb_BusAssignment_fz_logic_is_green_hydraulic_power_avail; boolean_T rtb_BusAssignment_n_logic_any_landing_gear_not_uplocked; boolean_T rtb_NOT2_b; boolean_T rtb_NOT_g; boolean_T rtb_OR1; boolean_T rtb_OR3; + boolean_T rtb_OR6; boolean_T rtb_doubleAdrFault; boolean_T rtb_doubleIrFault; boolean_T rtb_isEngagedInPitch; @@ -237,6 +238,7 @@ void SecComputer::step() SecComputer_DWork.Memory_PreviousInput_n = SecComputer_P.SRFlipFlop_initial_condition_k; SecComputer_DWork.Delay1_DSTATE_i = SecComputer_P.Delay1_InitialCondition_l; SecComputer_DWork.Delay_DSTATE_n = SecComputer_P.Delay_InitialCondition_j; + SecComputer_DWork.Delay2_DSTATE = SecComputer_P.Delay2_InitialCondition; SecComputer_DWork.Delay_DSTATE = SecComputer_P.Delay_InitialCondition; SecComputer_DWork.icLoad = true; SecComputer_MATLABFunction_e_Reset(&SecComputer_DWork.sf_MATLABFunction_jk); @@ -315,8 +317,8 @@ void SecComputer::step() (SignStatusMatrix::NormalOperation)) || SecComputer_P.Constant_Value_l); rtb_singleIrFault = (rtb_OR || rtb_OR6); rtb_doubleIrFault = (rtb_OR && rtb_OR6); - rtb_y_l = !rtb_OR3; - if ((!rtb_OR1) && rtb_y_l) { + rtb_y_j = !rtb_OR3; + if ((!rtb_OR1) && rtb_y_j) { rtb_V_ias = (SecComputer_U.in.bus_inputs.adr_2_bus.airspeed_computed_kn.Data + SecComputer_U.in.bus_inputs.adr_2_bus.airspeed_computed_kn.Data) / 2.0F; rtb_V_tas = (SecComputer_U.in.bus_inputs.adr_2_bus.airspeed_true_kn.Data + @@ -330,7 +332,7 @@ void SecComputer::step() rtb_V_tas = SecComputer_U.in.bus_inputs.adr_1_bus.airspeed_true_kn.Data; rtb_mach = SecComputer_U.in.bus_inputs.adr_1_bus.mach.Data; rtb_alpha = SecComputer_U.in.bus_inputs.adr_1_bus.aoa_corrected_deg.Data; - } else if (rtb_OR1 && rtb_y_l) { + } else if (rtb_OR1 && rtb_y_j) { rtb_V_ias = SecComputer_U.in.bus_inputs.adr_2_bus.airspeed_computed_kn.Data; rtb_V_tas = SecComputer_U.in.bus_inputs.adr_2_bus.airspeed_true_kn.Data; rtb_mach = SecComputer_U.in.bus_inputs.adr_2_bus.mach.Data; @@ -345,9 +347,9 @@ void SecComputer::step() rtb_eta_trim_limit_lo_d = rtb_V_ias; rtb_BusConversion_InsertedFor_BusAssignment_at_inport_8_BusCreator1_V_tas_kn = rtb_V_tas; rtb_BusConversion_InsertedFor_BusAssignment_at_inport_8_BusCreator1_mach = rtb_mach; - rtb_y_l = !rtb_OR; + rtb_y_j = !rtb_OR; rtb_OR1 = !rtb_OR6; - if (rtb_y_l && rtb_OR1) { + if (rtb_y_j && rtb_OR1) { rtb_theta = (SecComputer_U.in.bus_inputs.ir_1_bus.pitch_angle_deg.Data + SecComputer_U.in.bus_inputs.ir_2_bus.pitch_angle_deg.Data) / 2.0F; rtb_phi = (SecComputer_U.in.bus_inputs.ir_1_bus.roll_angle_deg.Data + @@ -366,7 +368,7 @@ void SecComputer::step() SecComputer_U.in.bus_inputs.ir_2_bus.pitch_att_rate_deg_s.Data) / 2.0F; rtb_phi_dot = (SecComputer_U.in.bus_inputs.ir_1_bus.roll_att_rate_deg_s.Data + SecComputer_U.in.bus_inputs.ir_2_bus.roll_att_rate_deg_s.Data) / 2.0F; - } else if (rtb_y_l && rtb_OR6) { + } else if (rtb_y_j && rtb_OR6) { rtb_theta = SecComputer_U.in.bus_inputs.ir_1_bus.pitch_angle_deg.Data; rtb_phi = SecComputer_U.in.bus_inputs.ir_1_bus.roll_angle_deg.Data; rtb_q = SecComputer_U.in.bus_inputs.ir_1_bus.body_pitch_rate_deg_s.Data; @@ -401,81 +403,81 @@ void SecComputer::step() rtb_Switch5_tmp_tmp = rtb_theta; rtb_Switch6_m = rtb_phi; rtb_handleIndex = rtb_n_x; - SecComputer_MATLABFunction_l(&SecComputer_U.in.bus_inputs.lgciu_2_bus.discrete_word_3, &rtb_OR); + SecComputer_MATLABFunction_l(&SecComputer_U.in.bus_inputs.lgciu_2_bus.discrete_word_3, &rtb_y_ei); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.lgciu_2_bus.discrete_word_3, SecComputer_P.BitfromLabel13_bit, &rtb_Switch7_c); - rtb_OR6 = (rtb_Switch7_c != 0U); + rtb_OR = (rtb_Switch7_c != 0U); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.lgciu_2_bus.discrete_word_3, SecComputer_P.BitfromLabel12_bit, &rtb_Switch7_c); - rtb_y_m = (rtb_Switch7_c != 0U); + rtb_y_f5 = (rtb_Switch7_c != 0U); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.lgciu_2_bus.discrete_word_3, SecComputer_P.BitfromLabel10_bit, &rtb_Switch7_c); - rtb_OR6 = (rtb_OR6 || rtb_y_m || (rtb_Switch7_c != 0U)); - rtb_y_k4 = (rtb_OR && rtb_OR6); + rtb_OR = (rtb_OR || rtb_y_f5 || (rtb_Switch7_c != 0U)); + rtb_y_ls = (rtb_y_ei && rtb_OR); SecComputer_MATLABFunction_l(&SecComputer_U.in.bus_inputs.lgciu_1_bus.discrete_word_3, &rtb_NOT_bl); - rtb_OR1 = (rtb_y_k4 && (!rtb_NOT_bl)); - SecComputer_MATLABFunction_l(&SecComputer_U.in.bus_inputs.lgciu_1_bus.discrete_word_3, &rtb_y_b); + rtb_OR6 = (rtb_y_ls && (!rtb_NOT_bl)); + SecComputer_MATLABFunction_l(&SecComputer_U.in.bus_inputs.lgciu_1_bus.discrete_word_3, &rtb_y_la); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.lgciu_1_bus.discrete_word_3, SecComputer_P.BitfromLabel5_bit, &rtb_Switch7_c); - rtb_y_m = (rtb_Switch7_c != 0U); + rtb_y_f5 = (rtb_Switch7_c != 0U); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.lgciu_1_bus.discrete_word_3, SecComputer_P.BitfromLabel4_bit, &rtb_Switch7_c); - rtb_y_am = (rtb_Switch7_c != 0U); + rtb_y_l = (rtb_Switch7_c != 0U); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.lgciu_1_bus.discrete_word_3, SecComputer_P.BitfromLabel2_bit, &rtb_Switch7_c); - rtb_y_m = (rtb_y_m || rtb_y_am || (rtb_Switch7_c != 0U)); - rtb_AND4_a = (rtb_y_b && rtb_y_m); + rtb_y_f5 = (rtb_y_f5 || rtb_y_l || (rtb_Switch7_c != 0U)); + rtb_AND4_a = (rtb_y_la && rtb_y_f5); SecComputer_MATLABFunction_l(&SecComputer_U.in.bus_inputs.lgciu_2_bus.discrete_word_3, &rtb_NOT_bl); - rtb_AND4_a = (rtb_OR1 || (rtb_AND4_a && (!rtb_NOT_bl)) || (rtb_y_k4 && rtb_AND4_a)); + rtb_AND4_a = (rtb_OR6 || (rtb_AND4_a && (!rtb_NOT_bl)) || (rtb_y_ls && rtb_AND4_a)); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.lgciu_1_bus.discrete_word_3, SecComputer_P.BitfromLabel15_bit, &rtb_Switch7_c); - rtb_y_am = (rtb_Switch7_c != 0U); - SecComputer_MATLABFunction_l(&SecComputer_U.in.bus_inputs.lgciu_1_bus.discrete_word_3, &rtb_y_l); + rtb_y_l = (rtb_Switch7_c != 0U); + SecComputer_MATLABFunction_l(&SecComputer_U.in.bus_inputs.lgciu_1_bus.discrete_word_3, &rtb_y_j); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.lgciu_1_bus.discrete_word_3, SecComputer_P.BitfromLabel14_bit, &rtb_Switch7_c); - rtb_y_k4 = (rtb_Switch7_c != 0U); + rtb_y_ls = (rtb_Switch7_c != 0U); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.lgciu_1_bus.discrete_word_3, SecComputer_P.BitfromLabel11_bit, &rtb_Switch7_c); rtb_AND1_h = (rtb_Switch7_c != 0U); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.lgciu_1_bus.discrete_word_3, SecComputer_P.BitfromLabel8_bit, &rtb_Switch7_c); - rtb_OR1 = ((!rtb_y_k4) && (!rtb_AND1_h) && (rtb_Switch7_c == 0U)); + rtb_OR6 = ((!rtb_y_ls) && (!rtb_AND1_h) && (rtb_Switch7_c == 0U)); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.lgciu_2_bus.discrete_word_3, SecComputer_P.BitfromLabel16_bit, &rtb_Switch7_c); rtb_NOT_bl = (rtb_Switch7_c != 0U); - SecComputer_MATLABFunction_n((rtb_Switch7_c != 0U) && rtb_OR && rtb_OR6, SecComputer_U.in.time.dt, - SecComputer_P.ConfirmNode_isRisingEdge, SecComputer_P.ConfirmNode_timeDelay, &rtb_OR6, + SecComputer_MATLABFunction_n((rtb_Switch7_c != 0U) && rtb_y_ei && rtb_OR, SecComputer_U.in.time.dt, + SecComputer_P.ConfirmNode_isRisingEdge, SecComputer_P.ConfirmNode_timeDelay, &rtb_OR, &SecComputer_DWork.sf_MATLABFunction_jk); - rtb_OR = (rtb_y_am && rtb_y_l && rtb_OR1 && rtb_OR6); + rtb_OR = (rtb_y_l && rtb_y_j && rtb_OR6 && rtb_OR); SecComputer_MATLABFunction_l(&SecComputer_U.in.bus_inputs.lgciu_1_bus.discrete_word_3, &rtb_AND1_h); SecComputer_MATLABFunction_l(&SecComputer_U.in.bus_inputs.lgciu_2_bus.discrete_word_3, &rtb_NOT_bl); rtb_OR6 = ((!rtb_AND1_h) && (!rtb_NOT_bl)); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.lgciu_2_bus.discrete_word_3, SecComputer_P.BitfromLabel7_bit, &rtb_Switch7_c); rtb_NOT_bl = (rtb_Switch7_c != 0U); - SecComputer_MATLABFunction_l(&SecComputer_U.in.bus_inputs.lgciu_2_bus.discrete_word_3, &rtb_y_l); + SecComputer_MATLABFunction_l(&SecComputer_U.in.bus_inputs.lgciu_2_bus.discrete_word_3, &rtb_y_j); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.lgciu_2_bus.discrete_word_3, SecComputer_P.BitfromLabel6_bit, &rtb_Switch7_c); rtb_AND1_h = (rtb_Switch7_c != 0U); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.lgciu_2_bus.discrete_word_3, SecComputer_P.BitfromLabel3_bit, &rtb_Switch7_c); - rtb_y_am = (rtb_Switch7_c != 0U); + rtb_y_l = (rtb_Switch7_c != 0U); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.lgciu_2_bus.discrete_word_3, SecComputer_P.BitfromLabel1_bit, &rtb_Switch7_c); - rtb_OR1 = (rtb_NOT_bl && rtb_y_l && ((!rtb_AND1_h) && (!rtb_y_am) && (rtb_Switch7_c == 0U))); + rtb_OR1 = (rtb_NOT_bl && rtb_y_j && ((!rtb_AND1_h) && (!rtb_y_l) && (rtb_Switch7_c == 0U))); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.lgciu_1_bus.discrete_word_3, SecComputer_P.BitfromLabel9_bit, &rtb_Switch7_c); rtb_NOT_bl = (rtb_Switch7_c != 0U); - SecComputer_MATLABFunction_n((rtb_Switch7_c != 0U) && rtb_y_b && rtb_y_m, SecComputer_U.in.time.dt, + SecComputer_MATLABFunction_n((rtb_Switch7_c != 0U) && rtb_y_la && rtb_y_f5, SecComputer_U.in.time.dt, SecComputer_P.ConfirmNode1_isRisingEdge, SecComputer_P.ConfirmNode1_timeDelay, &rtb_NOT_bl, &SecComputer_DWork.sf_MATLABFunction_dw); - rtb_OR6 = (rtb_OR || rtb_OR6 || (rtb_OR1 && rtb_NOT_bl)); + rtb_OR = (rtb_OR || rtb_OR6 || (rtb_OR1 && rtb_NOT_bl)); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.lgciu_1_bus.discrete_word_2, SecComputer_P.BitfromLabel4_bit_c, &rtb_Switch7_c); rtb_NOT_bl = (rtb_Switch7_c != 0U); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.lgciu_2_bus.discrete_word_2, SecComputer_P.BitfromLabel6_bit_l, &rtb_Switch7_c); - rtb_OR = (rtb_NOT_bl || (rtb_Switch7_c != 0U)); + rtb_OR6 = (rtb_NOT_bl || (rtb_Switch7_c != 0U)); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.lgciu_1_bus.discrete_word_2, SecComputer_P.BitfromLabel5_bit_a, &rtb_Switch7_c); rtb_NOT_bl = (rtb_Switch7_c != 0U); @@ -486,22 +488,22 @@ void SecComputer::step() if (SecComputer_DWork.is_active_c8_SecComputer == 0U) { SecComputer_DWork.is_active_c8_SecComputer = 1U; SecComputer_DWork.is_c8_SecComputer = SecComputer_IN_OnGround; - rtb_OR1 = true; + rtb_OR6 = true; } else if (SecComputer_DWork.is_c8_SecComputer == SecComputer_IN_InAir) { - if ((static_cast(rtb_OR) > 0.1) || (static_cast(rtb_OR1) > 0.1)) { + if ((static_cast(rtb_OR6) > 0.1) || (static_cast(rtb_OR1) > 0.1)) { SecComputer_DWork.is_c8_SecComputer = SecComputer_IN_OnGround; - rtb_OR1 = true; + rtb_OR6 = true; } else { - rtb_OR1 = false; + rtb_OR6 = false; } - } else if ((!rtb_OR) && (!rtb_OR1)) { + } else if ((!rtb_OR6) && (!rtb_OR1)) { SecComputer_DWork.is_c8_SecComputer = SecComputer_IN_InAir; - rtb_OR1 = false; + rtb_OR6 = false; } else { - rtb_OR1 = true; + rtb_OR6 = true; } - rtb_OR3 = (SecComputer_U.in.sim_data.slew_on || SecComputer_U.in.sim_data.pause_on || + rtb_OR1 = (SecComputer_U.in.sim_data.slew_on || SecComputer_U.in.sim_data.pause_on || SecComputer_U.in.sim_data.tracking_mode_on_override); if (SecComputer_DWork.is_active_c30_SecComputer == 0U) { SecComputer_DWork.is_active_c30_SecComputer = 1U; @@ -510,7 +512,7 @@ void SecComputer::step() } else { switch (SecComputer_DWork.is_c30_SecComputer) { case SecComputer_IN_Flight: - if (rtb_OR1 && (rtb_theta < 2.5F)) { + if (rtb_OR6 && (rtb_theta < 2.5F)) { SecComputer_DWork.on_ground_time = SecComputer_U.in.time.simulation_time; SecComputer_DWork.is_c30_SecComputer = SecComputer_IN_FlightToGroundTransition; } else { @@ -522,7 +524,7 @@ void SecComputer::step() if (SecComputer_U.in.time.simulation_time - SecComputer_DWork.on_ground_time >= 5.0) { SecComputer_DWork.is_c30_SecComputer = SecComputer_IN_Ground; SecComputer_B.in_flight = 0.0; - } else if ((!rtb_OR1) || (rtb_theta >= 2.5F)) { + } else if ((!rtb_OR6) || (rtb_theta >= 2.5F)) { SecComputer_DWork.on_ground_time = 0.0; SecComputer_DWork.is_c30_SecComputer = SecComputer_IN_Flight; SecComputer_B.in_flight = 1.0; @@ -530,7 +532,7 @@ void SecComputer::step() break; default: - if (((!rtb_OR1) && (rtb_theta > 8.0F)) || (SecComputer_P.Constant_Value_m > 400.0)) { + if (((!rtb_OR6) && (rtb_theta > 8.0F)) || (SecComputer_P.Constant_Value_m > 400.0)) { SecComputer_DWork.on_ground_time = 0.0; SecComputer_DWork.is_c30_SecComputer = SecComputer_IN_Flight; SecComputer_B.in_flight = 1.0; @@ -543,13 +545,13 @@ void SecComputer::step() rtb_NOT_bl = (SecComputer_B.in_flight != 0.0); SecComputer_MATLABFunction_n(!SecComputer_U.in.discrete_inputs.yellow_low_pressure, SecComputer_U.in.time.dt, - SecComputer_P.ConfirmNode_isRisingEdge_a, SecComputer_P.ConfirmNode_timeDelay_c, &rtb_OR, + SecComputer_P.ConfirmNode_isRisingEdge_a, SecComputer_P.ConfirmNode_timeDelay_c, &rtb_y_ei, &SecComputer_DWork.sf_MATLABFunction_ndv); SecComputer_MATLABFunction_n(!SecComputer_U.in.discrete_inputs.blue_low_pressure, SecComputer_U.in.time.dt, - SecComputer_P.ConfirmNode1_isRisingEdge_j, SecComputer_P.ConfirmNode1_timeDelay_k, &rtb_y_l, + SecComputer_P.ConfirmNode1_isRisingEdge_j, SecComputer_P.ConfirmNode1_timeDelay_k, &rtb_y_j, &SecComputer_DWork.sf_MATLABFunction_gf); SecComputer_MATLABFunction_n(!SecComputer_U.in.discrete_inputs.green_low_pressure, SecComputer_U.in.time.dt, - SecComputer_P.ConfirmNode2_isRisingEdge, SecComputer_P.ConfirmNode2_timeDelay, &rtb_y_b, + SecComputer_P.ConfirmNode2_isRisingEdge, SecComputer_P.ConfirmNode2_timeDelay, &rtb_y_la, &SecComputer_DWork.sf_MATLABFunction_h); rtb_BusAssignment_f_logic_ir_computation_data_n_z_g = rtb_n_z; rtb_BusAssignment_f_logic_ir_computation_data_theta_dot_deg_s = rtb_theta_dot; @@ -601,32 +603,32 @@ void SecComputer::step() } if (SecComputer_U.in.discrete_inputs.is_unit_1) { - leftElevatorAvail = ((!SecComputer_U.in.discrete_inputs.l_elev_servo_failed) && rtb_y_l); - rightElevatorAvail = ((!SecComputer_U.in.discrete_inputs.r_elev_servo_failed) && rtb_y_l); + rtb_OR3 = ((!SecComputer_U.in.discrete_inputs.l_elev_servo_failed) && rtb_y_j); + rightElevatorAvail = ((!SecComputer_U.in.discrete_inputs.r_elev_servo_failed) && rtb_y_j); } else { - leftElevatorAvail = ((!SecComputer_U.in.discrete_inputs.l_elev_servo_failed) && rtb_y_b); - rightElevatorAvail = ((!SecComputer_U.in.discrete_inputs.r_elev_servo_failed) && rtb_OR); + rtb_OR3 = ((!SecComputer_U.in.discrete_inputs.l_elev_servo_failed) && rtb_y_la); + rightElevatorAvail = ((!SecComputer_U.in.discrete_inputs.r_elev_servo_failed) && rtb_y_ei); } - rtb_thsAvail = ((!SecComputer_U.in.discrete_inputs.ths_motor_fault) && (rtb_OR || rtb_y_b)); - canEngageInPitch = ((leftElevatorAvail || rightElevatorAvail) && (!SecComputer_U.in.discrete_inputs.is_unit_3)); + rtb_thsAvail = ((!SecComputer_U.in.discrete_inputs.ths_motor_fault) && (rtb_y_ei || rtb_y_la)); + canEngageInPitch = ((rtb_OR3 || rightElevatorAvail) && (!SecComputer_U.in.discrete_inputs.is_unit_3)); if (SecComputer_U.in.discrete_inputs.is_unit_1) { hasPriorityInPitch = (SecComputer_U.in.discrete_inputs.pitch_not_avail_elac_1 && SecComputer_U.in.discrete_inputs.pitch_not_avail_elac_2 && SecComputer_U.in.discrete_inputs.left_elev_not_avail_sec_opp && SecComputer_U.in.discrete_inputs.right_elev_not_avail_sec_opp); - spoilerPair1SupplyAvail = rtb_y_l; - spoilerPair2SupplyAvail = rtb_OR; + spoilerPair1SupplyAvail = rtb_y_j; + spoilerPair2SupplyAvail = rtb_y_ei; } else { hasPriorityInPitch = (SecComputer_U.in.discrete_inputs.is_unit_2 && (SecComputer_U.in.discrete_inputs.pitch_not_avail_elac_1 && SecComputer_U.in.discrete_inputs.pitch_not_avail_elac_2)); if (SecComputer_U.in.discrete_inputs.is_unit_2) { - spoilerPair1SupplyAvail = rtb_y_b; + spoilerPair1SupplyAvail = rtb_y_la; spoilerPair2SupplyAvail = false; } else { - spoilerPair1SupplyAvail = rtb_y_b; - spoilerPair2SupplyAvail = rtb_OR; + spoilerPair1SupplyAvail = rtb_y_la; + spoilerPair2SupplyAvail = rtb_y_ei; } } @@ -642,7 +644,7 @@ void SecComputer::step() SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.elac_1_bus.discrete_status_word_1, SecComputer_P.BitfromLabel_bit, &rtb_Switch7_c); SecComputer_MATLABFunction_l(&SecComputer_U.in.bus_inputs.elac_1_bus.discrete_status_word_1, &rtb_AND4_a); - rtb_y_k4 = ((rtb_Switch7_c != 0U) && rtb_AND4_a); + rtb_y_ls = ((rtb_Switch7_c != 0U) && rtb_AND4_a); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.elac_2_bus.discrete_status_word_1, SecComputer_P.BitfromLabel1_bit_g, &rtb_Switch7_c); SecComputer_MATLABFunction_l(&SecComputer_U.in.bus_inputs.elac_2_bus.discrete_status_word_1, &rtb_AND1_h); @@ -658,20 +660,20 @@ void SecComputer::step() SecComputer_MATLABFunction_n(SecComputer_U.in.sim_data.slew_on, SecComputer_U.in.time.dt, SecComputer_P.ConfirmNode_isRisingEdge_g, SecComputer_P.ConfirmNode_timeDelay_e, &rtb_NOT_bl, &SecComputer_DWork.sf_MATLABFunction_k4); - rtb_y_am = !rtb_OR1; - abnormalCondition = ((!rtb_NOT_bl) && rtb_y_am && (((!rtb_doubleAdrFault) && ((rtb_mach > 0.91) || (rtb_alpha < + rtb_y_l = !rtb_OR6; + abnormalCondition = ((!rtb_NOT_bl) && rtb_y_l && (((!rtb_doubleAdrFault) && ((rtb_mach > 0.91) || (rtb_alpha < -10.0F) || (rtb_alpha > 40.0F) || (rtb_V_ias > 440.0F) || (rtb_V_ias < 60.0F))) || ((!rtb_doubleIrFault) && ((!rtb_singleIrFault) || (!SecComputer_P.Constant_Value_l)) && ((std::abs(static_cast(rtb_phi)) > 125.0) || ((rtb_theta > 50.0F) || (rtb_theta < -30.0F)))))); - SecComputer_DWork.abnormalConditionWasActive = (abnormalCondition || (rtb_y_am && + SecComputer_DWork.abnormalConditionWasActive = (abnormalCondition || (rtb_y_l && SecComputer_DWork.abnormalConditionWasActive)); if (rtb_doubleIrFault || ((SecComputer_B.in_flight != 0.0) && - ((rtb_BusAssignment_n_logic_any_landing_gear_not_uplocked && (!rtb_OR6)) || ((rtb_AND4_a || ((rtb_Switch7_c != - 0U) && rtb_AND1_h)) && rtb_OR6)))) { + ((rtb_BusAssignment_n_logic_any_landing_gear_not_uplocked && (!rtb_OR)) || ((rtb_AND4_a || ((rtb_Switch7_c != + 0U) && rtb_AND1_h)) && rtb_OR)))) { rtb_pitchLawCapability = pitch_efcs_law::DirectLaw; } else if ((rtb_singleAdrFault && SecComputer_P.Constant2_Value_c) || rtb_doubleAdrFault || - SecComputer_DWork.abnormalConditionWasActive || ((!rtb_y_k4) && (!rtb_AND2_j) && ((!leftElevatorAvail) || - (!rightElevatorAvail)))) { + SecComputer_DWork.abnormalConditionWasActive || ((!rtb_y_ls) && (!rtb_AND2_j) && ((!rtb_OR3) || + (!rightElevatorAvail)))) { rtb_pitchLawCapability = pitch_efcs_law::AlternateLaw2; } else { rtb_pitchLawCapability = pitch_efcs_law::AlternateLaw1; @@ -702,20 +704,20 @@ void SecComputer::step() u0 = SecComputer_P.Saturation_LowerSat_h; } - SecComputer_MATLABFunction_e(SecComputer_B.in_flight != 0.0, SecComputer_P.PulseNode_isRisingEdge_h, &rtb_y_k4, + SecComputer_MATLABFunction_e(SecComputer_B.in_flight != 0.0, SecComputer_P.PulseNode_isRisingEdge_h, &rtb_y_ls, &SecComputer_DWork.sf_MATLABFunction_b4); - rtb_y_am = (SecComputer_U.in.discrete_inputs.pitch_not_avail_elac_1 && - SecComputer_U.in.discrete_inputs.pitch_not_avail_elac_2); - rtb_AND1_h = (SecComputer_U.in.discrete_inputs.is_unit_1 && rtb_thsAvail && rtb_y_am); + rtb_y_l = (SecComputer_U.in.discrete_inputs.pitch_not_avail_elac_1 && + SecComputer_U.in.discrete_inputs.pitch_not_avail_elac_2); + rtb_AND1_h = (SecComputer_U.in.discrete_inputs.is_unit_1 && rtb_thsAvail && rtb_y_l); SecComputer_DWork.Memory_PreviousInput = SecComputer_P.Logic_table[((((!rtb_AND1_h) || (std::abs (SecComputer_U.in.analog_inputs.ths_pos_deg) <= SecComputer_P.CompareToConstant1_const) || - SecComputer_U.in.discrete_inputs.ths_override_active) + (static_cast(rtb_y_k4) << 1)) << 1) + + SecComputer_U.in.discrete_inputs.ths_override_active) + (static_cast(rtb_y_ls) << 1)) << 1) + SecComputer_DWork.Memory_PreviousInput]; rtb_NOT_bl = (rtb_AND1_h && SecComputer_DWork.Memory_PreviousInput); rtb_AND4_a = !abnormalCondition; rtb_AND1_h = ((rtb_isEngagedInPitch && (SecComputer_B.in_flight != 0.0) && ((rtb_activePitchLaw != SecComputer_P.EnumeratedConstant_Value_f) && rtb_AND4_a)) || rtb_NOT_bl); - rtb_y_k4 = rtb_AND1_h; + rtb_y_ls = rtb_AND1_h; rtb_AND2_j = rtb_NOT_bl; SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.elac_1_bus.discrete_status_word_2, SecComputer_P.BitfromLabel7_bit_g, &rtb_Switch7_c); @@ -724,7 +726,7 @@ void SecComputer::step() SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.elac_2_bus.discrete_status_word_2, SecComputer_P.BitfromLabel6_bit_f, &rtb_Switch7_c); SecComputer_MATLABFunction_l(&SecComputer_U.in.bus_inputs.elac_2_bus.discrete_status_word_2, &rtb_AND4_a); - rtb_y_m = ((rtb_Switch7_c != 0U) && rtb_AND4_a); + rtb_y_f5 = ((rtb_Switch7_c != 0U) && rtb_AND4_a); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.sfcc_1_bus.slat_flap_actual_position_word, SecComputer_P.BitfromLabel_bit_l, &rtb_Switch7_c); SecComputer_MATLABFunction_l(&SecComputer_U.in.bus_inputs.sfcc_1_bus.slat_flap_actual_position_word, &rtb_AND4_a); @@ -744,76 +746,77 @@ void SecComputer::step() rtb_NOT_g = (rtb_Switch7_c == 0U); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.elac_2_bus.discrete_status_word_1, SecComputer_P.BitfromLabel2_bit_p, &rtb_Switch7_c); - rtb_NOT_bl = (rtb_NOT_bl || rtb_y_m || (rtb_AND4_a || rtb_AND1_h) || (((!rtb_y_am) && rtb_NOT2_b && (rtb_NOT_g || - (rtb_Switch7_c == 0U))) || (rtb_y_am && ((SecComputer_U.in.discrete_inputs.left_elev_not_avail_sec_opp && - (!leftElevatorAvail)) || (SecComputer_U.in.discrete_inputs.right_elev_not_avail_sec_opp && (!rightElevatorAvail))))) - || ((SecComputer_U.in.analog_inputs.thr_lever_1_pos >= SecComputer_P.CompareToConstant3_const) || - (SecComputer_U.in.analog_inputs.thr_lever_2_pos >= SecComputer_P.CompareToConstant4_const))); + rtb_NOT_bl = (rtb_NOT_bl || rtb_y_f5 || (rtb_AND4_a || rtb_AND1_h) || (((!rtb_y_l) && rtb_NOT2_b && (rtb_NOT_g || + (rtb_Switch7_c == 0U))) || (rtb_y_l && ((SecComputer_U.in.discrete_inputs.left_elev_not_avail_sec_opp && (!rtb_OR3)) + || (SecComputer_U.in.discrete_inputs.right_elev_not_avail_sec_opp && (!rightElevatorAvail))))) || + ((SecComputer_U.in.analog_inputs.thr_lever_1_pos >= SecComputer_P.CompareToConstant3_const) || + (SecComputer_U.in.analog_inputs.thr_lever_2_pos >= SecComputer_P.CompareToConstant4_const))); SecComputer_MATLABFunction_n(SecComputer_U.in.analog_inputs.spd_brk_lever_pos < SecComputer_P.CompareToConstant_const, SecComputer_U.in.time.dt, SecComputer_P.ConfirmNode_isRisingEdge_e, - SecComputer_P.ConfirmNode_timeDelay_eq, &rtb_y_m, &SecComputer_DWork.sf_MATLABFunction_fh); + SecComputer_P.ConfirmNode_timeDelay_eq, &rtb_y_f5, &SecComputer_DWork.sf_MATLABFunction_fh); SecComputer_DWork.Memory_PreviousInput_f = SecComputer_P.Logic_table_i[(((static_cast(rtb_NOT_bl) << 1) + - rtb_y_m) << 1) + SecComputer_DWork.Memory_PreviousInput_f]; - rtb_y_m = (rtb_NOT_bl || SecComputer_DWork.Memory_PreviousInput_f); - rtb_NOT2_b = rtb_y_l; - rtb_NOT_g = rtb_y_b; - SecComputer_MATLABFunction_e(rtb_OR1, SecComputer_P.PulseNode3_isRisingEdge, &rtb_y_b, + rtb_y_f5) << 1) + SecComputer_DWork.Memory_PreviousInput_f]; + rtb_y_f5 = (rtb_NOT_bl || SecComputer_DWork.Memory_PreviousInput_f); + rtb_NOT2_b = rtb_y_ei; + rtb_NOT_g = rtb_y_j; + rtb_BusAssignment_fz_logic_is_green_hydraulic_power_avail = rtb_y_la; + SecComputer_MATLABFunction_e(rtb_OR6, SecComputer_P.PulseNode3_isRisingEdge, &rtb_y_la, &SecComputer_DWork.sf_MATLABFunction_nd); - rtb_NOT_bl = (rtb_y_b || ((SecComputer_U.in.analog_inputs.wheel_speed_left < SecComputer_P.CompareToConstant11_const) - && (SecComputer_U.in.analog_inputs.wheel_speed_right < SecComputer_P.CompareToConstant12_const))); - SecComputer_MATLABFunction_e(rtb_OR1, SecComputer_P.PulseNode2_isRisingEdge, &rtb_y_b, + rtb_NOT_bl = (rtb_y_la || ((SecComputer_U.in.analog_inputs.wheel_speed_left < + SecComputer_P.CompareToConstant11_const) && (SecComputer_U.in.analog_inputs.wheel_speed_right < + SecComputer_P.CompareToConstant12_const))); + SecComputer_MATLABFunction_e(rtb_OR6, SecComputer_P.PulseNode2_isRisingEdge, &rtb_y_la, &SecComputer_DWork.sf_MATLABFunction_n); SecComputer_DWork.Memory_PreviousInput_n = SecComputer_P.Logic_table_ii[(((static_cast(rtb_NOT_bl) << 1) + - rtb_y_b) << 1) + SecComputer_DWork.Memory_PreviousInput_n]; + rtb_y_la) << 1) + SecComputer_DWork.Memory_PreviousInput_n]; SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.lgciu_1_bus.discrete_word_2, SecComputer_P.BitfromLabel4_bit_a, &rtb_Switch7_c); rtb_AND1_h = (rtb_Switch7_c != 0U); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.lgciu_2_bus.discrete_word_2, SecComputer_P.BitfromLabel6_bit_d, &rtb_Switch7_c); - rtb_y_b = (rtb_AND1_h && (rtb_Switch7_c != 0U)); + rtb_y_la = (rtb_AND1_h && (rtb_Switch7_c != 0U)); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.lgciu_1_bus.discrete_word_2, SecComputer_P.BitfromLabel5_bit_i, &rtb_Switch7_c); rtb_AND1_h = (rtb_Switch7_c != 0U); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.lgciu_2_bus.discrete_word_2, SecComputer_P.BitfromLabel7_bit_ms, &rtb_Switch7_c); - SecComputer_MATLABFunction_e(rtb_y_b || (rtb_AND1_h && (rtb_Switch7_c != 0U)), - SecComputer_P.PulseNode1_isRisingEdge_k, &rtb_y_l, &SecComputer_DWork.sf_MATLABFunction_a); + SecComputer_MATLABFunction_e(rtb_y_la || (rtb_AND1_h && (rtb_Switch7_c != 0U)), + SecComputer_P.PulseNode1_isRisingEdge_k, &rtb_y_j, &SecComputer_DWork.sf_MATLABFunction_a); rtb_NOT_bl = (SecComputer_U.in.analog_inputs.spd_brk_lever_pos < SecComputer_P.CompareToConstant_const_m); - SecComputer_DWork.Delay1_DSTATE_i = (((((SecComputer_U.in.analog_inputs.spd_brk_lever_pos > - SecComputer_P.CompareToConstant15_const) || rtb_NOT_bl) && ((SecComputer_U.in.analog_inputs.thr_lever_1_pos <= - SecComputer_P.CompareToConstant1_const_l) || (SecComputer_U.in.analog_inputs.thr_lever_2_pos <= + rtb_AND1_h = ((((SecComputer_U.in.analog_inputs.spd_brk_lever_pos > SecComputer_P.CompareToConstant15_const) || + rtb_NOT_bl) && ((SecComputer_U.in.analog_inputs.thr_lever_1_pos <= + SecComputer_P.CompareToConstant1_const_l) && (SecComputer_U.in.analog_inputs.thr_lever_2_pos <= SecComputer_P.CompareToConstant2_const))) || (((SecComputer_U.in.analog_inputs.thr_lever_1_pos < SecComputer_P.CompareToConstant3_const_a) && (SecComputer_U.in.analog_inputs.thr_lever_2_pos <= SecComputer_P.CompareToConstant4_const_j)) || ((SecComputer_U.in.analog_inputs.thr_lever_1_pos <= SecComputer_P.CompareToConstant13_const) && (SecComputer_U.in.analog_inputs.thr_lever_2_pos < - SecComputer_P.CompareToConstant14_const)))) && (rtb_y_l || ((SecComputer_U.in.analog_inputs.wheel_speed_left >= + SecComputer_P.CompareToConstant14_const)))); + SecComputer_DWork.Delay1_DSTATE_i = (rtb_AND1_h && (rtb_y_j || ((SecComputer_U.in.analog_inputs.wheel_speed_left >= SecComputer_P.CompareToConstant5_const) && (SecComputer_U.in.analog_inputs.wheel_speed_right >= SecComputer_P.CompareToConstant6_const) && SecComputer_DWork.Memory_PreviousInput_n) || SecComputer_DWork.Delay1_DSTATE_i)); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.lgciu_1_bus.discrete_word_2, SecComputer_P.BitfromLabel_bit_g, &rtb_Switch7_c); - rtb_AND1_h = (rtb_Switch7_c != 0U); + rtb_AND4_a = (rtb_Switch7_c != 0U); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.lgciu_2_bus.discrete_word_2, SecComputer_P.BitfromLabel2_bit_l, &rtb_Switch7_c); - rtb_y_b = (rtb_AND1_h || (rtb_Switch7_c != 0U)); + rtb_y_la = (rtb_AND4_a || (rtb_Switch7_c != 0U)); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.lgciu_1_bus.discrete_word_2, SecComputer_P.BitfromLabel1_bit_a, &rtb_Switch7_c); - rtb_AND1_h = (rtb_Switch7_c != 0U); + rtb_AND4_a = (rtb_Switch7_c != 0U); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.lgciu_2_bus.discrete_word_2, SecComputer_P.BitfromLabel3_bit_m, &rtb_Switch7_c); - SecComputer_MATLABFunction_e(rtb_y_b || (rtb_AND1_h || (rtb_Switch7_c != 0U)), - SecComputer_P.PulseNode_isRisingEdge_hj, &rtb_y_l, &SecComputer_DWork.sf_MATLABFunction_e3); - SecComputer_DWork.Delay_DSTATE_n = (((((SecComputer_U.in.analog_inputs.spd_brk_lever_pos > - SecComputer_P.CompareToConstant10_const) || rtb_NOT_bl) && ((SecComputer_U.in.analog_inputs.thr_lever_1_pos <= - SecComputer_P.CompareToConstant7_const) && (SecComputer_U.in.analog_inputs.thr_lever_2_pos <= - SecComputer_P.CompareToConstant16_const))) || (((SecComputer_U.in.analog_inputs.thr_lever_1_pos < - SecComputer_P.CompareToConstant17_const) && (SecComputer_U.in.analog_inputs.thr_lever_2_pos <= - SecComputer_P.CompareToConstant18_const)) || ((SecComputer_U.in.analog_inputs.thr_lever_1_pos <= - SecComputer_P.CompareToConstant8_const) && (SecComputer_U.in.analog_inputs.thr_lever_2_pos < - SecComputer_P.CompareToConstant9_const)))) && (rtb_y_l || SecComputer_DWork.Delay_DSTATE_n)); - rtb_AND1_h = ((!SecComputer_DWork.Delay1_DSTATE_i) && SecComputer_DWork.Delay_DSTATE_n); + rtb_y_l = (rtb_Switch7_c != 0U); + SecComputer_MATLABFunction_e(rtb_y_la || (rtb_AND4_a || (rtb_Switch7_c != 0U)), + SecComputer_P.PulseNode_isRisingEdge_hj, &rtb_y_ei, &SecComputer_DWork.sf_MATLABFunction_e3); + SecComputer_DWork.Delay_DSTATE_n = (rtb_AND1_h && (rtb_y_ei || SecComputer_DWork.Delay_DSTATE_n)); + rtb_AND4_a = (SecComputer_U.in.analog_inputs.thr_lever_2_pos <= SecComputer_P.CompareToConstant8_const); + SecComputer_DWork.Delay2_DSTATE = (rtb_NOT_bl && ((SecComputer_U.in.analog_inputs.thr_lever_1_pos <= + SecComputer_P.CompareToConstant7_const) && rtb_AND4_a) && (rtb_y_j || SecComputer_DWork.Delay2_DSTATE)); + rtb_AND1_h = ((!SecComputer_DWork.Delay1_DSTATE_i) && (SecComputer_DWork.Delay_DSTATE_n || + SecComputer_DWork.Delay2_DSTATE)); SecComputer_Y.out.logic.total_sidestick_roll_command = pair1SpdBrkCommand; - rtb_y_b = rtb_NOT_bl; + rtb_y_la = rtb_NOT_bl; if (SecComputer_DWork.Delay1_DSTATE_i) { rtb_Switch5 = SecComputer_P.Constant_Value; } else if (rtb_AND1_h) { @@ -830,7 +833,7 @@ void SecComputer::step() SecComputer_P.BitfromLabel4_bit_m, &rtb_Switch7_c); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.elac_2_bus.discrete_status_word_2, SecComputer_P.BitfromLabel5_bit_h, &rtb_y); - if (rtb_y_m) { + if (rtb_y_f5) { rtb_Switch3 = SecComputer_P.Constant3_Value; } else { if ((rtb_Switch7_c != 0U) || (rtb_y != 0U)) { @@ -861,26 +864,26 @@ void SecComputer::step() SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.elac_1_bus.discrete_status_word_1, SecComputer_P.BitfromLabel2_bit_o, &rtb_y_af); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.elac_2_bus.discrete_status_word_1, - SecComputer_P.BitfromLabel3_bit_j, &rtb_y_mx); + SecComputer_P.BitfromLabel3_bit_j, &rtb_y_m); if (SecComputer_U.in.bus_inputs.elac_1_bus.roll_spoiler_command_deg.SSM == static_cast(SignStatusMatrix:: NormalOperation)) { pair1SpdBrkCommand = SecComputer_U.in.bus_inputs.elac_1_bus.roll_spoiler_command_deg.Data; - rtb_y_l = (rtb_Switch7_c != 0U); - rtb_AND4_a = (rtb_y_af != 0U); + rtb_y_j = (rtb_Switch7_c != 0U); + rtb_y_ei = (rtb_y_af != 0U); } else if (SecComputer_U.in.bus_inputs.elac_2_bus.roll_spoiler_command_deg.SSM == static_cast (SignStatusMatrix::NormalOperation)) { pair1SpdBrkCommand = SecComputer_U.in.bus_inputs.elac_2_bus.roll_spoiler_command_deg.Data; - rtb_y_l = (rtb_y != 0U); - rtb_AND4_a = (rtb_y_mx != 0U); + rtb_y_j = (rtb_y != 0U); + rtb_y_ei = (rtb_y_m != 0U); } else { pair1SpdBrkCommand = rtb_Switch3 * 35.0 / 25.0; - rtb_y_l = true; - rtb_AND4_a = true; + rtb_y_j = true; + rtb_y_ei = true; } rtb_zeta_deg = std::fmax(std::fmin(pair1SpdBrkCommand, 35.0), -35.0); if (SecComputer_U.in.discrete_inputs.is_unit_1) { - if (rtb_y_l) { + if (rtb_y_j) { pair1RollCommand = rtb_zeta_deg; } else { pair1RollCommand = 0.0; @@ -896,7 +899,7 @@ void SecComputer::step() pair2SpdBrkCommand = 0.0; } else { pair1RollCommand = 0.0; - if (rtb_AND4_a) { + if (rtb_y_ei) { rtb_Switch3 = rtb_zeta_deg; } else { rtb_Switch3 = 0.0; @@ -984,7 +987,7 @@ void SecComputer::step() pair1RollCommand = pair1SpdBrkCommand; rtb_NOT_oi = rtb_handleIndex; SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.sfcc_1_bus.slat_flap_system_status_word, - SecComputer_P.BitfromLabel_bit_a1, &rtb_y_mx); + SecComputer_P.BitfromLabel_bit_a1, &rtb_y_m); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.sfcc_1_bus.slat_flap_system_status_word, SecComputer_P.BitfromLabel1_bit_gf, &rtb_y_af); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.sfcc_1_bus.slat_flap_system_status_word, @@ -995,7 +998,7 @@ void SecComputer::step() SecComputer_P.BitfromLabel4_bit_n, &rtb_DataTypeConversion1); SecComputer_MATLABFunction(&SecComputer_U.in.bus_inputs.sfcc_1_bus.slat_flap_system_status_word, SecComputer_P.BitfromLabel5_bit_m, &rtb_Switch7_c); - if (rtb_y_mx != 0U) { + if (rtb_y_m != 0U) { rtb_handleIndex = 0.0; } else if ((rtb_y_af != 0U) && (rtb_Switch7_c != 0U)) { rtb_handleIndex = 1.0; @@ -1012,16 +1015,16 @@ void SecComputer::step() } pair1SpdBrkCommand = (SecComputer_B.in_flight != 0.0); - rtb_y_l = (rtb_OR3 || ((static_cast(rtb_activePitchLaw) != SecComputer_P.CompareToConstant2_const_f) && ( + rtb_y_j = (rtb_OR1 || ((static_cast(rtb_activePitchLaw) != SecComputer_P.CompareToConstant2_const_f) && ( static_cast(rtb_activePitchLaw) != SecComputer_P.CompareToConstant3_const_o))); - rtb_AND4_a = (rtb_activePitchLaw != SecComputer_P.EnumeratedConstant_Value_i); + rtb_y_ei = (rtb_activePitchLaw != SecComputer_P.EnumeratedConstant_Value_i); LawMDLOBJ2.step(&SecComputer_U.in.time.dt, &rtb_BusAssignment_f_logic_ir_computation_data_n_z_g, &rtb_Switch5_tmp_tmp, &rtb_Switch6_m, &rtb_BusAssignment_f_logic_ir_computation_data_theta_dot_deg_s, (const_cast(&SecComputer_RGND)), &SecComputer_U.in.analog_inputs.ths_pos_deg, &rtb_eta_trim_limit_lo_d, &rtb_BusConversion_InsertedFor_BusAssignment_at_inport_8_BusCreator1_mach, &rtb_BusConversion_InsertedFor_BusAssignment_at_inport_8_BusCreator1_V_tas_kn, &rtb_handleIndex, ( const_cast(&SecComputer_RGND)), (const_cast(&SecComputer_RGND)), &u0, &pair1SpdBrkCommand, - &rtb_y_l, &rtb_AND4_a, &rtb_eta_deg, &rtb_eta_trim_dot_deg_s, &rtb_eta_trim_limit_lo, + &rtb_y_j, &rtb_y_ei, &rtb_eta_deg, &rtb_eta_trim_dot_deg_s, &rtb_eta_trim_limit_lo, &rtb_eta_trim_limit_up); LawMDLOBJ3.step(&SecComputer_U.in.time.dt, &u0, &rtb_handleIndex, &rtb_zeta_deg, &rtb_eta_trim_limit_lo_d, &pair1SpdBrkCommand); @@ -1079,7 +1082,7 @@ void SecComputer::step() } rtb_zeta_deg = SecComputer_P.DiscreteTimeIntegratorVariableTsLimit_Gain * rtb_zeta_deg * SecComputer_U.in.time.dt; - SecComputer_DWork.icLoad = ((!rtb_y_k4) || SecComputer_DWork.icLoad); + SecComputer_DWork.icLoad = ((!rtb_y_ls) || SecComputer_DWork.icLoad); if (SecComputer_DWork.icLoad) { SecComputer_DWork.Delay_DSTATE_l = SecComputer_U.in.analog_inputs.ths_pos_deg - rtb_zeta_deg; } @@ -1113,28 +1116,28 @@ void SecComputer::step() } else if (SecComputer_U.in.discrete_inputs.is_unit_2) { rtb_Switch8 = SecComputer_U.in.bus_inputs.elac_1_bus.elevator_double_pressurization_command_deg; } else { - rtb_y_fp = std::fmod(std::floor(SecComputer_P.Constant1_Value_m), 4.2949673E+9F); - rtb_Switch8.SSM = rtb_y_fp < 0.0F ? static_cast(-static_cast(static_cast(-rtb_y_fp))) - : static_cast(rtb_y_fp); + rtb_y_e = std::fmod(std::floor(SecComputer_P.Constant1_Value_m), 4.2949673E+9F); + rtb_Switch8.SSM = rtb_y_e < 0.0F ? static_cast(-static_cast(static_cast(-rtb_y_e))) : + static_cast(rtb_y_e); rtb_Switch8.Data = SecComputer_P.Constant1_Value_m; } SecComputer_MATLABFunction_l(&rtb_Switch8, &rtb_AND4_a); if (SecComputer_U.in.discrete_inputs.is_unit_1) { - rtb_y_l = SecComputer_U.in.discrete_inputs.pitch_not_avail_elac_1; + rtb_y_j = SecComputer_U.in.discrete_inputs.pitch_not_avail_elac_1; } else { - rtb_y_l = SecComputer_U.in.discrete_inputs.pitch_not_avail_elac_2; + rtb_y_j = SecComputer_U.in.discrete_inputs.pitch_not_avail_elac_2; } - rtb_NOT_bl = (rtb_y_l && (!rtb_isEngagedInPitch) && rtb_AND4_a); + rtb_NOT_bl = (rtb_y_j && (!rtb_isEngagedInPitch) && rtb_AND4_a); if (rtb_NOT_bl) { rtb_handleIndex = rtb_Switch8.Data; } - SecComputer_MATLABFunction_n(rtb_OR || rtb_NOT2_b || rtb_NOT_g, SecComputer_U.in.time.dt, - SecComputer_P.ConfirmNode_isRisingEdge_c, SecComputer_P.ConfirmNode_timeDelay_m, &rtb_y_am, - &SecComputer_DWork.sf_MATLABFunction_i); - rtb_y_fp = static_cast(SecComputer_U.in.analog_inputs.thr_lever_2_pos); + SecComputer_MATLABFunction_n(rtb_NOT2_b || rtb_NOT_g || rtb_BusAssignment_fz_logic_is_green_hydraulic_power_avail, + SecComputer_U.in.time.dt, SecComputer_P.ConfirmNode_isRisingEdge_c, SecComputer_P.ConfirmNode_timeDelay_m, + &rtb_y_l, &SecComputer_DWork.sf_MATLABFunction_i); + rtb_y_e = static_cast(SecComputer_U.in.analog_inputs.thr_lever_2_pos); rtb_VectorConcatenate[0] = (SecComputer_U.in.discrete_inputs.l_spoiler_1_servo_failed || SecComputer_U.in.discrete_inputs.r_spoiler_1_servo_failed); rtb_VectorConcatenate[1] = (SecComputer_U.in.discrete_inputs.l_spoiler_2_servo_failed || @@ -1143,7 +1146,7 @@ void SecComputer::step() rtb_VectorConcatenate[3] = SecComputer_U.in.discrete_inputs.r_elev_servo_failed; rtb_VectorConcatenate[4] = spoilerPair1SupplyAvail; rtb_VectorConcatenate[5] = spoilerPair2SupplyAvail; - rtb_VectorConcatenate[6] = leftElevatorAvail; + rtb_VectorConcatenate[6] = rtb_OR3; rtb_VectorConcatenate[7] = rightElevatorAvail; rtb_VectorConcatenate[8] = (rtb_activePitchLaw == pitch_efcs_law::AlternateLaw2); rtb_VectorConcatenate[9] = ((rtb_activePitchLaw == pitch_efcs_law::AlternateLaw1) || (rtb_activePitchLaw == @@ -1153,18 +1156,18 @@ void SecComputer::step() rtb_VectorConcatenate[12] = rtb_isEngagedInPitch; rtb_VectorConcatenate[13] = SecComputer_P.Constant8_Value; rtb_VectorConcatenate[14] = SecComputer_DWork.Delay1_DSTATE_i; - rtb_VectorConcatenate[15] = rtb_y_b; + rtb_VectorConcatenate[15] = rtb_y_la; rtb_VectorConcatenate[16] = SecComputer_P.Constant8_Value; rtb_VectorConcatenate[17] = SecComputer_P.Constant8_Value; rtb_VectorConcatenate[18] = SecComputer_P.Constant8_Value; - SecComputer_MATLABFunction_c(rtb_VectorConcatenate, &rtb_y_h); + SecComputer_MATLABFunction_c(rtb_VectorConcatenate, &rtb_y_fn); rtb_VectorConcatenate[0] = SecComputer_P.Constant7_Value; rtb_VectorConcatenate[1] = SecComputer_P.Constant7_Value; rtb_VectorConcatenate[2] = SecComputer_DWork.pLeftStickDisabled; rtb_VectorConcatenate[3] = SecComputer_DWork.pRightStickDisabled; rtb_VectorConcatenate[4] = SecComputer_DWork.Delay_DSTATE_c; rtb_VectorConcatenate[5] = SecComputer_DWork.Delay1_DSTATE; - rtb_VectorConcatenate[6] = rtb_OR6; + rtb_VectorConcatenate[6] = rtb_OR; rtb_VectorConcatenate[7] = rtb_BusAssignment_n_logic_any_landing_gear_not_uplocked; rtb_VectorConcatenate[8] = SecComputer_P.Constant10_Value; rtb_VectorConcatenate[9] = SecComputer_P.Constant10_Value; @@ -1177,7 +1180,7 @@ void SecComputer::step() rtb_VectorConcatenate[16] = SecComputer_P.Constant10_Value; rtb_VectorConcatenate[17] = SecComputer_P.Constant10_Value; rtb_VectorConcatenate[18] = SecComputer_P.Constant10_Value; - SecComputer_MATLABFunction_c(rtb_VectorConcatenate, &rtb_y_fp); + SecComputer_MATLABFunction_c(rtb_VectorConcatenate, &rtb_y_e); SecComputer_Y.out.data = SecComputer_U.in; SecComputer_Y.out.laws.lateral_law_outputs.left_spoiler_1_command_deg = rtb_Switch3; SecComputer_Y.out.laws.lateral_law_outputs.right_spoiler_1_command_deg = pair2SpdBrkCommand; @@ -1185,35 +1188,35 @@ void SecComputer::step() SecComputer_Y.out.laws.lateral_law_outputs.right_spoiler_2_command_deg = rtb_NOT_oi; SecComputer_Y.out.laws.lateral_law_outputs.speedbrake_command_deg = rtb_Switch5; SecComputer_Y.out.laws.pitch_law_outputs.ths_command_deg = SecComputer_DWork.Delay_DSTATE; - SecComputer_Y.out.logic.on_ground = rtb_OR1; + SecComputer_Y.out.logic.on_ground = rtb_OR6; SecComputer_Y.out.logic.pitch_law_in_flight = (SecComputer_B.in_flight != 0.0); - SecComputer_Y.out.logic.tracking_mode_on = rtb_OR3; + SecComputer_Y.out.logic.tracking_mode_on = rtb_OR1; SecComputer_Y.out.logic.pitch_law_capability = rtb_pitchLawCapability; SecComputer_Y.out.logic.active_pitch_law = rtb_activePitchLaw; SecComputer_Y.out.logic.abnormal_condition_law_active = abnormalCondition; SecComputer_Y.out.logic.is_engaged_in_pitch = rtb_isEngagedInPitch; SecComputer_Y.out.logic.can_engage_in_pitch = canEngageInPitch; SecComputer_Y.out.logic.has_priority_in_pitch = hasPriorityInPitch; - SecComputer_Y.out.logic.left_elevator_avail = leftElevatorAvail; + SecComputer_Y.out.logic.left_elevator_avail = rtb_OR3; SecComputer_Y.out.logic.right_elevator_avail = rightElevatorAvail; SecComputer_Y.out.logic.ths_avail = rtb_thsAvail; - SecComputer_Y.out.logic.ths_active_commanded = rtb_y_k4; + SecComputer_Y.out.logic.ths_active_commanded = rtb_y_ls; SecComputer_Y.out.logic.ths_ground_setting_active = rtb_AND2_j; SecComputer_Y.out.logic.is_engaged_in_roll = rtb_isEngagedInRoll; SecComputer_Y.out.logic.spoiler_pair_1_avail = spoilerPair1SupplyAvail; SecComputer_Y.out.logic.spoiler_pair_2_avail = spoilerPair2SupplyAvail; - SecComputer_Y.out.logic.is_yellow_hydraulic_power_avail = rtb_OR; - SecComputer_Y.out.logic.is_blue_hydraulic_power_avail = rtb_NOT2_b; - SecComputer_Y.out.logic.is_green_hydraulic_power_avail = rtb_NOT_g; + SecComputer_Y.out.logic.is_yellow_hydraulic_power_avail = rtb_NOT2_b; + SecComputer_Y.out.logic.is_blue_hydraulic_power_avail = rtb_NOT_g; + SecComputer_Y.out.logic.is_green_hydraulic_power_avail = rtb_BusAssignment_fz_logic_is_green_hydraulic_power_avail; SecComputer_Y.out.logic.left_sidestick_disabled = SecComputer_DWork.pLeftStickDisabled; SecComputer_Y.out.logic.right_sidestick_disabled = SecComputer_DWork.pRightStickDisabled; SecComputer_Y.out.logic.left_sidestick_priority_locked = SecComputer_DWork.Delay_DSTATE_c; SecComputer_Y.out.logic.right_sidestick_priority_locked = SecComputer_DWork.Delay1_DSTATE; SecComputer_Y.out.logic.total_sidestick_pitch_command = u0; - SecComputer_Y.out.logic.ground_spoilers_armed = rtb_y_b; + SecComputer_Y.out.logic.ground_spoilers_armed = rtb_y_la; SecComputer_Y.out.logic.ground_spoilers_out = SecComputer_DWork.Delay1_DSTATE_i; SecComputer_Y.out.logic.partial_lift_dumping_active = rtb_AND1_h; - SecComputer_Y.out.logic.speed_brake_inhibited = rtb_y_m; + SecComputer_Y.out.logic.speed_brake_inhibited = rtb_y_f5; SecComputer_Y.out.logic.single_adr_failure = rtb_singleAdrFault; SecComputer_Y.out.logic.double_adr_failure = rtb_doubleAdrFault; SecComputer_Y.out.logic.cas_or_mach_disagree = SecComputer_P.Constant2_Value_c; @@ -1235,30 +1238,30 @@ void SecComputer::step() SecComputer_Y.out.logic.ir_computation_data.theta_dot_deg_s = rtb_theta_dot; SecComputer_Y.out.logic.ir_computation_data.phi_dot_deg_s = rtb_phi_dot; SecComputer_Y.out.logic.any_landing_gear_not_uplocked = rtb_BusAssignment_n_logic_any_landing_gear_not_uplocked; - SecComputer_Y.out.logic.lgciu_uplock_disagree_or_fault = rtb_OR6; + SecComputer_Y.out.logic.lgciu_uplock_disagree_or_fault = rtb_OR; SecComputer_Y.out.discrete_outputs.thr_reverse_selected = SecComputer_P.Constant1_Value_g; - SecComputer_Y.out.discrete_outputs.left_elevator_ok = leftElevatorAvail; + SecComputer_Y.out.discrete_outputs.left_elevator_ok = rtb_OR3; SecComputer_Y.out.discrete_outputs.right_elevator_ok = rightElevatorAvail; SecComputer_Y.out.discrete_outputs.ground_spoiler_out = SecComputer_DWork.Delay1_DSTATE_i; SecComputer_Y.out.discrete_outputs.sec_failed = SecComputer_P.Constant2_Value_n; - SecComputer_Y.out.discrete_outputs.left_elevator_damping_mode = (rtb_isEngagedInPitch && leftElevatorAvail); + SecComputer_Y.out.discrete_outputs.left_elevator_damping_mode = (rtb_isEngagedInPitch && rtb_OR3); SecComputer_Y.out.discrete_outputs.right_elevator_damping_mode = (rtb_isEngagedInPitch && rightElevatorAvail); - SecComputer_Y.out.discrete_outputs.ths_active = (rtb_y_k4 && rtb_thsAvail); - SecComputer_Y.out.discrete_outputs.batt_power_supply = rtb_y_am; - rtb_y_l = (rtb_isEngagedInPitch || rtb_NOT_bl); - if (rtb_y_l && leftElevatorAvail) { + SecComputer_Y.out.discrete_outputs.ths_active = (rtb_y_ls && rtb_thsAvail); + SecComputer_Y.out.discrete_outputs.batt_power_supply = rtb_y_l; + rtb_y_j = (rtb_isEngagedInPitch || rtb_NOT_bl); + if (rtb_y_j && rtb_OR3) { SecComputer_Y.out.analog_outputs.left_elev_pos_order_deg = rtb_handleIndex; } else { SecComputer_Y.out.analog_outputs.left_elev_pos_order_deg = SecComputer_P.Constant_Value_h; } - if (rtb_y_l && rightElevatorAvail) { + if (rtb_y_j && rightElevatorAvail) { SecComputer_Y.out.analog_outputs.right_elev_pos_order_deg = rtb_handleIndex; } else { SecComputer_Y.out.analog_outputs.right_elev_pos_order_deg = SecComputer_P.Constant_Value_h; } - if (rtb_y_k4 && rtb_thsAvail) { + if (rtb_y_ls && rtb_thsAvail) { SecComputer_Y.out.analog_outputs.ths_pos_order_deg = SecComputer_DWork.Delay_DSTATE; } else { SecComputer_Y.out.analog_outputs.ths_pos_order_deg = SecComputer_P.Constant_Value_h; @@ -1394,10 +1397,10 @@ void SecComputer::step() (SecComputer_U.in.analog_inputs.thr_lever_2_pos); SecComputer_Y.out.bus_outputs.discrete_status_word_1.SSM = static_cast (SecComputer_P.EnumeratedConstant1_Value); - SecComputer_Y.out.bus_outputs.discrete_status_word_1.Data = rtb_y_h; + SecComputer_Y.out.bus_outputs.discrete_status_word_1.Data = rtb_y_fn; SecComputer_Y.out.bus_outputs.discrete_status_word_2.SSM = static_cast (SecComputer_P.EnumeratedConstant1_Value); - SecComputer_Y.out.bus_outputs.discrete_status_word_2.Data = rtb_y_fp; + SecComputer_Y.out.bus_outputs.discrete_status_word_2.Data = rtb_y_e; SecComputer_DWork.icLoad = false; SecComputer_DWork.Delay_DSTATE_l = SecComputer_DWork.Delay_DSTATE; } else { @@ -1414,6 +1417,7 @@ void SecComputer::initialize() SecComputer_DWork.Memory_PreviousInput_n = SecComputer_P.SRFlipFlop_initial_condition_k; SecComputer_DWork.Delay1_DSTATE_i = SecComputer_P.Delay1_InitialCondition_l; SecComputer_DWork.Delay_DSTATE_n = SecComputer_P.Delay_InitialCondition_j; + SecComputer_DWork.Delay2_DSTATE = SecComputer_P.Delay2_InitialCondition; SecComputer_DWork.Delay_DSTATE = SecComputer_P.Delay_InitialCondition; SecComputer_DWork.icLoad = true; LawMDLOBJ2.init(); diff --git a/src/fbw_a320/src/model/SecComputer.h b/src/fbw_a320/src/model/SecComputer.h index ae7935deeff..ede5cfbd4d8 100644 --- a/src/fbw_a320/src/model/SecComputer.h +++ b/src/fbw_a320/src/model/SecComputer.h @@ -46,6 +46,7 @@ class SecComputer final boolean_T Delay1_DSTATE; boolean_T Delay1_DSTATE_i; boolean_T Delay_DSTATE_n; + boolean_T Delay2_DSTATE; uint8_T is_active_c30_SecComputer; uint8_T is_c30_SecComputer; uint8_T is_active_c8_SecComputer; @@ -163,13 +164,8 @@ class SecComputer final real_T CompareToConstant4_const_j; real_T CompareToConstant13_const; real_T CompareToConstant14_const; - real_T CompareToConstant10_const; real_T CompareToConstant7_const; - real_T CompareToConstant16_const; - real_T CompareToConstant17_const; - real_T CompareToConstant18_const; real_T CompareToConstant8_const; - real_T CompareToConstant9_const; real_T CompareToConstant2_const_f; real_T CompareToConstant3_const_o; real_T CompareToConstant1_const_p; @@ -277,6 +273,7 @@ class SecComputer final boolean_T Logic_table_ii[16]; boolean_T Delay1_InitialCondition_l; boolean_T Delay_InitialCondition_j; + boolean_T Delay2_InitialCondition; boolean_T Constant1_Value_g; boolean_T Constant2_Value_n; boolean_T Constant8_Value; diff --git a/src/fbw_a320/src/model/SecComputer_data.cpp b/src/fbw_a320/src/model/SecComputer_data.cpp index 5de3d3e38c7..18ad6a448bb 100644 --- a/src/fbw_a320/src/model/SecComputer_data.cpp +++ b/src/fbw_a320/src/model/SecComputer_data.cpp @@ -242,19 +242,9 @@ SecComputer::Parameters_SecComputer_T SecComputer::SecComputer_P{ 0.0, - 0.05, - - 0.0, - - 0.0, - - 0.0, + 25.0, - 35.0, - - 35.0, - - 0.0, + 25.0, 1.0, @@ -1747,5 +1737,7 @@ SecComputer::Parameters_SecComputer_T SecComputer::SecComputer_P{ false, + false, + false }; From 79afedeb14dd198a6cc7214477fee9a99ff4b0fa Mon Sep 17 00:00:00 2001 From: crocket63 <38904654+crocket63@users.noreply.github.com> Date: Fri, 30 Dec 2022 16:34:46 +0100 Subject: [PATCH 07/39] feat(hyd): faster core hydraulics solver (#7635) --- .github/CHANGELOG.md | 1 + src/systems/a320_systems/src/hydraulic/mod.rs | 190 ++++++++---------- src/systems/a380_systems/src/hydraulic/mod.rs | 108 ++++------ .../src/hydraulic/electrical_generator.rs | 10 +- .../src/hydraulic/electrical_pump_physics.rs | 6 +- .../systems/src/hydraulic/flap_slat.rs | 6 +- .../systems/src/hydraulic/landing_gear.rs | 38 ++-- .../systems/src/hydraulic/linear_actuator.rs | 125 ++++++------ src/systems/systems/src/hydraulic/mod.rs | 11 +- .../trimmable_horizontal_stabilizer.rs | 10 +- 10 files changed, 229 insertions(+), 276 deletions(-) diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index 532ce5e4e6e..bd35d741bec 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -10,6 +10,7 @@ 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) 1. [FMGC] Don't accept blank input or / for hold distance - @tracernz (Mike) +1. [HYD] Faster core hydraulics solver - @Crocket63 (crocket) 1. [ATSU] Fix LSK6L not returning to ATSU DATALINK page in ATC MENU - @BravoMike99 (Bruno_pt99#5802) 1. [HYD] Trimmable physical assemblies - @Crocket63 (crocket) 1. [HYD] Simulation of the rudder mechanical assembly and yaw dampers - @Crocket63 (crocket) diff --git a/src/systems/a320_systems/src/hydraulic/mod.rs b/src/systems/a320_systems/src/hydraulic/mod.rs index b0c1e38f093..3d5f992824a 100644 --- a/src/systems/a320_systems/src/hydraulic/mod.rs +++ b/src/systems/a320_systems/src/hydraulic/mod.rs @@ -56,16 +56,14 @@ use systems::{ AutoOffFaultPushButton, AutoOnFaultPushButton, MomentaryOnPushButton, MomentaryPushButton, }, shared::{ - interpolation, - low_pass_filter::LowPassFilter, - random_from_normal_distribution, random_from_range, - update_iterator::{FixedStepLoop, MaxStepLoop}, - AdirsDiscreteOutputs, AirbusElectricPumpId, AirbusEngineDrivenPumpId, - DelayedFalseLogicGate, DelayedPulseTrueLogicGate, DelayedTrueLogicGate, ElectricalBusType, - ElectricalBuses, EmergencyElectricalRatPushButton, EmergencyElectricalState, - EmergencyGeneratorPower, EngineFirePushButtons, GearWheel, HydraulicColor, - HydraulicGeneratorControlUnit, LandingGearHandle, LgciuInterface, LgciuWeightOnWheels, - ReservoirAirPressure, SectionPressure, TrimmableHorizontalStabilizer, + interpolation, low_pass_filter::LowPassFilter, random_from_normal_distribution, + random_from_range, update_iterator::MaxStepLoop, AdirsDiscreteOutputs, + AirbusElectricPumpId, AirbusEngineDrivenPumpId, DelayedFalseLogicGate, + DelayedPulseTrueLogicGate, DelayedTrueLogicGate, ElectricalBusType, ElectricalBuses, + EmergencyElectricalRatPushButton, EmergencyElectricalState, EmergencyGeneratorPower, + EngineFirePushButtons, GearWheel, HydraulicColor, HydraulicGeneratorControlUnit, + LandingGearHandle, LgciuInterface, LgciuWeightOnWheels, ReservoirAirPressure, + SectionPressure, TrimmableHorizontalStabilizer, }, simulation::{ InitContext, Read, Reader, SimulationElement, SimulationElementVisitor, SimulatorReader, @@ -1423,9 +1421,7 @@ pub(super) struct A320Hydraulic { nose_steering: SteeringActuator, - core_hydraulic_updater: FixedStepLoop, - physics_updater: MaxStepLoop, - ultra_fast_physics_updater: MaxStepLoop, + core_hydraulic_updater: MaxStepLoop, brake_steer_computer: A320HydraulicBrakeSteerComputerUnit, @@ -1542,13 +1538,7 @@ impl A320Hydraulic { ElectricalBusType::DirectCurrentHot(2); // Refresh rate of core hydraulic simulation - const HYDRAULIC_SIM_TIME_STEP: Duration = Duration::from_millis(33); - // Refresh rate of max fixed step loop for fast physics - const HYDRAULIC_SIM_MAX_TIME_STEP_MILLISECONDS: Duration = Duration::from_millis(33); - // Refresh rate of max fixed step loop for fastest flight controls physics needing super stability - // and fast reacting time - const HYDRAULIC_SIM_FLIGHT_CONTROLS_MAX_TIME_STEP_MILLISECONDS: Duration = - Duration::from_millis(10); + const HYDRAULIC_SIM_TIME_STEP: Duration = Duration::from_millis(10); pub(super) fn new(context: &mut InitContext) -> A320Hydraulic { A320Hydraulic { @@ -1564,11 +1554,7 @@ impl A320Hydraulic { Ratio::new::(0.18), ), - core_hydraulic_updater: FixedStepLoop::new(Self::HYDRAULIC_SIM_TIME_STEP), - physics_updater: MaxStepLoop::new(Self::HYDRAULIC_SIM_MAX_TIME_STEP_MILLISECONDS), - ultra_fast_physics_updater: MaxStepLoop::new( - Self::HYDRAULIC_SIM_FLIGHT_CONTROLS_MAX_TIME_STEP_MILLISECONDS, - ), + core_hydraulic_updater: MaxStepLoop::new(Self::HYDRAULIC_SIM_TIME_STEP), brake_steer_computer: A320HydraulicBrakeSteerComputerUnit::new(context), @@ -1785,19 +1771,6 @@ impl A320Hydraulic { adirs: &impl AdirsDiscreteOutputs, ) { self.core_hydraulic_updater.update(context); - self.physics_updater.update(context); - self.ultra_fast_physics_updater.update(context); - - for cur_time_step in self.physics_updater { - self.update_fast_physics( - &context.with_delta(cur_time_step), - rat_and_emer_gen_man_on, - emergency_elec, - lgcius.lgciu1(), - lgcius.lgciu2(), - adirs, - ); - } self.update_with_sim_rate( context, @@ -1811,11 +1784,15 @@ impl A320Hydraulic { engine2, ); - for cur_time_step in self.ultra_fast_physics_updater { - self.update_ultra_fast_physics(&context.with_delta(cur_time_step), lgcius); - } - for cur_time_step in self.core_hydraulic_updater { + self.update_physics( + &context.with_delta(cur_time_step), + rat_and_emer_gen_man_on, + emergency_elec, + lgcius, + adirs, + ); + self.update_core_hydraulics( &context.with_delta(cur_time_step), engine1, @@ -1916,11 +1893,70 @@ impl A320Hydraulic { self.yellow_circuit.system_section_pressure_switch() == PressureSwitchState::Pressurised } - fn update_ultra_fast_physics( + // Updates at the same rate as the sim or at a fixed maximum time step if sim rate is too slow + fn update_physics( &mut self, context: &UpdateContext, + rat_and_emer_gen_man_on: &impl EmergencyElectricalRatPushButton, + emergency_elec: &(impl EmergencyElectricalState + EmergencyGeneratorPower), lgcius: &LandingGearControlInterfaceUnitSet, + adirs: &impl AdirsDiscreteOutputs, ) { + self.forward_cargo_door.update( + context, + &self.forward_cargo_door_controller, + self.yellow_circuit.system_section(), + ); + + self.aft_cargo_door.update( + context, + &self.aft_cargo_door_controller, + self.yellow_circuit.system_section(), + ); + + self.ram_air_turbine.update_physics( + &context.delta(), + context.indicated_airspeed(), + self.blue_circuit.system_section(), + ); + + self.gcu.update( + context, + &self.emergency_gen, + self.blue_circuit.system_section(), + emergency_elec, + rat_and_emer_gen_man_on, + lgcius.lgciu1(), + ); + + self.emergency_gen.update( + context, + self.blue_circuit.system_section(), + &self.gcu, + emergency_elec, + ); + + self.gear_system_hydraulic_controller.update( + adirs, + lgcius.lgciu1(), + lgcius.lgciu2(), + &self.gear_system_gravity_extension_controller, + ); + + self.trim_assembly.update( + context, + &self.trim_controller, + &self.trim_controller, + [ + self.green_circuit + .system_section() + .pressure_downstream_leak_valve(), + self.yellow_circuit + .system_section() + .pressure_downstream_leak_valve(), + ], + ); + self.left_aileron.update( context, self.aileron_system_controller.left_controllers(), @@ -1981,72 +2017,6 @@ impl A320Hydraulic { ); } - // Updates at the same rate as the sim or at a fixed maximum time step if sim rate is too slow - fn update_fast_physics( - &mut self, - context: &UpdateContext, - rat_and_emer_gen_man_on: &impl EmergencyElectricalRatPushButton, - emergency_elec: &(impl EmergencyElectricalState + EmergencyGeneratorPower), - lgciu1: &impl LgciuInterface, - lgciu2: &impl LgciuInterface, - adirs: &impl AdirsDiscreteOutputs, - ) { - self.forward_cargo_door.update( - context, - &self.forward_cargo_door_controller, - self.yellow_circuit.system_section(), - ); - - self.aft_cargo_door.update( - context, - &self.aft_cargo_door_controller, - self.yellow_circuit.system_section(), - ); - - self.ram_air_turbine.update_physics( - &context.delta(), - context.indicated_airspeed(), - self.blue_circuit.system_section(), - ); - - self.gcu.update( - context, - &self.emergency_gen, - self.blue_circuit.system_section(), - emergency_elec, - rat_and_emer_gen_man_on, - lgciu1, - ); - - self.emergency_gen.update( - context, - self.blue_circuit.system_section(), - &self.gcu, - emergency_elec, - ); - - self.gear_system_hydraulic_controller.update( - adirs, - lgciu1, - lgciu2, - &self.gear_system_gravity_extension_controller, - ); - - self.trim_assembly.update( - context, - &self.trim_controller, - &self.trim_controller, - [ - self.green_circuit - .system_section() - .pressure_downstream_leak_valve(), - self.yellow_circuit - .system_section() - .pressure_downstream_leak_valve(), - ], - ); - } - fn update_with_sim_rate( &mut self, context: &UpdateContext, @@ -10525,7 +10495,7 @@ mod tests { .set_cold_dark_inputs() .start_eng1(Ratio::new::(80.)) .start_eng2(Ratio::new::(80.)) - .run_waiting_for(Duration::from_millis(500)); + .run_waiting_for(Duration::from_millis(1000)); assert!(!test_bed.ptu_has_fault()); assert!(!test_bed.green_edp_has_fault()); diff --git a/src/systems/a380_systems/src/hydraulic/mod.rs b/src/systems/a380_systems/src/hydraulic/mod.rs index f093da09f1e..8e4318c97e8 100644 --- a/src/systems/a380_systems/src/hydraulic/mod.rs +++ b/src/systems/a380_systems/src/hydraulic/mod.rs @@ -1890,14 +1890,7 @@ impl A380Hydraulic { ); for cur_time_step in self.core_hydraulic_updater { - self.update_fast_physics( - &context.with_delta(cur_time_step), - lgcius.lgciu1(), - lgcius.lgciu2(), - adirs, - ); - - self.update_ultra_fast_physics(&context.with_delta(cur_time_step), lgcius); + self.update_physics(&context.with_delta(cur_time_step), lgcius, adirs); self.update_core_hydraulics( &context.with_delta(cur_time_step), @@ -1957,11 +1950,45 @@ impl A380Hydraulic { self.yellow_circuit.system_section_pressure_switch() == PressureSwitchState::Pressurised } - fn update_ultra_fast_physics( + fn update_physics( &mut self, context: &UpdateContext, lgcius: &LandingGearControlInterfaceUnitSet, + adirs: &impl AdirsDiscreteOutputs, ) { + self.forward_cargo_door.update( + context, + &self.forward_cargo_door_controller, + self.green_circuit.auxiliary_section(), + ); + + self.aft_cargo_door.update( + context, + &self.aft_cargo_door_controller, + self.green_circuit.auxiliary_section(), + ); + + self.gear_system_hydraulic_controller.update( + adirs, + lgcius.lgciu1(), + lgcius.lgciu2(), + &self.gear_system_gravity_extension_controller, + ); + + self.trim_assembly.update( + context, + &self.trim_controller, + &self.trim_controller, + [ + self.green_circuit + .system_section() + .pressure_downstream_leak_valve(), + self.yellow_circuit + .system_section() + .pressure_downstream_leak_valve(), + ], + ); + self.left_aileron.update( context, [ @@ -2080,48 +2107,6 @@ impl A380Hydraulic { ); } - // Updates at the same rate as the sim or at a fixed maximum time step if sim rate is too slow - fn update_fast_physics( - &mut self, - context: &UpdateContext, - lgciu1: &impl LgciuInterface, - lgciu2: &impl LgciuInterface, - adirs: &impl AdirsDiscreteOutputs, - ) { - self.forward_cargo_door.update( - context, - &self.forward_cargo_door_controller, - self.green_circuit.auxiliary_section(), - ); - - self.aft_cargo_door.update( - context, - &self.aft_cargo_door_controller, - self.green_circuit.auxiliary_section(), - ); - - self.gear_system_hydraulic_controller.update( - adirs, - lgciu1, - lgciu2, - &self.gear_system_gravity_extension_controller, - ); - - self.trim_assembly.update( - context, - &self.trim_controller, - &self.trim_controller, - [ - self.green_circuit - .system_section() - .pressure_downstream_leak_valve(), - self.yellow_circuit - .system_section() - .pressure_downstream_leak_valve(), - ], - ); - } - fn update_with_sim_rate( &mut self, context: &UpdateContext, @@ -10019,27 +10004,6 @@ mod tests { assert!(test_bed.yellow_pressure().get::() < 3500.); } - #[test] - fn low_air_press_fault_causes_ptu_fault() { - let mut test_bed = test_bed_on_ground_with() - .engines_off() - .on_the_ground() - .set_cold_dark_inputs() - .start_eng1(Ratio::new::(80.)) - .start_eng2(Ratio::new::(80.)) - .run_waiting_for(Duration::from_millis(500)); - - assert!(!test_bed.green_edp_has_fault()); - assert!(!test_bed.yellow_edp_has_fault()); - - test_bed = test_bed - .air_press_low() - .run_waiting_for(Duration::from_secs_f64(10.)); - - assert!(test_bed.green_edp_has_fault()); - assert!(test_bed.yellow_edp_has_fault()); - } - #[test] fn ailerons_are_dropped_down_in_cold_and_dark() { let mut test_bed = test_bed_on_ground_with() diff --git a/src/systems/systems/src/hydraulic/electrical_generator.rs b/src/systems/systems/src/hydraulic/electrical_generator.rs index e5e85daa0f4..3ff0f08f8cd 100644 --- a/src/systems/systems/src/hydraulic/electrical_generator.rs +++ b/src/systems/systems/src/hydraulic/electrical_generator.rs @@ -364,7 +364,7 @@ impl EmergencyGeneratorPower for TestGenerator { #[cfg(test)] mod tests { use super::*; - use crate::shared::update_iterator::FixedStepLoop; + use crate::shared::update_iterator::MaxStepLoop; use crate::simulation::test::{SimulationTestBed, TestBed}; use crate::simulation::{Aircraft, SimulationElement, SimulationElementVisitor}; use std::time::Duration; @@ -478,7 +478,7 @@ mod tests { } struct TestAircraft { - updater_fixed_step: FixedStepLoop, + updater_max_step: MaxStepLoop, gcu: GeneratorControlUnit<9>, lgciu: TestLgciuSensors, @@ -491,7 +491,7 @@ mod tests { impl TestAircraft { fn new(context: &mut InitContext) -> Self { Self { - updater_fixed_step: FixedStepLoop::new(Duration::from_millis(33)), + updater_max_step: MaxStepLoop::new(Duration::from_millis(10)), gcu: gen_control_unit(), lgciu: TestLgciuSensors::compressed(), rat_man_on: TestRatManOn::not_pressed(), @@ -524,9 +524,9 @@ mod tests { } impl Aircraft for TestAircraft { fn update_after_power_distribution(&mut self, context: &UpdateContext) { - self.updater_fixed_step.update(context); + self.updater_max_step.update(context); - for cur_time_step in &mut self.updater_fixed_step { + for cur_time_step in &mut self.updater_max_step { self.gcu.update( &context.with_delta(cur_time_step), &self.emergency_gen, diff --git a/src/systems/systems/src/hydraulic/electrical_pump_physics.rs b/src/systems/systems/src/hydraulic/electrical_pump_physics.rs index d7e9f29fb1e..329be545db9 100644 --- a/src/systems/systems/src/hydraulic/electrical_pump_physics.rs +++ b/src/systems/systems/src/hydraulic/electrical_pump_physics.rs @@ -301,7 +301,7 @@ mod tests { use crate::electrical::ElectricalBus; use crate::electrical::Electricity; - use crate::shared::{update_iterator::FixedStepLoop, PotentialOrigin}; + use crate::shared::{update_iterator::MaxStepLoop, PotentialOrigin}; use crate::simulation::{Aircraft, SimulationElement, SimulationElementVisitor, UpdateContext}; use crate::simulation::test::{SimulationTestBed, TestBed}; @@ -332,7 +332,7 @@ mod tests { } struct TestAircraft { - core_hydraulic_updater: FixedStepLoop, + core_hydraulic_updater: MaxStepLoop, pump: ElectricalPumpPhysics, hydraulic_section: TestHydraulicSection, @@ -345,7 +345,7 @@ mod tests { impl TestAircraft { fn new(context: &mut InitContext) -> Self { Self { - core_hydraulic_updater: FixedStepLoop::new(Duration::from_millis(33)), + core_hydraulic_updater: MaxStepLoop::new(Duration::from_millis(10)), pump: physical_pump(context), hydraulic_section: TestHydraulicSection::default(), current_displacement: Volume::new::(0.), diff --git a/src/systems/systems/src/hydraulic/flap_slat.rs b/src/systems/systems/src/hydraulic/flap_slat.rs index 2520513b200..0b8eccc1b26 100644 --- a/src/systems/systems/src/hydraulic/flap_slat.rs +++ b/src/systems/systems/src/hydraulic/flap_slat.rs @@ -498,7 +498,7 @@ mod tests { use std::time::Duration; use uom::si::{angle::degree, pressure::psi}; - use crate::shared::update_iterator::FixedStepLoop; + use crate::shared::update_iterator::MaxStepLoop; use crate::simulation::{ test::{SimulationTestBed, TestBed}, @@ -531,7 +531,7 @@ mod tests { } struct TestAircraft { - core_hydraulic_updater: FixedStepLoop, + core_hydraulic_updater: MaxStepLoop, flaps_slats: FlapSlatAssembly, @@ -544,7 +544,7 @@ mod tests { impl TestAircraft { fn new(context: &mut InitContext, max_speed: AngularVelocity) -> Self { Self { - core_hydraulic_updater: FixedStepLoop::new(Duration::from_millis(33)), + core_hydraulic_updater: MaxStepLoop::new(Duration::from_millis(10)), flaps_slats: flap_system(context, max_speed), left_motor_angle_request: None, right_motor_angle_request: None, diff --git a/src/systems/systems/src/hydraulic/landing_gear.rs b/src/systems/systems/src/hydraulic/landing_gear.rs index 9a120ae099f..049b927d225 100644 --- a/src/systems/systems/src/hydraulic/landing_gear.rs +++ b/src/systems/systems/src/hydraulic/landing_gear.rs @@ -1283,14 +1283,16 @@ mod tests { #[test] fn door_assembly_init_uplocked() { let mut test_bed = SimulationTestBed::new(|context| { + let gear_door = main_gear_door_right_assembly(context); + TestSingleGearAircraft::new( - Duration::from_millis(33), - main_gear_door_right_assembly(context), + Duration::from_millis(10), + gear_door, main_gear_right_assembly(context, true), ) }); - test_bed.run_with_delta(Duration::from_millis(33)); + test_bed.run_with_delta(Duration::from_millis(10)); assert!(test_bed.query(|a| a.door_assembly.is_locked())); assert!( @@ -1301,14 +1303,16 @@ mod tests { #[test] fn door_uplocked_gives_correct_proximity_sensor_state() { let mut test_bed = SimulationTestBed::new(|context| { + let gear_door = main_gear_door_right_assembly(context); + TestSingleGearAircraft::new( - Duration::from_millis(33), - main_gear_door_right_assembly(context), + Duration::from_millis(10), + gear_door, main_gear_right_assembly(context, true), ) }); - test_bed.run_with_delta(Duration::from_millis(33)); + test_bed.run_with_delta(Duration::from_millis(10)); assert!( test_bed.query(|a| a.door_assembly.position_normalized()) == Ratio::new::(0.) @@ -1324,14 +1328,16 @@ mod tests { #[test] fn door_opens_gear_stays_down_and_locked() { let mut test_bed = SimulationTestBed::new(|context| { + let gear_door = main_gear_door_right_assembly(context); + TestSingleGearAircraft::new( - Duration::from_millis(33), - main_gear_door_right_assembly(context), + Duration::from_millis(10), + gear_door, main_gear_right_assembly(context, true), ) }); - test_bed.run_with_delta(Duration::from_millis(33)); + test_bed.run_with_delta(Duration::from_millis(10)); assert!(test_bed.query(|a| a.is_door_sensor_uplock(LgciuId::Lgciu1))); assert!(test_bed.query(|a| a.is_door_sensor_uplock(LgciuId::Lgciu2))); @@ -1342,9 +1348,11 @@ mod tests { #[test] fn no_unlocking_from_door_uplock_without_pressure() { let mut test_bed = SimulationTestBed::new(|context| { + let gear_door = main_gear_door_right_assembly(context); + TestSingleGearAircraft::new( - Duration::from_millis(33), - main_gear_door_right_assembly(context), + Duration::from_millis(10), + gear_door, main_gear_right_assembly(context, true), ) }); @@ -1360,13 +1368,15 @@ mod tests { #[test] fn full_retract_extend_cycle() { let mut test_bed = SimulationTestBed::new(|context| { + let gear_door = main_gear_door_right_assembly(context); + TestSingleGearAircraft::new( - Duration::from_millis(33), - main_gear_door_right_assembly(context), + Duration::from_millis(10), + gear_door, main_gear_right_assembly(context, true), ) }); - test_bed.run_with_delta(Duration::from_millis(33)); + test_bed.run_with_delta(Duration::from_millis(10)); println!("RETRACT -- > DOOR OPENING"); test_bed.command(|a| a.command_doors_opening()); diff --git a/src/systems/systems/src/hydraulic/linear_actuator.rs b/src/systems/systems/src/hydraulic/linear_actuator.rs index 7874997c54f..eb2619901a7 100644 --- a/src/systems/systems/src/hydraulic/linear_actuator.rs +++ b/src/systems/systems/src/hydraulic/linear_actuator.rs @@ -2085,13 +2085,14 @@ mod tests { power_consumption: Power, } impl TestAircraft { + const PHYSICS_TIME_STEP: Duration = Duration::from_millis(10); + fn new( context: &mut InitContext, - time_step: Duration, hydraulic_assembly: HydraulicLinearActuatorAssembly, ) -> Self { Self { - loop_updater: MaxStepLoop::new(time_step), + loop_updater: MaxStepLoop::new(Self::PHYSICS_TIME_STEP), hydraulic_assembly, @@ -2551,7 +2552,7 @@ mod tests { fn linear_actuator_not_moving_on_locked_rigid_body() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = cargo_door_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(33), tested_object) + TestAircraft::new(context, tested_object) }); let actuator_position_init = test_bed.query(|a| a.body_position()); @@ -2565,7 +2566,7 @@ mod tests { fn linear_actuator_moving_on_unlocked_rigid_body() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = cargo_door_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(33), tested_object) + TestAircraft::new(context, tested_object) }); let actuator_position_init = test_bed.query(|a| a.body_position()); @@ -2584,7 +2585,7 @@ mod tests { fn linear_actuator_can_move_rigid_body_up() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = cargo_door_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(33), tested_object) + TestAircraft::new(context, tested_object) }); let actuator_position_init = test_bed.query(|a| a.body_position()); @@ -2607,7 +2608,7 @@ mod tests { fn linear_actuator_resists_body_drop_when_valves_closed() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = cargo_door_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(33), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -2630,7 +2631,7 @@ mod tests { fn linear_actuator_dampens_body_drop_when_active_damping_mode() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = cargo_door_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(33), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -2654,7 +2655,7 @@ mod tests { fn linear_actuator_dampens_super_slow_body_drop_when_slow_damping_mode() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = cargo_door_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(33), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -2678,7 +2679,7 @@ mod tests { fn linear_actuator_without_hyd_pressure_cant_move_body_up() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = cargo_door_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(33), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -2695,7 +2696,7 @@ mod tests { fn linear_actuator_losing_hyd_pressure_half_way_cant_move_body_up() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = cargo_door_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(33), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -2721,7 +2722,7 @@ mod tests { fn body_gravity_movement_if_unlocked() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = cargo_door_assembly(context, false); - TestAircraft::new(context, Duration::from_millis(33), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -2740,7 +2741,7 @@ mod tests { fn start_moving_once_unlocked() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = cargo_door_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(33), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.write_by_name(UpdateContext::PLANE_BANK_KEY, -45.); @@ -2762,7 +2763,7 @@ mod tests { fn locks_at_required_position() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = cargo_door_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(33), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.write_by_name(UpdateContext::PLANE_BANK_KEY, -45.); @@ -2791,7 +2792,7 @@ mod tests { fn soft_lock_with_zero_velocity_stops_the_body() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = cargo_door_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(33), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.write_by_name(UpdateContext::PLANE_BANK_KEY, -45.); @@ -2830,7 +2831,7 @@ mod tests { fn linear_actuator_can_control_position() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = cargo_door_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(33), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -2854,7 +2855,7 @@ mod tests { fn right_main_gear_door_drops_when_unlocked() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = main_gear_door_right_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_closed_circuit_damping_mode(0)); @@ -2868,7 +2869,7 @@ mod tests { fn right_main_gear_door_drops_freefall_when_unlocked_with_broken_actuator() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = main_gear_door_right_broken_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_closed_circuit_damping_mode(0)); @@ -2882,7 +2883,7 @@ mod tests { fn right_main_gear_door_cant_open_fully_if_banking_right() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = main_gear_door_right_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.run_with_delta(Duration::from_secs(1)); @@ -2899,7 +2900,7 @@ mod tests { fn right_main_gear_door_closes_after_opening_with_pressure() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = main_gear_door_right_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.set_pressures([Pressure::new::(3000.)])); @@ -2923,7 +2924,7 @@ mod tests { fn nose_gear_door_closes_after_opening_with_pressure() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = nose_gear_door_assembly(context); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.set_pressures([Pressure::new::(3000.)])); @@ -2947,7 +2948,7 @@ mod tests { fn left_main_gear_door_drops_when_unlocked() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = main_gear_door_left_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_closed_circuit_damping_mode(0)); @@ -2961,7 +2962,7 @@ mod tests { fn left_main_gear_door_can_open_fully_if_banking_right() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = main_gear_door_left_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.write_by_name(UpdateContext::PLANE_BANK_KEY, -45.); @@ -2976,7 +2977,7 @@ mod tests { fn left_main_gear_door_opens_with_pressure() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = main_gear_door_left_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.set_pressures([Pressure::new::(3000.)])); @@ -2991,7 +2992,7 @@ mod tests { fn right_main_gear_retracts_with_pressure() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = main_gear_right_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.set_pressures([Pressure::new::(3000.)])); @@ -3006,7 +3007,7 @@ mod tests { fn right_main_gear_locked_down_at_init() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = main_gear_right_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(33), tested_object) + TestAircraft::new(context, tested_object) }); assert!(test_bed.query(|a| a.is_locked())); @@ -3022,7 +3023,7 @@ mod tests { fn right_main_gear_locks_up_when_retracted() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = main_gear_right_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.set_pressures([Pressure::new::(3000.)])); @@ -3041,7 +3042,7 @@ mod tests { fn right_main_gear_locks_down_when_extended_by_gravity() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = main_gear_right_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); // FIRST GEAR UP @@ -3072,7 +3073,7 @@ mod tests { fn left_main_gear_retracts_with_pressure() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = main_gear_left_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.set_pressures([Pressure::new::(3000.)])); @@ -3087,7 +3088,7 @@ mod tests { fn left_main_gear_retracts_with_limited_pressure() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = main_gear_left_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.set_pressures([Pressure::new::(1500.)])); @@ -3102,7 +3103,7 @@ mod tests { fn left_main_gear_locked_down_at_init() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = main_gear_left_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(33), tested_object) + TestAircraft::new(context, tested_object) }); assert!(test_bed.query(|a| a.is_locked())); @@ -3118,7 +3119,7 @@ mod tests { fn left_main_gear_locks_up_when_retracted() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = main_gear_left_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.set_pressures([Pressure::new::(3000.)])); @@ -3137,7 +3138,7 @@ mod tests { fn left_main_gear_locks_down_when_extended_by_gravity() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = main_gear_left_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); // FIRST GEAR UP @@ -3168,7 +3169,7 @@ mod tests { fn nose_gear_locks_up_when_retracted() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = nose_gear_assembly(context); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.set_pressures([Pressure::new::(3000.)])); @@ -3187,7 +3188,7 @@ mod tests { fn aileron_initialized_down_stays_down_with_broken_actuator() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = aileron_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -3202,7 +3203,7 @@ mod tests { fn aileron_initialized_down_moves_up_when_commanded() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = aileron_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -3220,7 +3221,7 @@ mod tests { fn aileron_drops_from_middle_pos_in_more_20s_in_closed_circuit_damping() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = aileron_assembly(context, false); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -3238,7 +3239,7 @@ mod tests { fn aileron_drops_from_middle_pos_and_damping_is_stable() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = aileron_assembly(context, false); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -3258,7 +3259,7 @@ mod tests { fn aileron_position_control_is_stable() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = aileron_assembly(context, false); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -3294,7 +3295,7 @@ mod tests { fn aileron_position_control_from_down_to_up_less_0_5s() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = aileron_assembly(context, false); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -3318,7 +3319,7 @@ mod tests { fn aileron_initialized_down_goes_neutral_when_trimmed_90_degrees_down() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = aileron_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -3339,7 +3340,7 @@ mod tests { fn aileron_position_control_resists_step_change_in_aero_force() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = aileron_assembly(context, false); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -3367,7 +3368,7 @@ mod tests { fn aileron_position_control_fails_when_aero_force_over_max_force() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = aileron_assembly(context, false); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -3402,7 +3403,7 @@ mod tests { { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = aileron_assembly(context, false); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -3447,7 +3448,7 @@ mod tests { fn aileron_position_control_from_down_to_up_less_0_5s_with_limited_pressure() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = aileron_assembly(context, false); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -3471,7 +3472,7 @@ mod tests { fn elevator_position_control_is_stable_with_all_actuators_in_control() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = elevator_assembly(context); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -3509,7 +3510,7 @@ mod tests { fn elevator_droop_control_is_stable_engaged_at_full_speed() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = elevator_assembly(context); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -3550,7 +3551,7 @@ mod tests { fn spoiler_position_control_from_down_to_up_less_0_8s() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = spoiler_assembly(context, false); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -3568,7 +3569,7 @@ mod tests { fn spoiler_position_can_go_down_but_not_up_when_soft_locked_up() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = spoiler_assembly(context, false); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -3606,7 +3607,7 @@ mod tests { fn spoiler_position_cant_go_up_when_not_pressurised() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = spoiler_assembly(context, false); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -3623,7 +3624,7 @@ mod tests { fn elevator_electro_hydrostatic_cannot_move_with_elec_and_no_pressure_but_backup_not_active() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = elevator_electro_hydrostatic_assembly(context); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -3645,7 +3646,7 @@ mod tests { fn elevator_electro_hydrostatic_can_move_with_elec_and_no_pressure() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = elevator_electro_hydrostatic_assembly(context); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -3669,7 +3670,7 @@ mod tests { fn elevator_electro_hydrostatic_losing_elec_cannot_move_anymore() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = elevator_electro_hydrostatic_assembly(context); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -3701,7 +3702,7 @@ mod tests { fn spoiler_electro_hydrostatic_can_move_with_pressure() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = spoiler_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -3719,7 +3720,7 @@ mod tests { fn spoiler_electro_hydrostatic_cannot_move_without_pressure_without_backup_active() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = spoiler_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -3737,7 +3738,7 @@ mod tests { fn spoiler_electro_hydrostatic_cannot_move_without_pressure_without_elec_with_backup_active() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = spoiler_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -3756,7 +3757,7 @@ mod tests { fn spoiler_electro_hydrostatic_can_move_without_pressure_with_elec_with_backup_active() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = spoiler_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -3776,7 +3777,7 @@ mod tests { fn electro_hydrostatic_actuator_consumes_power_when_moving() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = spoiler_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -3801,7 +3802,7 @@ mod tests { fn electro_hydrostatic_actuator_do_not_use_hydraulic_flow_when_moving() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = spoiler_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -3826,7 +3827,7 @@ mod tests { fn electro_hydrostatic_actuator_do_not_consume_power_when_inactive() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = spoiler_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -3851,7 +3852,7 @@ mod tests { fn spoiler_electro_hydrostatic_cannot_move_once_accumulator_empty() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = spoiler_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); test_bed.command(|a| a.command_unlock()); @@ -3877,7 +3878,7 @@ mod tests { fn electro_hydrostatic_accumulator_pressure_increase_when_refilled() { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = spoiler_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); let accumulator_press_init = test_bed.query(|a| a.accumulator_pressure(0)); @@ -3896,7 +3897,7 @@ mod tests { { let mut test_bed = SimulationTestBed::new(|context| { let tested_object = spoiler_assembly(context, true); - TestAircraft::new(context, Duration::from_millis(10), tested_object) + TestAircraft::new(context, tested_object) }); let accumulator_press_init = test_bed.query(|a| a.accumulator_pressure(0)); diff --git a/src/systems/systems/src/hydraulic/mod.rs b/src/systems/systems/src/hydraulic/mod.rs index 7f88975be94..b43a2badb2a 100644 --- a/src/systems/systems/src/hydraulic/mod.rs +++ b/src/systems/systems/src/hydraulic/mod.rs @@ -138,9 +138,13 @@ pub struct PressureSwitch { high_hysteresis_threshold: Pressure, low_hysteresis_threshold: Pressure, + current_pressure_filtered: LowPassFilter, + sensor_type: PressureSwitchType, } impl PressureSwitch { + const PRESSURE_DYNAMIC_TIME_CONSTANT: Duration = Duration::from_millis(200); + pub fn new( high_threshold: Pressure, low_threshold: Pressure, @@ -150,6 +154,7 @@ impl PressureSwitch { state_is_pressurised: false, high_hysteresis_threshold: high_threshold, low_hysteresis_threshold: low_threshold, + current_pressure_filtered: LowPassFilter::new(Self::PRESSURE_DYNAMIC_TIME_CONSTANT), sensor_type, } } @@ -159,10 +164,12 @@ impl PressureSwitch { PressureSwitchType::Relative => current_pressure - context.ambient_pressure(), PressureSwitchType::Absolute => current_pressure, }; + self.current_pressure_filtered + .update(context.delta(), pressure_measured); - if pressure_measured <= self.low_hysteresis_threshold { + if self.current_pressure_filtered.output() <= self.low_hysteresis_threshold { self.state_is_pressurised = false; - } else if pressure_measured >= self.high_hysteresis_threshold { + } else if self.current_pressure_filtered.output() >= self.high_hysteresis_threshold { self.state_is_pressurised = true; } } diff --git a/src/systems/systems/src/hydraulic/trimmable_horizontal_stabilizer.rs b/src/systems/systems/src/hydraulic/trimmable_horizontal_stabilizer.rs index 303786f0dab..6af805708d5 100644 --- a/src/systems/systems/src/hydraulic/trimmable_horizontal_stabilizer.rs +++ b/src/systems/systems/src/hydraulic/trimmable_horizontal_stabilizer.rs @@ -740,7 +740,7 @@ mod tests { use crate::electrical::Electricity; use super::*; - use crate::shared::{update_iterator::FixedStepLoop, PotentialOrigin}; + use crate::shared::{update_iterator::MaxStepLoop, PotentialOrigin}; use crate::simulation::test::{ReadByName, SimulationTestBed, TestBed}; use crate::simulation::{Aircraft, SimulationElement}; use std::time::Duration; @@ -818,7 +818,7 @@ mod tests { } struct TestAircraft { - updater_fixed_step: FixedStepLoop, + updater_max_step: MaxStepLoop, elec_trim_control: TestElecTrimControl, manual_trim_control: TestManualTrimControl, @@ -836,7 +836,7 @@ mod tests { impl TestAircraft { fn new(context: &mut InitContext) -> Self { Self { - updater_fixed_step: FixedStepLoop::new(Duration::from_millis(33)), + updater_max_step: MaxStepLoop::new(Duration::from_millis(10)), elec_trim_control: TestElecTrimControl::inactive_control(), manual_trim_control: TestManualTrimControl::without_manual_input(), trim_assembly: TrimmableHorizontalStabilizerAssembly::new( @@ -916,9 +916,9 @@ mod tests { } fn update_after_power_distribution(&mut self, context: &UpdateContext) { - self.updater_fixed_step.update(context); + self.updater_max_step.update(context); - for cur_time_step in &mut self.updater_fixed_step { + for cur_time_step in &mut self.updater_max_step { self.trim_assembly.update( &context.with_delta(cur_time_step), &self.elec_trim_control, From b0f9c7bec5ec3e5ffdca4f80eff6082e3193cd00 Mon Sep 17 00:00:00 2001 From: Frank Kopp Date: Sat, 31 Dec 2022 18:36:24 +0100 Subject: [PATCH 08/39] fix: Improve import flight plan from MSFS World Map (#7646) --- .github/CHANGELOG.md | 1 + .../src/flightplanning/FlightPlanAsoboSync.ts | 239 ++++++++++-------- .../src/flightplanning/FlightPlanManager.ts | 69 +++-- src/fmgc/src/flightplanning/LegsProcedure.ts | 169 +++++++------ .../src/flightplanning/ManagedFlightPlan.ts | 160 ++++++------ src/fmgc/src/flightplanning/RawDataMapper.ts | 20 +- 6 files changed, 359 insertions(+), 299 deletions(-) diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index bd35d741bec..3c28bcd6e7c 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -19,6 +19,7 @@ 1. [EFB] Fix and improve pushback system and add API documentation - @frankkopp (Frank Kopp) 1. [RMP] RMPs navigation backup - Julian Sebline (Julian Sebline#8476 on Discord) 1. [SEC] Fix GND SPLR logic, add missing GND SPLR partial extension condition - @lukecologne (luke) +1. [FMGC] Improved importing flight plans from MSFS World Map - @frankkopp (Frank Kopp) ## 0.9.0 diff --git a/src/fmgc/src/flightplanning/FlightPlanAsoboSync.ts b/src/fmgc/src/flightplanning/FlightPlanAsoboSync.ts index 5c7367c6268..483e68bf223 100644 --- a/src/fmgc/src/flightplanning/FlightPlanAsoboSync.ts +++ b/src/fmgc/src/flightplanning/FlightPlanAsoboSync.ts @@ -45,142 +45,159 @@ export class FlightPlanAsoboSync { Coherent.call('LOAD_CURRENT_ATC_FLIGHTPLAN').catch(console.error); setTimeout(() => { Coherent.call('GET_FLIGHTPLAN').then(async (data: Record) => { - console.log('COHERENT GET_FLIGHTPLAN received'); - const { isDirectTo } = data; + console.log('COHERENT GET_FLIGHTPLAN received:'); + console.log('Data from MSFS flight plan:', data); + // Purpose unclear // TODO: talk to matt about dirto - if (!isDirectTo) { - // TODO FIXME: better handling of mid-air spawning and syncing fpln - if (data.waypoints.length === 0 || data.waypoints[0].icao[0] !== 'A') { - fpln.resumeSync(); - resolve(); - return; - } + const { isDirectTo } = data; + if (isDirectTo) { + return; + } - await fpln._parentInstrument.facilityLoader.getFacilityRaw(data.waypoints[0].icao, 10000).catch((e) => { - console.error('[FP LOAD] Error getting first wp data'); - console.error(e); - }); + // Mid air flight plan loading not yet supported - return if first waypoint is not an airport + // TODO FIXME: better handling of mid-air spawning and syncing fpln + if (data.waypoints.length === 0 || data.waypoints[0].icao[0] !== 'A') { + fpln.resumeSync(); + resolve(); + return; + } - // set origin - await fpln.setOrigin(data.waypoints[0].icao).catch((e) => { - console.error('[FP LOAD] Error setting origin'); - console.error(e); - }); + // result dismissed - why?? + // assumption: counter timeout issues when reading facility from MSFS? + await fpln._parentInstrument.facilityLoader.getFacilityRaw(data.waypoints[0].icao, 10000).catch((e) => { + console.error('[FP LOAD] Error getting first wp data'); + console.error(e); + }); - // set dest - await fpln.setDestination(data.waypoints[data.waypoints.length - 1].icao).catch((e) => { - console.error('[FP LOAD] Error setting Destination'); - console.error(e); - }); + // set origin + await fpln.setOrigin(data.waypoints[0].icao).catch((e) => { + console.error('[FP LOAD] Error setting origin'); + console.error(e); + }); + + // set dest + await fpln.setDestination(data.waypoints[data.waypoints.length - 1].icao).catch((e) => { + console.error('[FP LOAD] Error setting Destination'); + console.error(e); + }); - // set route + // set route + const enrouteStart = (data.departureWaypointsSize === -1) ? 1 : data.departureWaypointsSize; + // Find out first approach waypoint, - 1 to skip destination + const enrouteEnd = data.waypoints.length - ((data.arrivalWaypointsSize === -1) ? 0 : data.arrivalWaypointsSize) - 1; + const enroute = data.waypoints.slice(enrouteStart, enrouteEnd); - const enrouteStart = (data.departureWaypointsSize === -1) ? 1 : data.departureWaypointsSize; - // Find out first approach waypoint, - 1 to skip destination - const enrouteEnd = data.waypoints.length - ((data.arrivalWaypointsSize === -1) ? 1 : data.arrivalWaypointsSize) - 1; - const enroute = data.waypoints.slice(enrouteStart, enrouteEnd - 1); - for (let i = 0; i < enroute.length - 1; i++) { - const wpt = enroute[i]; - if (wpt.icao.trim() !== '') { - fpln.addWaypoint(wpt.icao, Infinity, () => console.log(`[FP LOAD] Adding [${wpt.icao}]... SUCCESS`)).catch(console.error); - } + for (let i = 0; i < enroute.length; i++) { + const wpt = enroute[i]; + if (wpt.icao.trim() !== '') { + // Without the 'await' the order of import is undefined and the flight plan waypoints + // are not in the correct order + // eslint-disable-next-line no-await-in-loop + await fpln.addWaypoint(wpt.icao, Infinity, + () => { + // console.log(`[FP LOAD] Adding [${wpt.icao}]... SUCCESS`); + }) + .catch(console.error); } + } - // set departure - // rwy index - await fpln.setDepartureRunwayIndex(data.departureRunwayIndex) - // .then(() => console.log(`[FP LOAD] Setting Departure Runway ${data.departureRunwayIndex} ... SUCCESS`)) - .catch((e) => { - console.error(`[FP LOAD] Setting Departure Runway ${data.departureRunwayIndex} ... FAILED`); - console.error(e); - }); - // proc index - await fpln.setDepartureProcIndex(data.departureProcIndex) - // .then(() => console.log(`[FP LOAD] Setting Departure Procedure ${data.departureProcIndex} ... SUCCESS`)) + // set departure + // rwy index + await fpln.setDepartureRunwayIndex(data.departureRunwayIndex) + // .then(() => console.log(`[FP LOAD] Setting Departure Runway ${data.departureRunwayIndex} ... SUCCESS`)) + .catch((e) => { + console.error(`[FP LOAD] Setting Departure Runway ${data.departureRunwayIndex} ... FAILED`); + console.error(e); + }); + // proc index + await fpln.setDepartureProcIndex(data.departureProcIndex) + // .then(() => console.log(`[FP LOAD] Setting Departure Procedure ${data.departureProcIndex} ... SUCCESS`)) + .catch((e) => { + console.error(`[FP LOAD] Setting Departure Procedure ${data.departureProcIndex} ... FAILED`); + console.error(e); + }); + // origin runway + if (data.originRunwayIndex !== -1) { + await fpln.setOriginRunwayIndex(data.originRunwayIndex) + // .then(() => console.log(`[FP LOAD] Setting Origin ${data.originRunwayIndex} ... SUCCESS`)) .catch((e) => { - console.error(`[FP LOAD] Setting Departure Procedure ${data.departureProcIndex} ... FAILED`); + console.error(`[FP LOAD] Setting Origin ${data.originRunwayIndex} ... FAILED`); console.error(e); }); - // origin runway - if (data.originRunwayIndex !== -1) { - await fpln.setOriginRunwayIndex(data.originRunwayIndex) - // .then(() => console.log(`[FP LOAD] Setting Origin ${data.originRunwayIndex} ... SUCCESS`)) - .catch((e) => { - console.error(`[FP LOAD] Setting Origin ${data.originRunwayIndex} ... FAILED`); - console.error(e); - }); - } else if (data.departureRunwayIndex !== -1 && data.departureProcIndex !== -1) { - await fpln.setOriginRunwayIndexFromDeparture() - // .then(() => console.log(`[FP LOAD] Setting Origin using ${data.departureProcIndex}/${data.departureRunwayIndex}... SUCCESS`)) + } else if (data.departureRunwayIndex !== -1 && data.departureProcIndex !== -1) { + await fpln.setOriginRunwayIndexFromDeparture() + // .then(() => console.log(`[FP LOAD] Setting Origin using ${data.departureProcIndex}/${data.departureRunwayIndex}... SUCCESS`)) .catch((e) => { - console.error(`[FP LOAD] Setting Origin using ${data.departureProcIndex}/${data.departureRunwayIndex} ... FAILED`); - console.error(e); - }); - } - // enroutetrans index - await fpln.setDepartureEnRouteTransitionIndex(data.departureEnRouteTransitionIndex) - // .then(() => console.log(`[FP LOAD] Setting Departure En Route Transition ${data.departureEnRouteTransitionIndex} ... SUCCESS`)) - .catch((e) => { - console.error(`[FP LOAD] Setting Departure En Route Transition ${data.departureEnRouteTransitionIndex} ... FAILED`); + console.error(`[FP LOAD] Setting Origin using ${data.departureProcIndex}/${data.departureRunwayIndex} ... FAILED`); console.error(e); }); - // set approach - // rwy index - await fpln.setArrivalRunwayIndex(data.arrivalRunwayIndex) - // .then(() => console.log(`[FP LOAD] Setting Arrival Runway ${data.arrivalRunwayIndex} ... SUCCESS`)) + } + // enroutetrans index + await fpln.setDepartureEnRouteTransitionIndex(data.departureEnRouteTransitionIndex) + // .then(() => console.log(`[FP LOAD] Setting Departure En Route Transition ${data.departureEnRouteTransitionIndex} ... SUCCESS`)) + .catch((e) => { + console.error(`[FP LOAD] Setting Departure En Route Transition ${data.departureEnRouteTransitionIndex} ... FAILED`); + console.error(e); + }); + // set approach + // rwy index + await fpln.setArrivalRunwayIndex(data.arrivalRunwayIndex) + // .then(() => console.log(`[FP LOAD] Setting Arrival Runway ${data.arrivalRunwayIndex} ... SUCCESS`)) .catch((e) => { console.error(`[FP LOAD] Setting Arrival Runway ${data.arrivalRunwayIndex} ... FAILED`); console.error(e); }); - // approach index - await fpln.setApproachIndex(data.approachIndex) - // .then(() => console.log(`[FP LOAD] Setting Approach ${data.approachIndex} ... SUCCESS`)) - .catch((e) => { - console.error(`[FP LOAD] Setting Approach ${data.approachIndex} ... FAILED`); - console.error(e); - }); - // approachtrans index - await fpln.setApproachTransitionIndex(data.approachTransitionIndex) - // .then(() => console.log(`[FP LOAD] Setting Approach Transition ${data.approachTransitionIndex} ... SUCCESS`)) - .catch((e) => { - console.error(`[FP LOAD] Setting Approach Transition ${data.approachTransitionIndex} ... FAILED`); - console.error(e); - }); + // approach index + await fpln.setApproachIndex(data.approachIndex) + // .then(() => console.log(`[FP LOAD] Setting Approach ${data.approachIndex} ... SUCCESS`)) + .catch((e) => { + console.error(`[FP LOAD] Setting Approach ${data.approachIndex} ... FAILED`); + console.error(e); + }); + // approachtrans index + await fpln.setApproachTransitionIndex(data.approachTransitionIndex) + // .then(() => console.log(`[FP LOAD] Setting Approach Transition ${data.approachTransitionIndex} ... SUCCESS`)) + .catch((e) => { + console.error(`[FP LOAD] Setting Approach Transition ${data.approachTransitionIndex} ... FAILED`); + console.error(e); + }); - // set arrival - // arrivalproc index - await fpln.setArrivalProcIndex(data.arrivalProcIndex) - // .then(() => console.log(`[FP LOAD] Setting Arrival Procedure ${data.arrivalProcIndex} ... SUCCESS`)) - .catch((e) => { - console.error(`[FP LOAD] Setting Arrival Procedure ${data.arrivalProcIndex} ... FAILED`); - console.error(e); - }); - // arrivaltrans index - await fpln.setArrivalEnRouteTransitionIndex(data.arrivalEnRouteTransitionIndex) - // .then(() => console.log(`[FP LOAD] Setting En Route Transition ${data.arrivalEnRouteTransitionIndex} ... SUCCESS`)) - .catch((e) => { - console.error(`[FP LOAD] Setting En Route Transition ${data.arrivalEnRouteTransitionIndex} ... FAILED`); - console.error(e); - }); + // set arrival + // arrivalproc index + await fpln.setArrivalProcIndex(data.arrivalProcIndex) + // .then(() => console.log(`[FP LOAD] Setting Arrival Procedure ${data.arrivalProcIndex} ... SUCCESS`)) + .catch((e) => { + console.error(`[FP LOAD] Setting Arrival Procedure ${data.arrivalProcIndex} ... FAILED`); + console.error(e); + }); + // arrivaltrans index + await fpln.setArrivalEnRouteTransitionIndex(data.arrivalEnRouteTransitionIndex) + // .then(() => console.log(`[FP LOAD] Setting En Route Transition ${data.arrivalEnRouteTransitionIndex} ... SUCCESS`)) + .catch((e) => { + console.error(`[FP LOAD] Setting En Route Transition ${data.arrivalEnRouteTransitionIndex} ... FAILED`); + console.error(e); + }); - await fpln.setDestinationRunwayIndexFromApproach() - // .then(() => console.log(`[FP LOAD] Setting Destination Runway using ${data.approachIndex} ... SUCCESS`)) + await fpln.setDestinationRunwayIndexFromApproach() + // .then(() => console.log(`[FP LOAD] Setting Destination Runway using ${data.approachIndex} ... SUCCESS`)) .catch((e) => { console.error(`[FP LOAD] Setting Destination Runway using ${data.approachIndex} ... FAILED`); console.error(e); }); - fpln.resumeSync(); + fpln.resumeSync(); - this.fpChecksum = fpln.getCurrentFlightPlan().checksum; - // Potential CTD source? - Coherent.call('SET_ACTIVE_WAYPOINT_INDEX', 0) - .catch((e) => console.error('[FP LOAD] Error when setting Active WP')); - Coherent.call('RECOMPUTE_ACTIVE_WAYPOINT_INDEX') - .catch((e) => console.error('[FP LOAD] Error when recomputing Active WP')); - resolve(); - } + this.fpChecksum = fpln.getCurrentFlightPlan().checksum; + + // Potential CTD source? + Coherent.call('SET_ACTIVE_WAYPOINT_INDEX', 0) + .catch((e) => console.error('[FP LOAD] Error when setting Active WP', e)); + Coherent.call('RECOMPUTE_ACTIVE_WAYPOINT_INDEX') + .catch((e) => console.error('[FP LOAD] Error when recomputing Active WP', e)); + resolve(); + + console.log('Resulting aircraft flight plan: ', fpln); }).catch(console.error); }, 500); }, 200); @@ -270,8 +287,8 @@ export class FlightPlanAsoboSync { this.fpChecksum = plan.checksum; } Coherent.call('RECOMPUTE_ACTIVE_WAYPOINT_INDEX') - .catch((e) => console.log('[FP SAVE] Setting Active Waypoint... FAILED')) - .then(() => console.log('[FP SAVE] Setting Active Waypoint... SUCCESS')); + // .then(() => console.log('[FP SAVE] Setting Active Waypoint... SUCCESS')) + .catch((e) => console.log('[FP SAVE] Setting Active Waypoint... FAILED: ', e)); })); }); } diff --git a/src/fmgc/src/flightplanning/FlightPlanManager.ts b/src/fmgc/src/flightplanning/FlightPlanManager.ts index 23df0d9f7f2..feb23944995 100644 --- a/src/fmgc/src/flightplanning/FlightPlanManager.ts +++ b/src/fmgc/src/flightplanning/FlightPlanManager.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-underscore-dangle */ /* * MIT License * @@ -23,16 +24,16 @@ */ import { NXDataStore } from '@shared/persistence'; -import { LegType, TurnDirection } from '@fmgc/types/fstypes/FSEnums'; +import { LegType } from '@fmgc/types/fstypes/FSEnums'; import { FlightLevel } from '@fmgc/guidance/vnav/verticalFlightPlan/VerticalFlightPlan'; +import { LnavConfig } from '@fmgc/guidance/LnavConfig'; +import { ApproachStats, HoldData } from '@fmgc/flightplanning/data/flightplan'; +import { SegmentType } from '@fmgc/wtsdk'; import { ManagedFlightPlan } from './ManagedFlightPlan'; import { GPS } from './GPS'; import { FlightPlanSegment } from './FlightPlanSegment'; import { FlightPlanAsoboSync } from './FlightPlanAsoboSync'; import { FixInfo } from './FixInfo'; -import { LnavConfig } from '@fmgc/guidance/LnavConfig'; -import { ApproachStats, HoldData } from '@fmgc/flightplanning/data/flightplan'; -import { SegmentType } from '@fmgc/wtsdk'; export enum WaypointConstraintType { CLB = 1, @@ -149,9 +150,12 @@ export class FlightPlanManager { } public registerListener() { + // empty } + // eslint-disable-next-line @typescript-eslint/no-unused-vars public addHardCodedConstraints(wp) { + // empty } /** @@ -160,7 +164,9 @@ export class FlightPlanManager { * @param currentWaypoints The waypoints array to modify with the data loaded. * @param callback A callback to call when the data has completed loading. */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars private _loadWaypoints(data: any, currentWaypoints: any, callback: () => void) { + // empty } /** @@ -177,6 +183,7 @@ export class FlightPlanManager { * @param {() => void} callback A callback to call when the update has completed. * @param {Boolean} log Whether or not to log the loaded flight plan value. */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars public updateFlightPlan(callback: () => void = () => { }, log = false, force = false): void { const flightPlanVersion = SimVar.GetSimVarValue(FlightPlanManager.FlightPlanVersionKey, 'number'); if (flightPlanVersion !== this._currentFlightPlanVersion || force) { @@ -202,6 +209,7 @@ export class FlightPlanManager { } } + // eslint-disable-next-line @typescript-eslint/no-unused-vars public updateCurrentApproach(callback = () => { }, log = false): void { callback(); } @@ -356,16 +364,18 @@ export class FlightPlanManager { * @param forceSimVarCall Unused * @param useCorrection Unused */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars public getActiveWaypointIndex(forceSimVarCall = false, useCorrection = false, flightPlanIndex = NaN): number { - if (isNaN(flightPlanIndex)) { + if (Number.isNaN(flightPlanIndex)) { return this._flightPlans[this._currentFlightPlanIndex].activeWaypointIndex; } return this._flightPlans[flightPlanIndex]?.activeWaypointIndex ?? -1; } + // eslint-disable-next-line @typescript-eslint/no-unused-vars public isActiveWaypointAtEnd(forceSimVarCall = false, useCorrection = false, flightPlanIndex = NaN): boolean { - if (isNaN(flightPlanIndex)) { + if (Number.isNaN(flightPlanIndex)) { return this._flightPlans[this._currentFlightPlanIndex].activeWaypointIndex + 1 === this.getWaypointsCount(this._currentFlightPlanIndex) - 1; } return this._flightPlans[flightPlanIndex].activeWaypointIndex === this.getWaypointsCount(flightPlanIndex) - 1; @@ -403,6 +413,7 @@ export class FlightPlanManager { * Gets the index of the waypoint prior to the currently active waypoint. * @param forceSimVarCall Unused */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars public getPreviousActiveWaypoint(forceSimVarCall = false): WayPoint { const currentFlightPlan = this._flightPlans[this._currentFlightPlanIndex]; const previousWaypointIndex = currentFlightPlan.activeWaypointIndex - 1; @@ -414,6 +425,7 @@ export class FlightPlanManager { * Gets the ident of the active waypoint. * @param forceSimVarCall Unused */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars public getActiveWaypointIdent(forceSimVarCall = false): string { const currentFlightPlan = this._flightPlans[this._currentFlightPlanIndex]; if (currentFlightPlan.activeWaypoint) { @@ -427,6 +439,7 @@ export class FlightPlanManager { * Gets the active waypoint index from fs9gps. Currently unimplemented. * @param forceSimVarCall Unused */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars public getGPSActiveWaypointIndex(forceSimVarCall = false): number { return this.getActiveWaypointIndex(); } @@ -436,8 +449,9 @@ export class FlightPlanManager { * @param forceSimVarCall Unused * @param useCorrection Unused */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars public getActiveWaypoint(forceSimVarCall = false, useCorrection = false, flightPlanIndex = NaN): WayPoint { - if (isNaN(flightPlanIndex)) { + if (Number.isNaN(flightPlanIndex)) { flightPlanIndex = this._currentFlightPlanIndex; } @@ -448,6 +462,7 @@ export class FlightPlanManager { * Gets the next waypoint following the active waypoint. * @param forceSimVarCall Unused */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars public getNextActiveWaypoint(forceSimVarCall = false): WayPoint { const currentFlightPlan = this._flightPlans[this._currentFlightPlanIndex]; const nextWaypointIndex = currentFlightPlan.activeWaypointIndex + 1; @@ -510,7 +525,7 @@ export class FlightPlanManager { return { name, distanceFromPpos, - } + }; } /** @@ -578,7 +593,7 @@ export class FlightPlanManager { */ public getDeparture(flightPlanIndex = NaN): WayPoint | undefined { const origin = this.getOrigin(); - if (isNaN(flightPlanIndex)) { + if (Number.isNaN(flightPlanIndex)) { flightPlanIndex = this._currentFlightPlanIndex; } const currentFlightPlan = this._flightPlans[flightPlanIndex]; @@ -678,7 +693,7 @@ export class FlightPlanManager { /** * Gets the index of the last waypoint in the enroute segment of the current flight plan. */ - public getEnRouteWaypointsFirstIndex(flightPlanIndex = this._currentFlightPlanIndex): number | null { + public getEnRouteWaypointsFirstIndex(flightPlanIndex = this._currentFlightPlanIndex): number | null { const currentFlightPlan = this._flightPlans[flightPlanIndex]; const enrouteSegment = currentFlightPlan?.enroute; @@ -721,7 +736,7 @@ export class FlightPlanManager { * @param waypoint The waypoint we want to find the segment for. */ public getSegmentFromWaypoint(waypoint: WayPoint | undefined, flightPlanIndex = NaN): FlightPlanSegment { - if (isNaN(flightPlanIndex)) { + if (Number.isNaN(flightPlanIndex)) { flightPlanIndex = this._currentFlightPlanIndex; } @@ -947,6 +962,7 @@ export class FlightPlanManager { * @param {*} _callback Unused */ public addFlightPlanUpdateCallback(_callback) { + // empty } /** @@ -972,6 +988,7 @@ export class FlightPlanManager { callback(); } + // eslint-disable-next-line @typescript-eslint/no-unused-vars addWaypointOverfly(index: number, thenSetActive = false, callback = () => { }): void { this._flightPlans[this._currentFlightPlanIndex].setWaypointOverfly(index, true); @@ -979,6 +996,7 @@ export class FlightPlanManager { callback(); } + // eslint-disable-next-line @typescript-eslint/no-unused-vars removeWaypointOverfly(index: number, thenSetActive = false, callback = () => { }): void { this._flightPlans[this._currentFlightPlanIndex].setWaypointOverfly(index, false); @@ -1008,6 +1026,7 @@ export class FlightPlanManager { * @param index The index of the first waypoint to remove. * @param callback A callback to call when the operation finishes. */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars public truncateWaypoints(index: number, thenSetActive = false, callback = () => { }): void { const fp = this._flightPlans[this._currentFlightPlanIndex]; for (let i = fp.length; i >= index; i--) { @@ -1031,7 +1050,7 @@ export class FlightPlanManager { * @param flightPlanIndex The index of the flight plan. If omitted, will get the current flight plan. */ public getWaypointsCount(flightPlanIndex = NaN): number { - if (isNaN(flightPlanIndex)) { + if (Number.isNaN(flightPlanIndex)) { return this._flightPlans[this._currentFlightPlanIndex]?.length ?? 0; } @@ -1058,8 +1077,9 @@ export class FlightPlanManager { * @param flightPlanIndex The index of the flight plan to get the waypoint from. If omitted, will get from the current flight plan. * @param considerApproachWaypoints Whether or not to consider approach waypoints. */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars public getWaypoint(index: number, flightPlanIndex = NaN, considerApproachWaypoints = false): WayPoint | undefined { - if (isNaN(flightPlanIndex)) { + if (Number.isNaN(flightPlanIndex)) { flightPlanIndex = this._currentFlightPlanIndex; } @@ -1072,7 +1092,7 @@ export class FlightPlanManager { * @param flightPlanIndex The index of the flight plan to get the waypoints from. If omitted, will get from the current flight plan. */ public getWaypoints(flightPlanIndex = NaN): WayPoint[] { - if (isNaN(flightPlanIndex)) { + if (Number.isNaN(flightPlanIndex)) { flightPlanIndex = this._currentFlightPlanIndex; } @@ -1223,12 +1243,11 @@ export class FlightPlanManager { && currentFlightPlan.procedureDetails.departureIndex >= 0 && currentFlightPlan.originAirfield ) { - const transition = (currentFlightPlan.originAirfield.infos as AirportInfo) .departures[currentFlightPlan.procedureDetails.departureIndex] .runwayTransitions[currentFlightPlan.procedureDetails.departureRunwayIndex]; const runways = (currentFlightPlan.originAirfield.infos as AirportInfo).oneWayRunways; - await this.setOriginRunwayIndex(runways.findIndex(r => r.number === transition.runwayNumber && r.designator === transition.runwayDesignation)); + await this.setOriginRunwayIndex(runways.findIndex((r) => r.number === transition.runwayNumber && r.designator === transition.runwayDesignation)); } } @@ -1262,6 +1281,7 @@ export class FlightPlanManager { * Unused */ public getDepartureDiscontinuity() { + // empty } /** @@ -1335,6 +1355,7 @@ export class FlightPlanManager { * Unused */ public getArrivalDiscontinuity() { + // empty } /** @@ -1451,11 +1472,9 @@ export class FlightPlanManager { const currentFlightPlan = this._flightPlans[this._currentFlightPlanIndex]; if (currentFlightPlan.hasDestination && currentFlightPlan.procedureDetails.approachIndex >= 0) { - console.error('Destination runway index is -1 with valid STAR'); const approach = (currentFlightPlan.destinationAirfield.infos as AirportInfo).approaches[currentFlightPlan.procedureDetails.approachIndex]; const destRunways = (currentFlightPlan.destinationAirfield.infos as AirportInfo).oneWayRunways; - - await this.setDestinationRunwayIndex(destRunways.findIndex(r => r.number === approach.runwayNumber && r.designator === approach.runwayDesignator)); + await this.setDestinationRunwayIndex(destRunways.findIndex((r) => r.number === approach.runwayNumber && r.designator === approach.runwayDesignator)); } } @@ -1472,6 +1491,7 @@ export class FlightPlanManager { * @param callback A callback to call when the operation has completed. * @param transition The approach transition index to set in the approach information. */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars public async setApproachIndex(index: number, callback = () => { }, transition = -1): Promise { const currentFlightPlan = this._flightPlans[this._currentFlightPlanIndex]; // console.log(currentFlightPlan); @@ -1494,6 +1514,7 @@ export class FlightPlanManager { * Whether or not an approach is loaded in the current flight plan. * @param forceSimVarCall Unused */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars public isLoadedApproach(forceSimVarCall = false): boolean { const currentFlightPlan = this._flightPlans[this._currentFlightPlanIndex]; return currentFlightPlan.procedureDetails.approachIndex >= 0; @@ -1503,6 +1524,7 @@ export class FlightPlanManager { * Whether or not the approach is active in the current flight plan. * @param forceSimVarCall Unused */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars public isActiveApproach(forceSimVarCall = false): boolean { const currentFlightPlan = this._flightPlans[this._currentFlightPlanIndex]; return currentFlightPlan.approach.waypoints.length > 0 @@ -1526,12 +1548,14 @@ export class FlightPlanManager { * Deactivates the approach segments in the current flight plan. */ public deactivateApproach() { + // empty } /** * Attemptes to auto-activate the approach in the current flight plan. */ public tryAutoActivateApproach() { + // empty } /** @@ -1602,7 +1626,7 @@ export class FlightPlanManager { const approach = (flightPlan.destinationAirfield.infos as AirportInfo).approaches[flightPlan.procedureDetails.approachIndex]; const runways = (flightPlan.destinationAirfield.infos as AirportInfo).oneWayRunways; - return runways.findIndex(r => r.number === approach.runwayNumber && r.designator === approach.runwayDesignator); + return runways.findIndex((r) => r.number === approach.runwayNumber && r.designator === approach.runwayDesignator); } return -1; } @@ -1670,7 +1694,7 @@ export class FlightPlanManager { * @param callback A callback to call when the operation completes. */ public cancelDirectTo(callback = EmptyCallback.Void): void { - const currentFlightPlan = this._flightPlans[this._currentFlightPlanIndex]; + // const currentFlightPlan = this._flightPlans[this._currentFlightPlanIndex]; // currentFlightPlan.directTo.cancel(); callback(); @@ -1703,6 +1727,7 @@ export class FlightPlanManager { } public getCoordinatesHeadingAtDistanceAlongFlightPlan(_distance) { + // empty } /** @@ -1715,11 +1740,9 @@ export class FlightPlanManager { if (destination) { const fromStartDistance = destination.cumulativeDistanceInFP - distance; - let prevIndex; let prev; let next; for (let i = 0; i < allWaypoints.length - 1; i++) { - prevIndex = i; prev = allWaypoints[i]; next = allWaypoints[i + 1]; if (prev.cumulativeDistanceInFP < fromStartDistance && next.cumulativeDistanceInFP > fromStartDistance) { diff --git a/src/fmgc/src/flightplanning/LegsProcedure.ts b/src/fmgc/src/flightplanning/LegsProcedure.ts index 00f06fcabf5..3dfeed7ee75 100644 --- a/src/fmgc/src/flightplanning/LegsProcedure.ts +++ b/src/fmgc/src/flightplanning/LegsProcedure.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-underscore-dangle */ /* * MIT License * @@ -76,7 +77,7 @@ export class LegsProcedure { private airportMagVar: number, private approachType?: ApproachType, private legAnnotations?: string[], - ) { + ) { for (const leg of this._legs) { if (this.isIcaoValid(leg.fixIcao)) { this._facilitiesToLoad.set(leg.fixIcao, this._instrument.facilityLoader.getFacilityRaw(leg.fixIcao, 2000, true)); @@ -262,72 +263,72 @@ export class LegsProcedure { } private getMagCorrection(currentLeg: RawProcedureLeg): number { - // we try to interpret PANS OPs as accurately as possible within the limits of available data - - // magnetic tracks to/from a VOR always use VOR station declination - if (currentLeg.fixIcao.charAt(0) === 'V') { - const vor: RawVor = this.getLoadedFacility(currentLeg.fixIcao) as RawVor; - if (!vor || vor.magneticVariation === undefined) { - console.warn('Leg coded incorrectly (missing vor fix or station declination)', currentLeg, vor); - return this.airportMagVar; + // we try to interpret PANS OPs as accurately as possible within the limits of available data + + // magnetic tracks to/from a VOR always use VOR station declination + if (currentLeg.fixIcao.charAt(0) === 'V') { + const vor: RawVor = this.getLoadedFacility(currentLeg.fixIcao) as RawVor; + if (!vor || vor.magneticVariation === undefined) { + console.warn('Leg coded incorrectly (missing vor fix or station declination)', currentLeg, vor); + return this.airportMagVar; + } + return 360 - vor.magneticVariation; } - return 360 - vor.magneticVariation; - } - // we use station declination for VOR/DME approaches - if (this.approachType === ApproachType.APPROACH_TYPE_VORDME) { + // we use station declination for VOR/DME approaches + if (this.approachType === ApproachType.APPROACH_TYPE_VORDME) { // find a leg with the reference navaid for the procedure - for (let i = this._legs.length - 1; i >= 0; i--) { - if (this._legs[i].originIcao.trim().length > 0) { - const recNavaid: RawVor = this.getLoadedFacility(currentLeg.originIcao) as RawVor; - if (recNavaid && recNavaid.magneticVariation !== undefined) { - return 360 - recNavaid.magneticVariation; + for (let i = this._legs.length - 1; i >= 0; i--) { + if (this._legs[i].originIcao.trim().length > 0) { + const recNavaid: RawVor = this.getLoadedFacility(currentLeg.originIcao) as RawVor; + if (recNavaid && recNavaid.magneticVariation !== undefined) { + return 360 - recNavaid.magneticVariation; + } + } } - } + console.warn('VOR/DME approach coded incorrectly (missing recommended navaid or station declination)', currentLeg); + return this.airportMagVar; } - console.warn('VOR/DME approach coded incorrectly (missing recommended navaid or station declination)', currentLeg); - return this.airportMagVar; - } - // for RNAV procedures use recommended navaid station declination for these leg types - let useStationDeclination = (currentLeg.type === LegType.CF || currentLeg.type === LegType.FA || currentLeg.type === LegType.FM); + // for RNAV procedures use recommended navaid station declination for these leg types + let useStationDeclination = (currentLeg.type === LegType.CF || currentLeg.type === LegType.FA || currentLeg.type === LegType.FM); - // for localiser bearings (i.e. at or beyond FACF), always use airport value - if (this.approachType === ApproachType.APPROACH_TYPE_ILS || this.approachType === ApproachType.APPROACH_TYPE_LOCALIZER) { - useStationDeclination = useStationDeclination && this._legs.indexOf(currentLeg) < this.getFacfIndex(); - } + // for localiser bearings (i.e. at or beyond FACF), always use airport value + if (this.approachType === ApproachType.APPROACH_TYPE_ILS || this.approachType === ApproachType.APPROACH_TYPE_LOCALIZER) { + useStationDeclination = useStationDeclination && this._legs.indexOf(currentLeg) < this.getFacfIndex(); + } - if (useStationDeclination) { - const recNavaid: RawVor = this.getLoadedFacility(currentLeg.originIcao) as RawVor; - if (!recNavaid || recNavaid.magneticVariation === undefined) { - console.warn('Leg coded incorrectly (missing recommended navaid or station declination)', currentLeg, recNavaid); - return this.airportMagVar; + if (useStationDeclination) { + const recNavaid: RawVor = this.getLoadedFacility(currentLeg.originIcao) as RawVor; + if (!recNavaid || recNavaid.magneticVariation === undefined) { + console.warn('Leg coded incorrectly (missing recommended navaid or station declination)', currentLeg, recNavaid); + return this.airportMagVar; + } + return 360 - recNavaid.magneticVariation; } - return 360 - recNavaid.magneticVariation; - } - // for all other terminal procedure legs we use airport magnetic variation - return this.airportMagVar; + // for all other terminal procedure legs we use airport magnetic variation + return this.airportMagVar; } private getLoadedFacility(icao: string): RawFacility { - const facility = this._facilities.get(icao); - if (!facility) { - throw new Error(`Failed to load facility: ${icao}`); - } - return facility; + const facility = this._facilities.get(icao); + if (!facility) { + throw new Error(`Failed to load facility: ${icao}`); + } + return facility; } private getFacfIndex(): number { - if (this.approachType !== undefined) { - for (let i = this._legs.length - 1; i >= 0; i--) { - if (this._legs[i].fixTypeFlags & FixTypeFlags.IF) { - return i; - } + if (this.approachType !== undefined) { + for (let i = this._legs.length - 1; i >= 0; i--) { + if (this._legs[i].fixTypeFlags & FixTypeFlags.IF) { + return i; + } + } } - } - return undefined; + return undefined; } /** @@ -376,37 +377,37 @@ export class LegsProcedure { * @returns The mapped leg. */ public mapBearingAndDistanceFromOrigin(leg: RawProcedureLeg): WayPoint { - const origin = this.getLoadedFacility(leg.fixIcao); - const originIdent = origin.icao.substring(7, 12).trim(); - const course = leg.trueDegrees ? leg.course : A32NX_Util.magneticToTrue(leg.course, Facilities.getMagVar(origin.lat, origin.lon)); - // this is the leg length for FC, and the DME distance for FD - const refDistance = leg.distance / 1852; - - let termPoint; - let legLength; - if (leg.type === LegType.FD) { - const recNavaid = this.getLoadedFacility(leg.originIcao); - termPoint = firstSmallCircleIntersection( - { lat: recNavaid.lat, long: recNavaid.lon }, - refDistance, - { lat: origin.lat, long: origin.lon }, - course, - ); - legLength = Avionics.Utils.computeGreatCircleDistance( - { lat: origin.lat, long: origin.lon }, - termPoint, - ); - } else { // FC - termPoint = Avionics.Utils.bearingDistanceToCoordinates( - course, - refDistance, - origin.lat, - origin.lon, - ); - legLength = refDistance; - } - - return this.buildWaypoint(`${originIdent.substring(0, 3)}/${Math.round(legLength).toString().padStart(2, '0')}`, termPoint); + const origin = this.getLoadedFacility(leg.fixIcao); + const originIdent = origin.icao.substring(7, 12).trim(); + const course = leg.trueDegrees ? leg.course : A32NX_Util.magneticToTrue(leg.course, Facilities.getMagVar(origin.lat, origin.lon)); + // this is the leg length for FC, and the DME distance for FD + const refDistance = leg.distance / 1852; + + let termPoint; + let legLength; + if (leg.type === LegType.FD) { + const recNavaid = this.getLoadedFacility(leg.originIcao); + termPoint = firstSmallCircleIntersection( + { lat: recNavaid.lat, long: recNavaid.lon }, + refDistance, + { lat: origin.lat, long: origin.lon }, + course, + ); + legLength = Avionics.Utils.computeGreatCircleDistance( + { lat: origin.lat, long: origin.lon }, + termPoint, + ); + } else { // FC + termPoint = Avionics.Utils.bearingDistanceToCoordinates( + course, + refDistance, + origin.lat, + origin.lon, + ); + legLength = refDistance; + } + + return this.buildWaypoint(`${originIdent.substring(0, 3)}/${Math.round(legLength).toString().padStart(2, '0')}`, termPoint); } /** @@ -437,6 +438,7 @@ export class LegsProcedure { * @param nextLeg The next leg in the procedure to intercept. * @returns The mapped leg. */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars public mapHeadingToInterceptNextLeg(leg: RawProcedureLeg, prevLeg: WayPoint, nextLeg: RawProcedureLeg): WayPoint | null { const magVar = Facilities.getMagVar(prevLeg.infos.coordinates.lat, prevLeg.infos.coordinates.long); const course = leg.trueDegrees ? leg.course : A32NX_Util.magneticToTrue(leg.course, magVar); @@ -489,7 +491,7 @@ export class LegsProcedure { public mapHeadingUntilAltitude(leg: RawProcedureLeg, prevLeg: WayPoint) { const magVar = Facilities.getMagVar(prevLeg.infos.coordinates.lat, prevLeg.infos.coordinates.long); const course = leg.trueDegrees ? leg.course : A32NX_Util.magneticToTrue(leg.course, magVar); - const heading = leg.trueDegrees ? A32NX_Util.trueToMagnetic(leg.course, magVar) : leg.course; + // const heading = leg.trueDegrees ? A32NX_Util.trueToMagnetic(leg.course, magVar) : leg.course; const altitudeFeet = (leg.altitude1 * 3.2808399); const distanceInNM = altitudeFeet / 500.0; @@ -510,7 +512,7 @@ export class LegsProcedure { public mapVectors(leg: RawProcedureLeg, prevLeg: WayPoint) { const magVar = Facilities.getMagVar(prevLeg.infos.coordinates.lat, prevLeg.infos.coordinates.long); const course = leg.trueDegrees ? leg.course : A32NX_Util.magneticToTrue(leg.course, magVar); - const heading = leg.trueDegrees ? A32NX_Util.trueToMagnetic(leg.course, magVar) : leg.course; + // const heading = leg.trueDegrees ? A32NX_Util.trueToMagnetic(leg.course, magVar) : leg.course; const coordinates = GeoMath.relativeBearingDistanceToCoords(course, 1, prevLeg.infos.coordinates); const waypoint = this.buildWaypoint(FixNamingScheme.vector(), coordinates); @@ -531,11 +533,10 @@ export class LegsProcedure { return RawDataMapper.toWaypoint(facility, this._instrument); } + // eslint-disable-next-line @typescript-eslint/no-unused-vars public mapArcToFix(leg: RawProcedureLeg, prevLeg: WayPoint): WayPoint { const toFix = this.getLoadedFacility(leg.fixIcao); - const waypoint = RawDataMapper.toWaypoint(toFix, this._instrument); - return waypoint; } diff --git a/src/fmgc/src/flightplanning/ManagedFlightPlan.ts b/src/fmgc/src/flightplanning/ManagedFlightPlan.ts index 24a199964d9..951cbfcbbc8 100644 --- a/src/fmgc/src/flightplanning/ManagedFlightPlan.ts +++ b/src/fmgc/src/flightplanning/ManagedFlightPlan.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-underscore-dangle */ /* * MIT License * @@ -23,6 +24,7 @@ */ import { HoldData, WaypointStats } from '@fmgc/flightplanning/data/flightplan'; +import { WaypointConstraintType } from '@fmgc/flightplanning/FlightPlanManager'; import { AltitudeDescriptor, FixTypeFlags, LegType } from '../types/fstypes/FSEnums'; import { FlightPlanSegment, SegmentType } from './FlightPlanSegment'; import { LegsProcedure } from './LegsProcedure'; @@ -32,7 +34,6 @@ import { ProcedureDetails } from './ProcedureDetails'; import { DirectTo } from './DirectTo'; import { GeoMath } from './GeoMath'; import { WaypointBuilder } from './WaypointBuilder'; -import { WaypointConstraintType } from '@fmgc/flightplanning/FlightPlanManager'; /** * A flight plan managed by the FlightPlanManager. @@ -200,11 +201,7 @@ export class ManagedFlightPlan { private computeWaypointEta(distance: number, preComputedTime? :number) { const eta = preComputedTime ?? this.computeWaypointTime(distance); - const utcTime = SimVar.GetGlobalVarValue('ZULU TIME', 'seconds'); - - // // console.log(`BRUHEGG: ${utcTime}, BRUHHH #2: ${eta}`); - return eta + utcTime; } @@ -361,7 +358,8 @@ export class ManagedFlightPlan { index?: number | undefined, segmentType?: SegmentType, ): number { - console.log('addWaypoint', waypoint, index, SegmentType[segmentType]); + console.log(`addWaypoint ${waypoint.icao}, ${index}, ${SegmentType[segmentType]}`, waypoint); + const mappedWaypoint: WayPoint = (waypoint instanceof WayPoint) ? waypoint : RawDataMapper.toWaypoint(waypoint, this._parentInstrument); if (mappedWaypoint.type === 'A' && index === 0) { @@ -482,28 +480,21 @@ export class ManagedFlightPlan { * @param index The index of the waypoint to remove. */ public removeWaypoint(index: number, noDiscontinuity: boolean = false): void { - let removed = null; if (this.originAirfield && index === 0) { - removed = this.originAirfield; this.originAirfield = undefined; - this.reflowSegments(); this.reflowDistances(); } else if (this.destinationAirfield && index === this.length - 1) { - removed = this.destinationAirfield; this.destinationAirfield = undefined; } else { const segment = this.findSegmentByWaypointIndex(index); if (segment) { - // console.log("--> REMOVING WAYPOINT ", this.getWaypoint(index), ", FROM SEGMENT ", segment); const spliced = segment.waypoints.splice(index - segment.offset, 1); - removed = spliced[0]; - + console.log(`removing waypoint ${spliced[0].icao} from segment ${segment.type}`); if (segment.waypoints.length === 0 && segment.type !== SegmentType.Enroute) { - // console.log("SEGMENT LENGTH is 0, REMOVING..."); + console.log(`removing segment ${segment.type} as length is 0`); this.removeSegment(segment.type); } - this.reflowSegments(); this.reflowDistances(); } @@ -570,7 +561,7 @@ export class ManagedFlightPlan { const atWaypoint = this.getWaypoint(index); if (!atWaypoint) { - return; + return 0; } const magVar = Facilities.getMagVar(atWaypoint.infos.coordinates.lat, atWaypoint.infos.coordinates.long); @@ -588,14 +579,13 @@ export class ManagedFlightPlan { atWaypoint.additionalData.defaultHold = defaultHold; } return index; - } else { - const manualHoldWaypoint = WaypointBuilder.fromWaypointManualHold(atWaypoint, desiredHold.turnDirection, trueCourse, desiredHold.distance, desiredHold.time, this._parentInstrument); - manualHoldWaypoint.additionalData.modifiedHold = modifiedHold; - manualHoldWaypoint.additionalData.defaultHold = defaultHold; - - this.addWaypoint(manualHoldWaypoint, index + 1); - return index + 1; } + const manualHoldWaypoint = WaypointBuilder.fromWaypointManualHold(atWaypoint, desiredHold.turnDirection, trueCourse, desiredHold.distance, desiredHold.time, this._parentInstrument); + manualHoldWaypoint.additionalData.modifiedHold = modifiedHold; + manualHoldWaypoint.additionalData.defaultHold = defaultHold; + + this.addWaypoint(manualHoldWaypoint, index + 1); + return index + 1; } /** @@ -799,7 +789,7 @@ export class ManagedFlightPlan { newFlightPlan._segments[i].waypoints = [...seg.waypoints.map((wp) => { const clone = new (wp as any).constructor(); Object.assign(clone, wp); - clone.additionalData = Object.assign({}, wp.additionalData); + clone.additionalData = { ...wp.additionalData }; return clone; })]; } @@ -832,10 +822,15 @@ export class ManagedFlightPlan { const oldToWp = this.waypoints[this.activeWaypointIndex]; - const turningPoint = WaypointBuilder.fromCoordinates('T-P', new LatLongAlt(lat, long), this._parentInstrument, { legType: LegType.CF, course: trueTrack, dynamicPpos: true }, this.getTurningPointIcao()); + const turningPoint = WaypointBuilder.fromCoordinates( + 'T-P', + new LatLongAlt(lat, long), + this._parentInstrument, { legType: LegType.CF, course: trueTrack, dynamicPpos: true }, + this.getTurningPointIcao(), + ); turningPoint.isTurningPoint = true; - let waypointIndex = this.waypoints.findIndex((w, idx) => idx >= this.activeWaypointIndex && w.icao === waypoint.icao); + const waypointIndex = this.waypoints.findIndex((w, idx) => idx >= this.activeWaypointIndex && w.icao === waypoint.icao); if (waypointIndex === -1) { // in this case the waypoint is not already in the flight plan // we string it to the start of the flight plan, add a discontinuity after, and then the existing flight plan @@ -880,7 +875,7 @@ export class ManagedFlightPlan { private getTurningPointIcao(): string { this.turningPointIndex = (this.turningPointIndex + 1) % 1000; - return `WXX TP${this.turningPointIndex.toFixed(0).padStart(3, '0')}` + return `WXX TP${this.turningPointIndex.toFixed(0).padStart(3, '0')}`; } /** @@ -925,7 +920,7 @@ export class ManagedFlightPlan { const departure: RawDeparture = airportInfo.departures[departureIndex]; if (runwayTransition) { legs.push(...runwayTransition.legs); - legAnnotations.push(...runwayTransition.legs.map(_ => departure.name)); + legAnnotations.push(...runwayTransition.legs.map((_) => departure.name)); origin.endsInDiscontinuity = false; origin.discontinuityCanBeCleared = undefined; } @@ -934,14 +929,14 @@ export class ManagedFlightPlan { if (departureIndex >= 0) { const departure: RawDeparture = airportInfo.departures[departureIndex]; legs.push(...departure.commonLegs); - legAnnotations.push(...departure.commonLegs.map(_ => departure.name)); + legAnnotations.push(...departure.commonLegs.map((_) => departure.name)); } if (transitionIndex >= 0 && departureIndex >= 0) { if (airportInfo.departures[departureIndex].enRouteTransitions.length > 0) { const transition: RawEnRouteTransition = airportInfo.departures[departureIndex].enRouteTransitions[transitionIndex]; legs.push(...transition.legs); - legAnnotations.push(...transition.legs.map(_ => transition.name)); + legAnnotations.push(...transition.legs.map((_) => transition.name)); } } @@ -956,7 +951,7 @@ export class ManagedFlightPlan { if (legs.length > 0 || selectedOriginRunwayIndex >= 0 || (departureIndex >= 0 && runwayIndex >= 0)) { segment = this.addSegment(SegmentType.Departure); - let procedure = new LegsProcedure(legs, origin, this._parentInstrument, airportMagVar, undefined, legAnnotations); + const procedure = new LegsProcedure(legs, origin, this._parentInstrument, airportMagVar, undefined, legAnnotations); const runway: OneWayRunway | null = this.getOriginRunway(); @@ -983,6 +978,7 @@ export class ManagedFlightPlan { let waypointIndex = segment.offset; while (procedure.hasNext()) { + // eslint-disable-next-line no-await-in-loop const waypoint = await procedure.getNext(); if (waypoint !== undefined) { @@ -1018,7 +1014,7 @@ export class ManagedFlightPlan { const destination = this.destinationAirfield; const { arrivalIndex } = this.procedureDetails; - const { approachTransitionIndex } = this.procedureDetails; + // const { approachTransitionIndex } = this.procedureDetails; const { arrivalRunwayIndex } = this.procedureDetails; const { arrivalTransitionIndex } = this.procedureDetails; @@ -1029,7 +1025,7 @@ export class ManagedFlightPlan { const transition: RawEnRouteTransition = destinationInfo.arrivals[arrivalIndex].enRouteTransitions[arrivalTransitionIndex]; if (transition !== undefined) { legs.push(...transition.legs); - legAnnotations.push(...transition.legs.map(_ => transition.name)); + legAnnotations.push(...transition.legs.map((_) => transition.name)); // console.log('MFP: buildArrival - pushing transition legs ->', legs); } } @@ -1038,7 +1034,7 @@ export class ManagedFlightPlan { // string the common legs in the middle of the STAR const arrival: RawArrival = destinationInfo.arrivals[arrivalIndex]; legs.push(...arrival.commonLegs); - legAnnotations.push(...arrival.commonLegs.map(_ => arrival.name)); + legAnnotations.push(...arrival.commonLegs.map((_) => arrival.name)); // console.log('MFP: buildArrival - pushing STAR legs ->', legs); // if no runway is selected at all (non-runway-specific approach) @@ -1051,7 +1047,7 @@ export class ManagedFlightPlan { const runwayTransition = arrival.runwayTransitions[runwayTransIndex]; if (runwayTransition) { legs.push(...runwayTransition.legs); - legAnnotations.push(...runwayTransition.legs.map(_ => arrival.name)); + legAnnotations.push(...runwayTransition.legs.map((_) => arrival.name)); } } @@ -1068,6 +1064,7 @@ export class ManagedFlightPlan { let waypointIndex = segment.offset; // console.log('MFP: buildArrival - ADDING WAYPOINTS ------------------------'); while (procedure.hasNext()) { + // eslint-disable-next-line no-await-in-loop const waypoint = await procedure.getNext(); if (waypoint) { @@ -1106,7 +1103,7 @@ export class ManagedFlightPlan { if (approachIndex >= 0 && approachTransitionIndex >= 0) { const transition: RawApproachTransition = destinationInfo.approaches[approachIndex].transitions[approachTransitionIndex]; legs.push(...transition.legs); - legAnnotations.push(...transition.legs.map(_ => transition.name)); + legAnnotations.push(...transition.legs.map((_) => transition.name)); // console.log('MFP: buildApproach - pushing approachTransition legs ->', legs); } @@ -1125,7 +1122,7 @@ export class ManagedFlightPlan { this.procedureDetails.approachType = approach.approachType; legs.push(...finalLegs); - legAnnotations.push(...finalLegs.map(_ => approachName)); + legAnnotations.push(...finalLegs.map((_) => approachName)); missedLegs.push(...approach.missedLegs); } @@ -1153,6 +1150,7 @@ export class ManagedFlightPlan { let waypointIndex = _startIndex; // console.log('MFP: buildApproach - ADDING WAYPOINTS ------------------------'); while (procedure.hasNext()) { + // eslint-disable-next-line no-await-in-loop const waypoint = await procedure.getNext(); if (waypoint !== undefined) { @@ -1164,19 +1162,19 @@ export class ManagedFlightPlan { } if (runway) { - const selectedRunwayMod = runway.designation.slice(-1); - let selectedRunwayOutput; - if (selectedRunwayMod === 'L' || selectedRunwayMod === 'C' || selectedRunwayMod === 'R') { - if (runway.designation.length === 2) { - selectedRunwayOutput = `0${runway.designation}`; - } else { - selectedRunwayOutput = runway.designation; - } - } else if (runway.designation.length === 2) { - selectedRunwayOutput = runway.designation; - } else { - selectedRunwayOutput = `0${runway.designation}`; - } + // const selectedRunwayMod = runway.designation.slice(-1); + // let selectedRunwayOutput; + // if (selectedRunwayMod === 'L' || selectedRunwayMod === 'C' || selectedRunwayMod === 'R') { + // if (runway.designation.length === 2) { + // selectedRunwayOutput = `0${runway.designation}`; + // } else { + // selectedRunwayOutput = runway.designation; + // } + // } else if (runway.designation.length === 2) { + // selectedRunwayOutput = runway.designation; + // } else { + // selectedRunwayOutput = `0${runway.designation}`; + // } // When adding approach, edit destination waypoint this.destinationAirfield.infos.coordinates = runway.beginningCoordinates; @@ -1186,7 +1184,9 @@ export class ManagedFlightPlan { if (approachIndex >= 0) { const lastLeg = approach.finalLegs[approach.finalLegs.length - 1]; if (lastLeg.type === LegType.CF) { - const magCourse = lastLeg.trueDegrees ? A32NX_Util.trueToMagnetic(lastLeg.course, Facilities.getMagVar(runway.beginningCoordinates.lat, runway.beginningCoordinates.long)) : lastLeg.course; + const magCourse = lastLeg.trueDegrees + ? A32NX_Util.trueToMagnetic(lastLeg.course, Facilities.getMagVar(runway.beginningCoordinates.lat, runway.beginningCoordinates.long)) + : lastLeg.course; this.destinationAirfield.additionalData.annotation = `C${magCourse.toFixed(0).padStart(3, '0')}°`; } else { this.destinationAirfield.additionalData.annotation = approachName; @@ -1231,26 +1231,26 @@ export class ManagedFlightPlan { private static isXfLeg(leg: WayPoint): boolean { switch (leg?.additionalData?.legType) { - case LegType.CF: - case LegType.DF: - case LegType.IF: - case LegType.RF: - case LegType.TF: - return true; - default: - return false; + case LegType.CF: + case LegType.DF: + case LegType.IF: + case LegType.RF: + case LegType.TF: + return true; + default: + return false; } } private static isFxLeg(leg: WayPoint): boolean { switch (leg?.additionalData?.legType) { - case LegType.FA: - case LegType.FC: - case LegType.FD: - case LegType.FM: - return true; - default: - return false; + case LegType.FA: + case LegType.FC: + case LegType.FD: + case LegType.FM: + return true; + default: + return false; } } @@ -1260,21 +1260,25 @@ export class ManagedFlightPlan { private static climbConstraint(leg: WayPoint): number { switch (leg.legAltitudeDescription) { - case AltitudeDescriptor.At: - case AltitudeDescriptor.AtOrBelow: - return leg.legAltitude1; - case AltitudeDescriptor.Between: - return leg.legAltitude2; + case AltitudeDescriptor.At: + case AltitudeDescriptor.AtOrBelow: + return leg.legAltitude1; + case AltitudeDescriptor.Between: + return leg.legAltitude2; + default: + break; } return Infinity; } private static descentConstraint(leg: WayPoint): number { switch (leg.legAltitudeDescription) { - case AltitudeDescriptor.At: - case AltitudeDescriptor.AtOrAbove: - case AltitudeDescriptor.Between: - return leg.legAltitude1; + case AltitudeDescriptor.At: + case AltitudeDescriptor.AtOrAbove: + case AltitudeDescriptor.Between: + return leg.legAltitude1; + default: + break; } return -Infinity; } @@ -1324,7 +1328,7 @@ export class ManagedFlightPlan { legAltitude1, legAltitude2, speedConstraint: Number.isFinite(speed) ? speed : 0, - } + }; } /** @@ -1534,8 +1538,7 @@ export class ManagedFlightPlan { default: } } else if (ManagedFlightPlan.isXfLeg(a) && ManagedFlightPlan.isXfLeg(b) - || ManagedFlightPlan.isFxLeg(a) && ManagedFlightPlan.isFxLeg(b)) - { + || ManagedFlightPlan.isFxLeg(a) && ManagedFlightPlan.isFxLeg(b)) { return a.icao === b.icao; } @@ -1593,6 +1596,7 @@ export class ManagedFlightPlan { return wp.legAltitude1; } } + return undefined; } get destinationIndex(): number { diff --git a/src/fmgc/src/flightplanning/RawDataMapper.ts b/src/fmgc/src/flightplanning/RawDataMapper.ts index 6a260d65777..3627adc4fa2 100644 --- a/src/fmgc/src/flightplanning/RawDataMapper.ts +++ b/src/fmgc/src/flightplanning/RawDataMapper.ts @@ -53,16 +53,28 @@ 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.trim().length === 0 && (trans.name = WayPoint.formatIdentFromIcao(trans.legs[0].fixIcao)))); + 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.trim().length === 0 && (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.trim().length === 0 && (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; @@ -143,6 +155,8 @@ export class RawDataMapper { case 3: name += 'C'; break; + default: + break; } return name; From 592f561238546cc8a9ac4b257dd12c5093fee169 Mon Sep 17 00:00:00 2001 From: Benjamin Dupont Date: Sat, 31 Dec 2022 15:23:38 -0500 Subject: [PATCH 09/39] ci: upload to cloudflare in master and stable pipelines (#7680) --- .github/workflows/master.yml | 6 ++++++ .github/workflows/release.yml | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml index b495948338f..2e447ba35f9 100644 --- a/.github/workflows/master.yml +++ b/.github/workflows/master.yml @@ -89,6 +89,12 @@ jobs: run: | ./scripts/cdn.sh $BUNNY_BUCKET_DESTINATION ./build-modules ./scripts/cdn.sh $BUNNY_BUCKET_DESTINATION ./${{ env.BUILD_DIR_NAME }} + - name: Upload to CloudFlare CDN + env: + CLOUDFLARE_BUCKET_PASSWORD: ${{ secrets.CLOUDFLARE_BUCKET_PASSWORD }} + CDN_BUCKET_DESTINATION: addons/a32nx/master + run: | + ./scripts/cf-cdn.sh $CDN_BUCKET_DESTINATION ./build-modules - name: Delete old GitHub Pre-Release assets uses: mknejp/delete-release-assets@v1 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2f7d92ef3e2..9d594385774 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -66,6 +66,12 @@ jobs: run: | ./scripts/cdn.sh $BUNNY_BUCKET_DESTINATION ./build-modules ./scripts/cdn.sh $BUNNY_BUCKET_DESTINATION ./${{ env.BUILD_DIR_NAME }} + - name: Upload to CloudFlare CDN + env: + CLOUDFLARE_BUCKET_PASSWORD: ${{ secrets.CLOUDFLARE_BUCKET_PASSWORD }} + CDN_BUCKET_DESTINATION: addons/a32nx/stable + run: | + ./scripts/cf-cdn.sh $CDN_BUCKET_DESTINATION ./build-modules - name: Delete old GitHub Pre-Release assets uses: mknejp/delete-release-assets@v1 with: From ca06c904ce3eaeaebf360202608db343c07e01d5 Mon Sep 17 00:00:00 2001 From: Benjamin Dupont Date: Sat, 31 Dec 2022 16:20:01 -0500 Subject: [PATCH 10/39] fix: cf-cdn.sh permissions (#7681) Co-authored-by: Saschl --- scripts/cf-cdn.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/cf-cdn.sh diff --git a/scripts/cf-cdn.sh b/scripts/cf-cdn.sh old mode 100644 new mode 100755 From 2b2721a36a3e021db354f487a8222f00d4caaca5 Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 2 Jan 2023 12:35:17 +0100 Subject: [PATCH 11/39] feat(efb): Add estimated boarding time (#7583) Co-authored-by: Frank Kopp Fixes https://github.com/flybywiresim/a32nx/issues/7418 --- .github/CHANGELOG.md | 2 + .../src/EFB/Ground/Pages/Payload/Payload.tsx | 43 ++++++++++++++++--- src/instruments/src/EFB/Localization/de.json | 3 +- 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index 3c28bcd6e7c..e923ee90f94 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -20,6 +20,7 @@ 1. [RMP] RMPs navigation backup - Julian Sebline (Julian Sebline#8476 on Discord) 1. [SEC] Fix GND SPLR logic, add missing GND SPLR partial extension condition - @lukecologne (luke) 1. [FMGC] Improved importing flight plans from MSFS World Map - @frankkopp (Frank Kopp) +1. [EFB] Added boarding time indication to Payload page - @ChristianLutzCL (Christian Lutz) @frankkopp (Frank Kopp) ## 0.9.0 @@ -1155,3 +1156,4 @@ 1. [DCDU] Fixed MSG- and MSG+ button labels - @tyler58546 (tyler58546) 1. [ISIS] Fixed issue where ISIS was allowing a bug to be set while in the OFF state - Patrick Macken (@Pat M on Discord) +1. [EFB] Added estimated boarding time to Payload screen - @ChristianLutzCL (Christian Lutz) \ No newline at end of file diff --git a/src/instruments/src/EFB/Ground/Pages/Payload/Payload.tsx b/src/instruments/src/EFB/Ground/Pages/Payload/Payload.tsx index 97d1f23ac69..c4edd54850d 100644 --- a/src/instruments/src/EFB/Ground/Pages/Payload/Payload.tsx +++ b/src/instruments/src/EFB/Ground/Pages/Payload/Payload.tsx @@ -16,7 +16,7 @@ import { useBitFlags } from '@instruments/common/bitFlags'; import { round } from 'lodash'; import { CargoWidget } from './Seating/CargoWidget'; import { ChartWidget } from './Chart/ChartWidget'; -import { PaxStationInfo, CargoStationInfo } from './Seating/Constants'; +import { CargoStationInfo, PaxStationInfo } from './Seating/Constants'; import { t } from '../../../translation'; import { TooltipWrapper } from '../../../UtilComponents/TooltipWrapper'; import { SimpleInput } from '../../../UtilComponents/Form/SimpleInput/SimpleInput'; @@ -356,6 +356,27 @@ export const Payload = () => { setBoardingStarted(false); }; + const calculateBoardingTime = useMemo(() => { + // factors taken from flybywire-aircraft-a320-neo/html_ui/Pages/A32NX_Core/A32NX_Boarding.js line 175+ + let boardingRateMultiplier = 0; + if (boardingRate === 'REAL') { + boardingRateMultiplier = 5; + } else if (boardingRate === 'FAST') { + boardingRateMultiplier = 1; + } + + // value taken from flybywire-aircraft-a320-neo/html_ui/Pages/A32NX_Core/A32NX_Boarding.js line 210 + const cargoWeightPerWeightStep = 60; + + const differentialPax = Math.abs(totalPaxDesired - totalPax); + const differentialCargo = Math.abs(totalCargoDesired - totalCargo); + + const estimatedPaxBoardingSeconds = differentialPax * boardingRateMultiplier; + const estimatedCargoLoadingSeconds = (differentialCargo / cargoWeightPerWeightStep) * boardingRateMultiplier; + + return Math.max(estimatedPaxBoardingSeconds, estimatedCargoLoadingSeconds); + }, [totalPaxDesired, totalPax, totalCargoDesired, totalCargo, boardingRate]); + const boardingStatusClass = useMemo(() => { if (!boardingStarted) { return 'text-theme-highlight'; @@ -575,6 +596,13 @@ export const Payload = () => { emptyWeight, ]); + const remainingTimeString = () => { + const minutes = Math.round(calculateBoardingTime / 60); + const seconds = calculateBoardingTime % 60; + const padding = seconds < 10 ? '0' : ''; + return `${minutes}:${padding}${seconds.toFixed(0)} ${t('Ground.Payload.EstimatedDurationUnit')}`; + }; + return (
@@ -753,7 +781,7 @@ export const Payload = () => {