EmrysFilter 0.1.0
State estimation utilities in C++23 using Eigen
Loading...
Searching...
No Matches
MeasurementUpdate.h
Go to the documentation of this file.
1#pragma once
2
9
10#include <array>
11#include <concepts>
12#include <cstddef>
13#include <expected>
14#include <optional>
15#include <span>
16#include <tuple>
17#include <type_traits>
18#include <utility>
19#include <variant>
20#include <vector>
21
22#include <Eigen/Cholesky>
23
41
42namespace Emrys
43{
44
52template <typename Space, typename MeasurementSpace, typename Scalar = double>
54{
55 Scalar logWeight;
58 Eigen::Index mode = 0;
59 Eigen::Index component;
60
62 std::size_t iterations = 1;
63
65 bool converged = true;
66
68 [[nodiscard]] Scalar
70 {
72 }
73
77 [[nodiscard]] Scalar
78 nis() const
79 {
80 return innovation.nis();
81 }
82};
83
84namespace internal
85{
86
87struct MixtureEvidenceAccess;
88
89} // namespace internal
90
101template <
102 typename Space,
103 typename MeasurementSpace,
104 std::size_t Count = std::dynamic_extent,
105 typename Scalar_ = double,
106 typename Allocator = DefaultAllocator>
108{
109 using Scalar = Scalar_;
110 using SpaceType = Space;
111 using MeasurementSpaceType = MeasurementSpace;
113 using allocator_type = Allocator;
114
118 using Container = std::conditional_t<
119 Count == std::dynamic_extent,
120 internal::Buffer<BranchType, Allocator>,
121 std::array<BranchType, Count>>;
122
123 static constexpr std::size_t BranchCount = Count;
124
126
127 MeasurementUpdate() = default;
128
132 MeasurementUpdate(Container branches, Scalar mixtureLogLikelihood = 0)
133 : branches{std::move(branches)}
134 , m_mixtureLogLikelihood{mixtureLogLikelihood}
135 {}
136
138 [[nodiscard]] Scalar
140 {
141 if constexpr (Count == 1)
142 {
143 return branches.front().logLikelihood();
144 }
145 else
146 {
147 return m_mixtureLogLikelihood;
148 }
149 }
150
152 [[nodiscard]] Eigen::Index
154 {
155 return branches.front().innovation.differenceDimension();
156 }
157
161 [[nodiscard]] Allocator
163 {
164 if constexpr (Count == std::dynamic_extent)
165 {
166 return Allocator(branches.get_allocator());
167 }
168 else
169 {
170 return Allocator{};
171 }
172 }
173
174private:
175
176 friend struct internal::MixtureEvidenceAccess;
177
181 Scalar m_mixtureLogLikelihood = 0;
182};
183
184namespace internal
185{
186
188template <typename T>
189inline constexpr bool isMeasurementUpdate = false;
190
192template <typename Space, typename MeasurementSpace, std::size_t Count, typename Scalar, typename Allocator>
193inline constexpr bool isMeasurementUpdate<MeasurementUpdate<Space, MeasurementSpace, Count, Scalar, Allocator>> = true;
194
196
197} // namespace internal
198
205template <typename MeasurementSpace, typename Scalar = double>
207{
208 Scalar logWeight;
210 Eigen::Index mode = 0;
211 Eigen::Index component;
212 std::size_t iterations = 1;
213 bool converged = true;
214
216 [[nodiscard]] Scalar
218 {
219 return innovation.logLikelihood();
220 }
221
223 [[nodiscard]] Scalar
224 nis() const
225 {
226 return innovation.nis();
227 }
228};
229
245template <
246 typename MeasurementSpace,
247 std::size_t Count = std::dynamic_extent,
248 typename Scalar_ = double,
249 typename Allocator = DefaultAllocator>
251{
252 using Scalar = Scalar_;
253 using MeasurementSpaceType = MeasurementSpace;
255 using allocator_type = Allocator;
256
260 using Container = std::conditional_t<
261 Count == std::dynamic_extent,
262 internal::Buffer<BranchType, Allocator>,
263 std::array<BranchType, Count>>;
264
265 static constexpr std::size_t BranchCount = Count;
266
268
269 bool accepted = false;
270
271 FilterUpdate() = default;
272
276 FilterUpdate(Container branches, Scalar mixtureLogLikelihood = 0, bool accepted = false)
277 : branches{std::move(branches)}
279 , m_mixtureLogLikelihood{mixtureLogLikelihood}
280 {}
281
283 [[nodiscard]] Scalar
285 {
286 if constexpr (Count == 1)
287 {
288 return branches.front().logLikelihood();
289 }
290 else
291 {
292 return m_mixtureLogLikelihood;
293 }
294 }
295
297 [[nodiscard]] Eigen::Index
299 {
300 return branches.front().innovation.differenceDimension();
301 }
302
306 [[nodiscard]] Allocator
308 {
309 if constexpr (Count == std::dynamic_extent)
310 {
311 return Allocator(branches.get_allocator());
312 }
313 else
314 {
315 return Allocator{};
316 }
317 }
318
319private:
320
321 friend struct internal::MixtureEvidenceAccess;
322
326 Scalar m_mixtureLogLikelihood = 0;
327
332 Scalar m_logKeptWeight = 0;
333};
334
335namespace internal
336{
337
343struct MixtureEvidenceAccess
344{
348 template <typename U>
349 static void
350 setLogKeptWeight(U & update, typename U::Scalar value)
351 {
352 update.m_logKeptWeight = value;
353 }
354
358 template <typename U>
359 [[nodiscard]] static typename U::Scalar
360 logKeptWeight(U const & update)
361 {
362 return update.m_logKeptWeight;
363 }
364
366 template <typename U>
367 static void
368 setMixtureLogLikelihood(U & update, typename U::Scalar value)
369 {
370 update.m_mixtureLogLikelihood = value;
371 }
372
374 template <typename U>
375 [[nodiscard]] static typename U::Scalar
376 mixtureLogLikelihood(U const & update)
377 {
378 return update.m_mixtureLogLikelihood;
379 }
380};
381
382} // namespace internal
383
400template <typename Space, typename MeasurementSpace, typename Scalar = double, typename Allocator = DefaultAllocator>
401struct ReusableFilterUpdate : FilterUpdate<MeasurementSpace, std::dynamic_extent, Scalar, Allocator>
402{
404
407
409
411 explicit ReusableFilterUpdate(Allocator const & allocator)
412 : Base{typename Base::Container(allocator), Scalar(0), false}
413 , measured{typename MeasuredType::Container(allocator), Scalar(0)}
414 {}
415
418
420 ReusableFilterUpdate(ReusableFilterUpdate const & other, Allocator const & allocator)
421 : Base{
422 typename Base::Container(other.branches, typename Base::Container::allocator_type(allocator)),
423 internal::MixtureEvidenceAccess::mixtureLogLikelihood(other),
424 other.accepted
425 }
426 , measured{
428 other.measured.branches,
430 ),
431 internal::MixtureEvidenceAccess::mixtureLogLikelihood(other.measured)
432 }
433 {
434 internal::MixtureEvidenceAccess::setLogKeptWeight(*this, internal::MixtureEvidenceAccess::logKeptWeight(other));
435 }
436
440 ReusableFilterUpdate(ReusableFilterUpdate && other, Allocator const & allocator)
441 : Base{
442 typename Base::Container(std::move(other.branches), typename Base::Container::allocator_type(allocator)),
443 internal::MixtureEvidenceAccess::mixtureLogLikelihood(other),
444 other.accepted
445 }
446 , measured{
447 typename MeasuredType::Container(
448 std::move(other.measured.branches),
449 typename MeasuredType::Container::allocator_type(allocator)
450 ),
451 internal::MixtureEvidenceAccess::mixtureLogLikelihood(other.measured)
452 }
453 {
454 internal::MixtureEvidenceAccess::setLogKeptWeight(*this, internal::MixtureEvidenceAccess::logKeptWeight(other));
455 }
456
458 operator=(ReusableFilterUpdate const &) = default;
459
461 operator=(ReusableFilterUpdate &&) noexcept = default;
462
463 ~ReusableFilterUpdate() = default;
464
466};
467
468namespace internal
469{
470
472template <typename MeasurementSpace, std::size_t Count, typename Scalar, typename Allocator>
473std::true_type
475
477std::false_type
478isFilterUpdateTest(void const *);
479
481template <typename U>
482inline constexpr bool isFilterUpdate = decltype(isFilterUpdateTest(static_cast<U const *>(nullptr)))::value;
483
487template <typename Space, typename MeasurementSpace, std::size_t Count, typename Scalar, typename Allocator>
488struct FilterUpdateWithScratchOf
489{
492};
493
495template <typename Space, typename MeasurementSpace, typename Scalar, typename Allocator>
496struct FilterUpdateWithScratchOf<Space, MeasurementSpace, std::dynamic_extent, Scalar, Allocator>
497{
499};
500
502
504template <typename Space, typename MeasurementSpace, std::size_t Count, typename Scalar, typename Allocator>
505using FilterUpdateWithScratch =
506 typename FilterUpdateWithScratchOf<Space, MeasurementSpace, Count, Scalar, Allocator>::type;
507
514template <typename Update, typename Allocator>
515struct RebindUpdateAllocatorOf
516{
518 using type = Update;
519};
520
522template <typename Space, typename MeasurementSpace, typename Scalar, typename Old, typename Allocator>
523struct RebindUpdateAllocatorOf<ReusableFilterUpdate<Space, MeasurementSpace, Scalar, Old>, Allocator>
524{
526};
527
528template <typename Update, typename Error, typename Allocator>
529struct RebindUpdateAllocatorOf<std::expected<Update, Error>, Allocator>
530{
531 using type = std::expected<typename RebindUpdateAllocatorOf<Update, Allocator>::type, Error>;
532};
533
535
539template <typename Update, typename Allocator>
540using RebindUpdateAllocator = typename RebindUpdateAllocatorOf<Update, Allocator>::type;
541
546template <typename Update, typename Allocator>
547concept EmptyFromAllocator = std::is_constructible_v<Update, Allocator const &>;
548
552template <typename Update, typename Allocator>
553 requires EmptyFromAllocator<Update, Allocator>
554[[nodiscard]] Update
555emptyUpdate(Allocator const & allocator)
556{
557 return Update(allocator);
558}
559
560} // namespace internal
561
562} // namespace Emrys
The allocator conventions of decisions.md [allocation]: DefaultAllocator, Capacity,...
Spaces built from other spaces (decisions.md [sizes-and-dimensions], [several-resizable-blocks]): Com...
The coordinate types (decisions.md [no-bounded-coordinates]): Linear, plain coordinates,...
Execution policies (decisions.md [execution-policies]): execution::sequential, the ExecutionPolicy co...
The Gaussian: its parameters GaussianParams, the Gaussian that evaluates the density,...
What marginals and conditionals are built from: resolving Eigen index sets against a space; the share...
What a transform returns and what a measurement update reads from it (decisions.md [linearization-for...
The macros every header includes first.
The mixture: the parameters MixtureParams of weighted components of one type (decisions....
Products of fixed-size matrices by Eigen's fixed-size product at every size: multiply() is by Eigen'...
Product: the product of independent densities, each on its own block of a space, built with on<Path>(...
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...
Subspaces, and growing and shrinking blocks (decisions.md [several-resizable-blocks]).
Tag paths and the index utilities (decisions.md [tag-addressing], [index-names]): TagPath and TagPath...
Propagating a distribution through a function (decisions.md [method-per-measurement],...
Log-weights: the WeightError a normalization can fail with (NumericError.h), and the streaming log-su...
A Gaussian distribution: a mean and covariance in a space.
Definition Gaussian.h:259
The innovation of an update: the residual of the observation from the predicted output,...
Definition Linearization.h:536
Scalar nis() const
Definition Linearization.h:608
Scalar logLikelihood() const
Definition Linearization.h:615
A type usable as the space of a distribution.
Definition Space.h:186
std::allocator< std::byte > DefaultAllocator
The allocator a type with a run-time count uses unless given one.
Definition Allocation.h:47
std::expected< CategoricalUpdate< Space, Scalar >, WeightError > update(CategoricalParams< Space, Scalar > const &prior, E const &emission)
Definition Emission.h:97
One branch of a filter's update (see FilterUpdate): its weight, its innovation, and its labels,...
Definition MeasurementUpdate.h:207
Eigen::Index component
Definition MeasurementUpdate.h:211
bool converged
Definition MeasurementUpdate.h:213
Innovation< MeasurementSpace, Scalar > innovation
Definition MeasurementUpdate.h:209
Scalar logLikelihood() const
Definition MeasurementUpdate.h:217
Scalar nis() const
Definition MeasurementUpdate.h:224
std::size_t iterations
Definition MeasurementUpdate.h:212
Eigen::Index mode
Definition MeasurementUpdate.h:210
Scalar logWeight
Definition MeasurementUpdate.h:208
static constexpr std::size_t BranchCount
Definition MeasurementUpdate.h:265
FilterUpdate()=default
no branches, not accepted
MeasurementSpace MeasurementSpaceType
the measurement space
Definition MeasurementUpdate.h:253
Allocator get_allocator() const
Definition MeasurementUpdate.h:307
std::conditional_t< Count==std::dynamic_extent, internal::Buffer< BranchType, Allocator >, std::array< BranchType, Count > > Container
The branches' container: an array when their number is known at compile time, and otherwise a buffer ...
Definition MeasurementUpdate.h:260
Scalar logLikelihood() const
Definition MeasurementUpdate.h:284
Eigen::Index innovationSize() const
Definition MeasurementUpdate.h:298
Allocator allocator_type
where a run-time number of branches comes from
Definition MeasurementUpdate.h:255
FilterBranch< MeasurementSpace, Scalar > BranchType
one branch
Definition MeasurementUpdate.h:254
FilterUpdate(Container branches, Scalar mixtureLogLikelihood=0, bool accepted=false)
The branches branches, as MeasurementUpdate(branches, mixtureLogLikelihood), and whether the policy a...
Definition MeasurementUpdate.h:276
Scalar_ Scalar
the scalar type
Definition MeasurementUpdate.h:252
The result of update(): weighted branches, one per noise component, and the observation's log-likelih...
Definition MeasurementUpdate.h:108
static constexpr std::size_t BranchCount
Definition MeasurementUpdate.h:123
Allocator get_allocator() const
Definition MeasurementUpdate.h:162
MeasurementUpdate(Container branches, Scalar mixtureLogLikelihood=0)
The branches branches of an observation whose log-likelihood, where they are more than the one a sing...
Definition MeasurementUpdate.h:132
Space SpaceType
the state's space
Definition MeasurementUpdate.h:110
MeasurementUpdate()=default
no branches
Scalar logLikelihood() const
Definition MeasurementUpdate.h:139
Scalar_ Scalar
the scalar type
Definition MeasurementUpdate.h:109
Allocator allocator_type
where a run-time number of branches comes from
Definition MeasurementUpdate.h:113
Eigen::Index innovationSize() const
Definition MeasurementUpdate.h:153
MeasurementSpace MeasurementSpaceType
the measurement space
Definition MeasurementUpdate.h:111
UpdateBranch< Space, MeasurementSpace, Scalar > BranchType
one branch
Definition MeasurementUpdate.h:112
std::conditional_t< Count==std::dynamic_extent, internal::Buffer< BranchType, Allocator >, std::array< BranchType, Count > > Container
The branches' container: an array when their number is known at compile time, and otherwise a buffer ...
Definition MeasurementUpdate.h:118
A FilterUpdate of a run-time number of branches that keeps the MeasurementUpdate it was last filled f...
Definition MeasurementUpdate.h:402
ReusableFilterUpdate(Allocator const &allocator)
Empty, with its branches and scratch from allocator.
Definition MeasurementUpdate.h:411
ReusableFilterUpdate(ReusableFilterUpdate &&) noexcept=default
takes other's storage
MeasurementUpdate< Space, MeasurementSpace, std::dynamic_extent, Scalar, Allocator > MeasuredType
The measurement's branches it keeps.
Definition MeasurementUpdate.h:406
ReusableFilterUpdate(ReusableFilterUpdate const &)=default
copies, keeping the source's allocator
ReusableFilterUpdate & operator=(ReusableFilterUpdate const &)=default
copies, keeping this allocator
MeasuredType measured
the branches of the last fill, posteriors included, reused by the next
Definition MeasurementUpdate.h:465
FilterUpdate< MeasurementSpace, std::dynamic_extent, Scalar, Allocator > Base
the update it is
Definition MeasurementUpdate.h:403
ReusableFilterUpdate()=default
empty, from a default-constructed allocator
ReusableFilterUpdate & operator=(ReusableFilterUpdate &&) noexcept=default
takes other's storage
ReusableFilterUpdate(ReusableFilterUpdate &&other, Allocator const &allocator)
Moves other into storage from allocator, taking its storage when the allocators are equal.
Definition MeasurementUpdate.h:440
One outcome of an update: a posterior, how probable it is, and its innovation, from which the observa...
Definition MeasurementUpdate.h:54
Eigen::Index component
Definition MeasurementUpdate.h:59
Scalar nis() const
Definition MeasurementUpdate.h:78
Scalar logWeight
Definition MeasurementUpdate.h:55
std::size_t iterations
Definition MeasurementUpdate.h:62
Scalar logLikelihood() const
Definition MeasurementUpdate.h:69
bool converged
Definition MeasurementUpdate.h:65
GaussianParams< Space, Scalar > posterior
Definition MeasurementUpdate.h:56
Eigen::Index mode
Definition MeasurementUpdate.h:58
Innovation< MeasurementSpace, Scalar > innovation
Definition MeasurementUpdate.h:57