rotm2euler.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. /*
  2. * Copyright (c) 2016 Satya Mallick <spmallick@learnopencv.com>
  3. * All rights reserved. No warranty, explicit or implicit, provided.
  4. */
  5. #include "opencv2/opencv.hpp"
  6. #include <stdlib.h> /* srand, rand */
  7. #include <time.h> /* time */
  8. using namespace cv;
  9. using namespace std;
  10. // Checks if a matrix is a valid rotation matrix.
  11. bool isRotationMatrix(Mat &R)
  12. {
  13. Mat Rt;
  14. transpose(R, Rt);
  15. Mat shouldBeIdentity = Rt * R;
  16. Mat I = Mat::eye(3,3, shouldBeIdentity.type());
  17. return norm(I, shouldBeIdentity) < 1e-6;
  18. }
  19. // Calculates rotation matrix to euler angles
  20. // The result is the same as MATLAB except the order
  21. // of the euler angles ( x and z are swapped ).
  22. Vec3f rotationMatrixToEulerAngles(Mat &R)
  23. {
  24. assert(isRotationMatrix(R));
  25. float sy = sqrt(R.at<double>(0,0) * R.at<double>(0,0) + R.at<double>(1,0) * R.at<double>(1,0) );
  26. bool singular = sy < 1e-6; // If
  27. float x, y, z;
  28. if (!singular)
  29. {
  30. x = atan2(R.at<double>(2,1) , R.at<double>(2,2));
  31. y = atan2(-R.at<double>(2,0), sy);
  32. z = atan2(R.at<double>(1,0), R.at<double>(0,0));
  33. }
  34. else
  35. {
  36. x = atan2(-R.at<double>(1,2), R.at<double>(1,1));
  37. y = atan2(-R.at<double>(2,0), sy);
  38. z = 0;
  39. }
  40. return Vec3f(x, y, z);
  41. }
  42. // Calculates rotation matrix given euler angles.
  43. Mat eulerAnglesToRotationMatrix(Vec3f &theta)
  44. {
  45. // Calculate rotation about x axis
  46. Mat R_x = (Mat_<double>(3,3) <<
  47. 1, 0, 0,
  48. 0, cos(theta[0]), -sin(theta[0]),
  49. 0, sin(theta[0]), cos(theta[0])
  50. );
  51. // Calculate rotation about y axis
  52. Mat R_y = (Mat_<double>(3,3) <<
  53. cos(theta[1]), 0, sin(theta[1]),
  54. 0, 1, 0,
  55. -sin(theta[1]), 0, cos(theta[1])
  56. );
  57. // Calculate rotation about z axis
  58. Mat R_z = (Mat_<double>(3,3) <<
  59. cos(theta[2]), -sin(theta[2]), 0,
  60. sin(theta[2]), cos(theta[2]), 0,
  61. 0, 0, 1);
  62. // Combined rotation matrix
  63. Mat R = R_z * R_y * R_x;
  64. return R;
  65. }
  66. int main(int argc, char** argv)
  67. {
  68. // Initialize random number generator
  69. srand (time(NULL));
  70. // Randomly generate Euler angles in Degrees.
  71. Vec3f eDegrees(rand() % 360 - 180.0, rand() % 360 - 180.0, rand() % 360 - 180.0);
  72. // Convert angles to radians
  73. Vec3f e = eDegrees * M_PI / 180.0;
  74. // Calculate rotation matrix
  75. Mat R = eulerAnglesToRotationMatrix(e);
  76. // Calculate Euler angles from rotation matrix
  77. Vec3f e1 = rotationMatrixToEulerAngles(R);
  78. // Calculate rotation matrix
  79. Mat R1 = eulerAnglesToRotationMatrix(e1);
  80. // Note e and e1 will be the same a lot of times
  81. // but not always. R and R1 should be the same always.
  82. cout << endl << "Input Angles" << endl << e << endl;
  83. cout << endl << "R : " << endl << R << endl;
  84. cout << endl << "Output Angles" << endl << e1 << endl;
  85. cout << endl << "R1 : " << endl << R1 << endl;
  86. }