Skip to content

Instantly share code, notes, and snippets.

@sritchie
Last active June 25, 2026 20:07
Show Gist options
  • Select an option

  • Save sritchie/a17910192def194b127286bbf544c14c to your computer and use it in GitHub Desktop.

Select an option

Save sritchie/a17910192def194b127286bbf544c14c to your computer and use it in GitHub Desktop.
OnSpeed Live-Calibration Violin — a guide to the self-serve AOA calibration visualization

OnSpeed Live-Calibration Violin — a guide

A visualization for self-serve AOA calibration. The pilot flies a few decel-to-stall runs at each flap; this shows, live, how complete the calibration is and what to do next. This guide explains every element.


What problem this solves

OnSpeed maps a pressure-based lift coefficient (CoeffP) to angle of attack (AOA), per flap. Today that calibration is done with a guided wizard and careful flying. Self-serve calibration lets a pilot build the same calibration by just flying normally plus a few stalls — no perfect technique required. The hard part is telling the pilot, in flight, whether they've done enough and what's still missing. That's this display.

Each flap (0 / 16 / 33 here) gets its own panel. In the real product the pilot sees the flap they're currently flying; the 3-up is for review.

The axis: α₀ (bottom) → α-stall (top)

The vertical axis is raw AOA in degrees. It's bounded by the two ends of the percent-lift scale, both of which the system fits live:

  • α₀ (bottom) — the zero-lift body angle (percentLift = (AOA−α₀)/(α_stall−α₀)). It's typically negative (≈ −2° clean, more negative with flaps) because the wing is mounted at positive incidence. α₀ comes from a weighted fit of body-angle vs 1/airspeed² — and it's gated on the decel: until you do a stall, the airspeed range is too narrow to pin it, so the panel says "α₀ not ready (need a decel)". The moment you stall, the speed range from cruise→stall pins α₀ within ~0.5° (validated against an independent boom-AOA reference to <1°). No prior is needed — the decel that gives you the stall also gives you α₀.
  • α-stall (top, dashed line) — the measured stall body angle = the fitted curve evaluated at the running peak CoeffP (CpMax). It ratchets up: you never have to exceed it, but if you stall deeper, it bumps up. It's the curve's value at CpMax, not a single noisy reading, so EKF AOA noise washes out (stable to ~0.4° even though individual stall-break AOA readings scatter ~1.7°).
  • For flaps-down (16/33) the bottom is floored at Vfe − 1° (you enter Vfe before calibrating; faster than Vfe is out of bounds, so we don't show it).

The violin width: how much the curve still needs data here

Width = how much work this AOA still needs. Fat/red = needs data; thin/green = settled. As you fly decels, the fat zone shaves down — that's the satisfying part. Two different things drive the width in two regions (this is the key idea):

  • Approach / slow band (the middle, below the stall): width = data coverage. If you race to the stall, you blow through this band quickly and leave it sparse → it stays fat → the message is "do a slower deceleration so you map the approach you flew through too fast."
  • At the stall (the top): width = CpMax consistency. Each stall attempt has a peak CoeffP. If your stalls agree in CoeffP (repeatable), the top is tight — the stall is known. If they scatter, the top stays fat"stall again, your attempts don't agree yet." This is measured in CoeffP, which is repeatable, NOT in AOA, which is noisy at the break.
  • Cruise (the bottom): floods with data instantly, always thin — you're never calibrating there.

So the shape itself tells the pilot what to fix: fat middle → slow down through the approach; fat top → stall again; solid green throughout → done.

The markers

  • NOW (black bar) — your current AOA, on the flap you're flying. You pull NOW up toward the stall.
  • The 4 cue setpoints — L/Dmax (blue), OnSpeed-fast (purple), OnSpeed-slow (pink), StallWarn (red), at their live fitted AOA. They move as the calibration refines and lock in when the flap is captured. This lets you fly the calibration before saving it (and, next step, hear it — see below).
  • α-stall (dashed, top) and α₀ (green dashed, bottom) — the scale ends, as above.
  • FLAP # (boxed) and ✓ CAPTURED — capture means the calibration at that flap is trustworthy: CpMax has plateaued (you found the stall and deeper attempts stop going deeper), it's credibly deep, and the StallWarn estimate has stopped drifting.

What "done" looks like

A flap is captured when its stall is found and stable. On the display: the violin is solid green from α₀ up to α-stall, the cue marks have stopped moving and gone solid, and the panel shows ✓ CAPTURED. Typically ~2–3 clean decels per flap get you there. Once captured, it stays captured — it does not flicker back as you fly away to set up the next decel.

"Captured" un-latches only when a new stall MATERIALLY disagrees — the confirmation stall

Capture latches: a routine deeper stall that confirms the same answer keeps you captured. But if a new stall moves the StallWarn estimate materially (more than ~0.8°), the panel drops back to capturing. This is deliberate, and it's a confirmation-stall mechanism:

One stall that changes the answer is, by itself, ambiguous — it could be the truth, or it could be one bad pass (fast/gusty/uncoordinated). The system can't tell from a single sample. So a material move breaks the agreement and asks you to fly one more to break the tie. If the next stall confirms the new value, it re-captures there. If it comes back to the old value, the outlier averages out and the original capture stands.

So it does not re-capture immediately at the moved value — the calibration's strength is in stalls agreeing with each other, not in any single most-recent stall. A lone dissenting stall is corroborated before it's trusted. (Going deeper than before is more authoritative than a shallower disagreement, so a future refinement may re-confirm a deeper stall faster; the safe default is "any material move wants a confirmation stall.")

Reading the example (RV-10, one flight)

  • Flap 0 & 16: captured, tight green to the top — consistent stalls, well-mapped approach.
  • Flap 33: captured but with a wider/orange top — its stalls were less consistent in CoeffP (one outlier) than flaps 0/16. That's the display honestly flagging "these stalls agreed less well" — exactly the signal it's designed to give.

(This example is RV-10 EKF data — self-consistency, not validated against a boom truth reference on this airframe. The α₀ method itself was cross-checked against boom truth on a second airframe to <1°.)

Next step: fly-by-ear ("live calibrating mode")

Because the cue setpoints are live, the system can drive the actual OnSpeed audio tones from the unsaved, in-progress calibration — so the pilot flies the calibration by ear, hears the tone boundaries tighten as the curve refines, and saves when it sounds right. This is opt-in and calibration-mode-only (normal flight drives tones from the saved config). The violin shows where to fly; the tones confirm by feel.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment