|
EmrysFilter 0.1.0
State estimation utilities in C++23 using Eigen
|
The autonomous multiple model (AMM) estimator: a bank of filters, one per mode, each running on its own, and the probability that each mode is the one in force, by Bayes' rule over their measurement likelihoods. More...
#include <EmrysFilter/Filters/AmmFilter.h>
Public Types | |
| using | Base = ImmFilter<Component_, Model_, Method_, Allocator_, Upkeep_> |
| the filter this is | |
| Public Types inherited from Emrys::ImmFilter< Component_, Model_, Method_, Allocator_, Upkeep_ > | |
| using | RecursionType = ImmRecursion<Component_, Model_, Method_, Allocator_> |
| the steps it runs | |
| using | Scalar = typename RecursionType::Scalar |
| the scalar type | |
| using | SpaceType = typename RecursionType::SpaceType |
| the state space | |
| using | ModelType = Model_ |
| the process model | |
| using | MethodType = Method_ |
| the prediction method | |
| using | ModeSpaceType = typename RecursionType::ModeSpaceType |
| the discrete mode space | |
| using | StateType = typename RecursionType::StateType |
| the state the filter owns | |
| using | ComponentType = Params<Component_> |
| one component of the state | |
| using | allocator_type = Allocator_ |
| the state's allocator | |
| using | JointType = typename RecursionType::JointType |
| what predictJoint() returns | |
Public Member Functions | |
|
template<typename... Models> requires std::constructible_from<Model_, typename Model_::ChainType, Models...> | |
| AmmFilter (typename Base::StateType state, Models... models) | |
| A filter with initial state state whose modes follow models, one per mode in flat-index order or one shared by every mode, each predicting by its models' default method. | |
| template<typename... Models> requires (!isFixedStep<Model_> && std::constructible_from<Model_, typename Model_::ChainType, Models...>) | |
| AmmFilter (Method_ method, typename Base::StateType state, Models... models) | |
| As AmmFilter(state, models...), predicting by method. | |
| template<typename... Models> requires ( !std::same_as<Upkeep_, Emrys::upkeep::None> && std::constructible_from<Model_, typename Model_::ChainType, Models...> ) | |
| AmmFilter (std::type_identity_t< Upkeep_ > upkeep, typename Base::StateType state, Models... models) | |
| As AmmFilter(state, models...), with upkeep upkeep, which maintain() runs. | |
|
template<typename... Models> requires ( !isFixedStep<Model_> && !std::same_as<Upkeep_, Emrys::upkeep::None> && std::constructible_from<Model_, typename Model_::ChainType, Models...> ) | |
| AmmFilter (Method_ method, std::type_identity_t< Upkeep_ > upkeep, typename Base::StateType state, Models... models) | |
| As AmmFilter(method, state, models...), with upkeep upkeep, which maintain() runs. | |
| Public Member Functions inherited from Emrys::ImmFilter< Component_, Model_, Method_, Allocator_, Upkeep_ > | |
| ImmFilter (Model_ model, StateType state, MethodFor< Model_, Method_ > method={}, std::type_identity_t< Upkeep_ > upkeep={}) | |
| A filter with switching model model, initial state state, prediction method method, and upkeep upkeep, which maintain() runs. | |
| ImmFilter (Model_ model, StateType state, std::type_identity_t< Upkeep_ > upkeep) | |
| A filter with switching model model, initial state state, the default prediction method, and upkeep upkeep, which maintain() runs. | |
| allocator_type | get_allocator () const |
| StateType const & | state () const |
| StateType & | state () |
| void | setState (StateType state) |
| Replaces the state, as when reinitializing, with one that has the model's modes and whose space every process model's writes partition, as the constructor's must. | |
| RecursionType const & | recursion () const |
| Model_ const & | model () const |
| Model_ & | model () |
| Method_ const & | method () const |
| template<typename... Inputs> requires (!isFixedStep<Model_>) | |
| auto | predict (TimeStep< Scalar > auto const &dt, Inputs const &... inputs) |
| Mixes the modes' components through the chain, moves each by dt, any TimeStep (see Time steps), through its mode's process model, with inputs passed as in Emrys::predict(), and moves the mode probabilities one step of the chain. | |
|
template<typename... Inputs> requires (isFixedStep<Model_> && !internal::leadsWithSteps<Inputs...>) | |
| auto | predict (Inputs const &... inputs) |
| Mixes the modes' components through the chain, moves each by its mode's fixed-step model's step, by that model's method, with inputs passed as in Emrys::predict(), and moves the mode probabilities one step of the chain, returning as predict(dt, inputs...) does. | |
| template<typename... Inputs> requires isFixedStep<Model_> | |
| auto | predict (Steps steps, Inputs const &... inputs) |
| Moves the state forward by steps of the fixed-step models, as that many calls of predict(inputs...) do, with inputs at every step: the chain takes a step each time. | |
| template<typename... Inputs> requires (!isFixedStep<Model_>) | |
| JointType | predictJoint (TimeStep< Scalar > auto const &dt, Inputs const &... inputs) |
| Moves the state forward as predict(dt, inputs...) does. | |
|
template<typename JointAllocator, typename... Inputs> requires (!isFixedStep<Model_>) | |
| void | predictJoint (TimeStep< Scalar > auto const &dt, HybridPredictedJoint< SpaceType, ModeSpaceType, Scalar, JointAllocator > &joint, Inputs const &... inputs) |
| As predictJoint(dt, inputs...), but into joint, whose storage is reused: with the same joint at every step, recording allocates nothing once it has been filled. | |
| template<typename... Inputs> requires (isFixedStep<Model_> && !internal::leadsWithSteps<Inputs...>) | |
| JointType | predictJoint (Inputs const &... inputs) |
| Moves the state forward as predict(inputs...) does with fixed-step models. | |
|
template<typename JointAllocator, typename... Inputs> requires isFixedStep<Model_> | |
| void | predictJoint (HybridPredictedJoint< SpaceType, ModeSpaceType, Scalar, JointAllocator > &joint, Inputs const &... inputs) |
| As predictJoint(inputs...), but into joint, whose storage is reused. | |
| template<Measurement M, typename Policy = reductions::Collapse> | |
| auto | update (M const &measurement, Policy const &policy={}) |
| Conditions each mode's component on measurement, by the measurement's own method, reduces its branches with policy (Collapse, Select, or a Gate), and multiplies each mode's probability by \( p(z \mid m) \). | |
| template<Measurement M, typename Policy, typename ModeUpdate, typename ResultAllocator> | |
| std::expected< void, NumericError > | update (M const &measurement, Policy const &policy, ImmFilterUpdate< ModeUpdate, Scalar, ResultAllocator > &result) |
| As update(measurement, policy), but into result, whose storage is reused: with the same result at every step, an update allocates nothing once it has been as large. | |
| template<typename P, Measurement... Ms, typename Policy = reductions::Collapse> | |
| auto | update (SwitchingMeasurement< P, Ms... > const &measurement, Policy const &policy={}) |
| As update(measurement, policy), but with a measurement per value of the mode axis that measurement names (see SwitchingMeasurement): each mode is updated by the measurement that its value in that axis selects, and its own likelihood \( p(z \mid m) \) reweights it. | |
| template<typename P, Measurement... Ms, typename Policy, typename ModeUpdate, typename ResultAllocator> | |
| std::expected< void, NumericError > | update (SwitchingMeasurement< P, Ms... > const &measurement, Policy const &policy, ImmFilterUpdate< ModeUpdate, Scalar, ResultAllocator > &result) |
| As update(measurement, policy) with a SwitchingMeasurement, but into result, whose storage is reused. | |
The autonomous multiple model (AMM) estimator: a bank of filters, one per mode, each running on its own, and the probability that each mode is the one in force, by Bayes' rule over their measurement likelihoods.
The mode is fixed for all time but unknown, so it is a parameter to identify rather than a state that switches: the ImmFilter with the identity chain, which this class builds from the state's modes and gives its base. The two are one algorithm, with \( \Pi = I \), so every IMM step works here unchanged. Mixing through the identity gives each mode its own component, and the IMM's predict() sees the identity and skips it: each mode's component moves through its own process model as a KalmanFilter's would, and the mode probabilities carry over. update() updates each component and multiplies each mode's probability by \( p(z \mid m) \). The combined estimate is the collapsed() of the state's density.
The models are a pack, so the filter's upkeep comes before the state, after the method if one is given, and maintain() runs it:
Its known failure is a mode probability that falls to zero, or so near it that no run of measurements brings it back: the estimator then cannot follow a mode that changes after all, nor recover from a mode that was wrongly ruled out. FloorModes, applied after each update, bounds the probabilities below. The chain stays the base's to change through model(); a chain that is no longer the identity makes the filter the IMM it is built on.
The multiple model estimator that Athans et al. (1977), §V.B–C, credit to Magill (1965): a Kalman filter per model and the probabilities of equation (5.5). Theirs are steady-state filters with constant innovation covariances; here each mode's component is a full filter's, so its likelihood is exact under the mode. Bar-Shalom, Li, andKirubarajan (2001) set it beside the IMM.
| Component_ | the component given one mode (see Component), a Gaussian over the state space (see Spaces) |
| Model_ | a SwitchingModel over the mode space, with the mode space as its own axis: one process model per mode, or one shared |
| Method_ | the prediction method of every mode whose model carries none of its own (see withMethod()); ModelsMethod with fixed-step models, which all carry one |
| Allocator_ | the state's allocator (see Allocation) |
| Upkeep_ | the upkeep maintain() runs on the state (see Upkeep), upkeep::None unless given one, such as FloorModes |
|
inline |
As AmmFilter(state, models...), predicting by method.
The method comes first because the models are a pack; fixed-step models carry their own, so there is none to give.
|
inline |
As AmmFilter(state, models...), with upkeep upkeep, which maintain() runs.
The upkeep comes before the state because the models are a pack.