Sign in to follow this  
nebemore

Quaternions step by step

Recommended Posts

hi, I've spent the last 9 hours in the world of Quaternions. There are so many Threads and after reading about 100 of them, i have to say that i still don't know how to use them(yes, I feel ashamed). So i don't want to write 3 pages about what I already know about Quaternions and what not. I don't want also to post a code. Let's say i have everything I need, a Quaternion class with all needed member functions, very usefull ODE-functions that handle Quaternions and so on... What I have: 1. a rigid body in the world 2. position and rotation matrix of the body 3. center of mass My Goal: 1. roll/pitch/yaw the body around his point of reference(here the mass center) note: i've already implemented all roll/yaw/pitch-functions and key-controls What I need: 1. someone to tell me step-by-step what i have to do. no code, just words or pseudo-code. i need just to understand it. for all that aren't big fans of Quaternions: i have already made this body rotating with matrix, so please talk only about Quats. Thanks a lot in advance!

Share this post


Link to post
Share on other sites
Quote:
i have already made this body rotating with matrix, so please talk only about Quats.
May I ask, if you already have it working with matrices, why do you want to introduce quaternions?

Share this post


Link to post
Share on other sites
That's one good reason:
"A matrix product requires many more operations than a quaternion product so we can save a lot of time and preserve more numerical accuracy with quaternions than with matrices."

And another one: I'm implementing a body that moves and rotates around and has a camera inside(so the object is transparent). to manipulate both of them (body & cam) i think using quaternions is better idea that with matrices.

cheers

Share this post


Link to post
Share on other sites
Quote:
Original post by nebemore
That's one good reason:
"A matrix product requires many more operations than a quaternion product so we can save a lot of time and preserve more numerical accuracy with quaternions than with matrices."
Well, I'm not trying to avoid your question of how to use quaternions in this context, but I guess I am playing devil's advocate a bit. Regarding the above observation, the fact that quaternion concatenation is a bit more efficient really only matters (IMO) in a context where you're performing many, many concatenations per frame. The classic example of where quaternions can really pay off is in animation using hierarchical models or keyframe interpolation; in this context the more efficient concatenation and interpolation and minimal storage can be a win. There are other situations though where (again, IMO) matrices are a perfectly suitable solution.
Quote:
And another one: I'm implementing a body that moves and rotates around and has a camera inside(so the object is transparent). to manipulate both of them (body & cam) i think using quaternions is better idea that with matrices.
This doesn't make much sense to me. Why would using a quaternion be better for a transparent object, a camera, manipulating two objects at once, or any combination of the above?

The reason I question the switch to quats here is that (or so I observe) there is a lot of misinformation and misunderstanding about quaternions, matrices, other rotation representations, and their respective characteristics. Quite often people seem to think quaternions are a better (or the only) solution to a problem, when in fact rotation matrices would work just fine.

Anyway, to get back to your original question, can you be more specific? It'd be easier to provide information if we knew exactly what aspect of using quaternions in this context is giving you trouble.

Share this post


Link to post
Share on other sites
What about for a trailing camera that is "springy". Wouldn't interpolations between the targets location and the camera be best handled using a quaternion? From what I understood interpolation is the quaternion's strong point.

nebemore: Have you looked at gamedevs articles on Quaternions? There is plenty of information on them. Take a look.

There isn't, unfortunately, that great of a step by step walkthrough for understanding the math behind them but there are articles that walk you through implimenting them in code.

Share this post


Link to post
Share on other sites
thanks for the answers!

i'll try to be more specific:

first let forget the camera and concentrate only on the object in the space.

i want to yaw,pitch and roll the body in the space using control-keys.

let's say the body lies at point (x,y,z) with z positive as Up.

1. At the begin the body has a init orentation. Like I said, i'm using ODE for the physics. There is the function dBodyGetRotation that gives me the start orientation of the body. Another function dRtoQ transforms the initial Rotation Matrix in Quaternion. Good, now i have the initial Quaternion. let name it Qstart.

2. Let take the formula Vnew= q ∗ Vold ∗ q∗, where q is the desired rotation quaternion and q* = q conjugate. The first Question here is: what is Vold? Is Vold=Qstart? (you can correct me anytime)

3. The next is to determine what is q. Now i'm taking the function dQFromAxisAndAngle(dQuaternion q, dReal ax, dReal ay, dReal az,
dReal angle)
.
This function computes q as a rotation of angle radians along the axis (ax,ay,az). so if i want to yaw the body it will look like:
dQFromAxisAndAngle(yawQuat, 0, 0, 1, rotAngle),where rotAngle is set by pushing a key and yawQuat the quatenion to store the result. Is the setting of the ax,ay,az correct?

4. So if everything till now is correct(I doubt). what is when i have 3 quaternions - yawQuat, rollQuat and pitchQuat? Should I first multiply all three of them and store in another Quaternion. Let say
[/b]Qtemp = rollQuat*pitchQuat*yawQuat[/b]. Is the order correct?
Is now the formula correct Vnew= Qtemp ∗ Vold ∗ Qtemp∗ ?

5. Transforming of the rotation matrix into quaternion is necessary only at the begin. After that by every key-input i have to take the actuall rotation Quaternion (Vold(frame t)=Vnew(frame t-1)). Am I right?

6. Is Vnew in every frame the new rotation of the body?

so, there are almost all my questions about quaternions.
Thanks for reading, advices and of course for your corections.

cheers

Share this post


Link to post
Share on other sites
IMO the easiest way to get a grip on quaternions is just to think of them as a drop-in substitute for rotation matrices. Every operation you would perform with rotation matrices - construction from an axis-angle pair or Euler angle triple, concatenation, normalization, normalized linear interpolation, spherical linear interpolation, transformation of vectors - can also be done with quaternions. If you have working code that uses rotation matrices, the same code (perhaps with some slight changes in syntax) will work with quaternions as well.

One potential gotcha is that the concatenation order for your matrices and quaternions must match. If your matrices are configured for column vectors, you'll want to use the standard mathematical definition for quaternion multiplication, and the standard formula for rotating a vector by a quat. If your matrices are configured for row vectors, you'll want to use the 'reverse' form for quat multiplication (wherein the sign of the cross-product term is negated), and also the reverse of the vector rotation formula (just transpose the terms).

Rotation matrices and quaternions each have particular strengths and weaknesses with respect to the aforementioned common operations. The two forms can be freely converted back and forth, so if one or the other representation is more suitable for a particular purpose (such as quaternions and interpolation), you can always convert to that form when needed.

Share this post


Link to post
Share on other sites
I hate to disappoint you, but typically a quaternion is used only for storage and intermediate computations and is converted to a rotation matrix when needed for a transformation. But if you want to use a quaternion, then (as jyk wrote) everything is pretty much the same except that you use a quaternion in place of a rotation matrix.

To answer your specific questions (note that many of your questions don't make sense if you have already done this using matrices):

1. ok
2. Vold is a position. Quaternions represent orientations, not positions. The formula computes a rotated position.
3. ok
4. Yes, but the question is still, "what is Vold"? What are you rotating?
5. No, see my comments in #2.
6. No, see my comments in #2. To accumulate rotations, you simply multiply the current orientation by this frame's rotation. Qnew = Qold * Qframe.

Share this post


Link to post
Share on other sites

so thanks a lot.

i was confused with all the stuff before your posts. now i know that Vold is the position vector. So when i take the position of the body (the position of his local center point) and construct a quaternion for example with
FromAxesAndAngles i can apply them in the formula to get Vnew. Am i right?

What information can I extract from Vnew. Can I transform Vnew direct in rotation matrix and apply the matrix on the body (using for example something like
dBodySetRotation(newRotMatrix))?

Share this post


Link to post
Share on other sites
hi once again

i've tried all the things that u said and can say...now at least is the body rotating in my scene . Ok, not the way I want to be. Like u said, i tried to store the current rotation of the body in quaternion (camQuat). by every key-input i compute the new rotation using Euler Angles and store the result in a Quaternion (resultQuat).

After that i multiply the quaternions:

camQuat = resultQuat * camQuat;(1)

and apply the camQuat to the body. When I pitch and after that yaw, the body yaws around the local z Axis(x,y,z-up). I want the body to yaw always around the world z Axis. So i changed the order in (1) to
camQuat = camQuat * resultQuat ;(2)
and it works for yaw and pitch perfect. The big problem is the roll. When I roll after that is everything wrong. (in both cases)

What is the best way to become the body yawing always around the global z-axis independent from the pitch and the roll. By pitch and roll the body have to rotate around local axes x(for pitch) and y(for roll).

Any ideas?

Share this post


Link to post
Share on other sites
Quote:
Original post by nebemore
hi once again

i've tried all the things that u said and can say...now at least is the body rotating in my scene . Ok, not the way I want to be. Like u said, i tried to store the current rotation of the body in quaternion (camQuat). by every key-input i compute the new rotation using Euler Angles and store the result in a Quaternion (resultQuat).

After that i multiply the quaternions:

camQuat = resultQuat * camQuat;(1)

and apply the camQuat to the body. When I pitch and after that yaw, the body yaws around the local z Axis(x,y,z-up). I want the body to yaw always around the world z Axis. So i changed the order in (1) to
camQuat = camQuat * resultQuat ;(2)
and it works for yaw and pitch perfect. The big problem is the roll. When I roll after that is everything wrong. (in both cases)

What is the best way to become the body yawing always around the global z-axis independent from the pitch and the roll. By pitch and roll the body have to rotate around local axes x(for pitch) and y(for roll).

Any ideas?

if you want yaw to be global and roll and pitch local, make separate rotation quaternion for yaw, and multiply it on the left, and multiply the pitch and roll on the right.
I.e. like
camQuat=yaw * camQuat * pitchAndRoll.

anyway, if you are doing this kind of movement and want it working precisely as with euler angles, there's not much purprose in using quaternions.

Share this post


Link to post
Share on other sites

Dmytry: i've tried what u said, and yaw is working fine (rotating around global z), roll is working also fine(around local y), only pitch is going wrong(for example when i first roll and after that pitch, the pitch is no more correct.) I have tried with Euler Angles and with FromAxisAndAngle - same result.

here pseudo code: (in every frame)

//yawQuat,pitchQuat,rollQuat - Quaternions;
//angleY/P/R = angle if key pressed, else 0

QFromAxisAndAngle (yawQuat, 0, 0, 1, angleYaw);
QFromAxisAndAngle (pitchQuat, 1, 0, 0, anglePitch);
QFromAxisAndAngle (rollQuat, 0, 1, 0, angleRoll);

Quat temp = rollQuat * pitchQuat;
//modelQuat holds the current rotation
modelQuat = yawQuat * modelQuat;
modelQuat = modelQuat * temp;

//sets Quat to body
BodySetQuaternion (body, modelQuat);

how can i fix it?

Share this post


Link to post
Share on other sites
Well, firstly: This really is no issue of "correct" and "incorrect", there's issue of knowing what kind of control specifically you want and implementing this kind of control.
It looks like what you want is not really pitch, yaw, and roll (otherwise you'd simply need them all to be global or local and no problem in first place).

My guess is that you want to emulate addition of euler angles with quaterions, so that "yaw" turn around global vertical axis, "pitch" turns around the the local side (x) axis projected onto ground (xy) plane, and "roll" turn around local forward axis (y) . You will get gimbal lock with quaternions there as well as with euler angles, as the gimbal lock is a problem of this concept of motion and not really of how orientation is storen.

The pseudocode for guess:

// note, gonna have gimbal lock like euler.
vector p_axis=TransformFromCameraSpaceToGlobalSpace(Vector(1,0,0));
p_axis-=DotProduct(axis,Vector(0,0,1))*axis; // note: it's not unit length anymore. QFromAxisAndAngle need to handle it gracefully

QFromAxisAndAngle (yawQuat, 0, 0, 1, angleYaw);
QFromAxisAndAngle (pitchQuat, p_axis, anglePitch);// note: the pitch is in global space because we transformed it above
QFromAxisAndAngle (rollQuat, 0, 1, 0, angleRoll);

modelQuat = yawQuat * modelQuat * pitchQuat * rollQuat;

(I'm still not certain it is really the kind of control you want)

Share this post


Link to post
Share on other sites
hmm, the forum was down...

Dmytry: thanks for your reply. my main goal is to implement a camera that yaw/pitch/roll around local axes (my first post) and the rotations have to be correct (no gimbal lock).

That with the yawing around global axis was just...curiosity. i've tried but don't like the results.

to the main problem: as i'm understanding to avoid gimlble lock i have to compute every frame the new rotation quaternion(or matrix) and after that multiply the current quaternion with the new one (in this order). and for the computation of the new one is equal using QfromEulerAngles or QfromAxisAndAnle.

feel free to correct me i'm talking nonsense

cheers

Share this post


Link to post
Share on other sites
if you want to do pitch/yaw/roll around local axises, just multiply them with camera's rotation quaternion from the right. Then you get the camera as for flight or space simulator.

Obviously since you have questions it is not what you want right? I think something around 90% of problems with rotations (or just problems) in this forum is just problem with poster knowing/understanding what he want, in terms of rotations. Try taking some cube, write X,Y,Z on three sides (the vectors is then pointing to the center of side). Also define global directions in the room (like x to window, y to right, z to up), then play around with this cube. Rotation around local axis, is rotation about cube's axis. Rotation around global is around room's axises. Then you can figure what rotations do you want. It's interesting that most people (except to who's job it is relatd) don't quite understand the rotations in 3D space in which they live, so it's not just you.

As for gimbal lock, there seems to be lot of confusion. The rotations needs to be clarified first, then you can begin to understand what is gimbal lock, why and when it happens. "euler angles = gimbal lock, quaternions = no gimbal lock" is as informative as not knowing about gimbal lock at all. Gimbal lock is really a problem with controls behavior when you look up or down. If you have controls exactly as for euler angles cam, it will lock just as well as straightforward euler angles based implementation.

edit: btw, alternatively, you can specify which known game has camera like one you want. If it's quake/halflife/other FPS, what's the problem with euler angles again? the camera controls inherently have to stop when you look straight up or down.

[Edited by - Dmytry on October 9, 2006 5:12:43 PM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this