"I do not remember every measurement I have ever seen. I remember exactly one distribution, and I update it politely each time you speak."
A Well-Adjusted AI Agent
The Big Picture
Section 9.1 gave you the two ingredients of a state-space model: a transition model that says how the hidden state drifts from one instant to the next, and an observation model that says how a noisy sensor reading depends on that state. This section is the engine that turns those two models into a running estimate. The central trick is recursion. Instead of re-deriving your best guess from the entire measurement history every time a new sample lands, you carry forward a single object, the posterior distribution over the current state, and revise it in place. That revision is always the same two-beat cycle: predict the state forward through the transition model, then correct it against the new measurement through Bayes' rule. Every filter in this chapter and the next, the Kalman filter, the extended and unscented variants, the particle filter, is a special case of this one recursion. Get the recursion right in the abstract and the rest of Part III is just choosing how to represent the distribution.
This section assumes you are comfortable with Bayes' rule, conditional probability, and the language of priors, likelihoods, and posteriors from Chapter 4, and with the hidden-state and observation-model notation introduced in Section 9.1. We stay representation-agnostic here: the closed-form Gaussian version arrives in Section 9.3, and the sample-based version in Chapter 10.
The belief, and why one number of it is enough
Write \(x_t\) for the hidden state at time \(t\) and \(z_{1:t} = \{z_1, \dots, z_t\}\) for every measurement seen so far. The quantity we actually want is the filtering distribution, also called the belief:
$$\mathrm{bel}(x_t) \;=\; p(x_t \mid z_{1:t}).$$This is a full distribution, not a point estimate. It answers "where do I think the state is, and how sure am I?" in one object. A naive way to compute it would re-run inference over the whole growing history at every step, an amount of work that increases without bound as the sensor keeps streaming. Recursive estimation refuses to pay that bill. It exploits the Markov property of the state-space model: given \(x_{t-1}\), the next state \(x_t\) is independent of everything earlier, and given \(x_t\), the measurement \(z_t\) is independent of everything earlier. Under those two assumptions the previous belief \(\mathrm{bel}(x_{t-1})\) is a sufficient statistic for the entire past. You never need the raw history again. That single fact is what makes constant-time, constant-memory estimation on a live stream possible.
Key Insight
Recursion is not an optimization bolted onto Bayesian estimation; it is a consequence of the model. The Markov assumptions make yesterday's posterior a complete summary of yesterday's evidence, so today's update reads only the previous belief and the current measurement. Cost per step is flat regardless of how long the system has been running. The price is that the assumptions must hold: if the state has hidden long-range memory the model does not capture, the recursion will confidently forget something it should have kept.
Predict: pushing the belief forward
The cycle begins by asking where the state will be before looking at the new measurement. We propagate the previous posterior through the transition model \(p(x_t \mid x_{t-1})\), summing over every place the state could have come from. This is the Chapman-Kolmogorov equation, the time update:
$$\overline{\mathrm{bel}}(x_t) \;=\; \int p(x_t \mid x_{t-1})\; \mathrm{bel}(x_{t-1})\; dx_{t-1}.$$The bar denotes the predicted belief, our estimate after motion but before correction. Intuitively, prediction always spreads the distribution out: process noise and dynamic uncertainty add variance, so the predicted belief is broader and less confident than the posterior it came from. A tracker that has not received a measurement for a while grows steadily more uncertain, exactly as it should. When the transition is discrete the integral becomes a sum; when it is linear-Gaussian it becomes the matrix propagation of Section 9.3.
Correct: folding in the measurement
Now the sensor speaks. We sharpen the predicted belief using the new reading \(z_t\) and the observation model \(p(z_t \mid x_t)\), the likelihood. Bayes' rule does the folding:
$$\mathrm{bel}(x_t) \;=\; \eta\; p(z_t \mid x_t)\; \overline{\mathrm{bel}}(x_t), \qquad \eta = \frac{1}{\int p(z_t \mid x_t)\, \overline{\mathrm{bel}}(x_t)\, dx_t}.$$Read it as a pointwise product: for each candidate state, multiply how plausible that state was after prediction by how well it explains the measurement, then renormalize with \(\eta\) so the result integrates to one. States the sensor rules out get suppressed; states consistent with the reading get reinforced. The measurement update always concentrates the belief, the mirror image of prediction. The whole filter is these two operations alternating forever: predict widens, correct narrows, and the balance between them is the estimator's entire personality. Tune it in Section 9.4.
Practical Example: a warehouse robot that knows where it is not
An autonomous forklift navigates a warehouse aisle lined with barcode markers at known positions. Its wheel odometry is the transition model: each control command predicts a forward displacement, but wheel slip on a dusty floor injects process noise, so after a few meters of dead reckoning the belief over its position has smeared across most of the aisle. Then a downward camera reads a marker. The observation model says "if I am truly at position \(x\), a marker at 12.0 m produces this reading with such-and-such noise," and the correction step collapses the smeared belief onto a tight peak near 12.0 m. Critically, the filter does not throw away its uncertainty between markers; it grows it faithfully, so the motion planner can slow down when the belief is wide and speed up when a fresh marker has just sharpened it. That honest uncertainty is what later feeds probabilistic fusion in Chapter 49.
The recursion, made concrete
The equations are easiest to trust once you watch them run on a distribution you can print. The classic teaching case is a discrete histogram filter: chop the state space into cells, store the belief as an array of probabilities, and implement predict and correct as array operations. Below, a robot lives on a 1-D loop of 20 cells, moves one cell per step with occasional slip, and carries a noisy sensor that reports "landmark" or "no landmark" at known positions.
import numpy as np
N = 20
landmarks = {3, 9, 14} # cells that emit "landmark"
bel = np.ones(N) / N # start fully uncertain
def predict(bel, p_slip=0.1): # move +1 cell, sometimes slip
moved = np.roll(bel, 1) # intended one-cell advance
slipped = np.roll(bel, 2) # over-shoot by an extra cell
return (1 - p_slip) * moved + p_slip * slipped
def correct(bel, saw_landmark, hit=0.9, miss=0.1):
like = np.array([hit if (c in landmarks) == saw_landmark else miss
for c in range(N)])
post = like * bel # Bayes: likelihood x prior
return post / post.sum() # renormalize (this is eta)
measurements = [False, True, False, False, True]
for z in measurements:
bel = predict(bel) # Chapman-Kolmogorov time update
bel = correct(bel, z) # Bayes measurement update
print(f"seen={z!s:5} MAP cell={bel.argmax():2d} "
f"peak={bel.max():.2f}")
predict is the Chapman-Kolmogorov sum (a shift plus a slip term); correct multiplies by the measurement likelihood and renormalizes. Watch the printed peak fall during each predict (belief spreads) and rise after each correct (belief sharpens): the two-beat cycle of this whole chapter in twenty lines.The array bel is the only state the loop keeps between iterations, the recursion in the flesh. Nothing about this code assumes a Gaussian, a linear model, or even a smooth state space, which is exactly why the histogram filter is the honest picture of what "recursive Bayesian estimation" means before any specialization narrows it.
Right Tool: FilterPy for the Gaussian specialization
The histogram filter above is deliberately hand-rolled to expose the mechanics. In production you rarely represent the belief as a raw grid; you commit to the linear-Gaussian case and let a library carry the algebra. filterpy.kalman.KalmanFilter reduces the entire predict-correct recursion, the covariance propagation, the Kalman gain, the update, to about five lines of setup plus a two-line loop, replacing roughly forty lines of matrix bookkeeping you would otherwise write and debug by hand. You supply the transition matrix, the measurement matrix, and the two noise covariances; the library runs the recursion. We build exactly that in Section 9.3.
When the belief has no closed form
The recursion is exact and universal, but the two integrals, the Chapman-Kolmogorov sum and the normalizer \(\eta\), are only tractable in special cases. If the transition and observation models are linear with Gaussian noise, every belief stays Gaussian and the integrals collapse to the finite matrix updates of the Kalman filter. If the state space is small and discrete, the histogram filter above computes them by brute force. Outside those cases, for nonlinear dynamics or non-Gaussian, multi-modal beliefs, the integrals have no analytic answer and the grid becomes exponentially expensive as dimensions grow. That is the entire motivation for Chapter 10: the extended and unscented Kalman filters linearize the models to keep the Gaussian machinery, while the particle filter represents the belief with a cloud of weighted samples and approximates both integrals by Monte Carlo. Each is a different answer to the same question posed here: how do I actually carry this belief forward when I cannot integrate it in closed form?
Exercise
Extend the histogram-filter code. (1) Print the full belief array after the predict step and again after the correct step of one iteration, and quantify how much prediction flattens the distribution and how much correction sharpens it (use the entropy \(-\sum_c b_c \log b_c\) as your measure). (2) Set p_slip = 0.0 and then p_slip = 0.4; explain how a noisier transition model changes the peak height the filter can reach after a landmark sighting. (3) Feed the filter a contradictory sequence of measurements (alternating True/False at a non-landmark cell) and describe, in terms of the two updates, why the belief never settles.
Self-Check
- Why does the Markov property let a recursive filter discard the raw measurement history, and what exactly plays the role of "everything the filter remembers"?
- One of the two updates always spreads the belief out and the other always concentrates it. Which is which, and which model, transition or observation, drives each?
- The measurement update includes a normalizer \(\eta\). What goes wrong if you skip it, and what does its value tell you about how surprising the latest measurement was?
What's Next
In Section 9.3, we commit the abstract recursion to its most famous special case. Assume linear transition and observation models with Gaussian noise, and the belief stays Gaussian at every step, collapsing the two integrals of this section into a handful of matrix operations: the predict-correct cycle you just met, now with the Kalman gain deciding exactly how much to trust each new measurement.