Contents
  1. The Problem
  2. Variables
  3. The Two-Phase Loop
  4. Phase 1: Predict
  5. Phase 2: Correct
  6. Understanding the Kalman Gain
  7. Why This Matters for Control
  8. What You Can Do Now
← All posts

The Kalman Filter: State Estimation Under Noise

The Kalman filter estimates the true state of a system from noisy measurements. It alternates between prediction and correction, weighting each by how much it trusts the model vs the sensor.

The Problem

You are running a system and you want to know its true state xkx_k. The problem: your sensors produce noisy measurements, and your model of how the state evolves also has uncertainty. The Kalman filter combines both sources of information (the physical model and the measurement) to produce the best possible estimate of the true state.

Variables

SymbolMeaning
xkx_k, x^k\hat{x}_kTrue state / predicted state
PkP_k, P^k\hat{P}_kProcess covariance matrices
AAState transition matrix
BBControl input matrix
CCMeasurement conversion matrix
DDNoise input matrix
HHMeasurement matrix (shapes the calculation)
KKKalman gain
UkU_kControl input (external variable)
yky_kMeasured state
εk\varepsilon_kProcess noise
θk\theta_kMeasurement noise
QQProcess noise covariance
RRMeasurement noise covariance

The Two-Phase Loop

The Kalman filter alternates between predict and correct at every time step.

Phase 1: Predict

Use the physical model to project the state forward:

x^kk1=Axk1+BUk+Dεk\hat{x}_{k|k-1} = A x_{k-1} + B U_k + D \varepsilon_k

Project the process covariance forward:

P^kk1=APk1AT+Dεk\hat{P}_{k|k-1} = A P_{k-1} A^T + D \varepsilon_k

This gives a predicted state and predicted uncertainty, both based on the model alone, before seeing the new measurement.

Phase 2: Correct

Take the new measurement:

yk=Cx^k+θky_k = C \hat{x}_k + \theta_k

Compute the Kalman gain, which determines how much to trust the measurement vs the prediction:

K=P^kk1HTHP^kk1HT+RK = \frac{\hat{P}_{k|k-1} H^T}{H \hat{P}_{k|k-1} H^T + R}

Update the state estimate by blending the prediction with the measurement residual [ykHx^kk1][y_k - H\hat{x}_{k|k-1}]:

xk=x^kk1+K[ykHx^kk1]x_k = \hat{x}_{k|k-1} + K[y_k - H \hat{x}_{k|k-1}]

Update the covariance:

Pk=(IKH)P^kkP_k = (I - KH)\hat{P}_{k|k}

Understanding the Kalman Gain

The term [ykHx^kk1][y_k - H\hat{x}_{k|k-1}] is the innovation, the difference between what the sensor measured and what the model predicted. The Kalman gain KK controls how much of this innovation to absorb:

  • If RR is large (sensor is noisy), KK is small. Trust the model more, ignore most of the measurement
  • If RR is small (sensor is accurate), KK is large. Trust the measurement more, correct the model aggressively

The covariance update (IKH)P^(I - KH)\hat{P} shows the same logic: a larger KK (more trust in measurement) shrinks the uncertainty PkP_k faster.

Why This Matters for Control

The Kalman filter is commonly embedded inside MPC and other control systems when the full state xx cannot be measured directly. It provides a clean, statistically optimal estimate of the state at each time step, which the controller then uses to compute the next action.

What You Can Do Now

The code below runs a 1D Kalman filter on a constant signal buried in sensor noise, showing the predict-correct loop and how the estimate converges to the true value.

import numpy as np

np.random.seed(42)
n_steps = 40
true_state = 5.0     # constant true value we are trying to estimate

# Noise parameters
Q = 0.01   # process noise variance (model uncertainty)
R = 2.0    # measurement noise variance (sensor uncertainty)

# Noisy measurements
measurements = true_state + np.random.normal(0, np.sqrt(R), n_steps)

# Initial estimates
x_est = 0.0    # prior state estimate
P = 1.0        # prior uncertainty

print(f"{'Step':>4}  {'Measured':>10}  {'Estimated':>10}  {'Kalman Gain':>12}")
for k, z in enumerate(measurements):
    # --- Predict ---
    x_pred = x_est          # state doesn't change (constant signal model)
    P_pred = P + Q          # uncertainty grows slightly each step

    # --- Correct ---
    K = P_pred / (P_pred + R)           # Kalman gain
    x_est = x_pred + K * (z - x_pred)  # blend prediction with measurement
    P = (1 - K) * P_pred               # update uncertainty

    if k < 5 or k == n_steps - 1:
        print(f"{k+1:>4}  {z:>10.3f}  {x_est:>10.3f}  {K:>12.4f}")

print(f"\nTrue value: {true_state:.3f}, Final estimate: {x_est:.3f}")

Change R to a larger value (noisy sensor) and watch the Kalman gain stay small. The filter leans on the model. Reduce R and the gain grows, trusting measurements more. Setting Q = 0 models a perfectly known system with no drift.

← All posts