Probability for Robotics · Theory · M11
M11-T2 — MAP Estimation and Weighted Least Squares
A prior is one more term in the least-squares problem. The Kalman filter solves it one step at a time.
Maximum likelihood trusts the readings alone. When something is known beforehand (where the robot started, how it can move) it enters as a prior, and the best estimate becomes the maximum a posteriori (MAP) estimate. This lesson shows that this is least squares with extra terms, tests when the prior helps and when it hurts, and proves by experiment the statement that unifies Modules 6 to 8 and 11: the Kalman filter is the MAP estimate computed recursively, and the Rauch–Tung–Striebel smoother is the same estimate for the whole path.
Learning objectives
After this lesson, you should be able to:
- Write the MAP estimate as the minimiser of a negative log-posterior: likelihood terms plus prior terms.
- Show how a Gaussian prior acts as regularisation, and predict when MAP beats maximum likelihood and when it does not.
- Formulate a filtering problem (prior, motion model, measurements) as one weighted least-squares problem over the whole path.
- State the equivalences: filter = last step of the batch MAP; smoother = the whole batch MAP.
The intuition
Maximum likelihood asks: which state makes the readings most probable? MAP asks: which state is most probable given the readings and what I knew before? By Bayes' rule the posterior is likelihood times prior, so the log-posterior is the log-likelihood plus the log-prior. In least-squares terms a Gaussian prior is just one more squared residual, , pulling the estimate towards what we expected, with a force that depends on how sure we were.
The left panel quantifies the pull. When the quantity really comes from the prior, MAP wins: with one reading its error is 0.70 against 0.995 for ML, a 30% reduction; with three, 0.51 against 0.585; with ten the advantage almost disappears (0.30 against 0.31), because ten readings outweigh the prior. When the prior is wrong (the truth is three prior standard deviations away) MAP loses: 1.66 against 0.995 with one reading, and still 0.40 against 0.31 with ten. The prior is a bet: it pays when it is right and costs when it is wrong, and the more readings there are, the less either matters.
The right panel is the statement that ties the modules together. Take a robot with a constant-velocity model and position readings for 20 steps. The Kalman filter processes them one at a time and its velocity uncertainty falls from 0.90 to 0.073 m/s. The smoother, which uses every reading to estimate every step, is much better in the middle (0.039) and better at the start (0.073 at step 1, where the filter has 0.90), because readings from the future say how fast the robot was going at the beginning. At the last step the two coincide. Solved as one large least-squares problem over all 40 unknowns, the MAP path is identical to the smoother's, to the last digit printed.
The batch MAP path is the smoother. The filter is the same problem, solved one step at a time, and reporting only the newest state: its answer equals the batch answer at the last step and no other.
Definitions
- Prior
- What is believed before the readings. For a Gaussian prior .
- Posterior
- .
- MAP estimate
- .
- Regularisation
- A term in the objective that penalises solutions far from a preferred one. A Gaussian prior is a quadratic penalty (ridge).
- Batch estimation
- Estimating all the states of a trajectory together from all the readings.
- Smoother
- The posterior of every state given all readings, past and future. For linear-Gaussian models, the RTS smoother computes it by a backward pass.
Derivation: MAP from Bayes’ rule, shrinkage, and filter = recursive MAP
MAP is least squares plus a prior term
Bayes’ rule. The denominator does not depend on θ.
With Gaussian likelihood and Gaussian prior, both negative logs are quadratic. The sum is the MAP objective.
The Gauss–Newton step for the MAP problem. The prior adds its information to the information matrix and a restoring force to the right-hand side.
Shrinkage
For a mean with a prior and readings of variance , the MAP is the sample mean multiplied by : shrunk towards the prior mean. Its error has two parts.
Write the estimate in terms of the true value . The first term is the reduced noise of the sample mean, the second the bias from shrinking.
The mean squared error for a given true μ: variance plus bias squared.
Averaged over the prior the MAP error is always below that of ML: with σ = σ₀ = 1, n = 1 it is 0.5 against 1 (rms 0.71 against 1.0: the 0.703 measured).
The bias term grows with the square of the distance of the truth from the prior mean. A wrong prior costs more than a right one saves.
Filter = last step of the batch MAP, smoother = all of it
The MAP objective for the path is a sum of terms, each involving at most two consecutive states: a chain. The normal equations are block-tridiagonal. Minimising over all states except the last by eliminating them one at a time from the oldest (a forward pass) leaves a quadratic in alone, whose minimiser and curvature are the filter's mean and information at : this elimination is the Kalman filter, and it needs no future data. Back-substituting from to (a backward pass) gives every other state of the batch solution: this is the RTS smoother.
The marginalisation of the earlier states leaves exactly the Kalman filter posterior at T (Gaussian). Marginalising a Gaussian is the Schur complement, treated in lesson 3.
The RTS backward recursion: each state is corrected by how much the next one moved relative to its prediction.
Filtering, smoothing and batch estimation are one problem at three levels of use. The filter is cheap and causal; the smoother and the batch are better because they use the future.
A worked example
Two programs.
- ML against MAP. A quantity with prior N(0, 1) and readings with noise 1; 20 000 trials per row. Prior right: the rms error of ML and MAP is 0.995 and 0.703 for n = 1, 0.585 and 0.508 for n = 3, 0.313 and 0.299 for n = 10. Prior wrong (true value from N(3, 1)): 0.995 and 1.655 for n = 1, 0.585 and 0.910 for n = 3, 0.313 and 0.404 for n = 10.
- Filter, smoother and batch. The constant-velocity robot of Module 7 (0.5 s steps, 20 steps, position readings with noise 0.2 m), a prior of identity covariance on (0, 0). The batch problem has 40 unknowns, assembled block by block: a term for the prior, 19 motion terms and 20 reading terms. Its solution matches the Kalman filter at the last step to 9 decimals and the RTS smoother at every step to 9 decimals; it differs from the filter at earlier steps, by up to 0.213 m in position and 0.698 m/s in velocity.
- What the future adds. The filter's velocity at step 1 is 0.28 m/s (the truth is about 1.0) with a standard deviation of 0.898; the smoother has 0.979 with a standard deviation of 0.073. In the middle of the run the smoother's velocity standard deviation, 0.039, is nearly half the filter's 0.073.
import math
from robotprob import Rng, mean, solve, inverse, transpose, matmul, matvec, madd, mscale, kf_predict, kf_update, rts_smoother
# 1. ML against MAP for a quantity with a prior N(0, 1), from n readings with noise std 1
print('the true value is drawn from n rms error ML rms error MAP')
for label, draw in (('the prior N(0, 1) ', lambda r: r.gauss(0.0, 1.0)), ('far from it N(3, 1)', lambda r: r.gauss(3.0, 1.0))):
for n in (1, 3, 10):
rng = Rng(100 + n)
e_ml, e_map = [], []
for _ in range(20000):
truth = draw(rng)
z = [truth + rng.gauss(0.0, 1.0) for _ in range(n)]
ml = sum(z) / n
mp = sum(z) / (n + 1.0) # prior precision 1, data precision n: the MAP is the sum divided by (n + 1)
e_ml.append((ml - truth) ** 2); e_map.append((mp - truth) ** 2)
print(label.ljust(24), str(n).rjust(3), str(round(math.sqrt(mean(e_ml)), 3)).rjust(12), str(round(math.sqrt(mean(e_map)), 3)).rjust(14))
# 2. the Kalman filter, the smoother and one batch MAP problem over the whole path give the same answers
dt, sq, r_, T = 0.5, 0.05, 0.04, 20
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_]]
rng = Rng(5)
pos, vel = 0.0, 1.0
zs = []
for t in range(T):
vel += rng.gauss(0.0, sq * math.sqrt(dt)); pos += vel * dt
zs.append(pos + rng.gauss(0.0, math.sqrt(r_)))
x0, P0 = [0.0, 0.0], [[1.0, 0.0], [0.0, 1.0]]
xs, Ps, xp, Pp = [], [], [], []
x, P = list(x0), P0
for z in zs:
x, P = kf_predict(x, P, F, Q); xp.append(x); Pp.append(P)
x, P, y, S, K = kf_update(x, P, [z], H, R)
xs.append(x); Ps.append(P)
sm_x, sm_P = rts_smoother(xs, Ps, F, Q)
# the same problem as one least squares problem over the 2T unknowns x_1 ... x_T: a term for the prior, one for every motion step, one for every reading
n = 2 * T
A = [[0.0] * n for _ in range(n)]; b = [0.0] * n
def add_block(i, j, M): # add the 2x2 block M at block row i, block column j
for p in range(2):
for c in range(2): A[2 * i + p][2 * j + c] += M[p][c]
Qinv = inverse(Q)
FT = transpose(F)
C1 = madd(Q, matmul(matmul(F, P0), FT)) # x_1 given the prior on x_0: covariance Q + F P0 F^T
C1inv = inverse(C1)
add_block(0, 0, C1inv)
m0 = matvec(F, x0)
for p, v in enumerate(matvec(C1inv, m0)): b[p] += v
for t in range(T - 1): # motion terms (x_{t+1} - F x_t)^T Q^-1 (x_{t+1} - F x_t)
add_block(t + 1, t + 1, Qinv)
add_block(t, t, matmul(matmul(FT, Qinv), F))
add_block(t + 1, t, mscale(matmul(Qinv, F), -1.0))
add_block(t, t + 1, mscale(matmul(FT, Qinv), -1.0))
for t in range(T): # reading terms (z - x_pos)^2 / r
A[2 * t][2 * t] += 1.0 / r_; b[2 * t] += zs[t] / r_
sol = solve(A, b)
batch = [[sol[2 * t], sol[2 * t + 1]] for t in range(T)]
mx = lambda U, V, k: max(abs(u[k] - v[k]) for u, v in zip(U, V))
print('largest difference between the batch MAP path and the Kalman filter, positions and velocities, steps 1-20:', round(mx(batch, xs, 0), 3), round(mx(batch, xs, 1), 3))
print('last step only: batch vs filter', round(abs(batch[-1][0] - xs[-1][0]), 9), round(abs(batch[-1][1] - xs[-1][1]), 9))
print('largest difference between the batch MAP path and the RTS smoother:', round(mx(batch, sm_x, 0), 9), round(mx(batch, sm_x, 1), 9))
print('velocity standard deviation after each step 1..20')
print(' filter :', [round(math.sqrt(P[1][1]), 3) for P in Ps])
print(' smoother:', [round(math.sqrt(P[1][1]), 3) for P in sm_P])
print('velocity estimate at step 1 (the true velocity is about 1.0 m/s): filter', round(xs[0][1], 3), ' smoother', round(sm_x[0][1], 3))the true value is drawn from n rms error ML rms error MAP the prior N(0, 1) 1 0.995 0.703 the prior N(0, 1) 3 0.585 0.508 the prior N(0, 1) 10 0.313 0.299 far from it N(3, 1) 1 0.995 1.655 far from it N(3, 1) 3 0.585 0.91 far from it N(3, 1) 10 0.313 0.404 largest difference between the batch MAP path and the Kalman filter, positions and velocities, steps 1-20: 0.213 0.698 last step only: batch vs filter 0.0 0.0 largest difference between the batch MAP path and the RTS smoother: 0.0 0.0 velocity standard deviation after each step 1..20 filter : [0.898, 0.463, 0.265, 0.176, 0.13, 0.105, 0.091, 0.082, 0.078, 0.075, 0.074, 0.074, 0.073, 0.073, 0.073, 0.073, 0.073, 0.073, 0.073, 0.073] smoother: [0.073, 0.064, 0.057, 0.05, 0.046, 0.042, 0.04, 0.04, 0.039, 0.039, 0.039, 0.039, 0.04, 0.041, 0.042, 0.046, 0.051, 0.057, 0.065, 0.073] velocity estimate at step 1 (the true velocity is about 1.0 m/s): filter 0.28 smoother 0.979
rts_smoother gives the smoothed states and covariances. The batch problem is assembled as a 40 × 40 matrix from blocks: add_block(i, j, M) adds a 2 × 2 block at block row i and block column j, and solve returns the whole path at once.In robotics
Priors in robotics
- Initial pose: the prior on x₀ anchors the problem; without it a SLAM problem is gauge-free (lesson 4).
- Motion model: each odometry measurement is a prior-like constraint between consecutive poses.
- Map priors: a known floor plan, smoothness of a surface, gravity direction for an IMU.
- Regularisation in calibration: a weak prior on parameters that the data constrain poorly stabilises the solution.
When to use which
| Need | Use |
|---|---|
| Estimate now, with a bounded cost per step, for control | Filter (EKF, UKF, particles) |
| Best estimate of the whole trajectory, offline (mapping, calibration) | Batch MAP / smoother |
| Recent history improved with future data, online | Fixed-lag smoother or sliding-window optimisation |
| Nonlinear models with many loop closures | Nonlinear least squares on a factor graph (lessons 3 and 4) |
Choosing priors responsibly
A prior is justified when it comes from knowledge (a datasheet, a calibration, physics). A prior used just to make a problem numerically solvable should be weak, so that it does not bias the answer, and the effect of changing it should be tested, as the right-and-wrong experiment above does: if the answer moves a lot when the prior moves a little, the data are not saying much.
Cost
The batch problem has a block-tridiagonal structure and can be solved in time linear in the number of steps, not cubic, by exactly the forward and backward pass described above. A dense 40 × 40 solve as in the program is for illustration; real solvers exploit the sparsity (lesson 4).
Common misconceptions
“MAP is more accurate than ML.”
Only if the prior is right. With the truth three prior standard deviations away MAP had 1.66 against 0.995. The prior is a bet whose payoff shrinks as readings accumulate.
“The Kalman filter is a different kind of algorithm from least squares.”
It is least squares: the filter is the batch MAP solved recursively, forgetting the past states after folding them into the current belief. The two agree at the last step to the printed precision.
“Smoothing needs a different model.”
It uses the same model and the same noises; it just uses the readings after time t as well. It is the posterior of every state given all readings.
“A flat prior means no prior.”
A prior with infinite variance means the term vanishes and the MAP equals the ML. A very wide but finite prior still biases slightly, and a flat prior over a bounded range still says the range is bounded.
Key takeaways
- MAP = ML plus a prior: minimise the weighted squared residuals plus (θ − μ₀)ᵀP₀⁻¹(θ − μ₀).
- A Gaussian prior shrinks the estimate towards the prior mean. Averaged over the prior it always helps (0.703 against 0.995 for one reading); with a wrong prior it hurts (1.655 against 0.995).
- Filtering as a batch problem: the prior on x₀, one term per motion step and one per reading; the Gauss–Newton matrix is block-tridiagonal.
- The Kalman filter equals the batch MAP at the last step, and the RTS smoother equals it at every step (9 decimals in the experiment).
- The smoother is much more certain than the filter wherever there are future readings: the velocity at step 1 had a standard deviation of 0.073 instead of 0.898.
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.
- T. D. Barfoot, State Estimation for Robotics, 2nd edition, 2024 , chapter 3, which derives the Kalman filter and the RTS smoother from the batch MAP problem for exactly this model. Free to read as the author’s PDF; the book is copyrighted.
- S. Särkkä and L. Svensson, Bayesian Filtering and Smoothing, 2nd edition, 2023 , the chapters on batch estimation, Kalman filtering and the RTS smoother. Free to read as the authors’ online PDF; the book is copyrighted.
- S. Thrun, W. Burgard and D. Fox, Probabilistic Robotics, MIT Press, 2005, section 3.2.4 (the information filter) and chapter 11 (the graph SLAM view of the same objective). Paid book.
- H. E. Rauch, F. Tung and C. T. Striebel, “Maximum Likelihood Estimates of Linear Dynamic Systems”, AIAA Journal 3 (8), 1965. Paid journal article.
Knowledge check
Three questions. Write an answer, then reveal the explanation. Your answers stay in your browser.
Question 1
A quantity has prior N(0, 1) and you take two readings with noise variance 1: 1.4 and 0.8. Give the ML and MAP estimates and the MAP variance.
Explanation
The sample mean (ML) is 1.1. The MAP estimate is the sum of the readings divided by n + 1 = 3: 2.2/3 = 0.733, shrunk towards the prior mean 0. The posterior variance is (n/σ² + 1/σ₀²)⁻¹ = (2 + 1)⁻¹ = 0.333 (standard deviation 0.577), against 0.5 for ML (0.707): the prior adds the information of one reading.
Question 2
Why can the Kalman filter at step 10 not equal the batch MAP of the first 10 readings at step 5, and what does equal it?
Explanation
The filter at step 5 has used only the first five readings, while the batch MAP at step 5 has used all ten, including the five that come after; the future readings change the estimate of step 5 (by up to 0.2 m in position in the experiment). What does equal the batch estimate of step 5 is the RTS smoother, which processes the filter results backwards from step 10. The filter at step 10 does equal the batch estimate of step 10, since there is nothing after it.
Question 3
You have a prior of N(0, 1) on a position but you are not sure it is correct. How would you test its influence, and what do the experiments suggest about the number of readings you need before it stops mattering?
Explanation
Run the estimate with the prior weakened (say variance 10 and 100) and see how much the answer moves; a large movement means the data are weak and the prior is doing the work. The experiments show the bias of a wrong prior fading with the number of readings: the extra rms error of MAP over ML was 0.66 with one reading, 0.33 with three and 0.09 with ten, so the prior (with unit variance) stops mattering at around ten readings. The more informative each reading is relative to the prior, the fewer are needed.
What’s next
The batch view scales to problems where states are not a chain: poses linked by loop closures, landmarks seen from many poses. The next lesson describes such problems as factor graphs and shows how to eliminate variables one at a time, which is marginalisation by the Schur complement.
Related content
Nothing below is required to finish this lesson.
- BeforeM11-T1: Maximum Likelihood Estimation
Write a likelihood function, maximise its logarithm, and derive the maximum likelihood estimates of a Gaussian mean and variance.
- LabM11-L1: Occupancy Grid and Pose Graph SLAM
The map of the lab has a doubled wall where the loop should close. Build the grid in log odds, find why it smears, and correct the trajectory with a pose graph before mapping again.
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.