Recursive Estimation & the Kalman Filter
Stop re-solving from scratch every second — remember where you were, predict where you're going, and fold in each new fix
Why it matters
Every real GNSS receiver, and essentially every navigation system that fuses sensors over time, runs a Kalman filter or a close relative. It turns a stream of noisy, standalone fixes into a smooth track with velocity and a trustworthy uncertainty, and it is the frame on which GNSS/INS integration, RTK, and PPP estimators are all built.
Prerequisites
The receiver with amnesia
Here is something slightly absurd about every solver you have met so far. SPP computes a fix this second, reports it, and then — for the next second — forgets it completely and solves again from nothing. A receiver doing 40 km/h in a straight line computes each position as if it had teleported there from the void, with no memory that one second ago it was twenty metres back along the exact same line.
That amnesia is not just inelegant; it is throwing away information. If you know where you were and roughly how you are moving, you already have a very good guess about where you are now, before the next fix even arrives. A noisy fix that disagrees wildly with that guess is probably mostly noise. A receiver that remembers can tell signal from noise in a way a receiver that re-solves from scratch never can.
The question this lesson answers is simply: how do you let a receiver remember — correctly, optimally, and in a way that also tells you how fast you are going and how sure you are?
The idea, before any mathematics
Hold two numbers in your head about your own position: your best guess, and how sure you are of it. Not just "I'm at the corner of 5th and Main," but "I'm at the corner of 5th and Main, give or take three metres." That give or take is as important as the guess, and the whole filter is just the disciplined bookkeeping of both through time.
Now run a two-beat rhythm, forever:
- Predict. Before the next fix, use what you know about motion to coast your guess forward: I was here, moving that way, so a second later I'm probably over here. Your best guess moves — and crucially your give or take grows, because coasting blind makes you less certain.
- Update. A fresh fix arrives, itself noisy with its own give or take. Now you have two opinions about where you are: your prediction and the measurement. Don't pick one — blend them, leaning toward whichever is more confident. The blended guess is better than either, and your give or take shrinks, because two independent opinions pin you down better than one.
That is the entire filter. Predict grows uncertainty, update shrinks it, and the cycle settles into a steady state where the two balance. The genius is in the word blend: the filter works out the mathematically optimal weighting from the two uncertainties, so you never hand-pick how much to trust the fix — the covariances decide.
A Kalman filter is not a smoother bolted onto your measurements. It is a running belief — a guess and its uncertainty — that coasts forward on a model and gets corrected by evidence, each weighted by exactly how much it deserves.
And here is the quiet miracle: if your state includes velocity, the predict step couples it to position (position tomorrow = position today + velocity × time). So when the updates keep nudging your position, they implicitly pin down the velocity that explains the motion — and the filter reports a speed it was never directly told. Observing the unmeasured through the measured is the deepest trick in estimation.
Seeing it
Picture a car on a gently curving road. Once a second a noisy GPS fix drops onto the map, scattered a few metres off the true road in a random direction — a little cloud of dots that never quite lands on the asphalt. Lay the filter's track over them and it threads between the dots, riding the actual road, because it refuses to believe any single dot that lurches away from where its model said the car should be. Around the car, draw an ellipse: the filter's own statement of its give or take, fat when fixes are sparse or noisy, tight when they are clean.
Try it yourself
The dashed line is the true path — the filter never sees it. All it gets are the scattered fixes. Watch it thread the track, then tune it.
- Raw fix error
- 3.17 m
- Filtered error
- 3.20 m
- Est. speed
- 6.13 m/s
- True speed
- 6.00 m/s
- Position σ
- 2.08 m
- Innovation
- 7.95 m
Each grey dot is a standalone fix — exactly what SPP would hand you, scattered by its error budget. The filter never sees the true path (dashed); it only sees the dots, yet the blue track rides far closer to the truth, because it also remembers: every estimate is last second’s prediction blended with this second’s fix. Notice it even reports a speed it was never told, read purely from how the position marches. Now tune it. Push process noise toward zero and the track turns glassy-smooth but cuts the corner — the filter trusts its straight-line model too much to believe you are turning. Push it high and the track grows jittery, chasing every dot. Crank measurement noise up and the filter leans on its model and smooths harder; drop it and the filter believes the dots. That tension — model versus measurement — is the entire craft of filter tuning, and the ellipse is the filter’s own honest statement of how sure it is right now.
Scrub the time step and watch the blue estimate ride far closer to the road than the grey fixes it is built from — and read the speed it recovers from position alone. Now play with the two knobs that are the filter. Slide process noise toward zero: the track turns glass-smooth but visibly cuts the corner, because a near-zero process noise tells the filter "the target never deviates from a straight line," so it refuses to believe the turn until the fixes drag it around, late. Slide it high and the track gets jumpy, chasing individual dots. Then work the measurement-noise slider: high values tell the filter the dots are garbage, so it leans on its model and smooths hard; low values tell it the dots are gospel, and the track snaps onto them. Every real filter lives somewhere in that tension, and choosing where is the craft.
Now the mathematics
Collect what you are estimating into a state vector. For a vehicle in our plane, position and velocity:
in metres and metres/second. Your give or take is the covariance matrix — its diagonal holds the variance of each state, its off-diagonals how they correlate.
Predict. A constant-velocity model propagates the state over a step with the transition matrix , and the uncertainty grows by the process noise :
Read literally: the new position is the old position plus velocity times — that one coupling is what lets position measurements teach the filter about velocity. encodes how much real acceleration the model ignores: small means "I trust constant velocity," large means "the target can manoeuvre."
Update. A measurement (here a position fix) relates to the state through , with measurement-noise covariance . Form the innovation — how much the fix disagrees with the prediction — and its covariance :
The Kalman gain is the optimal blend weight, and it is worth staring at:
Everything is in that . When the measurement is noisy ( large), is large, is small, and the fix barely moves your estimate — you trust the model. When your prediction is uncertain ( large), grows toward 1 and you snap to the fix — you trust the measurement. The gain is nothing but the ratio of confidences, computed automatically every step. And is not invented: it is the single-epoch fix accuracy, the UERE scaled by DOP straight from the error budget. The filter is literally fed the previous lessons' output.
This is the linear filter, where and are matrices. When the measurement is a nonlinear function of the state — as a raw pseudorange is — you linearise each step and get the Extended Kalman Filter (EKF), which is what production GNSS engines actually run. The rhythm is identical; only the bookkeeping grows.
How this appears in engineering
The Kalman filter is the spine of real navigation. A GNSS receiver filters its position/velocity states so the track is smooth and a dropped fix just widens the ellipse instead of tearing a hole. GNSS/INS integration lives or dies here: between fixes the filter predicts using the inertial sensors' acceleration and rotation, and each GNSS fix updates it — so the system coasts through tunnels on inertial dead-reckoning and snaps back when the sky returns, the two sensors covering each other's weaknesses through one covariance.
Look back and you will see the filter hiding everywhere. RTK engines run a Kalman filter over the carrier and ambiguity states; PPP is almost always a Kalman filter, and the convergence you watched there is literally its covariance shrinking epoch by epoch as the updates accumulate. The innovation is also a built-in alarm: a fix that disagrees with the prediction far more than says it should is probably an outlier — a multipath blunder or a cycle slip — and gets down-weighted or rejected before it can poison the state. That is the validation stage of estimation, falling out of the same covariance arithmetic for free.
Check your understanding
- A position-only filter reports a confident velocity. Where did that information come from, and which matrix made it possible?
- You set the process noise very small and the track lags badly whenever the vehicle turns. Explain the mechanism, and say what happens to the Kalman gain when the fixes finally drag the estimate around.
- Two receivers use identical hardware; one sits in an open field, the other in an urban canyon with a poor DOP. Which matrix differs between their filters, and how should it differ?
- A single fix lands ten metres from the prediction while the innovation covariance says to expect one metre of disagreement. What has the filter just learned, and what should it do with that fix?
Where to go next
You now have the machine the whole field is built on: a running belief, corrected by evidence, weighted by confidence. Point it at raw pseudoranges and linearise, and you have the EKF behind every receiver. Feed it inertial sensors between fixes and you have GNSS/INS integration. Run it over carrier phase and ambiguities and you are back at RTK and PPP, now seen for what they really are — Kalman filters in disguise. Every precise, real-time positioning system you will ever meet is some elaboration of the two-beat rhythm you just tuned by hand.
Common misconceptions
- The Kalman filter just averages or smooths the measurements. It runs a physical model of the state and weights model against measurement by their covariances; the smoothing is a consequence, not the mechanism.
- A smoother filter is a better filter. Over-smoothing (too little process noise) lags and cuts corners on manoeuvres; the right tuning balances responsiveness against noise.
- The filter needs to measure velocity to know it. A position-only filter observes velocity through the changing position, as long as the motion model couples them.
Key takeaways
- Recursive estimation carries a belief forward instead of re-solving each epoch from scratch.
- The state holds what you estimate; the covariance holds how sure you are.
- Predict propagates and grows uncertainty; update shrinks it with a measurement.
- The Kalman gain is the optimal blend of prediction and measurement by their covariances.
- Process noise vs measurement noise is the core tuning trade-off between lag and jitter.