Sign in to follow this  
david_watt78

Yaw + Pitch = Roll

Recommended Posts

david_watt78    133
I am currently coding a space sim and have found that anytime you rotate a Quaternion in the Yaw axis and in the Pitch Axis at the same time you also get a Roll Rotation. Is there anyway to avoid this? I am doing my Rotations in the order Roll,Pitch, then Yaw, but it doesn't help. I have seen the same issue in some games as well. Is this a product of using Quaternions or is it a nature of the beast issue?

Share this post


Link to post
Share on other sites
Sneftel    1788
That depends on what you mean by "you also get a roll rotation". Can you give an example of a set of angles to yaw and pitch which produce a roll? Also, when you say your ordering is "roll, pitch, then yaw", is that world-space order or object-space order?

Share this post


Link to post
Share on other sites
Sneftel    1788
If you get the same results then you're definitely doing it wrong (read: in an order-independent way). Y-then-P and P-then-Y should NEVER produce the same results. Post your code.

Share this post


Link to post
Share on other sites
jyk    2094
Quote:
I have tried yaw then pitch and pitch then yaw same results.
If you're building your orientation using 'from scratch' Euler angles in the usual way, then one of the above orders should be giving you the desired results (i.e. no roll). Can we see some code?

Keep in mind that with true 6DOF motion (where rotations are applied incrementally about the object's local axes), accumulated yaw and pitch can (and usually will) result in perceived roll. This is the expected behavior in this case, but it can be countered by adding an 'autoleveling' feature (as in the Descent games).

Share this post


Link to post
Share on other sites
david_watt78    133
Here you go. I would love to find an answer to the roll induction issue. I hope this helps.


CISQuaternion Temp = *this;
if(dRoll != 0.0)
{
CISQuaternion Roll;
Roll.FromAngleAxis(dRoll, Temp * CISVector::s_UNITZ);
*this = *this * Roll;
Normalize();
}
if(dYaw != 0.0)
{
CISQuaternion Yaw;
Yaw.FromAngleAxis(dYaw,Temp * CISVector::s_UNITY);
CISQuaternion Temp = *this;
*this = *this * Yaw;
Normalize();
}
if(dPitch != 0.0)
{
CISQuaternion Pitch;
Pitch.FromAngleAxis(dPitch,Temp * CISVector::s_UNITX);
CISQuaternion Temp = *this;
*this = *this * Pitch;
Normalize();
}

Share this post


Link to post
Share on other sites
jyk    2094
How is this function used? Do you start with a 'fresh' quaternion each time (i.e. identity), or do you start with a quaternion representing the current orientation of the object?

Share this post


Link to post
Share on other sites
jyk    2094
Quote:
current orientation I tried tracking the cumulative angle changes but it got messy fast.
In that case, the accumulated roll is to be expected. If you don't want this, you'll need to implement some sort of autoleveling, or manage your vehicle's orientation in some other way.

It also looks to me like there might be some issues with your rotation function. Does the quaternion class that you're using use the standard convention for multiplication order? Or does it use the 'reversed' convention?

Share this post


Link to post
Share on other sites
david_watt78    133
Being that I had the same issue using the XNA math lib. I will go with the nature of the beast explanation. As stated I had noticed that other games such as X3 have the exact same issue. It also looks like any attempt to correct for it is also not working as there are cases such as pass 90 degrees in the pitch axis where a 180 degree roll is normal. So I guess for now I shall leave and revisit it later. Thank you for your help.

Share this post


Link to post
Share on other sites
lightbringer    1070
David, if you set up a quaternion to pitch/yaw and, say, always pass the same axis angle, it won't work as you expect because those rotations happen in the (already rotated) model coordinate system, not in the world coordinate system. Here's how you can get a "non-rolling" result, I use this for a pitch-able and yaw-able camera.


// call these to change the pitch/yaw
public void pitch(float delta) {
pitch += delta;
if (pitch >= 360f) {
pitch -= 360f;
}
else if (pitch <= 0f) {
pitch += 360f;
}
}

public void yaw(float delta) {
yaw += delta;
if (yaw >= 360f) {
yaw -= 360f;
}
else if (yaw <= 0f) {
yaw += 360f;
}
}
...
// on each frame, update the camera:
public void update() {
...
transform.resetOrientation();
transform.rotate(yaw, 0.0f, 1.0f, 0.0f);
transform.rotate(pitch, 1.0f, 0.0f, 0.0f);
...
//(the rest omitted for brevity)
}

Share this post


Link to post
Share on other sites
Fingers_    410
This is correct, desirable behavior. A real spaceship or plane will do the same thing. Any attempt to "fix" it with Euler angles etc will result in unrealistic and annoying gimbal lock behavior.

Consider the case of the plane pitching up 90 degrees, then yawing right 90 degrees. Model it by holding a miniature plane in your hand if you'd like. The only realistic result is that the plane ends up rolled 90 degrees right and pointed horizontally to the right. If you used absolute yaw/pitch angles, changing the yaw angle when pointed up would result in the plane rolling rather than yawing from the pilot's point of view, making it feel like the plane is "stuck" pointing upward.

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