EmrysFilter 0.1.0
State estimation utilities in C++23 using Eigen
Loading...
Searching...
No Matches
GaussianHistory.h
Go to the documentation of this file.
1#pragma once
2
11
12#include <list>
13#include <optional>
14#include <utility>
15
16#include <Eigen/Cholesky>
17
28
29namespace Emrys
30{
31
54template <typename Space_, typename Scalar_>
59 GaussianParams<Space_, Scalar_> const & smoothedNext
60)
61{
62 using GaussianType = GaussianParams<Space_, Scalar_>;
63 using MatrixType = typename GaussianType::MatrixType;
64 auto const & space = joint.filtered.space();
65 EMRYS_FILTER_ASSERT(
66 joint.cross.rows() == joint.filtered.differenceDimension()
67 && joint.cross.cols() == joint.predicted.differenceDimension()
68 && "the joint's cross-covariance has the wrong shape"
69 );
70 EMRYS_FILTER_ASSERT(
71 gain.rows() == joint.filtered.differenceDimension() && gain.cols() == joint.predicted.differenceDimension()
72 && "the gain has the wrong shape"
73 );
74 EMRYS_FILTER_ASSERT(
75 smoothedNext.differenceDimension() == joint.predicted.differenceDimension()
76 && "the smoothed Gaussian must be over the space the joint predicted"
77 );
78 MatrixType const predictedCov = joint.predicted.covarianceLower().template selfadjointView<Eigen::Lower>();
79 MatrixType nextCov = smoothedNext.covarianceLower().template selfadjointView<Eigen::Lower>();
80 typename GaussianType::DifferenceVectorType const correction =
81 Emrys::minus(joint.predicted.space(), smoothedNext.mean(), joint.predicted.mean());
82 internal::resetCovarianceAt<true>(
83 joint.predicted.space(),
84 joint.predicted.mean(),
85 correction,
86 smoothedNext.mean(),
87 nextCov
88 );
89 typename GaussianType::DifferenceVectorType const step = internal::multiply(gain, correction);
90 typename GaussianType::VectorType mean = Emrys::plus(space, joint.filtered.mean(), step);
91 MatrixType cov = joint.filtered.covarianceLower().template selfadjointView<Eigen::Lower>();
92 cov.noalias() += internal::multiply(internal::multiply(gain, nextCov - predictedCov), gain.transpose());
93 cov = (Scalar_(0.5) * (cov + cov.transpose())).eval();
94 internal::resetCovarianceAt(space, joint.filtered.mean(), step, mean, cov);
95 return {space, std::move(mean), std::move(cov)};
96}
97
98namespace internal
99{
100
107template <typename Space_, typename Scalar_>
109rtsGain(PredictedJoint<Space_, Scalar_> const & joint)
110{
111 using MatrixType = typename GaussianParams<Space_, Scalar_>::MatrixType;
112 EMRYS_FILTER_ASSERT(
113 joint.cross.rows() == joint.filtered.differenceDimension()
114 && joint.cross.cols() == joint.predicted.differenceDimension()
115 && "the joint's cross-covariance has the wrong shape"
116 );
117 MatrixType const predictedCov = joint.predicted.covarianceLower().template selfadjointView<Eigen::Lower>();
118 auto const ldlt = Eigen::LDLT<MatrixType>{predictedCov};
119 return internal::transposedSolve<MatrixType>(ldlt, joint.cross.transpose());
120}
121
122} // namespace internal
123
128template <typename Space_, typename Scalar_>
131{
132 return smoothStep(joint, internal::rtsGain(joint), smoothedNext);
133}
134
176template <Space Space_, RealScalar Scalar_ = double, typename Allocator_ = DefaultAllocator>
178{
179public:
180
181 using Scalar = Scalar_;
182 using SpaceType = Space_;
185 using allocator_type = Allocator_;
186 using Index = Eigen::Index;
187
201
202private:
203
204 using StepAllocator = internal::ReBound<Allocator_, Step>;
205 using ListType = std::list<Step, StepAllocator>;
206
207public:
208
209 using const_iterator = typename ListType::const_iterator;
210
212 GaussianHistory() = default;
213
215 explicit GaussianHistory(Allocator_ const & allocator)
216 : m_steps(StepAllocator(allocator))
217 {}
218
220 explicit GaussianHistory(Lag lag, Allocator_ const & allocator = {})
221 : m_steps(StepAllocator(allocator))
222 , m_lag{lag.steps}
223 {
224 EMRYS_FILTER_ASSERT(lag.steps > 0 && "a fixed-lag history keeps at least one step");
225 }
226
229 : GaussianHistory{other, other.get_allocator()}
230 {}
231
233 GaussianHistory(GaussianHistory const & other, Allocator_ const & allocator)
234 : m_steps(other.m_steps, StepAllocator(allocator))
235 , m_lag{other.m_lag}
236 {}
237
239 GaussianHistory(GaussianHistory && other) = default;
240
244 GaussianHistory(GaussianHistory && other, Allocator_ const & allocator)
245 : m_steps(std::move(other.m_steps), StepAllocator(allocator))
246 , m_lag{other.m_lag}
247 {}
248
251 operator=(GaussianHistory const & other) = default;
252
255 operator=(GaussianHistory && other) = default;
256
257 ~GaussianHistory() = default;
258
260 [[nodiscard]] allocator_type
262 {
263 return allocator_type(m_steps.get_allocator());
264 }
265
267 [[nodiscard]] std::optional<Index>
268 lag() const
269 {
270 return m_lag > 0 ? std::optional<Index>{m_lag} : std::nullopt;
271 }
272
274 [[nodiscard]] Index
275 size() const
276 {
277 return Index(m_steps.size());
278 }
279
281 [[nodiscard]] bool
282 empty() const
283 {
284 return m_steps.empty();
285 }
286
288 [[nodiscard]] Step const &
289 front() const
290 {
291 EMRYS_FILTER_ASSERT(!empty() && "the history is empty");
292 return m_steps.front();
293 }
294
296 [[nodiscard]] Step const &
297 back() const
298 {
299 EMRYS_FILTER_ASSERT(!empty() && "the history is empty");
300 return m_steps.back();
301 }
302
304 [[nodiscard]] const_iterator
305 begin() const
306 {
307 return m_steps.begin();
308 }
309
311 [[nodiscard]] const_iterator
312 end() const
313 {
314 return m_steps.end();
315 }
316
320 void
322 {
323 if (m_lag > 0 && size() == m_lag)
324 {
325 m_steps.splice(m_steps.end(), m_steps, m_steps.begin());
326 Step & step = m_steps.back();
327 step.joint = std::move(joint);
328 step.smoothed = step.joint.filtered;
329 step.gain = internal::rtsGain(step.joint);
330 }
331 else
332 {
333 GaussianType smoothed = joint.filtered;
334 typename GaussianType::MatrixType gain = internal::rtsGain(joint);
335 m_steps.push_back(Step{std::move(joint), std::move(smoothed), std::move(gain)});
336 }
337 }
338
343 void
344 smooth(GaussianType const & latest)
345 {
346 GaussianType const * next{&latest};
347 for (auto step = m_steps.rbegin(); step != m_steps.rend(); ++step)
348 {
349 step->smoothed = smoothStep(step->joint, step->gain, *next);
350 next = &step->smoothed;
351 }
352 }
353
355 void
357 {
358 m_steps.clear();
359 }
360
361private:
362
363 ListType m_steps;
364 Index m_lag = 0;
365};
366
367} // namespace Emrys
The allocator conventions of decisions.md [allocation]: DefaultAllocator, Capacity,...
The Gaussian: its parameters GaussianParams, the Gaussian that evaluates the density,...
Lag, the number of steps a fixed-lag history keeps, which every history of the Smoothers layer takes ...
The macros every header includes first.
Mathematical constants and scalar functions that work in every scalar type the library accepts,...
Products of fixed-size matrices by Eigen's fixed-size product at every size: multiply() is by Eigen'...
Process models as functions with reads and writes (decisions.md [model-policies], [continuous-time-no...
The covariance reset (decisions.md [covariance-reset]): hasIdentityReset<>, resetJacobian(),...
Solving by a factorization of a small matrix: transposedSolve() gives , the shape of a Kalman gain an...
The Space concept and what every continuous space shares (decisions.md [sizes-and-dimensions]): the t...
The record of a Kalman filter's forward pass that a smoother runs backward over: one PredictedJoint p...
Definition GaussianHistory.h:178
GaussianHistory()=default
An empty history that keeps every step.
Eigen::Index Index
Eigen's index type.
Definition GaussianHistory.h:186
void clear()
Drops every step, keeping the lag.
Definition GaussianHistory.h:356
Space_ SpaceType
the state space
Definition GaussianHistory.h:182
GaussianHistory(GaussianHistory &&other)=default
Takes other's steps.
GaussianHistory & operator=(GaussianHistory &&other)=default
Takes other's steps and lag, as std::list's move assignment does.
Scalar_ Scalar
the scalar type
Definition GaussianHistory.h:181
GaussianHistory & operator=(GaussianHistory const &other)=default
Copies other's steps and lag.
typename ListType::const_iterator const_iterator
iterates the steps, oldest first
Definition GaussianHistory.h:209
GaussianHistory(Allocator_ const &allocator)
An empty history that keeps every step, with nodes from allocator.
Definition GaussianHistory.h:215
void push(JointType joint)
Records joint as the newest step.
Definition GaussianHistory.h:321
bool empty() const
Definition GaussianHistory.h:282
PredictedJoint< Space_, Scalar_ > JointType
what each step records
Definition GaussianHistory.h:184
GaussianParams< Space_, Scalar_ > GaussianType
the smoothed Gaussian's type
Definition GaussianHistory.h:183
void smooth(GaussianType const &latest)
Fills every step's smoothed Gaussian by smoothStep(), from the newest back, given latest,...
Definition GaussianHistory.h:344
GaussianHistory(GaussianHistory const &other, Allocator_ const &allocator)
Copies other's steps into nodes from allocator.
Definition GaussianHistory.h:233
Step const & back() const
Definition GaussianHistory.h:297
Allocator_ allocator_type
the allocator the steps come from
Definition GaussianHistory.h:185
const_iterator begin() const
Definition GaussianHistory.h:305
GaussianHistory(Lag lag, Allocator_ const &allocator={})
An empty history that keeps the newest lag steps, with nodes from allocator.
Definition GaussianHistory.h:220
const_iterator end() const
Definition GaussianHistory.h:312
GaussianHistory(GaussianHistory const &other)
Copies the steps into nodes from other's allocator (see Allocation).
Definition GaussianHistory.h:228
Index size() const
Definition GaussianHistory.h:275
allocator_type get_allocator() const
Definition GaussianHistory.h:261
Step const & front() const
Definition GaussianHistory.h:289
std::optional< Index > lag() const
Definition GaussianHistory.h:268
GaussianHistory(GaussianHistory &&other, Allocator_ const &allocator)
Moves other's steps into nodes from allocator, taking its nodes when the allocators are equal.
Definition GaussianHistory.h:244
A Gaussian distribution: a mean and covariance in a space.
Definition Gaussian.h:259
typename MomentsType::MatrixType MatrixType
a matrix over differences
Definition Gaussian.h:267
MatrixType const & covarianceLower() const
Definition Gaussian.h:543
Index differenceDimension() const
Definition Gaussian.h:439
VectorType const & mean() const
Definition Gaussian.h:533
Space_ const & space() const
Definition Gaussian.h:519
CategoricalParams< Space, Scalar > smoothStep(CategoricalPredictedJoint< Space, Scalar > const &joint, CategoricalParams< Space, Scalar > const &smoothedNext)
Definition CategoricalHistory.h:114
auto plus(S const &space, Eigen::MatrixBase< XDerived > const &x, Eigen::MatrixBase< DDerived > const &d)
Definition Space.h:675
auto minus(S const &space, Eigen::MatrixBase< ADerived > const &a, Eigen::MatrixBase< BDerived > const &b)
Definition Space.h:715
One recorded prediction and its smoothed Gaussian.
Definition GaussianHistory.h:190
GaussianType smoothed
for the step's (joint.filtered), as of the last smooth(); a copy of joint.filtered until then
Definition GaussianHistory.h:196
JointType joint
the prediction as predictJoint() returned it
Definition GaussianHistory.h:191
GaussianType::MatrixType gain
The step's Rauch-Tung-Striebel gain (internal::rtsGain()), made once at push().
Definition GaussianHistory.h:199
The number of steps a fixed-lag history keeps.
Definition Lag.h:17
One prediction step as a joint: the Gaussian the step started from, the Gaussian it predicted,...
Definition ProcessModel.h:2817
MatrixType cross
: a row per difference coordinate of , a column per one of
Definition ProcessModel.h:2829
GaussianType predicted
, process noise included
Definition ProcessModel.h:2824
GaussianType filtered
, the state the step started from
Definition ProcessModel.h:2823