smooth
A C++ library for Lie theory
Loading...
Searching...
No Matches
lie_group.hpp
Go to the documentation of this file.
1// Copyright (C) 2021-2022 Petter Nilsson. MIT License.
2
3#pragma once
4
5#include <utility>
6
7#include <Eigen/Core>
8
9#include "manifold.hpp"
10
15SMOOTH_BEGIN_NAMESPACE
16
17namespace traits {
18
22template<typename T>
23struct lie;
24
25} // namespace traits
26
27// clang-format off
28
32template<typename G>
33concept LieGroup =
34requires (Eigen::Index dof) { //NOLINT
35 // Underlying scalar type
37 // Default representation
39 // Compile-time degrees of freedom (tangent space dimension). Can be dynamic (equal to -1)
40 {traits::lie<G>::Dof}->std::convertible_to<int>;
41 // Commutativity
42 {traits::lie<G>::IsCommutative}->std::convertible_to<bool>;
43 // Return the identity element (dof = Dof for static size)
44 {traits::lie<G>::Identity(dof)}->std::convertible_to<typename traits::lie<G>::PlainObject>;
45 // Return a random element (dof = Dof for static size)
46 {traits::lie<G>::Random(dof)}->std::convertible_to<typename traits::lie<G>::PlainObject>;
47} &&
48// GROUP INTERFACE
49requires(const G & g1, const G & g2, typename traits::lie<G>::Scalar eps) {
50 // Group adjoint
51 {traits::lie<G>::Ad(g1)}->std::convertible_to<Eigen::Matrix<typename traits::lie<G>::Scalar, traits::lie<G>::Dof, traits::lie<G>::Dof>>; //NOLINT
52 // Group composition
53 {traits::lie<G>::composition(g1, g2)}->std::convertible_to<typename traits::lie<G>::PlainObject>;
54 // Run-time degrees of freedom (tangent space dimension).
55 {traits::lie<G>::dof(g1)}->std::convertible_to<Eigen::Index>;
56 // Group inverse
57 {traits::lie<G>::inverse(g1)}->std::convertible_to<typename traits::lie<G>::PlainObject>;
58 // Check if two elements are (approximately) equal
59 {traits::lie<G>::isApprox(g1, g2, eps)}->std::convertible_to<bool>;
60 // Group logarithm (maps from group to algebra)
61 {traits::lie<G>::log(g1)}->std::convertible_to<Eigen::Vector<typename traits::lie<G>::Scalar, traits::lie<G>::Dof>>;
62} &&
63// TANGENT INTERFACE
64requires(const Eigen::Vector<typename traits::lie<G>::Scalar, traits::lie<G>::Dof> & a) {
65 // Algebra adjoint
66 {traits::lie<G>::ad(a)}->std::convertible_to<Eigen::Matrix<typename traits::lie<G>::Scalar, traits::lie<G>::Dof, traits::lie<G>::Dof>>; //NOLINT
67 // Algebra exponential (maps from algebra to group)
68 {traits::lie<G>::exp(a)}->std::convertible_to<typename traits::lie<G>::PlainObject>;
69 // Right derivative of the exponential map
70 {traits::lie<G>::dr_exp(a)}->std::convertible_to<Eigen::Matrix<typename traits::lie<G>::Scalar, traits::lie<G>::Dof, traits::lie<G>::Dof>>; //NOLINT
71 // Right derivative of the exponential map inverse
72 {traits::lie<G>::dr_expinv(a)}->std::convertible_to<Eigen::Matrix<typename traits::lie<G>::Scalar, traits::lie<G>::Dof, traits::lie<G>::Dof>>; //NOLINT
73 // Second right derivative of the exponential map
74 {traits::lie<G>::d2r_exp(a)}->std::convertible_to<Eigen::Matrix<typename traits::lie<G>::Scalar, traits::lie<G>::Dof, (traits::lie<G>::Dof > 0 ? traits::lie<G>::Dof * traits::lie<G>::Dof : -1)>>; //NOLINT
75 // Second right derivative of the exponential map inverse
76 {traits::lie<G>::d2r_expinv(a)}->std::convertible_to<Eigen::Matrix<typename traits::lie<G>::Scalar, traits::lie<G>::Dof, (traits::lie<G>::Dof > 0 ? traits::lie<G>::Dof * traits::lie<G>::Dof : -1)>>; //NOLINT
77} && (
78 // Cast to different scalar type
79 !std::is_convertible_v<typename traits::lie<G>::Scalar, double> ||
80 requires (const G & g) { //NOLINT
81 {traits::lie<G>::template cast<double>(g)}; //NOLINT
82 }
83) && (
84 !std::is_convertible_v<typename traits::lie<G>::Scalar, float> ||
85 requires (const G & g) { //NOLINT
86 {traits::lie<G>::template cast<double>(g)}; //NOLINT
87 }
88) &&
89// PlainObject must be default-constructible
90std::is_default_constructible_v<typename traits::lie<G>::PlainObject> &&
91std::is_copy_constructible_v<typename traits::lie<G>::PlainObject> &&
92// PlainObject must be assignable from G
93std::is_assignable_v<typename traits::lie<G>::PlainObject &, G>;
94
95namespace traits {
96
100template<LieGroup G>
101struct man<G>
102{
103 // \cond
104 using Scalar = typename traits::lie<G>::Scalar;
106 template<typename NewScalar>
108
109 static constexpr int Dof = traits::lie<G>::Dof;
110
111 static inline PlainObject Default(Eigen::Index dof) { return traits::lie<G>::Identity(dof); }
112
113 static inline Eigen::Index dof(const G & g) { return traits::lie<G>::dof(g); }
114
115 template<typename NewScalar>
116 static inline CastT<NewScalar> cast(const G & g)
117 {
118 return traits::lie<G>::template cast<NewScalar>(g);
119 }
120
121 template<typename Derived>
122 static inline PlainObject rplus(const G & g, const Eigen::MatrixBase<Derived> & a)
123 {
125 }
126
127 template<LieGroup Go = G>
128 static inline Eigen::Matrix<Scalar, Dof, 1> rminus(const G & g1, const Go & g2)
129 {
131 }
132 // \endcond
133};
134
135} // namespace //NOLINT
136
140
141// Group interface
142
143template<LieGroup G>
144static constexpr bool IsCommutative = traits::lie<G>::IsCommutative;
145
151template<LieGroup G>
152inline PlainObject<G> Identity(Eigen::Index dof)
153{
155}
156
160template<LieGroup G>
161 requires(Dof<G> > 0)
163
169template<LieGroup G>
170inline PlainObject<G> Random(Eigen::Index dof)
171{
173}
174
178template<LieGroup G>
179 requires(Dof<G> > 0)
180inline PlainObject<G> Random() { return traits::lie<G>::Random(Dof<G>); }
181
185template<LieGroup G>
186inline TangentMap<G> Ad(const G & g)
187{
188 return traits::lie<G>::Ad(g);
189}
190
194template<LieGroup G, typename Arg>
195inline PlainObject<G> composition(const G & g, Arg && a)
196{
197 return traits::lie<G>::composition(g, std::forward<Arg>(a));
198}
199
203template<LieGroup G, typename Arg, typename... Args>
204inline PlainObject<G> composition(const G & g, Arg && a, Args &&... as)
205{
206 return composition(composition(g, std::forward<Arg>(a)), std::forward<Args>(as)...);
207}
208
212template<LieGroup G>
213inline PlainObject<G> inverse(const G & g)
214{
215 return traits::lie<G>::inverse(g);
216}
217
221template<LieGroup G, typename Arg>
222inline bool isApprox(
223 const G & g,
224 Arg && a,
225 typename traits::lie<G>::Scalar eps = Eigen::NumTraits<typename traits::lie<G>::Scalar>::dummy_precision())
226{
227 return traits::lie<G>::isApprox(g, std::forward<Arg>(a), eps);
228}
229
235template<LieGroup G>
236inline Tangent<G> log(const G & g)
237{
238 return traits::lie<G>::log(g);
239}
240
241// Tangent interface
242
246template<LieGroup G, typename Arg>
247inline TangentMap<G> ad(Arg && a)
248{
249 return traits::lie<G>::ad(std::forward<Arg>(a));
250}
251
257template<LieGroup G, typename Arg>
258inline PlainObject<G> exp(Arg && a)
259{
260 return traits::lie<G>::exp(std::forward<Arg>(a));
261}
262
266template<LieGroup G, typename Arg>
267inline TangentMap<G> dr_exp(Arg && a)
268{
269 return traits::lie<G>::dr_exp(std::forward<Arg>(a));
270}
271
275template<LieGroup G, typename Arg>
276inline TangentMap<G> dr_expinv(Arg && a)
277{
278 return traits::lie<G>::dr_expinv(std::forward<Arg>(a));
279}
280
284template<LieGroup G, typename Arg>
285inline Hessian<G> d2r_exp(Arg && a)
286{
287 return traits::lie<G>::d2r_exp(std::forward<Arg>(a));
288}
289
293template<LieGroup G, typename Arg>
294inline Hessian<G> d2r_expinv(Arg && a)
295{
296 return traits::lie<G>::d2r_expinv(std::forward<Arg>(a));
297}
298
299// Convenience methods
300
304template<LieGroup G, typename Derived>
305inline PlainObject<G> lplus(const G & g, const Eigen::MatrixBase<Derived> & a)
306{
307 return composition(::smooth::exp<G>(a), g);
308}
309
313template<LieGroup G, LieGroup Go>
314inline Tangent<G> lminus(const G & g1, const Go & g2)
315{
316 return log(composition(g1, inverse(g2)));
317}
318
322template<LieGroup G, typename Derived>
323inline TangentMap<G> dl_exp(const Eigen::MatrixBase<Derived> & a)
324{
325 return dr_exp<G>(-a);
326}
327
331template<LieGroup G, typename Derived>
332inline TangentMap<G> dl_expinv(const Eigen::MatrixBase<Derived> & a)
333{
334 return dr_expinv<G>(-a);
335}
336
340template<LieGroup G, typename Derived>
341inline Hessian<G> d2l_exp(const Eigen::MatrixBase<Derived> & a)
342{
343 return -d2r_exp<G>(-a);
344}
345
349template<LieGroup G, typename Derived>
350inline Hessian<G> d2l_expinv(const Eigen::MatrixBase<Derived> & a)
351{
352 return -d2r_expinv<G>(-a);
353}
354
355SMOOTH_END_NAMESPACE
Class-external Lie group interface defined through the traits::lie trait class.
Definition lie_group.hpp:33
Tangent< G > lminus(const G &g1, const Go &g2)
Left-minus.
TangentMap< G > Ad(const G &g)
Group adjoint .
PlainObject< G > Random()
Random element in Lie group with static Dof.
TangentMap< G > dl_expinv(const Eigen::MatrixBase< Derived > &a)
Left Jacobian of exponential map inverse.
Hessian< G > d2r_exp(Arg &&a)
Right Hessian of exponential map.
bool isApprox(const G &g, Arg &&a, typename traits::lie< G >::Scalar eps=Eigen::NumTraits< typename traits::lie< G >::Scalar >::dummy_precision())
Check if two group elements are approximately equal.
Tangent< G > log(const G &g)
Group logarithm.
TangentMap< G > dr_exp(Arg &&a)
Right Jacobian of exponential map.
Hessian< G > d2l_exp(const Eigen::MatrixBase< Derived > &a)
Left Hessian of exponential map.
TangentMap< G > dl_exp(const Eigen::MatrixBase< Derived > &a)
Left Jacobian of exponential map.
Hessian< G > d2l_expinv(const Eigen::MatrixBase< Derived > &a)
Left Hessian of exponential map inverse.
PlainObject< G > composition(const G &g, Arg &&a)
Group binary composition.
PlainObject< G > exp(Arg &&a)
Lie algebra exponential.
PlainObject< G > lplus(const G &g, const Eigen::MatrixBase< Derived > &a)
Left-plus.
Hessian< G > d2r_expinv(Arg &&a)
Right Hessian of exponential map inverse.
PlainObject< G > Identity()
Identity in Lie group with static Dof.
TangentMap< G > ad(Arg &&a)
Lie algebra adjoint .
PlainObject< G > inverse(const G &g)
Group inverse.
TangentMap< G > dr_expinv(Arg &&a)
Right Jacobian of exponential map inverse.
PlainObject< M > Default()
Default-initialized Manifold with static dof.
Definition manifold.hpp:135
Eigen::Matrix< Scalar< M >, Dof< M >,(Dof< M > > 0 ? Dof< M > *Dof< M > :-1)> Hessian
Matrix of size Dof x Dof*Dof.
Definition manifold.hpp:118
Eigen::Vector< Scalar< M >, Dof< M > > Tangent
Tangent as a Dof-length vector.
Definition manifold.hpp:106
typename traits::man< M >::Scalar Scalar
Manifold scalar type.
Definition manifold.hpp:88
Eigen::Index dof(const M &m)
Manifold degrees of freedom (tangent space dimension)
Definition manifold.hpp:145
Tangent< M > rminus(const M &g1, const Mo &g2)
Manifold right-minus.
Definition manifold.hpp:172
Eigen::Matrix< Scalar< M >, Dof< M >, Dof< M > > TangentMap
Matrix of size Dof x Dof.
Definition manifold.hpp:112
PlainObject< M > rplus(const M &m, const Eigen::MatrixBase< Derived > &a)
Manifold right-plus.
Definition manifold.hpp:163
typename traits::man< M >::template CastT< NewScalar > CastT
Cast'ed type.
Definition manifold.hpp:100
CastT< NewScalar, M > cast(const M &m)
Cast to different scalar type.
Definition manifold.hpp:154
typename traits::man< M >::PlainObject PlainObject
Manifold default type.
Definition manifold.hpp:94
Trait class for making a class a LieGroup instance via specialization.
Definition lie_group.hpp:23
Trait class for making a class a Manifold instance via specialization.
Definition manifold.hpp:21