Three-axes Rotation with Quaternions

Started by
5 comments, last by Drag0n 18 years, 11 months ago
Hi! I'm sorry if this has been asked before. I've been searching for an answer for awhile, so if there is an answer (to my rather stupid question) please point me to it. Now. I've been hacking some quaternions together, and after a bit of trying I am now able to fly through space, using my joystick. It works like a charm, but since I don't quite understand quaternions (yet) I thought it might be a good idea to ask if I do it right. The way I do it now is, I have my pitch, yaw and roll increments stored every frame in delta_pitch, delta_yaw, and delta_roll. Rotation velocity per axis is at most 90deg/s so with around 430 fps the deltas are very small. I build my three quaternions q_delta_pitch, q_delta_yaw, and q_delta_roll like this:

q_delta_pitch.fromAxisAngle( delta_pitch, 1.0, 0.0, 0.0 );
q_delta_roll.fromAxisAngle( delta_roll, 0.0, 1.0, 0.0 );
q_delta_yaw.fromAxisAngle( delta_yaw, 0.0, 0.0, 1.0 );

Note that I'm using OpenGL with the positive z-axis as up-vector. I then apply these deltas to my rotation:

q_rotation = q_rotation * q_delta_pitch * q_delta_roll * q_delta_yaw;

This rotation is then applied to my camera. This works perfectly. I pitch when I want to pitch, I roll when I want to roll, and I yaw when I want to yaw. However, as I said earlier, my deltas are really small, so I can't really tell whether this is the right way to do it, but I believe it is not. Another way to do it would be to store the angles, and increment (or decrement) them every frame, and then build the rotation by first rotating the (identity) quaternion around the x-axis, then around the (local) y-axis, and then around the (local) z-axis. What is the best way to do it? I know I shouldn't rely on my high frame rate. But even after hours and hours of trying different combinations, I still need enlightment. ;-) Hope you understand my problem! Thanks in advance... Cheers, Drag0n
-----------------------------"Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to build bigger and better idiots. So far, the universe is winning..." -- Rich Cook"...nobody ever accused English pronounciation and spelling of being logical." -- Bjarne Stroustrup"...the war on terror is going badly because, if you where to compare it to WWII, it's like America being attacked by Japan, and responding by invading Brazil." -- Michalson
Advertisement
I think that for greater accuracy and consistency at lower frame rates, you'll want to rotate around your object's local axes rather than the world axes (as you suggested in your post). Here is an article that discusses this approach, but with vectors rather than quaternions. In any case it should be a fairly easy adjustment to make to you code.

(This is assuming I read your code correctly...)
Quote:Original post by jyk
I think that for greater accuracy and consistency at lower frame rates, you'll want to rotate around your object's local axes rather than the world axes (as you suggested in your post).

Think the multiplication order of the quaternions results in exactly that, local-based rotations instead of world based.. but then i always get this stuff wrong >>;;
Thanks alot so far guys.

So, should I stick to my delta-value based rotations, or is there some way of using my pitch, yaw, and roll angles to create a rotation? Using them as Euler angles doesn't really work...

EDIT: I don't have DirectX available (Linux), so can't test this myself. But how does D3DXQuaternionRotationYawPitchRoll() do it? ;-)

Cheers,
Drag0n
-----------------------------"Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to build bigger and better idiots. So far, the universe is winning..." -- Rich Cook"...nobody ever accused English pronounciation and spelling of being logical." -- Bjarne Stroustrup"...the war on terror is going badly because, if you where to compare it to WWII, it's like America being attacked by Japan, and responding by invading Brazil." -- Michalson
Quote:I don't have DirectX available (Linux), so can't test this myself. But how does D3DXQuaternionRotationYawPitchRoll() do it? ;-)
I don't know D3D, but my guess is that this function create a matrix from scratch as three successive rotations about the world axes. I could be wrong about that though.

In any case I would stick with relative, incremental rotation rather than trying to maintain a set of Euler angles. Rotate the quaternion successively about its local axes by your delta values. You'll want to renormalize the quaternion occasionally - it's cheap so it's reasonable to do it every update.
Quote:Original post by Drag0n
So, should I stick to my delta-value based rotations, or is there some way of using my pitch, yaw, and roll angles to create a rotation? Using them as Euler angles doesn't really work...

You /could/ keep track on cumulative Euler angles 'built' from the delta changes and then generate transformation matrix from them on each frame, but given this will eventually lead to the gimbal lock while offering little in return, it's perhaps better to stick to your current way (unless someone can suggest a better alternative ^^;
Once again, thanks for your replies.

I decided to stick to my incremental method now. I switched back and forth between applying my delta values to local and global axes, but that didn't make any difference. It might have been a difference if I turned down the frame rate even more, but I guess anything under 10 fps is not what I would call playable, and at 10 fps I didn't notice anything. So, it seems to work.

As for normalization, my quaternion implementation "keeps itself normalized". Meaning, everytime an operation is performed that would denormalize the quaternion significantly, it calls normalize(). I've yet to find out (or derive) which operations these are exactly! Normalizing it once in awhile even though it (in theory) wouldn't be denormalized is probably also a good idea though. ;)

What I'm trying to do now is to draw a HUD, those elevation lines seen in fighter jets. I might come back and ask pretty soon... :)

Thanks again,
Dave
-----------------------------"Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to build bigger and better idiots. So far, the universe is winning..." -- Rich Cook"...nobody ever accused English pronounciation and spelling of being logical." -- Bjarne Stroustrup"...the war on terror is going badly because, if you where to compare it to WWII, it's like America being attacked by Japan, and responding by invading Brazil." -- Michalson

This topic is closed to new replies.

Advertisement