OpenKalman
Transformation.hpp
1 /* This file is part of OpenKalman, a header-only C++ library for
2  * Kalman filters and other recursive filters.
3  *
4  * Copyright (c) 2018-2021 Christopher Lee Ogden <ogden@gatech.edu>
5  *
6  * This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0. If a copy of the MPL was not distributed with this
8  * file, You can obtain one at https://mozilla.org/MPL/2.0/.
9  */
10 
11 #ifndef OPENKALMAN_TRANSFORMATION_HPP
12 #define OPENKALMAN_TRANSFORMATION_HPP
13 
14 #include <type_traits>
15 
16 namespace OpenKalman
17 {
18  namespace oin = OpenKalman::internal;
19 
32  template<typename Function, typename ... TaylorDerivatives>
34 
35 
36  namespace internal
37  {
38 #ifdef __cpp_concepts
39  template<typename Function, std::size_t order, typename...TaylorDerivatives> requires
40  (order <= sizeof...(TaylorDerivatives))
41  struct is_linearized_function<Transformation<Function, TaylorDerivatives...>, order> : std::true_type {};
42 #else
43  template<typename Function, std::size_t order, typename...TaylorDerivatives>
44  struct is_linearized_function<Transformation<Function, TaylorDerivatives...>, order, std::enable_if_t<
45  (order <= sizeof...(TaylorDerivatives))>> : std::true_type {};
46 #endif
47 
48  } // namespace internal
49 
50 
51  // ------------------------------ //
52  // Non-linearized Transformation //
53  // ------------------------------ //
54 
55  template<typename Function>
56  struct Transformation<Function>
57  {
58 
61  : function {Function()} {}
62 
63 
65  template<typename F>
66  Transformation(F&& f) : function {std::forward<F>(f)} {}
67 
68 
70 #ifdef __cpp_concepts
71  template<transformation_input In, perturbation ... Perturbations>
72 #else
73  template<typename In, typename ... Perturbations, std::enable_if_t<transformation_input<In> and
74  (perturbation<Perturbations> and ...), int> = 0>
75 #endif
76  auto operator()(In&& in, Perturbations&& ... ps) const
77  {
78  return function(std::forward<In>(in), oin::get_perturbation(std::forward<Perturbations>(ps))...);
79  }
80 
81  private:
82 
83  const Function function;
84 
85  };
86 
87 
88  // -------------------------------------- //
89  // First-Order Linearized Transformation //
90  // -------------------------------------- //
91 
92  template<typename Function, typename JacobianFunction>
93  struct Transformation<Function, JacobianFunction> : Transformation<Function>
94  {
95 
96  private:
97 
99 
100  protected:
101 
102  static auto default_Jacobian(const Function& f)
103  {
104  if constexpr (linearized_function<Function, 1>) return oin::get_Taylor_term<1>(f);
105  else return JacobianFunction();
106  }
107 
108  public:
109 
112  : Base {Function()}, jacobian_fun {JacobianFunction()} {}
113 
114 
116  template<typename F>
117  Transformation(const F& f)
118  : Base {f}, jacobian_fun {default_Jacobian(f)} {}
119 
120 
122  template<typename F, typename J>
123  Transformation(const F& f, const J& j)
124  : Base {f}, jacobian_fun {j} {}
125 
126 
128 #ifdef __cpp_concepts
129  template<transformation_input In, perturbation ... Perturbations>
130 #else
131  template<typename In, typename ... Perturbations, std::enable_if_t<transformation_input<In> and
132  (perturbation<Perturbations> and ...), int> = 0>
133 #endif
134  auto jacobian(In&& in, Perturbations&& ... ps) const
135  {
136  return jacobian_fun(std::forward<In>(in), oin::get_perturbation(std::forward<Perturbations>(ps))...);
137  }
138 
139  private:
140 
141  const JacobianFunction jacobian_fun;
142  };
143 
144 
145  // ---------------------------------------- //
146  // Second-Order Linearized Transformation //
147  // ---------------------------------------- //
148 
149  template<
150  typename Function,
151  typename JacobianFunction,
152  typename HessianFunction>
153  struct Transformation<Function, JacobianFunction, HessianFunction> : Transformation<Function, JacobianFunction>
154  {
155 
156  private:
157 
159 
160  protected:
161 
162  static auto default_Hessian(const Function& f)
163  {
164  if constexpr (linearized_function<Function, 2>) return oin::get_Taylor_term<2>(f);
165  else return HessianFunction();
166  }
167 
168  public:
169 
173  : Base(), hessian_fun(HessianFunction()) {}
174 
175 
177  template<typename F>
178  Transformation(const F& f)
179  : Base {f}, hessian_fun {default_Hessian(f)} {}
180 
181 
183  template<typename F, typename J>
184  Transformation(const F& f, const JacobianFunction& j)
185  : Base(f, j), hessian_fun(default_Hessian(f)) {}
186 
187 
189  template<typename F, typename J, typename H>
190  Transformation(const F& f, const J& j, const H& h)
191  : Base(f, j), hessian_fun(h) {}
192 
193 
195 #ifdef __cpp_concepts
196  template<transformation_input In, perturbation ... Perturbations>
197 #else
198  template<typename In, typename ... Perturbations, std::enable_if_t<transformation_input<In> and
199  (perturbation<Perturbations> and ...), int> = 0>
200 #endif
201  auto hessian(In&& in, Perturbations&& ... ps) const
202  {
203  return hessian_fun(std::forward<In>(in), oin::get_perturbation(std::forward<Perturbations>(ps))...);
204  }
205 
206  private:
207 
208  const HessianFunction hessian_fun;
209 
210  };
211 
212 
213  // ------------------ //
214  // Deduction guides //
215  // ------------------ //
216 
217  template<typename Function, typename ... TaylorDerivatives>
218  Transformation(Function&&, TaylorDerivatives&& ...)
219  -> Transformation<std::decay_t<Function>, std::decay_t<TaylorDerivatives> ...>;
220 
221 
222 #ifdef __cpp_concepts
223  template<linearized_function<0> Function> requires (not linearized_function<Function, 1>)
224 #else
225  template<typename Function, std::enable_if_t<
226  linearized_function<Function, 0> and (not linearized_function<Function, 1>), int> = 0>
227 #endif
229 
230 
231 #if defined(__cpp_concepts) and OPENKALMAN_CPP_FEATURE_CONCEPTS_2
232  template<linearized_function<1> Function> requires (not linearized_function<Function, 2>)
233  // \todo Unlike SFINAE version, this incorrectly matches linearized_function<0> in both GCC 10.1.0 and clang 10.0.0:
234 #else
235  template<typename Function, std::enable_if_t<
236  linearized_function<Function, 1> and (not linearized_function<Function, 2>), int> = 0>
237 #endif
239  std::decay_t<decltype(oin::get_Taylor_term<1>(std::declval<Function>()))>>;
240 
241 
242 #if defined(__cpp_concepts) and OPENKALMAN_CPP_FEATURE_CONCEPTS_2
243  template<linearized_function<2> Function>
244  // \todo Unlike SFINAE version, this incorrectly matches linearized_function<0> in both GCC 10.1.0 and clang 10.0.0:
245 #else
246  template<typename Function, std::enable_if_t<linearized_function<Function, 2>, int> = 0>
247 #endif
249  std::decay_t<decltype(oin::get_Taylor_term<1>(std::declval<Function>()))>,
250  std::decay_t<decltype(oin::get_Taylor_term<2>(std::declval<Function>()))>>;
251 
252 
253 }
254 
255 
256 #endif //OPENKALMAN_TRANSFORMATION_HPP
auto operator()(In &&in, Perturbations &&... ps) const
Applies the tests.
Definition: Transformation.hpp:76
Transformation(const F &f, const JacobianFunction &j)
Constructs tests using a tests function and a Jacobian function.
Definition: Transformation.hpp:184
Definition: tuple_reverse.hpp:103
constexpr bool transformation_input
T is an acceptable input to a tests.
Definition: TransformationTraits.hpp:158
Transformation()
Default constructor.
Definition: Transformation.hpp:111
Transformation(const F &f)
Constructs tests using a tests function.
Definition: Transformation.hpp:117
The root namespace for OpenKalman.
Definition: basics.hpp:34
Transformation()
Constructs tests using a tests function and a Jacobian and Hessian functions.
Definition: Transformation.hpp:172
auto hessian(In &&in, Perturbations &&... ps) const
Returns a tuple of Hessian matrices for the input and each perturbation term.
Definition: Transformation.hpp:201
auto jacobian(In &&in, Perturbations &&... ps) const
Returns a tuple of the Jacobians for the input and each perturbation term.
Definition: Transformation.hpp:134
Transformation(F &&f)
Constructor from a tests function.
Definition: Transformation.hpp:66
Transformation(const F &f, const J &j, const H &h)
Constructs tests using a tests function and a Jacobian function.
Definition: Transformation.hpp:190
Definition: Transformation.hpp:56
Transformation(const F &f, const J &j)
Constructs tests using a tests function and a Jacobian function.
Definition: Transformation.hpp:123
Definition: TransformationTraits.hpp:39
Transformation(const F &f)
Constructs tests using a tests function.
Definition: Transformation.hpp:178
Definition: basics.hpp:48
Transformation()
Default constructor.
Definition: Transformation.hpp:60
A tests from one single-column vector to another.
Definition: Transformation.hpp:33