[HN Gopher] Rotations with quaternions
       ___________________________________________________________________
        
       Rotations with quaternions
        
       Author : imadr
       Score  : 159 points
       Date   : 2021-06-01 12:03 UTC (10 hours ago)
        
 (HTM) web link (imadr.github.io)
 (TXT) w3m dump (imadr.github.io)
        
       | greggman3 wrote:
       | Be aware, quaternions are not always the right solution. There's
       | a reason Unity, Unreal, 3DSMax, Maya, Blender, etc all support
       | Euler interpolation in animation. A simple example is an artist
       | might want to show a clock hand spinning fast to show the
       | progress of time. To do that they set a start angle of 0 and an
       | end angle of say 20000. Sure, there may be ways to represent that
       | with specialized quaternions but in general the 3D tools all
       | seems to default to using Eulers.
       | 
       | This is an issue with the GLTF format. They chose quaternions to
       | represent rotations in animation and as such can't easily
       | represent what the artist's intent was.
       | 
       | You might claim you can sample the Euler animation and split it
       | into multiple quaternion slerps but that brings up another issue
       | which is you need support for discontinuous animations in order
       | to handle other situations (another thing the GLTF format
       | apparently didn't consider).
        
         | klodolph wrote:
         | Quaternions _usually_ match artist 's intent, and Euler angles
         | usually don't. glTF isn't alone in using quaternions. I did a
         | bunch of FBX imports a while back all the orientation channels
         | are just quaternions. It makes sense, because it's _one natural
         | way_ to interpolate rotation data, just based on the
         | orientations of bones during the keyframes. The kind of stuff
         | that you interpolate using Euler angles is going to be stuff
         | that is naturally on gimbals, like cameras, tanks, robots,
         | turrets, and stuff like that. You can do that easily enough by
         | adding another node to your transform hierarchy with
         | quaternions, but if you started off with Euler angles, you don
         | 't really have a way to back out.
         | 
         | Quaternions are not always right, but they are the right
         | default. If you want Euler angles, you can always translate to-
         | from quaternions. Quaternions are independent of the way you
         | set up the coordinate system and each axis is equal.
         | 
         | Unity, for example, uses quaternions internally. It exposes
         | getters and setters for Euler angles that do the conversion
         | to/from quaternions as a convenience. The editor edits Euler
         | angles but they disappear as soon as you are in-game, and if
         | you open up your scene file in a text editor, you'll see
         | m_LocalRotation with the x/y/z/w of a quaternion. I believe
         | Unreal is the same way.
         | 
         | Honestly, that just makes too much sense. Trying to do a
         | physics simulation with Euler angles is just adding extra
         | steps, because Euler angles are not easily composable. If you
         | want to compose two Euler angles to get a third, the easy way
         | to do it is to convert to quaternions, multiply, and then
         | convert back to euler angles. You can see Euler angles in the
         | editor when you are animating a model, but most of the time you
         | are just dragging stuff around on screen or matching mocap data
         | and quaternions make 100x more sense than Euler angles for
         | representing that stuff.
         | 
         | My sense is that any code which does a lot of trig, when
         | there's an obvious way to write the code that does no trig,
         | should probably be rewritten to eliminate the trig. A little
         | bit of sin/cos/tan is fine but as soon as you are doing round
         | trips with acos/asin/atan, you have to start considering where
         | the branch cuts are.
        
           | greggman3 wrote:
           | Unity uses quaternions in the rotation but the actual
           | animation curves are still interpolating Euler angles. Same
           | with Unreal, Maya, 3DSMax, Blender etc... GLTF requires you
           | to convert the animation curves to quaternions. That's a
           | lossy operation
        
         | jonas21 wrote:
         | Yeah, I think any time you need to interface with a human,
         | Euler angles are better because they're more intuitive. There's
         | a good reason aircraft instruments display things in Euler
         | angles, for example.
        
         | sillysaurusx wrote:
         | "Why not both?"
        
           | mottosso wrote:
           | Yes, exactly. The article even points this out:
           | 
           | > However writing a rotation directly in quaternion form
           | isn't really intuitive, what we do instead is convert an
           | Euler angle to a quaternion then use it for rotating.
        
       | Animats wrote:
       | For a simpler discussion, see [1].
       | 
       | [1] http://wiki.secondlife.com/wiki/Rotation
        
       | FabHK wrote:
       | A few remarks:
       | 
       | 0) Very nice practical introduction to quaternions and their
       | application to rotation.
       | 
       | 1) Neat didactic "textbook" implementation, but note that it is
       | not production quality (eg potential overflow in the norm
       | function unnecessarily). That was not the aim, either, but just
       | something to bear in mind.
       | 
       | 2) As a supplement, a useful practical reference for rotations in
       | 3D (with good clarifications and basically all formulae you'll
       | ever need, but no implementation) is
       | 
       |  _Representing Attitude: Euler Angles, Unit Quaternions, and
       | Rotation Vectors_ by James Diebel
       | 
       | https://www.astro.rug.nl/software/kapteyn-beta/_downloads/at...
        
         | tbabb wrote:
         | What would you do differently with the norm function?
        
           | hanche wrote:
           | To compute a norm without overflow (unless it is totally
           | unavoidable), let m be the maximum of the absolute values of
           | the components. Divide each component by m, compute the
           | square root of the sum of squares, and multiply by m. Only
           | the last step might overflow, and if it does, it could not be
           | avoided in any case. Incidentally, this normalization
           | procedure also avoids underflow problems.
        
             | tbabb wrote:
             | I see. I'd say it depends what the application is, then,
             | because in graphics correctly handling (unlikely) extreme
             | values would be quite secondary to performance, especially
             | for an inner loop function like norm. See fastinvsqrt,
             | e.g., which is extremely imprecise!
        
               | FabHK wrote:
               | Absolutely, I should've been more precise: it's perfectly
               | fine for most applications, but not for a library, or,
               | say, manned aviation. So, yeah, when optimising for
               | accuracy, range, or speed you might implement it
               | differently, respectively.
               | 
               | I mean, papers have been written about sqrt(a^2+b^2)
               | alone... :-)
               | 
               | https://arxiv.org/abs/1904.09481
        
               | hanche wrote:
               | In many applications there is definitely no reason to
               | worry about overflow when computing norms. That is more
               | of an issue if you are writing library code for general
               | use, which should be as robust as you can make it.
        
           | xscott wrote:
           | The hypot() function avoids many overflow and underflow
           | cases:                   return hypot(hypot(q.w, q.x),
           | hypot(q.y, q.z));
        
             | tbabb wrote:
             | Interestingly, with clang and -O3 I get identical assembly
             | for hypot() and the "naive" implementation.
        
       | [deleted]
        
       | captainmuon wrote:
       | > A quaternion is basically a 4 dimensional vector, so it has a
       | magnitude (or norm, or length)
       | 
       | Is it really a _vector_ in the physical sense? People often say
       | vector when they mean N-tuple -- for example we learned in high
       | school that vectors are just N numbers taken together.
       | 
       | For physicists, a vector must satisfy certain transformation laws
       | - it must transform in the correct way if a rotation is applied,
       | and the scalar product must be invariant of the coordinate
       | system, IIRC. I don't have enough intuition of quaternions to say
       | how they behave under transformations, though. I would be
       | surprized if you could have "proper" vectors with four components
       | in three-dimensional space.
        
         | littlestymaar wrote:
         | A vector is a member of a vector space. A vector space is a set
         | _V_ + a Field _F_ , where for all _x_ , _y_ in _V_ and _a_ in
         | _F_ , _x + ay_ is also in V. That 's it.
        
         | marosgrego wrote:
         | It's a vector in the mathematical sense.
        
           | foo92691 wrote:
           | Well, quaternions form a vector space over quaternion
           | addition. This part is not very interesting. Vector spaces do
           | not describe multiplication of vectors by each other. So,
           | quaternions are _not_ (only) vectors  "in the mathematical
           | sense" when it comes to their more interesting properties.
        
             | marosgrego wrote:
             | What do you mean? They also form an algebra (a vector space
             | where a "multiplication" is defined).
        
       | vladTheInhaler wrote:
       | For anyone who is interested in an accessible introduction to
       | representing rotations, I highly recommend this site:
       | https://rotations.berkeley.edu. One of my professors provided it
       | for one of his courses, and it's been a really helpful reference
       | several times since then.
        
         | iab wrote:
         | That's a great resource, thank you
        
       | gspr wrote:
       | The reason this works is often skipped in computationally
       | oriented writeups:
       | 
       | Rotations of 3-dimensional real space form the topological group
       | SO(3). Naive parameterizations of that group do not form a cover
       | [1], but the group of norm-1 quaterinons, Spin(3), does.
       | 
       | The failure of naive parameterizations, like the Euler angles, to
       | be a cover manifests itself as gimbal lock.
       | 
       | [1] https://en.wikipedia.org/wiki/Covering_space
        
         | rnhmjoj wrote:
         | Technically the unit quaterions are not Spin(3), but only
         | isomorphic to it, they are properly Sp(1) = GL(1, H). It's all
         | fuzzy because the low dimensional classical groups are all
         | isomorphic to each other: SU(2) ~ Sp(1) ~ Spin(3).
        
           | tobinfricke wrote:
           | > Technically X is not Y, but only isomorphic to it
           | 
           | Not sure this is a useful argument. If two structures are
           | isomorphic, there is no way to tell them apart. If you can't
           | tell them apart - maybe they are the same thing.
        
           | gspr wrote:
           | Indeed.
        
           | jacobolus wrote:
           | This seems extraordinarily nitpicky. Like saying that unit
           | complex numbers are technically not the group of plane
           | rotations about a fixed point, but only isomorphic to it. Or
           | for that matter like saying that the "real number line" is
           | technically not a line, but only isomorphic to one.
        
             | rnhmjoj wrote:
             | Well yeah, it is. The point I wanted to make is that these
             | isomorphism are "exceptional"[1] and only hold for the
             | lower dimensional groups. The general Spin group and
             | quaterions are very different objects.
             | 
             | [1]: https://en.wikipedia.org/wiki/Exceptional_isomorphism
        
           | joppy wrote:
           | That really depends on how you define Spin(3), for example
           | some would define it as the compact simply-connected Lie
           | group of a certain type, at which point the unit quaternions
           | model of Spin(3) is as good as any other.
        
         | GolDDranks wrote:
         | Here's a similar argument from my naive, intuition-based
         | perspective:
         | 
         | It's important to remember that the the group of rotations in
         | 3d space is represented by _unit_ quaternions. This is a subset
         | of the full 4d quaternion space: a spherical shell around the
         | origin, like the skin of a 3d ball but in 4d.
         | 
         | A 3d ball has a 2d, "flat" skin that is "spherically"
         | symmetric.
         | 
         | A 4d ball has a 3d, "volumetric" skin that is, similarly,
         | "spherically" symmetric.
         | 
         | If we are stuck to that 3d skin, it makes perfect sense that it
         | manages to represent rotations in 3d, which have 3 degrees of
         | freedom and spherical symmetry.
         | 
         | The space of rotations that is formed by this "skin" has two
         | special points: the point where all the imaginary coordinates
         | are zero and the real coordinate is one, and it's dual, the
         | negative one, precisely because we are talking about _unit_
         | quaternions. (Similarly as there is only two "purely x" points
         | in a unit circle: (1, 0) and (-1, 0)).
         | 
         | These points represent the identity rotation, i.e. "don't
         | rotate at all". This makes sense, if you think how complex
         | numbers work: the effect of multiplying "one" is that it keeps
         | everything as-is, whereas every other "unit" complex number has
         | a rotating effect.
         | 
         | Then as you think the three imaginary dimensions as degrees of
         | freedoms you can start traveling into, from this neutral point,
         | you get all kinds of rotations. The geometry of the "round",
         | "skin-shaped" space ensures that the rotations wrap around the
         | correct way, "spherically". Especially that after you have
         | travelled "tau" (2 times pi) units, you are again in purely
         | "real", "not rotated" state. And the spherical symmetry means
         | that this works similarly in _any_ direction you can travel to.
         | 
         | The only gotcha is that the unit quaternion space contains
         | doubly the space of minimal 3d rotations, because of the
         | negative number symmetry. There's some good arguments why this
         | is especially beautiful and true, but they are a bit beyond me.
        
           | hanche wrote:
           | There is a nice experiment you can do, illustrating this:
           | Hold a glass of water in the palm of your hand. Not too full,
           | especially not until you get the hang of the following move:
           | Assuming you use your right hand, rotate your hand
           | counterclockwise. At first, your hand goes under your arm,
           | until it has rotated about 270 degrees or so. You can now
           | continue that rotation, but you have to lift your hand up, so
           | it is now above the arm. Keep going, and you end up where you
           | started, but the glass has done two full revolutions.
           | Hopefully without spilling an water (takes practice). The fun
           | thing is, after just one revolution, your arm is twisted into
           | a really uncomfortable configuration.
           | 
           | The mathematical explanation is that SO(3) is doubly
           | connected, whereas the unit quaternions, like any sphere, is
           | simply connected. At any time, each part of your arm has
           | undergone some rotation from the orientation at rest. Halfway
           | through the move, as you travel from the shoulder down to the
           | hand, this rotation starts at the identity, and changes
           | continuously through one rotation, back to the identity once
           | more. But in the unit quaternions, that path takes you from
           | one pole to the opposite pole. This explains why you can't
           | untwist your arm.
           | 
           | Sorry if that made no sense.
           | 
           | Edit: Have a look at "Your palm is a spinor" [1], and then at
           | this Phillipine* tradtional dance [2] about 40 seconds in. I
           | knew I had written about this before [3].
           | 
           | [1] https://www.youtube.com/watch?v=fTlbVLGBm3Q
           | 
           | [2] https://www.youtube.com/watch?v=mOO_IQznZCQ
           | 
           | [3] https://math.stackexchange.com/a/383549
           | 
           | * I wrote Thai originally.
        
         | hanche wrote:
         | I know what you mean, but I would hesitate to call Euler angles
         | naive. ;-)
        
         | an1sotropy wrote:
         | Speaking of gimbal lock - it was a real (as opposed to only
         | theoretical/mathematical) concern for navigation during the
         | Apollo 11 moon landing [1].
         | 
         | Euler angles are fugly and annoying. Quarternions are clean and
         | refreshing.
         | 
         | [1] https://apollo11space.com/apollo-and-gimbal-lock/
        
         | imadr wrote:
         | How far into algebra do you need to get to understand
         | "Rotations of 3-dimensional real space form the topological
         | group SO(3)"? I kinda understand that norm-1 quaternions map to
         | rotations in 3D space somehow but I can't prove it myself. What
         | kind of curriculum do I need to follow to really grasp this?
        
           | gspr wrote:
           | To understand the definitions and apply them in practice, a
           | first course in group theory + a basic understanding of
           | vector calculus suffices. To add the adjective "topology",
           | the first parts of a general topology course is enough.
           | 
           | To truly appreciate groups like SO(3), a course in
           | differential geometry and differential topology is useful.
           | 
           | Edit: This is all assuming you have no background in
           | mathematics (or, alternatively, physics) at all. If you do, a
           | targeted text can teach you these concepts in a few pages.
        
             | billfruit wrote:
             | The thing is group theory is taught in an incredibly
             | abstract manner, its hard to find any motivating
             | application for it, or any problems it helps us solve.
             | 
             | Also terminology/definitions are vague too, whether a
             | vector has an endpoint or it something unachored in space
             | is itself not clear from many treatments.
        
               | swiley wrote:
               | That's an odd complaint to hear on a technology centered
               | forum.
               | 
               | The most obvious application for algebra should be
               | thinking about data structures with their operations. If
               | you can't be sure about a method on a class being valid
               | in terms of the contracts for that class (IE being a
               | closed operation) then the method can't be public
               | (usually an idea taught in "intro to OOP" style classes
               | although with other words unless you're reading something
               | like SICP.)
        
               | klodolph wrote:
               | Some of the motivating examples are hard to understand,
               | unfortunately. You can't do quantum mechanics without
               | group theory, and if you can't do quantum mechanics, it
               | will be much harder to understand how half the
               | instrumentation in your chemistry lab works.
        
               | gspr wrote:
               | > The thing is group theory is taught in an incredibly
               | abstract manner, its hard to find any motivating
               | application for it, or any problems it helps us solve.
               | 
               | Mathematics is abstractly defined. But for basic group
               | theory there's a plentitude of very concrete examples to
               | rely on.
               | 
               | > Also terminology/definitions are vague too,
               | 
               | Absolutely not. There is no vagueness at all! Everything
               | is completely well-defined in most introductory
               | textbooks/courses (or you can even read the precise
               | definitions on Wikipedia, which is often not the case).
               | 
               | > whether a vector has an endpoint or it something
               | unachored in space is itself not clear from many
               | treatments.
               | 
               | Vectors do not have endpoints. Vectors are not anchored.
               | Vectors are elements of vector spaces. Vector spaces are
               | completely clearly defined.
        
               | jcora wrote:
               | Sounds snarky but completely correct. Parent should look
               | for a more diverse set of examples for vector spaces. In
               | fact sounds like a good linear algebra course would be a
               | priority over group theory
        
               | immmmmm wrote:
               | it's actually more group representation theory you'll
               | need: the rotation group has an infinite number of
               | representations acting on different vectors spaces,
               | rotation of an electron in 3d is SU(2) which maps to
               | SO(3), the rotation of vectors.
        
           | meiji163 wrote:
           | You can get a very good intuition with 3B1B's video (
           | https://www.youtube.com/watch?v=zjMuIxRvygQ )
        
           | rikroots wrote:
           | I failed advanced math (UK A level) and dumped advanced
           | physics before reaching the point of taking the exams. I've
           | managed to implement a quaternion system in my canvas
           | library[1] - with nagging doubts that it's not entirely right
           | - mainly by staring at lots of (poorly explained) examples
           | online and hoping that things would click 'by osmosis'. So, I
           | reckon you can go a long way without understanding the
           | concepts behind quaternions, but you'll need to do a lot of
           | geometry and physics study if you ever want to feel
           | comfortable with any quaternion code you write.
           | 
           | The only reason I went through all that pain was because I
           | kept on coming across articles saying that "quaternions fix
           | the gimbal lock issue you encounter with Euler angles" - now
           | I see people saying in this thread that the assertion is
           | false. I no longer know what to believe, but I do know I
           | never want to go crawling down the Euler/quaternion rabbit
           | hole again!
           | 
           | [1] - https://scrawl-v8.rikweb.org.uk/docs/source/factory/qua
           | terni... - just looking at that code makes me wince!
        
           | jacobolus wrote:
           | Start by reading
           | http://geocalc.clas.asu.edu/pdf/OerstedMedalLecture.pdf
        
             | gspr wrote:
             | It's a good text, but the parent poster may wish to be made
             | aware that it's very physics-centric. If they do not come
             | at this from an interest in physics or a physics mindset,
             | it may be counterproductive.
        
         | blovescoffee wrote:
         | This is really interesting. Why does the failure of naive
         | parameterizations to form a cover imply a group with gimbal
         | lock? I'm unclear on how a cover is linked to gimbal lock.
         | 
         | I've taken undergrad topology and algebra if you could explain
         | in those terms (I understand what a covering is).
        
         | quietbritishjim wrote:
         | You're definitely right to bring up Gimbal lock [1]
         | 
         | One of the benefits of knowing about it is to know when it
         | _doesn 't_ matter to you. In that case, you can just use Euler
         | angles, as you say. If you just need to express a rotation in
         | terms of three angles, or convert back from three angles (e.g.
         | yaw/pitch/roll [2]) to a rotation matrix, then you don't need
         | to know about quartertonians at all.
         | 
         | [1] https://en.wikipedia.org/wiki/Gimbal_lock
         | 
         | [2] https://en.wikipedia.org/wiki/Aircraft_principal_axes
        
           | gspr wrote:
           | Even in this case you need to take care of the action of
           | rotations on points near the poles, don't you? (I don't
           | remember, it's been a long time since I did such
           | calculations).
           | 
           | But yes, otherwise I agree with you.
        
             | gilbetron wrote:
             | If you are going to apply 3 angles directly, then you run
             | into problems (specifically, if you pitch +/- 90 degrees,
             | then roll and yaw become the same thing, aka gimbal lock).
             | If you take those 3 angles and convert them to a matrix,
             | and use that matrix to apply the angles, you're all good.
             | You can then even take the new matrix and pull 3 angles out
             | of that.
        
               | toxik wrote:
               | ... and those three angles will be discontinuous at the
               | poles.
        
       | Jyaif wrote:
       | Most of the time you don't want to use his SLERP function. You
       | can even see what is wrong in his illustration video: the cube
       | does 3/4s of a full rotation, while only 1/4 of a full rotation
       | would have been sufficient. In other words, it's not always
       | taking the shortest path between 2 rotations.
       | 
       | If you are not careful, this is what you may end up with:
       | https://www.reddit.com/r/FIFA/comments/9gms3n/most_realistic...
        
         | imadr wrote:
         | What would be the alternative to slerp that takes the shortest
         | path?
        
           | edflsafoiewq wrote:
           | Just replace q2 with -q2 if q1 and q2 are in opposite
           | hemispheres, then slerp.
        
             | imadr wrote:
             | If I'm not wrong you check if q1 and q2 are in opposite
             | hemispheres with the sign of their dot product?
        
               | edflsafoiewq wrote:
               | Yes.
        
       | Scene_Cast2 wrote:
       | As a much more intuitive version of quaternions, there's
       | Geometric Algebra (aka Clifford Algebra). In 4D, the calculations
       | end up being the same, but there's much more intuition and
       | generalizability behind the Geometric version.
        
       | OmarShehata wrote:
       | This article incorrectly states that gimbal lock is a property of
       | Euler angles, and that using quaternions prevents it.
       | 
       | This is a common misconception.
       | 
       | Euler angles can be used to rotate an object exactly the same way
       | as quaternions do with no gimbal lock. Similarly, you can apply
       | quaternions in such a way that gimbal lock will happen (if you
       | wanted to represent a physical system of gimbals with
       | quaternions, where that is a physical property).
       | 
       | I wrote a short article demonstrating and clarifying this, hope
       | it helps: https://omar-shehata.medium.com/how-to-fix-gimbal-lock-
       | in-n-...
        
         | DecoPerson wrote:
         | I was hoping your article would example how gimbal lock can
         | occur with quaternions, but from a quick skim I can't see any
         | such paragraph.
         | 
         | Would you mind elaborating?
        
           | OmarShehata wrote:
           | It's at the bottom of the "What causes gimbal lock?" section,
           | the final code snippet:
           | 
           | ``` rotationAroundX = Quaternion.fromAxisAngle(angle1,
           | Xaxis); rotationAroundY = Quaternion.fromAxisAngle(angle2,
           | Yaxis); rotationAroundZ = Quaternion.fromAxisAngle(angle3,
           | Zaxis);
           | 
           | cubeRotation = rotationAroundX * rotationAroundY *
           | rotationAroundZ; ```
           | 
           | Basically, you store 3 quaternions, representing 3 angles,
           | and combine them to get the final rotation.
           | 
           | You might say "This is just quaternions emulating Euler
           | angles!" and my answer is, sure. You can say the same about
           | rotation matrices. There's nothing inherent about rotation
           | matrices that makes them susceptible to gimbal lock. You can
           | implement them as representing 3 fixed angles, thus gimbal
           | lock, or you can implement them as accumulating rotations,
           | thus no gimbal lock. Same is true of quaternions.
           | 
           | The fact that you can get gimbal lock with quaternions is a
           | feature, not a bug. Quaternions are just one way to describe
           | rotations. Gimbal lock is a natural phenomenon of certain
           | physical rotation systems, and can be described whether you
           | use quaternions, or matrices etc.
        
         | imadr wrote:
         | Thanks for the heads up, I'm going to rephrase the statement
         | about gimbal lock and link you article.
         | 
         | And just to be 100% sure, is the approach I'm using the right
         | one: storing a quaternion instead of 3 angles, multiplying,
         | overwriting the rotation value?
        
           | greggman3 wrote:
           | Something else to be aware of
           | 
           | http://number-
           | none.com/product/Understanding%20Slerp,%20Then...
        
           | OmarShehata wrote:
           | Yes, exactly!
           | 
           | And the idea is, _that's_ how you avoid gimbal lock. It's
           | that implementation of multiplying, and overwriting, which
           | can be done with any system that describes and applies
           | rotation, including Euler angles, rotation matrices, etc.
        
         | dahart wrote:
         | Similarly, slerp is also not a property of quaternions [1],
         | contrary to the claim in the article, and is usually _not_
         | implemented inside quaternion libraries using quaternion
         | exponentiation like the article does, but by computing angles
         | explicitly [2], for robustness I believe, and also because
         | slerp is designed for normalized quats, not for general quats
         | with non-unit magnitude.
         | 
         | With these two things combined - the two most commonly cited
         | reasons about why to use quaternions (using slerp and avoiding
         | gimbal lock) - what are other reasons to use quaternions? I'm
         | aware that there are moderate compute savings in some cases (a
         | matrix obviously has more degrees of freedom than a rigid
         | orientation). Are there other good reasons to deal in
         | quaternions? There are some reasonable ideas about why not to
         | use them. [3]
         | 
         | [1] https://en.wikipedia.org/wiki/Slerp#Geometric_Slerp
         | 
         | [2]
         | https://www.euclideanspace.com/maths/algebra/realNormedAlgeb...
         | 
         | [3] http://number-
         | none.com/product/Understanding%20Slerp,%20Then...
        
           | user-the-name wrote:
           | It is easier to deal with accumulating floating point when
           | using quaternions than when using matrices. Various other
           | operations are also quite easy to express in terms of
           | quaternions, such as swing/twist decomposition.
        
           | dllthomas wrote:
           | One reason to accumulate into quaternions vs a matrix is that
           | compounded errors can add scaling and shear to a rotation
           | matrix, whereas unit quaternions remain pure rotation (and
           | non-unit quaternions can be trivially normalized).
        
             | dahart wrote:
             | That's reasonable, but compound matrix ops can also re-
             | normalized and re-orthogonalized as they go, right? It's
             | easier with a quat, for sure, but does it make up for the
             | general complications with using quats?
        
               | user-the-name wrote:
               | I have not seen any complications of using quaternions
               | that would be anywhere near as big as the complications
               | of using any other approach.
        
               | dahart wrote:
               | That's why I posted an article that describes what the
               | complications are, reference number [3] above. It's
               | mainly a game-centric and people-centric view of problems
               | with quaternions, not a list of technical problems with
               | the representation. In short, many programmers don't
               | understand quaternions, so using them puts an education
               | burden on the team, a burden that is most frequently un-
               | met. Quats can be less efficient, if you're not paying
               | attention to what you're doing.
        
               | jacobolus wrote:
               | The part that is less efficient is applying a rotation to
               | a vector (you need to "sandwich multiply" by your
               | quaternion which involves 3x4 + 4x4 = 28 multiplications,
               | whereas with a matrix you only need 3x3 = 9
               | multiplications).
               | 
               | But composing, interpolating, exponentiating, etc. is a
               | lot nicer with quaternions. (Easier to reason about,
               | numerically better behaved, computationally cheaper.)
               | 
               | If you need to apply the same rotation to a large number
               | of separate vectors, keep your rotation representation as
               | a quaternion internally and convert to a matrix just
               | before vector rotation.
        
           | jackling wrote:
           | I believe that even though slerp isn't a property of
           | quaterions and can be retrieve without them, having your
           | orientation represented as a vector is a clean way for the
           | developer to hold the state of an orientation and interpolate
           | it. What's happening under the hood shouldn't matter much,
           | the abstraction in the code using quaterions makes it easier
           | for the developer to interpolate orientations without the
           | worry of gibal locking.
        
           | klodolph wrote:
           | > ...not implemented inside quaternion libraries using
           | quaternion exponentiation like the article does, but by
           | computing angles explicitly...
           | 
           | How else would you compute quaternion exponentiation? I don't
           | think there's really a dichotomy here. When you compute
           | quaternion exponentiation, one natural way to do it (as with
           | complex numbers) is to think of the quaternions as a real
           | magnitude multiplied by a phase. For complex numbers, the
           | magnitude grows according to exp(x) and the phase evolves
           | according to cos(x)+isin(x). This just falls out of Euler's
           | formula. If you know that the magnitude is 1, you take the
           | exp(x) term out, and you end up with a point that moves in a
           | circle.
           | 
           | The same thing applies to quaternions.
           | 
           | I'm aware that there are other ways to compute quaternion
           | exponentiation, but this is just a natural way to do it,
           | especially for people who aren't experts in numeric
           | programming.
        
             | dahart wrote:
             | The article's quat_pow is implemented using
             | 'quat_exp(quat_scale(quat_log(q), n));' where the code
             | example I posted computes the half-angle of the rotation.
             | If you stand back, I'd agree with you that there's an
             | equivalence here, and it could be argued that
             | Euclideanspace's code example is a kind of simplification
             | and flattening of using an exponentiation function. Still,
             | there are real differences between these two
             | implementations, and the article's here looks conceptually
             | simple, while the one people use in practice _looks_ more
             | complicated, and requires knowing how quaternions works. It
             | 's natural if you're fluent in quats, but not necessarily
             | intuitive otherwise.
        
               | klodolph wrote:
               | > If you stand back, I'd agree with you that there's an
               | equivalence here, and it could be argued that
               | Euclideanspace's code example is a kind of simplification
               | and flattening of using an exponentiation function.
               | 
               | You don't have to stand back that far! They're really
               | quite similar pieces of code.
               | 
               | quat_log() is basically a conversion to axis-angle.
               | quat_exp() is basically a conversion from axis-angle back
               | to quaternions. So, the quat_exp(t quat_log(x)) formula,
               | with different _names_ for the functions, is described
               | as:
               | 
               | 1. Figure out the angle between the starting and ending
               | position, and the axis of rotation.
               | 
               | 2. Vary the angle of rotation smoothly from t=0..1.
               | 
               | 3. Convert back from axis-angle to an orientation.
               | 
               | The only funny thing here is that the axis-angle encoding
               | of quaternions uses a magnitude which a factor of two
               | away from the angle in radians, so you'll see the sample
               | code you linked to (with SLERP) use variables like
               | "halfTheta" and "cosHalfTheta", where the quat_exp() and
               | quat_log() formulas simply _won 't name them that way._
               | 
               | In the end I think the point of learning more math is so
               | you can see past the differences in naming and recognize
               | when two _seemingly_ different approaches to the same
               | problem are really just two different sets of terminology
               | and names for the same approach.
        
               | dahart wrote:
               | You're right and it's a great point!
        
         | Ono-Sendai wrote:
         | If you want to represent different rotations as differential
         | Euler angles, then I think you can say it's a property of Euler
         | angles, or at least linked to them.
        
         | jayd16 wrote:
         | Are you simply saying that quaternions can be used to perform
         | the same rotation as the Euler method or are you saying that
         | the rotation information along the Euler axes can also be lost
         | even when using the quaternion method?
         | 
         | Said another way, are you conflating gimbal lock the physical
         | property, with gimbal lock the common bug of creating
         | irreversible rotations or is the bug still possible?
        
         | hanche wrote:
         | Here's an abstract view regarding the inevitability of gimbal
         | lock: The state of a single gimbal is described by an angle.
         | Since angles are mod 360deg, that is topologically a circle.
         | The state of three gimbals are then given by three angles. One
         | point on each of three circles is a point on a three-
         | dimensional torus T^3. With no gimbal lock, you get a map from
         | T^3 to SO(3), which is locally a diffeomorphism at every point.
         | For topological reasons, no such map exists: Due to
         | compactness, it would be a cover, but the only covers of SO(3)
         | are SO(3) itself (a single cover) and the three-sphere (unit
         | quaternions, a double cover). And T^3 is distinct from either
         | of these two. Hence gimbal lock is unavoidable with three
         | gimbals. (Four gimbals is a different story, but then you have
         | a redundant dimension to play with.)
        
           | anon_tor_12345 wrote:
           | lol i'm a dummy for never realizing that SO(3) isn't
           | homeomorphic (the diffeo part isn't necessary to prove
           | this...) to T^3 (which i naively thought because s in SO(3)
           | seemingly has 3 free parameters). surprise surprise SO(3) is
           | actually homeomorphic to P^3 lol.
        
             | hanche wrote:
             | You can drop "seemingly": SO(3) is indeed tree-dimensional.
             | And SO(3) a.k.a. P^3 has fundamental group Z_2 a.k.a.
             | GF(2), whereas T^3 has fundamental group Z^3, so they are
             | quite different beasts indeed.
        
         | benrbray wrote:
         | Howdy 4ur :) Nice article, I'm pretty sure I got dinged once
         | for making this point in a job interview, so good to see you
         | spreading the word.
        
           | OmarShehata wrote:
           | Oh hey!! Always a pleasure running into familiar faces from
           | NG out in the wild :)
           | 
           | And that's funny...I had the exact same experience in a job
           | interview...which gave me the extra motivation I needed to
           | finally write that up!
        
         | IshKebab wrote:
         | Great article. Presumably the reason this confusing exists
         | exists is that people don't want to store full rotation
         | matrices, so their choices are Euler angles or quaternions, and
         | Euler angles _guarantee_ gimbal lock by quaternions allow you
         | to avoid it. Is that right?
        
         | zemnmez wrote:
         | I'm so confused. The article you wrote says that you fix gimbal
         | lock by using quaternion rotation, quote:
         | 
         | >To fix gimbal lock, we must avoid modelling this physical
         | gimbal system.
         | 
         | > In 3D, instead of using 3 fixed angles that we multiply
         | together to get the final rotation, we will:
         | 
         | > 1. Construct a quaternion that describes a rotation around
         | whatever axis we want, and the angle to rotate by.
        
       | rthomas6 wrote:
       | As a non-math person, I've thought a lot about quaternions and
       | why they need 4 dimensions, and why there aren't 3d complex
       | numbers. It's because if you think about it, on the complex
       | plane, the imaginary number i just represents a rotation of 90
       | degrees. Now if you think about a 3d space, i represents a
       | rotation across one dimension, and j represents a rotation across
       | another dimension. But how do you rotate from i to j? You can't
       | without another number k.
        
         | hanche wrote:
         | Hamilton famously had the same problem before he came up with
         | the quaternions.
        
       | [deleted]
        
       | imadr wrote:
       | I made this guide on how to implement quaternions yourself and
       | use them to rotate objects in a 3D engine. The implementation is
       | probably not the most efficient, but I tried to make it simple
       | enough to understand how quaternions work.
        
         | KboPAacDA3 wrote:
         | Thank you for making this and getting straight to the useful
         | code. Too often, guides on quaternions stray into proofs and
         | waste time for a programmer who just wants to apply the
         | quaternion concept.
        
       | darkstarsys wrote:
       | This is good, thanks. But a much more interesting problem I
       | haven't seen a good writeup for is how to interpolate smoothly
       | between quaternions at different times. Quaternion slerp has
       | jerks (C_0 but not C_1 or C_2) at the keyframes.
        
         | dahart wrote:
         | Ken Shoemake's 1985 Siggraph paper "Animation Rotation with
         | Quaternion Curves", that brought quaternions to computer
         | graphics, covered this. The idea is to use quaternions as
         | control points in a spline the same way you would use 3d points
         | in a spline. You could have a series of quaternion
         | orientations, and connect them with C_2 continuity by using a
         | connected series of piecewise cubic Bezier splines.
         | 
         | The abstract mentions it: "This paper gives one answer by
         | presenting a new kind of spline curve, created on a sphere,
         | suitable for smoothly in-hetweening (i.e. interpolating)
         | sequences of arbitrary rotations." And the final punch line is
         | section 4.3, then you can work through the details in the
         | earlier sections.
         | 
         | https://www.cs.cmu.edu/~kiranb/animation/p245-shoemake.pdf
        
         | gilbetron wrote:
         | It's been a while for me, but iirc, there's two ways you can
         | slerp between two quaternions, and by using the shortest path,
         | you can avoid the jerk.
        
         | chombier wrote:
         | I've used "A General Construction Scheme for Unit Quaternion
         | Curveswith Simple High Order Derivatives" in the past, and
         | while not perfect it was generally good enough and fairly easy
         | to implement.
         | 
         | Basically it extends Hermite splines to Quaternion splines
         | using the Lie group operations.
        
       | aardvark179 wrote:
       | Since this will get posted here anyway I'll just get it done now.
       | https://marctenbosch.com/quaternions/
       | 
       | I don't entirely agree with the article's viewpoint that people
       | do not perfectly understand quaternions and therefore they should
       | not be used, as I get the feeling there are many parts of 3D
       | graphics that are not perfectly understood by developers, and
       | that's okay.
        
         | marosgrego wrote:
         | The Geometric Algebra viewpoint is much nicer, more natural and
         | encompasses more.
        
       | ww520 wrote:
       | Quaternion is great for dealing with 3D rotation. Another great
       | approach is using the rotor in geometric algebra. It's pretty
       | simple and it works on rotation in dimensions higher than 3D as
       | well.
        
       | sojuz151 wrote:
       | Small trivia: Existence of two unit quaternions corresponding to
       | the same rotation is the same thing as the fact that an electron
       | must be fully rotated twice before it has the same configuration
       | as when it started.
        
         | marosgrego wrote:
         | How?
        
       | unholiness wrote:
       | If you want to intuitively understand _why_ this particular 4D
       | construction is the right representation of a 3D rotation, then I
       | highly recommend 3blue1brown 's explorable interactive video
       | series on the topic:
       | 
       | https://eater.net/quaternions
       | 
       | The interactive videos alone are quite the technical feat, but
       | after going through it, it's honestly hard to imagine fully
       | understanding this topic with less technology (or with a less
       | incredible teacher!)
        
         | nighthawk454 wrote:
         | In particular, that toggle switch to show it in terms of an
         | angle makes it super clear.
         | 
         | The 4 components can be re-written in terms of 3 variables for
         | an orientation vector and 1 variable for rotation about that
         | axis. Basically "point this way and rotate this much". The 4
         | variables are expressed as two complex numbers.
         | 
         | That helped me understand what the quaternions are actually
         | describing. Incidentally, it also kind of explains why 3
         | variables isn't enough, and so the regular rotation thing must
         | not be sufficient.
        
       | dnautics wrote:
       | am I wrong that this use of a union is UB in C?
        
         | imadr wrote:
         | I'm absolutely not a pro in C, so if it is undefined behaviour
         | I'd be glad to know and fix it, I just found out about the
         | notation and it looks handy
        
           | dnautics wrote:
           | checked myself. My cursory, poor search suggests it's UB in
           | C++, but not in C?
        
             | steerablesafe wrote:
             | It is definitely UB in C++ and probably implementation
             | defined in C (and this use is fine all implementations,
             | AFAIK). Some C++ implementations allow this as a conforming
             | language extension.
        
               | dnautics wrote:
               | thanks for clarifying!
        
       | rdevsrex wrote:
       | There was a post about Geometric Algebra, a while back. Is that
       | more in use these days?
        
         | Jenz wrote:
         | Was hoping to see some discussion on this too.
        
         | Syzygies wrote:
         | In "Further Reading" the article links to [Let's remove
         | Quaternions from every 3D
         | Engine](https://marctenbosch.com/quaternions/) which is about
         | Geometric Algebra.
         | 
         | Many chefs are brilliant, but only Jeremiah Tower's book covers
         | will tell you he's brilliant. Many branches of mathematics are
         | of great utility. Geometric Algebra will breathlessly tell you
         | this. I know few fields quite so evangelical.
         | 
         | If you don't know better, you should use quaternions rather
         | than matrices. If you don't know better, stick with quaternions
         | and avoid the generalization presented by Geometric Algebra
         | until the benefit is clear.
         | 
         | This tension is probably why the field is so evangelical.
         | 
         | Quaternions are inevitable. In ten thousand runs of the
         | simulation, sentient beings would come up with quaternions
         | every time. Geometric Algebra is not so inevitable. An
         | aesthetic awareness of the centrality of ideas guides some but
         | not all mathematicians. Like that famous quote about taking an
         | instant dislike to Ted Cruz, it saves time.
        
       | frankus wrote:
       | Sort of unrelated but I wonder if this could make certain kinds
       | of latitude/longitude calculations easier.
        
         | jacobolus wrote:
         | If you are dealing with a sphere, is much easier to work with
         | pure vector methods than with classical spherical trigonometry.
         | 
         | If you are dealing with an ellipsoid of revolution, then vector
         | methods can also get tricky.
        
       | neonological wrote:
       | Guys I work at a company that uses Quaternions for rotations of
       | physical objects. PTUs we call them (Pan Tilt Units).
       | 
       | I am telling you Quaternions have HUGE issues. These issues
       | become much more apparent when you deal with physical objects.
       | 
       | Here's the thing Quaternions don't exist in reality. It
       | represents an orientation of rotation but it completely masks the
       | path took to achieve that orientation.
       | 
       | For every gimbal in reality there is an actual YawPitchRoll (YPR)
       | that was executed to achieve that orientation. AS soon as you
       | convert that real YPR into a Quaternion you lose the YPR that was
       | needed to achieve that orienation.
       | 
       | So let's say I need to have one gimbal imitate the position of
       | another gimbal. I take the YPR given to me by gimbal "A" convert
       | the YPR to a Quat, send that Quat over the wire to Gimbal "B" and
       | convert that Quat back to YPR to feed to the gimbal so it can
       | rotate itself to imitate the orientation of gimbal A.
       | 
       | The quat is a higher entropy form of information. Now when
       | converting back to YPR there are MULTIPLE YPRs that yield the
       | same orientation. You can derive a YPR that is out of bounds of
       | the physical gimbal.
       | 
       | Literally you can get a YPR that tells your gimbal to Yaw 190 and
       | pitch all the way back past 90 to 170 degrees and roll 180
       | degrees until it's right side up. This YPR is identical to a yaw
       | of 10, a pitch of 20 and 0 roll. Quaternions hide the original
       | YPR, you lose information so when you receive a Quaternion it's
       | hard to translate it into a physical realization of the
       | orientation.
       | 
       | The company I work for doesn't realize this. They used
       | Quaternions from day one and we have all kinds of headaches like
       | this when we try to extract the YPR and use these orientations in
       | the real world. Actually I should say only I have these
       | headaches. A lot of people haven't figured out this problem yet.
       | 
       | The only time you should use Quats are if you need to transform
       | an orientation or you're dealing with virtual objects that have
       | no rotational limits. Everybody thinks quats are magic and
       | better. They are not. They have huge downsides. Huge.
        
         | edflsafoiewq wrote:
         | Interesting to read about experience with a physical gimble,
         | thanks. In this case the "problems" of Euler angles are
         | actually an accurate model of the problem space.
        
         | dakr wrote:
         | This real hardware handles quaternions just fine:
         | https://en.wikipedia.org/wiki/Stratospheric_Observatory_for_...
        
           | neonological wrote:
           | I'm sure it does, I'll give you the benefit of the doubt even
           | though the article makes no mention of Quaternions. My point
           | is, using Quaternions for physical devices is using a hammer
           | on a screw. Huge mistake, but it can be done by people who
           | don't know any better. I'm guessing you worked on this and
           | bought in to the whole Quaternion BS?
           | 
           | I'm in the defense industry as well and guess what? Basically
           | most people don't know any better.
        
         | phkahler wrote:
         | >> For every gimbal in reality there is an actual YawPitchRoll
         | (YPR) that was executed to achieve that orientation. AS soon as
         | you convert that real YPR into a Quaternion you lose the YPR
         | that was needed to achieve that orienation.
         | 
         | I would say you obscure it. You can certainly calculate it from
         | the 4 quaternion parameters.
         | 
         | SolveSpace (Free CAD software) can be used to design assemblies
         | and mechanisms from a set of parts with constraints. You can
         | certainly build a gimbal with it by constraining the pieces. If
         | you do it correctly, it will be possible to re-orient the final
         | 3DoF part and the constraint solver will solve for the angles
         | (assuming you built it that way).
         | 
         | Internally we treat all object orientations as quaternions, so
         | this would just be using the algebraic constraint solver to
         | find the angles. In practice there will be closed form
         | solutions - with problems at gimbal lock.
        
           | neonological wrote:
           | >I would say you obscure it. You can certainly calculate it
           | from the 4 quaternion parameters.
           | 
           | No it is an actual information loss.
           | 
           | There are multiple valid YPR solutions like my example
           | illustrated.
           | 
           | There is NO way to determine which YPR out of the multiple
           | possibilities was the original solution.
           | 
           | Something like solve space can only determine the original
           | YPR with additional assumptions or the original YPR still
           | referenced in memory.
        
       | marcodiego wrote:
       | tldr: Simply explained without demonstrations: Quaternions are
       | hypercomplex numbers of the form
       | 
       | w + x _i + y_ j + z _k
       | 
       | Where w, x, y, and z are real and i^2 = j^2 = k^2 = -1 and i_j =
       | k, j _i = -k, j_ k = i, k _j = -i, k_ i = j, i _k = -j.
       | 
       | Being u = (x, y, z) = x_i + y _j + z_ k a unitary vector parallel
       | to a rotation axis, it is possible rotate any vector q with a
       | theta arc around u by doing:
       | 
       | p _q_ p'
       | 
       | where p = cos(theta/2) + sin(theta/2) _u and p ' = cos(theta/2) -
       | sin(theta/2)_u .
        
       ___________________________________________________________________
       (page generated 2021-06-01 23:01 UTC)