open-simulation-interface icon indicating copy to clipboard operation
open-simulation-interface copied to clipboard

Matrix order in definition of Euler Angles is wrong

Open joullsson opened this issue 3 years ago • 10 comments

Describe the bug

In https://opensimulationinterface.github.io/osi-documentation/open-simulation-interface/structosi3_1_1Orientation3d.html there are two different issues

  • while the text correctly interprets the ISO8855 as describing the intrinsic rotation z-y'-x'', the formula that defines the rotation as a product of three elementary rotations is in reverse order.
  • the preferred angular range is given as [-pi,pi]. However, euler angles are not unique on the cube [-pi, pi]^3.

Describe the expected behavior

The expected behavior can simply be taken from wikipedia https://de.wikipedia.org/wiki/Eulersche_Winkel#Roll-,_Nick-_und_Gierwinkel:_z-y%E2%80%B2-x%E2%80%B3-Konvention. This means that

  • the formula should read R_{yaw,pitch,roll} = R_{yaw} * R_{pitch} * R_{roll}
  • the angular range should be set to [-pi, pi] x [-pi/2, pi/2] x [-pi , pi] in order to make it unique (in the interior at least)

joullsson avatar Mar 10 '21 11:03 joullsson

Since I wasn't able to create a branch as a non-member here is the PR from my fork https://github.com/OpenSimulationInterface/open-simulation-interface/pull/496

joullsson avatar Mar 11 '21 11:03 joullsson

The order of rotation is correct. ISO specifies z-y'-x'' This means yaw first, pitch second, roll last. Rotation of a vector p is done by multiplying the rotation matrix from the left side e.g. R * p. That is why the right most rotation has to be yaw.

For euler angles there are a lot of different conventions ISO 8855 is basically equivalent to what Wikipedia refers to as intrinsic Tait-Bryan-Angles. You can find them in the wikipedia article you linked their equation is given by R_GNR^T in the section Roll-, Nick- und Gierwinkel: z-y′-x″-Konvention. You can see here that the order is indeed R_{yaw,pitch,roll} = R_{roll} * R_{pitch} * R_{yaw}.

For the ranges I agree that pitch shall be limited to [-pi/2,pi/2] to make the rotation unique.

jola6897 avatar Apr 16 '21 14:04 jola6897

Hi Jonas, thanks for considering this issue and for the detailed answer!

As you have said. ISO specifies z-y'-x'' and in the standard it is also described what this means: it means that first, the vector p is rotated around the z-axis. This results in a rotated intermediate frame with new x and y- axes. The rotated y- axis is called y'. Then second rotation for pitch then is performed with respect to this intermediate axis y'. This clearly creates another x-axis which is called x''. The final roll rotation is performed around this x'' axis, resulting in the vehicle frame.

The procedure described above is referred to as the intrinsic rotations, as you have correctly pointed out. For intrinsic rotations however, the reasoning "from right to left" is not applicable. In fact, the order of rotation matrices is reversed for intrinsic rotations compared to simple extrinsic rotations, as is, e.g., explained in https://de.wikipedia.org/wiki/Eulersche_Winkel#Matrix-Herleitung_im_allgemeinen_Fall.

joullsson avatar Apr 19 '21 07:04 joullsson

Following your detailed description of changing the axis this means:

  1. Starting in system with axis, x, y, z. A point here is p.
  2. yaw rotation in x, y, z to system x', y', z'. To transform p to a point p' in the new coordinate system, this would mean p' = R_{yaw} * p
  3. pitch rotation in x', y', z' to system x'', y'', z''. To transform p' to a point p'' in the new coordinate system, this would mean p'' = R_{pitch} * p'
  4. roll in x'', y'', z''. To get the final position R_{roll} * p''

You can look at it as incremental rotations and each transition between the coordinate system is quite clear. Now if you put it together: R_{roll} * (R_{pitch} * (R_{yaw} * p)) This gives you the order of rotation.

I think there is a misunderstanding as the chapter that you quoted describes how to get the intrinsic rotation from an EXTRINSIC rotation. Basically if you have angles as extrinsic their value will change when transforming them to intrinsic. This would mean your oder is correct if the values given are extrinsic but they should be intrinsic. This means

  • intrinsic angles: roll, pitch, yaw: R_{roll} * R_{pitch} * R_{yaw}
  • extrinsic angles: ROLL, PITCH, YAW: R_{YAW} * R_{PITCH} * R_{ROLL} The important part is that it is not garantueed that roll == ROLL, pitch ==PITCH, yaw ==YAW.

Does this resolve your question? Please let me know.

jola6897 avatar Apr 20 '21 04:04 jola6897

Unfortunately this does not resolve the problem. First of all, I would like to get back to the wikipedia article, where it is clearly explicitly stated what is the correct order for Gier-Nick-Roll, for ISO8855 https://de.wikipedia.org/wiki/Eulersche_Winkel#Roll-,_Nick-_und_Gierwinkel:_z-y%E2%80%B2-x%E2%80%B3-Konvention. Please, simply read off R_GNR, the transposed one just adds more confusion.

But I agree that there is no derivation given in the article, therefore we can do it here if you like: Just consider an intrinsic rotation where you do yaw = pi/2 first and then you any pitch. After the yaw rotation, the new x'-axis of the vehicle clearly points in the direction of the y-axis of the world fixed frame, the one you started with. But if you now simply apply R_{pitch}, you only rotate around the y-axis of the world fixed frame, which is not what you want to do. In fact, for an intrinsic rotation around y' you have to do a change of basis in the following way: R_{pitch,y'} = R_{yaw} R_{pitch,y} R_{yaw}^{T}. In this way we get p'' = R_{yaw} R_{pitch,y} R_{yaw}^{T} R_{yaw} p = R_{yaw} R_{pitch,y} p. Now for the last rotation you want to perform a roll in the double primed frame, that is, R_{roll,x''} = R_{yaw} R_{pitch,y} R_{roll,x} ( R_{yaw} R_{pitch,y})^{T} which gives you, after applying to p'', the desired result R_{yaw} R_{pitch,y} R_{roll,x}.

joullsson avatar Apr 20 '21 13:04 joullsson

Hi, I am very sorry, you are right. It has to be indeed R_{yaw,pitch,roll} = R_{yaw} * R_{pitch} * R_{roll}.

This means that the second equation in https://opensimulationinterface.github.io/osi-documentation/open-simulation-interface/structosi3_1_1Orientation3d.html is also wrong. It should read:

vector_{gobal coord system} := Rotation_{yaw, pitch, roll} * vector_{local coord system} + local_{origin}::position

Since the Rotation_{yaw, pitch, roll} rotates from local to global already and therefore the inverse is not needed. @joullsson do you also see it that way?

jola6897 avatar Apr 20 '21 14:04 jola6897

I am having a litte "Déja vu" here as I think the disccusion came already up here. I was pretty confident we solved it correctly at that time?

jdsika avatar Apr 20 '21 15:04 jdsika

Hey, I do agree that it should read: vector_{gobal coord system} := Rotation_{yaw, pitch, roll} * vector_{local coord system} + local_{origin}::position I overlooked this one as well, good point!

Edit: I am not sure what the formatting is about, but local_{origin::position} would make more sense to me.

joullsson avatar Apr 21 '21 08:04 joullsson

Output from ArchitectureGroup Meeting 28.05.2021

  1. @joullsson Is this issue now solved or should we have a pull request to integrate your suggestion regarding "local_{origin::position} "

kmeids avatar May 28 '21 13:05 kmeids

Hey, from my side it is important to merge the PR https://github.com/OpenSimulationInterface/open-simulation-interface/pull/496 which correct the problems mentioned and settled here.

joullsson avatar May 28 '21 13:05 joullsson