24template<
typename T>
struct traits;
29template<
class Class,
int N>
34 typedef Eigen::Matrix<double, N, 1> TangentVector;
36 typedef Eigen::Matrix<double, N, N> Jacobian;
37 static size_t GetDimension(
const Class&) {
return static_cast<size_t>(N);}
39 static TangentVector Local(
const Class& origin,
const Class& other,
40 ChartJacobian H1 = {}, ChartJacobian H2 = {}) {
41 if (H1) *H1 = - Jacobian::Identity();
42 if (H2) *H2 = Jacobian::Identity();
43 Class v = other - origin;
47 static Class Retract(
const Class& origin,
const TangentVector& v,
48 ChartJacobian H1 = {}, ChartJacobian H2 = {}) {
49 if (H1) *H1 = Jacobian::Identity();
50 if (H2) *H2 = Jacobian::Identity();
59 typedef Eigen::Matrix<double, N, 1> LieAlgebra;
61 static TangentVector Logmap(
const Class& m, ChartJacobian Hm = {}) {
62 if (Hm) *Hm = Jacobian::Identity();
66 static Class Expmap(
const TangentVector& v, ChartJacobian Hv = {}) {
67 if (Hv) *Hv = Jacobian::Identity();
71 static Class Compose(
const Class& v1,
const Class& v2, ChartJacobian H1 = {},
72 ChartJacobian H2 = {}) {
73 if (H1) *H1 = Jacobian::Identity();
74 if (H2) *H2 = Jacobian::Identity();
78 static Class Between(
const Class& v1,
const Class& v2, ChartJacobian H1 = {},
79 ChartJacobian H2 = {}) {
80 if (H1) *H1 = - Jacobian::Identity();
81 if (H2) *H2 = Jacobian::Identity();
85 static Class Inverse(
const Class& v, ChartJacobian H = {}) {
86 if (H) *H = - Jacobian::Identity();
90 static LieAlgebra Hat(
const TangentVector& v) {
return v; }
92 static TangentVector Vee(
const LieAlgebra& X) {
return X; }
94 static Jacobian AdjointMap(
const Class& ) {
95 return Jacobian::Identity();
106 static Class Compose(
const Class& v1,
const Class& v2) {
return v1+v2;}
107 static Class Between(
const Class& v1,
const Class& v2) {
return v2-v1;}
108 static Class Inverse(
const Class& m) {
return -m;}
113 typedef Eigen::VectorXd TangentVector;
115 static size_t GetDimension(
const Class& m) {
return m.dim();}
117 static Eigen::MatrixXd Eye(
const Class& m) {
118 size_t dim = GetDimension(m);
119 return Eigen::MatrixXd::Identity(dim, dim);
122 static TangentVector Local(
const Class& origin,
const Class& other,
123 ChartJacobian H1 = {}, ChartJacobian H2 = {}) {
124 if (H1) *H1 = - Eye(origin);
125 if (H2) *H2 = Eye(other);
126 Class v = other - origin;
130 static Class Retract(
const Class& origin,
const TangentVector& v,
131 ChartJacobian H1 = {}, ChartJacobian H2 = {}) {
132 if (H1) *H1 = Eye(origin);
133 if (H2) *H2 = Eye(origin);
142 static TangentVector Logmap(
const Class& m, ChartJacobian Hm = {}) {
143 if (Hm) *Hm = Eye(m);
147 static Class Expmap(
const TangentVector& v, ChartJacobian Hv = {}) {
149 if (Hv) *Hv = Eye(result);
153 static Class Compose(
const Class& v1,
const Class& v2, ChartJacobian H1,
154 ChartJacobian H2 = {}) {
155 if (H1) *H1 = Eye(v1);
156 if (H2) *H2 = Eye(v2);
160 static Class Between(
const Class& v1,
const Class& v2, ChartJacobian H1,
161 ChartJacobian H2 = {}) {
162 if (H1) *H1 = - Eye(v1);
163 if (H2) *H2 = Eye(v2);
167 static Class Inverse(
const Class& v, ChartJacobian H) {
172 static Eigen::MatrixXd AdjointMap(
const Class& m) {
return Eye(m); }
180 inline constexpr static auto dim = Class::dimension;
186 p = Class::Identity();
209 static Class Identity() {
return Class::Identity();}
214 inline constexpr static auto dimension = Class::dimension;
215 typedef Class ManifoldType;
225template<
typename Scalar>
232 static void Print(Scalar m,
const std::string& str =
"") {
235 static bool Equals(Scalar v1, Scalar v2,
double tol = 1e-8) {
236 return std::abs(v1 - v2) < tol;
243 static Scalar Identity() {
return 0;}
248 typedef Scalar ManifoldType;
249 inline constexpr static auto dimension = 1;
250 typedef Eigen::Matrix<double, 1, 1> TangentVector;
253 static TangentVector Local(Scalar origin, Scalar other,
254 ChartJacobian H1 = {}, ChartJacobian H2 = {}) {
255 if (H1) (*H1)[0] = -1.0;
256 if (H2) (*H2)[0] = 1.0;
257 TangentVector result;
258 result(0) = other - origin;
262 static Scalar Retract(Scalar origin,
const TangentVector& v,
263 ChartJacobian H1 = {}, ChartJacobian H2 = {}) {
264 if (H1) (*H1)[0] = 1.0;
265 if (H2) (*H2)[0] = 1.0;
266 return origin + v[0];
272 static TangentVector Logmap(Scalar m, ChartJacobian H = {}) {
273 if (H) (*H)[0] = 1.0;
277 static Scalar Expmap(
const TangentVector& v, ChartJacobian H = {}) {
278 if (H) (*H)[0] = 1.0;
296template<
int M,
int N,
int Options,
int MaxRows,
int MaxCols>
297struct traits<Eigen::Matrix<double, M, N, Options, MaxRows, MaxCols> > :
299 Eigen::Matrix<double, M, N, Options, MaxRows, MaxCols>, M * N> {
302 typedef Eigen::Matrix<double, M, N, Options, MaxRows, MaxCols> Fixed;
306 static void Print(
const Fixed& m,
const std::string& str =
"") {
309 static bool Equals(
const Fixed& v1,
const Fixed& v2,
double tol = 1e-8) {
317 static Fixed Identity() {
return Fixed::Zero();}
322 inline constexpr static auto dimension = M * N;
323 typedef Fixed ManifoldType;
324 typedef Eigen::Matrix<double, dimension, 1> TangentVector;
325 typedef Eigen::Matrix<double, dimension, dimension> Jacobian;
334 if constexpr (D == 1) {
337 result.col(0).tail(dimension) =
338 Eigen::Map<const TangentVector>(value.data());
341 throw std::invalid_argument(
342 "fixed-size vector-space QCQP values only support D=1.");
349 if constexpr (D == 1) {
354 throw std::invalid_argument(
355 "fixed-size vector-space QCQP constraints only support D=1.");
362 if constexpr (D == 1) {
363 if (qcqpValue.rows() !=
QcqpVectorDim || qcqpValue.cols() != 1 ||
364 std::abs(qcqpValue(0, 0)) < 1e-12) {
365 throw std::invalid_argument(
366 "fixed-size vector-space QCQP recovery requires a compatible "
367 "homogeneous vector.");
370 Eigen::Map<TangentVector>(result.data()) =
371 qcqpValue.col(0).tail(dimension) / qcqpValue(0, 0);
374 throw std::invalid_argument(
375 "fixed-size vector-space QCQP recovery only supports D=1.");
379 static TangentVector Local(
const Fixed& origin,
const Fixed& other,
380 ChartJacobian H1 = {}, ChartJacobian H2 = {}) {
381 if (H1) (*H1) = -Jacobian::Identity();
382 if (H2) (*H2) = Jacobian::Identity();
383 TangentVector result;
384 Eigen::Map<Fixed>(result.data()) = other - origin;
388 static Fixed Retract(
const Fixed& origin,
const TangentVector& v,
389 ChartJacobian H1 = {}, ChartJacobian H2 = {}) {
390 if (H1) (*H1) = Jacobian::Identity();
391 if (H2) (*H2) = Jacobian::Identity();
392 return origin + Eigen::Map<const Fixed>(v.data());
398 static TangentVector
Logmap(
const Fixed& m, ChartJacobian H = {}) {
399 if (H) *H = Jacobian::Identity();
400 TangentVector result;
401 Eigen::Map<Fixed>(result.data()) = m;
405 static Fixed Expmap(
const TangentVector& v, ChartJacobian H = {}) {
408 if (H) *H = Jacobian::Identity();
409 return m + Eigen::Map<const Fixed>(v.data());
421template<
int M,
int N,
int Options,
int MaxRows,
int MaxCols>
425 typedef Eigen::Matrix<double, M, N, Options, MaxRows, MaxCols> Dynamic;
429 static void Print(
const Dynamic& m,
const std::string& str =
"") {
432 static bool Equals(
const Dynamic& v1,
const Dynamic& v2,
441 static Dynamic Identity() {
442 throw std::runtime_error(
"Identity not defined for dynamic types");
448 inline constexpr static auto dimension = Eigen::Dynamic;
449 typedef Eigen::VectorXd TangentVector;
450 typedef Eigen::MatrixXd Jacobian;
452 typedef Dynamic ManifoldType;
454 static size_t GetDimension(
const Dynamic& m) {
455 return static_cast<size_t>(m.rows() * m.cols());
458 static Jacobian Eye(
const Dynamic& m) {
459 size_t dim = GetDimension(m);
460 return Eigen::Matrix<double, dimension, dimension>::Identity(dim, dim);
463 static TangentVector Local(
const Dynamic& m,
const Dynamic& other,
464 ChartJacobian H1 = {}, ChartJacobian H2 = {}) {
465 if (H1) *H1 = -Eye(m);
466 if (H2) *H2 = Eye(m);
467 TangentVector v(GetDimension(m));
468 Eigen::Map<Dynamic>(v.data(), m.rows(), m.cols()) = other - m;
472 static Dynamic Retract(
const Dynamic& m,
const TangentVector& v,
473 ChartJacobian H1 = {}, ChartJacobian H2 = {}) {
474 if (H1) *H1 = Eye(m);
475 if (H2) *H2 = Eye(m);
476 return m + Eigen::Map<const Dynamic>(v.data(), m.rows(), m.cols());
482 using LieAlgebra = Dynamic;
484 static TangentVector Logmap(
const Dynamic& m, ChartJacobian H = {}) {
486 TangentVector result(GetDimension(m));
487 Eigen::Map<Dynamic>(result.data(), m.rows(), m.cols()) = m;
491 static Dynamic Expmap(
const TangentVector& v, ChartJacobian H = {}) {
492 if constexpr (M == Eigen::Dynamic && N == Eigen::Dynamic) {
493 static_cast<void>(v);
494 static_cast<void>(H);
495 throw std::runtime_error(
"Expmap not defined for fully dynamic matrices");
497 const int rows = (M == Eigen::Dynamic) ? v.size() / N : M;
498 const int cols = (N == Eigen::Dynamic) ? v.size() / M : N;
499 if (rows * cols != v.size()) {
500 throw std::invalid_argument(
501 "Dynamic Expmap tangent dimension does not match matrix shape");
503 Dynamic result(rows, cols);
504 result = Eigen::Map<const Dynamic>(v.data(), rows, cols);
505 if (H) *H = Jacobian::Identity(v.size(), v.size());
510 static Dynamic Inverse(
const Dynamic& m, ChartJacobian H = {}) {
515 static Dynamic Compose(
const Dynamic& v1,
const Dynamic& v2,
516 ChartJacobian H1 = {}, ChartJacobian H2 = {}) {
517 if (H1) *H1 = Eye(v1);
518 if (H2) *H2 = Eye(v1);
522 static Dynamic Between(
const Dynamic& v1,
const Dynamic& v2,
523 ChartJacobian H1 = {}, ChartJacobian H2 = {}) {
524 if (H1) *H1 = -Eye(v1);
525 if (H2) *H2 = Eye(v1);
529 static LieAlgebra Hat(
const TangentVector& v) {
533 static TangentVector Vee(
const LieAlgebra& X) {
537 static Jacobian AdjointMap(
const Dynamic& m) {
return Eye(m); }
545template<
int Options,
int MaxRows,
int MaxCols>
546struct traits<Eigen::Matrix<double, -1, -1, Options, MaxRows, MaxCols> > :
551template<
int Options,
int MaxRows,
int MaxCols>
552struct traits<Eigen::Matrix<double, -1, 1, Options, MaxRows, MaxCols> > :
557template<
int Options,
int MaxRows,
int MaxCols>
558struct traits<Eigen::Matrix<double, 1, -1, Options, MaxRows, MaxCols> > :
571 (std::is_base_of<vector_space_tag, structure_category_tag>::value),
572 "This type's trait does not assert it as a vector space (or derived)");
Base class and basic functions for Lie types.
Global functions in a separate testing namespace.
Definition chartTesting.h:28
void print(const Matrix &A, const string &s, ostream &stream)
print without optional string, must specify cout yourself
Definition Matrix.cpp:143
@ Logmap
Use the SE_2(3) NavState Logmap for every backend.
Definition PreintegrationParams.h:32
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
tag to assert a type is a Lie group
Definition Lie.h:271
Lie Group Concept.
Definition Lie.h:377
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
tag to assert a type is a vector space
Definition VectorSpace.h:21
VectorSpaceTraits Implementation for Fixed sizes.
Definition VectorSpace.h:30
Requirements on type to pass it to Manifold template below.
Definition VectorSpace.h:178
A helper that implements the traits interface for classes that define vector spaces To use this for y...
Definition VectorSpace.h:199
VectorSpace provides both Testable and VectorSpaceTraits.
Definition VectorSpace.h:221
A helper that implements the traits interface for scalar vector spaces.
Definition VectorSpace.h:226
static Matrix QcqpValue(const Fixed &value)
Return the exact D=1 homogeneous QCQP representation.
Definition VectorSpace.h:333
static std::vector< std::pair< Matrix, double > > QcqpConstraints()
Return the homogeneous-coordinate constraint x(0)^2 = 1.
Definition VectorSpace.h:348
static constexpr int QcqpVectorDim
Dimension of the exact D=1 homogeneous QCQP vector [1; vec(value)].
Definition VectorSpace.h:329
static Fixed FromQcqpValue(const Matrix &qcqpValue)
Recover a fixed-size value from its exact D=1 homogeneous QCQP vector.
Definition VectorSpace.h:361
Definition VectorSpace.h:422
Vector Space concept.
Definition VectorSpace.h:564