gtsam
Loading...
Searching...
No Matches
SOn.h
Go to the documentation of this file.
1/* ----------------------------------------------------------------------------
2
3 * GTSAM Copyright 2010-2019, 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
18
19#pragma once
20
22#include <gtsam/dllexport.h>
23
24#include <Eigen/Core>
25#include <Eigen/Geometry>
26
27#if GTSAM_ENABLE_BOOST_SERIALIZATION
28#include <boost/serialization/nvp.hpp>
29#endif
30
31#include <iostream> // TODO(frank): how to avoid?
32#include <string>
33#include <type_traits>
34#include <vector>
35#include <random>
36#include <cassert>
37
38namespace gtsam {
39
40namespace internal {
42constexpr int DimensionSO(int N) {
43 return (N < 0) ? Eigen::Dynamic : N * (N - 1) / 2;
44}
45
46// Calculate N^2 at compile time, or return Dynamic if so
47constexpr int NSquaredSO(int N) { return (N < 0) ? Eigen::Dynamic : N * N; }
48} // namespace internal
49
54template <int N>
55class SO : public MatrixLieGroup<SO<N>, internal::DimensionSO(N), N> {
56 public:
57 inline constexpr static auto dimension = internal::DimensionSO(N);
58 using MatrixNN = Eigen::Matrix<double, N, N>;
59 using VectorN2 = Eigen::Matrix<double, internal::NSquaredSO(N), 1>;
60 using MatrixDD = Eigen::Matrix<double, dimension, dimension>;
61
63 using LieAlgebra = MatrixNN;
64
65 protected:
66 MatrixNN matrix_;
67
68 // enable_if_t aliases, used to specialize constructors/methods, see
69 // https://www.fluentcpp.com/2018/05/18/make-sfinae-pretty-2-hidden-beauty-sfinae/
70 template <int N_>
71 using IsDynamic = typename std::enable_if<N_ == Eigen::Dynamic, void>::type;
72 template <int N_>
73 using IsFixed = typename std::enable_if<N_ >= 2, void>::type;
74 template <int N_>
75 using IsSO3 = typename std::enable_if<N_ == 3, void>::type;
76
77 public:
80
82 template <int N_ = N, typename = IsFixed<N_>>
83 SO() : matrix_(MatrixNN::Identity()) {}
84
86 template <int N_ = N, typename = IsDynamic<N_>>
87 explicit SO(size_t n = 0) {
88 // We allow for n=0 as the default constructor, needed for serialization,
89 // wrappers etc.
90 matrix_ = Eigen::MatrixXd::Identity(n, n);
91 }
92
94 template <typename Derived>
95 explicit SO(const Eigen::MatrixBase<Derived>& R) : matrix_(R.eval()) {}
96
98 template <typename Derived>
99 static SO FromMatrix(const Eigen::MatrixBase<Derived>& R) {
100 return SO(R);
101 }
102
104 template <typename Derived, int N_ = N, typename = IsDynamic<N_>>
105 static SO Lift(size_t n, const Eigen::MatrixBase<Derived> &R) {
106 Matrix Q = Matrix::Identity(n, n);
107 const int p = R.rows();
108 assert(p >= 0 && p <= static_cast<int>(n) && R.cols() == p);
109 Q.topLeftCorner(p, p) = R;
110 return SO(Q);
111 }
112
114 template <int M, int N_ = N, typename = IsDynamic<N_>>
115 explicit SO(const SO<M>& R) : matrix_(R.matrix()) {}
116
118 template <int N_ = N, typename = IsSO3<N_>>
119 explicit SO(const Eigen::AngleAxisd& angleAxis) : matrix_(angleAxis) {}
120
122 static SO AxisAngle(const Vector3& axis, double theta);
123
126 static SO ClosestTo(const MatrixNN& M);
127
131 static SO ChordalMean(const std::vector<SO>& rotations);
132
134 template <int N_ = N, typename = IsDynamic<N_>>
135 static SO Random(std::mt19937& rng, size_t n = 0) {
136 if (n == 0) throw std::runtime_error("SO: Dimensionality not known.");
137 // TODO(frank): this might need to be re-thought
138 static std::uniform_real_distribution<double> randomAngle(-M_PI, M_PI);
139 const size_t d = SO::Dimension(n);
140 Vector xi(d);
141 for (size_t j = 0; j < d; j++) {
142 xi(j) = randomAngle(rng);
143 }
144 return SO::Retract(xi);
145 }
146
148 template <int N_ = N, typename = IsFixed<N_>>
149 static SO Random(std::mt19937& rng) {
150 // By default, use dynamic implementation above. Specialized for SO(3).
151 return SO(SO<Eigen::Dynamic>::Random(rng, N).matrix());
152 }
153
157
159 const MatrixNN& matrix() const { return matrix_; }
160
161 size_t rows() const { return matrix_.rows(); }
162 size_t cols() const { return matrix_.cols(); }
163
167
168 void print(const std::string& s = std::string()) const;
169
170 bool equals(const SO& other, double tol) const {
171 return equal_with_abs_tol(matrix_, other.matrix_, tol);
172 }
173
177
179 SO operator*(const SO& other) const {
180 assert(dim() == other.dim());
181 return SO(matrix_ * other.matrix_);
182 }
183
185 template <int N_ = N, typename = IsFixed<N_>>
186 static SO Identity() {
187 return SO();
188 }
189
191 template <int N_ = N, typename = IsDynamic<N_>>
192 static SO Identity(size_t n = 0) {
193 return SO(n);
194 }
195
197 SO inverse() const { return SO(matrix_.transpose()); }
198
202
203 using TangentVector = Eigen::Matrix<double, dimension, 1>;
204 using ChartJacobian = OptionalJacobian<dimension, dimension>;
205
206 // Calculate manifold dimensionality for SO(n).
207 // Available as dimension or Dim() for fixed N.
208 static size_t Dimension(size_t n) { return n * (n - 1) / 2; }
209
210 // Calculate ambient dimension n from manifold dimensionality d.
211 static size_t AmbientDim(size_t d) { return (1 + std::sqrt(1 + 8 * d)) / 2; }
212
213 // Calculate run-time dimensionality of manifold.
214 size_t dim() const { return Dimension(static_cast<size_t>(matrix_.rows())); }
215
231 static MatrixNN Hat(const TangentVector& xi);
232
234 static void Hat(const Vector &xi, Eigen::Ref<MatrixNN> X);
235
237 static TangentVector Vee(const MatrixNN& X);
238
239 // Chart at origin
245 static SO Retract(const TangentVector& xi);
246
249 static SO Retract(const TangentVector& xi, ChartJacobian H) = delete;
250
254 static TangentVector Local(const SO& R);
255
257 static TangentVector Local(const SO& R, ChartJacobian H) = delete;
258 };
259
260 // Return dynamic identity DxD Jacobian for given SO(n)
261 template <int N_ = N, typename = IsDynamic<N_>>
262 static MatrixDD IdentityJacobian(size_t n) {
263 const size_t d = Dimension(n);
264 return MatrixDD::Identity(d, d);
265 }
266
270
272 MatrixDD AdjointMap() const {
274 }
275
279 static SO Expmap(const TangentVector& omega);
280
282 static SO Expmap(const TangentVector& omega, ChartJacobian H) = delete;
283
285 static MatrixDD ExpmapDerivative(const TangentVector& omega) = delete;
286
290 static TangentVector Logmap(const SO& R);
291
293 static TangentVector Logmap(const SO& R, ChartJacobian H) = delete;
294
296 static MatrixDD LogmapDerivative(const TangentVector& omega) = delete;
297
298 // inverse with optional derivative
300
304
306 VectorN2 vec(OptionalJacobian<internal::NSquaredSO(N), dimension> H =
307 {}) const {
309 }
310
312 template <int N_ = N, typename = IsFixed<N_>>
313 static Matrix VectorizedGenerators() {
314 constexpr size_t N2 = static_cast<size_t>(N * N);
315 Eigen::Matrix<double, N2, dimension> G;
316 for (size_t j = 0; j < dimension; j++) {
317 const auto X = Hat(Vector::Unit(dimension, j));
318 G.col(j) = Eigen::Map<const VectorN2>(X.data());
319 }
320 return G;
321 }
322
324 template <int N_ = N, typename = IsDynamic<N_>>
325 static Matrix VectorizedGenerators(size_t n = 0) {
326 const size_t n2 = n * n, dim = Dimension(n);
327 Matrix G(n2, dim);
328 for (size_t j = 0; j < dim; j++) {
329 const auto X = Hat(Vector::Unit(dim, j));
330 G.col(j) = Eigen::Map<const Matrix>(X.data(), n2, 1);
331 }
332 return G;
333 }
334
338
339#if GTSAM_ENABLE_BOOST_SERIALIZATION
340 template <class Archive>
341 friend void save(Archive&, SO&, const unsigned int);
342 template <class Archive>
343 friend void load(Archive&, SO&, const unsigned int);
344 template <class Archive>
345 friend void serialize(Archive&, SO&, const unsigned int);
346 friend class boost::serialization::access;
347 friend class Rot3; // for serialize
348#endif
349
351};
352
353using SOn = SO<Eigen::Dynamic>;
354
355/*
356 * Specialize dynamic Hat and Vee, because recursion depends on dynamic nature.
357 * The definition is in SOn.cpp. Fixed-size SO3 and SO4 have their own version,
358 * and implementation for other fixed N is in SOn-inl.h.
359 */
360
361template <>
362GTSAM_EXPORT
363Matrix SOn::Hat(const Vector& xi);
364
365template <>
366GTSAM_EXPORT
367Vector SOn::Vee(const Matrix& X);
368
369/*
370 * Specialize dynamic compose and between, because the derivative is unknowable
371 * by the LieGroup implementations, who return a fixed-size matrix for H2.
372 */
373
374using DynamicJacobian = OptionalJacobian<Eigen::Dynamic, Eigen::Dynamic>;
375
376template <>
377GTSAM_EXPORT
378SOn LieGroup<SOn, Eigen::Dynamic>::compose(const SOn& g, DynamicJacobian H1,
379 DynamicJacobian H2) const;
380
381template <>
382GTSAM_EXPORT
383SOn LieGroup<SOn, Eigen::Dynamic>::between(const SOn& g, DynamicJacobian H1,
384 DynamicJacobian H2) const;
385
386#if GTSAM_ENABLE_BOOST_SERIALIZATION
388template<class Archive>
389void serialize(
390 Archive& ar, SOn& Q,
391 const unsigned int file_version
392) {
393 Matrix& M = Q.matrix_;
394 ar& BOOST_SERIALIZATION_NVP(M);
395}
396#endif
397
398/*
399 * Define the traits. internal::MatrixLieGroup provides both Lie group and Testable
400 */
401
402template <int N>
403struct traits<SO<N>> : public internal::MatrixLieGroup<SO<N>, N> {};
404
405template <int N>
406struct traits<const SO<N>> : public internal::MatrixLieGroup<SO<N>, N> {};
407
408} // namespace gtsam
409
410#include "SOn-inl.h"
Base class and basic functions for Matrix Lie groups.
constexpr int DimensionSO(int N)
Calculate dimensionality of SO<N> manifold, or return Dynamic if so.
Definition SOn.h:42
Template implementations for SO(n).
Global functions in a separate testing namespace.
Definition chartTesting.h:28
void save(const Matrix &A, const string &s, const string &filename)
save a matrix to file, which can be loaded by matlab
Definition Matrix.cpp:154
bool equal_with_abs_tol(const Eigen::DenseBase< MATRIX > &A, const Eigen::DenseBase< MATRIX > &B, double tol=1e-9)
equals with a tolerance
Definition Matrix.h:81
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 SO< N > Retract(const TangentVector &v)
Definition Lie.h:193
A CRTP helper class that implements matrix Lie group methods.
Definition MatrixLieGroup.h:51
std::enable_if_t< M !=Eigen::Dynamic, int > dim() const
Both LieGroupTraits and Testable.
Definition MatrixLieGroup.h:350
OptionalJacobian is an Eigen::Ref like class that can take be constructed using either a fixed size o...
Definition OptionalJacobian.h:40
Rot3 is a 3D rotation represented as a rotation matrix if the preprocessor symbol GTSAM_USE_QUATERNIO...
Definition Rot3.h:65
Manifold of special orthogonal rotation matrices SO<N>.
Definition SOn.h:55
static SO FromMatrix(const Eigen::MatrixBase< Derived > &R)
Named constructor from Eigen Matrix.
Definition SOn.h:99
static Matrix VectorizedGenerators()
Calculate N^2 x dim matrix of vectorized Lie algebra generators for SO(N).
Definition SOn.h:313
SO inverse() const
inverse of a rotation = transpose
Definition SOn.h:197
static SO ChordalMean(const std::vector< SO > &rotations)
Named constructor that finds chordal mean , currently only defined for SO3.
SO operator*(const SO &other) const
Multiplication.
Definition SOn.h:179
static TangentVector Vee(const MatrixNN &X)
Inverse of Hat. See note about xi element order in Hat.
Definition SOn-inl.h:35
MatrixNN matrix_
Definition SOn.h:66
VectorN2 vec(OptionalJacobian< internal::NSquaredSO(N), dimension > H={}) const
Return vectorized rotation matrix in column order.
Definition SOn.h:306
static SO Expmap(const TangentVector &omega)
Exponential map at identity - create a rotation from canonical coordinates.
Definition SOn-inl.h:57
MatrixNN LieAlgebra
Definition SOn.h:63
static SO Expmap(const TangentVector &omega, ChartJacobian H)=delete
Exponential map with a Jacobian, specialized when supported.
static SO AxisAngle(const Vector3 &axis, double theta)
Constructor from axis and angle. Only defined for SO3.
static void Hat(const Vector &xi, Eigen::Ref< MatrixNN > X)
In-place version of Hat (see details there), implements recursion.
static SO Identity()
Definition SOn.h:186
static MatrixNN Hat(const TangentVector &xi)
Hat operator creates Lie algebra element corresponding to d-vector, where d is the dimensionality of ...
Definition SOn-inl.h:29
SO(const SO< M > &R)
Construct dynamic SO(n) from Fixed SO<M>.
Definition SOn.h:115
SO(size_t n=0)
Construct SO<N> identity for N == Eigen::Dynamic.
Definition SOn.h:87
SO()
Construct SO<N> identity for N >= 2.
Definition SOn.h:83
static MatrixDD LogmapDerivative(const TangentVector &omega)=delete
Derivative of Logmap, specialized when supported.
static MatrixDD ExpmapDerivative(const TangentVector &omega)=delete
Derivative of Expmap, specialized when supported.
static TangentVector Logmap(const SO &R)
Log map at identity - returns the canonical coordinates of this rotation.
Definition SOn-inl.h:62
static SO Lift(size_t n, const Eigen::MatrixBase< Derived > &R)
Named constructor from lower dimensional matrix.
Definition SOn.h:105
static SO Random(std::mt19937 &rng, size_t n=0)
Random SO(n) element (no big claims about uniformity). SO(3) is specialized in SO3....
Definition SOn.h:135
static SO Identity(size_t n=0)
SO<N> identity for N == Eigen::Dynamic.
Definition SOn.h:192
const MatrixNN & matrix() const
Definition SOn.h:159
static TangentVector Logmap(const SO &R, ChartJacobian H)=delete
Logarithm map with a Jacobian, specialized when supported.
static SO Random(std::mt19937 &rng)
Random SO(N) element (no big claims about uniformity).
Definition SOn.h:149
MatrixDD AdjointMap() const
Adjoint map.
Definition SOn.h:272
static SO ClosestTo(const MatrixNN &M)
Named constructor that finds SO(n) matrix closest to M in Frobenius norm, currently only defined for ...
SO(const Eigen::AngleAxisd &angleAxis)
Constructor from AngleAxisd.
Definition SOn.h:119
static Matrix VectorizedGenerators(size_t n=0)
Calculate n^2 x dim matrix of vectorized Lie algebra generators for SO(n).
Definition SOn.h:325
SO(const Eigen::MatrixBase< Derived > &R)
Constructor from Eigen Matrix, dynamic version.
Definition SOn.h:95
Definition SOn.h:240
static TangentVector Local(const SO &R)
Inverse of Retract.
Definition SOn-inl.h:49
static SO Retract(const TangentVector &xi, ChartJacobian H)=delete
Retract with a Jacobian, specialized only for dimensions that support it.
static SO Retract(const TangentVector &xi)
Retract uses Cayley map.
Definition SOn-inl.h:40
static TangentVector Local(const SO &R, ChartJacobian H)=delete
Local coordinates with a Jacobian, specialized when supported.