SigmaPointUKF¶
The SigmaPointUKF is an Unscented Kalman Filter with a pluggable sigma point strategy. Unlike the built-in UKF which hardcodes sigma point generation, this filter delegates sigma point computation to external strategy objects, enabling maximum flexibility and experimentation.
Fundamental Concepts¶
Why Pluggable Sigma Points?¶
Different sigma point strategies have different numerical properties:
| Strategy | Spread Control | Numerical Stability | Best For |
|---|---|---|---|
| SimplexSigmaPoints | \(\alpha, \beta, \kappa\) | Standard | General use |
| MerweScaledSigmaPoints | \(\alpha, \beta, \kappa\) | Excellent for large \(n\) | High-dimensional systems |
| JulierSigmaPoints | \(\kappa\) | Robust | Certain non-Gaussian systems |
The Algorithm¶
The UKF uses the unscented transform to propagate statistics through nonlinear functions:
- Generate \(2n+1\) sigma points from \((x, P)\)
- Propagate each point through \(f\) (predict) or \(h\) (update)
- Reconstruct mean and covariance from transformed points
When to Use¶
| ✅ Use SigmaPointUKF when | ❌ Don't use when |
|---|---|
| You need to experiment with sigma point strategies | Standard UKF works fine |
| High-dimensional state space | Low-dimensional systems (use standard UKF) |
| Custom sigma point weighting needed | Linear system (use KF) |
| Research on UKF variants | — |
How to Use¶
Basic Example¶
import numpy as np
from kalbee import SigmaPointUKF, MerweScaledSigmaPoints
state = np.zeros((2, 1))
covariance = np.eye(2) * 10.0
Q = np.eye(2) * 0.01
R = np.array([[0.5]])
# Define nonlinear functions
def transition(x, dt):
return np.array([
[x[0, 0] + x[1, 0] * dt],
[x[1, 0]]
])
def measurement(x):
return np.array([[x[0, 0]]])
# Create UKF with MerweScaled sigma points
sigma_pts = MerweScaledSigmaPoints(n=2, alpha=0.1, beta=2.0, kappa=0.0)
ukf = SigmaPointUKF(
state, covariance, Q, R,
transition_function=transition,
measurement_function=measurement,
sigma_points=sigma_pts
)
measurements = [1.2, 2.1, 2.8, 4.1, 5.0]
for z in measurements:
ukf.predict(dt=1.0)
ukf.update(np.array([[z]]))
print(f"Position: {ukf.x[0,0]:.2f}, Velocity: {ukf.x[1,0]:.2f}")
Swapping Sigma Point Strategies¶
from kalbee import SimplexSigmaPoints, JulierSigmaPoints
# Simplex (default)
ukf_simplex = SigmaPointUKF(
state, cov, Q, R, f, h,
sigma_points=SimplexSigmaPoints(n=2)
)
# Julier
ukf_julier = SigmaPointUKF(
state, cov, Q, R, f, h,
sigma_points=JulierSigmaPoints(n=2, kappa=0.0)
)
# Auto-create from parameters (uses Simplex by default)
ukf_auto = SigmaPointUKF(
state, cov, Q, R, f, h,
alpha=0.001, beta=2.0, kappa=0.0
)
Sigma Point Strategies¶
SimplexSigmaPoints¶
Standard UKF sigma points. Produces \(2n+1\) points symmetrically around the mean.
from kalbee import SimplexSigmaPoints
sp = SimplexSigmaPoints(n=4, alpha=0.001, beta=2.0, kappa=0.0)
sigma_points = sp.sigma_points(x, P) # (2n+1, n) array
MerweScaledSigmaPoints¶
Scalable sigma points with better numerical properties for large state dimensions.
from kalbee import MerweScaledSigmaPoints
sp = MerweScaledSigmaPoints(n=4, alpha=0.1, beta=2.0, kappa=0.0)
sigma_points = sp.sigma_points(x, P)
JulierSigmaPoints¶
Original Julier formulation. More robust for certain non-Gaussian applications.
from kalbee import JulierSigmaPoints
sp = JulierSigmaPoints(n=4, kappa=0.0)
sigma_points = sp.sigma_points(x, P)