Rotations with quaternions
imadr.github.io
imadr.github.io
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.
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.
But yes, otherwise I agree with you.
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.
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.
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.
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.
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.
Ehh.... compare this text from the wikipedia article on affine spaces:
> In an affine space, there is no distinguished point that serves as an origin. Hence, no vector has a fixed origin and no vector can be uniquely associated to a point. In an affine space, there are instead displacement vectors, also called translation vectors or simply translations, between two points of the space.
If you're working with vectors, you're generally working with them as points, not as values that happen to obey the axioms defining a vector space. Those vectors are anchored, and the anchoring is so deeply embedded in the concept that there's a separate concept, affine spaces, specifically devoted to the question of "what if we had things that were like vectors, except without being anchored to a particular point in space?"
I swept a detail under the rug, which is that the vectors are infinitesimal arrows, so their tip is not actually another point of the manifold. In an affine space, vectors can be regarded as non-infinitesimal arrows -- the arrows that you always find textbook illustrations on vector arithmetic. The arrows with a common root form a vector space.
It's interesting to think about how we came to the modern viewpoint. Some of the underlying context behind my comment is that long ago manifolds were concretely subsets of R^n that could be locally parameterized. The tangent space at a point was the affine subspace of R^n that was tangent to the manifold there, and you could regard a tangent vector as an arrow rooted at that point inside that subspace. Even though we have our clean modern notion of an abstract vector space, somehow these old intuitions linger on in other disciplines
In math we have a precise definition for a vector (an element of a vector space, full stop), but I don't think experts have the authority to be prescriptive about jargon outside their discipline. Of course, a student should be willing to drop preconceptions and to absorb correct usage.
I personally don't consider functions or polynomials to be "anchored", but yes, of course there is the zero polynomial etc.
Also, keep in mind that physicists, for example, often use a more restricted definition of "vector" than mathematicians. That Wikipedia definition you quoted doesn't strike me as very mathematical. A mathematician's definition of an affine space is much more abstract.
Of course it is. I'm sure there are instances where it isn't, but it also mostly is.
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.)
And that’s a shame, because a lot of group theory originated in concrete, tangible problems. Check out the book Visual Group Theory by Nathan Carter, discussed (a bit) here:
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/quaterni... - just looking at that code makes me wince!
Nevertheless, I think it's still a good and important idea to work things out concretely a few times and for that all you really need is linear algebra.
That said, the concrete version of your statement is as follows:
SO(3) is best defined as the group of all rotations in 3 space. You then show that this is just all 3x3 matrices that are orthogonal (their transpose is the inverse) and have determinant 1.
You can do this by abstract linearity arguments (e.g. the rotation of a vector times a scalar is the scalar times the rotation of the vector) or by directly writing things out with linear algebra.
The first ingredient is to realize that the rotation in the plane by angle t is a linear map of the plane to itself, and can be represented by matrix multiplication and thus a square 2x2 matrix which sends
(1, 0) to (cos(t), sin(t))
and
(0, 1) to (-sin(t), cos(t)).
Thus the matrix is
[cos(t), -sin(t)]
[sin(t), cos(t)]
this matrix clearly has determinant = 1 and you can verify that the transpose is the inverse. But you could have derived this from general principles that rotations are volume and orientation preserving.
Now a rotation in 3 space must fix some line and then is just a planar rotation for the plane perpendicular to the line. So you can pick a new basis in 3 space corresponding to the line, v, and then two orthonormal unit vectors so that the rotation is just the matrix
[1 0 0]
[0 cos(t) -sin(t)]
[0 sin(t), cos(t)]
for some choice of unit vector v and some angle t. Here you should realize that you need an orientation. E.g. the plane perpendicular to v is the same plane as is perpendicular to -v, but you need an orientation on the plane to figure out the direction of rotation.
Already this should tell you that SO(3) is three dimensional and you have a parametrization of (most of) SO(3) as a point on a sphere together with an angle, so it's kinda like S^2xS^1, except the parametrization breaks down when the angle is pi as you get the same rotation if you pick anti-podal directions and when the angle is zero all the points on the sphere map to the same (identity) rotation. So this parametrization is not a diffeomorphism, it's not even 1 to 1, but it is surjective, and knowing exactly how it fails to be 1 to 1 allows you to understand SO(3) completely because you can think of SO(3) as S^2xS^1 with some points identified.
All of the above relies solely the basics of linear algebra such as what you usually get in a multi-variable calculus course. You don't even need stuff like Jordan decomposition or other more advanced linear algebra topics, just the definition of linear maps, the definition of a "rotation" in 3 space, ideas of orthogonality and the determinant being an oriented volume of a linear map. Most of these concepts are taught in multi-variable calculus as you need them to get volume forms as the result of a change of basis when you are doing integrals over surfaces and volumes.
In terms of 'topological group", the set of matrices with determinant 1 that are orthogonal form a group, as is easily verified via the fact that det(A*B) = det(A)det(B) and det(A^t) = det(A). That is all you need to show that this is a group. It is a topological group in the sense that the multiplication operation is continuous in the inherited norm you expect to get on matrices. E.g. if you write out the multiplication of matrices with the entries being variables you just get polynomials in the product of the two matrices so multiplication is a continuous operation.
When you are working at the elementary level, you don't care too much about whether the matrices are topological groups because you are not going to be using the heavy duty Lie theory machinery, you can write everything out in terms of matrices and maps between them explicitly. It's really good to write things out explicitly a few times and then learn all the abstract stuff because it helps you understand what the general results are really saying. Do not be intimated by people using terms like "universal cover", homotopy, classifying spaces, etc, as you don't need any of that to understand the basic properties of quaternions and the orthogonal groups, but these abstractions have shown to be an very useful way of looking at these spaces so they can help explain what is happening in a deeper way than relying on matrix algebra once you get to the point where you are searching for unifying ideas behind these results. The results themselves can always be proved with elementary techniques.
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.
Real number under addition are isomorphic¹ to positive real number under multiplication. Yet they are not the same objects.
1- The mapping is f(x)=e^x. See https://math.stackexchange.com/questions/573794/prove-that-m... for the proof
Euler angles are fugly and annoying. Quarternions are clean and refreshing.
I've taken undergrad topology and algebra if you could explain in those terms (I understand what a covering is).
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-...
Would you mind elaborating?
``` 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.
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?
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.
http://number-none.com/product/Understanding%20Slerp,%20Then...
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!
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...
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.
Also, it is not really interesting what matrices or quaternions "can do". What is interesting is what we can do with them. And quaternions make a lot of things possible that are intractable or at least a huge pain with matrices.
Yes, that was my point, that what you can do with quats is a strict subset of what you can do with 4x4 mats. Not sure what you thought I meant.
> quaternions make a lot of things possible that are intractable
Such as?
Certainly, but as you say it's a bit harder.
> does it make up for the general complications with using quats?
I'm sure that's context dependent, and don't have much of an opinion which way it's likely to break in general. I was just throwing something in the "pro" column that hadn't yet been discussed.
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.
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.
>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.
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?
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.
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).
> 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.
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.
http://motion.pratt.duke.edu/RoboticSystems/3DRotations.html
If you are not careful, this is what you may end up with: https://www.reddit.com/r/FIFA/comments/9gms3n/most_realistic...
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...
I mean, papers have been written about sqrt(a^2+b^2) alone… :-)
return hypot(hypot(q.w, q.x), hypot(q.y, q.z));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!)
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.
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.
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.
Basically it extends Hermite splines to Quaternion splines using the Lie group operations.
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.
If you are dealing with an ellipsoid of revolution, then vector methods can also get tricky.
w + xi + yj + zk
Where w, x, y, and z are real and i^2 = j^2 = k^2 = -1 and ij = k, ji = -k, jk = i, kj = -i, ki = j, ik = -j.
Being u = (x, y, z) = xi + yj + zk a unitary vector parallel to a rotation axis, it is possible rotate any vector q with a theta arc around u by doing:
pqp'
where p = cos(theta/2) + sin(theta/2)u and p' = cos(theta/2) - sin(theta/2)u .
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.
I'm in the defense industry as well and guess what? Basically most people don't know any better.
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.
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.
A quick Google search even turns up a Wikipedia entry on this problem: https://en.wikipedia.org/wiki/Conversion_between_quaternions...
If you really need this problem solve I might know someone willing to do paid consulting on it.
The formula for conversion from quat to ypr involves arctan and arcsin. These functions yield multiple answers.
Additionally your own Wikipedia link explicitly states the existence of multiple answers, and that traditionally atan and asin in programming languages yield only one answer. I quote:
"Note, however, that the arctan and arcsin functions implemented in computer languages only produce results between −π/2 and π/2, and for three rotations between −π/2 and π/2 one does not obtain all possible orientations. To generate all the orientations one needs to replace the arctan functions in computer code by atan2"
Either way you misunderstand the math behind quaternions and you lack a basic grasp of trigonometry. Assuming you read your own Wikipedia link, what I said is categorically true.
If you really need education in math and how to properly do trigonometry I will help you solve this problem for free. Just ask me questions. I'm super nice and won't go around fraudulently espousing an expertise in math and demanding people pay me to solve trivial math problems.
Frankly you are not even qualified to solve the problem yourself or give me a recommendation.
Especially when this problem is basically impossible to solve. I'll give you 10 thousand dollars if you can give me a quaternion that doesn't have multiple yprs here on HN. Literally, give me your venmo.
>Nope. The only thing you need to specify is the order the YPR angles are applied (that more a convention than an assumption). In SolveSpace the assembly constraints would effectively encode the order of application.
The term "yaw pitch roll" ALREADY has the order of the Euler angles applied. Let me tell you that order, it's: yaw, pitch and then roll.
Ypr is different from straight up Euler angles in that ypr has order fixed; hence the term "ypr"
With the order of angles fixed you still get multiple answers for a single quaternion. Why don't you try it in 3D space in your own head. Given A rotational orientation in 3D, find at least two yprs needed to arrive there.
Here maybe this will help you: a ypr of (0,0,0) is the same as a ypr of (180, 180, 180). These two yprs can only be represented by a single quat. Think about it. Given only a quat you cannot determine which ypr was used by the physical gimbal to realize this orientation. For solve space to know it must be making assumptions or holding onto information outside of the quat.
There free education for you and I didn't even ask you for a dime.
However, how the Ypr was picked by the hardware must be explicitly encoded as an assumption that must be part of every conversion from quat to ypr that happens downstream.
Compressing it all into one orientation may work for some use cases, but generally one should not expect that. Similarily one wouldn't try to represent all of the axes of a KuKa arm robot with just one orientation. You need info about the individual axes when you want to control it.
Your company can still use quaternions to represent the rotations of each axis, tho. Might help in convincing them going forward, as they don't have to let go of them (they are good fellas actually).
I don't understand this can you elaborate? My company does indeed use motorized pan tilt units.
As said before you still want to retain the actual angles somewhere.
Depending on your physical configuration one of the Euler angle variants (Tait–Bryan angles is another term to search for) could perfectly describe your case and you could just use these to store the angles. Euler angles can also be converted to quaternion. But you can't recover the original used angles from the quaternion alone because of the 2pi wrapping of angles.
For others still wondering why quaternion or orientation alone won't suffice, here is a different example: Imagine an axis which can rotate more than only one revolution, i.e. can have angles like 4 pi, for example motorized volume knobs. An orientation alone can't represent that as it wraps the angles to 2pi. User manually turns the knob to two full revolutions (4pi) and then increases the value by remote control, which results in motorized knob to rotate. Should the knob turn back to nearly zero revolutions (rotate back 4pi) plus the increase? No, it should rotate to 4pi+increase.
By the way, when you have internally stored the "multi revolution" angle and have a sensor reading in range [0..2pi[ you can recover an multi revolution angle equivalent to the sensor reading with wrapToPiSeq( angle in radians before, sensor reading).
# to equivalent angle in [0,2pi[ range
def wrapTo2Pi(rad):
return rad % (2*pi)
# to equivalent angle in ]-pi,pi] range
def wrapToPi(rad):
return wrapTo2Pi(rad + pi) - pi
# angle difference between rad0 and rad1, in range ]-pi,pi]
def angleDiff(rad0, rad1):
r0 = wrapToPi(rad0)
r1 = wrapToPi(rad1)
return wrapToPi(r1-r0)
# rad1 to equivalent angle so the jump from rad0won't be greater than |PI|
def wrapToPiSeq(rad0, rad1):
r0 = wrapToPi(rad0)
r1 = wrapToPi(rad1)
diff = wrapToPi(r1-r0)
return rad0+diffBut doesn't that magnify the problem by 3x? Extracting the angle from the quat again can yield multiple possibilities. If you have 3 quats you now have 3x more possibilities. This can only be done if you assume certain restrictions for each quat such that they yield a singular axis angle when you do a back conversion.
Additionally doesn't that technique yield more possibility to encode axises that are incorrect? A quaternion representing the x axis can be accidentally encoded with rotations along other axises. It's better to keep the type of your domain restricted to be able to encode only possible answers.
Still this can be done as a valid-ish workaround. I give you credit for that, I wouldn't of thought of this so thanks for ur explanation. Although I might use this idea it is far from ideal imo because of the problems I mentioned above. That is if I interpreted what you're saying correctly?
Also addressing your example, the bigger problem in my mind is that there are still issues that arise even if the physical gimbal is restricted on all axises to (0, 2pi). Any gimbal that can go 4pi likely can go infinite pi and that knob will likely be the same so losing rotational information greater than 2pi is ok for most cases in my mind. (If the system yawed 790pi, users are usually only interested in some value under 2pi). The insidious thing imo, is that information is lost even in (0, 2pi) and a lot of people don't realize this.
Represent your axes with the actual angles. These probably correspond to motor position or revolutions.
Use the quaternions only when you want an orientation for these angles.
Maybe you want to know in which direction the PTU is pointing for a particular set of motor positions, or axis angles. Compute the kinematic chain by multiplying the quaternions corresponding to each axis in the order they are physically applied, but multiply from right to left. Your final result is one quaternion representing the direction the PTU is pointing at. (You could also use 3x3 matrices or other representations) Depending on your physical configuration one of the Euler angle variants (Tait–Bryan angles is another term to search for) could perfectly describe your case and you could just use these to store the angles and compute the orientation.
If you don't actually need the final orientation, then you can omit the quaternions altogether.
If you have orientations as input and need to control the motors so the PTUs are pointing in the required direction: I would compute the current orientation of the PTU. Then compute a trajectory of quaternions interpolating from the current orientation to the target orientation (use quaternion slerp for interpolation). Then at each timestep you compute the required motor positions using inverse kinematics [1].
It is a common problem that multiple motor positions are possible and actually an unfinished research problem. Now that I wrote this, I think this might be the problem you are encountering.
For PTU I think it would be ok to try to recover the current target angles from the target quaternions of the trajectory using one of the Euler configurations. There are papers [2] listing all together, so one can try which is correct. Having a configuration chosen there is still the problem of multiple solutions. In this case use the one closest to the actual current angles. For cases when all angles are possible for an axis, use the current angle as target (i.e. motor doesn't change). When you then have an target angle use `wrapToPiSeq` to get an equivalent angle close the current actual angle as input for the motor controller.
[1] https://en.wikipedia.org/wiki/Inverse_kinematics In computer animation and robotics, inverse kinematics is the mathematical process of calculating the variable joint parameters needed to place the end of a kinematic chain, such as a robot manipulator or animation character's skeleton, in a given position and orientation relative to the start of the chain.
[2] In the past I used this (but be careful in which direction they apply the transformations, I stumbled over this): Diebel, J. (2006). Representing attitude: Euler angles, unit quaternions, and rotation vectors. Matrix, 58(15-16), 1-35. https://www.astro.rug.nl/software/kapteyn/_downloads/fa29752...
Yeah that's how I solved this issue. But still if we avoided quaternions we wouldn't have this problem all together, which is my point.
Specifically what's going on is that we're sending quaternion values over the network and the person on the receiving end needs YPR so we're basically like wtf, there's no transformations being performed on the quat, the source of info is a YPR and the output is needed is the same exact YPR so we're only converting to a company wide Quat Protobuf type to send over the wire. I submitted a request to make a new protobuf type that included YPR but I was met with huge company resistance from other engineers saying that a YPR was redundant to a Quat (It's not).
>In computer animation and robotics, inverse kinematics is the mathematical process of calculating the variable joint parameters needed to place the end of a kinematic chain, such as a robot manipulator or animation character's skeleton, in a given position and orientation relative to the start of the chain.
Interesting, but yeah the application in my company is just a single gimbal so there's no chain of "joints" here. I don't think this would apply to our my specific case.
>https://www.astro.rug.nl/software/kapteyn/_downloads/fa29752...
Thanks for all your input. I'll take a look at the link above, it looks interesting.