smooth
A C++ library for Lie theory
Loading...
Searching...
No Matches
lie_group_base.hpp
1// Copyright (C) 2021-2022 Petter Nilsson. MIT License.
2
3#pragma once
4
5#include <Eigen/Core>
6
7#include "smooth/version.hpp"
8
9SMOOTH_BEGIN_NAMESPACE
10
19template<typename T>
21{};
22
26template<typename Derived>
28{
29 Derived & derived() noexcept { return static_cast<Derived &>(*this); }
30
31 const Derived & cderived() const noexcept { return static_cast<const Derived &>(*this); }
32
33protected:
34 LieGroupBase() = default;
35
38
40 using Impl = typename traits::Impl;
41
43 static constexpr bool is_mutable = traits::is_mutable;
44
45public:
47 static constexpr int RepSize = Impl::RepSize;
49 static constexpr int Dof = Impl::Dof;
51 static constexpr int Dim = Impl::Dim;
53 static constexpr bool IsCommutative = Impl::IsCommutative;
54
56 using Scalar = typename traits::Scalar;
58 using Matrix = Eigen::Matrix<Scalar, Dim, Dim>;
60 using Tangent = Eigen::Matrix<Scalar, Dof, 1>;
62 using TangentMap = Eigen::Matrix<Scalar, Dof, Dof>;
64 using Hessian = Eigen::Matrix<Scalar, Dof, Dof * Dof>;
66 template<typename NewScalar>
67 using CastT = typename traits::template PlainObject<NewScalar>;
70
72 template<bool = true>
73 requires(is_mutable)
74 auto & coeffs() const
75 {
76 return derived().coeffs();
77 }
79 const auto & coeffs() const { return cderived().coeffs(); }
80
82 template<bool = true>
83 requires(is_mutable)
84 auto * data() const
85 {
86 return derived().data();
87 }
89 const auto * data() const { return cderived().data(); }
90
94 template<typename OtherDerived>
95 requires(is_mutable && std::is_same_v<Impl, typename liebase_info<OtherDerived>::Impl>)
96 Derived & operator=(const LieGroupBase<OtherDerived> & o) noexcept
97 {
98 derived().coeffs() = static_cast<const OtherDerived &>(o).coeffs();
99 return derived();
100 }
101
102 // Group API
103
107 Eigen::Index dof() const noexcept { return Dof; }
108
112 void setIdentity() noexcept { Impl::setIdentity(derived().coeffs()); }
113
119 void setRandom() noexcept { Impl::setRandom(derived().coeffs()); }
120
125 {
127 ret.setIdentity();
128 return ret;
129 }
130
137 {
139 ret.setRandom();
140 return ret;
141 }
142
148 {
149 Matrix ret;
150 Impl::matrix(cderived().coeffs(), ret);
151 return ret;
152 }
153
157 template<typename OtherDerived>
158 requires(std::is_same_v<Impl, typename liebase_info<OtherDerived>::Impl>)
159 bool isApprox(const LieGroupBase<OtherDerived> & o, const Scalar & eps = Eigen::NumTraits<Scalar>::dummy_precision())
160 const noexcept
161 {
162 return cderived().coeffs().isApprox(static_cast<const OtherDerived &>(o).coeffs(), eps);
163 }
164
168 template<typename NewScalar>
170 {
172 ret.coeffs() = cderived().coeffs().template cast<NewScalar>();
173 return ret;
174 }
175
179 template<typename OtherDerived>
180 requires(std::is_same_v<Impl, typename liebase_info<OtherDerived>::Impl>)
181 PlainObject operator*(const LieGroupBase<OtherDerived> & o) const noexcept
182 {
184 Impl::composition(cderived().coeffs(), static_cast<const OtherDerived &>(o).coeffs(), ret.coeffs());
185 return ret;
186 }
187
191 template<typename OtherDerived>
192 requires(is_mutable && std::is_same_v<Impl, typename liebase_info<OtherDerived>::Impl>)
193 Derived & operator*=(const LieGroupBase<OtherDerived> & o) noexcept
194 {
195 derived().coeffs() = (*this * o).coeffs();
196 return derived();
197 }
198
203 {
205 Impl::inverse(cderived().coeffs(), ret.coeffs());
206 return ret;
207 }
208
215 {
216 Tangent ret;
217 Impl::log(cderived().coeffs(), ret);
218 return ret;
219 }
220
228 {
229 if constexpr (IsCommutative) {
230 return TangentMap::Identity();
231 } else {
233 Impl::Ad(cderived().coeffs(), ret);
234 return ret;
235 }
236 }
237
243 template<typename TangentDerived>
244 PlainObject operator+(const Eigen::MatrixBase<TangentDerived> & a) const noexcept
245 {
246 return *this * exp(a);
247 }
248
254 template<typename TangentDerived>
255 requires(is_mutable)
256 Derived & operator+=(const Eigen::MatrixBase<TangentDerived> & a) noexcept
257 {
258 *this *= exp(a);
259 return derived();
260 }
261
272 template<typename OtherDerived>
273 requires(std::is_same_v<Impl, typename liebase_info<OtherDerived>::Impl>)
274 Tangent operator-(const LieGroupBase<OtherDerived> & xo) const noexcept
275 {
276 return (xo.inverse() * *this).log();
277 }
278
279 // Tangent API
280
284 template<typename TangentDerived>
285 static PlainObject exp(const Eigen::MatrixBase<TangentDerived> & a) noexcept
286 {
288 Impl::exp(a, ret.coeffs());
289 return ret;
290 }
291
301 template<typename TangentDerived>
302 static Matrix hat(const Eigen::MatrixBase<TangentDerived> & a) noexcept
303 {
304 Matrix ret;
305 Impl::hat(a, ret);
306 return ret;
307 }
308
317 template<typename MatrixDerived>
318 static Tangent vee(const Eigen::MatrixBase<MatrixDerived> & A) noexcept
319 {
320 Tangent ret;
321 Impl::vee(A, ret);
322 return ret;
323 }
324
331 template<typename TangentDerived>
332 static TangentMap ad(const Eigen::MatrixBase<TangentDerived> & a) noexcept
333 {
334 if constexpr (IsCommutative) {
335 return TangentMap::Zero();
336 } else {
338 Impl::ad(a, ret);
339 return ret;
340 }
341 }
342
350 template<typename TangentDerived1, typename TangentDerived2>
351 static Tangent
352 lie_bracket(const Eigen::MatrixBase<TangentDerived1> & a, const Eigen::MatrixBase<TangentDerived2> & b) noexcept
353 {
354 if constexpr (IsCommutative) {
355 return Tangent::Zero();
356 } else {
357 return ad(a) * b;
358 }
359 }
360
366 template<typename TangentDerived>
367 static TangentMap dr_exp(const Eigen::MatrixBase<TangentDerived> & a) noexcept
368 {
369 if constexpr (IsCommutative) {
370 return TangentMap::Identity();
371 } else {
373 Impl::dr_exp(a, ret);
374 return ret;
375 }
376 }
377
383 template<typename TangentDerived>
384 static TangentMap dr_expinv(const Eigen::MatrixBase<TangentDerived> & a) noexcept
385 {
386 if constexpr (IsCommutative) {
387 return TangentMap::Identity();
388 } else {
390 Impl::dr_expinv(a, ret);
391 return ret;
392 }
393 }
394
400 template<typename TangentDerived>
401 static TangentMap dl_exp(const Eigen::MatrixBase<TangentDerived> & a) noexcept
402 {
403 return dr_exp(-a);
404 }
405
411 template<typename TangentDerived>
412 static TangentMap dl_expinv(const Eigen::MatrixBase<TangentDerived> & a) noexcept
413 {
414 return dr_expinv(-a);
415 }
416
422 template<typename TangentDerived>
423 static Hessian d2r_exp(const Eigen::MatrixBase<TangentDerived> & a) noexcept
424 {
425 if constexpr (IsCommutative) {
426 return Hessian::Zero();
427 } else {
428 Hessian ret;
429 Impl::d2r_exp(a, ret);
430 return ret;
431 }
432 }
433
440 template<typename TangentDerived>
441 static Hessian d2r_expinv(const Eigen::MatrixBase<TangentDerived> & a) noexcept
442 {
443 if constexpr (IsCommutative) {
444 return Hessian::Zero();
445 } else {
446 Hessian ret;
447 Impl::d2r_expinv(a, ret);
448 return ret;
449 }
450 }
451
457 template<typename TangentDerived>
458 static Hessian d2l_exp(const Eigen::MatrixBase<TangentDerived> & a) noexcept
459 {
460 return -d2r_exp(-a);
461 }
462
469 template<typename TangentDerived>
470 static Hessian d2l_expinv(const Eigen::MatrixBase<TangentDerived> & a) noexcept
471 {
472 return -d2r_expinv(-a);
473 }
474};
475
479template<typename Stream, typename Derived>
480Stream & operator<<(Stream & s, const LieGroupBase<Derived> & g)
481{
482 s << static_cast<const Derived &>(g).coeffs().transpose();
483 return s;
484}
485
489template<typename T>
490class Map;
491
495template<typename T>
496using MapDispatch = std::conditional_t<
497 std::is_base_of_v<Eigen::MatrixBase<std::remove_const_t<T>>, std::remove_const_t<T>>,
498 ::Eigen::Map<T>,
499 ::smooth::Map<T>>;
500
501SMOOTH_END_NAMESPACE
Base class for Lie group types.
bool isApprox(const LieGroupBase< OtherDerived > &o, const Scalar &eps=Eigen::NumTraits< Scalar >::dummy_precision()) const noexcept
Check if (approximately) equal to other element o.
PlainObject operator+(const Eigen::MatrixBase< TangentDerived > &a) const noexcept
Right-plus.
static constexpr int Dof
Degrees of freedom of manifold (equal to tangent space dimension).
typename traits::Scalar Scalar
Scalar type.
auto & coeffs() const
Access underlying storages.
static Tangent vee(const Eigen::MatrixBase< MatrixDerived > &A) noexcept
Lie alebra vee map.
liebase_info< Derived > traits
CRTP traits.
static TangentMap dl_expinv(const Eigen::MatrixBase< TangentDerived > &a) noexcept
Inverse of left jacobian of the exponential map.
static Hessian d2r_exp(const Eigen::MatrixBase< TangentDerived > &a) noexcept
Right Hessian of the exponential map.
static constexpr bool IsCommutative
Commutativity of group. A commutative group has a zero Lie bracket.
void setRandom() noexcept
Set to a random element.
static Hessian d2r_expinv(const Eigen::MatrixBase< TangentDerived > &a) noexcept
Right Hessian of the log map.
static Tangent lie_bracket(const Eigen::MatrixBase< TangentDerived1 > &a, const Eigen::MatrixBase< TangentDerived2 > &b) noexcept
Lie algebra bracket.
CastT< Scalar > PlainObject
Plain return type.
static constexpr bool is_mutable
True if underlying storage supports modification.
static PlainObject Random() noexcept
Construct a random element.
static PlainObject Identity() noexcept
Construct the identity element.
typename traits::Impl Impl
Group-specific Lie group implementation.
TangentMap Ad() const noexcept
Lie group adjoint.
static constexpr int Dim
Side of Lie group matrix representation.
static PlainObject exp(const Eigen::MatrixBase< TangentDerived > &a) noexcept
Lie group exponential map.
void setIdentity() noexcept
Set to group identity element.
Eigen::Matrix< Scalar, Dof, 1 > Tangent
Lie group parameterized tangent type.
Eigen::Matrix< Scalar, Dof, Dof > TangentMap
Matrix representing map between tangent elements.
auto * data() const
Access raw pointer.
static TangentMap ad(const Eigen::MatrixBase< TangentDerived > &a) noexcept
Lie algebra adjoint.
Tangent log() const noexcept
Lie group logarithm.
Eigen::Matrix< Scalar, Dof, Dof *Dof > Hessian
Plain return type with different scalar.
static Hessian d2l_exp(const Eigen::MatrixBase< TangentDerived > &a) noexcept
Left Hessian of the exponential map.
PlainObject inverse() const noexcept
Group inverse operation.
static constexpr int RepSize
Number of scalars in internal representation.
static TangentMap dr_exp(const Eigen::MatrixBase< TangentDerived > &a) noexcept
Right jacobian of the exponential map.
CastT< NewScalar > cast() const noexcept
Cast to different scalar type.
static Matrix hat(const Eigen::MatrixBase< TangentDerived > &a) noexcept
Lie algebra hat map.
const auto & coeffs() const
Const access underlying storages.
const auto * data() const
Const access raw pointer.
static TangentMap dl_exp(const Eigen::MatrixBase< TangentDerived > &a) noexcept
Left jacobian of the exponential map.
Matrix matrix() const noexcept
Return as matrix Lie group element in .
Eigen::Index dof() const noexcept
Dynamic size (degrees of freedom).
static Hessian d2l_expinv(const Eigen::MatrixBase< TangentDerived > &a) noexcept
Left Hessian of the log map.
Eigen::Matrix< Scalar, Dim, Dim > Matrix
Lie group matrix type.
static TangentMap dr_expinv(const Eigen::MatrixBase< TangentDerived > &a) noexcept
Inverse of right jacobian of the exponential map.
typename traits::template PlainObject< NewScalar > CastT
Plain return type with different scalar.
Memory mapping of internal Lie group types.
Eigen::Vector< Scalar< M >, Dof< M > > Tangent
Tangent as a Dof-length vector.
Definition manifold.hpp:106
Type trait that maps a type to Lie group operations.