EmrysFilter 0.1.0
State estimation utilities in C++23 using Eigen
Loading...
Searching...
No Matches
Transforms

transform() pushes independent uncertain inputs through a function \( y = f(x) \boxplus v \) and returns the distribution of \( y \) as a Gaussian (decisions.md [transform-policies]). More...

Namespaces

namespace  Emrys::updates
 The covariance update forms, each made by its factory (decisions.md [policy-factories], [covariance-update-forms]): standard(), symmetric(), and joseph().
namespace  Emrys::methods
 The transform methods and the sigma-point rules, each made by its factory (decisions.md [policy-factories], [method-per-measurement]): linearized(), unscented(), cubature(), sphericalSimplex(), gaussHermite(), and iterated().

Concepts

concept  Emrys::CovarianceUpdate
 One of the covariance updates: updates::Standard, updates::Symmetric, or updates::Joseph.
concept  Emrys::UncertainInput
 An argument of transform() that is uncertain: something with a mean, a space, and either a covariance, whose lower triangle covarianceLower() gives, or a lower-triangular root \( S \) of it, \( S S^T = \Sigma \), which root() gives.
concept  Emrys::UnscentedRule
 A rule for the scaled unscented transform's parameters by the number of coordinates it spreads its points over: a method that places Unscented's \( 2L + 1 \) points with Unscented's weights, at the \( \alpha \), \( \beta \), and \( \kappa \) it gives for each \( L \).
concept  Emrys::PointSet
 A set of sigma points other than Unscented's: a method that evaluates a function at weighted points given in the coordinates of a root of the covariance, with one weight per point for the mean and the covariance alike.
concept  Emrys::TransformMethod
 A method observe() can take: Linearized, an UnscentedRule (Unscented, FourthMomentUnscented, or one of the user's own), a PointSet (Cubature, SphericalSimplex, GaussHermite, or one of the user's own), or an Iterated one of them.

Classes

struct  Emrys::Conditioned< Space, OutputSpace, Scalar >
 The result of condition(): the posterior, and the innovation, from which the log-likelihood of the observation follows when asked for. More...
struct  Emrys::updates::Standard
 The standard covariance update of condition(): \( P - K \Sigma_{xy}^T \), which is \( (I - K H) P \) written without \( H \). More...
struct  Emrys::updates::Symmetric
 The symmetric covariance update: \( P - K \Sigma_{yy} K^T \), equal to the standard form when \( K \) is the optimal gain, and made exactly symmetric. More...
struct  Emrys::updates::Joseph
 The Joseph covariance update: \( (I - K H) P (I - K H)^T + K R K^T \), with \( H \) and \( R \) from the statistical linearization of the output in the input (see statisticalLinearization()). More...
struct  Emrys::StatisticalLinearization< InputSpace, OutputSpace, Scalar >
 The statistical linearization of an output in an input, from statisticalLinearization(): the affine function of the input that best predicts the output in mean square, \( y \approx \bar y \boxplus H (x \boxminus \mu) \), and the covariance \( \Omega \) of what it leaves unexplained. More...
struct  Emrys::JacobianForm
 The Jacobian form of a linearization (decisions.md [linearization-forms]), which methods::linearized() and a Jacobian returned with the value compute (decisions.md [returned-jacobians]): the Jacobian \( H \) of the output in the marked input at its mean, and the cross-covariance \( \Sigma_{xy} = P H^T \). More...
struct  Emrys::RootForm
 The root form of a linearization (decisions.md [linearization-forms]), which every sigma-point method computes: the root \( S \) of the marked input's covariance that spread the points, \( S S^T = P \), and the whitened cross-covariance \( \Psi = S^{-1} \Sigma_{xy} = (H S)^T \), the weighted sum \( \sum_i w_i \xi_i \Delta y_i^T \) over the unit points \( \xi_i \) and the output deviations \( \Delta y_i \). More...
class  Emrys::OutputWithCross< InputSpace, OutputSpace, Form, Scalar >
 The result of transform() with an input marked by withCross(): the output's Gaussian and its linearization in that input, in the Form the method computes it, JacobianForm or RootForm (decisions.md [linearization-forms]). More...
class  Emrys::Innovation< Space, Scalar >
 The innovation of an update: the residual \( r \) of the observation from the predicted output, normalized in the output space, and its covariance \( S \), from which the update's statistics follow (decisions.md [innovation-statistics]). More...
struct  Emrys::WithJacobian< Value, Jacobian >
 What a function returns when it knows its Jacobian: its value, and the Jacobian of its output differences in its uncertain inputs' differences, at the same point (decisions.md [returned-jacobians]). More...
struct  Emrys::UnscentedParams< Scalar >
 The parameters of the scaled unscented transform over a number of coordinates, in Scalar, as an UnscentedRule gives them: \( \lambda = \alpha^2 (L + \kappa) - L \). More...
struct  Emrys::methods::Linearized
 Linearized method: \( \bar y = f(\mu) \) and \( \Sigma_{yy} = \sum_i J_i \Sigma_i J_i^T \), with the Jacobians \( J_i \) of f at the input means. More...
struct  Emrys::methods::Unscented< Alpha, Beta, Kappa >
 Unscented method: \( 2L + 1 \) sigma points over the joint input space of dimension \( L \), spread by \( \lambda = \alpha^2 (L + \kappa) - L \). More...
struct  Emrys::methods::FourthMomentUnscented
 Unscented method with \( \alpha = 1 \), \( \beta = 0 \), and \( \kappa = 3 - L \) over \( L \) coordinates, so that \( L + \lambda = 3 \): the points sit at \( \sqrt 3 \) standard deviations along each column of the root whatever \( L \) is, and their fourth moment along each column is a Gaussian's, 3. More...
struct  Emrys::methods::Cubature
 Cubature method: the \( 2L \) points \( \mu \boxplus \pm \sqrt{L} \, S_j \) over the joint input space of dimension \( L \), for each column \( S_j \) of a root of the joint covariance, equally weighted by \( 1 / (2L) \), with no center point and no parameter. More...
struct  Emrys::methods::SphericalSimplex< CenterWeight >
 Spherical simplex method: \( L + 2 \) points over the joint input space of dimension \( L \), the mean with weight centerWeight \( W_0 \) and \( L + 1 \) points of weight \( (1 - W_0) / (L + 1) \) on a sphere of radius \( \sqrt{L / (1 - W_0)} \) about it, in the coordinates of a root of the joint covariance. More...
struct  Emrys::methods::GaussHermite< Order >
 Gauss-Hermite method: the product rule of Order points per coordinate over the joint input space of dimension \( L \), \( \mathrm{Order}^L \) points in the coordinates of a root of the joint covariance. More...
struct  Emrys::methods::Spread< Rule, A >
 A sigma-point rule spread by axes of its own (decisions.md [sigma-point-axes]): Rule's unit points and weights, an UnscentedRule or a PointSet, carried into the input by the root A takes (Axes), in place of the default, roots::cholesky(roots::pivoted()). More...
struct  Emrys::IteratedOptions< Scalar >
 The run-time settings of an Iterated method, given to methods::iterated() as iterated(method, {.tolerance = 1e-6}): what stops the iteration, in the scalar the method holds (decisions.md [policy-factories]). More...
struct  Emrys::methods::Iterated< Method, Scalar >
 Iterated method, for a measurement update: the update of Method relinearized with respect to its own posterior, with the prior held fixed, until the mean stops moving. More...
struct  Emrys::CrossMarked< Input >
 An uncertain input marked by withCross(). More...
struct  Emrys::LinearizedAbout< Reference >
 Where a step linearizes its input: a point, or a distribution, in place of the input's own mean and spread (decisions.md [linearization-reference]). More...

Functions

constexpr Standard Emrys::updates::standard ()
constexpr Symmetric Emrys::updates::symmetric ()
constexpr Joseph Emrys::updates::joseph ()
template<typename InputSpace, typename OutputSpace, typename Form, typename Scalar>
StatisticalLinearization< InputSpace, OutputSpace, Scalar > Emrys::statisticalLinearization (OutputWithCross< InputSpace, OutputSpace, Form, Scalar > const &predicted)
template<UncertainInput Prior, typename OutputSpace, typename LinearizationForm, typename Derived, CovarianceUpdate Form = updates::Standard>
auto Emrys::condition (Prior const &prior, OutputWithCross< typename Prior::SpaceType, OutputSpace, LinearizationForm, typename Prior::Scalar > const &predicted, Eigen::MatrixBase< Derived > const &observed, Form const &form={})
template<typename Value, typename Jacobian>
WithJacobian< internal::PlainResult< std::remove_cvref_t< Value > >, internal::PlainResult< std::remove_cvref_t< Jacobian > > > Emrys::withJacobian (Value &&value, Jacobian &&jacobian)
constexpr Linearized Emrys::methods::linearized ()
template<double Alpha = 1.0, double Beta = 2.0, double Kappa = 0.0>
constexpr Unscented< Alpha, Beta, Kappa > Emrys::methods::unscented ()
constexpr FourthMomentUnscented Emrys::methods::fourthMomentUnscented ()
constexpr Cubature Emrys::methods::cubature ()
template<double CenterWeight = 0.0>
constexpr SphericalSimplex< CenterWeight > Emrys::methods::sphericalSimplex ()
template<int Order = 3>
constexpr GaussHermite< Order > Emrys::methods::gaussHermite ()
template<typename Rule, typename A>
constexpr Spread< Rule, A > Emrys::methods::spread (Rule rule, A axes)
template<RealScalar Scalar = double, typename Method = Linearized>
Iterated< Method, Scalar > Emrys::methods::iterated (Method method={}, IteratedOptions< Scalar > options={})
template<UncertainInput Input>
CrossMarked< Input > Emrys::withCross (Input const &input)
 Marks the uncertain input, usually the state, whose cross-covariance with the output transform() also returns (see OutputWithCross).
template<UncertainInput Input>
void Emrys::withCross (Input const &&input)=delete
 withCross() of a temporary is deleted: the mark refers to its input, which would be gone at the end of the full expression, so a mark kept in a variable would dangle.
template<UncertainInput Distribution>
LinearizedAbout< Distribution const & > Emrys::linearizedAbout (Distribution const &distribution)
template<UncertainInput Distribution>
void Emrys::linearizedAbout (Distribution const &&distribution)=delete
 linearizedAbout() of a temporary distribution is deleted, as withCross()'s is: the mark refers to it, and it would be gone at the end of the full expression.
template<typename Derived>
LinearizedAbout< typename Derived::PlainObject > Emrys::linearizedAbout (Eigen::MatrixBase< Derived > const &point)
template<typename Method, typename F, typename... Args>
requires (!MeasurementModel<F> && !internal::isModel<F> && internal::crossCount<Args...> <= 1)
auto Emrys::transform (Method const &method, F const &f, Args const &... args)
template<typename Method, typename Model, typename... Inputs>
requires ((MeasurementModel<Model> || internal::isModel<Model>) && internal::crossCount<Inputs...> <= 1)
auto Emrys::transform (Method const &method, Model const &model, Inputs const &... inputs)

Detailed Description

transform() pushes independent uncertain inputs through a function \( y = f(x) \boxplus v \) and returns the distribution of \( y \) as a Gaussian (decisions.md [transform-policies]).

A process model maps a state to a later state; a measurement model maps a state to a measurement in its measurement space, whose minus() forms the residual of an observation. The function and its policies are a measurement model's: f takes f(x), f(in, x), or f(in, out, x), and the policies, each a call before the inputs, are reads(), writes() or outputSpace(), affineIn(), and additiveNoise(), one Gaussian \( v \). A measurement model is a transform with its inputs left unbound, and transform(method, model, inputs...) takes one in place of the function and its policies.

The inputs reach f as one vector \( x \):

  • without reads(), \( x \) is the one uncertain input (see UncertainInput: a GaussianParams, a Gaussian, a marginal of one, or a SqrtGaussianParams), whole;
  • with reads(), each input is an uncertain input over a tagged space or sure<Tag>(value), a value known exactly, matched to the items of reads() by tag in any order, and \( x \) is a vector in the Composite of the items' names, read with block<Tag>(in, x). Uncertain inputs are independent of each other, so their joint space is the concatenation of their spaces.

The result is a Gaussian in the output space. Marking one uncertain input with withCross(), usually the state, also returns its cross-covariance with y (see OutputWithCross), and condition() then conditions that input on an observation of y: the Kalman update. The other uncertain inputs are nuisance parameters, such as noise or an uncertain sensor position, whose correlations are not tracked; anything worth tracking belongs in the state.

The output space is outputSpace()'s, an instance or a function of the input space; else the Composite of writes(); else the space of the additive noise; and otherwise Linear, sized by f's return type.

The method is any TransformMethod, made by a factory in methods (decisions.md [policy-factories]). They differ in what they cost and what they ask of f; \( L \) is the difference dimension of the joint uncertain input:

Method Calls of f Exact for the mean and covariance when f is
methods::linearized() 1 affine
methods::unscented() \( 2L + 1 \) affine, or with the defaults quadratic
methods::fourthMomentUnscented(), a user's UnscentedRule \( 2L + 1 \) affine, or one coordinate squared
methods::cubature() \( 2L \) affine; quadratic, for the mean
methods::sphericalSimplex() \( L + 2 \) affine; quadratic, for the mean
methods::gaussHermite<N>() \( N^L \) of degree \( 2N - 1 \) per coordinate, for the mean
a user's PointSet its pointCount(L) as its points integrate

Linearized calls f once with dual numbers carrying \( L \) derivatives, or with plain scalars when f returns its Jacobian; every other method takes any callable. A point set over a fixed \( L \) has at most 4096 points. A model's affineIn() factors the coordinates it names out of every sigma-point method (decisions.md [affine-coordinates]), and methods::iterated() is a measurement update's method, which transform() refuses (decisions.md [iterated-update]). For \( x^2 \) the third-degree rules get the mean and miss the variance, which needs the fourth moment; methods::unscented() gets it through \( \beta = 2 \) (see statisticalLinearization()). A sigma-point rule is spread by the axes of methods::spread(), or by the default root otherwise (decisions.md [sigma-point-axes]).

To be differentiated by Linearized, f must be generic in its scalar type: take uncertain input as const auto& and build outputs with ScalarOf. A sure input reaches f in the input vector's scalar; captured constants may stay double, as Eigen mixes double with its dual numbers, but a float filter holds its constants in float. An f that knows its Jacobian returns it with its value instead, as withJacobian(), one matrix over the input's differences, and need not be generic; the sigma-point methods take the value and ignore the Jacobian, so one function serves every method.

The rules for the inputs: all uncertain inputs share one scalar; at least one input is uncertain; a marginal is an uncertain input in its tag's space. Two marginals of one Gaussian passed as two inputs are taken as independent, losing their correlation, so a state is passed once and its blocks selected inside f. withCross() refuses a temporary, a marginal made in the call included, so that nothing they mark dangles. A function's returned Eigen expression is evaluated at the call, while the arguments it refers to are alive.

The methods are the standard ones: the Kalman filter's affine case (Kalman (1960)), the first-order linearization of the extended Kalman filter (Bar-Shalom, Li, and Kirubarajan (2001)), and the unscented transform of Julier and Uhlmann (2004); Särkkä (2013), chapters 5 and 6, gives all three in one notation. The transform's job of carrying several independent inputs and a marked cross-covariance through one function, so that a measurement update is a conditioning of the joint, is how Hertzberg et al. (2013) phrase the Kalman update on a manifold.

auto const rangeBearing = []<typename T>(auto const & state) {
return Eigen::Matrix<T, 2, 1>{
Eigen::numext::sqrt(state.template head<2>().squaredNorm()), Eigen::numext::atan2(state(1), state(0))
};
};
auto const predicted = Emrys::transform(Emrys::methods::linearized(), rangeBearing,
Emrys::outputSpace(RangeBearing{}), withCross(state));
auto const updated = Emrys::condition(state, predicted, z);
// updated->posterior; updated->logLikelihood() and updated->innovation.nis() when wanted, or
// updated.error() when the predicted covariance is not positive definite
OutputSpace< std::remove_cvref_t< X > > outputSpace(X &&x)
Definition Policies.h:718
auto transform(Method const &method, F const &f, Args const &... args)
Definition Transform.h:2661
CrossMarked< Input > withCross(Input const &input)
Marks the uncertain input, usually the state, whose cross-covariance with the output transform() also...
Definition Transform.h:1649
constexpr Linearized linearized()
Definition Methods.h:333
auto condition(Prior const &prior, OutputWithCross< typename Prior::SpaceType, OutputSpace, LinearizationForm, typename Prior::Scalar > const &predicted, Eigen::MatrixBase< Derived > const &observed, Form const &form={})
Definition Condition.h:676

Function Documentation

◆ condition()

template<UncertainInput Prior, typename OutputSpace, typename LinearizationForm, typename Derived, CovarianceUpdate Form = updates::Standard>
auto Emrys::condition ( Prior const & prior,
OutputWithCross< typename Prior::SpaceType, OutputSpace, LinearizationForm, typename Prior::Scalar > const & predicted,
Eigen::MatrixBase< Derived > const & observed,
Form const & form = {} )
nodiscard
Returns
prior conditioned on an observation observed of the output of predicted, which came from transform() with prior marked by withCross(), and the log-likelihood of the observation, with the covariance updated by form (updates::Standard by default, updates::Symmetric, or updates::Joseph).

The covariance form's fold of one prediction (decisions.md [linearization-forms]), which a measurement's update, update(prior, measurement), ends in for each of its branches. It has a name of its own because it conditions the very input the prediction was made from, with no noise of its own and one posterior, where update() corrects a whole state through the blocks a measurement reads and branches on its noise.

The Kalman update: with gain \( K = \Sigma_{xy} \Sigma_{yy}^{-1} \) and residual \( r = y \boxminus \bar y \), normalized in the output space, the posterior mean is \( \mu \boxplus K r \), normalized in the prior's space, and its covariance is \( \Sigma - K \Sigma_{xy}^T \) in the standard form. Solves with the Cholesky factor of \( \Sigma_{yy} \). updates::Joseph takes \( H \) and \( R = N + \Omega \) from the prediction's parts (statisticalLinearization()), so noise passed to the transform as an uncertain input is never recovered by subtraction.

This is the update of Kalman (1960) written as the conditioning of the joint Gaussian of input and output, the form that holds for every transform method alike (Särkkä (2013), §6.1).

Returns
the Conditioned posterior and innovation, or GaussianError::NotPositiveDefinite if \( \Sigma_{yy} \) is not positive definite (decisions.md [innovation-cholesky])

◆ cubature()

Cubature Emrys::methods::cubature ( )
nodiscardconstexpr
Returns
the Cubature method

◆ fourthMomentUnscented()

FourthMomentUnscented Emrys::methods::fourthMomentUnscented ( )
nodiscardconstexpr
Returns
the FourthMomentUnscented method

◆ gaussHermite()

template<int Order = 3>
GaussHermite< Order > Emrys::methods::gaussHermite ( )
nodiscardconstexpr
Returns
the GaussHermite method of Order points per coordinate (gaussHermite<3>())

◆ iterated()

template<RealScalar Scalar = double, typename Method = Linearized>
Iterated< Method, Scalar > Emrys::methods::iterated ( Method method = {},
IteratedOptions< Scalar > options = {} )
nodiscard
Returns
an Iterated method relinearizing method (Linearized by default) until a step is within options.tolerance or options.maxIterations is reached, holding them in Scalar: double unless named, since a braced argument deduces nothing, so iterated(method, {.tolerance = 1e-6}) holds a double and iterated<float>(method, {.tolerance = 1e-6f}) a float. Asserts that the tolerance is not negative and that at least one linearization is made.

◆ joseph()

Joseph Emrys::updates::joseph ( )
nodiscardconstexpr
Returns
the Joseph covariance update

◆ linearized()

Linearized Emrys::methods::linearized ( )
nodiscardconstexpr
Returns
the Linearized method

◆ linearizedAbout() [1/2]

template<UncertainInput Distribution>
LinearizedAbout< Distribution const & > Emrys::linearizedAbout ( Distribution const & distribution)
nodiscard
Returns
the distribution distribution as the reference a step linearizes about, in place of its input's own mean and spread (decisions.md [linearization-reference]): every method linearizes over it, Linearized at its mean and a sigma-point method over its spread, and the result is carried to the input's chart and applied to the input's own moments.

A transform takes it right before the input it is for, a prediction before its inputs, and an update after its measurement:

// A shadow filter linearized about the main filter's state, as a tracker's shadow does.
auto const about = Emrys::linearizedAbout(main.state());
shadow.predict(dt, about);
auto const report = shadow.update(measurement, about);
LinearizedAbout< Distribution const & > linearizedAbout(Distribution const &distribution)
Definition Transform.h:1688

Linearized about another estimate is the linearized Kalman filter of Gelb (1974), about a nominal trajectory, here supplied at each step; about the step's own posterior it is one iteration of the iterated update (see Iterated), and a sigma-point method's is the statistical linear regression with respect to distribution of García-Fernández, Svensson, Morelande, and Särkkä (2015). The mark refers to distribution, so it is used as it is made or while distribution lives.

◆ linearizedAbout() [2/2]

template<typename Derived>
LinearizedAbout< typename Derived::PlainObject > Emrys::linearizedAbout ( Eigen::MatrixBase< Derived > const & point)
nodiscard
Returns
the point point, a column vector, copied, as the reference a step linearizes at (decisions.md [linearization-reference]). Only a linear method (Linearized) linearizes at a point; a sigma-point method needs a distribution to spread over and refuses one at compile time.

◆ sphericalSimplex()

template<double CenterWeight = 0.0>
SphericalSimplex< CenterWeight > Emrys::methods::sphericalSimplex ( )
nodiscardconstexpr
Returns
the SphericalSimplex method with the center weight CenterWeight (sphericalSimplex<0.5>())

◆ spread()

template<typename Rule, typename A>
Spread< Rule, A > Emrys::methods::spread ( Rule rule,
A axes )
nodiscardconstexpr
Returns
the sigma-point rule rule spread by the axes axes (Spread): spread(cubature(), roots::principal()), or spread(sphericalSimplex(), roots::along(d, roots::pivoted()))

◆ standard()

Standard Emrys::updates::standard ( )
nodiscardconstexpr
Returns
the Standard covariance update, the default

◆ statisticalLinearization()

template<typename InputSpace, typename OutputSpace, typename Form, typename Scalar>
StatisticalLinearization< InputSpace, OutputSpace, Scalar > Emrys::statisticalLinearization ( OutputWithCross< InputSpace, OutputSpace, Form, Scalar > const & predicted)
nodiscard
Returns
the statistical linearization of the output of predicted, which came from transform() with an input marked by withCross(), in that input: \( H \), the Jacobian of the affine fit, and \( N + \Omega \), the covariance of its error (see StatisticalLinearization), read from the prediction's parts (see OutputWithCross), so that neither needs a factorization of the input's covariance or a subtraction (decisions.md [linearization-forms]).

The error covariance holds whatever \( H \) does not explain: the other uncertain inputs, such as noise passed to the function, and the function's curvature over the input's spread. For the Linearized method it is the other inputs' part alone, and \( H \) is the Jacobian at the mean. For a sigma-point method \( H = \Psi^T S^{-1} \), and the curvature is the covariance of the fit's residuals at the points, which can be indefinite when a sigma-point weight is negative. It is returned as the method computed it, never projected onto the positive semidefinite cone: a caller that needs it semidefinite makes it so. updates::Joseph takes its \( H \) and \( R \) from here.

auto const predicted = Emrys::transform<RangeBearing>(Emrys::methods::unscented(), rangeBearing, withCross(state));
auto const [jacobian, errorCov] = Emrys::statisticalLinearization(predicted);
StatisticalLinearization< InputSpace, OutputSpace, Scalar > statisticalLinearization(OutputWithCross< InputSpace, OutputSpace, Form, Scalar > const &predicted)
Definition Condition.h:635
constexpr Unscented< Alpha, Beta, Kappa > unscented()
Definition Methods.h:389

The statistical linear regression through the transform's moments of Lefebvre, Bruyninckx, and De Schutter (2002), who read the unscented transform as one; the same formulas hold for every transform method here.

◆ symmetric()

Symmetric Emrys::updates::symmetric ( )
nodiscardconstexpr
Returns
the Symmetric covariance update

◆ transform() [1/2]

template<typename Method, typename F, typename... Args>
requires (!MeasurementModel<F> && !internal::isModel<F> && internal::crossCount<Args...> <= 1)
auto Emrys::transform ( Method const & method,
F const & f,
Args const &... args )
nodiscard
Returns
the distribution of \( y = f(x) \boxplus v \) computed by method (Linearized, or a sigma-point method), with f a function and args its policies followed by its inputs (decisions.md [transform-policies]): a Gaussian in the output space, or with an input marked by withCross(), an OutputWithCross.

The function takes f(x), f(in, x), or f(in, out, x), as a measurement model's does, and the policies are a measurement model's, each a call before the inputs: reads(), whose items each name an input by its tag; writes() or outputSpace() for the output space; affineIn(), the inputs the function is affine in, which a sigma-point method factors out (decisions.md [affine-coordinates]); and additiveNoise(), one Gaussian \( v \) added to the output. Without reads(), f reads the one uncertain input whole, as \( x \). With it, each input is a distribution over a tagged space, sure<Tag>(value), or one of them marked by withCross(), matched to the items of reads() by tag, and \( x \) is a vector in their Composite, read with block<Tag>(in, x). The output space is outputSpace()'s, given an instance or a function of the input space; else the Composite of writes(); else the noise's space; else a Linear sized by what f returns.

With a linearizedAbout() reference first among the inputs, the input after it, the only one withCross() may then mark, is linearized about the reference rather than over itself (decisions.md [linearization-reference]): the affine model \( y \approx v \boxplus A \delta \) with error covariance \( \Omega \) is taken at the reference's point, or over its distribution, in the input's chart, and the result is its mean \( v \) and covariance \( A P A^T + \Omega \), with cross-covariance \( P A^T \). About the input itself this is the transform without a reference, to rounding.

auto const y = transform(methods::unscented(), [](auto const & x) { return polar(x); }, state);
affineIn(path<ScaleNoise>), withCross(position), scaleNoise);
auto affineIn(Names const &...)
Definition Policies.h:288
auto reads(Items const &...)
Definition Policies.h:196
constexpr TagPath< Tags... > path
The path TagPath<Tags...> as a value, for a call that takes its paths as arguments rather than as tem...
Definition TagPath.h:372
constexpr Cubature cubature()
Definition Methods.h:488
See also
Transforms, condition(), linearizedAbout()

◆ transform() [2/2]

template<typename Method, typename Model, typename... Inputs>
requires ((MeasurementModel<Model> || internal::isModel<Model>) && internal::crossCount<Inputs...> <= 1)
auto Emrys::transform ( Method const & method,
Model const & model,
Inputs const &... inputs )
nodiscard
Returns
the distribution of the measurement model model's output at inputs, computed by method, as transform(method, f, policies..., inputs...) computes it with the model's function and policies: the model's predicted measurement, with its additive noise, where the inputs are the blocks it reads (decisions.md [transform-policies]). A process model is refused, since its step is predict()'s.

◆ unscented()

template<double Alpha = 1.0, double Beta = 2.0, double Kappa = 0.0>
Unscented< Alpha, Beta, Kappa > Emrys::methods::unscented ( )
nodiscardconstexpr
Returns
the Unscented method with the parameters Alpha, Beta, and Kappa (unscented<0.5>())

◆ withCross()

template<UncertainInput Input>
CrossMarked< Input > Emrys::withCross ( Input const & input)
nodiscard

Marks the uncertain input, usually the state, whose cross-covariance with the output transform() also returns (see OutputWithCross).

At most one input may be marked.

◆ withJacobian()

template<typename Value, typename Jacobian>
WithJacobian< internal::PlainResult< std::remove_cvref_t< Value > >, internal::PlainResult< std::remove_cvref_t< Jacobian > > > Emrys::withJacobian ( Value && value,
Jacobian && jacobian )
nodiscard
Returns
value with jacobian beside it, for a function to return when it knows its Jacobian (see WithJacobian). Expressions are evaluated, and plain matrices passed as rvalues are moved.

Linearized then takes the Jacobian as it is and calls the function once; the other methods use the value alone, so a function used only by them has no reason to return one.

// Ranges to anchors, and their Jacobian: each anchor's unit direction from p, negated.
auto const ranges = [&](Eigen::Vector2d const & p) {
Eigen::Matrix<double, 2, 4> const toAnchor = anchors.colwise() - p;
Eigen::Vector4d const r = toAnchor.colwise().norm().transpose();
return Emrys::withJacobian(r, -(toAnchor.array().rowwise() / r.transpose().array()).matrix().transpose());
};
WithJacobian< internal::PlainResult< std::remove_cvref_t< Value > >, internal::PlainResult< std::remove_cvref_t< Jacobian > > > withJacobian(Value &&value, Jacobian &&jacobian)
Definition Methods.h:222