OSVR-Core
MatrixExponentialMap.h
Go to the documentation of this file.
1 
11 // Copyright 2015 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_ExponentialMap_h_GUID_FB61635E_CF8A_4FAE_5343_2258F4BC1E60
26 #define INCLUDED_ExponentialMap_h_GUID_FB61635E_CF8A_4FAE_5343_2258F4BC1E60
27 
28 // Internal Includes
29 // - none
30 
31 // Library/third-party includes
33 
34 // Standard includes
35 // - none
36 
37 namespace osvr {
38 namespace kalman {
39 
46  template <typename Derived>
47  inline Eigen::Matrix3d
49  Eigen::Matrix3d ret;
50  // clang-format off
51  ret << 0, -v.z(), v.y(),
52  v.z(), 0, -v.x(),
53  -v.y(), v.x(), 0;
54  // clang-format on
55  return ret;
56  }
57 
75  namespace matrix_exponential_map {
80  template <typename T> inline void avoidSingularities(T &&omega) {
81  // if magnitude gets too close to 2pi, in this case, pi...
82  if (omega.squaredNorm() > M_PI * M_PI) {
83  // replace omega with an equivalent one.
84  omega = ((1 - (2 * M_PI) / omega.norm()) * omega).eval();
85  }
86  }
87 
90  template <typename Derived>
91  inline double getAngle(Eigen::MatrixBase<Derived> const &omega) {
92  return omega.norm();
93  }
94 
98  template <typename Derived>
99  inline Eigen::Quaterniond
101  auto theta = getAngle(omega);
102  auto xyz = omega * std::sin(theta / 2.);
103  return Eigen::Quaterniond(std::cos(theta / 2.), xyz.x(), xyz.y(),
104  xyz.z());
105  }
106 
109  public:
110  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
113  template <typename Derived>
115  : m_omega(omega) {}
116 
117  ExponentialMapData() : m_omega(Eigen::Vector3d::Zero()) {}
118 
121  if (&other != this) {
122  m_omega = other.m_omega;
123  m_gotTheta = other.m_gotTheta;
124  if (m_gotTheta) {
125  m_theta = other.m_theta;
126  }
127  m_gotBigOmega = other.m_gotBigOmega;
128  if (m_gotBigOmega) {
129  m_bigOmega = other.m_bigOmega;
130  }
131  m_gotR = other.m_gotR;
132  if (m_gotR) {
133  m_R = other.m_R;
134  }
135  m_gotQuat = other.m_gotQuat;
136  if (m_gotQuat) {
137  m_quat = other.m_quat;
138  }
139  }
140  return *this;
141  }
142 
145  if (&other != this) {
146  m_omega = std::move(other.m_omega);
147  m_gotTheta = std::move(other.m_gotTheta);
148  if (m_gotTheta) {
149  m_theta = std::move(other.m_theta);
150  }
151  m_gotBigOmega = std::move(other.m_gotBigOmega);
152  if (m_gotBigOmega) {
153  m_bigOmega = std::move(other.m_bigOmega);
154  }
155  m_gotR = std::move(other.m_gotR);
156  if (m_gotR) {
157  m_R = std::move(other.m_R);
158  }
159  m_gotQuat = std::move(other.m_gotQuat);
160  if (m_gotQuat) {
161  m_quat = std::move(other.m_quat);
162  }
163  }
164  return *this;
165  }
166 
167  template <typename Derived>
168  void reset(Eigen::MatrixBase<Derived> const &omega) {
170  *this = ExponentialMapData(omega);
171  }
172 
176  Eigen::Matrix3d const &getBigOmega() {
177  if (!m_gotBigOmega) {
178  m_gotBigOmega = true;
179  m_bigOmega = makeSkewSymmetrixCrossProductMatrix(m_omega);
180  }
181  return m_bigOmega;
182  }
183 
187  double getTheta() {
188  if (!m_gotTheta) {
189  m_gotTheta = true;
190  m_theta = getAngle(m_omega);
191  }
192  return m_theta;
193  }
194 
201  Eigen::Matrix3d const &getRotationMatrix() {
202  if (!m_gotR) {
203  m_gotR = true;
204  auto theta = getTheta();
205  auto &Omega = getBigOmega();
207  double k1 = 1. - theta * theta / 6.;
208 
210  double k2 = theta / 2. - theta * theta * theta / 24.;
211 
212  m_R = Eigen::Matrix3d::Identity() + k1 * Omega +
213  k2 * Omega * Omega;
214  }
215  return m_R;
216  }
217 
218  Eigen::Quaterniond const &getQuaternion() {
219  if (!m_gotQuat) {
220  m_gotQuat = true;
221  auto theta = getTheta();
222  auto xyz = m_omega * std::sin(theta / 2.);
223  m_quat = Eigen::Quaterniond(std::cos(theta / 2.), xyz.x(),
224  xyz.y(), xyz.z());
225  }
226  return m_quat;
227  }
228 
229  private:
230  Eigen::Vector3d m_omega;
231  bool m_gotTheta = false;
232  double m_theta;
233  bool m_gotBigOmega = false;
234  Eigen::Matrix3d m_bigOmega;
235  bool m_gotR = false;
236  Eigen::Matrix3d m_R;
237  bool m_gotQuat = false;
238  Eigen::Quaterniond m_quat;
239  };
240 
241  } // namespace exponential_map
242 } // namespace kalman
243 } // namespace osvr
244 #endif // INCLUDED_ExponentialMap_h_GUID_FB61635E_CF8A_4FAE_5343_2258F4BC1E60
double getAngle(Eigen::MatrixBase< Derived > const &omega)
Gets the rotation angle of a rotation vector.
Definition: MatrixExponentialMap.h:91
void avoidSingularities(T &&omega)
Adjust a matrix exponential map rotation vector, if required, to avoid singularities.
Definition: MatrixExponentialMap.h:80
The main namespace for all C++ elements of the framework, internal and external.
Definition: namespace_osvr.dox:3
Eigen::Matrix3d makeSkewSymmetrixCrossProductMatrix(Eigen::MatrixBase< Derived > const &v)
Produces the "hat matrix" that produces the same result as performing a cross-product with v...
Definition: MatrixExponentialMap.h:48
double getTheta()
Gets the rotation angle of a rotation vector.
Definition: MatrixExponentialMap.h:187
Header wrapping include of <Eigen/Core> and <Eigen/Geometry> for warning quieting.
Contained cached computed values.
Definition: MatrixExponentialMap.h:108
RealScalar norm() const
Definition: Dot.h:125
ExponentialMapData & operator=(ExponentialMapData const &other)
assignment operator - its presence is an optimization only.
Definition: MatrixExponentialMap.h:120
ExponentialMapData & operator=(ExponentialMapData &&other)
move-assignment operator - its presence is an optimization only.
Definition: MatrixExponentialMap.h:144
Eigen::Quaterniond getQuat(Eigen::MatrixBase< Derived > const &omega)
Gets the unit quaternion corresponding to the exponential rotation vector.
Definition: MatrixExponentialMap.h:100
Eigen::Matrix3d const & getRotationMatrix()
Converts a rotation vector to a rotation matrix: Uses Rodrigues&#39; formula, and the first two terms of ...
Definition: MatrixExponentialMap.h:201
Definition: Quaternion.h:47
Quaternion< double > Quaterniond
double precision quaternion type
Definition: Quaternion.h:211
void reset(Eigen::MatrixBase< Derived > const &omega)
Definition: MatrixExponentialMap.h:168
Eigen::Matrix3d const & getBigOmega()
Gets the "capital omega" skew-symmetrix matrix.
Definition: MatrixExponentialMap.h:176
EIGEN_MAKE_ALIGNED_OPERATOR_NEW ExponentialMapData(Eigen::MatrixBase< Derived > const &omega)
Construct from a matrixy-thing: should be a 3d vector containing a matrix-exponential-map rotation fo...
Definition: MatrixExponentialMap.h:114
Base class for all dense matrices, vectors, and expressions.
Definition: MatrixBase.h:48