|
EmrysFilter 0.1.0
State estimation utilities in C++23 using Eigen
|
Reduction policy that rejects branches by a chi-squared test on their normalized innovation squared, then reduces the rest with Inner. More...
#include <EmrysFilter/Models/Reduction.h>
Public Types | |
| using | Scalar = Scalar_ |
| The type of the probability or threshold it holds. | |
Public Member Functions | |
| Gate (Scalar probability, Inner inner={}) | |
| Passes branches whose NIS is within the probability chi-squared quantile. | |
| Gate (NisThreshold< Scalar > threshold, Inner inner={}) | |
| Passes branches whose NIS is at most threshold. | |
| template<RealScalar Result = Scalar> | |
| Result | threshold (Eigen::Index dimension) const |
| Inner const & | inner () const |
| template<typename Branches, typename Out> requires internal::BranchRange<Branches> && internal::ReducesInto<Inner, Branches, Out> && internal::ReducesInto<Inner, internal::PassingBranches<Branches>, Out> | |
| void | operator() (Branches &&branches, Out &out) const |
| Reduces the branches of branches that pass the gate into out by Inner, or adds nothing when none pass. | |
Static Public Attributes | |
| static constexpr std::size_t | InlinePassing = 32 |
| The most branches of a run-time number whose passing indices a gate holds on the stack. | |
Reduction policy that rejects branches by a chi-squared test on their normalized innovation squared, then reduces the rest with Inner.
A branch passes when its NIS (see UpdateBranch) is at most the threshold: the probability quantile of the chi-squared distribution with the innovation's dimension as its degrees of freedom, or a NisThreshold given directly. The passing branches, with their weights as they were, go to Inner (Collapse by default), and what Inner keeps stands for them alone: a filter of several components, modes, or points weights it by the passing branches' likelihood, \( \sum_{k \text{ passes}} w_k \, p(z \mid k) \), not the whole update's (see ReductionPolicy). When none pass, the measurement is rejected and the state keeps its prior.
This is an absolute test of each branch against its own innovation covariance, and needs no outlier model. It composes with mixture noise, which compares branches with each other: reductions::gate(0.997, reductions::select()) gates each noise component, then keeps the most probable.
The validation gate of Bar-Shalom, Li, and Kirubarajan (2001), as given in Bar-Shalom and Tse (1975), ยง4, equations (4.3) to (4.5), applied to an update's branches.
Scalar_ is the type of the probability or threshold it holds, deduced from the one given (reductions::gate(0.997f) holds a float). The quantile is computed in the update's scalar, so a float filter's gate does no double arithmetic, and one given a float holds no double either.
A gate given a probability computes its quantile on every update, an iteration that costs many times a small Kalman update, and the gate keeps no result between calls. Where the innovation's dimension is known and the filter runs at a high rate, compute the threshold once and give it as a NisThreshold, which costs a comparison per branch:
|
inlinenodiscard |
|
inline |
Reduces the branches of branches that pass the gate into out by Inner, or adds nothing when none pass.
When some but not all pass, Inner reads them through their indices, held in an array on the stack for an array of branches or a run-time number of up to InlinePassing, and otherwise in a buffer from the branches' allocator, the one case that allocates; posteriors are moved out of branches given as an rvalue.
|
inlinenodiscard |