rotation_matrix.hpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. /// @file
  2. /// Rotation matrix helper functions.
  3. #ifndef SOPHUS_ROTATION_MATRIX_HPP
  4. #define SOPHUS_ROTATION_MATRIX_HPP
  5. #include <Eigen/Dense>
  6. #include <Eigen/SVD>
  7. #include "types.hpp"
  8. namespace Sophus {
  9. /// Takes in arbitrary square matrix and returns true if it is
  10. /// orthogonal.
  11. template <class D>
  12. SOPHUS_FUNC bool isOrthogonal(Eigen::MatrixBase<D> const& R) {
  13. using Scalar = typename D::Scalar;
  14. static int const N = D::RowsAtCompileTime;
  15. static int const M = D::ColsAtCompileTime;
  16. static_assert(N == M, "must be a square matrix");
  17. static_assert(N >= 2, "must have compile time dimension >= 2");
  18. return (R * R.transpose() - Matrix<Scalar, N, N>::Identity()).norm() <
  19. Constants<Scalar>::epsilon();
  20. }
  21. /// Takes in arbitrary square matrix and returns true if it is
  22. /// "scaled-orthogonal" with positive determinant.
  23. ///
  24. template <class D>
  25. SOPHUS_FUNC bool isScaledOrthogonalAndPositive(Eigen::MatrixBase<D> const& sR) {
  26. using Scalar = typename D::Scalar;
  27. static int const N = D::RowsAtCompileTime;
  28. static int const M = D::ColsAtCompileTime;
  29. using std::pow;
  30. using std::sqrt;
  31. Scalar det = sR.determinant();
  32. if (det <= Scalar(0)) {
  33. return false;
  34. }
  35. Scalar scale_sqr = pow(det, Scalar(2. / N));
  36. static_assert(N == M, "must be a square matrix");
  37. static_assert(N >= 2, "must have compile time dimension >= 2");
  38. return (sR * sR.transpose() - scale_sqr * Matrix<Scalar, N, N>::Identity())
  39. .template lpNorm<Eigen::Infinity>() <
  40. sqrt(Constants<Scalar>::epsilon());
  41. }
  42. /// Takes in arbitrary square matrix (2x2 or larger) and returns closest
  43. /// orthogonal matrix with positive determinant.
  44. template <class D>
  45. SOPHUS_FUNC enable_if_t<
  46. std::is_floating_point<typename D::Scalar>::value,
  47. Matrix<typename D::Scalar, D::RowsAtCompileTime, D::RowsAtCompileTime>>
  48. makeRotationMatrix(Eigen::MatrixBase<D> const& R) {
  49. using Scalar = typename D::Scalar;
  50. static int const N = D::RowsAtCompileTime;
  51. static int const M = D::ColsAtCompileTime;
  52. static_assert(N == M, "must be a square matrix");
  53. static_assert(N >= 2, "must have compile time dimension >= 2");
  54. Eigen::JacobiSVD<Matrix<Scalar, N, N>> svd(
  55. R, Eigen::ComputeFullU | Eigen::ComputeFullV);
  56. // Determine determinant of orthogonal matrix U*V'.
  57. Scalar d = (svd.matrixU() * svd.matrixV().transpose()).determinant();
  58. // Starting from the identity matrix D, set the last entry to d (+1 or
  59. // -1), so that det(U*D*V') = 1.
  60. Matrix<Scalar, N, N> Diag = Matrix<Scalar, N, N>::Identity();
  61. Diag(N - 1, N - 1) = d;
  62. return svd.matrixU() * Diag * svd.matrixV().transpose();
  63. }
  64. } // namespace Sophus
  65. #endif // SOPHUS_ROTATION_MATRIX_HPP