EmrysFilter 0.1.0
State estimation utilities in C++23 using Eigen
Loading...
Searching...
No Matches
Emrys::Space Concept Reference

A type usable as the space of a distribution. More...

#include <EmrysFilter/Spaces/Space.h>

Concept definition

template<typename S>
concept Space = requires(S const & space) {
typename std::integral_constant<int, S::FixedValueDimension>;
typename std::integral_constant<int, S::ValueDimensionStep>;
typename std::integral_constant<int, S::MaxValueDimension>;
requires S::FixedValueDimension >= 0 && S::ValueDimensionStep >= 0;
requires(
S::ValueDimensionStep == 0
? S::MaxValueDimension == S::FixedValueDimension
: (S::MaxValueDimension == Eigen::Dynamic || S::MaxValueDimension >= S::FixedValueDimension)
);
requires std::regular<S>;
{ space.valueDimension() } -> std::convertible_to<Eigen::Index>;
requires internal::NormalizeTakesBlocks<S> && internal::PlusTakesBlocks<S> && internal::MinusTakesBlocks<S>;
requires internal::NormalizeTakesBlocks<typename internal::DifferenceSpaceOf<S>::type>;
requires internal::HasDifference<S>
|| (!internal::HasNormalize<S> && !internal::HasPlus<S> && !internal::HasMinus<S>);
requires internal::DifferenceSpaceFor<typename internal::DifferenceSpaceOf<S>::type, S>;
requires internal::HasPlus<S> == internal::HasMinus<S>;
requires internal::hasEqualSizes<S> || internal::HasPlus<S>;
requires S::ValueDimensionStep == 0 || internal::resizableBlockCount<S> > 1
|| requires(S & resizable, Eigen::Index n) { resizable.resize(n); };
}
A type usable as the space of a distribution.
Definition Space.h:186

Detailed Description

A type usable as the space of a distribution.

Linear, Periodic, Composite, Repeated, and tags derived from them satisfy it. A space written from scratch provides:

  • FixedValueDimension, ValueDimensionStep, and MaxValueDimension (int) as constant expressions, consistent with each other: a fixed space (ValueDimensionStep zero) has MaxValueDimension equal to FixedValueDimension, and a resizable one has MaxValueDimension at least FixedValueDimension, or Eigen::Dynamic;
  • valueDimension(), and resize(n) if it is resizable (a Composite with several resizable blocks has none);
  • if its values need normalizing, a const normalize() that takes any Eigen block by const reference and writes through it, rows being coordinates and columns samples;
  • if its differences are not plain values of the space itself, a const difference() returning its difference space (the library's spaces all have one, so that the difference space of a tag is never the tag): a regular type with FixedValueDimension, ValueDimensionStep, MaxValueDimension, and valueDimension(), fixed if the space is and bounded if the space is. A space with normalize() must have one, even if it returns Linear: whether differences wrap as values do is a choice to state. A space without one is its own difference space. Its sizes may differ from the space's, as a unit quaternion's differences are three-coordinate rotation vectors;
  • if \( x \boxplus \delta \) is not normalize(x + δ), a const plus(x, d, out), and if \( a \boxminus b \) is not a - b normalized in the difference space, a const minus(a, b, out). Each takes Eigen blocks by const reference, columns paired, and writes the canonical result through out, which does not alias the inputs. A space has both or neither, since a residual taken by subtraction would not invert its own update, and with them a difference(). Customization is by these members only: the library calls Emrys::plus() and Emrys::minus() qualified, so a free plus() or minus() in the space's namespace is never found;
  • optionally, for a space with its own plus(), the reset Jacobian that carries a covariance to the tangent space at a moved mean (decisions.md [covariance-reset], Reset.h): a const resetJacobian(x, d, out) that writes it in closed form at one value column x and step d into the square out, or static constexpr bool identityReset = true; when it is the identity, as for a multiplicative \( x e^\delta \). Without either it is computed by automatic differentiation of plus() and minus(), which must then take Eigen::AutoDiffScalar coefficients;
  • value semantics: default construction, copying, and equality (std::regular).

A normalize(), plus(), or minus() that is not a template and can't be called on Eigen blocks, such as one written for a single vector, keeps the type from being a Space, whether it is on the space or on its difference space: the library calls each on blocks of many columns, such as every particle's state at once. So does a template that is a near miss of the form, one that is not const or that takes a block by non-const reference, which the library would otherwise take as missing and the space as a plain vector. One the library can't see, such as a misspelled name or a member template that rejects every block, counts as missing.

A space written from scratch is a single block: a tag path can name it but not reach inside it.