Skip to main content
GameDev.net gamedev.net
🔒 Locked 🎮 Unity

When to normalise a quaternion

Started by pauls_1979 Oct 19, 2007 at 8:39 AM 8 replies 6.5k views
Original Post
pauls_1979
pauls_1979
I have a quaternion which I'm using to represent rotation, and I want to limit that rotation to just the y axis (i.e. remove rotation about x and z). I tried setting the x and z components to zero and this seemed to work okay, but then when I normalised the quaternion things went a bit wrong. My knowledge of quaternions is limited but I assume the quaternion needs to be normalised, am I wrong? Or am I approaching this the wrong way? Thanks in advance.
Rompa
Rompa
I'm under the impression that only unit quaternions may represent rotations, but I'm no math whiz.
haegarr
haegarr
Correct: Only unit quaternions represent pure rotations. From an angle/axis pair (where the ais is assumed to be a unit vector already) you compute the quaternion as
q := [ cos(a/2) x*sin(a/2) y*sin(a/2) z*sin(a/2) ]

With [x y z] = [0 1 0] you get
q := [ cos(a/2) 0 sin(a/2) 0 ]
which is a unit quaternion.

With [x y z] = [0 0.707 0.707] you get
q := [ cos(a/2) 0 0.707*sin(a/2) 0.707*sin(a/2) ]
which is also a unit quaternion.

Now, setting qz to zero
q' := [ cos(a/2) 0 0.707*sin(a/2) 0 ]
and re-normalizing that does not result in the same!
MrRowl
MrRowl
The quaternion needs to be normalised before you apply it. However, if you just remove some components, and then normalise, the resulting quaternion won't bear any meaningful (probably!) to what you actually want. Actually, it depends how you normalise too.

I think you need to think about exactly what you're trying to do more - or maybe describe exactly what you're trying to do here.
BS-er
BS-er
If your quaternion library has a function to make a quaternion from an angle and an axis (seems that most do), its fairly easy. The following examples is uses the Ogre Quaternion library:

Quaternion YaxisRotation;
YaxisRotation.fromAngleAxis(Angle, Vector3::UNIT_Y);

If you want to rotate an existing quaternion some amount around the Y axis, it would go something like:

Quaternion YaxisRotation;
YaxisRotation.fromAngleAxis(Angle, Vector3::UNIT_Y);
ExistingQuaternion = YaxisRotation * ExistingQuaternion;
pauls_1979
pauls_1979
Thanks guys. To give you some idea of context, I plan to use this in my animation system so that I can limit the rotation of a bone to a single axis at certain points during an animation.

Here's what I was trying to do:
Quaternion q1, q2;// Rotate q1 about all three axes.q1.Rotate(10, 20, 30);// Rotate q2 about just the y axis.q2.Rotate(0, 20, 0);// Remove rotation about x and z axes from q1.q1.x = 0;q1.z = 0;q1.Normalise();// q1 should now be equal to q2.


Unfortunately this doesn't work and I think it's because (as MrRowl pointed out) I can't just remove two components, then normalise the quaternion and expect to get a valid rotation. Does anyone have any suggestions as to how I might correctly limit the rotation?

I did think I could just convert the quaternion to eular angles, then create a new rotation using only the y component like this:
Quaternion q;float      x, y, z;q.ToEular(x, y, z);q.SetIdentity();q.Rotate(0, y, 0);


I've a feeling this might result in a loss of precision though and precision is farily important here.
haegarr
haegarr
As shown in my post above, from a pure mathematical point-of-view, you have to find a normalization that yields in the same quaternion as when the axis were altered originally. That means that the normalization must not alter the real part (or else the angle will differ). Without having proven it, I suggest to try the following:

You want find a value s for which, if used to scale the imaginaries of the altered quaternion, the norm becomes 1:
sqrt( r2 + ( x2 + y2 + z2 ) / s2 ) = 1
Doing some math, this is solved to be
s2 = ( x2 + y2 + z2 ) / ( 1 - r2 )

EDIT: So the normalized quaternion will be
q' := [ r x/s y/s z/s ]

Using that kind of normalization will yield in a unit quaternion and hence a pure rotation; additionally it constraints the quaternion to look like produced from a angle/axis representation. However, whether that is what you want is a totally other question. But I'd be glad to hear about your achievements.

[Edited by - haegarr on October 19, 2007 10:30:56 AM]
Vorpy
Vorpy
I think the quaternion you want might actually be found by leaving the y value as it is and changing the w value to be sqrt(1-(y^2)). This is based on intuition about the interpretation of the rotation as a point on a 4 dimensional sphere and is quite possibly wrong.
TerrorFLOP
TerrorFLOP
I wrote a handful of Word documents about vector projections, rotations and quaternions. Although I have to admit, I wrote them from a purely mathematical standpoint (i.e. using the language of Set and Group Theory).

Anyway, if you can follow the Math, it should give you an idea on how unit quaternions can represent rotations about arbitrary axes.

So give me a holla if you'd like 'em. No problemo.
johnb
johnb
Quote:
Original post by pauls_1979
Unfortunately this doesn't work and I think it's because (as MrRowl pointed out) I can't just remove two components, then normalise the quaternion and expect to get a valid rotation. Does anyone have any suggestions as to how I might correctly limit the rotation?

I did think I could just convert the quaternion to eular angles, then create a new rotation using only the y component like this ... I've a feeling this might result in a loss of precision though and precision is farily important here.


You are always going to lose some information, and for some rotations there may not be a right answer, but this is how I would do it:

Work out what your forward/preferred direction is, perpendicular to the Y axis. Suppose it is X, i.e. the X axis

X = (1, 0, 0)

Rotate this using your quaternion. you will get a new unit vector

V = (vx, vy, vz)

Zero the y coordinate of this, and renormalise (note that the sort of rotations this doesn't work for tend to make vy the largest component), to get

U = (ux, 0, uz)

Then the rotation you want about the Y axis is from X to U. You can work out the angle and use a quaternion from angle-axis, or work it out more directly.

John BlackburneProgrammer, The Pitbull Syndicate

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.