@h2loop/uav 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,72 @@
1
+ # FFT → Harmonic-Notch Recommender
2
+
3
+ The tuning recommender (`src/harness/tuning.ts`, `recommendNotch`) is the UAV pack's
4
+ signature feature. It closes the loop that pilots normally run by hand in Mission
5
+ Planner: pull a log, eyeball the FFT, guess a notch frequency, re-fly, repeat. Here it
6
+ is one deterministic pass over the log.
7
+
8
+ ## What it does
9
+
10
+ 1. **Reads the gyro signal.** Prefers the `IMU` table's `GyrX/GyrY/GyrZ` columns
11
+ (rad/s) and uses the highest-energy axis. Falls back to `VIBE` (`VibeX/Y/Z`) when
12
+ no IMU gyro is present.
13
+ 2. **Finds the sample rate.** Uses `IMU.GHz` (the gyro sample rate, in Hz) when
14
+ present, otherwise estimates it from the median of `TimeUS` deltas (µs → Hz).
15
+ 3. **Runs an FFT.** A pure-TypeScript radix-2 Cooley–Tukey FFT (no npm deps). The
16
+ signal is de-meaned, Hann-windowed, and zero-padded to the next power of two; the
17
+ one-sided magnitude spectrum is returned.
18
+ 4. **Picks the dominant peak** inside the search band (default **20–200 Hz**, the
19
+ usual multicopter motor/prop noise range) and reports the top ~3 peaks.
20
+ 5. **Emits ArduPilot harmonic-notch params**, each carrying a valid `range` and a
21
+ `source` of `{kind: "rule-of-thumb", ref: "ArduPilot harmonic notch tuning"}`.
22
+
23
+ ## The message it reads
24
+
25
+ A `DecodedLog` (see `src/types.ts`). It only touches three tables:
26
+
27
+ - `IMU` — `GyrX/GyrY/GyrZ` (signal), `GHz` (rate), `TimeUS` (rate fallback).
28
+ - `VIBE` — `VibeX/Y/Z` fallback signal.
29
+ - `CTUN` — `ThH` (hover throttle) for the throttle reference.
30
+
31
+ Nothing else is required. If none of these carry a usable signal it returns a null
32
+ recommendation — it **never throws**.
33
+
34
+ ## How to read the recommendation
35
+
36
+ `recommendNotch(log)` returns a `NotchRecommendation`:
37
+
38
+ - `dominant_peak_hz` — the centre frequency of the strongest in-band peak, or `null`.
39
+ - `peaks` — up to 3 `SpectralPeak`s (`freq_hz`, `magnitude`, `axis`), strongest first.
40
+ - `params` — the suggested settings:
41
+ - `INS_HNTCH_ENABLE = 1` — turn the harmonic notch on.
42
+ - `INS_HNTCH_MODE` — the **tracking mode**, chosen from the telemetry in the log:
43
+ **3 = ESC telemetry** (if `ESC.RPM` present), **2 = RPM sensor** (if an `RPM` message is
44
+ present), else **1 = throttle-based** (fallback). ESC/RPM modes track the measured motor
45
+ frequency directly, so they hold the notch on the peak across the whole throttle range —
46
+ preferred; throttle mode only approximates (freq ∝ √throttle).
47
+ - `INS_HNTCH_FREQ = round(peak)` — notch centre, clamped to [10, 495].
48
+ - `INS_HNTCH_BW = round(peak / 2)` — bandwidth ≈ half the centre, a standard
49
+ starting width, clamped to [5, 250].
50
+ - `INS_HNTCH_REF` — `avg(CTUN.ThH)` (hover throttle) in throttle mode; `1.0` in RPM/ESC
51
+ modes (the notch tracks measured RPM, so FREQ is just the low-RPM floor).
52
+ - `INS_HNTCH_HMNCS = 3` — track the 1st + 2nd harmonics (bitmask).
53
+ - **`INS_HNTC2_*`** — a **second** harmonic notch, emitted ONLY when a distinct, strong second
54
+ peak exists (well separated from the dominant and ≥ half its magnitude) — e.g. a separate
55
+ structural resonance or motor group. Same fields (ENABLE/MODE/FREQ/BW/REF/HMNCS) at that peak.
56
+ - `rationale` — one paragraph: the peak found, the sample rate and its source, and why
57
+ the values were chosen.
58
+
59
+ A `null`/empty result means "insufficient gyro/vibe data" — surface that, do not
60
+ fabricate params.
61
+
62
+ ## Safety note
63
+
64
+ These params are **starting values**, not a verified tune. They must be reviewed by a
65
+ human (or the gating subagent) before they touch a vehicle. Critically, this module
66
+ only *recommends* — it has no path to a flight controller.
67
+
68
+ **Pushing params is a separate, gated action.** `/uav-tune` (or the `uav_tune` tool) only
69
+ recommends — confirm the recommendation against the airframe and check the ranges, then
70
+ write parameters over the gated MAVLink param link (`--allow-param-write`). After applying,
71
+ re-fly and re-run `recommendNotch` on the new
72
+ log to confirm the peak dropped — the same FFT→notch loop, closed automatically.