Skip to content

Commit d34c517

Browse files
committed
refactor: convert graph_spectrum_calc to TypeScript (#924)
Convert the 929-line spectrum/PSD DSP singleton, no logic change (rename). - Typed the singleton via a GraphSpectrumCalcType interface + `as unknown as` cast, so the 25 methods get contextual `this`/param typing without per-method annotation. - Named result types: FlightSamples(VsX/PidError), PsdResult, FftResult, VsXResult; FFTComplex is already a class so `new FFTComplex(...)` is clean. - flightlog.ts: getMainFieldIndexes() now returns Record<string, number> (was unknown) — used by the VS-indexes lookup. - Preserved JS coercion / dynamic spots via type-only casts (gyroRate string*number, getMinTime/getMaxTime number|false, field-index lookups number|undefined, dynamic errorBySetpoint arrays). type-check, lint, build, and the parser golden test all pass; diff is type-only (verified). Refs #924
1 parent 9cfcb0b commit d34c517

2 files changed

Lines changed: 120 additions & 12 deletions

File tree

src/flightlog.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export interface FlightLog {
4848
getLogCount(): number;
4949
getActivitySummary(): unknown;
5050
getMainFieldIndexByName(name: string): number | undefined;
51-
getMainFieldIndexes(_name?: string): unknown;
51+
getMainFieldIndexes(_name?: string): Record<string, number>;
5252
getFrameAtTime(startTime: number): FrameArray | false;
5353
getSmoothedFrameAtTime(startTime: number): FrameArray | false;
5454
getCurrentFrameAtTime(startTime: number): unknown;
Lines changed: 119 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,110 @@
11
import { FFTComplex } from "./fft_complex.js";
22
import { FlightLogFieldPresenter } from "./flightlog_fields_presenter";
33
import { useSettingsStore } from "./stores/settings.js";
4+
import type { FlightLog } from "./flightlog";
5+
import type { SysConfig, FlightLogChunk } from "./flightlog_types";
6+
7+
interface FlightSamples {
8+
samples: Float64Array;
9+
count: number;
10+
}
11+
interface FlightSamplesVsX {
12+
samples: Float64Array;
13+
vsValues: Float64Array[];
14+
count: number;
15+
minValue: number;
16+
maxValue: number;
17+
}
18+
interface FlightSamplesPidError {
19+
piderror: Int16Array;
20+
setpoint: Int16Array;
21+
maxSetpoint: number;
22+
count: number;
23+
}
24+
interface PsdResult {
25+
psdOutput: Float64Array;
26+
min: number;
27+
max: number;
28+
maxNoiseFrequency: number;
29+
}
30+
interface FftResult {
31+
fieldIndex: number;
32+
fieldName: string | null;
33+
fftLength: number;
34+
fftOutput: Float64Array;
35+
maxNoiseFrequency: number;
36+
blackBoxRate: number;
37+
}
38+
interface VsXResult {
39+
vsRange: { min: number; max: number };
40+
}
41+
interface Curve {
42+
lookupRaw(value: number): number;
43+
}
44+
45+
// Singleton with methods added below; `this` and params are typed via this
46+
// interface (the object is cast to it, since methods are assigned afterwards).
47+
interface GraphSpectrumCalcType {
48+
_analyserTimeRange: { in: number; out: number };
49+
_blackBoxRate: number;
50+
_dataBuffer: { fieldIndex: number; curve: Curve; fieldName: string };
51+
_flightLog: FlightLog;
52+
_sysConfig: SysConfig;
53+
_motorPoles: number;
54+
_pointsPerSegmentPSD: number;
55+
_BetaflightRate: number;
56+
_actualeRate: number;
57+
initialize(
58+
flightLog: FlightLog,
59+
sysConfig: SysConfig,
60+
): { actualRate: number; betaflightRate: number } | undefined;
61+
setInTime(time: number): number;
62+
setOutTime(time: number): number;
63+
setDataBuffer(fieldIndex: number, curve: Curve, fieldName: string): undefined;
64+
dataLoadFrequency(): unknown;
65+
setPointsPerSegmentPSD(pointsCount: number): void;
66+
dataLoadPSD(_analyserZoomY?: unknown): unknown;
67+
dataLoadFrequencyVsThrottle(): VsXResult;
68+
dataLoadPowerSpectralDensityVsThrottle(): VsXResult;
69+
dataLoadFrequencyVsRpm(): VsXResult;
70+
dataLoadPowerSpectralDensityVsRpm(): VsXResult;
71+
dataLoadPidErrorVsSetpoint(): unknown;
72+
getNearPower2Value(size: number): number;
73+
_dataLoadFrequencyVsX(
74+
vsFieldNames: string[],
75+
minValue?: number,
76+
maxValue?: number,
77+
): VsXResult;
78+
_dataLoadPowerSpectralDensityVsX(
79+
vsFieldNames: string[],
80+
minValue?: number,
81+
maxValue?: number,
82+
): VsXResult;
83+
_getFlightChunks(): FlightLogChunk[];
84+
_getFlightSamplesFreq(scaled?: boolean): FlightSamples;
85+
_getVsIndexes(vsFieldNames: string[]): number[];
86+
_getFlightSamplesFreqVsX(
87+
vsFieldNames: string[],
88+
minValue?: number,
89+
maxValue?: number,
90+
scaled?: boolean,
91+
): FlightSamplesVsX;
92+
_getFlightSamplesPidErrorVsSetpoint(axisIndex: number): FlightSamplesPidError;
93+
_hanningWindow(samples: Float64Array | number[], size: number): void;
94+
_fft(samples: Float64Array | number[], type?: string): Float64Array;
95+
_normalizeFft(fftOutput: Float64Array): FftResult;
96+
_psd(
97+
samples: Float64Array | number[],
98+
pointsPerSegment: number,
99+
overlapCount: number,
100+
scaling?: string,
101+
): PsdResult;
102+
_fft_segmented(
103+
samples: Float64Array | number[],
104+
pointsPerSegment: number,
105+
overlapCount: number,
106+
): Float64Array[];
107+
}
4108

5109
const FIELD_THROTTLE_NAME = ["rcCommands[3]"],
6110
FIELD_RPM_NAMES = [
@@ -37,7 +141,7 @@ export const GraphSpectrumCalc = {
37141
_sysConfig: null,
38142
_motorPoles: null,
39143
_pointsPerSegmentPSD: 64,
40-
};
144+
} as unknown as GraphSpectrumCalcType;
41145

42146
GraphSpectrumCalc.initialize = function (flightLog, sysConfig) {
43147
this._flightLog = flightLog;
@@ -46,7 +150,7 @@ GraphSpectrumCalc.initialize = function (flightLog, sysConfig) {
46150
const gyroRate = (1000000 / this._sysConfig["looptime"]).toFixed(0);
47151
this._motorPoles = flightLog.getSysConfig()["motor_poles"];
48152
this._blackBoxRate =
49-
(gyroRate * this._sysConfig["frameIntervalPNum"]) /
153+
((gyroRate as unknown as number) * this._sysConfig["frameIntervalPNum"]) /
50154
this._sysConfig["frameIntervalPDenom"];
51155
if (this._sysConfig.pid_process_denom != null) {
52156
this._blackBoxRate = this._blackBoxRate / this._sysConfig.pid_process_denom;
@@ -432,11 +536,13 @@ GraphSpectrumCalc.dataLoadPidErrorVsSetpoint = function () {
432536
axisIndex = 2;
433537
}
434538

435-
const flightSamples = this._getFlightSamplesPidErrorVsSetpoint(axisIndex);
539+
const flightSamples = this._getFlightSamplesPidErrorVsSetpoint(axisIndex as number);
436540

437541
// Add the total error by absolute position
438-
const errorBySetpoint = Array.from({ length: flightSamples.maxSetpoint + 1 });
439-
const numberOfSamplesBySetpoint = Array.from({
542+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
543+
const errorBySetpoint: any[] = Array.from({ length: flightSamples.maxSetpoint + 1 });
544+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
545+
const numberOfSamplesBySetpoint: any[] = Array.from({
440546
length: flightSamples.maxSetpoint + 1,
441547
});
442548

@@ -480,9 +586,11 @@ GraphSpectrumCalc.dataLoadPidErrorVsSetpoint = function () {
480586
};
481587

482588
GraphSpectrumCalc._getFlightChunks = function () {
483-
const logStart = this._analyserTimeRange.in || this._flightLog.getMinTime();
589+
const logStart =
590+
this._analyserTimeRange.in || (this._flightLog.getMinTime() as number);
484591

485-
let logEnd = this._analyserTimeRange.out || this._flightLog.getMaxTime();
592+
let logEnd =
593+
this._analyserTimeRange.out || (this._flightLog.getMaxTime() as number);
486594

487595
// Limit size
488596
logEnd =
@@ -541,10 +649,10 @@ GraphSpectrumCalc._getFlightSamplesFreq = function (scaled = true) {
541649
};
542650

543651
GraphSpectrumCalc._getVsIndexes = function (vsFieldNames) {
544-
const fieldIndexes = [];
652+
const fieldIndexes: number[] = [];
545653
for (const fieldName of vsFieldNames) {
546654
if (Object.hasOwn(this._flightLog.getMainFieldIndexes(), fieldName)) {
547-
fieldIndexes.push(this._flightLog.getMainFieldIndexByName(fieldName));
655+
fieldIndexes.push(this._flightLog.getMainFieldIndexByName(fieldName)!);
548656
}
549657
}
550658
return fieldIndexes;
@@ -678,10 +786,10 @@ GraphSpectrumCalc._getFlightSamplesPidErrorVsSetpoint = function (axisIndex) {
678786
// Get the PID Error field
679787
const FIELD_PIDERROR_INDEX = this._flightLog.getMainFieldIndexByName(
680788
`axisError[${axisIndex}]`,
681-
);
789+
) as number;
682790
const FIELD_SETPOINT_INDEX = this._flightLog.getMainFieldIndexByName(
683791
`setpoint[${axisIndex}]`,
684-
);
792+
) as number;
685793

686794
const piderror = new Int16Array(
687795
(MAX_ANALYSER_LENGTH / (1000 * 1000)) * this._blackBoxRate,

0 commit comments

Comments
 (0)