35 typedef QUATERNION_TYPE ManifoldType;
36 typedef QUATERNION_TYPE Q;
50 inline constexpr static auto dimension = 3;
51 static int GetDimension(
const Q& ) {
return 3; }
53 typedef Eigen::Matrix<_Scalar, 3, 1, _Options, 3, 1> TangentVector;
58 static Q Compose(
const Q &g,
const Q & h,
59 ChartJacobian Hg = {}, ChartJacobian Hh = {}) {
60 if (Hg) *Hg = h.toRotationMatrix().transpose();
65 static Q Between(
const Q &g,
const Q & h,
66 ChartJacobian Hg = {}, ChartJacobian Hh = {}) {
67 Q d = g.inverse() * h;
68 if (Hg) *Hg = -d.toRotationMatrix().transpose();
73 static Q Inverse(
const Q &g,
74 ChartJacobian H = {}) {
75 if (H) *H = -g.toRotationMatrix();
80 static Q
Expmap(
const Eigen::Ref<const TangentVector>& omega,
81 ChartJacobian H = {}) {
85 _Scalar theta2 = omega.dot(omega);
86 if (theta2 > std::numeric_limits<_Scalar>::epsilon()) {
87 _Scalar theta = std::sqrt(theta2);
88 _Scalar ha = _Scalar(0.5) * theta;
89 Vector3 vec = (sin(ha) / theta) * omega;
90 return Q(cos(ha), vec.x(), vec.y(), vec.z());
93 Vector3 vec = _Scalar(0.5) * omega;
94 return Q(1.0, vec.x(), vec.y(), vec.z());
99 static TangentVector
Logmap(
const Q& q, ChartJacobian H = {}) {
113 const _Scalar qw = q.w();
114 const _Scalar n = q.vec().norm();
117 if (n == _Scalar(0)) {
118 omega = TangentVector::Zero();
123 const bool negate = !(qw > _Scalar(0));
124 const _Scalar w = negate ? -qw : qw;
125 const _Scalar theta = (w > n) ? _Scalar(2) * atan(n / w)
126 : _Scalar(M_PI) - _Scalar(2) * atan(w / n);
127 omega = (negate ? -theta / n : theta / n) * q.vec();
136 static Matrix3 AdjointMap(
const Q &g) {
137 return g.toRotationMatrix();
140 using LieAlgebra = Matrix3;
142 static Matrix3 Hat(
const Vector3& v) {
146 static Vector3 Vee(
const Matrix3& X) {
150 static Vector9 Vec(
const Q& q, OptionalJacobian<9, 3> H = {}) {
151 return SO3(q.toRotationMatrix()).SO3::vec(H);
158 static TangentVector Local(
const Q& g,
const Q& h,
159 ChartJacobian H1 = {}, ChartJacobian H2 = {}) {
160 Q b = Between(g, h, H1, H2);
162 TangentVector v =
Logmap(b, (H1 || H2) ? &D_v_b : 0);
163 if (H1) *H1 = D_v_b * (*H1);
164 if (H2) *H2 = D_v_b * (*H2);
168 static Q Retract(
const Q& g,
const TangentVector& v,
169 ChartJacobian H1 = {}, ChartJacobian H2 = {}) {
171 Q b = Expmap(v,H2 ? &D_h_v : 0);
172 Q h = Compose(g, b, H1, H2);
173 if (H2) *H2 = (*H2) * D_h_v;
180 static void Print(
const Q& q,
const std::string& str =
"") {
182 std::cout <<
"Eigen::Quaternion: ";
184 std::cout << str <<
" ";
185 std::cout << q.vec().transpose() << std::endl;
187 static bool Equals(
const Q& q1,
const Q& q2,
double tol = 1e-8) {
188 return Between(q1, q2).vec().array().abs().maxCoeff() < tol;
static TangentVector Logmap(const Q &q, ChartJacobian H={})
We use our own Logmap, as there is a slight bug in Eigen.
Definition Quaternion.h:99
static Q Expmap(const Eigen::Ref< const TangentVector > &omega, ChartJacobian H={})
Exponential map, using the inlined code from Eigen's conversion from axis/angle.
Definition Quaternion.h:80