Jump to content
  • Advertisement
Sign in to follow this  
Spa8nky

Quaternion to Euler angles and back. Why is the rotation changing?

This topic is 2754 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

If I take the current orientation of my entity and convert it to Euler angles:



Vector3 orientationEuler = audioObjects[0].Entity.Orientation.ToEulerAngles();


using the following method:



public static Vector3 ToEulerAngles(this Quaternion q)
{
// Store the Euler angles in radians
Vector3 pitchYawRoll = new Vector3();

double sqw = q.W * q.W;
double sqx = q.X * q.X;
double sqy = q.Y * q.Y;
double sqz = q.Z * q.Z;

// If quaternion is normalised the unit is one, otherwise it is the correction factor
double unit = sqx + sqy + sqz + sqw;
double test = q.X * q.Y + q.Z * q.W;

if (test > 0.499f * unit)
{
// Singularity at north pole
pitchYawRoll.Y = 2f * (float)Math.Atan2(q.X, q.W); // Yaw
pitchYawRoll.X = PI * 0.5f; // Pitch
pitchYawRoll.Z = 0f; // Roll
return pitchYawRoll;
}
else if (test < -0.499f * unit)
{
// Singularity at south pole
pitchYawRoll.Y = -2f * (float)Math.Atan2(q.X, q.W); // Yaw
pitchYawRoll.X = -PI * 0.5f; // Pitch
pitchYawRoll.Z = 0f; // Roll
return pitchYawRoll;
}

pitchYawRoll.Y = (float)Math.Atan2(2 * q.Y * q.W - 2 * q.X * q.Z, sqx - sqy - sqz + sqw); // Yaw
pitchYawRoll.X = (float)Math.Asin(2 * test / unit); // Pitch
pitchYawRoll.Z = (float)Math.Atan2(2 * q.X * q.W - 2 * q.Y * q.Z, -sqx + sqy - sqz + sqw); // Roll

return pitchYawRoll;
}


I then immediately convert it back to a Quaternion:


audioObjects[0].Entity.Orientation = Quaternion.CreateFromYawPitchRoll(orientationEuler.Y, orientationEuler.X, orientationEuler.Z);


using the following method:



public static Quaternion CreateFromYawPitchRoll(float yaw, float pitch, float roll)
{
Quaternion quaternion;
float num9 = roll * 0.5f;
float num6 = (float) Math.Sin((double) num9);
float num5 = (float) Math.Cos((double) num9);
float num8 = pitch * 0.5f;
float num4 = (float) Math.Sin((double) num8);
float num3 = (float) Math.Cos((double) num8);
float num7 = yaw * 0.5f;
float num2 = (float) Math.Sin((double) num7);
float num = (float) Math.Cos((double) num7);
quaternion.X = ((num * num4) * num5) + ((num2 * num3) * num6);
quaternion.Y = ((num2 * num3) * num5) - ((num * num4) * num6);
quaternion.Z = ((num * num3) * num6) - ((num2 * num4) * num5);
quaternion.W = ((num * num3) * num5) + ((num2 * num4) * num6);
return quaternion;
}


Why does the orientation change (flip) as shown in the pictures below?

Orientation1.png


Orientation2.png

Share this post


Link to post
Share on other sites
Advertisement
I'm not 100% but maybe check your algorithms.

For converting quaternions to Euler 123 rotations I use


eX = atan2(-2*(qy*qz-qw*qx), qw*qw-qx*qx-qy*qy+qz*qz);
eY = asin(2*(qx*qz + qw*qy));
eZ = atan2(-2*(qx*qy-qw*qz), qw*qw+qx*qx-qy*qy-qz*qz);

And for Euler 123 rotations to quaternions I use


c1 = cos(eX/2);
s1 = sin(eX/2);
c2 = cos(eY/2);
s2 = sin(eY/2);
c3 = cos(eZ/2);
s3 = sin(eZ/2);


qw = c1*c2*c3-s1*s2*s3;
qx = s1*c2*c3+c1*s2*s3;
qy = c1*s2*c3-s1*c2*s3;
qz = c1*c2*s3+s1*s2*c3;

Share this post


Link to post
Share on other sites
You are correct. If I change my quaternion from Euler angle method to the following:



public static Quaternion QuaternionFromEulerAngles(float yaw, float pitch, float roll)
{
// Heading = Yaw
// Attitude = Pitch
// Bank = Roll

yaw *= 0.5f;
pitch *= 0.5f;
roll *= 0.5f;

// Assuming the angles are in radians.
float c1 = (float)Math.Cos(yaw);
float s1 = (float)Math.Sin(yaw);
float c2 = (float)Math.Cos(pitch);
float s2 = (float)Math.Sin(pitch);
float c3 = (float)Math.Cos(roll);
float s3 = (float)Math.Sin(roll);
float c1c2 = c1 * c2;
float s1s2 = s1 * s2;

Quaternion quaternion = new Quaternion();
quaternion.W = c1c2 * c3 - s1s2 * s3;
quaternion.X = c1c2 * s3 + s1s2 * c3;
quaternion.Y = s1 * c2 * c3 + c1 * s2 * s3;
quaternion.Z = c1 * s2 * c3 - s1 * c2 * s3;

return quaternion;
}


then the rotation stays the same.

The XNA 'Quaternion.CreateFromYawPitchRoll' method is either wrong or I have gone wrong somehow?

If someone can explain what might be the cause of this phenomenon then please let me know as I am most interested.

Share this post


Link to post
Share on other sites
I doubt that the XNA function is wrong, you may just be using the output wrong. I'm assuming your using the angles it outputs to draw your 3D scene and for each angle you do something like

rotate(angle1, about axis [1, 0, 0])
rotate(angle2, about axis [0, 1, 0])
rotate(angle3, about axis [0, 0, 1])

sorry for the syntax, but I'm not too familiar with XNA, this is kinda what I do for OpenGL

When converting from Quaternions to Euler angles, the conversion can give one of many types of Euler angles. It probably says somewhere in the documentation. It can be an Euler123 in which you first rotate about the 1(x) axis, then the 2(y), and then the 3(z) or it can be other euler angle sequences such as Euler321, Euler313 etc.

A Euler313 rotation would be

rotate(angle1, about axis [0, 0, 1])
rotate(angle2, about axis [1, 0, 0])
rotate(angle3, about axis [0, 0, 1])

The order in which you rotate these matters. Those are the most common types of Euler angles that I have come across. I'm not really sure what they classify YawPitchRoll as because thats not even always a constant euler rotation (Ex: Spacecraft vs. Aircraft). Maybe try adjusting with the order of rotations you do with the angles given from XNA, if you can't get it to work, I dono, but I'd say just use what works. Good Luck!


Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!