gtsam
Loading...
Searching...
No Matches
GroupAction.h
Go to the documentation of this file.
1/* ----------------------------------------------------------------------------
2
3 * GTSAM Copyright 2010, Georgia Tech Research Corporation,
4 * Atlanta, Georgia 30332-0415
5 * All Rights Reserved
6 * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
7
8 * See LICENSE for the license information
9
10 * -------------------------------------------------------------------------- */
11
17
18#pragma once
19
20#include <gtsam/base/Manifold.h>
21#include <gtsam/base/Matrix.h>
23#include <gtsam/base/Testable.h>
24
25#include <type_traits>
26
27namespace gtsam {
28
30enum class ActionType { Left, Right };
31
32namespace group_action {
33
44template <typename Action>
45struct Orbit : public Action {
46 using G = typename Action::Group;
47 using M = typename Action::Manifold;
48 static constexpr int DimG = traits<G>::dimension;
49 static constexpr int DimM = traits<M>::dimension;
50
51 M m0;
52
53 explicit Orbit(const M& m) : m0(m) {}
54
56 Orbit(const M& m, const Action& a) : Action(a), m0(m) {}
57
59 M operator()(const G& g) const {
60 if constexpr (Action::type == ActionType::Left) {
61 return Action::operator()(g, m0);
62 } else {
63 return Action::operator()(m0, g);
64 }
65 }
66
67 // Version with Jacobian request: requires the action to provide Jacobians.
68 template <typename A = Action,
69 typename = std::enable_if_t<
70 std::is_invocable_r_v<M, const A&, const G&, const M&,
73 std::is_invocable_r_v<M, const A&, const M&, const G&,
76 M operator()(const G& g, OptionalJacobian<DimM, DimG> H) const {
77 if constexpr (Action::type == ActionType::Left) {
78 return Action::operator()(g, m0, H, {});
79 } else {
80 return Action::operator()(m0, g, {}, H);
81 }
82 }
83};
84
94template <typename Action>
95struct Diffeomorphism : public Action {
96 using G = typename Action::Group;
97 using M = typename Action::Manifold;
98 static constexpr int DimG = traits<G>::dimension;
99 static constexpr int DimM = traits<M>::dimension;
100
101 G g0;
102
103 explicit Diffeomorphism(const G& g) : g0(g) {}
104
106 Diffeomorphism(const G& g, const Action& a) : Action(a), g0(g) {}
107
109 M operator()(const M& m) const {
110 if constexpr (Action::type == ActionType::Left) {
111 return Action::operator()(g0, m);
112 } else {
113 return Action::operator()(m, g0);
114 }
115 }
116
117 // Version with Jacobian request: requires the action to provide Jacobians.
118 template <typename A = Action,
119 typename = std::enable_if_t<
120 std::is_invocable_r_v<M, const A&, const G&, const M&,
123 std::is_invocable_r_v<M, const A&, const M&, const G&,
126 M operator()(const M& m, OptionalJacobian<DimM, DimM> H) const {
127 if constexpr (Action::type == ActionType::Left) {
128 return Action::operator()(g0, m, {}, H);
129 } else {
130 return Action::operator()(m, g0, H, {});
131 }
132 }
133
142 template <typename A = Action,
143 typename = std::enable_if_t<
144 std::is_invocable_r_v<M, const A&, const G&, const M&,
145 OptionalJacobian<DimM, DimG>,
146 OptionalJacobian<DimM, DimM>> ||
147 std::is_invocable_r_v<M, const A&, const M&, const G&,
148 OptionalJacobian<DimM, DimM>,
149 OptionalJacobian<DimM, DimG>>>>
151 const M& m, const typename traits<M>::TangentVector& v,
152 OptionalJacobian<DimM, DimM> H = {}) const {
153 Eigen::Matrix<double, DimM, DimM> D;
154 OptionalJacobian<DimM, DimM> H_arg = H ? H : &D;
155 this->operator()(m, H_arg);
156 const auto& J = H ? *H : D;
157 return J * v;
158 }
159};
160
172template <typename Action, typename VectorField>
173struct InducedVectorField : public Action {
174 using G = typename Action::Group;
175 using M = typename Action::Manifold;
176 using TangentVector = typename traits<M>::TangentVector;
177
178 G g_;
179 VectorField field_;
180
181 InducedVectorField(const G& g, const VectorField& f) : g_(g), field_(f) {}
182
183 InducedVectorField(const G& g, const VectorField& f, const Action& action)
184 : Action(action), g_(g), field_(f) {}
185
186 TangentVector operator()(const M& xi) const {
187 const Action& action = static_cast<const Action&>(*this);
188 const Orbit<Action> orbit(xi, action);
189 const M transported = orbit(g_.inverse());
190 const TangentVector v = field_(transported);
191 const Diffeomorphism<Action> phi_g0(g_, action);
192 return phi_g0.pushforward(transported, v);
193 }
194};
195
196} // namespace group_action
197
235template <typename Derived, typename G, typename M>
238 const Derived& derived() const { return static_cast<const Derived&>(*this); }
239
240 // Helper typedefs
241 using Group = G;
242 using Manifold = M;
243 static constexpr int DimG = traits<G>::dimension;
244 static constexpr int DimM = traits<M>::dimension;
245
246 // --------------------------------------------------------------------------
247 // Function Objects for Partial Application
248 // --------------------------------------------------------------------------
249
250 using Orbit = group_action::Orbit<Derived>;
251 using Diffeomorphism = group_action::Diffeomorphism<Derived>;
252 template <typename VectorField>
253 struct InducedVectorField
254 : public group_action::InducedVectorField<Derived, VectorField> {
256 using Base::Base; // inherit default/aux constructors
257
258 InducedVectorField(const Group& g, const VectorField& f) : Base(g, f) {}
259
260 InducedVectorField(const Group& g, const VectorField& f,
261 const Derived& action)
262 : Base(g, f, action) {}
263 };
264 // These wrappers keep call sites short while allowing CTAD on the
265 // VectorField type: `Derived::InducedVectorField f(g, f_vecfield);`
266};
267
268// --------------------------------------------------------------------------
269// Test Helpers
270// --------------------------------------------------------------------------
271
273template <class Action, class M_, class G_>
274inline bool rightActionEqual(const Action& phi, const M_& m, const G_& g1,
275 const G_& g2) {
276 const M_ left = phi(m, g1 * g2);
277 const M_ right = phi(phi(m, g1), g2);
278 return assert_equal(left, right);
279}
280
282template <class Action, class G_, class M_>
283inline bool leftActionEqual(const Action& phi, const G_& g1, const G_& g2,
284 const M_& m) {
285 const M_ left = phi(g1 * g2, m);
286 const M_ right = phi(g1, phi(g2, m));
287 return assert_equal(left, right);
288}
289
290#define EXPECT_RIGHT_ACTION(phi, m, g1, g2) \
291 do { \
292 EXPECT(::gtsam::rightActionEqual((phi), (m), (g1), (g2))); \
293 } while (0)
294
295#define EXPECT_LEFT_ACTION(phi, g1, g2, m) \
296 do { \
297 EXPECT(::gtsam::leftActionEqual((phi), (g1), (g2), (m))); \
298 } while (0)
299
300} // namespace gtsam
typedef and functions to augment Eigen's MatrixXd
Special class for optional Jacobian arguments.
Concept check for values that can be used in unit tests.
Base class and basic functions for Manifold types.
Global functions in a separate testing namespace.
Definition chartTesting.h:28
bool rightActionEqual(const Action &phi, const M_ &m, const G_ &g1, const G_ &g2)
Check right action property: φ(m, g1 g2) = φ(φ(m, g1), g2).
Definition GroupAction.h:274
bool assert_equal(const Matrix &expected, const Matrix &actual, double tol)
equals with an tolerance, prints out message if unequal
Definition Matrix.cpp:39
ActionType
Enum to specify whether the action is a Left or Right action.
Definition GroupAction.h:30
bool leftActionEqual(const Action &phi, const G_ &g1, const G_ &g2, const M_ &m)
Check left action property: φ(g1 g2, m) = φ(g1, φ(g2, m)).
Definition GroupAction.h:283
A manifold defines a space in which there is a notion of a linear tangent space that can be centered ...
Definition Group.h:37
Orbit: The map g -> m, defined by fixing m0.
Definition GroupAction.h:45
Orbit(const M &m, const Action &a)
Constructor binding an explicit action instance (for stateful actions).
Definition GroupAction.h:56
M operator()(const G &g) const
Apply the orbit to a group element.
Definition GroupAction.h:59
Diffeomorphism: The map m -> m, defined by fixing g0.
Definition GroupAction.h:95
M operator()(const M &m) const
Apply the diffeomorphism to a manifold point.
Definition GroupAction.h:109
Diffeomorphism(const G &g, const Action &a)
Constructor with explicit action instance.
Definition GroupAction.h:106
traits< M >::TangentVector pushforward(const M &m, const typename traits< M >::TangentVector &v, OptionalJacobian< DimM, DimM > H={}) const
Push-forward a tangent vector through the diffeomorphism.
Definition GroupAction.h:150
Induced action on vector fields via push-forward.
Definition GroupAction.h:173
GroupAction CRTP base class.
Definition GroupAction.h:236
const Derived & derived() const
Access derived class.
Definition GroupAction.h:238
OptionalJacobian is an Eigen::Ref like class that can take be constructed using either a fixed size o...
Definition OptionalJacobian.h:40