The hard parts.
The trustworthy bits aren't the equations — they're what happens when the sensors lie: vibration, manoeuvre load, dropped links, stale data. This is the engineering that keeps the picture honest when the flying gets real.
Airframe and engine vibration ride on the raw accelerometer and gyro. Each axis is cleaned by its own 2-pole Butterworth low-pass — an IIR (infinite impulse response) filter in Direct Form II Transposed — before it reaches the filters and the slip ball — branch-free and allocation-free, safe to run at full sensor rate.
The accelerometer only tells you "down" when it's measuring pure gravity. In a turn, under braking, in turbulence, it isn't — so its correction is gated. And the reference gravity magnitude is learned per device (a slow exponential moving average (EMA), τ≈16 s) rather than assumed to be 9.81 m/s² — MEMS (Micro-Electro-Mechanical Systems) units often read ~10.2 — so a scale bias can't quietly tilt the horizon.
Gating the accelerometer would leave the filter blind through a long turn — so it is never the only correction. The ESKF (Error-State Kalman Filter) runs a set of independent measurement updates, each watching a different observable and weighted by its own σ. When gravity can't be trusted, these are what hold a true attitude.
| Gravity direction | accelerometer, pitch & roll (gated in turns) |
|---|---|
| Coordinated-turn bank | bank = atan(V·ω / g) (GPS) |
| Load-factor bank | bank = acos(1 / N) (no GPS) |
| Flight-path pitch | pitch = asin(VSI / V) + AoA (VSI = vertical speed, AoA = angle of attack; baro & GPS-alt) |
| Heading | magnetometer (GPS track as fallback) |
| Gyro bias | learned online, temperature-tracked b_eff(T) |
The load-factor bank is the quiet workhorse: acos(1/N) reads the bank straight off the g-load with no GPS at all — so a coordinated turn stays true even with no satellites and the accelerometer gated off.
Small touches that matter in the cockpit: the tape digits roll over with hysteresis so they never flicker on the boundary, and if the data goes quiet the display tells you — it doesn't pretend.
Rollover hysteresis
Tape digits only change past a small margin, so a value sitting on a boundary stays put instead of stuttering.
Stale-data caution
If samples stop arriving, an amber caution latches after a few seconds blind — the picture never silently freezes as if all were well.
Bluetooth in a metal cockpit drops. When it does, the reader reconnects on its own and re-seeds the attitude from the current orientation, so the horizon snaps back upright instead of tumbling. On the network path, the TCP gateway is found automatically by mDNS — no IP addresses to type.
Auto-reconnect & re-seed
A dropped Inertial Measurement Unit (IMU) link is re-established automatically; attitude is re-initialised from gravity so there's no long settle.
Zero-config discovery
The FlySys TCP source is located on the network by name — plug in and it appears, no manual addressing.
The IMU module fuses natively in ENU (East-North-Up); the PFD's attitude pipeline works in NED (North-East-Down). The app re-expresses the solution ENU→NED at ingestion, so every filter, the horizon and the slip ball share one consistent frame.