29 constexpr int product(
int a,
int b) {
30 return (a == Eigen::Dynamic || b == Eigen::Dynamic) ? Eigen::Dynamic : a * b;
34 template<
class Class,
int D,
int N>
35 auto computeVectorizedGenerators() {
36 static_assert(D != Eigen::Dynamic && N != Eigen::Dynamic,
37 "This helper is only for fixed-size Lie groups.");
38 Eigen::Matrix<double, N* N, D> P;
39 for (
int i = 0; i < D; ++i) {
40 const auto G_i = Class::Hat(Class::TangentVector::Unit(D, i));
41 P.col(i) = Eigen::Map<const Eigen::Matrix<double, N* N, 1>>(G_i.data());
50 template<
class Class,
int D,
int N>
53 using Base::dimension;
56 using ChartJacobian =
typename Base::ChartJacobian;
57 using Jacobian =
typename Base::Jacobian;
58 using TangentVector =
typename Base::TangentVector;
59 using Vectorized = Eigen::Matrix<double, internal::product(N, N), 1>;
60 using VectorizedJacobian =
75 Eigen::Matrix<double, internal::product(N, N), 1>
vec(
77 const auto& derived =
static_cast<const Class&
>(*this);
78 const auto& T = derived.matrix();
81 if constexpr (N != Eigen::Dynamic && D != Eigen::Dynamic) {
82 const auto& P = VectorizedGenerators();
83 for (
int i = 0; i < N; ++i) {
84 H->block(i * N, 0, N, D) = T * P.block(i * N, 0, N, D);
88 const size_t n = T.rows();
89 const size_t d = derived.dim();
93 Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> P(n * n, d);
94 for (
size_t j = 0; j < d; ++j) {
95 const auto G_j = Class::Hat(TangentVector::Unit(d, j));
96 P.col(j) = Eigen::Map<const Eigen::Matrix<double, Eigen::Dynamic, 1>>(
101 for (
size_t i = 0; i < n; ++i) {
102 H->block(i * n, 0, n, d) = T * P.block(i * n, 0, n, d);
107 if constexpr (N != Eigen::Dynamic) {
108 return Eigen::Map<const Eigen::Matrix<double, N* N, 1>>(T.data());
111 return Eigen::Map<const Eigen::Matrix<double, Eigen::Dynamic, 1>>(
126 const auto& m =
static_cast<const Class&
>(*this);
128 if constexpr (D == Eigen::Dynamic) d = m.dim();
130 const auto T_mat = m.matrix();
131 const auto T_inv_mat = m.inverse().matrix();
132 for (
size_t i = 0; i < d; i++) {
134 const auto G_i = Class::Hat(TangentVector::Unit(d, i));
135 adj.col(i) = Class::Vee(T_mat * G_i * T_inv_mat);
145 TangentVector
Adjoint(
const TangentVector& xi,
146 ChartJacobian H_this = {},
147 ChartJacobian H_xi = {})
const {
148 const auto& m =
static_cast<const Class&
>(*this);
149 const Jacobian Ad = m.AdjointMap();
150 if (H_this) *H_this = -Ad * Class::adjointMap(xi);
151 if (H_xi) *H_xi = Ad;
161 ChartJacobian H_this = {},
162 ChartJacobian H_x = {})
const {
163 const auto& m =
static_cast<const Class&
>(*this);
164 const Jacobian Ad = m.AdjointMap();
165 const TangentVector AdTx = Ad.transpose() * x;
168 const Eigen::Index d = tangentDim(&m,
nullptr);
169 setZeroJacobian(H_this, d);
170 if constexpr (D == Eigen::Dynamic) {
171 for (Eigen::Index i = 0; i < d; ++i) {
173 Class::adjointMap(TangentVector::Unit(d, i)).transpose() * AdTx;
176 const auto& basis = adjointBasis();
177 for (Eigen::Index i = 0; i < d; ++i) {
178 H_this->col(i) = basis[
static_cast<size_t>(i)].transpose() * AdTx;
183 if (H_x) *H_x = Ad.transpose();
192 const Eigen::Index d = tangentDim(
nullptr, &xi);
194 if constexpr (D == Eigen::Dynamic) {
199 const auto Xi = Class::Hat(xi);
200 for (Eigen::Index i = 0; i < d; ++i) {
201 const auto Ei = Class::Hat(TangentVector::Unit(d, i));
202 ad.col(i) = Class::Vee(Xi * Ei - Ei * Xi);
210 static TangentVector
adjoint(
const TangentVector& xi,
211 const TangentVector& y, ChartJacobian Hxi = {},
212 ChartJacobian H_y = {}) {
213 const Jacobian ad_xi = Class::adjointMap(xi);
214 if (Hxi) *Hxi = -Class::adjointMap(y);
215 if (H_y) *H_y = ad_xi;
223 const TangentVector& y,
224 ChartJacobian Hxi = {},
225 ChartJacobian H_y = {}) {
226 const Jacobian adT_xi = Class::adjointMap(xi).transpose();
228 const Eigen::Index d = tangentDim(
nullptr, &xi);
229 setZeroJacobian(Hxi, d);
230 if constexpr (D == Eigen::Dynamic) {
231 for (Eigen::Index i = 0; i < d; ++i) {
233 Class::adjointMap(TangentVector::Unit(d, i)).transpose() * y;
236 const auto& basis = adjointBasis();
237 for (Eigen::Index i = 0; i < d; ++i) {
238 Hxi->col(i) = basis[
static_cast<size_t>(i)].transpose() * y;
242 if (H_y) *H_y = adT_xi;
249 static Eigen::Index tangentDim(
const Class* m,
const TangentVector* xi) {
250 if constexpr (D == Eigen::Dynamic) {
251 return m ?
static_cast<Eigen::Index
>(traits<Class>::GetDimension(*m))
252 : static_cast<Eigen::Index>(xi->size());
260 static void setZeroJacobian(ChartJacobian H, Eigen::Index d) {
261 if constexpr (D == Eigen::Dynamic) {
270 template <
int DD = D,
typename std::enable_if_t<DD != Eigen::Dynamic,
int> = 0>
271 static const std::array<Jacobian, DD>& adjointBasis() {
272 static const std::array<Jacobian, DD> basis = []() {
273 std::array<Jacobian, DD> B{};
274 for (
int i = 0; i < DD; ++i) {
275 B[
static_cast<size_t>(i)] =
276 Class::adjointMap(TangentVector::Unit(DD, i));
284 inline static const Eigen::Matrix<double, internal::product(N, N), D>&
285 VectorizedGenerators() {
286 static const auto P =
287 internal::computeVectorizedGenerators<Class, D, N>();
296 using LieAlgebra =
typename Class::LieAlgebra;
297 using TangentVector =
typename LieGroupTraits<Class>::TangentVector;
298 using Jacobian =
typename LieGroupTraits<Class>::Jacobian;
299 using ChartJacobian =
typename LieGroupTraits<Class>::ChartJacobian;
301 static LieAlgebra Hat(
const TangentVector& v) {
302 return Class::Hat(v);
305 static TangentVector Vee(
const LieAlgebra& X) {
306 return Class::Vee(X);
310 static Eigen::Matrix<double, product(N, N), 1>
Vec(
313 LieGroupTraits<Class>::dimension> H = {}) {
317 static TangentVector AdjointTranspose(
const Class& m,
318 const TangentVector& x,
319 ChartJacobian Hm = {},
320 ChartJacobian Hx = {}) {
321 return m.AdjointTranspose(x, Hm, Hx);
324 static TangentVector Adjoint(
const Class& m,
const TangentVector& x,
325 ChartJacobian Hm = {},
326 ChartJacobian Hx = {}) {
327 return m.Adjoint(x, Hm, Hx);
330 static Jacobian adjointMap(
const TangentVector& xi) {
331 return Class::adjointMap(xi);
334 static TangentVector adjoint(
const TangentVector& xi,
335 const TangentVector& y,
336 ChartJacobian Hxi = {},
337 ChartJacobian H_y = {}) {
338 return Class::adjoint(xi, y, Hxi, H_y);
341 static TangentVector adjointTranspose(
const TangentVector& xi,
342 const TangentVector& y,
343 ChartJacobian Hxi = {},
344 ChartJacobian H_y = {}) {
345 return Class::adjointTranspose(xi, y, Hxi, H_y);
385 T
BCH(
const T& X,
const T& Y) {
386 static const double _2 = 1. / 2., _12 = 1. / 12., _24 = 1. / 24.;
387 T X_Y = bracket(X, Y);
388 return T(X + Y + _2 * X_Y + _12 * bracket(X - Y, X_Y) - _24 * bracket(Y, bracket(X, X_Y)));
391#ifdef GTSAM_ALLOW_DEPRECATED_SINCE_V43
394 [[deprecated(
"use T::Hat instead")]] Matrix wedge(
const Vector& x) {
406 T
expm(
const Vector& x,
int K = 7) {
407 const Matrix xhat = T::Hat(x);
408 return T(
expm(xhat, K));
422#define GTSAM_CONCEPT_MATRIX_LIE_GROUP_INST(T) template class gtsam::IsMatrixLieGroup<T>;
423#define GTSAM_CONCEPT_MATRIX_LIE_GROUP_TYPE(T) using _gtsam_IsMatrixLieGroup_##T = gtsam::IsMatrixLieGroup<T>;
Base class and basic functions for Lie types.
Global functions in a separate testing namespace.
Definition chartTesting.h:28
Matrix expm(const Matrix &A, size_t K)
Numerical exponential map, naive approach, not industrial strength !
Definition Matrix.cpp:587
T BCH(const T &X, const T &Y)
Three term approximation of the Baker-Campbell-Hausdorff formula In non-commutative Lie groups,...
Definition MatrixLieGroup.h:385
A manifold defines a space in which there is a notion of a linear tangent space that can be centered ...
Definition Group.h:37
A CRTP helper class that implements Lie group methods Prerequisites: methods operator*,...
Definition Lie.h:114
static constexpr int Dim()
Definition Lie.h:121
std::enable_if_t< M !=Eigen::Dynamic, int > dim() const
Definition Lie.h:125
A helper class that implements the traits interface for GTSAM lie groups.
Definition Lie.h:281
Lie Group Concept.
Definition Lie.h:377
A CRTP helper class that implements matrix Lie group methods.
Definition MatrixLieGroup.h:51
static TangentVector adjointTranspose(const TangentVector &xi, const TangentVector &y, ChartJacobian Hxi={}, ChartJacobian H_y={})
Dual Lie algebra action ad_xi^T(y), with optional Jacobians.
Definition MatrixLieGroup.h:222
static Jacobian adjointMap(const TangentVector &xi)
Lie algebra adjoint map ad_xi, with optional specialization in derived classes.
Definition MatrixLieGroup.h:191
Jacobian AdjointMap() const
A generic implementation of AdjointMap for matrix Lie groups.
Definition MatrixLieGroup.h:125
TangentVector AdjointTranspose(const TangentVector &x, ChartJacobian H_this={}, ChartJacobian H_x={}) const
Dual Adjoint action on a tangent covector.
Definition MatrixLieGroup.h:160
static TangentVector adjoint(const TangentVector &xi, const TangentVector &y, ChartJacobian Hxi={}, ChartJacobian H_y={})
Lie algebra action ad_xi(y), with optional Jacobians.
Definition MatrixLieGroup.h:210
TangentVector Adjoint(const TangentVector &xi, ChartJacobian H_this={}, ChartJacobian H_xi={}) const
Adjoint action on a tangent vector.
Definition MatrixLieGroup.h:145
Eigen::Matrix< double, internal::product(N, N), 1 > vec(OptionalJacobian< internal::product(N, N), D > H={}) const
Vectorize the matrix representation of a Lie group element.
Definition MatrixLieGroup.h:75
Adds MatrixLieGroup methods to LieGroupTraits.
Definition MatrixLieGroup.h:295
static Eigen::Matrix< double, product(N, N), 1 > Vec(const Class &m, OptionalJacobian< product(N, N), LieGroupTraits< Class >::dimension > H={})
Vectorize the matrix representation of a Lie group element.
Definition MatrixLieGroup.h:310
Both LieGroupTraits and Testable.
Definition MatrixLieGroup.h:350
Matrix Lie Group Concept.
Definition MatrixLieGroup.h:358
OptionalJacobian is an Eigen::Ref like class that can take be constructed using either a fixed size o...
Definition OptionalJacobian.h:40
A helper that implements the traits interface for GTSAM types.
Definition Testable.h:152