EmrysFilter 0.1.0
State estimation utilities in C++23 using Eigen
Loading...
Searching...
No Matches
Emrys::NeesMonitor< Window, MaxWindow, Scalar, Allocator > Class Template Reference

A chi-squared consistency check of a filter's estimates against the true states, over a window of them. More...

#include <EmrysFilter/Models/Consistency.h>

Inheritance diagram for Emrys::NeesMonitor< Window, MaxWindow, Scalar, Allocator >:

Public Member Functions

 NeesMonitor ()=default
 A monitor over the most recent Window estimates, or over every estimate for Cumulative.
 NeesMonitor (Eigen::Index window, Allocator const &allocator={})
 A monitor over the most recent window estimates, whose window, if it has no bound, comes from allocator.
 NeesMonitor (NeesMonitor const &other, Allocator const &allocator)
 Copies other into a window from allocator.
template<GaussianForm Estimate, typename Derived>
requires requires(Estimate const & estimate, Eigen::MatrixBase<Derived> const & truth) { nees(truth, estimate); }
void add (Eigen::MatrixBase< Derived > const &truth, Estimate const &estimate)
 Adds the estimate estimate of the true state truth: its nees(), with its difference dimension as the degrees of freedom.
template<typename Path, typename Derived, typename Estimate>
requires requires(Estimate const & estimate, Eigen::MatrixBase<Derived> const & truth) { nees<Path>(truth, estimate); }
void add (Eigen::MatrixBase< Derived > const &truth, Estimate const &estimate)
 Adds the block of estimate named by the path Path at the same block of the true state truth: its nees<Path>(), with the block's difference dimension as the degrees of freedom, and NaN as add(truth, estimate) adds it.

Detailed Description

template<int Window = Eigen::Dynamic, int MaxWindow = Window, typename Scalar = double, typename Allocator = DefaultAllocator>
class Emrys::NeesMonitor< Window, MaxWindow, Scalar, Allocator >

A chi-squared consistency check of a filter's estimates against the true states, over a window of them.

For a consistent filter, each estimate's normalized estimation error squared (see nees()) is chi-squared with the state's difference dimension as its degrees of freedom, and the sum of independent ones is chi-squared with the total. verdict() tests that sum against two-sided bounds, as NisMonitor does: above them the filter is overconfident, an error, and below them underconfident, a loss of precision but no error (see Consistency). The truth comes from a simulation (see simulate()), and the estimates must be independent, so the monitor takes one per run, from runs with their own truth and noise, at the same step:

auto monitor = NeesMonitor<Cumulative>{};
for (int run = 0; run < 100; ++run)
{
auto truth = drawSample(prior.toDensity().value(), rng);
auto filter = KalmanFilter{model, prior};
for (int k = 0; k < 50; ++k)
{
truth = simulate(space, truth, model, rng, dt);
filter.predict(dt);
filter.update(observe(gps, simulate(space, truth, gps, rng)));
}
monitor.add(truth, filter.state());
}
auto const verdict = monitor.verdict(0.99);
if (!verdict) { ... } // no run was added, or one's estimate had no density
else if (*verdict == Consistency::Overconfident) { ... }
A Kalman filter: a Gaussian state and the KalmanRecursion that predicts it through a process model an...
Definition KalmanFilter.h:561
NeesMonitor()=default
A monitor over the most recent Window estimates, or over every estimate for Cumulative.
Eigen::Index drawSample(Categorical< Space, Scalar > const &distribution, G &rng)
Definition Categorical.h:1111
@ Overconfident
the sum lies above the upper bound: the covariance understates the errors
Definition Consistency.h:58
Moments< Space_, typenameDerived::Scalar >::VectorType simulate(Space_ const &space, Eigen::MatrixBase< Derived > const &x, Model const &model, G &rng, TimeStep< typename Derived::Scalar > auto const &dt, Args const &... args)
Definition Simulation.h:130
auto observe(Method method, M &&model, Z &&observation, Args &&... args)
Definition MeasurementModel.h:1399

Here gps is a measurement model (see measurementModel()), whose simulate() draws a measurement of the true state from the noise the filter assumes. The window is sized as NisMonitor's is.

This is the Monte Carlo average test of Bar-Shalom, Li, and Kirubarajan (2001), as given in Chen et al. (2023), §III-B, equations (12) and (14). Unlike the NIS, the NEES of one run is no test over its steps: a filter's errors are correlated from step to step, where its innovations are white, so their sum spreads far wider than the chi-squared with the total, and a consistent filter fails often. A linear Kalman filter, consistent to a mean NEES of 1.00 over 60 seeds, failed the 0.999 test over 400 steps of one run on 11 seeds in 100.

See also
NisMonitor

Member Function Documentation

◆ add() [1/2]

template<int Window = Eigen::Dynamic, int MaxWindow = Window, typename Scalar = double, typename Allocator = DefaultAllocator>
template<typename Path, typename Derived, typename Estimate>
requires requires(Estimate const & estimate, Eigen::MatrixBase<Derived> const & truth) { nees<Path>(truth, estimate); }
void Emrys::NeesMonitor< Window, MaxWindow, Scalar, Allocator >::add ( Eigen::MatrixBase< Derived > const & truth,
Estimate const & estimate )
inline

Adds the block of estimate named by the path Path at the same block of the true state truth: its nees<Path>(), with the block's difference dimension as the degrees of freedom, and NaN as add(truth, estimate) adds it.

A monitor per block, fed alongside one of the whole state, says which block is inconsistent.

◆ add() [2/2]

template<int Window = Eigen::Dynamic, int MaxWindow = Window, typename Scalar = double, typename Allocator = DefaultAllocator>
template<GaussianForm Estimate, typename Derived>
requires requires(Estimate const & estimate, Eigen::MatrixBase<Derived> const & truth) { nees(truth, estimate); }
void Emrys::NeesMonitor< Window, MaxWindow, Scalar, Allocator >::add ( Eigen::MatrixBase< Derived > const & truth,
Estimate const & estimate )
inline

Adds the estimate estimate of the true state truth: its nees(), with its difference dimension as the degrees of freedom.

An estimate whose covariance doesn't factorize adds NaN, so average() and verdict() fail with NonFinite until it leaves the window, or for Cumulative until reset().


The documentation for this class was generated from the following file: