More questions about quaternions

Get answers to all your basic programming questions. No Ogre questions, please!
User avatar
Brocan
Orc
Posts: 441
Joined: Tue Aug 01, 2006 1:43 am
Location: Spain!!
x 8

More questions about quaternions

Post by Brocan »

Hi everyone!

I'm trying to convert quaternions to euler (and viceversa) using equations, one of our project doesn't uses ogre, so we can't use its functions.

Currently i've these two equations from this page:
QtE: http://www.euclideanspace.com/maths/geo ... /index.htm
EtQ: http://www.euclideanspace.com/maths/geo ... /index.htm
Standards: http://www.euclideanspace.com/maths/standards/index.htm

My implementation is:

Code: Select all

//http://www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToQuaternion/index.htm
        public void FromEulerAngles(float eulerX, float eulerY, float eulerZ)
        {
            // Assuming the angles are in radians.
            double c1 = System.Math.Cos(eulerY / 2);
            double s1 = System.Math.Sin(eulerY / 2);
            double c2 = System.Math.Cos(eulerZ / 2);
            double s2 = System.Math.Sin(eulerZ / 2);
            double c3 = System.Math.Cos(eulerX / 2);
            double s3 = System.Math.Sin(eulerX / 2);
            double c1c2 = c1 * c2;
            double s1s2 = s1 * s2;
            W = (float)(c1c2 * c3 - s1s2 * s3);
            X = (float)(c1c2 * s3 + s1s2 * c3);
            Y = (float)(s1 * c2 * c3 + c1 * s2 * s3);
            Z = (float)(c1 * s2 * c3 - s1 * c2 * s3);
        }

        //http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/index.htm
        public Vector3 ToEulerAngles()
        {
            Debug.Assert(IsNormalized(), "This formula assumes that the quaternion is normalized...");

            Vector3 p = new Vector3();
            float x = X, y = Y, z = Z, w = W;
 
            double test = x * y + z * w;
            if (test > 0.499)
            { // singularity at north pole
                p.Y = (float)(2.0 * System.Math.Atan2(x, w));
                p.Z = (float)(System.Math.PI / 2.0);
                p.X = 0;
            }
            else if (test < -0.499)
            { // singularity at south pole
                p.Y = (float)(-2.0 * System.Math.Atan2(x, w));
                p.Z = (float)(-System.Math.PI / 2.0);
                p.X = 0;
            }
            else
            {
                double sqx = x * x;
                double sqy = y * y;
                double sqz = z * z;
                p.Y = (float)System.Math.Atan2(2 * y * w - 2 * x * z, 1 - 2 * sqy - 2 * sqz);
                p.Z = (float)System.Math.Asin(2 * test);
                p.X = (float)System.Math.Atan2(2 * x * w - 2 * y * z, 1 - 2 * sqx - 2 * sqz);
            }
            return p;
        }
And my test code:

Code: Select all

public void TestEuler(Vector3 expectedEuler)
        {
            Quaternion convertedQuaternion = new Quaternion();
            convertedQuaternion.FromEulerAngles(expectedEuler);
            Vector3 reconvertedEuler = convertedQuaternion.ToEulerAngles();

            Assert.AreEqual(expectedEuler.X, reconvertedEuler.X, expectedEuler.X * 0.00001f, "Quaternion Euler conversion failed in component X");
            Assert.AreEqual(expectedEuler.Y, reconvertedEuler.Y, expectedEuler.Y * 0.00001f, "Quaternion Euler conversion failed in component Y");
            Assert.AreEqual(expectedEuler.Z, reconvertedEuler.Z, expectedEuler.Z * 0.00001f, "Quaternion Euler conversion failed in component Z");
        }

        [TestMethod()]
        public void TestQuaternions()
        {
            TestEuler(new Vector3(0, (float)Math.PI, (float)Math.PI / 2.0f));
            TestEuler(new Vector3(0.5489f, 1.5475f, 2.6845f));
            
        }
The first test is successful, but the second test is wrong, the values are:
expectedEuler {(0,5489, 1,5475, 2,6845)}
reconvertedEuler {(-2,592693, -1,594092, 0,4570926)}

I've no idea of what i'm doing wrong...

Thanks in advance! :D
Last edited by Brocan on Fri Jun 07, 2013 10:59 am, edited 2 times in total.
al2950
OGRE Expert User
OGRE Expert User
Posts: 1227
Joined: Thu Dec 11, 2008 7:56 pm
Location: Bristol, UK
x 157

Re: Quaternion to Euler Formulae

Post by al2950 »

I use the following code snippet to convert to quaternions;
http://www.ogre3d.org/tikiwiki/tiki-ind ... e=Cookbook

Ogre already has functions to get roll/pitch & yaw from a quaternion. If this is not what you are looking for the code might help you solve your problem!
User avatar
Brocan
Orc
Posts: 441
Joined: Tue Aug 01, 2006 1:43 am
Location: Spain!!
x 8

Re: Quaternion to Euler Formulae

Post by Brocan »

Thanks for your help!

After looking deeply the equations, i've realised that i made a mistake in the equations. I think that these are the correct ones:

Code: Select all

public void FromEulerAngles(float yaw, float pitch, float roll)
        {
            // Assuming the angles are in radians.
            double c1 = System.Math.Cos(yaw * 0.5);
            double s1 = System.Math.Sin(yaw * 0.5);
            double c2 = System.Math.Cos(pitch * 0.5);
            double s2 = System.Math.Sin(pitch * 0.5);
            double c3 = System.Math.Cos(roll * 0.5);
            double s3 = System.Math.Sin(roll * 0.5);
            double c1c2 = c1 * c2;
            double s1s2 = s1 * s2;
            W = (float)(c1c2 * c3 - s1s2 * s3);
            X = (float)(c1c2 * s3 + s1s2 * c3);
            Y = (float)(s1 * c2 * c3 + c1 * s2 * s3);
            Z = (float)(c1 * s2 * c3 - s1 * c2 * s3);
        }

        public Vector3 ToEulerAngles()
        {
            Vector3 p = new Vector3();
            float x = X, y = Y, z = Z, w = W;

            double sqw = w * w;
            double sqx = x * x;
            double sqy = y * y;
            double sqz = z * z;

            double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
	        double test = x*y + z*w;
	        if (test > 0.499*unit) { // singularity at north pole
		        p.Y = (float)(2 * System.Math.Atan2(x,w));
		        p.X = (float)(MathExt.PI * 0.5);
		        p.Z = 0;
	        }
            else if (test < -0.499 * unit)
            { // singularity at south pole
                p.Y = (float)(-2 * (System.Math.Atan2(x, w)));
                p.X = (float)(-MathExt.PI * 0.5);
                p.Z = 0;
            }
            else
            {
                p.Y = (float)(System.Math.Atan2(2 * y * w - 2 * x * z, sqx - sqy - sqz + sqw));
                p.X = (float)(System.Math.Asin(2 * test / unit));
                p.Z = (float)(System.Math.Atan2(2 * x * w - 2 * y * z, -sqx + sqy - sqz + sqw));
            }

            return p
        }
User avatar
Kojack
OGRE Moderator
OGRE Moderator
Posts: 7157
Joined: Sun Jan 25, 2004 7:35 am
Location: Brisbane, Australia
x 535

Re: [Solved] Quaternion to Euler Formulae

Post by Kojack »

Be aware that the resulting euler angles you get from ToEulerAngles may not look anything like the values you originally gave FromEulerAngles, but it is still correct. That's the way eulers work. For any orientation in space, there are multiple combinations of different euler angles that can make it (an infinite number if you consider wrap around, since each euler angle has infinite range while a quaternion is limited to 720 degrees). They will all generate the same quaternion. Going backwards will give you one of the combinations, but may not be the same one you started with.
User avatar
Brocan
Orc
Posts: 441
Joined: Tue Aug 01, 2006 1:43 am
Location: Spain!!
x 8

Re: [Solved] Quaternion to Euler Formulae

Post by Brocan »

Thanks for your tips Kojack :D
User avatar
Brocan
Orc
Posts: 441
Joined: Tue Aug 01, 2006 1:43 am
Location: Spain!!
x 8

Re: [Solved] Quaternion to Euler Formulae

Post by Brocan »

Uhms, i've another question regarding to quaternion math.

If i've a quaternion representing a rotation around the X axis, how i can modify them to apply the rotation around the Z axis?
bstone
OGRE Expert User
OGRE Expert User
Posts: 1920
Joined: Sun Feb 19, 2012 9:24 pm
Location: Russia
x 201

Re: [Solved] Quaternion to Euler Formulae

Post by bstone »

Decompose it using Ogre::Quaternion::ToAngleAxis() then construct a new quaternion using the same angle but Z as the axis.
User avatar
Kojack
OGRE Moderator
OGRE Moderator
Posts: 7157
Joined: Sun Jan 25, 2004 7:35 am
Location: Brisbane, Australia
x 535

Re: [Solved] Quaternion to Euler Formulae

Post by Kojack »

Or if you know it's always exactly around the x axis you can do a shortcut:
q.z = q.x;
q.x = 0;

(But that will break if q.z started as anything other than 0)
User avatar
Brocan
Orc
Posts: 441
Joined: Tue Aug 01, 2006 1:43 am
Location: Spain!!
x 8

Re: [Solved] Quaternion to Euler Formulae

Post by Brocan »

More doubts about quaternions. One (normalized) quaternion could have a different (normalized) one representing equivalent rotation?. Like 270º is equivalent to -90º, but with quaternions. :P
User avatar
Kojack
OGRE Moderator
OGRE Moderator
Posts: 7157
Joined: Sun Jan 25, 2004 7:35 am
Location: Brisbane, Australia
x 535

Re: [Solved] Quaternion to Euler Formulae

Post by Kojack »

Quaternions work on 720 degrees instead of 360 degrees.
So a rotation of 0 degrees and 360 degrees will both look identical on screen, but have different quaternion values. But once you get to 720 degrees it's wrapped back around to the same values as 0 degrees.
270 and -90 are rotations in opposite directions. They end up facing the same direction, but if you smoothly rotated by them over time one goes clockwise and one anticlockwise. The same works with quaternions, you could rotate in opposite directions and end up facing the same way.
User avatar
Brocan
Orc
Posts: 441
Joined: Tue Aug 01, 2006 1:43 am
Location: Spain!!
x 8

Re: [Solved] Quaternion to Euler Formulae

Post by Brocan »

Kojack wrote:Quaternions work on 720 degrees instead of 360 degrees.
So a rotation of 0 degrees and 360 degrees will both look identical on screen, but have different quaternion values. But once you get to 720 degrees it's wrapped back around to the same values as 0 degrees.
270 and -90 are rotations in opposite directions. They end up facing the same direction, but if you smoothly rotated by them over time one goes clockwise and one anticlockwise. The same works with quaternions, you could rotate in opposite directions and end up facing the same way.
Ok, i was afraid of that... :|

My input data seems to move from 0..360 to 360...720 sometimes, if i want to do an average (for smoothing purposes) of (for example) 5 quaternion values, how i can proceed?

Now i'm doing a simple sum by elements divided by num of quaternions, but this is making artifacts in the average if I receive one or more of those equivalent quaternions. I've looked at interpolations, slerp and so on, but the code seems to be only for interpolating between two quaternions... :|

Thanks in advance!
User avatar
Kojack
OGRE Moderator
OGRE Moderator
Posts: 7157
Joined: Sun Jan 25, 2004 7:35 am
Location: Brisbane, Australia
x 535

Re: [Solved] Quaternion to Euler Formulae

Post by Kojack »

if i want to do an average (for smoothing purposes) of (for example) 5 quaternion values, how i can proceed?
I once tried for days to work out a good way of averaging quaternions, I never found an answer.
There's papers around like http://citeseerx.ist.psu.edu/viewdoc/do ... 1&type=pdf that talk about averaging rotations, but they are over my head.

But there may be easier ways depending on what you are trying to do. If you just want a general averaged heading without local roll taken into account, then just add the forward direction of each orientation (such as node->getOrientation() * Ogre::Vector3::NEGATIVE_UNIT_Z) to each other and normalise the result.
User avatar
Brocan
Orc
Posts: 441
Joined: Tue Aug 01, 2006 1:43 am
Location: Spain!!
x 8

Re: [Solved] Quaternion to Euler Formulae

Post by Brocan »

Thank you very much for your tips Kojack :D

The problem is that i need to average the full rotation, i cant forgot the roll :( . I'm going to try to convert the quaterions to euler, averaging them, and go back to quaternion, but i'm think that is going to have the same problems... :|
User avatar
Brocan
Orc
Posts: 441
Joined: Tue Aug 01, 2006 1:43 am
Location: Spain!!
x 8

Re: [Solved] Quaternion to Euler Formulae

Post by Brocan »

Ok, another quaternion question. This is about equality.

I've this two quaternions:

A: {(0,01625779, 0,03296578, 0,3600621, 0,9322039)}
B: {(-0,03867393, -0,02447918, -0,3836132, -0,922359)}

I need to check if they are the same, with a tolerance suppose around 10%. I've made a function based in dot:

Code: Select all

public bool Equals(Quaternion q, float tolerance)
{
     float cosValue = Dot(q);
     float limit = 1.0f - tolerance;
     limit = MathExt.Clamp(limit, 0f, 0.995f);

     if (cosValue > limit)
          return true;
     return false;
}
The cosValue returns -0.999387, so it seems to be fairly the same rotation vector but in the opposite direction, although the W is similar but negate, so i think that the quaternions are the same... in the case of quaternions, if the rotation vector is in opposite direction, and the rotation angle is negated, the represented rotation is the same? I can check the abs value of cosValue? or it's matematically incorrect?

So, this piece of code should be valid?

Code: Select all

public bool Equals(Quaternion q, float tolerance)
{
     float cosValue = Dot(q);
     float limit = 1.0f - tolerance;
     limit = MathExt.Clamp(limit, 0f, 0.995f);

     if (System.Math.Abs(cosValue) > limit)
          return true;
     return false;
}
Thanks!
User avatar
Daixiwen
Greenskin
Posts: 105
Joined: Fri Feb 08, 2013 11:30 am
Location: Oslo
x 16

Re: [Solved] Quaternion to Euler Formulae

Post by Daixiwen »

Although mathematically the two quaternions are different, they do represent the same rotation. When you rotate u with the quaternion q, the operation you make is v = q * u * q\, where q\ is the conjugate of q. You can similarly write that v = (-q) * u * (-q\), so q and -q represent the same rotation. I think you can safely use the absolute value of the dot product.

It is a bit hard to give any physical meaning to the tolerance value though. If you want the tolerance value to have any physical meaning, it could be an idea to convert both quaternions to axis + angle and compare those separately. On the other hand if you just use tolerance to cope for repeated rounding errors then your method is good enough.
bluffy
Gnoblar
Posts: 1
Joined: Mon May 13, 2013 6:19 am

Re: More questions about quaternions

Post by bluffy »

what formula is this how to use this...


Bangalore Packers Movers|Chennai packers and Movers, Currency Trading in India: UFXMARKETS