The setup

Jam the GPS, and the drone must guess

Small guessing errors add up every minute.

  1. Always on
    Motion sensorsfeel every push and turn
  2. Guess
    Add up the movementgives a position, but it drifts
  3. Normally
    GPS fixes the driftseveral times a second
  4. Jammed
    No GPS to fix itthe drift keeps growing

Every number in this deck is from ArduPilot's simulator (Copter-4.6.3 SITL), not real flights. Tags: measured (sim) estimate not measured. Press N for speaker notes.

System 1 of 6 · reference

GPS working

The normal case. Nothing is jammed.

  1. In
    GPS + motion sensorsplus height and compass
  2. Step
    ArduPilot's filter blends themits built-in EKF3
  3. Step
    GPS corrects the driftso errors never build up
  4. Out
    Positionthe reference track
0.06 m off at the endmeasured (sim) median, 24 flights

Jam events removed: tests/harness/runner.py:108-109 · miss: Pathfinder-wt-fasttests/docs/night/2026-10-13-fast-run-2.md:20 · run names: sim/tools/naming.py:14-46

System 2 of 6 · worst case

Motion sensors only

Called dead reckoning. Nothing ever corrects it.

  1. In
    Motion sensorsaccelerometer + gyro
  2. Start
    True speed at jam timea generous head start
  3. Step
    Add up push → speedevery sensor reading
  4. Step
    Add up speed → positionerrors grow with time squared
  5. Out
    Positionnever corrected
9.2 km off at the endmeasured (sim) median, 24 flights

training/src/pathfinder_eval/baselines.py:70-85, swapped in at tests/harness/runner.py:236-241 · miss: fast-run-2.md:21

System 3 of 6 · ArduPilot alone

ArduPilot, emergency rules off

It keeps flying, and its position slowly slides away.

  1. In
    Motion, height, compassGPS until jammed
  2. Jam
    GPS fix is lostno outside correction
  3. Step
    Filter guesses from motionits built-in EKF3
  4. Step
    Emergency rules switched offso we can measure the slide
  5. Out
    Positiondrifting
9.2 km off at the endmeasured (sim) median, 24 flights

FS_EKF_THRESH, FS_THR_ENABLE, FS_GCS_ENABLE, FS_DR_ENABLE = 0: training/src/pathfinder_sim/runner.py:44-45, :246-255 · sim/tools/lab.py:41 · miss: fast-run-2.md:22

System 4 of 6 · what happens today

Stock ArduPilot, jammed

As shipped, it gives up and lands.

  1. In
    Motion, height, compassGPS until jammed
  2. Jam
    GPS fix is lostuncertainty starts growing
  3. Step
    Uncertainty passes its limit"EKF failsafe"
  4. Out
    Lands where it ismission lost
1.0 km off, on the groundmeasured (sim) median, 24 flights

Failsafes stock: sim/tools/lab.py:39 · LAND before 2 min: fast-run-2.md:34 · miss: fast-run-2.md:23

System 5 of 6 · Pathfinder

Pathfinder (physics only)

Pathfinder (physics only) · jam detection, drag model, learned wind
\hat p=\textstyle\int v\,dt,\quad v=C(q)\,u+w,\quad \bar f_{xy}=-k\,u-k_q\,u\lvert u\rvert,\quad \text{GPS used only if } d<6
  • \hat p where Pathfinder thinks the drone is
  • v speed and direction over the ground
  • u speed through the air, along the drone's own axes
  • w the wind, learned while GPS was good
  • C(q) the drone's tilt and heading (turns body axes into north-east-down)
  • \bar f_{xy} forward and sideways push the accelerometer feels; thrust only pushes up the body, so this is air drag
  • k,\;k_q drag coefficients fitted to the quad (linear and squared)
  • d how many standard deviations a GPS fix sits from the estimate

Physics of air drag replaces the missing GPS.

  1. In
    Motion, height, compass, GPSfrom the autopilot
  2. Step 1
    GPS checkjammed or fake fix is rejected
  3. Step 2
    Filter predictslearned sensor errors and wind
  4. Step 3
    Drag physicsair push → speed, plus wind
  5. Out
    Position to ArduPilotplus a 95% safety circle
165 m off at the endmeasured (sim) median, 24 flights

GPS check crates/pathfinder-core/src/integrity.rs:70 · filter states eskf.rs:6-11 · drag drag.rs:6-7, navigator.rs:113-119 · switch crates/pathfinderd/src/daemon.rs:303-307, sim/params/pathfinder-ekf3.parm:5-14 · no model loaded: tests/harness/runner.py:84 · miss fast-run-2.md:24

System 6 of 6 · Pathfinder

Pathfinder (physics + speed AI)

Pathfinder (physics + speed AI) · jam detection, drag model, learned wind, plus a neural-network speed estimate
\text{physics only}\;+\;z_{\text{AI}}=v-w+\nu,\quad \nu\sim\mathcal N(0,R_{\text{AI}}),\quad R_{\text{AI}}=22.9\times294\,I\;(\text{m/s})^2
  • z_{\text{AI}} the network's speed-through-the-air estimate
  • \nu its error, assumed random
  • R_{\text{AI}} how noisy the filter assumes it is: 4.8 m/s, counted as one reading per 29.4 s

Adds a learned speedometer, trusted only a little.

  1. In
    Same sensors + motor speedfrom the autopilot
  2. Steps 1-3
    GPS check, predict, dragas in physics only
  3. Step 4
    ML speedometerlast 1 s of sensors → speed
  4. Step 5
    Mix in, lightly≈ one reading per 29 s counts
  5. Out
    Position to ArduPilotplus a 95% safety circle
156 m off at the endmeasured (sim) median, 24 flights

Flown in proof Q3 run 3, 24 flights, and not merged: Pathfinder (physics + drift-correcting AI) was 24.59 m off at 2 min vs 3.99 m for physics only measured (sim); Pathfinder (physics + speed AI + drift-correcting AI) 24.14 m measured (sim). In offline replay it had won, 47.5 vs 78.4 m estimate.

Model loaded: tests/harness/runner.py:84-86 · inputs training/src/pathfinder_ml/spec.py:13-27 · network model.py:36-62 · retune crates/pathfinder-core/src/adapter.rs:1-6 · weight learned.rs:290-327, Pathfinder/docs/night/2026-10-13-ml-alternatives.md:22-28 · miss fast-run-2.md:25

The math · physics only

Physics only: the math

Pathfinder (physics only) · jam detection, drag model, learned wind
\hat p=\textstyle\int v\,dt,\quad v=C(q)\,u+w,\quad \bar f_{xy}=-k\,u-k_q\,u\lvert u\rvert,\quad \text{GPS used only if } d<6
1 · Predict200/s, every IMU sample
a=C(q)\,(\tilde f-b_a)+g\,e_z
p\leftarrow p+v\,\Delta t+\tfrac12 a\,\Delta t^2,\quad v\leftarrow v+a\,\Delta t
P\leftarrow F P F^\top+Q
Accelerometer f̃ minus its learned bias ba, turned to north-east-down, plus gravity g, moves speed and position. P is the uncertainty of all 17 error states.
eskf.rs:5-11 (17 states), :136-167
2 · Drag10/s, 0.1 s average
u=C(q)^\top(v-w)
\bar f_i=-k_i\,u_i-k_{q,i}\,u_i\lvert u_i\rvert+b_{a,i},\quad i\in\{x,y\}
Air speed u in body axes. kx 0.334/s, kq,x 0.0253/m, ky 0.240/s, kq,y 0.0250/m; noise σ 0.5 m/s².
drag.rs:6-82 · navigator.rs:111-119 · config.rs:15, :21, :56
3 · Windrandom walk, 2 states
w_{k+1}=w_k+\eta_k
\eta_k\sim\mathcal N(0,\;q_w^2\,\Delta t\,I_2),\quad q_w=0.05
GPS sees ground speed v; drag sees air speed v − w. The gap is the wind, learned while GPS is good, then held.
eskf.rs:20-38, :159-164 · navigator.rs:95-104
4 · Every measurementdrag, GPS, baro, compass, AI
S=HPH^\top+R,\quad K=PH^\top S^{-1}
x\leftarrow x\oplus K\,y,\quad P\leftarrow(I-KH)P(I-KH)^\top+KRK^\top
y is measured minus expected, H how it depends on the states, R its noise. Low R means more trust.
eskf.rs:183-198 (Joseph form)
5 · GPS jam gate5/s
d=\sqrt{\Delta^\top(P_{ne}+\sigma_h^2 I)^{-1}\Delta}
\text{reject if } d\ge 6 \;\lor\; \dot d\ge 4/\text{s} \;\lor\; m_{pv}\ge 0.7\,\text{m/s}
Δ: fix minus estimate, north-east. σh: the receiver's own accuracy. mpv: position and velocity disagree. d ≥ 3 is suspect; 2 s later rejected; 10 s clean to re-trust.
measurements.rs:68-75 · integrity.rs:23-38, :166-181, :197-217
6 · Safety circle20/s, sent with each position
r_{95}=\sqrt{5.991\;\lambda_{\max}(P_{ne})}
λmax: the long axis of the north-east uncertainty. 5.991 is the 95% chi-square value for 2 axes.
navigator.rs:11-19

All in crates/pathfinder-core/src · defaults from the code, quad · no equation added that the code does not run

The math · physics + speed AI

Physics + speed AI: one extra measurement

Pathfinder (physics + speed AI) · jam detection, drag model, learned wind, plus a neural-network speed estimate
\text{physics only}\;+\;z_{\text{AI}}=v-w+\nu,\quad \nu\sim\mathcal N(0,R_{\text{AI}}),\quad R_{\text{AI}}=22.9\times294\,I\;(\text{m/s})^2
7 · The network's speed, as a measurement10/s
z_{\text{AI}}=v-w+\nu,\qquad y=z_{\text{AI}}-(v-w)
H\,\delta x=\delta v-\delta w
The output is treated as air speed, so it is compared with ground speed minus wind. Then step 4 applies.
learned.rs:290-296, :313-321
8 · How much it is trustedR and its gate
R_{\text{AI}}=\big(s\,\Sigma_{\text{net}}+r_f I\big)\cdot\tfrac{2\tau}{\Delta s}\cdot\rho
s=0,\;r_f=22.9,\;\tau=14.7\,\text{s},\;\Delta s=0.1\,\text{s}\;\Rightarrow\;\times294
\text{used only if } y^\top S^{-1}y\le 11.34
Σnet, the network's own confidence, is switched off (s = 0). Floor rf = 4.8 m/s RMS. Errors stay correlated for τ, so R is inflated ×294. ρ: trust schedule, off.
learned.rs:296-327, :345-357 · config.rs:24-39, :59-66
  1. Inputs
    13 signalsgyro, accel (heading frame), baro rate, roll, pitch, motor mean + spread
  2. Window
    1 s at 50 Hz50 samples, a new guess every 0.1 s
  3. Network
    Causal TCN4 dilated blocks (1, 2, 4, 8), width 64, + airframe type
  4. Training
    MSE, then Gaussian NLLv2 400 · v3 1,200 · v4 5-seed ensemble
  5. Next · A + B
    Two heads, 5-10 sfix drag's residual; learn drag R and wind qw

training/src/pathfinder_ml/spec.py:13-27, model.py:36-62, :81, train.py:100 · data and v1-v4: Pathfinder/docs/night/2026-10-13-ml-alternatives.md:17-41, :90-118 · A + B: D-ML-ALT-2 "Build A + B in one model"

The AI · from our results

AI: what it buys, what it costs

Pathfinder (physics only) · jam detection, drag model, learned wind
\hat p=\textstyle\int v\,dt,\quad v=C(q)\,u+w,\quad \bar f_{xy}=-k\,u-k_q\,u\lvert u\rvert,\quad \text{GPS used only if } d<6
Pathfinder (physics + speed AI) · jam detection, drag model, learned wind, plus a neural-network speed estimate
\text{physics only}\;+\;z_{\text{AI}}=v-w+\nu,\quad \nu\sim\mathcal N(0,R_{\text{AI}}),\quad R_{\text{AI}}=22.9\times294\,I\;(\text{m/s})^2
Median off after jamphysics onlyphysics + speed AIAI change
1 min2.14 m1.97 m▼ 8% closer
2 min3.31 m3.71 m▲ 12% worse
5 min19.34 m23.18 m▲ 20% worse
Mission end, miss164.8 m156.2 m▼ 5% closer

Pros

  • 3.8×closer than ArduPilot alone, by itself (547 vs 2,059 m at 2 min) measured (sim)
  • 8%closer at 1 minute measured (sim)
  • 0new sensors: uses motor outputs already sent code

Cons

  • 12-20%worse at 2 and 5 minutes; AC-02 fails measured (sim)
  • ~100×noisier than drag (4.8 vs ≈0.03 m/s) estimate
  • 200flights: no gain past this measured (sim)
  • ×2000its own confidence was off; thrown away measured (sim)
  • 2 of 2flights landed when trusted more (D-68) measured (sim)

Table: Pathfinder-wt-fasttests/docs/night/2026-10-13-fast-run-2.md:11, :18-25 (24 held-out jammed flights) · ML alone and ArduPilot: ml-alternatives.md:38-40 · ×100, 200, ×2000, D-68: ml-alternatives.md:26-31, :43-52 · runs repeat within ~10%: fast-run-2.md:41

One cycle · the whole loop

One cycle in the air

Each motion reading, every 5 ms, moves the loop.

The Pathfinder loop with how often each step runs Seven steps in a circle: sensors in, motion 200 per second; predict, 200 per second; drag check, 10 per second; ML speed, 10 per second, ML version only; fuse, GPS judged 5 per second; position out, 20 per second; ArduPilot flies, then new sensor readings. 1 Sensors inmotion 200/s 2 Predict200/s · 5 ms 3 Drag check10/s · 100 ms 4 ML speed10/s · ML only 5 FuseGPS judged 5/s 6 Position out20/s + circle 7 ArduPilotflies on it Time per step on the drone's computer: not measured

Motion 200/s crates/pathfinderd/src/cli.rs:3 · predict per reading navigator.rs:107-109 (≤ 50 ms step config.rs:57) · drag 0.1 s config.rs:56, navigator.rs:113-119 · ML 50 samples/s, 1 s window, new guess each 0.1 s models/velocity-v3.meta.json · GPS 5/s daemon.rs:29 · out 20/s daemon.rs:17 · run time: open item docs/PLAN.md:117 not measured · loop from deck slide "One cycle in the air", docs/pitch/deck.html

One cycle · zoom in

200 milliseconds, zoomed in

Each mark is one run of that step.

Predict200/s Height20/s Drag check10/s ML speed10/s Compass10/s GPS check5/s Position out20/s 0 ms50100150200 ms

Height 20/s daemon.rs:30 · compass 10/s daemon.rs:23 · sensor rates above from the code; the alignment of marks within the 200 ms is a drawing, not a recording · run time per step not measured (docs/PLAN.md:117)

Tonight's results

Pathfinder: metres. ArduPilot: kilometres.

How far off after the jam. Each gridline: ten times more.

Motion sensors onlyArduPilotPathfinder
Pathfinder (physics only) · jam detection, drag model, learned wind
\hat p=\textstyle\int v\,dt,\quad v=C(q)\,u+w,\quad \bar f_{xy}=-k\,u-k_q\,u\lvert u\rvert,\quad \text{GPS used only if } d<6
Pathfinder (physics + speed AI) · jam detection, drag model, learned wind, plus a neural-network speed estimate
\text{physics only}\;+\;z_{\text{AI}}=v-w+\nu,\quad \nu\sim\mathcal N(0,R_{\text{AI}}),\quad R_{\text{AI}}=22.9\times294\,I\;(\text{m/s})^2
Motionsensors onlyArduPilot,failsafes offStockArduPilotPathfinderphysics onlyPathfinderphysics + speed AI 1 min2 min5 min 1 min2 min5 min 1 min2 min5 min 1 min2 min5 min 1 min2 min5 min 994 m8.8 km145 km 1.4 km2.1 km3.8 km 971 m 2.1 m3.3 m19 m 2.0 m3.7 m23 m landedlanded 1 m100 m10 km1000 km median of 24 jammed flights · measured (sim)

Pathfinder medians: Pathfinder-wt-fasttests/docs/night/2026-10-13-fast-run-2.md:11 · motion only, ArduPilot, stock: :32-34 · 24 held-out flights per system, fast run 2, 2026-10-13 measured (sim)

Tonight's results · the four tests

One pass, three fails

Pass marks were locked before any flight.

AC-01Finish without an emergency landing: 22 of 24 (needs 95%)✕ Fail
AC-02Beat ArduPilot, and beat Pathfinder (physics only)✕ Fail
AC-03Honest safety circle: 98.75% inside (needs 90-98%)✕ Fail
AC-04False GPS alarms: 0 in 5.26 flight hours✓ Pass

All measured (sim): fast-run-2.md:10-13

Why the ML adds drift

Two speedometers. One wobbles a lot.

Pathfinder (physics + speed AI) · jam detection, drag model, learned wind, plus a neural-network speed estimate
\text{physics only}\;+\;z_{\text{AI}}=v-w+\nu,\quad \nu\sim\mathcal N(0,R_{\text{AI}}),\quad R_{\text{AI}}=22.9\times294\,I\;(\text{m/s})^2

Mixing in the wobbly one adds error.

ML speedometer ± 4.8 m/s measured (sim) Drag physics ≈ ± 0.03 m/s estimate same dial, 0 to 20 m/s; shaded = typical error

Neither one sees the wind. estimate

ML 4.8 m/s RMS (D-62) and drag ≈ 0.03 m/s (3.31 m ÷ 120 s): Pathfinder/docs/night/2026-10-13-ml-alternatives.md:47-52 · wind: :53-56

Model versions

Four versions, none clearly better

ML alone, metres off 2 minutes after jamming.

  1. v1
    First try400 flights, older sensor format · not scored here
  2. v2
    580 m400 flights · still the one Pathfinder loads
  3. v3
    547 m1,200 flights · gap is within noise
  4. v4
    623 m5 models averaged, confidence fixed · worse
  5. Next
    A + Bfix drag, learn trust · not trained yet

For scale: ArduPilot alone is 2,059 m off on the same flights. measured (sim)

v1 data: ml-alternatives.md §4 · v2/v3/v4 and ArduPilot: ml-alternatives.md:39-41, docs/measurements/2026-10-learned-v3-heldout.md:19-21 (v4 on branch dnav-predictor, 8f3030f) · 8 held-out flights, quad + octa measured (sim)

Model versions · more data?

More flights stopped helping after 200

The 1-second window is the limit, not the data.

no gain past ~200 flights 0200400600800 m 718610613615708 v3: 547 1002004008001,600 training flights · measured (sim)

docs/measurements/2026-10-learning-curve.md:15-20 (quad + octa, n=8, heldout-jam-1000..1011) measured (sim)

What replaces it

Three ways forward. We build A + B.

One new model, two jobs.

✓ Chosen
A · Correct the drag modelLearn only what physics gets wrong, from 5-10 s of data.
✓ Chosen
B · Learn how much to trustTrust drag more in calm air; let wind change faster in gusts.
✕ Not now
C · Reinforcement learningBest case ties "physics only"; needs days of simulator flights.

Expected: A wins at 2 min, B cuts 5-min drift 10-25%. estimate

Options: Pathfinder/docs/night/2026-10-13-ml-alternatives.md:71-170 · decisions D-ML-ALT-1 "Develop an alternative ML model in parallel and compare" and D-ML-ALT-2 "Build A + B in one model": BaseClient/docs/Tasks/IN_PROGRESS/drone-nav/DNAV-1-gps-denied-navigation/DNAV-1-gps-denied-navigation.md:31-33

Error budget · physics only

Wind and drag cause most drift; heading barely matters

64 replays: wind plus drag explain about 27 of 34 m at 5 min.

Ranked share of drift at 1, 2 and 5 minutes over 64 physics-only replays. Wind estimate error 3.8, 8.8, 14.1 m. Drag coefficient, mass or accelerometer bias -0.2, 0.9, 12.6 m. Unexplained -1.7, -4.0, 9.1 m. Speed AI error 0.14, 0.20, 1.07 m. Heading 0.7, 0.3, -1.9 m.

Tap the chart to open it full size.

measured (sim) Median total 2.0 / 4.9 / 18.6 m at 1 / 2 / 5 min. Wind numbers are a fit estimate.

Chart: docs/night/2026-10-13-error-budget.svg · tool from fb9a2ae ACC-STEP-1 "Error budget: which source causes the drift"

Learning in flight · per aircraft

Tuned to each aircraft, while GPS is good

The aircraft type goes in; the rest adjusts in flight.

WindLearned while GPS is good, held after the jam; navigator.rs:145 (built, on main)built
Speed AILast layer refitted while GPS is good, stops by 180 s; adapter.rs:1 (built, on main)built
Drag scaleLearned while GPS is good; air_learn.rs:1, preset experimental-learn-air: 159.6 vs 80.4 m at 2 min (offline estimate)lost, off
Aircraftquad, hexa or octa is a parameter: spec.py:25, --frame in harness and pathfinderd; hexa never trained: 204 m at 2 min (measured (sim))built
Fine-tuneDrift-correcting AI fine-tuned in flight; a model per real aircraftplanned

crates/pathfinder-core/src/adapter.rs, air_learn.rs · training/src/pathfinder_ml/spec.py · DNAV-ACC-STEP-2 notes measured (sim) offline estimate

Progress · 11 to 12 October

Two days: from runaway to 85 m

Every milestone dated; losses kept.

11 Oct 00:58Core passes on Linux, ARM, Windows: AC-08 green (measured (code tests))
11 Oct 01:59First jammed flights in the simulator (built)
11 Oct 02:24Same answer on every replay: AC-09: 1,463 rows identical (measured (code tests))
11 Oct 12:46Runaway found and fixed: 3,135 to 29.6 m at 5 min (measured (sim))won
12 OctProof flight, flown twice: 85 m vs ArduPilot 2,366 m (measured (sim))won
12 OctFake GPS caught, 31 of 31: flagged in 0.09-2.25 s (measured (sim))won
12 OctMission test after fixes: AC-01: 11 to 20 of 24 (measured (sim))

docs/night/2026-10-12-morning-proof.md · DNAV-1 night log 2026-10-11 measured (sim)

Progress · 13 October

One day, three wins, three losses

What lost stays switched off.

00:13All four acceptance tests in one run: 1,086 s; AC-04 passes (measured (sim))
01:28Drift ranked by source: wind first: 14.1 m at 5 min (measured (sim))
02:16Re-flown fixes, one flight: 132 to 15 m at 5 min (measured (sim))won
15:05Model 2 flown in the loop: lost: 24.59 vs 3.99 m (measured (sim))lost
16:25Replay: every system on one map (built)
18:12Terrain matching, offline: 200.4 to 128.1 m at 5 min (offline estimate)won
18:32One branch, 11 presets (built)
18:32Terrain in the loop, 1 flight: lost: 333.7 vs 172.6 m (measured (sim))lost
19:37Control Room: New run in 5 steps (built)
19:46Drift-AI gate, replayed: lost: 3.30 vs 3.11 m (measured (sim))lost

docs/night/2026-10-13-fast-run-2.md · proof-Q3.md · terrain-offline.md (dnav-terrain) · drift-gate-replay.md (dnav-acc2-gate) measured (sim) offline estimate

Evidence · every try

Every try, against physics only

Same flights. Most tries lost.

Speed AI, fast run 2 (1 min): 1.97 vs 2.14 m (measured (sim))won
Speed AI, fast run 2 (2 min): 3.71 vs 3.31 m (measured (sim))lost
Q1 radius + adapter fix (2 min): 3.46 vs 2.75 m (measured (sim))lost
Q1 radius + adapter fix (5 min): 17.59 vs 18.78 m (measured (sim))won
Q2 touchdown clamp (2 min): 3.66 vs 3.35 m (measured (sim))lost
Drag learning in flight (2 min): 159.6 vs 80.4 m (measured (sim))lost
Model 2 drift AI, offline (2 min): 47.5 vs 78.4 m (offline estimate)won
Model 2 drift AI, Q3 in loop (2 min): 24.59 vs 3.99 m (measured (sim))lost
Drift-AI gate, best, replay (2 min): 3.3 vs 3.11 m (measured (sim))lost
Terrain fixes, offline (5 min): 128.1 vs 200.4 m (offline estimate)won
Terrain fixes, in the loop (5 min): 333.7 vs 172.6 m (measured (sim))lost

proof-Q1.md, proof-Q2.md, proof-Q3.md, fast-run-2.md (main) · drift-gate-replay.md (dnav-acc2-gate) · terrain-offline.md (dnav-terrain)

Integration

Plugs into ArduPilot over MAVLink

One program on a companion computer.

inHIGHRES_IMU at 200 Hz, SCALED_IMU, ATTITUDE, GPS_RAW_INT, SCALED_PRESSURE
outODOMETRY at 20 Hz as EKF3 external nav, or GPS_INPUT as a second GPS
pickconfig/presets.json: 11 presets, default best. Pick with --preset, PATHFINDER_PRESET or the Control Room Setup picker. Every switch off = byte-identical main.
runControl Room, localhost:8790: Fly, re-fly, train, test, replay and present from one browser page.

crates/pathfinderd/src/daemon.rs, cli.rs, intake.rs · config/presets.json · docs/CONTROL-ROOM.md

Demo

One jammed flight, every system

Live at localhost:8790; video if live fails.

Flight heldout-jam-1002, Q3 run 3 measured (sim)