OSVR-Core
EigenQuatExponentialMap.h
Go to the documentation of this file.
1 
11 // Copyright 2016 Sensics, Inc.
12 //
13 // Licensed under the Apache License, Version 2.0 (the "License");
14 // you may not use this file except in compliance with the License.
15 // You may obtain a copy of the License at
16 //
17 // http://www.apache.org/licenses/LICENSE-2.0
18 //
19 // Unless required by applicable law or agreed to in writing, software
20 // distributed under the License is distributed on an "AS IS" BASIS,
21 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 // See the License for the specific language governing permissions and
23 // limitations under the License.
24 
25 #ifndef INCLUDED_EigenQuatExponentialMap_h_GUID_7E15BC44_BCFB_438B_902B_BA0787BEE405
26 #define INCLUDED_EigenQuatExponentialMap_h_GUID_7E15BC44_BCFB_438B_902B_BA0787BEE405
27 
28 // Internal Includes
30 
31 // Library/third-party includes
32 // - none
33 
34 // Standard includes
35 // - none
36 
37 namespace osvr {
38 namespace util {
39  namespace ei_quat_exp_map {
40 
41  template <typename Scalar> struct FourthRootMachineEps;
42  template <> struct FourthRootMachineEps<double> {
44  static double get() { return 1.e-13; }
45  };
46  template <> struct FourthRootMachineEps<float> {
48  static float get() { return 1.e-6f; }
49  };
53  template <typename Scalar> inline Scalar sinc(Scalar theta) {
59  Scalar ret;
60  if (theta < FourthRootMachineEps<Scalar>::get()) {
61  // taylor series expansion.
62  ret = Scalar(1.f) - theta * theta / Scalar(6.f);
63  return ret;
64  }
65  // direct computation.
66  ret = std::sin(theta) / theta;
67  return ret;
68  }
69 
71  template <typename Derived>
74  EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Derived, 3);
75  using Scalar = typename Derived::Scalar;
86  Scalar theta = vec.norm();
87  Scalar vecscale = sinc(theta);
89  ret.vec() = vecscale * vec;
90  ret.w() = std::cos(theta);
91  return ret.normalized();
92  }
93 
96  template <typename Scalar>
97  inline Scalar cscTaylorExpansion(Scalar theta) {
98  return Scalar(1) +
99  // theta ^ 2 / 6
100  (theta * theta) / Scalar(6) +
101  // 7 theta^4 / 360
102  (Scalar(7) * theta * theta * theta * theta) / Scalar(360) +
103  // 31 theta^6/15120
104  (Scalar(31) * theta * theta * theta * theta * theta *
105  theta) /
106  Scalar(15120);
107  }
108 
115  template <typename Scalar>
118  // ln q = ( (phi)/(norm of vec) vec, ln(norm of quat))
119  // When we assume a unit quaternion, ln(norm of quat) = 0
120  // so then we just scale the vector part by phi/sin(phi) to get the
121  // result (i.e., ln(qv, qw) = (phi/sin(phi)) * qv )
122  Scalar vecnorm = quat.vec().norm();
123 
124  // "best for numerical stability" vs asin or acos
125  Scalar phi = std::atan2(vecnorm, quat.w());
126 
127  // Here is where we compute the coefficient to scale the vector part
128  // by, which is nominally phi / std::sin(phi).
129  // When the angle approaches zero, we compute the coefficient
130  // differently, since it gets a bit like sinc in that we want it
131  // continuous but 0 is undefined.
132  Scalar phiOverSin =
133  vecnorm < 1e-4 ? cscTaylorExpansion<Scalar>(phi)
134  : (phi / std::sin(phi));
135  return quat.vec() * phiOverSin;
136  }
137 
138  template <typename Derived> struct ScalarTrait;
139 
140  template <typename Derived>
141  using ScalarType = typename ScalarTrait<Derived>::type;
142 
143  template <typename Derived>
145 
146  template <typename Derived>
148 
150  template <typename Derived_> class QuatExpMapBase {
151  public:
152  using Derived = Derived_;
153  QuatType<Derived> exp() const { return quat_exp(derived().vec()); }
154 
155  Derived const &derived() const {
156  return *static_cast<Derived const *>(this);
157  }
158 
161  VecType<Derived> myVec = derived().vec();
162  static const double eps = 1.e-2;
163  ScalarType<Derived> vecNorm = myVec.norm();
164  if (vecNorm > M_PI - eps) {
165  // Too close to the sphere of 2pi - replace with the
166  // equivalent rotation.
167  myVec *= ((1. - 2. * M_PI) / vecNorm);
168  }
169  return myVec;
170  }
171  };
172  // forward declaration
173  template <typename Scalar_> class VecWrapper;
174  // traits declaration
175  template <typename Scalar_> struct ScalarTrait<VecWrapper<Scalar_>> {
176  using type = Scalar_;
177  };
178 
179  template <typename Scalar_>
180  class VecWrapper : public QuatExpMapBase<VecWrapper<Scalar_>> {
181  public:
182  using Scalar = Scalar_;
184  explicit VecWrapper(VecType const &vec) : m_vec(vec) {}
185 
186  VecType const &vec() const { return m_vec; }
187 
188  static const bool AlwaysPureVec = true;
189  static bool pureVec() { return true; }
190 
191  private:
192  VecType const &m_vec;
193  };
194 
195  // forward declaration
196  template <typename Scalar_> class QuatWrapper;
197  template <typename Scalar_> struct ScalarTrait<QuatWrapper<Scalar_>> {
198  using type = Scalar_;
199  };
200 
203  template <typename Scalar_>
204  class QuatWrapper : public QuatExpMapBase<QuatWrapper<Scalar_>> {
205  public:
206  using Scalar = Scalar_; // typename ScalarType<Derived>::type;
208  using LogVectorType = Eigen::Matrix<Scalar, 3, 1>;
209  using QuatCoefficients = typename QuatType::Coefficients;
211 
212  explicit QuatWrapper(QuatType const &quat) : m_quat(quat) {}
213 
216  LogVectorType ln() const { return quat_ln<Scalar>(m_quat); }
217 
220  VecBlock vec() const { return m_quat.vec(); }
221 
222  static const bool AlwaysPureVec = false;
223  bool pureVec() const {
225  return m_quat.w() == 0;
226  }
227 
228  private:
229  QuatType const &m_quat;
230  };
231 
232  template <typename Scalar>
233  inline QuatWrapper<Scalar>
234  quat_exp_map(Eigen::Quaternion<Scalar> const &q) {
235  return QuatWrapper<Scalar>(q);
236  }
237 
238  template <typename Scalar>
239  inline VecWrapper<Scalar>
240  quat_exp_map(Eigen::Matrix<Scalar, 3, 1> const &v) {
241  return VecWrapper<Scalar>(v);
242  }
243  } // namespace ei_quat_exp_map
244  using ei_quat_exp_map::quat_exp;
245  using ei_quat_exp_map::quat_ln;
246  using ei_quat_exp_map::quat_exp_map;
247 } // namespace util
248 } // namespace osvr
249 
250 #endif // INCLUDED_EigenQuatExponentialMap_h_GUID_7E15BC44_BCFB_438B_902B_BA0787BEE405
Matrix< Scalar, 4, 1 > Coefficients
the type of the Coefficients 4-vector
Definition: Quaternion.h:60
Definition: EigenQuatExponentialMap.h:138
Definition: RunLoopManager.h:42
Definition: EigenQuatExponentialMap.h:173
The main namespace for all C++ elements of the framework, internal and external.
Definition: namespace_osvr.dox:3
Definition: EigenQuatExponentialMap.h:41
Scalar sinc(Scalar theta)
Computes the "historical" (un-normalized) sinc(Theta) (sine(theta)/theta for theta != 0...
Definition: EigenQuatExponentialMap.h:53
VecType< Derived > avoidSingularities() const
Definition: EigenQuatExponentialMap.h:159
Header wrapping include of <Eigen/Core> and <Eigen/Geometry> for warning quieting.
const Block< const Coefficients, 3, 1 > vec() const
Definition: Quaternion.h:87
RealScalar norm() const
Definition: Dot.h:125
Expression of a fixed-size or dynamic-size sub-vector.
Definition: ForwardDeclarations.h:83
LogVectorType ln() const
Gets the log of the quat, in the exponential-map sense, as a 3d vector.
Definition: EigenQuatExponentialMap.h:216
VecBlock vec() const
Access to just the vector part, in case we&#39;re actually trying to exponentiate here.
Definition: EigenQuatExponentialMap.h:220
Scalar w() const
Definition: Quaternion.h:75
Eigen::Quaternion< typename Derived::Scalar > quat_exp(Eigen::MatrixBase< Derived > const &vec)
fully-templated free function for quaternion expontiation
Definition: EigenQuatExponentialMap.h:73
bool pureVec() const
Definition: EigenQuatExponentialMap.h:223
Definition: Quaternion.h:47
CRTP base for quaternion exponential map.
Definition: EigenQuatExponentialMap.h:150
Wrapper class for a quaternion to provide access to ln() in its exponential-map meaning.
Definition: EigenQuatExponentialMap.h:196
Quaternion normalized() const
Definition: Quaternion.h:154
Base class for all dense matrices, vectors, and expressions.
Definition: MatrixBase.h:48
Eigen::Matrix< Scalar, 3, 1 > quat_ln(Eigen::Quaternion< Scalar > const &quat)
fully-templated free function for quaternion log map, intended for implementation use within the clas...
Definition: EigenQuatExponentialMap.h:117
Scalar cscTaylorExpansion(Scalar theta)
Taylor series expansion of theta over sin(theta), aka cosecant, for use near 0 when you want continui...
Definition: EigenQuatExponentialMap.h:97
double Scalar
Common scalar type.
Definition: FlexibleKalmanBase.h:48