Six instruments,
four estimators.
Every element is drawn in OpenGL ES 3 from a single per-frame state snapshot — a crisp, low-latency display that stays readable in direct sunlight.
The display is drawn in OpenGL ES 3 from a single per-frame state snapshot. The pipeline is built for a steady, low-power, allocation-free frame — so the picture stays smooth and the battery lasts.
Render-on-dirty
A frame is drawn only when the state actually changes — selectable 30 Hz battery-saver, or uncapped 60 Hz bounded by vsync. The IMU streams up to 250 Hz (configurable, or synced to the display rate); the filters run at whatever the stream delivers.
Zero per-frame allocation
No objects are allocated while drawing, so there are no garbage-collection stalls — motion stays smooth.
Batched triangles
Geometry is accumulated and submitted in a few large draw calls instead of many small ones.
Cached geometry
Shapes whose parameters haven't changed reuse their cached vertices instead of rebuilding.
Shared GL resources
One shader program and a shared text atlas serve every instrument — minimal state changes.
Pre-allocated matrices
Attitude matrices live for the lifetime of the renderer, reused every frame.
No single sensor gives a trustworthy attitude. The gyroscope is fast but drifts; the accelerometer and magnetometer are stable on average but noisy and disturbed by manoeuvre. Every estimator below resolves the same conflict — trust the gyro over short intervals, correct it toward gravity and magnetic north over long ones — and they differ only in how they strike that balance. Each is presented in its own section below, in the order they appear in Settings.
The gyro propagates attitude fast; every other sensor only ever applies a small correction. The accelerometer anchors pitch and roll from gravity — but it is gated off the instant a sustained turn or linear acceleration makes "down" untrustworthy. What keeps the bank true under load is a set of independent EKF (Extended Kalman Filter) measurement updates, each watching a different quantity and weighted by its own confidence. Its state carries not only the quaternion and gyro bias but a per-device temperature coefficient — the IMU's temperature is logged and fed in, so the bias it removes tracks the sensor as it warms. This is the default estimator.
A Mahony-MARG filter (Magnetic, Angular-rate, Gravity) splits the signal by frequency: the gyro supplies the fast motion, accel and mag the slow reference. The correction is the rotation error between measured and estimated gravity/north, fed back through a proportional and an integral gain — and the integral term also learns and cancels gyro bias. Cheap, robust and predictable — the simple, dependable fallback.
Frames orientation as an optimisation: the gyro gives the rate, while a single gradient-descent step nudges the estimate toward the orientation that best matches measured gravity and north — at one tunable rate, β. Smooth and responsive for very little compute.
When the IMU already publishes its own fused quaternion, this mode passes it straight to the display — a useful reference, and the right choice when you trust the sensor's on-board fusion over the phone's.
| BLE Waveshare 10-DOF | external IMU (primary) |
|---|---|
| Internal sensors | phone accel, gyro, mag, baro |
| X-Plane UDP | simulator feed |
| FlySys TCP | TCP gateway |
| Replay | recorded CSV from Documents/PFS/ |
| Demo | synthetic motion (no hardware) |
Magnetometer
Hard- and soft-iron fit so heading stays honest near metal and avionics.
Accelerometer
A guided 6-face procedure recovers per-axis offset and scale, applied before the filters.
Gyro offset
A short static "Align" window zeroes gyro bias the moment you power up on the ground.