The record of an IMM filter's forward pass that its smoother runs backward over: one HybridPredictedJoint per prediction, each with room for its smoothed HybridGaussian.
More...
|
|
| HybridGaussianHistory ()=default |
| | An empty history that keeps every step.
|
|
| HybridGaussianHistory (Allocator_ const &allocator) |
| | An empty history that keeps every step, with storage from allocator.
|
|
| HybridGaussianHistory (Lag lag, Allocator_ const &allocator={}) |
| | An empty history that keeps the newest lag steps, with storage from allocator.
|
|
| HybridGaussianHistory (HybridGaussianHistory const &other) |
| | Copies the steps into nodes from other's allocator (see Allocation).
|
|
| HybridGaussianHistory (HybridGaussianHistory const &other, Allocator_ const &allocator) |
| | Copies other's steps into storage from allocator.
|
|
| HybridGaussianHistory (HybridGaussianHistory &&other)=default |
| | Takes other's steps.
|
|
| HybridGaussianHistory (HybridGaussianHistory &&other, Allocator_ const &allocator) |
| | Moves other's steps into storage from allocator, taking its storage when the allocators are equal.
|
|
HybridGaussianHistory & | operator= (HybridGaussianHistory const &other)=default |
| | Copies other's steps and lag.
|
|
HybridGaussianHistory & | operator= (HybridGaussianHistory &&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.
|
|
template<typename LatestAllocator> |
| void | smooth (HybridGaussianParams< Space_, ModeSpace_, Scalar_, LatestAllocator > const &latest) |
| | Fills every step's smoothed hybrid state by the backward IMM step above, from the newest back, given latest, the filter's state after the newest step: its posterior \( p(x_N, r_N \mid z_{1:N}) \), which is its own smoothed state.
|
|
void | clear () |
| | Drops every step, keeping the lag.
|
template<Space Space_, DiscreteSpace ModeSpace_, RealScalar Scalar_ = double, typename Allocator_ = DefaultAllocator>
class Emrys::HybridGaussianHistory< Space_, ModeSpace_, Scalar_, Allocator_ >
The record of an IMM filter's forward pass that its smoother runs backward over: one HybridPredictedJoint per prediction, each with room for its smoothed HybridGaussian.
It is to an ImmFilter what GaussianHistory is to a KalmanFilter (decisions.md [smoothing]): push() records the joint the filter's predictJoint() fills, and smooth() takes the filter's current state and fills every step's smoothed hybrid state, from the newest step back.
for (auto const & z : measurements)
{
filter.predictJoint(dt, joint);
if (!filter.update(fix(z))) { break; }
}
history.
smooth(filter.state());
for (auto const & step : history) { use(step.smoothed.modes(), step.smoothed.toDensity()->collapsed()); }
HybridGaussianHistory()=default
An empty history that keeps every step.
void push(JointType const &joint)
Records a copy of joint as the newest step.
Definition HybridGaussianHistory.h:477
void smooth(HybridGaussianParams< Space_, ModeSpace_, Scalar_, LatestAllocator > const &latest)
Fills every step's smoothed hybrid state by the backward IMM step above, from the newest back,...
Definition HybridGaussianHistory.h:503
One IMM prediction as its smoother needs it: the mode probabilities the step started from,...
Definition ImmFilter.h:138
Each backward step runs the IMM in reverse. With \( \mu_{t \mid t} \) the filtered mode probabilities, \( \Pi \) the chain, and the smoothed hybrid state at \( t + 1 \) given:
- the backward transition \( b_{ij} = p_{ji} \mu^j_{t \mid t} / e_i \), the probability of mode j at t given mode i at t + 1, with \( e_i = \sum_l p_{li} \mu^l_{t \mid t} \);
- the backward mixing \( \mu^{i \mid j} \propto b_{ij} \mu^i_{t+1 \mid N} \), the probability of mode i at t + 1 given mode j at t, and for each j the moment-matched mixture of the smoothed Gaussians at t + 1 under it;
- for each j, smoothStep() from mode j's filtered Gaussian, through the joint of its prediction by mode j's own model, to that mixture;
- the smoothed mode probabilities \( \mu^j_{t \mid N} = \sum_i \mu^i_{t+1 \mid N}\,
p(r_t = j \mid r_{t+1} = i, z_{1:N}) \), with \( p(r_t = j \mid r_{t+1} = i, z_{1:N}) \propto b_{ij}\, \mathcal{N}(\hat x^i_{t+1 \mid N};
\hat x^{j \to i}_{t+1 \mid t}, P^{j \to i}_{t+1 \mid t}) \) normalized over j, where \( \hat x^{j \to i}_{t+1 \mid t}, P^{j \to i}_{t+1 \mid t} \) is mode j's filtered Gaussian moved through mode i's model (HybridPredictedJoint::predictedThrough()): the expectation correction of Barber (2006), (12) and (13), under its mean approximation, which evaluates the average over the smoothed Gaussian at its mean.
The continuous part is the backward IMM smoother of Nadarajah (2009), ยง8.2.1, equations 8.11 to 8.17, published as Nadarajah, Tharmarasa,McDonald, and Kirubarajan (2012). It needs no backward-time dynamics, unlike the two-filter IMM smoother, and runs one RTS step per mode, not one per pair of modes. The mode probabilities are not its (8.18, 8.19), which weight each mode by \( \Lambda_j \), the density of the smoothed means at t + 1 under its own prediction, without the smoothed mode probabilities at t + 1: that left an autonomous multiple model filter's, which must stay at the final filtered ones, drifting from 0.27 to 0.003 where all were 0.034, and made a maneuver certain where enumeration gives 0.21 to 0.74. The expectation correction keeps the first exactly, since \( b_{ij} = \delta_{ij} \) for \( \Pi = I \), and the test ImmSmootherModeProbabilitiesTrackEnumeration holds it to the second; it is not the smoother of Kim (1994), \( \sum_i b_{ij} \mu^i_{t+1 \mid N} \), which is exact for \( \Pi = I \) too but loses what the later measurements say about a maneuver through the continuous state. It costs a prediction per pair of modes in predictJoint(). Three departures in the continuous part. The thesis calls \( \hat x^j_{t+1 \mid t}, P^j_{t+1 \mid t} \) the predicted mean and covariance of mode j; its derivation (8.2) divides by \( p(x_{t+1} \mid r_t = j, Z^t) \), which is mode j's filtered Gaussian moved through its own model, and its gain (8.17), \( P^j_{t \mid t} F_j^T (P^j_{t+1 \mid t})^{-1} \), is consistent only with that, so that is what ImmFilter::predictJoint() records, rather than the IMM's prediction from the mixed Gaussian. The smoothed covariance (8.16) is printed with a minus sign; this is the RTS update, with a plus, which is what the derivation gives. And the step is written with the cross-covariance and in the tangent space, as smoothStep() is, so that it serves every prediction method and manifold states. The weights are kept as logarithms; a mode no smoothed mode at t + 1 can have come from keeps its filtered Gaussian.
As with GaussianHistory, a Lag keeps the newest steps and recycles the oldest step's storage once full. A full history's push() copies the joint into that storage, so with one joint kept and refilled by predictJoint(dt, joint), fixed-lag smoothing allocates nothing once the window is full. Each step's joints and smoothed Gaussians come from the history's allocator, by uses-allocator construction.
- Template Parameters
-
| Space_ | the continuous state space |
| ModeSpace_ | the discrete mode space |
| Scalar_ | scalar type, double by default |
| Allocator_ | allocator for the steps and what they hold (see Allocation) |
- See also
- HybridPredictedJoint, ImmFilter::predictJoint(), GaussianHistory, Smoothers