21 #include <gtsam/base/concepts.h> 25 #define QUATERNION_TYPE Eigen::Quaternion<_Scalar,_Options> 30 template<
typename _Scalar,
int _Options>
32 typedef QUATERNION_TYPE ManifoldType;
33 typedef QUATERNION_TYPE Q;
51 typedef Eigen::Matrix<_Scalar, 3, 1, _Options, 3, 1> TangentVector;
56 static Q Compose(
const Q &g,
const Q & h,
57 ChartJacobian Hg = boost::none, ChartJacobian Hh = boost::none) {
58 if (Hg) *Hg = h.toRotationMatrix().transpose();
63 static Q Between(
const Q &g,
const Q & h,
64 ChartJacobian Hg = boost::none, ChartJacobian Hh = boost::none) {
65 Q d = g.inverse() * h;
66 if (Hg) *Hg = -d.toRotationMatrix().transpose();
71 static Q Inverse(
const Q &g,
72 ChartJacobian H = boost::none) {
73 if (H) *H = -g.toRotationMatrix();
78 static Q
Expmap(
const Eigen::Ref<const TangentVector>& omega,
79 ChartJacobian H = boost::none) {
83 _Scalar theta2 = omega.dot(omega);
84 if (theta2 > std::numeric_limits<_Scalar>::epsilon()) {
85 _Scalar theta = std::sqrt(theta2);
86 _Scalar ha = _Scalar(0.5) * theta;
87 Vector3 vec = (sin(ha) / theta) * omega;
88 return Q(cos(ha), vec.x(), vec.y(), vec.z());
91 Vector3 vec = _Scalar(0.5) * omega;
92 return Q(1.0, vec.x(), vec.y(), vec.z());
97 static TangentVector
Logmap(
const Q& q, ChartJacobian H = boost::none) {
102 static const double twoPi = 2.0 * M_PI, NearlyOne = 1.0 - 1e-10,
103 NearlyNegativeOne = -1.0 + 1e-10;
107 const _Scalar qw = q.w();
109 if (qw > NearlyOne) {
112 omega = ( 8. / 3. - 2. / 3. * qw) * q.vec();
113 }
else if (qw < NearlyNegativeOne) {
116 omega = (-8. / 3. - 2. / 3. * qw) * q.vec();
119 _Scalar angle = 2 * acos(qw), s = sqrt(1 - qw * qw);
123 else if (angle < -M_PI)
125 omega = (angle / s) * q.vec();
136 static TangentVector Local(
const Q& g,
const Q& h,
137 ChartJacobian H1 = boost::none, ChartJacobian H2 = boost::none) {
138 Q b = Between(g, h, H1, H2);
140 TangentVector v = Logmap(b, (H1 || H2) ? &D_v_b : 0);
141 if (H1) *H1 = D_v_b * (*H1);
142 if (H2) *H2 = D_v_b * (*H2);
146 static Q Retract(
const Q& g,
const TangentVector& v,
147 ChartJacobian H1 = boost::none, ChartJacobian H2 = boost::none) {
149 Q b = Expmap(v,H2 ? &D_h_v : 0);
150 Q h = Compose(g, b, H1, H2);
151 if (H2) *H2 = (*H2) * D_h_v;
158 static void Print(
const Q& q,
const std::string& str =
"") {
160 std::cout <<
"Eigen::Quaternion: ";
162 std::cout << str <<
" ";
163 std::cout << q.vec().transpose() << std::endl;
165 static bool Equals(
const Q& q1,
const Q& q2,
double tol = 1e-8) {
166 return Between(q1, q2).vec().array().abs().maxCoeff() < tol;
171 typedef Eigen::Quaternion<double, Eigen::DontAlign> Quaternion;
Base class and basic functions for Lie types.
static Matrix3 LogmapDerivative(const Vector3 &omega)
Derivative of Logmap.
Definition: SO3.cpp:176
OptionalJacobian is an Eigen::Ref like class that can take be constructed using either a fixed size o...
Definition: OptionalJacobian.h:39
3*3 matrix representation of SO(3)
Group operator syntax flavors.
Definition: Group.h:37
static TangentVector Logmap(const Q &q, ChartJacobian H=boost::none)
We use our own Logmap, as there is a slight bug in Eigen.
Definition: Quaternion.h:97
static Q Expmap(const Eigen::Ref< const TangentVector > &omega, ChartJacobian H=boost::none)
Exponential map, using the inlined code from Eigen's conversion from axis/angle.
Definition: Quaternion.h:78
tag to assert a type is a Lie group
Definition: Lie.h:167
A manifold defines a space in which there is a notion of a linear tangent space that can be centered ...
Definition: concepts.h:30
static Matrix3 ExpmapDerivative(const Vector3 &omega)
Derivative of Expmap.
Definition: SO3.cpp:128
Global functions in a separate testing namespace.
Definition: chartTesting.h:28