EmrysFilter 0.1.0
State estimation utilities in C++23 using Eigen
Loading...
Searching...
No Matches
Emrys::GaussianMixtureHistory< Space_, Scalar_, Allocator_ > Class Template Reference

The record of a Gaussian mixture filter's forward pass that its smoother runs backward over: one GaussianMixturePredictedJoint per prediction, each with room for its smoothed mixture. More...

#include <EmrysFilter/Smoothers/GaussianMixtureHistory.h>

Classes

class  Step
 One recorded prediction and its smoothed mixture, built from the history's allocator. More...

Public Types

using Scalar = Scalar_
 the scalar type
using SpaceType = Space_
 the state space
using JointType = GaussianMixturePredictedJoint<Space_, Scalar_, Allocator_>
 what each step records
using SmoothedType = GaussianMixtureParams<Space_, Scalar_, Allocator_>
 the smoothed mixture's type
using allocator_type = Allocator_
 the allocator the steps come from
using Index = Eigen::Index
 Eigen's index type.
using const_iterator = typename ListType::const_iterator
 iterates the steps, oldest first

Public Member Functions

 GaussianMixtureHistory ()=default
 An empty history that keeps every step.
 GaussianMixtureHistory (Allocator_ const &allocator)
 An empty history that keeps every step, with storage from allocator.
 GaussianMixtureHistory (Lag lag, Allocator_ const &allocator={})
 An empty history that keeps the newest lag steps, with storage from allocator.
 GaussianMixtureHistory (GaussianMixtureHistory const &other)
 Copies the steps into nodes from other's allocator (see Allocation).
 GaussianMixtureHistory (GaussianMixtureHistory const &other, Allocator_ const &allocator)
 Copies other's steps into storage from allocator.
 GaussianMixtureHistory (GaussianMixtureHistory &&other)=default
 Takes other's steps.
 GaussianMixtureHistory (GaussianMixtureHistory &&other, Allocator_ const &allocator)
 Moves other's steps into storage from allocator, taking its storage when the allocators are equal.
GaussianMixtureHistory & operator= (GaussianMixtureHistory const &other)=default
 Copies other's steps and lag.
GaussianMixtureHistory & operator= (GaussianMixtureHistory &&other)=default
 Takes other's steps and lag, as std::list's move assignment does.
allocator_type get_allocator () const
std::optional< Index > lag () const
Index size () const
bool empty () const
Step const & front () const
Step const & back () const
const_iterator begin () const
const_iterator end () const
void push (JointType const &joint)
 Records a copy of joint as the newest step; it must come from the predictJoint() after the newest step's.
void push (JointType &&joint)
 Records joint as the newest step, taking its storage unless the history is a full fixed-lag one, which copies it into its oldest step's.
template<typename LatestAllocator>
void smooth (GaussianMixtureParams< Space_, Scalar_, LatestAllocator > const &latest)
 Fills every step's smoothed mixture by the backward step above, from the newest back, given latest, the filter's state after the newest step: its posterior \( p(x_N \mid z_{1:N}) \), which is its own smoothed mixture, with its lineage from the newest step.
template<ExecutionPolicy P, typename LatestAllocator>
void smooth (P &&policy, GaussianMixtureParams< Space_, Scalar_, LatestAllocator > const &latest)
 smooth() under policy: each backward step's pairs and merges are a for-each over the step's components (see Execution policies), so the smoothed mixtures are Sequential's exactly.
void clear ()
 Drops every step, keeping the lag.

Detailed Description

template<Space Space_, RealScalar Scalar_ = double, typename Allocator_ = DefaultAllocator>
class Emrys::GaussianMixtureHistory< Space_, Scalar_, Allocator_ >

The record of a Gaussian mixture filter's forward pass that its smoother runs backward over: one GaussianMixturePredictedJoint per prediction, each with room for its smoothed mixture.

It is to a MixtureFilter of Gaussians what GaussianHistory is to a KalmanFilter (decisions.md [smoothing]): push() records the joint the filter's predictJoint() returns, and smooth() takes the filter's current state and fills every step's smoothed mixture, from the newest step back.

for (auto const & z : measurements)
{
history.push(filter.predictJoint(dt));
static_cast<void>(filter.update(fix(z), reductions::keep()));
static_cast<void>(reduce(filter.state())); // the caller's merge, as in examples/gaussian_mixture.cpp
}
history.smooth(filter.state());
for (auto const & step : history) { use(step.smoothed); } // p(x_k | z_{1:N}), oldest first
void push(JointType const &joint)
Records a copy of joint as the newest step; it must come from the predictJoint() after the newest ste...
Definition GaussianMixtureHistory.h:512
GaussianMixtureHistory()=default
An empty history that keeps every step.
void smooth(GaussianMixtureParams< Space_, Scalar_, LatestAllocator > const &latest)
Fills every step's smoothed mixture by the backward step above, from the newest back,...
Definition GaussianMixtureHistory.h:533
constexpr Keep keep()
Definition Reduction.h:371

Between two predictions the filter's updates and reductions branch, reweight, merge, and drop components, and its state's lineage (see MixtureLineage) records how each component descends from those at the last prediction: each component's share from each of them. Each backward step reads it:

  • every pair of a smoothed component p at k + 1 and a component n at k that it has a share from is smoothed by smoothStep(), from n's filtered Gaussian through its prediction to p's smoothed Gaussian;
  • the pair's weight is p's smoothed weight times its share from n, \( w^s_{k+1,p} \, P(n \mid m) \), where m is the filtered component at k + 1 that p smooths;
  • the pairs that share a parent n are merged into one Gaussian by moment matching, so the smoothed mixture at k has one component per filtered component at k, in the same order, with the summed weight.

A component at k that nothing at k + 1 descends from, such as one the filter pruned, keeps its filtered Gaussian with zero weight, so that the smoothed mixture lines up with the filtered one and with the lineage of the step before.

The forward-backward smoother on merged Gaussian mixtures of Rahmathullah, Svensson, and Svensson (2014), §IV and Algorithm 2, whose f-graph is the lineage and whose s-graph is the smoothed mixtures. Four departures. The paper writes each pair's weight as \( w^s_{k+1,p} \, w^f_{k+1,m}(r) \) in its (16), but its own (15), from which (16) follows, divides the branch weight by the merged node's, \( \Pr\{H^f_{k+1,m}\} = \sum_r w^f_{k+1,m}(r) \); without it, pairs through heavy nodes are counted twice over, so this takes (15), the share. The lineage keeps the share per parent rather than one weight per merged branch, which is the same once the branches from one parent are summed, as their pairs would be. The merge within each group is the full collapse to one Gaussian rather than the paper's threshold merging and pruning, which bounds the smoothed mixture by the filtered one and keeps them aligned. And the step is smoothStep(), in the cross-covariance form and the tangent space, so that it serves every prediction method and manifold states. With a policy that keeps one component per component and no merging, each component has one parent, and this is the Rauch-Tung-Striebel smoother per component; with Keep and no merging, on a plain vector space, each smoothed component has the weight and moments of the exact Gaussian-sum smoother's branches through it, since the RTS step is affine in the moments it smooths toward.

Successive records must be one predictJoint() apart, which the history asserts from the lineage's count: a filter state replaced by a copy has no lineage, and one predicted by predict() between records has no mark for it.

As with GaussianHistory, a Lag keeps the newest steps and recycles the oldest step's storage once full, so with one joint kept and refilled by predictJoint(dt, joint), at a steady number of components fixed-lag smoothing allocates nothing once the window is full. Each step's joint and smoothed mixture, and the backward step's scratch, come from the history's allocator.

Template Parameters
Space_the state space
Scalar_scalar type, double by default
Allocator_allocator for the steps, what they hold, and the scratch (see Allocation)
See also
GaussianMixturePredictedJoint, MixtureFilter::predictJoint(), MixtureLineage, GaussianHistory, Smoothers

Member Function Documentation

◆ back()

template<Space Space_, RealScalar Scalar_ = double, typename Allocator_ = DefaultAllocator>
Step const & Emrys::GaussianMixtureHistory< Space_, Scalar_, Allocator_ >::back ( ) const
inlinenodiscard
Returns
the newest step; the history must not be empty

◆ begin()

template<Space Space_, RealScalar Scalar_ = double, typename Allocator_ = DefaultAllocator>
const_iterator Emrys::GaussianMixtureHistory< Space_, Scalar_, Allocator_ >::begin ( ) const
inlinenodiscard
Returns
an iterator to the oldest step

◆ empty()

template<Space Space_, RealScalar Scalar_ = double, typename Allocator_ = DefaultAllocator>
bool Emrys::GaussianMixtureHistory< Space_, Scalar_, Allocator_ >::empty ( ) const
inlinenodiscard
Returns
whether no step is recorded

◆ end()

template<Space Space_, RealScalar Scalar_ = double, typename Allocator_ = DefaultAllocator>
const_iterator Emrys::GaussianMixtureHistory< Space_, Scalar_, Allocator_ >::end ( ) const
inlinenodiscard
Returns
an iterator past the newest step

◆ front()

template<Space Space_, RealScalar Scalar_ = double, typename Allocator_ = DefaultAllocator>
Step const & Emrys::GaussianMixtureHistory< Space_, Scalar_, Allocator_ >::front ( ) const
inlinenodiscard
Returns
the oldest step kept; the history must not be empty

◆ get_allocator()

template<Space Space_, RealScalar Scalar_ = double, typename Allocator_ = DefaultAllocator>
allocator_type Emrys::GaussianMixtureHistory< Space_, Scalar_, Allocator_ >::get_allocator ( ) const
inlinenodiscard
Returns
the allocator the steps come from

◆ lag()

template<Space Space_, RealScalar Scalar_ = double, typename Allocator_ = DefaultAllocator>
std::optional< Index > Emrys::GaussianMixtureHistory< Space_, Scalar_, Allocator_ >::lag ( ) const
inlinenodiscard
Returns
the most steps a fixed-lag history keeps, or nothing if it keeps every step

◆ push()

template<Space Space_, RealScalar Scalar_ = double, typename Allocator_ = DefaultAllocator>
void Emrys::GaussianMixtureHistory< Space_, Scalar_, Allocator_ >::push ( JointType const & joint)
inline

Records a copy of joint as the newest step; it must come from the predictJoint() after the newest step's.

A full fixed-lag history drops its oldest step and copies joint into its storage.

◆ size()

template<Space Space_, RealScalar Scalar_ = double, typename Allocator_ = DefaultAllocator>
Index Emrys::GaussianMixtureHistory< Space_, Scalar_, Allocator_ >::size ( ) const
inlinenodiscard
Returns
the number of steps recorded, at most lag()

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