Part III: State Estimation and Classical Inference
Chapter 10: Nonlinear and Particle Filtering

Rao-Blackwellization

"I was told to sample a fifteen-dimensional state with a thousand particles. Instead I sampled the three dimensions that were genuinely hard and solved the other twelve exactly. The same thousand particles suddenly did the work of a million."

A Frugal AI Agent

Prerequisites

This section builds directly on the particle filter and importance sampling of Section 10.3 and the resampling and degeneracy discussion of Section 10.4. It reuses the linear-Gaussian Kalman update in closed form from Chapter 9, so you should be comfortable with the predict/update recursion and the covariance matrices \(\mathbf{Q}\) and \(\mathbf{R}\). The probability tools (conditional densities, marginalization, the law of total expectation) come from Chapter 4. The core idea, that a mixed state splits into an "easy" conditionally linear part and a "hard" nonlinear part, echoes the state-augmentation habit introduced in Chapter 9.

Why marginalize when you could sample?

A particle filter pays an exponential price for dimension: the number of particles needed to keep the effective sample size healthy grows roughly like the volume of the state space you are exploring. Many real estimation problems, though, are only partly nasty. In a robot's map, the vehicle pose is fiercely nonlinear but, given the pose, each landmark's position is a plain linear-Gaussian estimate. In a target tracker with an unknown maneuver mode, the mode is discrete and awkward but, conditioned on the mode sequence, the kinematics are a textbook Kalman filter. The core idea in one line: never sample what you can solve exactly. You Monte-Carlo only the truly hard sub-state and attach an exact analytic filter to each particle for the rest. The payoff is a variance reduction guaranteed by a classical theorem, which in practice means you replace a million particles with a thousand and lose nothing.

The theorem behind the trick

What Rao-Blackwellization is, at root, is a variance-reduction identity from statistics. The Rao-Blackwell theorem says that if you have any estimator \(\hat{g}\) of a quantity, and \(T\) is a sufficient statistic, then conditioning on \(T\) can only help: the conditional estimator \(\mathbb{E}[\hat{g}\mid T]\) has variance no larger than \(\hat{g}\) itself. In symbols,

$$\operatorname{Var}\big(\mathbb{E}[\hat{g}\mid T]\big) \le \operatorname{Var}(\hat{g}),$$

with equality only when \(\hat{g}\) was already a function of \(T\); the gap comes from the law of total variance, every bit explained away by conditioning is variance you no longer pay for. Why this matters for filtering is that Monte-Carlo sampling is a high-variance estimator, and any state component we can handle analytically plays the role of "conditioning it away": instead of letting particles thrash around a dimension with a closed-form answer, we collapse that dimension into an exact conditional density carried alongside each particle.

Splitting the state: sample this, solve that

How you apply it is to partition the state \(\mathbf{x}_k\) into two blocks:

$$\mathbf{x}_k = \big(\mathbf{n}_k,\ \mathbf{l}_k\big),$$

where \(\mathbf{n}_k\) is the nonlinear (or discrete, or otherwise intractable) part and \(\mathbf{l}_k\) is a part that is conditionally linear-Gaussian: given the whole trajectory \(\mathbf{n}_{0:k}\) of the hard part, the dynamics and measurements of \(\mathbf{l}_k\) are linear with Gaussian noise. The joint posterior then factors exactly:

$$p(\mathbf{n}_{0:k},\, \mathbf{l}_k \mid \mathbf{z}_{1:k}) \;=\; \underbrace{p(\mathbf{n}_{0:k}\mid \mathbf{z}_{1:k})}_{\text{particle filter}} \;\cdot\; \underbrace{p(\mathbf{l}_k \mid \mathbf{n}_{0:k},\, \mathbf{z}_{1:k})}_{\text{Kalman filter, exact}}.$$

The first factor is approximated by particles over the hard trajectory, exactly as in Section 10.3. The second factor is a Gaussian, \(\mathcal{N}(\boldsymbol{\mu}_k^{(i)}, \boldsymbol{\Sigma}_k^{(i)})\), one per particle \(i\), maintained in closed form by a Kalman filter conditioned on that particle's sampled history. Each particle therefore carries not just a point \(\mathbf{n}_k^{(i)}\) but a small mean vector and covariance matrix for the linear part. This construction is the Rao-Blackwellized particle filter (RBPF), also called the marginalized particle filter.

A particle is now a hypothesis plus a Kalman filter

The mental shift is the whole section. In a vanilla particle filter, particle \(i\) is a guess at the entire state; in an RBPF, particle \(i\) guesses only the hard part and drags a full Gaussian belief about the easy part behind it. The weight update still uses the measurement likelihood, but that likelihood is now computed after marginalizing out \(\mathbf{l}_k\), which is exactly the Kalman filter's one-step predictive likelihood (the innovation term). Because the linear dimensions never contribute sampling noise, all your particles' diversity is spent where it is actually needed: the Rao-Blackwell theorem cashing out as fewer particles for the same accuracy.

The RBPF recursion, one step

Each cycle interleaves a sampling step for the hard part with an exact Kalman step for the easy part. For particle \(i\) at time \(k\):

  1. Propagate the hard part. Draw \(\mathbf{n}_k^{(i)} \sim q(\mathbf{n}_k \mid \mathbf{n}_{k-1}^{(i)}, \mathbf{z}_k)\) from a proposal, as usual.
  2. Kalman-update the easy part. Using the sampled \(\mathbf{n}_k^{(i)}\) to fix the otherwise-linear model matrices, run one predict/update of a Kalman filter to move \((\boldsymbol{\mu}_{k-1}^{(i)}, \boldsymbol{\Sigma}_{k-1}^{(i)})\) to \((\boldsymbol{\mu}_k^{(i)}, \boldsymbol{\Sigma}_k^{(i)})\).
  3. Weight by the marginal likelihood. Multiply the weight by the Gaussian innovation likelihood \(p(\mathbf{z}_k \mid \mathbf{n}_{0:k}^{(i)}, \mathbf{z}_{1:k-1})\) that the Kalman update produces for free, then normalize.
  4. Resample the particles (each carrying its own \((\boldsymbol{\mu}, \boldsymbol{\Sigma})\)) when the effective sample size drops, exactly the diagnostic from Section 10.4.

What can break the clean split is feedback: the linear block's own state sometimes feeds into the hard part's transition, not just the other way around. Why that matters is that the factorization above assumed \(\mathbf{l}_k\) is conditionally linear-Gaussian given \(\mathbf{n}_{0:k}\) alone; if the hard part's dynamics also depend on the sampled \(\mathbf{l}_k\), that assumption silently fails and the Kalman recursion stops being exact. How you keep it valid is to let the proposal for \(\mathbf{n}_k^{(i)}\) depend only on the previous Kalman mean \(\boldsymbol{\mu}_{k-1}^{(i)}\), never on a sampled draw of \(\mathbf{l}_k\) itself; when this discipline slips, for instance wiring the true linear state into the hard-part proposal to "help" tracking, the Rao-Blackwell variance-reduction guarantee no longer holds.

Misconception: one Kalman filter for the whole particle set

It is tempting to picture the RBPF as "a particle filter over the hard part, plus a Kalman filter on the side." That is wrong: every particle owns its own independent \((\boldsymbol{\mu}_k^{(i)}, \boldsymbol{\Sigma}_k^{(i)})\), because each has conditioned on a different sampled trajectory \(\mathbf{n}_{0:k}^{(i)}\) and therefore sees a different linear-Gaussian posterior. With \(N\) particles you run \(N\) separate Kalman filters in parallel, not one filter shared by all; a shared or averaged \((\boldsymbol{\mu}, \boldsymbol{\Sigma})\) collapses the very diversity that makes the marginalization exact.

FastSLAM on a warehouse robot

Consider an autonomous forklift building a map of a warehouse from wheel odometry and a lidar that detects rack legs as landmarks. The full state is the robot pose plus the 2D position of every one of, say, three hundred landmarks: a state of over six hundred dimensions. Sampling that directly is hopeless. The insight behind FastSLAM, a landmark RBPF, is that conditioned on the robot's path, the landmarks are mutually independent and each is a tiny 2D linear-Gaussian estimate. So the filter samples only the three-dimensional robot pose, and each particle owns three hundred independent 2 × 2 Kalman filters, one per landmark: a six-hundred-dimensional problem collapses to a three-dimensional sampling problem with an analytic tail. This is why RBPF-based SLAM ran in real time on modest robot CPUs years before the factor-graph methods of Chapter 11 and the full spatial-AI stacks of Chapter 52 became practical.

A minimal marginalized filter

The code below sketches the loop for a mixed model where a discrete mode (the hard part) selects among linear-Gaussian dynamics (the easy part). Each particle holds a mode plus a Kalman mean and covariance; the weight uses the Gaussian innovation likelihood. It is deliberately compact to show the two-layer structure rather than a production tracker.

import numpy as np

def rbpf_step(particles, z, models, resample_thresh=0.5):
    # particles: list of dicts with keys mode, mu, Sigma, w
    for p in particles:
        # 1. propagate the HARD part (discrete mode via a Markov transition)
        p["mode"] = sample_mode_transition(p["mode"], models)
        F, H, Q, R = models[p["mode"]]          # mode fixes the linear model

        # 2. exact Kalman predict + update for the EASY part
        mu_pred = F @ p["mu"]
        S_pred  = F @ p["Sigma"] @ F.T + Q
        y   = z - H @ mu_pred                    # innovation
        S   = H @ S_pred @ H.T + R               # innovation covariance
        K   = S_pred @ H.T @ np.linalg.inv(S)    # Kalman gain
        p["mu"]    = mu_pred + K @ y
        p["Sigma"] = S_pred - K @ H @ S_pred

        # 3. weight by the marginal (Gaussian) likelihood of this measurement
        d = y.shape[0]
        loglik = -0.5 * (y @ np.linalg.inv(S) @ y
                         + np.log(np.linalg.det(S)) + d*np.log(2*np.pi))
        p["w"] *= np.exp(loglik)

    # normalize and (optionally) resample on low effective sample size
    W = np.array([p["w"] for p in particles]); W /= W.sum()
    for p, w in zip(particles, W): p["w"] = w
    n_eff = 1.0 / np.sum(W**2)
    if n_eff < resample_thresh * len(particles):
        particles = systematic_resample(particles, W)
    return particles
One step of a Rao-Blackwellized particle filter for a switching linear-Gaussian model: the discrete mode is sampled, while mu and Sigma are updated exactly by the embedded Kalman filter, and the weight uses the innovation likelihood. Helpers sample_mode_transition and systematic_resample are the routines from Sections 10.3 and 10.4.

The code makes the division of labor concrete: the only stochastic line is the mode draw; every other line is deterministic linear algebra. That is the Rao-Blackwell theorem operationalized, sampling confined to the one variable that has no closed form.

The Right Tool: filterpy and particles

You rarely hand-roll the Kalman inner loop. In Python, filterpy supplies a tested KalmanFilter object you embed per particle, turning the twelve-line predict/update above into three calls (kf.predict(), kf.update(z), read kf.log_likelihood). The dedicated particles library ships a Rao_Blackwellized mixin and systematic resampling, cutting a from-scratch RBPF of roughly 120 lines down to about 25, and it handles fragile numerics (log-domain weights, Cholesky covariance updates) that otherwise diverge silently by hand. Reach for from-scratch code only to learn the mechanics; ship the library.

When to Rao-Blackwellize, and when not to

When the technique pays off is precisely when a clean conditional-linear substructure exists: SLAM (map given path), multi-target tracking with unknown data association or maneuver mode, positioning where a sensor bias or clock offset is linear given the trajectory, and any problem where a large slab of the state is a nuisance parameter you only need to integrate out. In these cases the variance reduction is dramatic and free. When it does not help is when almost the entire state is genuinely nonlinear, leaving no linear block worth marginalizing, or when the per-particle Kalman filter is itself expensive (a large \(\mathbf{l}_k\) means an \(O(d_l^3)\) covariance update per particle per step). The trade is arithmetic per particle bought with statistical efficiency: small linear blocks, as in FastSLAM's independent landmarks, make it overwhelmingly favorable, while a dense high-dimensional Gaussian can erase the gain. The estimator-selection guidance of Section 10.7 returns to this budget explicitly.

Where the idea lives now

Marginalization-of-the-tractable-part is far from a historical curiosity. FastSLAM 2.0 remains a reference baseline in robotics, and the same factorization now drives learned filters directly: differentiable RBPFs (2023-2024) back-propagate through the Kalman block while training only the nonlinear proposal network, and Gaussian-splatting SLAM systems such as MonoGS and Gaussian-SLAM (2024) keep an explicit Gaussian per landmark while sampling only camera-pose hypotheses, an unmistakably Rao-Blackwellized design. The linear-time state-space sequence models of Chapter 16, S4, S5, and Mamba, inherit the same instinct: solve the linear recurrence exactly, spend learned capacity only on what is not linear.

Exercise

Take a constant-velocity target whose acceleration switches between "cruise" and "maneuver" modes (a two-state Markov chain). The position and velocity are linear-Gaussian given the mode sequence. (a) Identify \(\mathbf{n}_k\) and \(\mathbf{l}_k\). (b) Implement both a plain particle filter over the full 5D state (position, velocity, mode) and an RBPF that samples only the mode. (c) Sweep the particle count from 20 to 5000 and plot RMSE versus count for both. Confirm empirically that the RBPF reaches a target RMSE with roughly an order of magnitude fewer particles, and explain the gap using the law of total variance.

Self-check

  1. Why does conditioning on the sampled trajectory make the linear block's posterior exactly Gaussian, and what would break that exactness?
  2. In an RBPF, what quantity plays the role of the importance weight's measurement likelihood, and where does it come from at no extra cost?
  3. Give one problem where Rao-Blackwellization offers no benefit, and state precisely why.

What's Next

In Section 10.6, we confront the assumption every filter in this chapter has quietly relied on: that the noise is well-behaved and the model is right. We turn to robust and adaptive filtering, handling heavy-tailed outliers, gross sensor faults, and noise statistics that drift while the system runs.