Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document intrinsic vs. extrinsic rotations #281

Open
juliohm opened this issue Jan 26, 2024 · 6 comments
Open

Document intrinsic vs. extrinsic rotations #281

juliohm opened this issue Jan 26, 2024 · 6 comments

Comments

@juliohm
Copy link
Member

juliohm commented Jan 26, 2024

We recently noticed that rotations such as RotXYZ are extrinsic, meaning that they rotate with respect to the original xyz axis. Is it possible to rotate around z, then rotate around the new y' and finally around the new x''? The so called intrinsic rotations?

https://en.wikipedia.org/wiki/Euler_angles#Chained_rotations_equivalence

We migrated from ReferenceFrameRotations.jl to Rotations.jl and noticed that some of our rotation conventions were compromised.

cc: @hyrodium

@juliohm
Copy link
Member Author

juliohm commented Jan 29, 2024

Discussing with other people on Zulip, we can better document this theorem:

https://math.stackexchange.com/questions/1137745/proof-of-the-extrinsic-to-intrinsic-rotation-transform

@juliohm juliohm changed the title How to obtain intrinsic rotations? Document intrinsic vs. extrinsic rotations Jan 29, 2024
@hyrodium
Copy link
Collaborator

hyrodium commented Jan 29, 2024

Sorry for the late response!

I was planning to answer with some visualizations after resolving #279, but that may take time a bit.
Intrinsic operations can be obtained by changing the rotation order or axes and signs of rotation angles.

julia> import Rotations

julia> import ReferenceFrameRotations

julia> ReferenceFrameRotations.angle_to_dcm(ReferenceFrameRotations.EulerAngles(1.2, 0.3, -0.8, :XYZ))
DCM{Float64}:
 0.665589  -0.0680412  -0.74321
 0.685316   0.450043    0.57254
 0.29552   -0.890411    0.346174

julia> Rotations.RotZYX(0.8,-0.3,-1.2)
3×3 RotZYX{Float64} with indices SOneTo(3)×SOneTo(3)(0.8, -0.3, -1.2):
 0.665589  -0.0680412  -0.74321
 0.685316   0.450043    0.57254
 0.29552   -0.890411    0.346174

julia> ReferenceFrameRotations.angle_to_dcm(ReferenceFrameRotations.EulerAngles(1.2, 0.3, -0.8, :ZYZ))
DCM{Float64}:
  0.909785  0.360416  -0.205891
 -0.401028  0.891199  -0.211993
  0.107084  0.275436   0.955336

julia> Rotations.RotZYZ(0.8,-0.3,-1.2)
3×3 RotZYZ{Float64} with indices SOneTo(3)×SOneTo(3)(0.8, -0.3, -1.2):
  0.909785  0.360416  -0.205891
 -0.401028  0.891199  -0.211993
  0.107084  0.275436   0.955336

@juliohm
Copy link
Member Author

juliohm commented Jan 29, 2024

Even inside Rotations.jl we can do that conversion with something like:

RotXYZ(a1, a2, a3) # extrinsic with a3 around Z, followed by a2 around Y, followed by a1 around X
RotZYX(a1, a2, a3) # intrinsic with a1 around Z, followed by a2 around Y, followed by a3 around X

We don't need to flip the signs if we read from left-to-right (intrinsic) versus right-to-left (extrinsic)

@juliohm
Copy link
Member Author

juliohm commented Jan 29, 2024

So maybe the docs could emphasize this "reading" convention. If users seek "intrinsic" rotations they can read the struct names and angles from left-to-right.

A dedicated paragraph explaining this reading convention and how angles are applied in order can really help end users.

@KronosTheLate
Copy link

If I am not mistaken, the following sentence in the readme covers this now?

This may be interpreted as an "extrinsic" rotation about the Z, Y, and X axes or as an "intrinsic" rotation about the X, Y, and Z axes. Similarly, RotZYX(z, y, x) may be interpreted as an "extrinsic" rotation about the X, Y, and Z axes or an "intrinsic" rotation about the Z, Y, and X axes.

I am not sure if this issue is asking for more words on the topic, or if it should be closed in light of the above quote.

I have to admit, I am quite fond of how Scipy allows users to specify the representation as a string, e.g. "xyz" for extrinsic x, y, z, for "XYZ" for intrinsic z, then y, then x. It frees the user from first having to understand the equivalency between the repsentations.

Discussing with other people on Zulip, we can better document this theorem:

https://math.stackexchange.com/questions/1137745/proof-of-the-extrinsic-to-intrinsic-rotation-transform

I actually ended up "proving" this myself recently for my master's thesis. It is not that mathematical in language and structure, making it somewhat more accasable, and I am pretty sure it holds up. The relevant page can be found here That might provide some inspiration on how to quickly prove the equivalency without invoking the heavy machinery of mathematical proofs xD

@KronosTheLate
Copy link

KronosTheLate commented Jun 9, 2024

What about a section like the following? It is rather verbose, but also extremely explicit and hopefully understandable. It also helps showing how a single rotation matrix has both an intrinsic and extrinsic interpretation, which I think the tables below do even better than the wikipedia article on euler angles.

In the tables below, note that

  • The axes $x$, $y$ and $z$ are the global axes, which remain fixed.
  • A prime (as in $x'$) indicates that the axis has been rotated once by a previous rotation.
    • Two primes then indicate that the axis has been rotated by two previous rotations

Tait-Bryan convention:

Constructor Factorized Rotation Matrix Extrinsic Interpretation Intrinsic Interpretation
RotXYZ(a, b, c) $R_x(a) R_y(b) R_z(c)$ 1. Rotate $c$ radians about $z$
2. Rotate $b$ radians about $y$
3. Rotate $a$ radians about $x$
1. Rotate $a$ radians about $x$
2. Rotate $b$ radians about $y'$
3. Rotate $c$ radians about $z''$
RotXZY(a, b, c) $R_x(a) R_z(b) R_y(c)$ 1. Rotate $c$ radians about $y$
2. Rotate $b$ radians about $z$
3. Rotate $a$ radians about $x$
1. Rotate $a$ radians about $x$
2. Rotate $b$ radians about $z'$
3. Rotate $c$ radians about $y''$
RotYXZ(a, b, c) $R_y(a) R_x(b) R_z(c)$ 1. Rotate $c$ radians about $z$
2. Rotate $b$ radians about $x$
3. Rotate $a$ radians about $y$
1. Rotate $a$ radians about $y$
2. Rotate $b$ radians about $x'$
3. Rotate $c$ radians about $z''$
RotYZX(a, b, c) $R_y(a) R_z(b) R_x(c)$ 1. Rotate $c$ radians about $x$
2. Rotate $b$ radians about $z$
3. Rotate $a$ radians about $y$
1. Rotate $a$ radians about $y$
2. Rotate $b$ radians about $z'$
3. Rotate $c$ radians about $x''$
RotZXY(a, b, c) $R_z(a) R_x(b) R_y(c)$ 1. Rotate $c$ radians about $y$
2. Rotate $b$ radians about $x$
3. Rotate $a$ radians about $z$
1. Rotate $a$ radians about $z$
2. Rotate $b$ radians about $x'$
3. Rotate $c$ radians about $y''$
RotZYX(a, b, c) $R_z(a) R_y(b) R_x(c)$ 1. Rotate $c$ radians about $x$
2. Rotate $b$ radians about $y$
3. Rotate $a$ radians about $z$
1. Rotate $a$ radians about $z$
2. Rotate $b$ radians about $y'$
3. Rotate $c$ radians about $x''$

"Proper" euler angles:

Constructor Factorized Rotation Matrix Extrinsic Interpretation Intrinsic Interpretation
RotZXZ(a, b, c) $R_z(a) R_x(b) R_z(c)$ 1. Rotate $c$ radians about $z$
2. Rotate $b$ radians about $x$
3. Rotate $a$ radians about $z$
1. Rotate $a$ radians about $z$
2. Rotate $b$ radians about $x'$
3. Rotate $c$ radians about $z''$
RotZYZ(a, b, c) $R_z(a) R_y(b) R_z(c)$ 1. Rotate $c$ radians about $z$
2. Rotate $b$ radians about $y$
3. Rotate $a$ radians about $z$
1. Rotate $a$ radians about $z$
2. Rotate $b$ radians about $y'$
3. Rotate $c$ radians about $z''$
RotXYX(a, b, c) $R_x(a) R_y(b) R_x(c)$ 1. Rotate $c$ radians about $x$
2. Rotate $b$ radians about $y$
3. Rotate $a$ radians about $x$
1. Rotate $a$ radians about $x$
2. Rotate $b$ radians about $y'$
3. Rotate $c$ radians about $x''$
RotXZX(a, b, c) $R_x(a) R_z(b) R_x(c)$ 1. Rotate $c$ radians about $x$
2. Rotate $b$ radians about $z$
3. Rotate $a$ radians about $x$
1. Rotate $a$ radians about $x$
2. Rotate $b$ radians about $z'$
3. Rotate $c$ radians about $x''$
RotYXY(a, b, c) $R_y(a) R_x(b) R_y(c)$ 1. Rotate $c$ radians about $y$
2. Rotate $b$ radians about $x$
3. Rotate $a$ radians about $y$
1. Rotate $a$ radians about $y$
2. Rotate $b$ radians about $x'$
3. Rotate $c$ radians about $y''$
RotYZY(a, b, c) $R_y(a) R_z(b) R_y(c)$ 1. Rotate $c$ radians about $y$
2. Rotate $b$ radians about $z$
3. Rotate $a$ radians about $y$
1. Rotate $a$ radians about $y$
2. Rotate $b$ radians about $z'$
3. Rotate $c$ radians about $y''$

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants