-3

My backend uses Euler rotations for efficiency reasons (gimbal lock is not a factor, so please don't comment about it).

If the given data supplies a quaternion, how could I convert that into an accurate Euler?

Most methods I've seen use asin for the Y axis, but there's a suggested method to use 3 atan2 functions for accuracy.

Also I should mention, I'm following OpenGL terms for axis representation, where Z is your monitor's depth, in relation:

{ X: width, Y: height, Z: depth }

so if you provide an example code, please provide the rotations as such:

{ X: pitch, Y: yaw, Z: roll }
halfer
  • 19,824
  • 17
  • 99
  • 186
Tcll
  • 7,140
  • 1
  • 20
  • 23
  • Did you try out the `atan2` method? If so, what was the problem? – BDL Feb 06 '17 at 10:19
  • no, I have yet to use C so you can expect I don't understand the code... heh – Tcll Feb 06 '17 at 10:22
  • What has C to do with the mathematical concept? Which code are you referring to btw.? – BDL Feb 06 '17 at 10:23
  • well, everything that explains the concept uses raw math, which I've never learnt in school, so I've pretty much been noobing everything in Python to figure it out... heh (yea, my life sucks) – Tcll Feb 06 '17 at 10:27
  • If you need someone to implement the given equations for you, then SO might not be the best place. We are not a coding service. – BDL Feb 06 '17 at 10:29
  • yea, I knew I was gonna get slapped in the face with that... I'm not in any way trying to claim as such, but I'm out of options... – Tcll Feb 06 '17 at 10:32
  • a visual explanation would help very much – Tcll Feb 06 '17 at 10:33
  • I don't believe I deserved that downvote... I'm not specifically asking for code, the question only notes if someone does post code. – Tcll Feb 06 '17 at 10:46
  • 1
    The equations you need to implement this can, for example, be found [here](https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles#Quaternion_to_Euler_Angles_Conversion) – BDL Feb 06 '17 at 10:49
  • nice code, but that's another Y-asin, which locks Y rotation to (+/-)90° – Tcll Feb 06 '17 at 10:53
  • "*please explain your downvotes*" It's probably your discussion of Gimbal lock. It has nothing to do with your question (how to convert a quaternion into Euler angles) and is somewhat... dubious, particularly as it relates to the relative cost of using Euler angles vs. quaternions. – Nicol Bolas Feb 06 '17 at 15:19
  • **TL;DR: I'd say you don't need to convert them at all. Use quaternions.** You seem to think that combining euler angles is faster than multiplying quaternions, which I'm sure is not true. Quaternion multiplication requires just 16 scalar multiplications and 12 additions/subtractions, which is not a lot. On the other hand, combining euler angles involves *a lot* of trigonometric functions. – HolyBlackCat Feb 06 '17 at 16:24
  • radians can be over-scaled and still return the same transformation result... so yea, 3 operations per bone vs 28 operations per bone, I think we know the winner... all that's left is transforming the vertices, which I think quaternion math wins there... not sure though, haven't gotten that far into my observations yet. – Tcll Feb 06 '17 at 18:00
  • @NicolBolas I only stated that because I know I'm gonna get flamed hard for using Eulers if I leave it out. thanks for your input though :) – Tcll Feb 06 '17 at 18:03
  • @Tcll: [This question](http://stackoverflow.com/q/16074344/734069) was not "flamed hard". Nor was [this one](http://stackoverflow.com/q/37146033/734069). Or [this one](http://stackoverflow.com/q/37768949/734069). Thus far, people are reacting negatively because you've defended your use of Euler angles with dubious reasoning. After all, you can't just accumulate rotations up the hierarchy; you have to accumulate translations and rotations. That's not the same thing as accumulating them *independently*. So it's not "3 operations per bone". – Nicol Bolas Feb 06 '17 at 18:20
  • I never said it was, too many people think "Euler angles" are bad, and I don't want to deal with the pointless arguments... also, I know transformation is more than just rotation, I'm only referring to rotation and ignoring the operations involved with translation and scale. so the reasoning isn't all that dubious, since I only need to know how to get eulers from quats... I don't need explanations for what I already know ;) – Tcll Feb 06 '17 at 18:43
  • forgive my first statement, the first link didn't load, so I thought you were talking about this question... to back up my standpoint though, I'm asking about converting to euler angles, rather than asking how to deal with them... you know the Royal question will be asked "why in god's name are you using eulers" – Tcll Feb 06 '17 at 18:50
  • alright fine, you guys got your wish, if anyone brings up euler rotations causing gimbal lock, I will downvote them without hesitation. – Tcll Feb 06 '17 at 20:20
  • Please use the @ symbol when you reply to people (not under their own questions/answers) like this: `@guy_name your_comment`, because otherwise they won't get a notification a probably won't reply to you. Also, free hint: Properly capitalize and format your post to get a better votes. – HolyBlackCat Feb 07 '17 at 01:49
  • I'm still sure you don't funlly understand what you're talking about. `so yea, 3 operations per bone vs 28 operations per bone, I think we know the winner` *Which* 3 operations? Are you talking about 3 additions? It won't combine rotations properly. Try it on paper if you think it will. – HolyBlackCat Feb 07 '17 at 01:55
  • @HolyBlackCat are you referring to a rotation like 470° (not sure what that is in radians)? if so, it should work, of course this and my earlier comment are only in theory, minorly tested with matrices from blender. the result can always be modulo'd within range. I will agree with you though and say my idea could be flawed, but there's no way for me to know without testing. – Tcll Feb 07 '17 at 14:40
  • also, yes, grammar would get me higher points, and I would pay more attention to it if I were on my computer... but I only have internet on this stupid phone and it's very annoying to use. – Tcll Feb 07 '17 at 14:42
  • `are you referring to a rotation like 470°` I'm not. In the original question you said you want to use euler angles for hierarchical rotations. But how are you going to combine 2 (or more) euler angles? You seem to think that adding them component-wise will work, but it won't. My point is that you will need to perform some very tricky math with lots of trigonometric functions to just combine 2 euler angles. That's nowhere as fast as combining (multiplying) 2 quaternions. – HolyBlackCat Feb 07 '17 at 14:59
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/135089/discussion-between-tcll-and-holyblackcat). – Tcll Feb 07 '17 at 15:10
  • 1
    Please don't add voting commentary in your posts: downvoters tend to vote and move on, so the people who you would want to see would have long gone. I appreciate that mobile phones are fiddly, but nevertheless if I feel that effort has not gone into a post then I will downvote too (I would have done so here too, but -3 is enough). The expectation for "example code" may not have helped either, but again I'd just be guessing. There are a lot of active editors on this site, helping improve posts, and they don't want to feel that lots of new work is being generated for them `:-)`. – halfer Apr 15 '17 at 14:51
  • I will admit I was quick to ask my question, but I do have a problem with wording which influences formatting... but I understand now the downvotes for formatting reasons. I just have trouble trying to comprehend how to fix it... – Tcll Apr 15 '17 at 18:34

1 Answers1

1

The concept is not trivial, but look to open source. There's plenty of people that have implemented this before you: Quaternion.java Line: 289, toAngles. The fact that it's mostly math should make it easy to convert to your language of preference. Angles also happen to be in the order you requested (pitch, yaw, roll)

public float[] toAngles(float[] angles) {
    if (angles == null) {
        angles = new float[3];
    } else if (angles.length != 3) {
        throw new IllegalArgumentException("Angles array must have three elements");
    }

    float sqw = w * w;
    float sqx = x * x;
    float sqy = y * y;
    float sqz = z * z;
    float unit = sqx + sqy + sqz + sqw; // if normalized is one, otherwise
    // is correction factor
    float test = x * y + z * w;
    if (test > 0.499 * unit) { // singularity at north pole
        angles[1] = 2 * FastMath.atan2(x, w);
        angles[2] = FastMath.HALF_PI;
        angles[0] = 0;
    } else if (test < -0.499 * unit) { // singularity at south pole
        angles[1] = -2 * FastMath.atan2(x, w);
        angles[2] = -FastMath.HALF_PI;
        angles[0] = 0;
    } else {
        angles[1] = FastMath.atan2(2 * y * w - 2 * x * z, sqx - sqy - sqz + sqw); // roll or heading 
        angles[2] = FastMath.asin(2 * test / unit); // pitch or attitude
        angles[0] = FastMath.atan2(2 * x * w - 2 * y * z, -sqx + sqy - sqz + sqw); // yaw or bank
    }
    return angles;
}
reden
  • 968
  • 7
  • 14
  • just realized the problems with this are no different from the wiki solution BDL provided: can't rotate Y (monitor height) beyond 90°, and orientation seems improper { X: yaw, Y: roll, Z: pitch } placing the plane facing up with it's left wing towards you. – Tcll Feb 08 '17 at 11:55
  • I haven't noticed any such issues during the time I've used the engine (some 7 years). I guess you can also take a look at the fromAngles method to make sure the Quat is constructed properly. – reden Feb 08 '17 at 13:30
  • I'm sure the engine you're using follows it's own standard all the way through, but it's YZX standard makes things all the more confusing, which is why I asked for XYZ. secondly, for my (the proper) standard (Z = monitor depth), this orientation means you can't look behind you, but only as far as your sides... which is why I asked for 3 atan2 functions. all in all though, it's just as good as any other version of this particular method, which is why I upvoted. – Tcll Feb 08 '17 at 23:10