geometry.hpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /// @file
  2. /// Transformations between poses and hyperplanes.
  3. #ifndef GEOMETRY_HPP
  4. #define GEOMETRY_HPP
  5. #include "se2.hpp"
  6. #include "se3.hpp"
  7. #include "so2.hpp"
  8. #include "so3.hpp"
  9. #include "types.hpp"
  10. namespace Sophus {
  11. /// Takes in a rotation ``R_foo_plane`` and returns the corresponding line
  12. /// normal along the y-axis (in reference frame ``foo``).
  13. ///
  14. template <class T>
  15. Vector2<T> normalFromSO2(SO2<T> const& R_foo_line) {
  16. return R_foo_line.matrix().col(1);
  17. }
  18. /// Takes in line normal in reference frame foo and constructs a corresponding
  19. /// rotation matrix ``R_foo_line``.
  20. ///
  21. /// Precondition: ``normal_foo`` must not be close to zero.
  22. ///
  23. template <class T>
  24. SO2<T> SO2FromNormal(Vector2<T> normal_foo) {
  25. SOPHUS_ENSURE(normal_foo.squaredNorm() > Constants<T>::epsilon(), "%",
  26. normal_foo.transpose());
  27. normal_foo.normalize();
  28. return SO2<T>(normal_foo.y(), -normal_foo.x());
  29. }
  30. /// Takes in a rotation ``R_foo_plane`` and returns the corresponding plane
  31. /// normal along the z-axis
  32. /// (in reference frame ``foo``).
  33. ///
  34. template <class T>
  35. Vector3<T> normalFromSO3(SO3<T> const& R_foo_plane) {
  36. return R_foo_plane.matrix().col(2);
  37. }
  38. /// Takes in plane normal in reference frame foo and constructs a corresponding
  39. /// rotation matrix ``R_foo_plane``.
  40. ///
  41. /// Note: The ``plane`` frame is defined as such that the normal points along
  42. /// the positive z-axis. One can specify hints for the x-axis and y-axis
  43. /// of the ``plane`` frame.
  44. ///
  45. /// Preconditions:
  46. /// - ``normal_foo``, ``xDirHint_foo``, ``yDirHint_foo`` must not be close to
  47. /// zero.
  48. /// - ``xDirHint_foo`` and ``yDirHint_foo`` must be approx. perpendicular.
  49. ///
  50. template <class T>
  51. Matrix3<T> rotationFromNormal(Vector3<T> const& normal_foo,
  52. Vector3<T> xDirHint_foo = Vector3<T>(T(1), T(0),
  53. T(0)),
  54. Vector3<T> yDirHint_foo = Vector3<T>(T(0), T(1),
  55. T(0))) {
  56. SOPHUS_ENSURE(xDirHint_foo.dot(yDirHint_foo) < Constants<T>::epsilon(),
  57. "xDirHint (%) and yDirHint (%) must be perpendicular.",
  58. xDirHint_foo.transpose(), yDirHint_foo.transpose());
  59. using std::abs;
  60. using std::sqrt;
  61. T const xDirHint_foo_sqr_length = xDirHint_foo.squaredNorm();
  62. T const yDirHint_foo_sqr_length = yDirHint_foo.squaredNorm();
  63. T const normal_foo_sqr_length = normal_foo.squaredNorm();
  64. SOPHUS_ENSURE(xDirHint_foo_sqr_length > Constants<T>::epsilon(), "%",
  65. xDirHint_foo.transpose());
  66. SOPHUS_ENSURE(yDirHint_foo_sqr_length > Constants<T>::epsilon(), "%",
  67. yDirHint_foo.transpose());
  68. SOPHUS_ENSURE(normal_foo_sqr_length > Constants<T>::epsilon(), "%",
  69. normal_foo.transpose());
  70. Matrix3<T> basis_foo;
  71. basis_foo.col(2) = normal_foo;
  72. if (abs(xDirHint_foo_sqr_length - T(1)) > Constants<T>::epsilon()) {
  73. xDirHint_foo.normalize();
  74. }
  75. if (abs(yDirHint_foo_sqr_length - T(1)) > Constants<T>::epsilon()) {
  76. yDirHint_foo.normalize();
  77. }
  78. if (abs(normal_foo_sqr_length - T(1)) > Constants<T>::epsilon()) {
  79. basis_foo.col(2).normalize();
  80. }
  81. T abs_x_dot_z = abs(basis_foo.col(2).dot(xDirHint_foo));
  82. T abs_y_dot_z = abs(basis_foo.col(2).dot(yDirHint_foo));
  83. if (abs_x_dot_z < abs_y_dot_z) {
  84. // basis_foo.z and xDirHint are far from parallel.
  85. basis_foo.col(1) = basis_foo.col(2).cross(xDirHint_foo).normalized();
  86. basis_foo.col(0) = basis_foo.col(1).cross(basis_foo.col(2));
  87. } else {
  88. // basis_foo.z and yDirHint are far from parallel.
  89. basis_foo.col(0) = yDirHint_foo.cross(basis_foo.col(2)).normalized();
  90. basis_foo.col(1) = basis_foo.col(2).cross(basis_foo.col(0));
  91. }
  92. T det = basis_foo.determinant();
  93. // sanity check
  94. SOPHUS_ENSURE(abs(det - T(1)) < Constants<T>::epsilon(),
  95. "Determinant of basis is not 1, but %. Basis is \n%\n", det,
  96. basis_foo);
  97. return basis_foo;
  98. }
  99. /// Takes in plane normal in reference frame foo and constructs a corresponding
  100. /// rotation matrix ``R_foo_plane``.
  101. ///
  102. /// See ``rotationFromNormal`` for details.
  103. ///
  104. template <class T>
  105. SO3<T> SO3FromNormal(Vector3<T> const& normal_foo) {
  106. return SO3<T>(rotationFromNormal(normal_foo));
  107. }
  108. /// Returns a line (wrt. to frame ``foo``), given a pose of the ``line`` in
  109. /// reference frame ``foo``.
  110. ///
  111. /// Note: The plane is defined by X-axis of the ``line`` frame.
  112. ///
  113. template <class T>
  114. Line2<T> lineFromSE2(SE2<T> const& T_foo_line) {
  115. return Line2<T>(normalFromSO2(T_foo_line.so2()), T_foo_line.translation());
  116. }
  117. /// Returns the pose ``T_foo_line``, given a line in reference frame ``foo``.
  118. ///
  119. /// Note: The line is defined by X-axis of the frame ``line``.
  120. ///
  121. template <class T>
  122. SE2<T> SE2FromLine(Line2<T> const& line_foo) {
  123. T const d = line_foo.offset();
  124. Vector2<T> const n = line_foo.normal();
  125. SO2<T> const R_foo_plane = SO2FromNormal(n);
  126. return SE2<T>(R_foo_plane, -d * n);
  127. }
  128. /// Returns a plane (wrt. to frame ``foo``), given a pose of the ``plane`` in
  129. /// reference frame ``foo``.
  130. ///
  131. /// Note: The plane is defined by XY-plane of the frame ``plane``.
  132. ///
  133. template <class T>
  134. Plane3<T> planeFromSE3(SE3<T> const& T_foo_plane) {
  135. return Plane3<T>(normalFromSO3(T_foo_plane.so3()), T_foo_plane.translation());
  136. }
  137. /// Returns the pose ``T_foo_plane``, given a plane in reference frame ``foo``.
  138. ///
  139. /// Note: The plane is defined by XY-plane of the frame ``plane``.
  140. ///
  141. template <class T>
  142. SE3<T> SE3FromPlane(Plane3<T> const& plane_foo) {
  143. T const d = plane_foo.offset();
  144. Vector3<T> const n = plane_foo.normal();
  145. SO3<T> const R_foo_plane = SO3FromNormal(n);
  146. return SE3<T>(R_foo_plane, -d * n);
  147. }
  148. /// Takes in a hyperplane and returns unique representation by ensuring that the
  149. /// ``offset`` is not negative.
  150. ///
  151. template <class T, int N>
  152. Eigen::Hyperplane<T, N> makeHyperplaneUnique(
  153. Eigen::Hyperplane<T, N> const& plane) {
  154. if (plane.offset() >= 0) {
  155. return plane;
  156. }
  157. return Eigen::Hyperplane<T, N>(-plane.normal(), -plane.offset());
  158. }
  159. } // namespace Sophus
  160. #endif // GEOMETRY_HPP