Estimation Pipelines¶
Contrax supports both recursive and optimization-based estimation workflows.
That matters because the right question is usually not “which filter do I know?”, but “what estimation pipeline fits this system, data stream, and JAX workflow?”
Recursive Filters¶
The recursive side of the library includes:
kalman()for linear Gaussian systemsekf()for nonlinear models with local Jacobian linearizationukf()for nonlinear models with sigma-point propagation
Each of those also has one-step helpers for runtime loops.
Use the one-step helpers when measurements arrive online or when the estimator must live inside a service loop. Use the batch filter when you want an entire offline pass over a fixed sequence.
Contrax uses an update-first batch convention. The forward pass starts from a
prior on x_0, updates with y_0, then predicts the prior on x_1.
Linear Kalman Filter¶
For the linear discrete model
the filter recursion is
Use the linear Kalman filter when the model is linear and Gaussian noise is a reasonable approximation.
The filter evaluates the posterior covariance in Joseph form by default,
(I-KC) P^- (I-KC).T + K R K.T. This is algebraically equivalent to the compact
equation above, while retaining the positive-semidefinite noise contribution
explicitly under roundoff. The compact form is an explicit solver option.
Extended Kalman Filter¶
For nonlinear transition and observation maps,
the EKF replaces the linear matrices with local Jacobians:
The EKF has low per-step overhead when a local linearization approximates the
model well over one update step.
EKF uses the same Joseph form with the final measurement Jacobian. An explicit
EKF(num_iter=...) solver relinearizes the update while holding the prior
covariance fixed; both online and batch updates support it.
Unscented Kalman Filter¶
The UKF keeps the same state-estimation goal but avoids local Jacobians. It starts from sigma points
and pushes them through the observation and transition maps:
The predicted moments are reconstructed with sigma-point weights:
and the update uses the cross-covariance
to form
Use the UKF when sigma-point propagation better captures the nonlinear maps than local Jacobians and a recursive estimate is sufficient.
Smoothers¶
Recursive filters consume information causally. Smoothers revisit the sequence with future information available.
Contrax provides:
rts()for filtered linear Kalman resultsuks()for filtered unscented Kalman results
These are offline tools. They are not replacements for runtime loops, but they are valuable when you want a retrospective state estimate or a comparison target for an optimization-based method.
RTS Smoother¶
For the linear filter, the Rauch-Tung-Striebel backward pass is
RTS validates the incoming filtered trajectory and propagates its failure status. Covariance validation first attempts a Cholesky factorization. In mixed trajectories, only matrices whose factorization fails use the spectral PSD check and its roundoff tolerance. If every factorization fails, a batched spectral check is used. The check does not modify covariances. The same validation applies when inspecting the smoothed result's status. Validation still costs O(T n³); fully singular trajectories also pay for the unsuccessful factorizations and can be slower than a spectral check alone.
Unscented RTS-Style Smoother¶
For uks(), the same backward structure is used, but the smoother gain is
built from the unscented cross-covariance:
MHE As A Sibling Workflow¶
Moving-horizon estimation optimizes the state trajectory over a fixed window:
- an arrival cost anchors the start of the window
- process costs enforce model consistency across transitions
- measurement costs enforce agreement with the observed outputs
- optional extra costs let the user express soft constraints or domain terms
mhe_objective() exposes the model, horizon, and cost directly, so callers can
select an optimizer separately.
The fixed-horizon objective is the optimization sibling of the recursive filters:
Choosing Between The Current Paths¶
Prefer:
kalman()when the model is linear and Gaussian assumptions are a good first approximationekf()when a local linearization is a reasonable approximation and you want the lightest nonlinear recursive pathukf()when sigma-point propagation is a better fit than local Jacobiansrts()oruks()when you need an offline smoothed trajectorymhe_objective()ormhe()when you want a fixed-window optimization-based estimate with explicit costs
Transform Contracts¶
Estimation functions use fixed-shape JAX workflows:
- batch filters are scans
- one-step helpers can live inside larger scans
- missing-measurement handling avoids Python branching on traced values
mhe_objective()is a pure JAX cost over explicit arrays
These functions compose with compilation and differentiation when their individual transform contracts allow it.