|
EmrysFilter 0.1.0
State estimation utilities in C++23 using Eigen
|
The posterior Cramér-Rao bound along true trajectories: the Fisher information \( J_k \) of the state, whose inverse bounds the mean squared error of any estimator of \( x_k \). More...
#include <EmrysFilter/Models/CramerRao.h>
Public Types | |
| using | Scalar = Scalar_ |
| the scalar type | |
| using | SpaceType = Space_ |
| the state space | |
| using | VectorType = typename Moments<Space_, Scalar_>::VectorType |
| a state value | |
| using | MatrixType = typename Moments<Space_, Scalar_>::MatrixType |
| \( J \), over differences | |
Public Member Functions | |
| template<MatrixExpression Info> | |
| PosteriorCramerRaoBound (Space_ space, Info &&info) | |
| The bound in space with the information matrix information, symmetric and positive semidefinite over the space's differences: zero for a state that nothing is known about. | |
| Space_ const & | space () const |
| MatrixType const & | info () const |
| std::expected< MatrixType, GaussianError > | covariance () const |
| template<ProcessModel Model, typename Truths, typename... Inputs> requires (!ExecutionPolicy<Model>) | |
| std::expected< void, GaussianError > | predict (Model const &model, Eigen::MatrixBase< Truths > const &truths, TimeStep< Scalar_ > auto const &dt, Inputs const &... inputs) |
| Moves the bound forward by dt, any TimeStep (see Time steps), through the process model model with the true inputs inputs, from the true states truths, a column each: \( J \leftarrow Q^{-1} - Q^{-1} \bar F (J + D^{11})^{-1} \bar F^T Q^{-1} \), with model's Jacobian \( F \) at each column. | |
| template<ExecutionPolicy P, ProcessModel Model, typename Truths, typename... Inputs> | |
| std::expected< void, GaussianError > | predict (P &&policy, Model const &model, Eigen::MatrixBase< Truths > const &truths, TimeStep< Scalar_ > auto const &dt, Inputs const &... inputs) |
| predict(model, truths, dt, inputs...) under policy: the Jacobians at the columns are taken as a reduction (see Execution policies), so the result depends on the count of truths but not on how the work was scheduled, and with fewer than internal::chunkSize truths it is Sequential's. | |
|
template<typename Model, typename Truths, typename... Inputs> requires ( !ExecutionPolicy<Model> && (isFixedStep<Model> || isUnboundStep<Model>) && requires(Model const & m) { m.model(); } ) | |
| std::expected< void, GaussianError > | predict (Model const &model, Eigen::MatrixBase< Truths > const &truths, Inputs const &... inputs) |
| predict() over the step of the fixed-step model model, or of fixedStep()'s result, with its process noise. | |
|
template<ExecutionPolicy P, typename Model, typename Truths, typename... Inputs> requires ((isFixedStep<Model> || isUnboundStep<Model>) && requires(Model const & m) { m.model(); }) | |
| std::expected< void, GaussianError > | predict (P &&policy, Model const &model, Eigen::MatrixBase< Truths > const &truths, Inputs const &... inputs) |
| predict(model, truths, inputs...) over a fixed-step model's step under policy. | |
| template<typename Truths, MeasurementModel M, typename... Args> | |
| std::expected< void, GaussianError > | update (Eigen::MatrixBase< Truths > const &truths, M const &model, Args const &... args) |
| Adds the information that a measurement at the true states truths, a column each, carries: \( J \leftarrow J + \mathrm{E}[H^T R^{-1} H] \), with \( H \) the Jacobian of the measurement model model's function at each column, and the call's args the sure inputs the model reads, as simulate() takes them. | |
| template<ExecutionPolicy P, typename Truths, MeasurementModel M, typename... Args> | |
| std::expected< void, GaussianError > | update (P &&policy, Eigen::MatrixBase< Truths > const &truths, M const &model, Args const &... args) |
| update(truths, model, args...) under policy: a reduction over the columns, as in predict(). | |
Static Public Member Functions | |
| static std::expected< PosteriorCramerRaoBound, GaussianError > | create (GaussianParams< Space_, Scalar_ > const &prior) |
The posterior Cramér-Rao bound along true trajectories: the Fisher information \( J_k \) of the state, whose inverse bounds the mean squared error of any estimator of \( x_k \).
This is the posterior, or Van Trees, form of the Cramér-Rao bound: for any filter, \( \mathrm{E}[(\hat x_k \boxminus x_k)(\hat x_k \boxminus x_k)^T] \ge J_k^{-1} \), the expectation taken over the true trajectories and their measurements. Compare a filter's mean squared error over Monte Carlo runs with covariance(), and its own covariance with NEES (see NeesMonitor): the bound says how far the error is from the best possible, NEES whether the filter knows its error.
It starts from the prior, \( J_0 = P_0^{-1} \) (create()), or from an information matrix, zero for a state that nothing is known about. Each step is given the true states at its time as the columns of a matrix, a SampleSet: one column for one trajectory, or one per Monte Carlo run, each drawn by simulate() from its own start, so that the bound takes the expectations over them. predict() and update() are the recursion of Tichavský, Muravchik, andNehorai (1998), Proposition 1, eq. (21), with the matrices of eqs. (34) to (36) for additive Gaussian noise, split in two since \( D^{22} \) is a sum:
\[ J \leftarrow Q^{-1} - Q^{-1} \bar F (J + D^{11})^{-1} \bar F^T Q^{-1}, \qquad J \leftarrow J + \mathrm{E}[H^T R^{-1} H], \]
with \( \bar F = \mathrm{E}[F] \) and \( D^{11} = \mathrm{E}[F^T Q^{-1} F] \), each expectation the mean over the columns. With one true state and no expectation the prediction is \( (Q + F J^{-1} F^T)^{-1} \), an extended Kalman filter's covariance recursion with every Jacobian taken at the truth, and for an affine model the Kalman filter's covariance itself.
The Jacobians are the Linearized method's at each true state, whatever method a model asks for, so a function that returns its Jacobian (withJacobian()) is called once per state. On a space with its own plus() and minus() they are in its tangent space, and the bound is that of Chahbazian et al. (2024), Proposition 2 and eqs. (68) to (72), for noise that enters as \( f(x) \boxplus w \), as simulate() draws it. The paper takes \( F \) at the pair of true states, as the derivative of \( x_{k+1} \boxminus f(x_k \boxplus \epsilon) \); this takes it at \( f(x_k) \), which is the same on Linear and agrees to first order in the noise elsewhere, the order of the paper's own truncation.
The process noise \( Q \) must be positive definite: a noiseless block, such as a Constant one, makes the transition density singular, which is Section IV of the paper and not supported yet. A model's inputs are the true ones, as simulate() takes them. The measurements are a measurement model's (see measurementModel()), with no observation, since the bound averages over the measurements the model would draw. Its noise must be additive and Gaussian (AdditiveNoise of a Gaussian), with \( R \) positive definite.
| Space_ | the state space (see Spaces) |
| Scalar_ | scalar type, double by default |
|
inlinenodiscard |
|
inlinestaticnodiscard |
|
inlinenodiscard |
|
inlinenodiscard |
Moves the bound forward by dt, any TimeStep (see Time steps), through the process model model with the true inputs inputs, from the true states truths, a column each: \( J \leftarrow Q^{-1} - Q^{-1} \bar F (J + D^{11})^{-1} \bar F^T Q^{-1} \), with model's Jacobian \( F \) at each column.
A model that gives its transition matrix is not differentiated, and its truths are not read.
|
inlinenodiscard |
|
inlinenodiscard |
Adds the information that a measurement at the true states truths, a column each, carries: \( J \leftarrow J + \mathrm{E}[H^T R^{-1} H] \), with \( H \) the Jacobian of the measurement model model's function at each column, and the call's args the sure inputs the model reads, as simulate() takes them.
The model's noise must be additive and Gaussian (additiveNoise() of a GaussianParams), with \( R \) positive definite. Several measurements at one time are several updates.