math_tools.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. #ifndef MATH_H
  2. #define MATH_H
  3. #include <cmath>
  4. #include <eigen3/Eigen/Dense>
  5. // Sign function
  6. template <typename T>
  7. T sgnFunc(T val)
  8. {
  9. return (T(0) < val) - (val < T(0));
  10. }
  11. // Hat (skew) operator
  12. template <typename T>
  13. inline Eigen::Matrix<T, 3, 3> hat(const Eigen::Matrix<T, 3, 1> &vec)
  14. {
  15. Eigen::Matrix<T, 3, 3> mat;
  16. mat << 0, -vec(2), vec(1),
  17. vec(2), 0, -vec(0),
  18. -vec(1), vec(0), 0;
  19. return mat;
  20. }
  21. template <typename Derived>
  22. static Eigen::Matrix<typename Derived::Scalar, 3, 3> skewSymmetric(const Eigen::MatrixBase<Derived> &q)
  23. {
  24. Eigen::Matrix<typename Derived::Scalar, 3, 3> ans;
  25. ans << typename Derived::Scalar(0), -q(2), q(1),
  26. q(2), typename Derived::Scalar(0), -q(0),
  27. -q(1), q(0), typename Derived::Scalar(0);
  28. return ans;
  29. }
  30. template <typename Derived>
  31. static Eigen::Matrix<typename Derived::Scalar, 4, 4> Qleft(const Eigen::QuaternionBase<Derived> &q)
  32. {
  33. Eigen::Matrix<typename Derived::Scalar, 4, 4> ans;
  34. ans(0, 0) = q.w(), ans.template block<1, 3>(0, 1) = -q.vec().transpose();
  35. ans.template block<3, 1>(1, 0) = q.vec(), ans.template block<3, 3>(1, 1) = q.w() * Eigen::Matrix<typename Derived::Scalar, 3, 3>::Identity() + skewSymmetric(q.vec());
  36. return ans;
  37. }
  38. template <typename Derived>
  39. static Eigen::Matrix<typename Derived::Scalar, 4, 4> Qright(const Eigen::QuaternionBase<Derived> &p)
  40. {
  41. Eigen::Matrix<typename Derived::Scalar, 4, 4> ans;
  42. ans(0, 0) = p.w(), ans.template block<1, 3>(0, 1) = -p.vec().transpose();
  43. ans.template block<3, 1>(1, 0) = p.vec(), ans.template block<3, 3>(1, 1) = p.w() * Eigen::Matrix<typename Derived::Scalar, 3, 3>::Identity() - skewSymmetric(p.vec());
  44. return ans;
  45. }
  46. // Convert from quaternion to rotation vector
  47. template <typename T>
  48. inline Eigen::Matrix<T, 3, 1> quaternionToRotationVector(const Eigen::Quaternion<T> &qua)
  49. {
  50. Eigen::Matrix<T, 3, 3> mat = qua.toRotationMatrix();
  51. Eigen::Matrix<T, 3, 1> rotation_vec;
  52. Eigen::AngleAxis<T> angle_axis;
  53. angle_axis.fromRotationMatrix(mat);
  54. rotation_vec = angle_axis.angle() * angle_axis.axis();
  55. return rotation_vec;
  56. }
  57. // Right Jacobian matrix
  58. template <typename T>
  59. inline Eigen::Matrix3d Jright(const Eigen::Quaternion<T> &qua)
  60. {
  61. Eigen::Matrix<T, 3, 3> mat;
  62. Eigen::Matrix<T, 3, 1> rotation_vec = quaternionToRotationVector(qua);
  63. double theta_norm = rotation_vec.norm();
  64. mat = Eigen::Matrix<T, 3, 3>::Identity()
  65. - (1 - cos(theta_norm)) / (theta_norm * theta_norm + 1e-10) * hat(rotation_vec)
  66. + (theta_norm - sin(theta_norm)) / (theta_norm * theta_norm * theta_norm + 1e-10) * hat(rotation_vec) * hat(rotation_vec);
  67. return mat;
  68. }
  69. // Calculate the Jacobian with respect to the quaternion
  70. template <typename T>
  71. inline Eigen::Matrix<T, 3, 4> quaternionJacobian(const Eigen::Quaternion<T> &qua, const Eigen::Matrix<T, 3, 1> &vec)
  72. {
  73. Eigen::Matrix<T, 3, 4> mat;
  74. Eigen::Matrix<T, 3, 1> quaternion_imaginary(qua.x(), qua.y(), qua.z());
  75. mat.template block<3, 1>(0, 0) = qua.w() * vec + quaternion_imaginary.cross(vec);
  76. mat.template block<3, 3>(0, 1) = quaternion_imaginary.dot(vec) * Eigen::Matrix<T, 3, 3>::Identity()
  77. + quaternion_imaginary * vec.transpose()
  78. - vec * quaternion_imaginary.transpose()
  79. - qua.w() * hat(vec);
  80. return T(2) * mat;
  81. }
  82. // Calculate the Jacobian with respect to the inverse quaternion
  83. template <typename T>
  84. inline Eigen::Matrix<T, 3, 4> quaternionInvJacobian(const Eigen::Quaternion<T> &qua, const Eigen::Matrix<T, 3, 1> &vec)
  85. {
  86. Eigen::Matrix<T, 3, 4> mat;
  87. Eigen::Matrix<T, 3, 1> quaternion_imaginary(qua.x(), qua.y(), qua.z());
  88. mat.template block<3, 1>(0, 0) = qua.w() * vec + vec.cross(quaternion_imaginary);
  89. mat.template block<3, 3>(0, 1) = quaternion_imaginary.dot(vec) * Eigen::Matrix<T, 3, 3>::Identity()
  90. + quaternion_imaginary * vec.transpose()
  91. - vec * quaternion_imaginary.transpose()
  92. + qua.w() * hat(vec);
  93. return T(2) * mat;
  94. }
  95. // Calculate the Jacobian rotation vector to quaternion
  96. template <typename T>
  97. inline Eigen::Matrix<T, 3, 4> JacobianV2Q(const Eigen::Quaternion<T> &qua)
  98. {
  99. Eigen::Matrix<T, 3, 4> mat;
  100. T c = 1 / (1 - qua.w() * qua.w());
  101. T d = acos(qua.w()) / sqrt(1 - qua.w() * qua.w());
  102. mat.template block<3, 1>(0, 0) = Eigen::Matrix<T, 3, 1>(c * qua.x() * (d * qua.x() - 1),
  103. c * qua.y() * (d * qua.x() - 1),
  104. c * qua.z() * (d * qua.x() - 1));
  105. mat.template block<3, 3>(0, 1) = d * Eigen::Matrix<T, 3, 4>::Identity();
  106. return T(2) * mat;
  107. }
  108. //get quaternion from rotation vector
  109. template <typename Derived>
  110. Eigen::Quaternion<typename Derived::Scalar> deltaQ(const Eigen::MatrixBase<Derived> &theta)
  111. {
  112. typedef typename Derived::Scalar Scalar_t;
  113. Eigen::Quaternion<Scalar_t> dq;
  114. Eigen::Matrix<Scalar_t, 3, 1> half_theta = theta;
  115. half_theta /= static_cast<Scalar_t>(2.0);
  116. dq.w() = static_cast<Scalar_t>(1.0);
  117. dq.x() = half_theta.x();
  118. dq.y() = half_theta.y();
  119. dq.z() = half_theta.z();
  120. return dq;
  121. }
  122. template<typename Derived>
  123. inline Eigen::Matrix<typename Derived::Scalar, 4, 4> LeftQuatMatrix(const Eigen::QuaternionBase<Derived> &q) {
  124. Eigen::Matrix<typename Derived::Scalar, 4, 4> m;
  125. Eigen::Matrix<typename Derived::Scalar, 3, 1> vq = q.vec();
  126. typename Derived::Scalar q4 = q.w();
  127. m.block(0, 0, 3, 3) << q4 * Eigen::Matrix3d::Identity() + skewSymmetric(vq);
  128. m.block(3, 0, 1, 3) << -vq.transpose();
  129. m.block(0, 3, 3, 1) << vq;
  130. m(3, 3) = q4;
  131. return m;
  132. }
  133. template<typename Derived>
  134. inline Eigen::Matrix<typename Derived::Scalar, 4, 4> RightQuatMatrix(const Eigen::QuaternionBase<Derived> &p) {
  135. Eigen::Matrix<typename Derived::Scalar, 4, 4> m;
  136. Eigen::Matrix<typename Derived::Scalar, 3, 1> vp = p.vec();
  137. typename Derived::Scalar p4 = p.w();
  138. m.block(0, 0, 3, 3) << p4 * Eigen::Matrix3d::Identity() - skewSymmetric(vp);
  139. m.block(3, 0, 1, 3) << -vp.transpose();
  140. m.block(0, 3, 3, 1) << vp;
  141. m(3, 3) = p4;
  142. return m;
  143. }
  144. template <typename T>
  145. Eigen::Quaternion<T> unifyQuaternion(const Eigen::Quaternion<T> &q)
  146. {
  147. if(q.w() >= 0) return q;
  148. else {
  149. Eigen::Quaternion<T> resultQ(-q.w(), -q.x(), -q.y(), -q.z());
  150. return resultQ;
  151. }
  152. }
  153. #endif // MATH_UTILS_H