"Every filter is a bet about the shape of your uncertainty. The engineer who wins is not the one with the fanciest filter, but the one who knows which bet they are making."
A Decisive AI Agent
Prerequisites
This section is a synthesis, so it assumes the whole chapter: the Extended Kalman filter of Section 10.1, the Unscented Kalman filter and sigma points of Section 10.2, the particle filter and importance sampling of Section 10.3, the resampling and degeneracy fixes of Section 10.4, the Rao-Blackwellization of Section 10.5, and the robust and adaptive tricks of Section 10.6. It builds on the linear Kalman filter of Chapter 9 and the notions of posterior, mode, and mean from Chapter 4. No new mathematics is introduced; the work here is judgment.
The big picture
You now own a toolbox: linear Kalman, EKF, UKF, particle filter, Rao-Blackwellized particle filter, plus the robust and adaptive layers that harden any of them. Owning the toolbox is not the skill. The skill is walking up to a new sensing problem, spending five minutes characterizing it, and reaching for the cheapest estimator that will not fail. Almost every engineer over-reaches here. They see the word "nonlinear" and jump to a particle filter with ten thousand samples, then ship a system that burns a battery to solve a problem a UKF would have handled in a hundredth of the compute. Conversely, the engineer who forces a stubborn multimodal problem through an EKF gets a filter that reports a tight, confident covariance around entirely the wrong answer. This section gives you a decision procedure grounded in four questions, a comparison table you can keep next to your keyboard, and a runnable experiment that measures the accuracy-versus-cost tradeoff so you stop guessing and start measuring.
The four questions that pick the filter
Before comparing filters, characterize the problem. Four questions settle most decisions, and you can answer all four from the measurement model and a few minutes of thought about the physics, exactly the physics developed in Chapter 2.
1. How nonlinear are the dynamics and the measurement? A GNSS pseudorange is mildly nonlinear over a one-second step; a bearing-only measurement of a nearby target is violently nonlinear. The relevant quantity is not the function itself but how much it curves across one standard deviation of your state uncertainty. If a first-order Taylor expansion is accurate over that spread, an EKF suffices. If the curvature matters but the posterior stays roughly bell-shaped, a UKF captures it. The linearization error of the EKF grows with the second derivative of \(f\) and \(h\); the UKF's sigma points sample the function directly and capture curvature to second order with no Jacobian at all.
2. Is the posterior unimodal or multimodal? This is the decisive question, and it is independent of nonlinearity. A unimodal posterior, a single blob of probability, can be summarized by a mean and covariance, which is precisely what the Kalman family stores. A multimodal posterior, arising in global localization ("am I in room A or the identical room B?"), data association ("which of three targets produced this blip?"), or the wrapped-angle ambiguities common in RF sensing, cannot be summarized by one Gaussian. No amount of tuning rescues a Gaussian filter here; it will collapse onto one mode and discard the others. Multimodality forces a particle filter or a Gaussian mixture.
3. What is your compute and latency budget? An EKF and a UKF cost on the order of \(O(n^3)\) per step in the state dimension \(n\), dominated by the covariance update, and both run comfortably in microseconds for a modest state. A particle filter costs \(O(N\,n)\) for \(N\) particles plus the per-particle likelihood evaluation, and \(N\) often needs to be thousands. On a microcontroller (revisit Chapter 61) that gap is the difference between shipping and not shipping.
4. Can you evaluate a likelihood, or only sample? Particle filters need to score how well each particle explains the measurement. If your measurement model is a clean probability density this is trivial; if it is a black-box renderer or a neural network, you may need an approximate likelihood, which weakens the filter.
Key insight
Nonlinearity and multimodality are different axes, and people conflate them. Nonlinearity asks whether a straight-line approximation of the sensor is good enough; multimodality asks whether one blob of probability can describe your belief at all. A problem can be highly nonlinear yet unimodal (satellite ranging), in which case a UKF is ideal, or nearly linear yet multimodal (a symmetric building for indoor positioning), in which case even a linear-measurement particle filter beats the finest Kalman variant. Pick the axis that is actually hurting you before you pick the filter.
A comparison you can keep on your desk
The table below compresses the chapter into one glance. Read it as a ladder: start at the top and descend only when a question above forces you down. Each row costs materially more than the one above it, so every downward step should be justified by a failure of the cheaper filter, not by ambition.
| Estimator | Handles nonlinearity | Handles multimodality | Relative cost | Reach for it when |
|---|---|---|---|---|
| Linear Kalman (Ch 9) | No | No | 1x | Dynamics and measurement are linear or nearly so. |
| EKF (10.1) | Mild, first order | No | 1-2x | Smooth nonlinearity, good initial guess, Jacobians available. |
| UKF (10.2) | Moderate, second order | No | 2-4x | Stronger curvature, no clean Jacobian, still one mode. |
| Particle filter (10.3-10.4) | Arbitrary | Yes | 100-10000x | Multimodal belief, non-Gaussian noise, hard nonlinearity. |
| Rao-Blackwellized PF (10.5) | Arbitrary in the sampled part | Yes, in the sampled part | 10-1000x | Some states are conditionally linear-Gaussian; sample the rest. |
Two refinements sit outside the ladder because they compose with any row. The robust and adaptive layer of Section 10.6 (outlier gating, adaptive noise estimation) should wrap whichever filter you chose; it fixes fragility, not the wrong choice of representation. And Rao-Blackwellization is a scalpel, not a default: it pays off dramatically only when a genuine linear-Gaussian substructure exists, such as landmark positions conditioned on a robot trajectory.
Practical example: a warehouse robot that picked the wrong filter twice
A team building an autonomous forklift for an automotive-parts warehouse started with an EKF fusing wheel odometry and a lidar scan match. It worked beautifully in testing and failed on day one in the real aisle. The aisles were identical, so on startup the robot's belief was genuinely bimodal: it could be at either end. The EKF averaged the two modes and confidently parked the forklift in the middle of the floor, halfway between two valid poses, reporting a small covariance the whole time. The fix was not a better Jacobian; it was switching global localization to a particle filter that held both hypotheses until a unique aisle marker collapsed them. Once localized, the team switched back: they Rao-Blackwellized the problem so the continuous pose ran in an efficient Gaussian sub-filter while only the discrete "which aisle" hypothesis carried particles. The particle count dropped from twelve thousand to eighty, and the estimator fit back inside the robot's real-time budget. The lesson is the ladder: they climbed down for the one phase that needed it and climbed back up the moment they could.
Measure the tradeoff, do not guess it
Intuition about accuracy-versus-cost is unreliable; the honest move is to run all the candidates on the same trajectory and plot error against wall-clock, on a leakage-safe split so the noise realizations in your test are not the ones you tuned on (the discipline from Chapter 5). The snippet below tracks a classic nonlinear benchmark, a range-and-bearing target, with an EKF, a UKF, and a bootstrap particle filter, then reports root-mean-square error and per-step time. It is the miniature of Lab 10.
import numpy as np
from filterpy.kalman import ExtendedKalmanFilter, UnscentedKalmanFilter, MerweScaledSigmaPoints
from filterpy.monte_carlo import systematic_resample
import time
def run_particle_filter(zs, N=2000):
# bootstrap PF: predict via dynamics, weight by measurement likelihood
parts = np.random.randn(N, 4) * 5.0 # [x, vx, y, vy]
w = np.full(N, 1.0 / N)
est = []
for z in zs:
parts[:, 0] += parts[:, 1]; parts[:, 2] += parts[:, 3] # constant velocity
parts[:, [1, 3]] += np.random.randn(N, 2) * 0.1 # process noise
rng = np.hypot(parts[:, 0], parts[:, 2])
brg = np.arctan2(parts[:, 2], parts[:, 0])
resid = np.array([z[0] - rng, z[1] - brg]).T
w *= np.exp(-0.5 * (resid**2 / np.array([1.0, 0.02])).sum(1))
w += 1e-300; w /= w.sum()
if 1.0 / np.sum(w**2) < N / 2: # resample on degeneracy (10.4)
idx = systematic_resample(w); parts = parts[idx]; w.fill(1.0 / N)
est.append(np.average(parts, axis=0, weights=w))
return np.array(est)
# ... EKF and UKF set up with the same f, h, Q, R (elided for space) ...
for name, fn in [("PF", run_particle_filter)]:
t0 = time.perf_counter(); xhat = fn(measurements)
dt = (time.perf_counter() - t0) / len(measurements)
rmse = np.sqrt(np.mean((xhat[:, [0, 2]] - truth[:, [0, 2]])**2))
print(f"{name}: RMSE={rmse:.3f} time/step={dt*1e6:.1f} us")
When you run the complete harness, the pattern is remarkably stable across problems. On a mildly nonlinear leg the EKF and UKF tie the particle filter on accuracy while running orders of magnitude faster, so the particle filter is pure waste. On a leg where the target passes close to the sensor, where bearing becomes violently nonlinear, the EKF's RMSE blows up while the UKF and particle filter hold, and that single leg is your evidence for climbing one rung down the ladder.
Library shortcut
You do not hand-code three filters to compare them. filterpy gives you ExtendedKalmanFilter, UnscentedKalmanFilter, and Monte-Carlo resampling helpers behind a shared interface, so a full EKF-versus-UKF-versus-PF bakeoff is roughly forty lines instead of the four hundred-plus a from-scratch implementation of all three would take, including sigma-point weights, Jacobian bookkeeping, and a numerically safe resampler. The library handles covariance-update numerics and the systematic-resample loop; you supply only \(f\), \(h\), \(\mathbf{Q}\), and \(\mathbf{R}\). Use it to choose, then hand-tune only the winner.
When the answer is "none of the above"
Three exits from this chapter are worth naming so you recognize them. First, if you can afford to wait and want the smoothed trajectory rather than the causal filtered estimate, stop filtering and formulate the problem as a factor graph, which is the entire subject of Chapter 11; smoothing over a window beats any filter when latency is not sacred. Second, if your measurement model is a learned function with no analytic form, a differentiable or neural filter that learns the dynamics may outperform any hand-built one, a thread picked up in Chapter 16. Third, if the real difficulty is not the estimator but knowing whether to trust its output, the calibration and conformal machinery of Chapter 18 is the missing piece, because a filter that reports a covariance is not the same as a filter whose covariance is honest.
Exercise
Take a clinical wearable that estimates respiration rate from a chest-strap accelerometer. Motion artifacts occasionally make the measurement bimodal (true breathing frequency versus a walking-cadence harmonic). Walk the four questions for this problem and state which estimator you would ship, then state what changes if the device must run for a week on a coin cell. Justify each answer in one sentence tied to a specific question.
Self-check
1. A colleague says "the problem is very nonlinear, so we need a particle filter." What single follow-up question tells you whether they are right, and why is nonlinearity alone insufficient justification?
2. Why does an EKF report a small, confident covariance even when it has converged to the wrong mode of a bimodal posterior, and why is this failure mode more dangerous than a large reported covariance?
3. You benchmark EKF, UKF, and PF and find the UKF matches the PF's accuracy at a hundredth of the cost. What does that tell you about the shape of the true posterior on this trajectory?
Lab 10
track a nonlinear system with EKF, UKF, and a particle filter; compare accuracy and cost.
Bibliography
Foundational surveys and comparisons
The canonical side-by-side of Kalman-family and particle methods; its framing of when each representation is appropriate is the backbone of this section's decision procedure.
Sarkka (2013). Bayesian Filtering and Smoothing. Cambridge University Press.
A unified treatment that derives EKF, UKF, and particle filters from one Bayesian recursion, making the cost-versus-fidelity ladder explicit and rigorous.
The individual estimators
Julier and Uhlmann (2004). Unscented Filtering and Nonlinear Estimation. Proceedings of the IEEE.
The definitive statement of why sigma-point propagation beats Jacobian linearization, and the practical regime where a UKF is the right rung of the ladder.
The bootstrap particle filter that made sequential Monte Carlo practical; read it to understand exactly which problems justify paying the particle-filter cost.
Thrun, Burgard, and Fox (2005). Probabilistic Robotics. MIT Press.
The definitive account of estimator choice in robotics, including the identical-corridor multimodality problem and Rao-Blackwellized filtering for SLAM.
Software and reproducibility
Labbe (2020). Kalman and Bayesian Filters in Python (and the filterpy library).
The open textbook and library behind the code in this section; its shared interface across EKF, UKF, and particle filters is what makes a real bakeoff cheap.
A rigorous retrospective on when sequential Monte Carlo pays off and when cheaper Gaussian approximations suffice, sharpening the cost side of the tradeoff.
What's Next
In Chapter 11, we take the most important exit from the filtering ladder. When latency is not sacred and you want the best estimate of the whole trajectory rather than the causal one, the problem stops being a recursive filter and becomes a large optimization over a factor graph. That reframing powers modern SLAM and visual-inertial odometry, and it turns the question "which filter?" into the question "how do I solve one big nonlinear least-squares problem efficiently?"