16 #ifndef OPENKALMAN_LINEARTRANSFORMBASE_HPP 17 #define OPENKALMAN_LINEARTRANSFORMBASE_HPP 30 template<
typename T,
typename F>
44 template<
typename Derived>
52 template<std::size_t return_cross,
typename J,
typename D, std::size_t...ints>
53 static auto sum_noise_terms(
const J& j, D&& d, std::index_sequence<ints...>)
55 using InputDist = std::tuple_element_t<0, D>;
56 if constexpr(cholesky_form<InputDist>)
58 if constexpr (return_cross)
60 auto sqrt_c0 =square_root(covariance_of(std::get<0>(std::forward<D>(d))));
61 auto term0 = std::get<0>(j) * sqrt_c0;
64 (std::get<ints+1>(j) * (square_root(covariance_of(std::get<ints+1>(std::forward<D>(d)))))))...))),
65 make_self_contained(std::move(sqrt_c0) *
adjoint(term0))};
70 std::get<0>(j) * square_root(covariance_of(std::get<0>(std::forward<D>(d)))),
71 Matrix((std::get<ints+1>(j) * (square_root(covariance_of(std::get<ints+1>(std::forward<D>(d)))))))...)));
76 if constexpr (return_cross)
78 auto cross = make_self_contained(covariance_of(std::get<0>(std::forward<D>(d))) *
adjoint(std::get<0>(j)));
80 (std::get<0>(j) * cross) +
81 ... + (std::get<ints+1>(j) * (covariance_of(std::get<ints+1>(std::forward<D>(d))) *
adjoint(std::get<ints+1>(j)))))));
82 return std::tuple {std::move(cov), std::move(cross)};
87 (std::get<0>(j) * covariance_of(std::get<0>(std::forward<D>(d))) *
adjoint(std::get<0>(j))) + ... +
88 (std::get<ints+1>(j) * (covariance_of(std::get<ints+1>(std::forward<D>(d))) *
adjoint(std::get<ints+1>(j)))))));
101 #ifdef __cpp_concepts 102 template<std::
size_t return_cross, linearized_function<1> Trans,
103 gaussian_distribution InputDist, gaussian_distribution ... NoiseDists>
105 template<std::size_t return_cross,
typename Trans,
typename InputDist,
typename ... NoiseDists, std::enable_if_t<
106 (gaussian_distribution<InputDist> and ... and gaussian_distribution<NoiseDists>) and
107 linearized_function<Trans, 1>,
int> = 0>
109 auto transform(
const Trans& g,
const InputDist& in,
const NoiseDists& ...n)
const 111 typename Derived::template TransformModel<Trans> transform_model {g};
112 auto [mean_output, jacobians] = transform_model(mean_of(in), mean_of(n)...);
113 using re =
typename DistributionTraits<InputDist>::random_number_engine;
115 if constexpr (return_cross)
117 auto [cov_out, cross_covariance] = sum_noise_terms<true>(jacobians, std::forward_as_tuple(in, n...),
118 std::make_index_sequence<std::min(
sizeof...(NoiseDists), std::tuple_size_v<decltype(jacobians)> - 1)> {});
120 auto out = make_GaussianDistribution<re>(std::move(mean_output), std::move(cov_out));
123 return std::tuple {make_self_contained(out + transform_model.add_correction(in, n...)), cross_covariance};
125 return std::tuple {out, cross_covariance};
129 auto cov_out = sum_noise_terms<false>(jacobians, std::forward_as_tuple(in, n...),
130 std::make_index_sequence<std::min(
sizeof...(NoiseDists), std::tuple_size_v<decltype(jacobians)> - 1)> {});
132 auto out = make_GaussianDistribution<re>(std::move(mean_output), std::move(cov_out));
136 return make_self_contained(out + transform_model.add_correction(in, n...));
154 #ifdef __cpp_concepts 157 template<
typename InputDist,
typename...Ts, std::enable_if_t<
158 gaussian_distribution<InputDist> and (tuple_like<Ts> and ...),
int> = 0>
162 return Base::operator()(x, ts...);
174 #ifdef __cpp_concepts 175 template<gaussian_distribution InputDist, linearized_function<1> Trans, gaussian_distribution ... NoiseDists>
176 requires requires(Trans g, InputDist x, NoiseDists...n) { g(mean_of(x), mean_of(n)...); }
178 template<
typename InputDist,
typename Trans,
typename ... NoiseDists, std::enable_if_t<
179 (gaussian_distribution<InputDist> and ... and gaussian_distribution<NoiseDists>) and
183 auto operator()(
const InputDist& x,
const Trans& g,
const NoiseDists&...ns)
const 185 return transform<false>(g, x, ns...);
196 #ifdef __cpp_concepts 199 template<
typename InputDist,
typename...Ts, std::enable_if_t<
200 gaussian_distribution<InputDist> and (tuple_like<Ts> and ...),
int> = 0>
204 return Base::transform_with_cross_covariance(x, ts...);
216 #ifdef __cpp_concepts 217 template<gaussian_distribution InputDist, linearized_function<1> Trans, gaussian_distribution ... NoiseDists>
218 requires requires(Trans g, InputDist x, NoiseDists...n) { g(mean_of(x), mean_of(n)...); }
220 template<
typename InputDist,
typename Trans,
typename ... NoiseDists, std::enable_if_t<
221 (gaussian_distribution<InputDist> and ... and gaussian_distribution<NoiseDists>) and
227 return transform<true>(g, x, ns...);
235 #endif //OPENKALMAN_LINEARTRANSFORMBASE_HPP Definition for collections::tuple_like.
decltype(auto) constexpr concatenate_horizontal(V &&v, Vs &&... vs)
Concatenate one or more matrix objects vertically.
Definition: typed-matrix-overloads.hpp:308
Matrix(M &&) -> Matrix< Dimensions< index_dimension_of_v< M, 0 >>, Dimensions< index_dimension_of_v< M, 1 >>, passable_t< M >>
Deduce parameter types from a typed_matrix_nestable.
decltype(auto) constexpr adjoint(Arg &&arg)
Take the adjoint of a matrix.
Definition: adjoint.hpp:33
decltype(auto) constexpr LQ_decomposition(A &&a)
Perform an LQ decomposition of matrix A=[L,0]Q, L is a lower-triangular matrix, and Q is orthogonal...
Definition: LQ_decomposition.hpp:33
auto make_covariance(Arg &&arg)
Make a Covariance from a covariance_nestable, specifying the fixed_pattern.
Definition: Covariance.hpp:735
constexpr bool gaussian_distribution
T is a Gaussian distribution.
Definition: object-types.hpp:182
Mean(V &&) -> Mean< Dimensions< index_dimension_of_v< V, 0 >>, passable_t< V >>
Deduce template parameters from a typed_matrix_nestable, assuming untyped coordinates::pattern.
Definition: basics.hpp:48
Definition: LinearTransformBase.hpp:31
constexpr bool tuple_like
T is a non-empty tuple, pair, array, or other type that acts like a tuple.
Definition: tuple_like.hpp:51