Yaw, pitch & roll in 1 matrix?

Started by
6 comments, last by Polkapunk 17 years, 10 months ago
Hey guys. Sorry if this has been covered before, but I was unable to find this in the forums and my web searches didn't turn up any solutions to my problem. My problem, in short, is representing rotations across multiple axes simultaneously. Here's the long version: I'm trying to orient "things" in the correct direction. For simplicities sake, I'll use a plane as an example. This plane can yaw, pitch and roll. I store the orientation of the plane as a matrix (the transform that maps all the points of the original mesh to the world space). The plane pitches by rotating on the x-axis of the plane. To achieve this, I first multiply the matrix that represents the current transformation to world space of the object with the vector that represents the axis of rotation in the object space, <1,0,0>, which gives me the axis of rotation in the world space (as opposed to the axis of rotation in the object space). I now know the angle the plane will pitch and know the axis in world space it must rotate around. I've been using the following formula to come up with the matrix that represents this rotation:

	[0][0] = cos(angle) + ((1 + cos(angle)) * (axis[0] * axis[0]));
	[0][1] = ((1 - cos(angle)) * axis[0] * axis[1]) - (sin(angle) * axis[2]);
	[0][2] = ((1 - cos(angle)) * axis[0] * axis[2]) + (sin(angle) * axis[1]);
	[1][0] = ((1 - cos(angle)) * axis[0] * axis[1]) + (sin(angle) * axis[2]);
	[1][1] = cos(angle) + ((1 - cos(angle)) * (axis[1] * axis[1]));
	[1][2] = ((1 - cos(angle)) * axis[0] * axis[2]) - (sin(angle) * axis[0]);
	[2][0] = ((1 - cos(angle)) * axis[0] * axis[2]) - (sin(angle) * axis[1]);
	[2][1] = ((1 - cos(angle)) * axis[1] * axis[2]) + (sin(angle) * axis[0]);
	[2][2] = cos(angle) + ((1 - cos(angle)) * (axis[2] * axis[2]));

(I found it on a book on 3D game math so unless I mistyped something it should be correct.) Now that I have this new matrix, I multiply it with the old to get the new transform to world space for the object (new matrix on the left, old matrix on the right). If I want to yaw, I use <0,1,0> as the initial rotation vector and for rolling use <0,0,1>. The problem I'm now running into is that it is possible for a plane to yaw, pitch and roll all at the same time and I am not aware of a formula that can represent rotations over multiple axes in one matrix. Although I could compute the yaw, pitch and roll matrices separately and then multiply them together, since matrix multiplication and rotations are not commutative the order of multiplication (or applying the rotations) would change the answer (orientation). Is there a formula for rotation around 3 axes at the same time? Please forgive me for such a long (and probably confusing) post. Thanks! -Polkapunk
Advertisement
Look into quaternions. It provides you with a method of representing any orientation using 4 numbers, and you can easily convert quaternions to matrices.

A good place to start would be the Quaternion entry in Wikipedia. I believe there is also an article on this in the Gamedev archives.
Quote:Original post by Guru2012
Look into quaternions. It provides you with a method of representing any orientation using 4 numbers, and you can easily convert quaternions to matrices.

A good place to start would be the Quaternion entry in Wikipedia. I believe there is also an article on this in the Gamedev archives.
I would disagree with the above advice. Quaternions are often viewed as a panacea for any rotation problem, but this is simply not the case. The fact is, quaternions and matrices are just two ways of representing a rotation, and for the most part, any problem you have with one, you'll have with the other.

The first thing I'll point out is that it's never necessary to multiply a cardinal basis vector such as (1,0,0) with a rotation matrix to get the same vector in world space. Such a multiplication will always give you the corresponding row or column of the rotation matrix itself, so it's easiest to just extract this vector directly.

From your description it sounds like you're maintaining your orientation matrix from frame to frame rather than constructing it from scratch each frame, and applying rotations incrementally about the local axes. If this is the case, I wouldn't worry too much about commutativity. It's true that pitching and then yawing may have a slightly different result than yawing and then pitching, but it won't be noticable the way it is when using 'from scratch' rotations. The rational here is that 'infinitesimal rotations commute'; frame-to-frame rotations are a discrete approximation of this, so you can usually get away with ignoring the commutativity issue (in my experience at least).

One last thing: it's actually the case that a local-axis pre/post-multiplication is equivalent to a global-axis post/pre-multiplication (whether pre or post depends on vector orientation). This means you don't actually have to use arbitrary axis-angle matrices (or extract the local basis vectors) in order to rotate the object.
My approach for combining rotations is to break the matrix into its 3 axial vectors.
treat the rotations as if they were linear 'forces' on each vector to move them all independantly. (linear motions are commutative)
Then re-orthogonalize/re-normalize them to get a new matrix.

occasionally I'll also assign different weights on the vectors; this *may* be equivalent to inertia tensor stuff, but since I never understood how those worked it may not be... seems to have good effects though...
Guru: I'm not quite sure how Quaternions would help out. I know that they are useful for linear interpolation in between keyframes, but I'm doing the exact opposite of that. Is there a way that they can easily represent rotations over multiple axes?


JYK: I guess I kinda spaced out when I coded to multiply by cardinal bases instead of simply pulling the applicable row. I think that applying the different rotations in an arbitrary order would be problematic. I'm fairly certain that none of the possible combinations would yield the correct result. Although this probably wouldn't be noticable if it were only in small increments, I plan to use this to represent the orientation of every movable object. Planes might yaw pitch and roll slowly, but if I were to have a ball that was thrown the ball could end up spinning multiple times in a single second. Furthermore, this would mean that if the computer slows down and misses a few frames, all the orientations would end up completely messed up. Multiplayer would also be made impossible.
Quote:It's actually the case that a local-axis pre/post-multiplication is equivalent to a global-axis post/pre-multiplication (whether pre or post depends on vector orientation). This means you don't actually have to use arbitrary axis-angle matrices (or extract the local basis vectors) in order to rotate the object.

I don't fully understand how I could eliminate the arbitrary axis rotation matrix. Could you explain this some more?


HaphazardlyNamed :
Quote:My approach for combining rotations is to break the matrix into its 3 axial vectors.
treat the rotations as if they were linear 'forces' on each vector to move them all independantly. (linear motions are commutative)

Ok, this went way over my head. I'm not sure how to apply forces without dealing with object masses. Even the formulas for torque I know of need it for the calculations. Are you able to go into more detail about this?


Perhaps I am trying to do things in an overly complicated manner, or completely wrong. I'm trying to allow any moveable object to be rotated in any manner. Any time an object is rotated I want to recalculate it's orientation on the next key-frame. Is there a better way I could be storing this information? Am I doing things completely wrong?

Thanks for all of your help and advice!!!
I think I've finally found a solution to my problem! According to this web site:

http://www.euclideanspace.com/maths/differential/quaternioncalculus/index.htm

there's a formula that can directly convert from angular velocity to a quaternion.

Even though the formula is a bit long and complicated, it still seems to have fewer operations than there'd be if I was applying 3 rotational matrices.

Is this the solution to what I'm looking for? This problem's been driving me crazy for the past week so I'm a bit afraid I'm jumping at something that won't actually help me...
Quote:Original post by Polkapunk
Is this the solution to what I'm looking for? This problem's been driving me crazy for the past week so I'm a bit afraid I'm jumping at something that won't actually help me...
If you're refering to:
q' = .5*quat(w)*q
Then yes, that may be what you're looking for. However, there is an equivalent equation for matrices:
R' = skew(w)*R
Note that there's nothing special about quaternions with respect to this particular problem; you can use matrices and get the exact same results.
Thanks!!! I actually hadn't planned on using quaternions, but I was unable to find the formula that would correctly convert rotations over several axes, or the angular velocity over several axes into a single matrix. I just happened to stumble across this particular site...

This topic is closed to new replies.

Advertisement