2010-01-08 08:40:17 +08:00
|
|
|
|
/*
|
|
|
|
|
* Lie.h
|
|
|
|
|
*
|
|
|
|
|
* Created on: Jan 5, 2010
|
|
|
|
|
* Author: Richard Roberts
|
|
|
|
|
*/
|
|
|
|
|
|
2010-01-14 13:58:58 +08:00
|
|
|
|
#pragma once
|
2010-01-08 08:40:17 +08:00
|
|
|
|
|
2010-01-10 14:35:16 +08:00
|
|
|
|
#include <string>
|
2010-03-02 10:25:27 +08:00
|
|
|
|
#include "Matrix.h"
|
2010-01-08 08:40:17 +08:00
|
|
|
|
|
|
|
|
|
namespace gtsam {
|
|
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
|
T expmap(const Vector& v); /* Exponential map about identity */
|
|
|
|
|
|
|
|
|
|
// The following functions may be overridden in your own class file
|
|
|
|
|
// with more efficient versions if possible.
|
|
|
|
|
|
|
|
|
|
// Compute l1 s.t. l2=l1*l0
|
|
|
|
|
template<class T>
|
Rot2 "named constructors" (http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.8):
/** Named constructor from angle == exponential map at identity */
static Rot2 fromAngle(double theta) { return Rot2(cos(theta),sin(theta));}
/** Named constructor from cos(theta),sin(theta) pair, will *not* normalize! */
static Rot2 fromCosSin(double c, double s);
/** Named constructor that behaves as atan2, i.e., y,x order (!) and normalizes */
static Rot2 atan2(double y, double x);
which are a bit more verbose, but at least won't cause hours of bug-tracking :-(
I also made most compose, inverse, and rotate functions into methods, with the global functions mostly calling the methods. Methods have privileged access to members and hence are typically much more readable.
2010-03-03 11:31:53 +08:00
|
|
|
|
inline T between(const T& l1, const T& l2) { return compose(inverse(l1),l2); }
|
2010-01-08 08:40:17 +08:00
|
|
|
|
|
|
|
|
|
// Log map centered at l0, s.t. exp(l0,log(l0,lp)) = lp
|
|
|
|
|
template<class T>
|
|
|
|
|
inline Vector logmap(const T& l0, const T& lp) { return logmap(between(l0,lp)); }
|
|
|
|
|
|
2010-01-27 04:00:17 +08:00
|
|
|
|
/* Exponential map centered at l0, s.t. exp(t,d) = t*exp(d) */
|
2010-01-08 08:40:17 +08:00
|
|
|
|
template<class T>
|
Rot2 "named constructors" (http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.8):
/** Named constructor from angle == exponential map at identity */
static Rot2 fromAngle(double theta) { return Rot2(cos(theta),sin(theta));}
/** Named constructor from cos(theta),sin(theta) pair, will *not* normalize! */
static Rot2 fromCosSin(double c, double s);
/** Named constructor that behaves as atan2, i.e., y,x order (!) and normalizes */
static Rot2 atan2(double y, double x);
which are a bit more verbose, but at least won't cause hours of bug-tracking :-(
I also made most compose, inverse, and rotate functions into methods, with the global functions mostly calling the methods. Methods have privileged access to members and hence are typically much more readable.
2010-03-03 11:31:53 +08:00
|
|
|
|
inline T expmap(const T& t, const Vector& d) { return compose(t,expmap<T>(d)); }
|
2010-01-08 08:40:17 +08:00
|
|
|
|
|
2010-01-10 07:15:06 +08:00
|
|
|
|
/**
|
|
|
|
|
* Base class for Lie group type
|
|
|
|
|
*/
|
|
|
|
|
template <class T>
|
|
|
|
|
class Lie {
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns dimensionality of the tangent space
|
|
|
|
|
*/
|
|
|
|
|
size_t dim() const;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns Exponential mapy
|
|
|
|
|
*/
|
|
|
|
|
T expmap(const Vector& v) const;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns Log map
|
|
|
|
|
*/
|
|
|
|
|
Vector logmap(const T& lp) const;
|
|
|
|
|
|
|
|
|
|
};
|
2010-01-10 14:35:16 +08:00
|
|
|
|
|
|
|
|
|
/** Call print on the object */
|
|
|
|
|
template<class T>
|
2010-01-10 22:59:22 +08:00
|
|
|
|
inline void print_(const T& object, const std::string& s = "") {
|
2010-01-10 14:35:16 +08:00
|
|
|
|
object.print(s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Call equal on the object */
|
|
|
|
|
template<class T>
|
|
|
|
|
inline bool equal(const T& obj1, const T& obj2, double tol) {
|
|
|
|
|
return obj1.equals(obj2, tol);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Call equal on the object without tolerance (use default tolerance) */
|
|
|
|
|
template<class T>
|
|
|
|
|
inline bool equal(const T& obj1, const T& obj2) {
|
2010-01-11 06:41:23 +08:00
|
|
|
|
return obj1.equals(obj2);
|
2010-01-10 14:35:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
2010-01-14 13:58:58 +08:00
|
|
|
|
// The rest of the file makes double and Vector behave as a Lie type (with + as compose)
|
|
|
|
|
|
|
|
|
|
// double,+ group operations
|
|
|
|
|
inline double compose(double p1,double p2) { return p1+p2;}
|
|
|
|
|
inline double inverse(double p) { return -p;}
|
|
|
|
|
inline double between(double p1,double p2) { return p2-p1;}
|
|
|
|
|
|
|
|
|
|
// double,+ is a trivial Lie group
|
|
|
|
|
template<> inline double expmap(const Vector& d) { return d(0);}
|
|
|
|
|
template<> inline double expmap(const double& p,const Vector& d) { return p+d(0);}
|
|
|
|
|
inline Vector logmap(const double& p) { return repeat(1,p);}
|
|
|
|
|
inline Vector logmap(const double& p1,const double& p2) { return Vector_(1,p2-p1);}
|
|
|
|
|
|
|
|
|
|
// Global functions needed for double
|
|
|
|
|
inline size_t dim(const double& v) { return 1; }
|
|
|
|
|
|
|
|
|
|
// Vector group operations
|
2010-01-10 20:22:59 +08:00
|
|
|
|
inline Vector compose(const Vector& p1,const Vector& p2) { return p1+p2;}
|
|
|
|
|
inline Vector inverse(const Vector& p) { return -p;}
|
|
|
|
|
inline Vector between(const Vector& p1,const Vector& p2) { return p2-p1;}
|
|
|
|
|
|
2010-01-14 13:58:58 +08:00
|
|
|
|
// Vector is a trivial Lie group
|
2010-01-10 20:22:59 +08:00
|
|
|
|
template<> inline Vector expmap(const Vector& d) { return d;}
|
|
|
|
|
template<> inline Vector expmap(const Vector& p,const Vector& d) { return p+d;}
|
|
|
|
|
inline Vector logmap(const Vector& p) { return p;}
|
|
|
|
|
inline Vector logmap(const Vector& p1,const Vector& p2) { return p2-p1;}
|
|
|
|
|
|
2010-02-27 22:58:54 +08:00
|
|
|
|
/**
|
|
|
|
|
* Three term approximation of the Baker<EFBFBD>Campbell<EFBFBD>Hausdorff formula
|
|
|
|
|
* In non-commutative Lie groups, when composing exp(Z) = exp(X)exp(Y)
|
|
|
|
|
* it is not true that Z = X+Y. Instead, Z can be calculated using the BCH
|
|
|
|
|
* formula: Z = X + Y + [X,Y]/2 + [X-Y,[X,Y]]/12 - [Y,[X,[X,Y]]]/24
|
|
|
|
|
* http://en.wikipedia.org/wiki/Baker<65>Campbell<6C>Hausdorff_formula
|
|
|
|
|
*/
|
|
|
|
|
template<class T>
|
|
|
|
|
T BCH(const T& X, const T& Y) {
|
|
|
|
|
static const double _2 = 1. / 2., _12 = 1. / 12., _24 = 1. / 24.;
|
|
|
|
|
T X_Y = bracket(X, Y);
|
|
|
|
|
return X + Y + _2 * X_Y + _12 * bracket(X - Y, X_Y) - _24 * bracket(Y,
|
|
|
|
|
bracket(X, X_Y));
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-02 10:25:27 +08:00
|
|
|
|
/**
|
|
|
|
|
* Declaration of wedge (see Murray94book) used to convert
|
|
|
|
|
* from n exponential coordinates to n*n element of the Lie algebra
|
|
|
|
|
*/
|
|
|
|
|
template <class T> Matrix wedge(const Vector& x);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Exponential map given exponential coordinates
|
|
|
|
|
* class T needs a wedge<> function and a constructor from Matrix
|
|
|
|
|
* @param x exponential coordinates, vector of size n
|
|
|
|
|
* @ return a T
|
|
|
|
|
*/
|
|
|
|
|
template <class T>
|
|
|
|
|
T expm(const Vector& x, int K=7) {
|
|
|
|
|
Matrix xhat = wedge<T>(x);
|
|
|
|
|
return expm(xhat,K);
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-14 13:58:58 +08:00
|
|
|
|
} // namespace gtsam
|