2

I have a 3D rotation matrix with small XYZ angles. Angles are between -20° < angle < 20°.
Rotation matrix is constructed with :

rot-mtx-construction

I want to get angles back from the rotation matrix, but several angles are possible.

How to recover the smallest angles allowing to build this rotation matrix in C++?

For the moment I use Eigen::eulerAngles() in C++ to get this angles, but Eigen return angle in the ranges x[0:pi] y[-pi:pi] z[-pi:pi]. So no negative X angles are returned. We can see that a rotation matrix constructed with a X angle of -0.2 return an angle of 2.94159

Here is a test code:

void eigen_test(float x, float y, float z) {
  auto mat = AngleAxisf(x, Vector3f::UnitX())
    * AngleAxisf(y, Vector3f::UnitY())
    * AngleAxisf(z, Vector3f::UnitZ());

  auto angle = mat.toRotationMatrix().eulerAngles(0,1,2);

  cout << "(" <<  x << ", " << y << ", " << z << ") 
-> (" << angle[2] << ", " << angle[1] << ", " << angle[0] << ")" << endl;

}

int main() {
  std::vector<float> num = { -0.2,0.,0.2 };
  for (auto x : num) {
    for (auto y : num) {
      for (auto z : num) {
        eigen_test(x, y, z);
      }
    }
  }

  return 0;
}

Full result :

X    , Y   , Z     -> X'   , Y'   , Z'
__________________________________________________
(-0.2, -0.2, -0.2) -> (2.94159, -2.94159, 2.94159)
(-0.2, -0.2, 0   ) -> (2.94159, -2.94159, -3.14159)
(-0.2, -0.2, 0.2 ) -> (2.94159, -2.94159, -2.94159)
(-0.2, 0,    -0.2) -> (2.94159, -3.14159, 2.94159)
(-0.2, 0,    0   ) -> (2.94159, 3.14159, -3.14159)
(-0.2, 0,    0.2 ) -> (2.94159, 3.14159, -2.94159)
(-0.2, 0.2,  -0.2) -> (2.94159, 2.94159, 2.94159)
(-0.2, 0.2,  0   ) -> (2.94159, 2.94159, 3.14159)
(-0.2, 0.2,  0.2 ) -> (2.94159, 2.94159, -2.94159)
(0,   -0.2,  -0.2) -> (0, -0.2, -0.2)
(0,   -0.2,  0   ) -> (0, -0.2, 0)
(0,   -0.2,  0.2 ) -> (3.14159, -2.94159, -2.94159)
(0,   0,     -0.2) -> (0, 0, -0.2)
(0,   0,     0   ) -> (-0, 0, -0)
(0,   0,     0.2 ) -> (-0, 0, 0.2)
(0,   0.2,   -0.2) -> (3.14159, 2.94159, 2.94159)
(0,   0.2,   0   ) -> (-0, 0.2, 0)
(0,   0.2,   0.2 ) -> (0, 0.2, 0.2)
(0.2, -0.2,  -0.2) -> (0.2, -0.2, -0.2)
(0.2, -0.2,  0   ) -> (0.2, -0.2, -0)
(0.2, -0.2,  0.2 ) -> (0.2, -0.2, 0.2)
(0.2, 0,     -0.2) -> (0.2, 0, -0.2)
(0.2, 0,     0   ) -> (0.2, 0, 0)
(0.2, 0,     0.2 ) -> (0.2, 0, 0.2)
(0.2, 0.2,   -0.2) -> (0.2, 0.2, -0.2)
(0.2, 0.2,   0   ) -> (0.2, 0.2, -0)
(0.2, 0.2,   0.2 ) -> (0.2, 0.2, 0.2)
Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
  • It's weird that you're only getting values in `[0..π]` for X. – 3Dave Jun 29 '22 at 18:20
  • @3Dave It's what it's written in the [Eigen doc](https://eigen.tuxfamily.org/dox/group__Geometry__Module.html#title20) – Maxime Charrière Jun 29 '22 at 19:13
  • What happens if you test it on a matrix with an X rotation of, say, 270º? That's well outside of the stated range. Either something is fishy with the library, or the documentation is incorrect. If this was a game library or physics system, I'd suspect something having to do with gymbal lock, but... that seems unlikely. Any X rotation can be represented as a product of Y and Z rotations, but that would be weird to assume in a math library. – 3Dave Jun 29 '22 at 20:41
  • Does this answer your question? [Is there a way to calculate 3D rotation on X and Y axis from a 4x4 matrix](https://stackoverflow.com/questions/56900173/is-there-a-way-to-calculate-3d-rotation-on-x-and-y-axis-from-a-4x4-matrix) – Spektre Jun 30 '22 at 06:20
  • @Spektre Tks for the link ! I will study your solution and come back to tell you if it was a solution for me – Maxime Charrière Jun 30 '22 at 07:11

1 Answers1

0

I have found how to do for angles between pi/2 and -pi/2 (so work with small angles).
For a rotation ordering of xyz, you can do:

//mat is the 3*3 rotation matrix
double rx = atan2(-mat(1, 2), mat(2, 2));
double ry = asin(mat(0, 2));
double rz = atan2(-mat(0, 1), mat(0, 0));

Found more info on https://www.geometrictools.com/Documentation/EulerAngles.pdf