Quaternions are bad, mkay?

Started by
20 comments, last by Charles B 19 years, 6 months ago
i was paying around with storing 2D rotations as complex numbers, for no other real reason than to see how it would work. however, i came to the conclusion they were not a good method to store rotation SPEEDS in. orientations, fine, but not speeds. you may think: so what? but the same goes for quaternions. think about it: there are endless rotations that result in the change of rotation specified by a quaternion or complex number or matrix. most of the time this isnt important, but when the path from the previous state to the new one IS important, for example when interpolating, quaternions do a poor job. you simply cant specify rotations larger than 180 deg, since they would be interpreted as a rotation the other way. axis-angle is really the only correct way to store rotationspeeds if youre strict about it.
Advertisement
i've always thought rotation speeds are storen in vector(i mean 3D vector) (without any angle) .... and in 2D , in scalar.
Interpolation is not exactly dealing with speeds.
Quote:Original post by Dmytry
i've always thought rotation speeds are storen in vector(i mean 3D vector) (without any angle) .... and in 2D , in scalar.

both are axis-angle tho.

in case of 2d the axis is implicit (z), and in the 3d case you speak of the angle is stored in the length of the vector. however, its often more convenient to store this as a seperate value, and keep the vector itself normalized.

Quote:
Interpolation is not exactly dealing with speeds.

strange, i thought the term interpolation was pretty broad, and can be applied to virtually everything.

yes indeed in the case of quaternion-quaternion interpolation people are often talking about orientation-interpolations. thats because they try to work around the nastyness that is raising quaternions to powers in order to do what actually makes sense: interpolating speeds to evaluate a state at a given time.

however, the real solution is not using quaternions at all for rotation speeds, since theyre not really well suited for the job, considering interpolation (which is nasty, especially compared to to axis-angle) aswell as in specifying rotationsspeeds of more than 180 deg/sec, which they cant do at all.

however, quaternions in 3d or complex number in 2d are very well suited for storing orientation information. if you try to use axis-angle for that youll run into a whole other set of problems. the point, which i kind of failed to make in my above post, is that a good engine should apply both axis angle and quaternions for the right job: something ive never seen done actually.
Quote:Original post by Eelco
i was paying around with storing 2D rotations as complex numbers, for no other real reason than to see how it would work. however, i came to the conclusion they were not a good method to store rotation SPEEDS in. orientations, fine, but not speeds.


Yes, rotation speed has only one linear dimension. If you are using complex numbers you get something like

dz/dt = iwz

Where w is the angular speed, z = x + iy the complex 2D position.

Quote:Original post by Eelco
you may think: so what? but the same goes for quaternions. ...


The formula for quaternions is very similar, i.e.

dq/dt = 0.5 * wq

where q is the quaternion and the 0.5 arises from the fact that you need two copies of q when rotating, i.e. using v' = qvq*

w is a purely imaginary quaternion, i.e. one with it's real part equal to zero. If it's thought of as a vector then it's usually called the "angular velocity vector" but you have to remember it's really a quaternion. As a vector it's magnitude is usually associated with the speed of rotation while it's direction is the same as the instantaneous angle of rotation - in general w is not constant.

'Angle axis' is sometimes proposed as an alternative to quaternions for 3D rotaations but it's far less efficient.

And the problem with interpolating quaternions going 'the wrong way' is easily solved, and even with the cost of the check to avoid this problem quaternion interpolation is by far the best way to interpolate quaternions.
John BlackburneProgrammer, The Pitbull Syndicate
Quote:Original post by johnb
Quote:Original post by Eelco
i was paying around with storing 2D rotations as complex numbers, for no other real reason than to see how it would work. however, i came to the conclusion they were not a good method to store rotation SPEEDS in. orientations, fine, but not speeds.


Yes, rotation speed has only one linear dimension. If you are using complex numbers you get something like

dz/dt = iwz

Where w is the angular speed, z = x + iy the complex 2D position.

Quote:Original post by Eelco
you may think: so what? but the same goes for quaternions. ...


The formula for quaternions is very similar, i.e.

dq/dt = 0.5 * wq

where q is the quaternion and the 0.5 arises from the fact that you need two copies of q when rotating, i.e. using v' = qvq*

w is a purely imaginary quaternion, i.e. one with it's real part equal to zero. If it's thought of as a vector then it's usually called the "angular velocity vector" but you have to remember it's really a quaternion. As a vector it's magnitude is usually associated with the speed of rotation while it's direction is the same as the instantaneous angle of rotation - in general w is not constant.

yup.

Quote:
'Angle axis' is sometimes proposed as an alternative to quaternions for 3D rotaations but it's far less efficient.

yes, it involves doing some conversion. note thought that for orientations quaternions are fine: only for rotationspeeds something else is needed imho. besides axis-angle makes other things easier, like evaluating the speed of any point in the mesh.

Quote:
And the problem with interpolating quaternions going 'the wrong way' is easily solved, and even with the cost of the check to avoid this problem quaternion interpolation is by far the best way to interpolate quaternions.

explain me how i should do the following then, using quaternions for my rotation speed:

i want to represent a rotationspeed of 10 degrees/sec using a quaternion. so far no problem. however, now i want to know the orientation of my object at t=0.1. ill have to raise my quaternion to the power of 0.1, something so impractical youll be pretty much forced to use fixed timesteps when using quaternions for rotationspeeds.

now i want to represent a rotation of 300 degrees/sec, and evaluate the state at t=0.5. again i would have to raise my quaternion to a power, but what if i would be crazy enough to do so? i wont get the desired 150 deg rotation, but 330 instead, since a quaternion doesnt specify the path, only the orientation youll end up with. halfway between 0 and 300 is 330 as far as a quaternion is concerned.

how are these problems easily solved? id say they are fundamental, and CANT be solved no matter how hard you try. if i was using axis-angle for rotationspeeds i could simply manipulate omega, and do a not-so-complex axis-angle -> quat. in the case variable timestepping is needed, this certainly makes more sense and is faster.
Quote:Original post by johnb
...quaternion interpolation is by far the best way to interpolate quaternions.


I agree...
...but I think you mean to say "quaternion interpolation is by far the best way to interpolate rotations" :).
Geocyte Has Committed Suicide.
Quote:Original post by Eelco
Quote:Original post by Dmytry
i've always thought rotation speeds are storen in vector(i mean 3D vector) (without any angle) .... and in 2D , in scalar.

both are axis-angle tho.

in case of 2d the axis is implicit (z), and in the 3d case you speak of the angle is stored in the length of the vector. however, its often more convenient to store this as a seperate value, and keep the vector itself normalized.

Quote:
Interpolation is not exactly dealing with speeds.

strange, i thought the term interpolation was pretty broad, and can be applied to virtually everything.

yes indeed in the case of quaternion-quaternion interpolation people are often talking about orientation-interpolations. thats because they try to work around the nastyness that is raising quaternions to powers in order to do what actually makes sense: interpolating speeds to evaluate a state at a given time.

however, the real solution is not using quaternions at all for rotation speeds, since theyre not really well suited for the job, considering interpolation (which is nasty, especially compared to to axis-angle) aswell as in specifying rotationsspeeds of more than 180 deg/sec, which they cant do at all.

however, quaternions in 3d or complex number in 2d are very well suited for storing orientation information. if you try to use axis-angle for that youll run into a whole other set of problems. the point, which i kind of failed to make in my above post, is that a good engine should apply both axis angle and quaternions for the right job: something ive never seen done actually.


i undestood what you mean - yes, quaternion is bad for rotation speed.

Because, from physics point of view it completely wrong to use quaternions for rotation speeds, because rotation speed have dimension 1/t and if we want to construct quaternions we have to take sin and cos of it, and we can apply sine and cosine only to dimensionless quantities, such as angles (such as orientation). Otherwise, bad things happens.

Rotation speed is not like rotation itself.Rotation during frame is not like rotation speed.
3 numbers is enough and don't cause any "lock" problems. So axis-angle is not really needed as well.Also,it's not axis and angle, but axis and radian/second.

I just store rotation speed in vector that have length equal to radian/second. If length is 0, it doesn't cause any problems- if it does not rotate i don't need to know rotation axis.

How my camera control works currently (q is camera orientation):
w.xyz=spinVector*0.5*dt;
w.r=1;
then when i do
q=w*q; //if spinVector is in global system
/// note: i'm getting q = q + 0.5*(w without real part)*q*dt ,
Normalize(q);

I can store rotations faster than 360 per second. What i can't do, it's rotations faster than 180 or so per timestep, it works correctly only with small timesteps.

To fix that and make it work correctly with any timestep, i can do something like:
(more correct version)
if(!VerySmall(spinVector)){
float l=Length(spinVector);
quaternion cameraRotationDuringFrameTime=AxisAngleToQuaternion(spinVector,l*dt);
cameraOrientation=cameraRotationDuringFrameTime*cameraOrientation;
}
and it will work for any timestep. (is it what you mean by "done correctly" ?)
And axis-angle might be probably faster a bit.(only if you don't have to re-normalize axis anyway)
Quote:Original post by Dmytry
i undestood what you mean - yes, quaternion is bad for rotation speed.

Because, from physics point of view it completely wrong to use quaternions for rotation speeds, because rotation speed have dimension 1/t and if we want to construct quaternions we have to take sin and cos of it, and we can apply sine and cosine only to dimensionless quantities, such as angles (such as orientation). Otherwise, bad things happens.

yeah i think thats indeed the core of the problem. quaternions 'wrap around', due to the nature of periodic functions, but you dont want your speed to wrap around at all.

Quote:
Rotation speed is not like rotation itself.Rotation during frame is not like rotation speed.
3 numbers is enough and don't cause any "lock" problems. So axis-angle is not really needed as well.Also,it's not axis and angle, but axis and radian/second.

yeahyeah, stop nitpicking :P. however, i think euler angles are the least inituative of all. besides, euler is the hardest to convert from (3 cos + 3 sin).

Quote:
I just store rotation speed in vector that have length equal to radian/second. If length is 0, it doesn't cause any problems- if it does not rotate i don't need to know rotation axis.

yeah thats an option. but for my application storing the speed as a seperate value is probably more efficient, because the magnitude of the speed is needed quite often. probably depends on the circumstances whats best.

Quote:
How my camera control works currently (q is camera orientation):
w.xyz=spinVector*0.5*dt;
w.r=1;
then when i do
q=w*q; //if spinVector is in global system
/// note: i'm getting q = q + 0.5*(w without real part)*q*dt ,
Normalize(q);

I can store rotations faster than 360 per second. What i can't do, it's rotations faster than 180 or so per timestep, it works correctly only with small timesteps.

To fix that and make it work correctly with any timestep, i can do something like:
(more correct version)
if(!VerySmall(spinVector)){
float l=Length(spinVector);
quaternion cameraRotationDuringFrameTime=AxisAngleToQuaternion(spinVector,l*dt);
cameraOrientation=cameraRotationDuringFrameTime*cameraOrientation;
}
and it will work for any timestep. (is it what you mean by "done correctly" ?)

exactly. extracting the speed isnt really needed i think tho. you can just multiply dt with the axis if the speed is stored implicitly, or multiply with omega if it isnt. handling of special cases where l=0 could be handled quite elegantly without fear of divide by zeros or inaccuracies in the axis->quat function i believe.

Quote:
And axis-angle might be probably faster a bit.(only if you don't have to re-normalize axis anyway)

yeah i think so aswell. i dont think youd have to renormalize that often either (if thats needed in any step at all), since rotationspeeds dont change that often under normal circumstances.
and on closer inspection, axis-angle -> quat is a relatively very inexpensive operation

EDIT: i suck at teh intarnet.

EDIT2: hard...
Quote:Original post by Eelco
explain me how i should do the following then, using quaternions for my rotation speed:

i want to represent a rotationspeed of 10 degrees/sec using a quaternion. so far no problem. however, now i want to know the orientation of my object at t=0.1. ill have to raise my quaternion to the power of 0.1, something so impractical youll be pretty much forced to use fixed timesteps when using quaternions for rotationspeeds.

now i want to represent a rotation of 300 degrees/sec, and evaluate the state at t=0.5. again i would have to raise my quaternion to a power, but what if i would be crazy enough to do so? i wont get the desired 150 deg rotation, but 330 instead, since a quaternion doesnt specify the path, only the orientation youll end up with. halfway between 0 and 300 is 330 as far as a quaternion is concerned.

how are these problems easily solved? id say they are fundamental, and CANT be solved no matter how hard you try. if i was using axis-angle for rotationspeeds i could simply manipulate omega, and do a not-so-complex axis-angle -> quat. in the case variable timestepping is needed, this certainly makes more sense and is faster.


The second problem is nothing special: it is another version of solving a quadratic. E.g. if I throw a ball up in the air with speed v, ignoring air resistance it's height at time t is


vt - 0.5gt^2

If I want to find when it hits the ground I have to solve the quadratic

vt - 0.5gt^2 = 0

This has two solutions, t = 0 and t =2v/g. The mathematics doesn't give me the answer, I have to use additional logic (in this case the knowledge that t = 0 is the start of the motion and I want the end of it) to deduce the solution.

Your problem is "I have a quaternion that gives a 300 degree rotation, what is the quaternion that is half way, that when applied twice gives me the 300 degrees rotation? " or "what is the square root of the 300 degree rotation?".

As in one and two dimensions (complex numbers) the square root of a general quaternion is two valued, i.e. there are two solutions to any such problem. The mathematics doesn't tell you which is correct or best, you have to use additional logic or information to deduce the right answer. But this is often straightforward as there's often a simple rule or test that will distinguish between the two possible answers.
John BlackburneProgrammer, The Pitbull Syndicate

This topic is closed to new replies.

Advertisement