Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat(a380x/fadec): N1 fan protection measures (METOTS, KOZ) #9481

Merged
merged 15 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from 13 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
2 changes: 2 additions & 0 deletions .github/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
1. [A380X/ENG] Another adjustment to taxi thrust - @donstim (donbikes)
1. [A380X/ANIM] Animation of flaps now from FPPU position. Interim fix for spoiler low end animation - @Crocket63 (crocket)
1. [A380X/ENG] Improve oil pressure lookup table - @tracernz (Mike)
1. [A380X/FADEC] Add N1 fan protection measures (METOTS, KOZ) - @flogross89 (floridude)
1. [A380/WING_FLEX] Reduced stiffness of wings for more tip up bend - @Crocket63 (crocket)
1. [A380X/WING_FLEX] Reduced stiffness of wings for more tip up bend - @Crocket63 (crocket)
1. [A380X/FWS] Add V1 callout - @flogross89 (floridude)
1. [FMS] Fix existing T-P moving when inserting temporary flight plan - @Benjozork (Benjamin Dupont)
Expand Down
44 changes: 35 additions & 9 deletions fbw-a380x/src/systems/instruments/src/EWD/elements/ThrustGauge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
ThrottlePositionDonutComponent,
ThrustTransientComponent,
} from 'instruments/src/MsfsAvionicsCommon/gauges';
import { Arinc429ConsumerSubject } from '@flybywiresim/fbw-sdk';
import { Arinc429ConsumerSubject, Arinc429LocalVarConsumerSubject } from '@flybywiresim/fbw-sdk';

interface ThrustGaugeProps {
bus: EventBus;
Expand All @@ -31,6 +31,8 @@ interface ThrustGaugeProps {
n1Degraded: Subscribable<boolean>;
}

const METOTS_N1_LIMIT = 76.5;

export class ThrustGauge extends DisplayComponent<ThrustGaugeProps> {
private readonly sub = this.props.bus.getSubscriber<Arinc429Values & EwdSimvars>();

Expand Down Expand Up @@ -123,16 +125,23 @@ export class ThrustGauge extends DisplayComponent<ThrustGaugeProps> {

private readonly thrustPercent = MappedSubject.create(
([n1, thrustLimitIdle, thrustLimitMax, thrIdleOffset]) =>
Math.min(
1,
Math.max(0, (n1 - thrustLimitIdle) / (thrustLimitMax - thrustLimitIdle)) * (1 - thrIdleOffset) + thrIdleOffset,
) * 100,
this.thrustPercentFromN1(n1, thrustLimitIdle, thrustLimitMax, thrIdleOffset),
this.n1,
this.thrustLimitIdle,
this.thrustLimitMax,
this.thrIdleOffset,
);

/** Expects values in percent 0-100, returns 0-100 */
private thrustPercentFromN1(n1: number, thrustLimitIdle: number, thrustLimitMax: number, thrIdleOffset: number) {
return (
Math.min(
1,
Math.max(0, (n1 - thrustLimitIdle) / (thrustLimitMax - thrustLimitIdle)) * (1 - thrIdleOffset) + thrIdleOffset,
) * 100
);
}

private readonly thrustPercentReverse = MappedSubject.create(
([n1, thrustLimitIdle, thrustLimitRev]) =>
Math.min(1, Math.max(0, (n1 - thrustLimitIdle) / (-thrustLimitRev - thrustLimitIdle))) * 100,
Expand Down Expand Up @@ -160,6 +169,23 @@ export class ThrustGauge extends DisplayComponent<ThrustGaugeProps> {

private readonly availRevText = this.availVisible.map((it) => (it ? 'AVAIL' : 'REV'));

private readonly cas1 = Arinc429LocalVarConsumerSubject.create(this.sub.on('cas_1'));

// FIXME replace with actual available thrust when ACUTE is implemented
private readonly maxThrustAvail = MappedSubject.create(
([cas, thrustLimitIdle, thrustLimitMax, thrIdleOffset]) =>
cas.isNoComputedData() || cas.valueOr(100) < 35
? Math.max(
thrIdleOffset * 100,
this.thrustPercentFromN1(METOTS_N1_LIMIT, thrustLimitIdle, thrustLimitMax, thrIdleOffset),
) / 10
: 10,
this.cas1,
this.thrustLimitIdle,
this.thrustLimitMax,
this.thrIdleOffset,
);

private radius = 64;
private startAngle = 230;
private endAngle = 90;
Expand Down Expand Up @@ -223,8 +249,8 @@ export class ThrustGauge extends DisplayComponent<ThrustGaugeProps> {
<GaugeThrustComponent
x={this.props.x}
y={this.props.y}
valueIdle={0.3}
valueMax={10}
valueIdle={Subject.create(0.42)}
valueMax={this.maxThrustAvail}
radius={this.radius}
startAngle={this.startAngle}
endAngle={this.endAngle}
Expand Down Expand Up @@ -394,8 +420,8 @@ export class ThrustGauge extends DisplayComponent<ThrustGaugeProps> {
<GaugeThrustComponent
x={this.props.x}
y={this.props.y}
valueIdle={0.04}
valueMax={2.6}
valueIdle={Subject.create(0.04)}
flogross89 marked this conversation as resolved.
Show resolved Hide resolved
valueMax={Subject.create(2.6)}
radius={this.revRadius}
startAngle={this.revStartAngle}
endAngle={this.revEndAngle}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export interface BaseEwdSimvars {
abnormal_debug_line: number;
nose_gear_compressed: boolean;
engine_fire_pb: boolean;
cas: number;
}

type IndexedTopics =
Expand All @@ -61,7 +62,8 @@ type IndexedTopics =
| 'memo_left'
| 'memo_right'
| 'nose_gear_compressed'
| 'engine_fire_pb';
| 'engine_fire_pb'
| 'cas';
type EwdIndexedEvents = {
[P in keyof Pick<BaseEwdSimvars, IndexedTopics> as IndexedEventType<P>]: BaseEwdSimvars[P];
};
Expand Down Expand Up @@ -123,6 +125,7 @@ export class EwdSimvarPublisher extends SimVarPublisher<EwdSimvars> {
{ name: 'L:A32NX_LGCIU_#index#_NOSE_GEAR_COMPRESSED', type: SimVarValueType.Bool, indexed: true },
],
['engine_fire_pb', { name: 'L:A32NX_FIRE_BUTTON_ENG#index#', type: SimVarValueType.Bool, indexed: true }],
['cas', { name: 'L:A32NX_ADIRS_ADR_#index#_COMPUTED_AIRSPEED', type: SimVarValueType.Number, indexed: true }],
];

super(new Map(simvars), bus, pacer);
Expand Down
78 changes: 37 additions & 41 deletions fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/gauges.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DisplayComponent, FSComponent, Subscribable, Subject, VNode } from '@microsoft/msfs-sdk';
import { DisplayComponent, FSComponent, Subscribable, Subject, VNode, MappedSubject } from '@microsoft/msfs-sdk';

import './gauges.scss';

Expand Down Expand Up @@ -451,61 +451,57 @@ interface GaugeThrustComponentProps {
endAngle: number;
class: string;
visible: Subscribable<boolean>;
valueIdle: number;
valueMax: number;
valueIdle: Subscribable<number>;
valueMax: Subscribable<number>;
reverse?: boolean;
}
export class GaugeThrustComponent extends DisplayComponent<GaugeThrustComponentProps> {
private thrustPath = Subject.create('');

constructor(props: GaugeThrustComponentProps) {
super(props);

this.update();
}

update(): void {
const valueIdleDir = valueRadianAngleConverter(
this.props.valueIdle,
this.props.min,
this.props.max,
this.props.endAngle,
this.props.startAngle,
);
const valueIdleEnd = {
x: this.props.x + valueIdleDir.x * this.props.radius,
y: this.props.y + valueIdleDir.y * this.props.radius,
};
const valueMaxDir = valueRadianAngleConverter(
this.props.valueMax,
this.props.min,
this.props.max,
this.props.endAngle,
this.props.startAngle,
);
const valueMaxEnd = {
x: this.props.x + valueMaxDir.x * this.props.radius,
y: this.props.y + valueMaxDir.y * this.props.radius,
};
private readonly thrustPath = MappedSubject.create(
([valueIdle, valueMax]) => {
const valueIdleDir = valueRadianAngleConverter(
valueIdle,
this.props.min,
this.props.max,
this.props.endAngle,
this.props.startAngle,
);
const valueIdleEnd = {
x: this.props.x + valueIdleDir.x * this.props.radius,
y: this.props.y + valueIdleDir.y * this.props.radius,
};
const valueMaxDir = valueRadianAngleConverter(
valueMax,
this.props.min,
this.props.max,
this.props.endAngle,
this.props.startAngle,
);
const valueMaxEnd = {
x: this.props.x + valueMaxDir.x * this.props.radius,
y: this.props.y + valueMaxDir.y * this.props.radius,
};

this.thrustPath.set(
[
return [
`M ${this.props.x},${this.props.y} L ${valueIdleEnd.x},${valueIdleEnd.y}`,
`A ${this.props.radius} ${this.props.radius} 0 ${this.props.reverse ? '0' : '1'} 1 ${valueMaxEnd.x} ${valueMaxEnd.y}`,
`M ${valueMaxEnd.x} ${valueMaxEnd.y} L ${this.props.x},${this.props.y}`,
].join(' '),
);
}
].join(' ');
},
this.props.valueIdle,
this.props.valueMax,
);

render(): VNode {
return (
<>
<g class="GaugeComponent">
<g class={this.props.visible.map((it) => (it ? 'Show' : 'Hide'))}>
<path d={this.thrustPath} class={this.props.class} />
</g>
<g class="GaugeComponent">
<g class={this.props.visible.map((it) => (it ? 'Show' : 'Hide'))}>
<path d={this.thrustPath} class={this.props.class} />
</g>
</>
</g>
);
}
}
Expand Down
2 changes: 1 addition & 1 deletion fbw-a380x/src/wasm/fbw_a380/src/FlyByWireInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2650,8 +2650,8 @@ bool FlyByWireInterface::updateAutothrust(double sampleTime) {
idAutothrustThrustLimitREV->get(),
idAutothrustThrustLimitIDLE->get(),
idAutothrustThrustLimitCLB->get(),
idAutothrustThrustLimitFLX->get(),
idAutothrustThrustLimitMCT->get(),
idAutothrustThrustLimitFLX->get(),
idAutothrustThrustLimitTOGA->get(),
idFmgcFlexTemperature->get(),
autopilotStateMachineOutput.autothrust_mode,
Expand Down
Loading