Probability for Robotics · Theory · M12
M12-T3 — Smoothing: Using Future Measurements
A smoother is a filter that is allowed to wait. How much better it gets depends on how long it waits.
A filter estimates the state at time t from readings up to t, because a controller cannot wait. Many tasks can: mapping, calibration, logging analysis, even a display that runs a second behind. A smoother uses the readings after t as well, and in exchange for the delay it gives better and more honest estimates. This lesson compares the three forms (filter, fixed-lag, fixed-interval), measures how accuracy depends on the lag, and shows that the largest gains are at the points where the filter is slowest: when the world changes.
Learning objectives
After this lesson, you should be able to:
- Distinguish filtering, fixed-lag smoothing and fixed-interval smoothing by what data each estimate uses and by its latency.
- Compute a fixed-lag smoothed estimate from the filter output with a backward recursion over a window.
- Explain the diminishing returns of lag and choose a lag from the filter’s memory.
- State when smoothing helps most (manoeuvres, initialisation, bias estimation) and what it costs.
The intuition
Suppose a robot travelling at 1 m/s suddenly reverses at step 60. At step 61 the filter has seen one reading that says “less far than expected”. It adjusts a little, being unsure whether this is a manoeuvre or noise, and takes about six steps (3 s) to get its velocity estimate within 0.5 m/s of the truth. A person looking at the whole record afterwards would put the turn at step 60 immediately: the readings at steps 62, 63, 64 all say “going back”.
That is what a smoother does: to estimate step it also uses readings . The left panel measures the benefit on a constant-velocity robot. With no lag (the filter) the position error is 11.7 cm and the velocity error 6.8 cm/s. One step of lag (0.5 s) gives 9.7 cm and 6.0; two steps 8.2 and 5.3; five steps (2.5 s) 6.9 cm and 4.1. After that, nothing: ten steps give 6.8 and 3.9, twenty 6.7 and 3.9. The curve flattens at about the time the filter takes to forget: readings further ahead tell the smoother nothing it does not already know about step .
The right panel shows where smoothing matters most. The reversal is a surprise to the model (it assumes a nearly constant velocity). The filter's rms velocity error in the 15 steps around it is 0.84 m/s and it needs 5.9 steps to recover; a smoother with a lag of five steps has 0.45 and needs 2.5 steps, and with ten steps 0.49 and 2.0: the same readings, interpreted with hindsight.
Smoothing buys accuracy with latency. The first few steps of lag are worth a lot, more lag is worth little, and nothing is gained for real-time control, which cannot wait.
Definitions
- Filtering
- The estimate of from : . Causal, no delay.
- Fixed-lag smoothing
- : the estimate of the state steps ago using everything up to now. A constant delay .
- Fixed-interval smoothing
- for all : offline, once the whole record is available.
- Fixed-point smoothing
- for a fixed as grows: refine the estimate of one moment (an initial state, a calibration) as data arrive.
- Smoother gain
- : how much the later estimate corrects the earlier one.
Derivation: why the backward pass is correct, and why lag saturates
The backward step
For the linear-Gaussian model the filter gives . The next state is . Condition on all the readings by first writing the joint of and given .
The joint of the state and its successor, with .
Conditioning a joint Gaussian (Module 4), with the gain .
The Markov property: once is known, the later readings tell nothing more about .
Average the conditional over (the law of total expectation and variance). This is the RTS recursion, run backward from .
Why lag saturates
The correction multiplies how much the next state moved relative to its prediction. Each backward step multiplies by again: the influence of a reading steps ahead on step is roughly , which decays geometrically. For the constant-velocity model of the example the steady-state smoother gain matrix has eigenvalues of modulus 0.81 (computed numerically from the converged filter), so the correction carried back from a reading steps ahead shrinks like : 0.35 at 5 steps, 0.12 at 10 and 0.015 at 20. That is why the table flattens between lag 5 and lag 10 and nothing is left to gain at 20.
Fixed-lag in a window
For an online system the backward pass need not go to the beginning: it runs over the window of steps and starts from the filter's estimate at the current time, so the cost per step is . The program does exactly this, using the filtered estimates and covariances already computed.
A smoother estimate is the filter estimate plus a correction from the future, passed back through gains that decay geometrically. A lag of a few filter time constants captures nearly all the benefit.
A worked example
The constant-velocity robot of Module 7: 0.5 s steps, acceleration noise 0.05, position readings with noise 0.2 m, a filter with correct models, 120 steps.
- Accuracy against lag (60 runs, steps 10–100). Lag 0: position 0.1173 m, velocity 0.0679 m/s, claimed velocity std 0.0733. Lag 1: 0.0966, 0.0598, 0.0648. Lag 2: 0.0824, 0.0527, 0.0571. Lag 5: 0.0686, 0.0414, 0.0424. Lag 10: 0.0679, 0.0393, 0.0387. Lag 20: 0.0667, 0.0391, 0.0386. The claimed standard deviations track the real errors: the smoother is consistent. Lag 5 captures 96% of the position gain and 92% of the velocity gain of lag 20, for 2.5 s of delay.
- A manoeuvre. At step 60 the velocity reverses from +1 to −1 m/s, which the motion model does not expect. The rms velocity error in steps 56 to 70 is 0.836 m/s for the filter, 0.574 with lag 2, 0.453 with lag 5 and 0.485 with lag 10; the mean time until the velocity estimate is within 0.5 m/s of the truth is 5.9, 4.2, 2.5 and 2.0 steps.
- Reading the result. Even with hindsight the estimate is not instantaneous: the smoother knows the velocity changed only after enough readings have accumulated, and the model's low process noise resists an abrupt change (a larger Q would react faster, at the price of noise in steady motion: module 7).
import math
from robotprob import Rng, mean, kf_predict, kf_update, rts_smoother
dt, sq, r_ = 0.5, 0.05, 0.04
F = [[1.0, dt], [0.0, 1.0]]; H = [[1.0, 0.0]]
q = sq * sq
Q = [[q * dt**3 / 3, q * dt**2 / 2], [q * dt**2 / 2, q * dt]]
R = [[r_]]
T = 120
def simulate(seed, jump=False):
rng = Rng(seed)
pos, vel = 0.0, 1.0
truth, zs = [], []
for t in range(T):
if jump and t == 60: vel = -1.0 # a manoeuvre the model does not know about: the robot reverses
vel += rng.gauss(0.0, sq * math.sqrt(dt)); pos += vel * dt
truth.append((pos, vel)); zs.append(pos + rng.gauss(0.0, math.sqrt(r_)))
return truth, zs
def filter_run(zs):
x, P = [0.0, 1.0], [[1.0, 0.0], [0.0, 1.0]]
xs, Ps = [], []
for z in zs:
x, P = kf_predict(x, P, F, Q)
x, P, y, S, K = kf_update(x, P, [z], H, R)
xs.append(x); Ps.append(P)
return xs, Ps
def fixed_lag(xs, Ps, t, lag):
"""The estimate of step t using the measurements up to t + lag: the RTS backward pass over that window only."""
end = min(len(xs) - 1, t + lag)
sm_x, sm_P = rts_smoother(xs[t:end + 1], Ps[t:end + 1], F, Q)
return sm_x[0], sm_P[0]
print('fixed-lag smoothing of the constant-velocity robot: 60 runs, steps 10-100')
print('lag (steps) delay (s) rms position error rms velocity error claimed velocity std')
for lag in (0, 1, 2, 5, 10, 20):
ep, ev, cl = [], [], []
for seed in range(1, 61):
truth, zs = simulate(seed)
xs, Ps = filter_run(zs)
for t in range(10, 101):
x, P = fixed_lag(xs, Ps, t, lag)
ep.append((x[0] - truth[t][0]) ** 2); ev.append((x[1] - truth[t][1]) ** 2); cl.append(P[1][1])
print(str(lag).rjust(8), str(lag * dt).rjust(11), str(round(math.sqrt(mean(ep)), 4)).rjust(16), str(round(math.sqrt(mean(ev)), 4)).rjust(20), str(round(math.sqrt(mean(cl)), 4)).rjust(20))
print('a manoeuvre the model does not know about: at step 60 the velocity changes from +1 to -1 m/s')
print('lag rms velocity error in steps 56-70 time (steps) until the velocity estimate is within 0.5 m/s of the truth')
for lag in (0, 2, 5, 10):
errs, reach = [], []
for seed in range(1, 61):
truth, zs = simulate(seed, jump=True)
xs, Ps = filter_run(zs)
est = [fixed_lag(xs, Ps, t, lag)[0] for t in range(50, 80)]
for t in range(56, 71): errs.append((est[t - 50][1] - truth[t][1]) ** 2)
k = next((t for t in range(60, 80) if abs(est[t - 50][1] - truth[t][1]) < 0.5), 80)
reach.append(k - 60)
print(str(lag).rjust(3), str(round(math.sqrt(mean(errs)), 3)).rjust(24), str(round(mean(reach), 1)).rjust(40))fixed-lag smoothing of the constant-velocity robot: 60 runs, steps 10-100
lag (steps) delay (s) rms position error rms velocity error claimed velocity std
0 0.0 0.1173 0.0679 0.0733
1 0.5 0.0966 0.0598 0.0648
2 1.0 0.0824 0.0527 0.0571
5 2.5 0.0686 0.0414 0.0424
10 5.0 0.0679 0.0393 0.0387
20 10.0 0.0667 0.0391 0.0386
a manoeuvre the model does not know about: at step 60 the velocity changes from +1 to -1 m/s
lag rms velocity error in steps 56-70 time (steps) until the velocity estimate is within 0.5 m/s of the truth
0 0.836 5.9
2 0.574 4.2
5 0.453 2.5
10 0.485 2.0fixed_lag runs rts_smoother over the window [t, t + lag] of the filter results and takes the first element: the state at t given the readings up to t + lag.In robotics
Where the delay is acceptable
- Mapping and reconstruction: the map is built from the smoothed trajectory (Module 11); no one needs the pose before the scan is processed.
- Calibration and system identification: estimating a fixed bias or alignment from a whole run uses the fixed-interval smoother or the batch problem.
- Offline analysis: flight-log reconstruction, sports tracking, post-processed GNSS.
- Display and logging: a trajectory shown with a one-second delay can be much smoother than a live one.
Sliding-window smoothers in robotics
Visual–inertial odometry systems optimise the last few seconds of poses, landmarks and IMU biases together (a fixed-lag smoother), marginalising the oldest states with the Schur complement as in Module 11, lesson 3. Each new image improves the estimates of the preceding poses; the control loop reads the newest pose, which is a filter-quality estimate, and the map uses the older, better ones. The SLAM course covers these windowed estimators in its back-end lessons.
Choosing the lag
- Plot the error (or the claimed standard deviation) against the lag as in the figure and stop where the curve flattens: here at about 5 steps.
- For a nearly constant-velocity system the memory is of order steps (the filter's gain K sets how fast it forgets); the lag should be a few times that.
- Budget the latency: if the downstream user can wait , spend it.
Smoothing and model errors
A smoother is only as good as its model. A wrong process noise gives wrong gains and a delayed but biased estimate; a smoother that is told the motion is nearly constant will smooth away a real manoeuvre. Check the smoothed residuals: if the smoothed trajectory is much smoother than the readings imply, the model is too stiff.
Common misconceptions
“A smoother gives the same estimate, just later.”
It gives a different, better estimate of the same moment: here the velocity error at lag 5 was 4.1 cm/s against 6.8 for the filter, and its claimed uncertainty was lower.
“More lag always helps.”
The gain decays geometrically with the number of steps; lag 10 and lag 20 differed by only about 1 mm and 0.2 mm/s. Beyond the filter’s memory, extra lag is only extra delay.
“The smoothed covariance is the filter covariance minus something.”
It is: smoothed P is never larger than the filtered one. But it is correct only if the model is, and in a manoeuvre the model is wrong, so the smoothed claims need the same checking as the filter’s.
“A smoother can be used in a control loop with a small lag.”
It can, but the controller then acts on an estimate that is already a few steps old: with lag 2 that is one second, and the delay can destabilise a fast loop. Control uses the filter estimate and the smoother improves the record.
Key takeaways
- Filtering uses readings up to t, fixed-lag smoothing up to t + L, fixed-interval smoothing the whole record.
- The RTS backward step corrects each state by the next smoothed state’s deviation from its prediction, through the gain C = P F ᵀ P̄⁻¹; smoothed covariances are never larger than filtered ones.
- The gain from lag decays geometrically: lag 5 (2.5 s) gave position error 0.069 against 0.117 for the filter, lag 20 only 0.067.
- Smoothing helps most at a surprise: after a reversal the velocity error fell from 0.84 to 0.45 m/s and the recovery from 5.9 to 2.5 steps with lag 5.
- Choose the lag where the error curve flattens, a few times the filter’s memory, and keep the filter for control.
References and further reading
Each source is marked free or paid. Free to read does not mean free to reuse: the course resources page lists every source with its licence.
- S. Särkkä and L. Svensson, Bayesian Filtering and Smoothing, 2nd edition, 2023 , the chapters on Bayesian smoothing and the RTS smoother (including fixed-lag and fixed-point forms). Free to read as the authors’ online PDF; the book is copyrighted.
- T. D. Barfoot, State Estimation for Robotics, 2nd edition, 2024 , chapter 3, which derives the smoother as the batch solution. Free to read as the author’s PDF; the book is copyrighted.
- H. E. Rauch, F. Tung and C. T. Striebel, “Maximum Likelihood Estimates of Linear Dynamic Systems”, AIAA Journal 3 (8), 1965. Paid journal article.
- B. D. O. Anderson and J. B. Moore, Optimal Filtering, Prentice-Hall, 1979, chapter 7 (smoothing, including the fixed-lag smoother). Paid book.
Knowledge check
Three questions. Write an answer, then reveal the explanation. Your answers stay in your browser.
Question 1
A filter has σt|t = 0.20 for a position, and a smoother brings it to σt|T = 0.12. What is the variance reduction, and what does it say about the information from the future readings?
Explanation
The variances are 0.04 and 0.0144. In information terms the filter has 25 per unit variance and the smoother 69.4: the future readings added 44.4, about 1.8 times what the past held. The reduction is 64% of the variance. It can never be negative: the smoothed covariance is never larger than the filtered one.
Question 2
Why is a fixed-lag smoother with lag 20 not noticeably better than one with lag 10 in the constant-velocity experiment?
Explanation
The correction passed back from a later step is multiplied by the smoother gain at every step it travels, and the gain matrix is a contraction (its eigenvalues have modulus 0.81 in the steady state), so the correction from a reading n steps ahead shrinks like 0.81^n: 0.12 at ten steps and 0.015 at twenty. By then the readings tell the smoother nothing about step t that the closer ones did not already. The error curve is flat beyond the filter’s memory, which is a few steps for this model.
Question 3
A robot reverses suddenly. Why does the smoother with lag 5 still need 2.5 steps to get within 0.5 m/s of the truth rather than recognising the reversal at once, and what would make it react faster?
Explanation
The model says the velocity is nearly constant (low process noise), so the smoother treats the first readings that disagree with it as probably noise and needs several consistent readings to move the velocity estimate. Lag lets it use the readings after the reversal, which is why it recovers faster than the filter, but the model’s stiffness still sets how many are needed. A larger process noise makes the model less stubborn (at the price of noisier estimates in steady motion), and a model that includes manoeuvres (a switching or interacting-multiple-model filter) reacts faster still.
What’s next
The last lesson of the course goes from estimating to deciding: a POMDP is the problem of choosing actions when all you have is a belief, and it closes the loop from this module to control.
Related content
Nothing below is required to finish this lesson.
- BeforeM12-T2: The Error-State Kalman Filter
Separate a nominal state from a small error state, write the predict, update, inject and reset steps, and say why inertial navigation uses them.
Other courses on this site treat neighbouring topics from their own angle:
Get notified when the next lesson and new labs are released.
One email per new lesson or lab.