Tutorial: GPS Degradation
The runnable source is core/examples/gnss_outage.rs:
cargo run -p strapdown-core --example gnss_outage
The scenario is the one every GNSS-denied study starts from: 60 s tracking normally, 120 s with no fixes at all (a tunnel, an urban canyon, jamming), then aiding returns for 120 s. The vehicle carries a 0.05 m/s² accelerometer bias on its forward axis, representative of a consumer MEMS part after turn-on.
The shape of the error
t (s) error (m) GNSS
60 0.0 ok
70 0.2 denied
100 2.0 denied
140 14.9 denied
180 49.4 denied
190 0.0 ok
Flat while aided, growing while coasting, and back to zero within a single fix of recovery. The growth is quadratic because a constant acceleration error integrates twice into position.
Why the drift is smaller than the textbook figure
Double-integrating the bias over the outage predicts 360 m:
0.5 × 0.05 m/s² × (120 s)² = 360 m
The observed error is 49.4 m, seven times smaller. The reason is worth reading off the filter state rather than guessing at, and the example prints it:
accelerometer bias present: 0.0500 m/s^2 (forward axis)
bias the filter estimated: 0.0001 m/s^2 <- it barely moved
pitch error at outage start: 0.2987 deg
gravity that tilt leaks forward: 0.0511 m/s^2 <- nearly cancels the bias
The filter did not estimate the bias. It absorbed it into attitude instead: it believes the vehicle is pitched nose-up by three tenths of a degree, and the gravity that tilt leaks into the forward axis very nearly cancels the bias.
That is not a defect. A constant forward specific-force bias and a small pitch error produce the same horizontal acceleration signature, so position and velocity aiding cannot separate them — the pair is unobservable from this measurement set alone. The filter found an explanation consistent with every fix it was given, and that explanation happens to coast well.
The practical lesson is not the quadratic. It is that which of the two the filter blames is arbitrary, and it changes how well the solution coasts. Aiding that does separate them — a zero-velocity update, a second antenna, a magnetometer for heading — is what makes dead-reckoning performance predictable rather than lucky.
Turning the knobs
Two constants at the top of the example are worth changing:
OUTAGE_DURATION_S— drift grows with the square of this, so doubling it roughly quadruples the peak error.ACCEL_BIAS_MPS2— set it to zero and the vehicle coasts almost perfectly. Note that the drift does not scale with it directly, for the reason above.
The same scenario from a config file
To run this through the CLI instead of in code, see
Example Configurations; simple_dropout.yaml and
extended_gnss_denied.yaml describe outages of 30 s and 5 minutes respectively.