EmrysFilter 0.1.0
State estimation utilities in C++23 using Eigen
Loading...
Searching...
No Matches
Emrys::KalmanRecursion< Component_, Model_, Method_ > Class Template Reference

The Kalman filter's steps over one component, without the state: a process model and a prediction method, acting on a component passed in (decisions.md [filters-and-recursions]). More...

#include <EmrysFilter/Filters/KalmanFilter.h>

Public Types

using Scalar = typename Params<Component_>::Scalar
 the scalar type
using SpaceType = typename Params<Component_>::SpaceType
 the state space
using ModelType = Model_
 the process model
using MethodType = Method_
 the prediction method
using StateType = Params<Component_>
 the state the steps act on
template<Measurement M>
using UpdateType = typename decltype(internal::kalmanUpdateType<Params<Component_>, M>())::type
 What update() with M returns: a FilterUpdate in a std::expected (decisions.md [innovation-cholesky]).
template<Measurement M>
using ResultType = typename UpdateType<M>::value_type
 What update() with M fills when given a result: the FilterUpdate of UpdateType.

Public Member Functions

 KalmanRecursion (Model_ model, MethodFor< Model_, Method_ > method={})
 The recursion with process model model and prediction method method; a fixed-step model carries its own, so there is none to give.
Model_ const & model () const
Model_ & model ()
Method_ const & method () const
bool partitions (SpaceType const &space) const
template<typename... Inputs>
requires (!isFixedStep<Model_>)
auto predict (Params< Component_ > &state, TimeStep< Scalar > auto const &dt, Inputs const &... inputs) const
 Moves state forward by dt, any TimeStep (see Time steps), through the process model, with inputs passed to its model as in Emrys::predict(): an uncertain input carries its uncertainty through the dynamics, and anything else is known.
template<typename... Inputs>
requires isFixedStep<Model_>
auto predict (Params< Component_ > &state, Inputs const &... inputs) const
 Moves state forward by the fixed-step model's step, with inputs passed as in Emrys::predict(), returning as predict(state, dt, inputs...) does.
template<typename... Inputs>
requires (!isFixedStep<Model_> && !IsForm)
PredictedJoint< SpaceType, Scalar > predictJoint (Params< Component_ > &state, TimeStep< Scalar > auto const &dt, Inputs const &... inputs) const
 Moves state forward as predict(state, dt, inputs...) does.
template<typename... Inputs>
requires (isFixedStep<Model_> && !IsForm)
PredictedJoint< SpaceType, Scalar > predictJoint (Params< Component_ > &state, Inputs const &... inputs) const
 Moves state forward as predict(state, inputs...) does with a fixed-step model.
template<Measurement M, typename Policy = reductions::Collapse>
requires ( (IsForm || ReductionPolicy<Policy, internal::MeasuredUpdate<Params<Component_>, M>, Params<Component_>>) &&
!internal::isLinearizedAbout<Policy> )
UpdateType< M > update (Params< Component_ > &state, M const &measurement, Policy const &policy={}) const
 Conditions state on measurement, by the measurement's own method, and reduces the branches to the new state with policy, a ReductionPolicy to the component (Collapse, Select, or a Gate).
template<Measurement M, typename Reference, typename Policy = reductions::Collapse>
requires (IsForm || ReductionPolicy<Policy, internal::MeasuredUpdate<Params<Component_>, M>, Params<Component_>>)
UpdateType< M > update (Params< Component_ > &state, M const &measurement, LinearizedAbout< Reference > const &about, Policy const &policy={}) const
 Conditions state on measurement as update(state, measurement, policy) does, with the measurement linearized about about, a point or a distribution (see linearizedAbout()), rather than at the state (decisions.md [linearization-reference]): a shadow filter's update about the main filter's state.
template<Measurement M, typename Policy, typename Result>
requires ( (IsForm || ReductionPolicy<Policy, internal::MeasuredUpdate<Params<Component_>, M>, Params<Component_>>) &&
!internal::isLinearizedAbout<Policy> )
std::expected< void, GaussianError > update (Params< Component_ > &state, M const &measurement, Policy const &policy, Result &result) const
 update(state, measurement, policy) into result, a ResultType: the form every recursion has, so that a MixtureFilter reuses one slot per component.
template<Measurement M, typename Reference, typename Policy, typename Result>
requires (IsForm || ReductionPolicy<Policy, internal::MeasuredUpdate<Params<Component_>, M>, Params<Component_>>)
std::expected< void, GaussianError > update (Params< Component_ > &state, M const &measurement, LinearizedAbout< Reference > const &about, Policy const &policy, Result &result) const
 update(state, measurement, about, policy) into result, as update(state, measurement, policy, result) fills it.

Static Public Attributes

static constexpr bool Reentrant = true
 the steps hold no scratch

Detailed Description

template<KalmanState Component_, typename Model_, typename Method_ = DefaultMethodFor<Model_>>
class Emrys::KalmanRecursion< Component_, Model_, Method_ >

The Kalman filter's steps over one component, without the state: a process model and a prediction method, acting on a component passed in (decisions.md [filters-and-recursions]).

KalmanFilter owns a component and runs this on it; MixtureFilter runs it on each Gaussian of a mixture, and ImmFilter mixes around it. It holds no scratch, so its steps on different components may run at once (Reentrant).

The filter of Kalman (1960); with the Linearized method it is the extended Kalman filter and with Unscented the unscented Kalman filter of Julier and Uhlmann (2004) (Särkkä (2013), chapters 4 to 6). Mixture noise with Collapse is the probabilistic data association filter of Bar-Shalom and Tse (1975).

update() returns a std::expected, empty when the innovation covariance is not positive definite, with the state unchanged (decisions.md [innovation-cholesky]). An update of one branch under Collapse, Select, or a Gate over them conditions the state where it is, the gate deciding on the NIS before the state is written, so a rejected measurement copies nothing [update-outcomes]. Over a square-root or information form of the Gaussian [gaussian-forms] the steps are the form's own (FormSteps.h): predict() then returns a std::expected that says whether the form could take the step, update() takes measurement noise of one component and those policies alone, and there is no predictJoint(), since the smoother's history holds the covariance form.

Template Parameters
Component_the component the steps act on (see Component), such as a Gaussian, or a form of the Gaussian (see GaussianForm)
Model_the process model, a ProcessModel or a FixedStepModel, which partition the component's space
Method_the prediction method; a FixedStepModel's own
See also
KalmanFilter

Member Function Documentation

◆ method()

template<KalmanState Component_, typename Model_, typename Method_ = DefaultMethodFor<Model_>>
Method_ const & Emrys::KalmanRecursion< Component_, Model_, Method_ >::method ( ) const
inlinenodiscard
Returns
the prediction method

◆ model() [1/2]

template<KalmanState Component_, typename Model_, typename Method_ = DefaultMethodFor<Model_>>
Model_ & Emrys::KalmanRecursion< Component_, Model_, Method_ >::model ( )
inlinenodiscard
Returns
the process model, to change its parameters

◆ model() [2/2]

template<KalmanState Component_, typename Model_, typename Method_ = DefaultMethodFor<Model_>>
Model_ const & Emrys::KalmanRecursion< Component_, Model_, Method_ >::model ( ) const
inlinenodiscard
Returns
the process model

◆ partitions()

template<KalmanState Component_, typename Model_, typename Method_ = DefaultMethodFor<Model_>>
bool Emrys::KalmanRecursion< Component_, Model_, Method_ >::partitions ( SpaceType const & space) const
inlinenodiscard
Returns
whether the model's writes partition space, which a state must be in

◆ predict()

template<KalmanState Component_, typename Model_, typename Method_ = DefaultMethodFor<Model_>>
template<typename... Inputs>
requires (!isFixedStep<Model_>)
auto Emrys::KalmanRecursion< Component_, Model_, Method_ >::predict ( Params< Component_ > & state,
TimeStep< Scalar > auto const & dt,
Inputs const &... inputs ) const
inlinenodiscard

Moves state forward by dt, any TimeStep (see Time steps), through the process model, with inputs passed to its model as in Emrys::predict(): an uncertain input carries its uncertainty through the dynamics, and anything else is known.

Returns
nothing for a Gaussian; for a form of the Gaussian, a std::expected that is empty when the form could not take the step (decisions.md [gaussian-forms]), such as an information form with no information asked to predict through its moments

◆ predictJoint() [1/2]

template<KalmanState Component_, typename Model_, typename Method_ = DefaultMethodFor<Model_>>
template<typename... Inputs>
requires (isFixedStep<Model_> && !IsForm)
PredictedJoint< SpaceType, Scalar > Emrys::KalmanRecursion< Component_, Model_, Method_ >::predictJoint ( Params< Component_ > & state,
Inputs const &... inputs ) const
inlinenodiscard

Moves state forward as predict(state, inputs...) does with a fixed-step model.

Returns
the step as a PredictedJoint, as predictJoint(state, dt, inputs...) does

◆ predictJoint() [2/2]

template<KalmanState Component_, typename Model_, typename Method_ = DefaultMethodFor<Model_>>
template<typename... Inputs>
requires (!isFixedStep<Model_> && !IsForm)
PredictedJoint< SpaceType, Scalar > Emrys::KalmanRecursion< Component_, Model_, Method_ >::predictJoint ( Params< Component_ > & state,
TimeStep< Scalar > auto const & dt,
Inputs const &... inputs ) const
inlinenodiscard

Moves state forward as predict(state, dt, inputs...) does.

Returns
the step as a PredictedJoint: the state before it, the state after it, and their cross-covariance, for a GaussianHistory to record

◆ update() [1/4]

template<KalmanState Component_, typename Model_, typename Method_ = DefaultMethodFor<Model_>>
template<Measurement M, typename Reference, typename Policy, typename Result>
requires (IsForm || ReductionPolicy<Policy, internal::MeasuredUpdate<Params<Component_>, M>, Params<Component_>>)
std::expected< void, GaussianError > Emrys::KalmanRecursion< Component_, Model_, Method_ >::update ( Params< Component_ > & state,
M const & measurement,
LinearizedAbout< Reference > const & about,
Policy const & policy,
Result & result ) const
inlinenodiscard

update(state, measurement, about, policy) into result, as update(state, measurement, policy, result) fills it.

Returns
nothing, or the error update(state, measurement, about, policy) would return, with state unchanged and result unspecified

◆ update() [2/4]

template<KalmanState Component_, typename Model_, typename Method_ = DefaultMethodFor<Model_>>
template<Measurement M, typename Reference, typename Policy = reductions::Collapse>
requires (IsForm || ReductionPolicy<Policy, internal::MeasuredUpdate<Params<Component_>, M>, Params<Component_>>)
UpdateType< M > Emrys::KalmanRecursion< Component_, Model_, Method_ >::update ( Params< Component_ > & state,
M const & measurement,
LinearizedAbout< Reference > const & about,
Policy const & policy = {} ) const
inlinenodiscard

Conditions state on measurement as update(state, measurement, policy) does, with the measurement linearized about about, a point or a distribution (see linearizedAbout()), rather than at the state (decisions.md [linearization-reference]): a shadow filter's update about the main filter's state.

An Iterated measurement refuses a reference at compile time.

Returns
as update(state, measurement, policy) does

◆ update() [3/4]

template<KalmanState Component_, typename Model_, typename Method_ = DefaultMethodFor<Model_>>
template<Measurement M, typename Policy, typename Result>
requires ( (IsForm || ReductionPolicy<Policy, internal::MeasuredUpdate<Params<Component_>, M>, Params<Component_>>) &&
!internal::isLinearizedAbout<Policy> )
std::expected< void, GaussianError > Emrys::KalmanRecursion< Component_, Model_, Method_ >::update ( Params< Component_ > & state,
M const & measurement,
Policy const & policy,
Result & result ) const
inlinenodiscard

update(state, measurement, policy) into result, a ResultType: the form every recursion has, so that a MixtureFilter reuses one slot per component.

A result of a run-time number of branches (a ReusableFilterUpdate) is refilled within its storage, so with the same result at every step an update allocates nothing once it has been as large (see Allocation).

Returns
nothing, or the error update(state, measurement, policy) would return, with state unchanged and result unspecified

◆ update() [4/4]

template<KalmanState Component_, typename Model_, typename Method_ = DefaultMethodFor<Model_>>
template<Measurement M, typename Policy = reductions::Collapse>
requires ( (IsForm || ReductionPolicy<Policy, internal::MeasuredUpdate<Params<Component_>, M>, Params<Component_>>) &&
!internal::isLinearizedAbout<Policy> )
UpdateType< M > Emrys::KalmanRecursion< Component_, Model_, Method_ >::update ( Params< Component_ > & state,
M const & measurement,
Policy const & policy = {} ) const
inlinenodiscard

Conditions state on measurement, by the measurement's own method, and reduces the branches to the new state with policy, a ReductionPolicy to the component (Collapse, Select, or a Gate).

If the policy keeps nothing, it rejects the measurement and the state is unchanged.

Returns
the update before reduction, without its posteriors, and whether it was accepted (see FilterUpdate): each noise component's posterior probability, such as the probability that the measurement is an outlier, and its innovation, from which the observation's log-likelihood and the NIS follow when asked for (decisions.md [innovation-statistics]). The update is in a std::expected, empty, with the state unchanged, when an innovation covariance is not positive definite [innovation-cholesky] or a form could not take the update [gaussian-forms].

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