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

Quaternion: Euler angles math fix and documentation #19

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

dmartinp
Copy link
Contributor

@dmartinp dmartinp commented Dec 20, 2019

I realized I hadn't fully reverted the math correctly. I have tested this with Myo armband which transmits quaternion values and the math seems correct.

I have also included these methods in the help file.

There could be a discussion about the orientation of the math with the tilt method. The ambisonic convention is that positive Y points to the left and moving clockwise around the x-axis (tilt) should put positive Y straight up. With the euler angles however, this motion results in -0.5pi radians. So this means the quaternion data (at least from the Myo) uses the convention that positive Y points to the right? And so a counterclockwise rotation around the x-axis results in the Euler angle of 0.5pi radians. I am by no means an expert with quaternions (which was my motivation to get the Euler angles in the first place).

@joslloand
Copy link
Contributor

@dmartinp another thought... what about yaw, pitch, roll?

@mtmccrea did some work noting intrinsic vs extrinsic referencing for ypr.

@dmartinp
Copy link
Contributor Author

@joslloand Could you elaborate? In the help documentation, I have included the terms yaw pitch and roll. In the referenced wiki page these are the terms used. I just translated them into rotate tilt and tumble, the terms used by the ATK.

@joslloand
Copy link
Contributor

@dmartinp it might be good to bring @mtmccrea in on the conversation....

@mtmccrea, any comments??

@mtmccrea
Copy link
Contributor

@mtmccrea, any comments??

I've reread the original comment and I'm still not clear on what the open question is.
Generally, you'll want to be clear about what frame of reference you're using, both axis directions and rotation directions, and document it. If the quark implements a specific algorithm (the one you linked to on wikipedia), then that's the frame of reference to document.
It's a separate task to see how that frame of reference relates to a specific application (the Myo and ATK), which may differ in obvious or more subtle ways. Without a clear understanding of these things (i.e. just implementing based on trial and error), it might make for future headaches.

@dmartinp another thought... what about yaw, pitch, roll?

I agree that it would be more widely applicable to use the yaw, pitch, roll convention. I haven't encountered RTT outside of the ATK. Similarly, you might consider using the more widely adopted axis/direction conventions than ambisonics. You could then either write additional methods for specific conventions, or those methods could live in as an extension to this one in another library (like the ATK). A thought about adapting one convention to another—if this is used in DSP or high-refresh rate situations, you'll want to make the conversion as close to the quaternion conversion as possible. So rather than going quaternion > euler then adding confusing direction inversions to get to your convention, maybe 2 different conversions directly from the quaternion would be best.

Some starting points would be to have a good idea of what intrinsic (rotations axes move with the rotation) vs. extrinsic ("lab fixed", rotation axes stay put while the object rotates) rotations are. The difference between Euler and Tait-Bryan angles are (which RTT more closely resembles), and how the order of rotations should be done to get the desired result. Offhand, I recall that basically to achieve a yaw-pitch-roll as we think of them in an airplane for example, with extrinsic rotations, you would apply the individual rotations in reverse order to achieve that end orientation.

Copy link
Contributor

@telephon telephon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly, there are still outstanding decisions about semantics.

@dmartinp
Copy link
Contributor Author

I think this discussion went in a different direction than I had expected, but it cleared some things up for me. The only thing my pull request does is convert a quaternion into the three rotation angles, whether we call them yaw-pitch-roll, or rotate-tilt-tumble is only a naming convention as far as I can see. The math behind them is the same? If so, then I propose that the math is done with yaw-pitch-roll and we can have convenience methods called rotate, tilt and tumble that simply call the yaw pitch and roll methods.

The discussion became one about how to apply these angles, which I think should be up to the user. All I have done here is return the Euler angles in radians from a given quaternion. I could see in the future how the quaternion class could apply a rotation matrix for the user, but that is not what I am proposing with this PR.

@telephon
Copy link
Contributor

ah good - so what do you think, @mtmccrea ?

@dyfer
Copy link
Contributor

dyfer commented Sep 18, 2020

I'd like to pitch in here. I tested the updated math by using a different device that outputs quaternions and the calculations seems to yield expected result, i.e. yaw/pitch/roll consistent with Tait-Bryan angles or symmetry axes of a plane. Again, if I understand, these represent:

  • intrinsic rotation
  • rotation order along axes: z-y-x

I'm fuzzy on these details... it would be great if this information is 1) confirmed by others and 2) make it to the documentation in this PR.
Again, I think this PR is functionally correct.

I also agree that yaw/pitch/roll should be the primary methods.

@dyfer
Copy link
Contributor

dyfer commented Apr 18, 2022

If I understand correctly, the only thing requested in this PR is clarification in the documentation. Is that right @mtmccrea @joslloand @dmartinp ? If so, is my comment above accurate and could it be used as a blueprint for the addition to the docs to be added to this PR?

@joslloand
Copy link
Contributor

If I understand correctly, the only thing requested in this PR is clarification in the documentation. Is that right @mtmccrea @joslloand @dmartinp ? If so, is my comment above accurate and could it be used as a blueprint for the addition to the docs to be added to this PR?

Seems fine to me. A Yaw, Pitch, Roll convention that matches expected results for an example hardware application, e.g., Myo armband, appears appropriate to me. AND, the single rotation names meets the ATK convention.

ALSO, I've just had a quick look, and there are no ATK dependencies on Quaternion at the moment, so this change won't break the ATK.

A comment from @mtmccrea :

Some starting points would be to have a good idea of what intrinsic (rotations axes move with the rotation) vs. extrinsic ("lab fixed", rotation axes stay put while the object rotates) rotations are. The difference between Euler and Tait-Bryan angles are (which RTT more closely resembles), and how the order of rotations should be done to get the desired result. Offhand, I recall that basically to achieve a yaw-pitch-roll as we think of them in an airplane for example, with extrinsic rotations, you would apply the individual rotations in reverse order to achieve that end orientation.

The intrinsic vs extrinsic aspect has to do with the "fixed world" or "reference" nature of the rotations. My understanding is this becomes important with compound rotations. Comments from the ATK code (thanks @mtmccrea)...

HoaRTT:

// Compound rotations applied in sequential order:
// Rotate > Tilt > Tumble.
// Extrinsic, "laboratory-fixed" axes.
HoaRTT : HoaUGen {

AND...

HoaYPR:

// Compound rotation: Yaw-Pitch-Roll.
// Mixed intrinsic/extrinsic.
// This rotation differs from HoaRTT, which is extrinsic.
HoaYPR : HoaUGen {

IN my understanding, as @dmartinp's contributions are single rather than compound rotations, the intrinsic vs extrinsic problem doesn't come into play here. So... more reason for me to feel this PR is ready to go.

IF a compound YPR rotation were to be implemented, then I'd say observe @mtmccrea's comment:

// Note reversed order of rotations to achieve intrinsic YPR

AND, test with the hardware in question. So.. after many words... it looks ready to go to me.

Any thoughts from @dmartinp & @mtmccrea?

@mtmccrea
Copy link
Contributor

mtmccrea commented Apr 22, 2022

@joslloand, I've done some more looking into it, and my takeaways are

  1. I think the synonyms .rotate, .tilt, .tumble should be removed, as they're specific to ambisonics/ATK, and there's a discrepancy in direction conventions (pitch != tumble, see below), and
  2. There should be clarifying comments made to the help docs.

1

I made a gist performing the quaternion rotation on unit vectors and comparing the rotation matrices to the atk-FOA implementations, and found that the pitch/tumble cases differ (tumble = -pitch). The quaternion-euler rotation conventions look to be consistent with a right-handed/counter-clockwise rotation convention on all axes.
(Note you'll need the MatrixArray quark and @dmartinp's added methods from this PR to run the second block of tests).

2

Given the referenced source for the quaternion<>Euler conversion, I'd suggest adding a clarification to the comment in the code:

// conversion to Euler (Tait–Bryan) angles.

The following explanation could live in a ::NOTE::/::DISCUSSION:: in the help docs:

The "Euler angles" returned here are, more specifically, Tait–Bryan angles. Whereas "proper/classic Euler angles" are defined by three rotations, of which the first and third are about the same axis (e.g. z-y-z), Tait–Bryan angles specify rotations about 3 distinct axes (e.g. x-y-z).

Yaw, pitch and roll correspond to heading , pitch, bank of flight dynamics:
Yaw – \psi : rotation about the Z-axis (aka Heading)
Pitch – \theta : rotation about the Y-axis (aka Pitch)
Roll – \varphi: rotation about the X-axis (aka Bank)
Each angle represents an elemental rotation about a principle axis, which move with the body on each subsequent rotation (i.e. "intrinsic rotation" or "body rotation").

The body's orientation can be achieved by successive intrinsic rotations, e.g. in order Z-Y-X (aka, yaw-pitch-roll, "Body 3-2-1"—capital letters denote axes moving with the body), or extrinsic rotations, e.g. about x-y-z (aka "lab 1-2-3"—lowercase letters denote axes fixed to the world frame).

@mtmccrea
Copy link
Contributor

With the euler angles however, this motion results in -0.5pi radians. So this means the quaternion data (at least from the Myo) uses the convention that positive Y points to the right?

Regarding the behavior of the Myo, I'm not sure what coordinate system it uses, but your description sounds like a left-handed rule. In any case, it looks like the rotation matrices generated from Quaternion class, as done in the gist in my previous post, show consistent directions with the values returned with calling the added yaw, pitch, roll methods (right-handed, counter-clockwise rule).

BTW, the quaternion-to-rotation-matrix method from my gist could be added to the Quaternion class in a separate PR.

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

Successfully merging this pull request may close these issues.

5 participants