rotationConverters.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. // This file is part of OpenCV project.
  2. // It is subject to the license terms in the LICENSE file found in the top-level directory
  3. // of this distribution and at http://opencv.org/license.html.
  4. #include "rotationConverters.hpp"
  5. #include <cmath>
  6. #include <opencv2/calib3d.hpp>
  7. #include <opencv2/core.hpp>
  8. #define CALIB_PI 3.14159265358979323846
  9. #define CALIB_PI_2 1.57079632679489661923
  10. void calib::Euler(const cv::Mat& src, cv::Mat& dst, int argType)
  11. {
  12. if((src.rows == 3) && (src.cols == 3))
  13. {
  14. //convert rotation matrix to 3 angles (pitch, yaw, roll)
  15. dst = cv::Mat(3, 1, CV_64F);
  16. double pitch, yaw, roll;
  17. if(src.at<double>(0,2) < -0.998)
  18. {
  19. pitch = -atan2(src.at<double>(1,0), src.at<double>(1,1));
  20. yaw = -CALIB_PI_2;
  21. roll = 0.;
  22. }
  23. else if(src.at<double>(0,2) > 0.998)
  24. {
  25. pitch = atan2(src.at<double>(1,0), src.at<double>(1,1));
  26. yaw = CALIB_PI_2;
  27. roll = 0.;
  28. }
  29. else
  30. {
  31. pitch = atan2(-src.at<double>(1,2), src.at<double>(2,2));
  32. yaw = asin(src.at<double>(0,2));
  33. roll = atan2(-src.at<double>(0,1), src.at<double>(0,0));
  34. }
  35. if(argType == CALIB_DEGREES)
  36. {
  37. pitch *= 180./CALIB_PI;
  38. yaw *= 180./CALIB_PI;
  39. roll *= 180./CALIB_PI;
  40. }
  41. else if(argType != CALIB_RADIANS)
  42. CV_Error(cv::Error::StsBadFlag, "Invalid argument type");
  43. dst.at<double>(0,0) = pitch;
  44. dst.at<double>(1,0) = yaw;
  45. dst.at<double>(2,0) = roll;
  46. }
  47. else if( (src.cols == 1 && src.rows == 3) ||
  48. (src.cols == 3 && src.rows == 1 ) )
  49. {
  50. //convert vector which contains 3 angles (pitch, yaw, roll) to rotation matrix
  51. double pitch, yaw, roll;
  52. if(src.cols == 1 && src.rows == 3)
  53. {
  54. pitch = src.at<double>(0,0);
  55. yaw = src.at<double>(1,0);
  56. roll = src.at<double>(2,0);
  57. }
  58. else{
  59. pitch = src.at<double>(0,0);
  60. yaw = src.at<double>(0,1);
  61. roll = src.at<double>(0,2);
  62. }
  63. if(argType == CALIB_DEGREES)
  64. {
  65. pitch *= CALIB_PI / 180.;
  66. yaw *= CALIB_PI / 180.;
  67. roll *= CALIB_PI / 180.;
  68. }
  69. else if(argType != CALIB_RADIANS)
  70. CV_Error(cv::Error::StsBadFlag, "Invalid argument type");
  71. dst = cv::Mat(3, 3, CV_64F);
  72. cv::Mat M(3, 3, CV_64F);
  73. cv::Mat i = cv::Mat::eye(3, 3, CV_64F);
  74. i.copyTo(dst);
  75. i.copyTo(M);
  76. double* pR = dst.ptr<double>();
  77. pR[4] = cos(pitch);
  78. pR[7] = sin(pitch);
  79. pR[8] = pR[4];
  80. pR[5] = -pR[7];
  81. double* pM = M.ptr<double>();
  82. pM[0] = cos(yaw);
  83. pM[2] = sin(yaw);
  84. pM[8] = pM[0];
  85. pM[6] = -pM[2];
  86. dst *= M;
  87. i.copyTo(M);
  88. pM[0] = cos(roll);
  89. pM[3] = sin(roll);
  90. pM[4] = pM[0];
  91. pM[1] = -pM[3];
  92. dst *= M;
  93. }
  94. else
  95. CV_Error(cv::Error::StsBadFlag, "Input matrix must be 1x3, 3x1 or 3x3" );
  96. }
  97. void calib::RodriguesToEuler(const cv::Mat& src, cv::Mat& dst, int argType)
  98. {
  99. CV_Assert((src.cols == 1 && src.rows == 3) || (src.cols == 3 && src.rows == 1));
  100. cv::Mat R;
  101. cv::Rodrigues(src, R);
  102. Euler(R, dst, argType);
  103. }
  104. void calib::EulerToRodrigues(const cv::Mat& src, cv::Mat& dst, int argType)
  105. {
  106. CV_Assert((src.cols == 1 && src.rows == 3) || (src.cols == 3 && src.rows == 1));
  107. cv::Mat R;
  108. Euler(src, R, argType);
  109. cv::Rodrigues(R, dst);
  110. }