Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(a380x/fctl): Protection speeds improvements after flight model update #9694

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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
1. [ATC/TCAS] Fixed TCAS failure on baro corrected altitude going invalid - @tracernz (Mike)
1. [ATC/TCAS] Fixed TCAS slant range computation - @tracernz (Mike)
1. [A380X] Add baro unit (hPa/in.Hg) auto selection - @tracernz (Mike)
1. [A380X/PRIM] Adapt protection speeds to new flight model - @flogross89 (floridude)

## 0.12.0

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { DisplayComponent, EventBus, FSComponent, Subject, Subscribable, VNode } from '@microsoft/msfs-sdk';
import { getDisplayIndex } from 'instruments/src/PFD/PFD';
import { Arinc429Word } from '@flybywiresim/fbw-sdk';
import { Arinc429ConsumerSubject, Arinc429Word } from '@flybywiresim/fbw-sdk';
import { FlightPathDirector } from './FlightPathDirector';
import { FlightPathVector } from './FlightPathVector';
import { Arinc429Values } from './shared/ArincValueProvider';
Expand All @@ -11,18 +11,22 @@ interface AttitudeIndicatorFixedUpperProps {
}

export class AttitudeIndicatorFixedUpper extends DisplayComponent<AttitudeIndicatorFixedUpperProps> {
private readonly sub = this.props.bus.getSubscriber<Arinc429Values>();

private roll = new Arinc429Word(0);

private pitch = new Arinc429Word(0);

private visibilitySub = Subject.create('hidden');

private readonly fcdcDiscreteWord1 = Arinc429ConsumerSubject.create(this.sub.on('fcdcDiscreteWord1'));

private readonly isNormalLawActive = this.fcdcDiscreteWord1.map((dw) => dw.bitValue(11) && !dw.isFailureWarning());

onAfterRender(node: VNode): void {
super.onAfterRender(node);

const sub = this.props.bus.getSubscriber<Arinc429Values>();

sub.on('rollAr').handle((roll) => {
this.sub.on('rollAr').handle((roll) => {
this.roll = roll;
if (!this.roll.isNormalOperation()) {
this.visibilitySub.set('hidden');
Expand All @@ -31,7 +35,7 @@ export class AttitudeIndicatorFixedUpper extends DisplayComponent<AttitudeIndica
}
});

sub.on('pitchAr').handle((pitch) => {
this.sub.on('pitchAr').handle((pitch) => {
this.pitch = pitch;
if (!this.pitch.isNormalOperation()) {
this.visibilitySub.set('hidden');
Expand All @@ -44,11 +48,19 @@ export class AttitudeIndicatorFixedUpper extends DisplayComponent<AttitudeIndica
render(): VNode {
return (
<g id="AttitudeUpperInfoGroup" visibility={this.visibilitySub}>
<g id="RollProtGroup" class="SmallStroke Green">
<g
id="RollProtGroup"
class="SmallStroke Green"
style={{ display: this.isNormalLawActive.map((nl) => (nl ? 'block' : 'none')) }}
>
<path id="RollProtRight" d="m105.64 62.887 1.5716-0.8008m-1.5716-0.78293 1.5716-0.8008" />
<path id="RollProtLeft" d="m32.064 61.303-1.5716-0.8008m1.5716 2.3845-1.5716-0.8008" />
</g>
<g id="RollProtLost" style="display: none" class="NormalStroke Amber">
<g
id="RollProtLost"
class="NormalStroke Amber"
style={{ display: this.isNormalLawActive.map((nl) => (!nl ? 'block' : 'none')) }}
>
<path id="RollProtLostRight" d="m107.77 60.696-1.7808 1.7818m1.7808 0-1.7808-1.7818" />
<path id="RollProtLostLeft" d="m30.043 62.478 1.7808-1.7818m-1.7808 0 1.7808 1.7818" />
</g>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
VNode,
} from '@microsoft/msfs-sdk';

import { Arinc429Register, Arinc429Word, ArincEventBus } from '@flybywiresim/fbw-sdk';
import { Arinc429ConsumerSubject, Arinc429Register, Arinc429Word, ArincEventBus } from '@flybywiresim/fbw-sdk';
import {
calculateHorizonOffsetFromPitch,
calculateVerticalOffsetFromRoll,
Expand Down Expand Up @@ -109,18 +109,22 @@ interface HorizonProps {
}

export class Horizon extends DisplayComponent<HorizonProps> {
private readonly sub = this.props.bus.getArincSubscriber<Arinc429Values>();

private pitchGroupRef = FSComponent.createRef<SVGGElement>();

private rollGroupRef = FSComponent.createRef<SVGGElement>();

private yOffset = Subject.create(0);

private readonly fcdcDiscreteWord1 = Arinc429ConsumerSubject.create(this.sub.on('fcdcDiscreteWord1'));

private readonly isNormalLawActive = this.fcdcDiscreteWord1.map((dw) => dw.bitValue(11) && !dw.isFailureWarning());

onAfterRender(node: VNode): void {
super.onAfterRender(node);

const apfd = this.props.bus.getArincSubscriber<Arinc429Values>();

apfd
this.sub
.on('pitchAr')
.withArinc429Precision(3)
.handle((pitch) => {
Expand All @@ -137,7 +141,7 @@ export class Horizon extends DisplayComponent<HorizonProps> {
this.yOffset.set(yOffset);
});

apfd
this.sub
.on('rollAr')
.withArinc429Precision(2)
.handle((roll) => {
Expand Down Expand Up @@ -189,19 +193,35 @@ export class Horizon extends DisplayComponent<HorizonProps> {
<path d="m47.906-19.177h42h0" />
</g>

<g id="PitchProtUpper" class="NormalStroke Green">
<g
id="PitchProtUpper"
class="NormalStroke Green"
style={{ display: this.isNormalLawActive.map((nl) => (nl ? 'inherit' : 'none')) }}
>
<path d="m51.506 31.523h4m-4-1.4h4" />
<path d="m86.306 31.523h-4m4-1.4h-4" />
</g>
<g id="PitchProtLostUpper" style="display: none" class="NormalStroke Amber">
<g
id="PitchProtLostUpper"
class="NormalStroke Amber"
style={{ display: this.isNormalLawActive.map((nl) => (!nl ? 'inherit' : 'none')) }}
>
<path d="m52.699 30.116 1.4142 1.4142m-1.4142 0 1.4142-1.4142" />
<path d="m85.114 31.53-1.4142-1.4142m1.4142 0-1.4142 1.4142" />
</g>
<g id="PitchProtLower" class="NormalStroke Green">
<g
id="PitchProtLower"
class="NormalStroke Green"
style={{ display: this.isNormalLawActive.map((nl) => (nl ? 'inherit' : 'none')) }}
>
<path d="m59.946 104.52h4m-4-1.4h4" />
<path d="m77.867 104.52h-4m4-1.4h-4" />
</g>
<g id="PitchProtLostLower" style="display: none" class="NormalStroke Amber">
<g
id="PitchProtLostLower"
class="NormalStroke Amber"
style={{ display: this.isNormalLawActive.map((nl) => (!nl ? 'inherit' : 'none')) }}
>
<path d="m61.199 103.12 1.4142 1.4142m-1.4142 0 1.4142-1.4142" />
<path d="m76.614 104.53-1.4142-1.4142m1.4142 0-1.4142 1.4142" />
</g>
Expand Down
26 changes: 24 additions & 2 deletions fbw-a380x/src/systems/instruments/src/PFD/FMA.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
import { ArmedLateralMode, isArmed, LateralMode, VerticalMode } from '@shared/autopilot';
import { Arinc429Values } from './shared/ArincValueProvider';
import { PFDSimvars } from './shared/PFDSimvarPublisher';
import { Arinc429Word } from '@flybywiresim/fbw-sdk';
import { Arinc429ConsumerSubject, Arinc429Word, Arinc429WordData } from '@flybywiresim/fbw-sdk';

abstract class ShowForSecondsComponent<T extends ComponentProps> extends DisplayComponent<T> {
private timeout: number = 0;
Expand Down Expand Up @@ -89,6 +89,10 @@ export class FMA extends DisplayComponent<{ bus: EventBus; isAttExcessive: Subsc

private readonly approachCapability = ConsumerSubject.create(this.sub.on('approachCapability'), 0);

private readonly fcdcDiscreteWord1 = Arinc429ConsumerSubject.create(this.sub.on('fcdcDiscreteWord1'));

private readonly fwcFlightPhase = ConsumerSubject.create(this.sub.on('fwcFlightPhase'), 0);

private disconnectApForLdg = MappedSubject.create(
([ap1, ap2, ra, altitude, landingElevation, verticalMode, selectedFpa, selectedVs, approachCapability]) => {
return (
Expand Down Expand Up @@ -126,6 +130,8 @@ export class FMA extends DisplayComponent<{ bus: EventBus; isAttExcessive: Subsc
this.props.isAttExcessive.get(),
this.armedVerticalModeSub.get(),
this.setHoldSpeed,
this.fcdcDiscreteWord1.get(),
this.fwcFlightPhase.get(),
this.trkFpaDeselected.get(),
this.tcasRaInhibited.get(),
this.tdReached,
Expand Down Expand Up @@ -164,6 +170,9 @@ export class FMA extends DisplayComponent<{ bus: EventBus; isAttExcessive: Subsc

this.disconnectApForLdg.sub(() => this.handleFMABorders());

this.fcdcDiscreteWord1.sub(() => this.handleFMABorders());
this.fwcFlightPhase.sub(() => this.handleFMABorders());

this.props.isAttExcessive.sub((_a) => {
this.handleFMABorders();
});
Expand Down Expand Up @@ -1347,19 +1356,23 @@ const getBC3Message = (
isAttExcessive: boolean,
armedVerticalMode: number,
setHoldSpeed: boolean,
fcdcWord1: Arinc429WordData,
fwcFlightPhase: number,
trkFpaDeselectedTCAS: boolean,
tcasRaInhibited: boolean,
tdReached: boolean,
disconnectApForLdg: boolean,
) => {
const flightPhaseForWarning =
fwcFlightPhase >= 2 && fwcFlightPhase <= 11 && !(fwcFlightPhase >= 4 && fwcFlightPhase <= 7);
const armedVerticalBitmask = armedVerticalMode;
const TCASArmed = (armedVerticalBitmask >> 6) & 1;

let text: string;
let className: string;

// All currently unused message are set to false
if (false) {
if (fcdcWord1.bitValue(15) && !fcdcWord1.isFailureWarning() && flightPhaseForWarning) {
text = 'USE MAN PITCH TRIM';
className = 'PulseAmber9Seconds Amber';
} else if (false) {
Expand Down Expand Up @@ -1425,11 +1438,17 @@ class BC3Cell extends DisplayComponent<{

private tdReached = false;

private readonly fcdcDiscreteWord1 = Arinc429ConsumerSubject.create(this.sub.on('fcdcDiscreteWord1'));

private readonly fwcFlightPhase = ConsumerSubject.create(this.sub.on('fwcFlightPhase'), 0);

private fillBC3Cell() {
const [text, className] = getBC3Message(
this.isAttExcessive,
this.armedVerticalMode,
this.setHoldSpeed,
this.fcdcDiscreteWord1.get(),
this.fwcFlightPhase.get(),
this.trkFpaDeselected,
this.tcasRaInhibited,
this.tdReached,
Expand All @@ -1446,6 +1465,9 @@ class BC3Cell extends DisplayComponent<{
onAfterRender(node: VNode): void {
super.onAfterRender(node);

this.fcdcDiscreteWord1.sub(() => this.fillBC3Cell());
this.fwcFlightPhase.sub(() => this.fillBC3Cell());

this.props.isAttExcessive.sub((e) => {
this.isAttExcessive = e;
this.fillBC3Cell();
Expand Down
Loading
Loading