Quaternion.toEuler() bug?

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
softbike
Posts: 7
Joined: Tue Apr 12, 2011 4:40 am
Location: unkonwn

Quaternion.toEuler() bug?

Post by softbike »

my english is poor....

i use quaternion to rotation...

the following is an example.

vector3df A(0.0, 0.0, 0.0);
Quaternion cQuat(A*core::DEGTORAD);
core::vector3df B;
cQuat.toEuler(B);
B*=core::RADTODEG;

if(B.x < 0.0f)
B.x += 360.0f;
if(B.y < 0.0f)
B.y += 360.0f;
if(B.z < 0.0f)
B.z += 360.0f;

this is Result...
A: 0.00, -0.00, 0.00
B: 0.00, -0.00, 0.00
-------------------------------------------------------- good
A: 90.00, -0.00, 0.00
B: 90.00, -0.00, 0.00
-------------------------------------------------------- good
A: 179.30, 359.18, 0.58
B: 179.30, 359.18, 0.58
-------------------------------------------------------- good
A: 355.82, 345.96, 273.26
B: 355.82, 345.96, 273.26
-------------------------------------------------------- good
A: 4.85, 359.30, 94.33
B: 4.85, 359.30, 94.33
-------------------------------------------------------- good
A: 0.00, 90.00, 270.00
B: 0.00, 90.00, 0.00
-------------------------------------------------------- bad
A: 3.23, 359.65, 10.21
B: 3.23, 359.65, 10.21
-------------------------------------------------------- good
A: 3.23, 359.65, 10.17
B: 3.23, 359.65, 10.17
-------------------------------------------------------- good
A: 0.00, 0.00, 24.04
B: 0.00, 0.00, 24.04
-------------------------------------------------------- good
A: 0.58, 4.36, 334.36
B: 0.58, 4.36, 334.36
-------------------------------------------------------- good
A: 0.00, 0.00, 103.99
B: 0.00, 0.00, 103.99
-------------------------------------------------------- good
A: 0.00, 90.00, 159.51
B: 176.21, 89.98, 335.72
-------------------------------------------------------- bad
A: 0.00, 90.00, 249.48
B: 235.26, 89.98, 124.74
-------------------------------------------------------- bad
A: 0.00, 75.55, 155.89
B: 0.00, 75.55, 155.89
-------------------------------------------------------- good
A: 11.64, 311.52, 345.35
B: 11.64, 311.52, 345.35
-------------------------------------------------------- good
A: 0.00, 0.00, 276.00
B: 0.00, 0.00, 276.00
-------------------------------------------------------- good
A: 90.95, 360.00, 360.00
B: 90.95, 0.00, 0.00
-------------------------------------------------------- good
A: 76.68, 1.11, 18.65
B: 76.68, 1.11, 18.65
-------------------------------------------------------- good
A: 360.00, 0.00, 295.00
B: 0.00, 0.00, 295.00
-------------------------------------------------------- good
A: 360.00, 0.00, 0.00
B: 0.00, 0.00, 0.00
-------------------------------------------------------- good
A: 351.10, 353.37, 9.27
B: 351.10, 353.37, 9.27
-------------------------------------------------------- good
A: 360.00, 360.00, 80.00
B: 0.00, 0.00, 80.00
-------------------------------------------------------- good
A: 360.00, 0.00, 80.00
B: 0.00, 0.00, 80.00
-------------------------------------------------------- good
A: 0.04, 359.99, 9.50
B: 0.04, 359.99, 9.50
-------------------------------------------------------- good
A: 360.00, 0.00, 80.00
B: 0.00, 0.00, 80.00
-------------------------------------------------------- good
A: 360.00, 360.00, 80.00
B: 0.00, 0.00, 80.00
-------------------------------------------------------- good
A: 12.10, 4.72, 11.24
B: 12.10, 4.72, 11.24
-------------------------------------------------------- good
A: 360.00, 360.00, 80.00
B: 0.00, 0.00, 80.00
-------------------------------------------------------- good
A: 0.00, 360.00, 80.00
B: 0.00, 0.00, 80.00
-------------------------------------------------------- good
A: 0.34, 89.58, 360.00
B: 0.34, 89.58, 0.00
-------------------------------------------------------- good
A: 0.00, 284.45, 155.89
B: 0.00, 284.45, 155.89
-------------------------------------------------------- good
A: 14.63, 48.72, 31.79
B: 14.63, 48.72, 31.79
-------------------------------------------------------- good
A: 0.00, 360.00, 286.29
B: 0.00, 0.00, 286.29
-------------------------------------------------------- good
A: 269.05, 0.00, 0.00
B: 269.05, 0.00, 0.00
-------------------------------------------------------- good
A: 283.32, 358.89, 18.65
B: 283.32, 358.89, 18.65
--------------------------------------------------------
A: 360.00, 360.00, 295.00
B: 0.00, 0.00, 295.00
--------------------------------------------------------
A: 0.00, 360.00, 0.00
B: 0.00, 0.00, 0.00
--------------------------------------------------------
A: 8.90, 6.63, 9.27
B: 8.90, 6.63, 9.27
--------------------------------------------------------
A: 360.00, 0.00, 80.00
B: 0.00, 0.00, 80.00
--------------------------------------------------------
A: 360.00, 360.00, 80.00
B: 0.00, 0.00, 80.00
--------------------------------------------------------
A: 359.96, 0.01, 9.50
B: 359.96, 0.01, 9.50
--------------------------------------------------------
A: 360.00, 0.00, 80.00
B: 0.00, 0.00, 80.00
--------------------------------------------------------
A: 360.00, 0.00, 80.00
B: 0.00, 0.00, 80.00
--------------------------------------------------------
A: 347.90, 355.28, 11.24
B: 347.90, 355.28, 11.24
--------------------------------------------------------
A: 0.00, 360.00, 80.00
B: 0.00, 0.00, 80.00
--------------------------------------------------------
A: 360.00, 0.00, 80.00
B: 0.00, 0.00, 80.00
--------------------------------------------------------
A: 0.01, 0.42, 90.38
B: 0.01, 0.42, 90.38
--------------------------------------------------------
A: 0.01, 0.42, 90.38
B: 0.01, 0.42, 90.38
--------------------------------------------------------
A: 115.52, 89.04, 205.51
B: 115.52, 89.04, 205.51
--------------------------------------------------------
A: 180.41, 359.94, 179.69
B: 180.41, 359.94, 179.69
--------------------------------------------------------
A: 0.00, 90.00, 269.91
B: 161.61, 90.00, 71.52
-------------------------------------------------------- bad
A: 0.00, 90.00, 269.91
B: 161.61, 90.00, 71.52
-------------------------------------------------------- bad
A: 180.92, 10.79, 144.53
B: 180.92, 10.79, 144.53
--------------------------------------------------------
A: 0.00, 0.00, 261.73
B: 0.00, 0.00, 261.73
--------------------------------------------------------
A: 358.24, 358.07, 342.82
B: 358.24, 358.07, 342.82
--------------------------------------------------------
A: 0.00, 0.00, 71.19
B: 0.00, 0.00, 71.19
--------------------------------------------------------
A: 90.01, 270.49, 360.00
B: 90.01, 270.49, 360.00
--------------------------------------------------------
A: 180.09, 270.06, 0.00
B: 180.09, 270.06, 0.00
--------------------------------------------------------
A: 173.58, 348.13, 132.25
B: 173.58, 348.13, 132.25
--------------------------------------------------------
A: 360.00, 0.00, 318.30
B: 0.00, 0.00, 318.30
--------------------------------------------------------
A: 359.78, 357.69, 7.52
B: 359.78, 357.69, 7.52
--------------------------------------------------------
A: 0.00, 360.00, 71.00
B: 0.00, 0.00, 71.00
--------------------------------------------------------
A: 269.99, 270.49, 360.00
B: 269.99, 270.49, 0.00
--------------------------------------------------------
A: 181.95, 270.03, 0.00
B: 181.95, 270.03, 360.00
--------------------------------------------------------

Why A and B do not always match...?
please answer ...
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Post by mongoose7 »

Interesting. Is it only Y=90 that causes the problem? What about X=90 or Z=90?

Also, try Y=89, 89.9, 89.99, 89.999.

There seems to be a singularity at 90 degrees. But I don't think Euler angles have any validity at this point. They are a second-rate method for general rotations.
softbike
Posts: 7
Joined: Tue Apr 12, 2011 4:40 am
Location: unkonwn

Post by softbike »

i try 89.9999 ... result is same..

thank you...
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Post by mongoose7 »

OK, I don't want to write code myself, so could you please do this. For the first "bad" test, could you please print out the four values of the quaternion. Thanks.
REDDemon
Developer
Posts: 1044
Joined: Tue Aug 31, 2010 8:06 pm
Location: Genova (Italy)

Post by REDDemon »

i think this has ben fixed in the latest trunk. A guy had the same problem. Are you using irrlicht 1.7.1 , 1.7.2 or 1.8.x?
Junior Irrlicht Developer.
Real value in social networks is not about "increasing" number of followers, but about getting in touch with Amazing people.
- by Me
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Post by mongoose7 »

I just diffed quaternion.h 1.7.2 with SVN 3556 and the only change is the copyright notice. :o
REDDemon
Developer
Posts: 1044
Joined: Tue Aug 31, 2010 8:06 pm
Location: Genova (Italy)

Post by REDDemon »

strange. maybe it needs to be moved to the bug report forum
Junior Irrlicht Developer.
Real value in social networks is not about "increasing" number of followers, but about getting in touch with Amazing people.
- by Me
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Post by mongoose7 »

OK, I wrote some code to check
A: 0.00, 90.00, 270.00
B: 0.00, 90.00, 0.00
I get B: 180, 90, 90

Edit: I just repeated the test and there is a problem. In fact the quaternion is (-0,5, -0.5, 0.5, -0.5) and B is (0, 90, 0), as softbike said.

But B should be (180, 90, 90).
Last edited by mongoose7 on Tue May 03, 2011 2:10 am, edited 2 times in total.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Yes, there is a gimbal lock problem in the toEuler method. Will be fixed in the 1.8 branch soon.
Oh, and Irrlicht's euler angles go from right to left IIRC.
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Quaternion.toEuler() bug?

Post by CuteAlien »

Bit of thread necromancy, but I still had it on my todo to test this and just 8 years later I found the time (not so long, right?). Result of my testing is - this works correct. You don't get the same angles back, but it's still the same rotation.

Code: Select all

 
#ifdef _MSC_VER
#pragma comment(lib, "Irrlicht.lib")
#endif
 
using namespace irr;
using namespace core;
 
float toRange360(f32 x)
{
    if ( x < 0 )
        return x + 360.f;
    if ( x >= 360.f)
        return x - 360.f;
    return x;
}
 
vector3df toRange360(const vector3df& v)
{
    return vector3df(toRange360(v.X), toRange360(v.Y), toRange360(v.Z));
}
 
bool cmrRot(f32 a, f32 b)
{
    const f32 eps = 0.1;
    return core::equals( a, b, eps)
        ||  core::equals( a+360.f, b, eps)
        ||  core::equals( a, b+360.f, eps);
}
 
int main() 
{
    core::array<vector3df> orig;
 
    orig.push_back(vector3df(0.00, -0.00, 0.00));
    orig.push_back(vector3df(90.00, -0.00, 0.00));
    orig.push_back(vector3df(179.30, 359.18, 0.58));
    orig.push_back(vector3df(355.82, 345.96, 273.26));
    orig.push_back(vector3df(4.85, 359.30, 94.33));
    orig.push_back(vector3df(0.00, 90.00, 270.00));
    orig.push_back(vector3df(3.23, 359.65, 10.21));
    orig.push_back(vector3df(3.23, 359.65, 10.17));
    orig.push_back(vector3df(0.00, 0.00, 24.04));
    orig.push_back(vector3df(0.58, 4.36, 334.36));
    orig.push_back(vector3df(0.00, 0.00, 103.99));
    orig.push_back(vector3df(0.00, 90.00, 159.51));
    orig.push_back(vector3df(0.00, 90.00, 249.48));
    orig.push_back(vector3df(0.00, 75.55, 155.89));
    orig.push_back(vector3df(11.64, 311.52, 345.35));
    orig.push_back(vector3df(0.00, 0.00, 276.00));
    orig.push_back(vector3df(90.95, 360.00, 360.00));
    orig.push_back(vector3df(76.68, 1.11, 18.65));
    orig.push_back(vector3df(360.00, 0.00, 295.00));
    orig.push_back(vector3df(360.00, 0.00, 0.00));
    orig.push_back(vector3df(351.10, 353.37, 9.27));
    orig.push_back(vector3df(360.00, 360.00, 80.00));
    orig.push_back(vector3df(360.00, 0.00, 80.00));
    orig.push_back(vector3df(0.04, 359.99, 9.50));
    orig.push_back(vector3df(360.00, 0.00, 80.00));
    orig.push_back(vector3df(360.00, 360.00, 80.00));
    orig.push_back(vector3df(12.10, 4.72, 11.24));
    orig.push_back(vector3df(360.00, 360.00, 80.00));
    orig.push_back(vector3df(0.00, 360.00, 80.00));
    orig.push_back(vector3df(0.34, 89.58, 360.00));
    orig.push_back(vector3df(0.00, 284.45, 155.89));
    orig.push_back(vector3df(14.63, 48.72, 31.79));
    orig.push_back(vector3df(0.00, 360.00, 286.29));
    orig.push_back(vector3df(269.05, 0.00, 0.00));
    orig.push_back(vector3df(283.32, 358.89, 18.65));
    orig.push_back(vector3df(360.00, 360.00, 295.00));
    orig.push_back(vector3df(0.00, 360.00, 0.00));
    orig.push_back(vector3df(8.90, 6.63, 9.27));
    orig.push_back(vector3df(360.00, 0.00, 80.00));
    orig.push_back(vector3df(360.00, 360.00, 80.00));
    orig.push_back(vector3df(359.96, 0.01, 9.50));
    orig.push_back(vector3df(360.00, 0.00, 80.00));
    orig.push_back(vector3df(360.00, 0.00, 80.00));
    orig.push_back(vector3df(347.90, 355.28, 11.24));
    orig.push_back(vector3df(0.00, 360.00, 80.00));
    orig.push_back(vector3df(360.00, 0.00, 80.00));
    orig.push_back(vector3df(0.01, 0.42, 90.38));
    orig.push_back(vector3df(0.01, 0.42, 90.38));
    orig.push_back(vector3df(115.52, 89.04, 205.51));
    orig.push_back(vector3df(180.41, 359.94, 179.69));
    orig.push_back(vector3df(0.00, 90.00, 269.91));
    orig.push_back(vector3df(0.00, 90.00, 269.91));
    orig.push_back(vector3df(180.92, 10.79, 144.53));
    orig.push_back(vector3df(0.00, 0.00, 261.73));
    orig.push_back(vector3df(358.24, 358.07, 342.82));
    orig.push_back(vector3df(0.00, 0.00, 71.19));
    orig.push_back(vector3df(90.01, 270.49, 360.00));
    orig.push_back(vector3df(180.09, 270.06, 0.00));    // different angles, but same rotation
    orig.push_back(vector3df(173.58, 348.13, 132.25));
    orig.push_back(vector3df(360.00, 0.00, 318.30));
    orig.push_back(vector3df(359.78, 357.69, 7.52));
    orig.push_back(vector3df(0.00, 360.00, 71.00));
    orig.push_back(vector3df(269.99, 270.49, 360.00));
    orig.push_back(vector3df(181.95, 270.03, 0.00));    // different angles, but same rotation
    orig.push_back(vector3df(300.00, 240.00, 0.00));    // different angles, but same rotation
 
    const f32 step = 15.f;
    for ( f32 x = -360.f; x <= 360.f; x += step )
        for ( f32 y = -360.f; y <= 360.f; y += step )
            for ( f32 z = -360.f; y <= 360.f; y += step )
            {
                orig.push_back(vector3df(x, y, z));
                orig.push_back(vector3df(x-0.05, y-0.05f, z-0.05));
                orig.push_back(vector3df(x+0.05, y+0.05f, z+0.05));
            }
 
    for ( u32 i=0; i < orig.size(); ++i )
    {
        vector3df A(orig[i]);
 
        quaternion cQuat(A*core::DEGTORAD);
        core::vector3df B;
        cQuat.toEuler(B);
        B *= core::RADTODEG;
 
        B = toRange360(B);
        vector3df Ar = toRange360(A);
 
        // Test if we get same angles back
        if (    !cmrRot(Ar.X, B.X)
            ||  !cmrRot(Ar.Y, B.Y)
            ||  !cmrRot(Ar.Z, B.Z) )
        {
            // still a chance it's same rotation, but with different angles
            irr::core::vector3df v1(123, 345, 678);
            irr::core::vector3df v2(v1);
            irr::core::matrix4 m1, m2;
            m1.setRotationDegrees(A);
            m2.setRotationDegrees(B);
            m1.rotateVect(v1);
            m2.rotateVect(v2);
 
            if (  !v1.equals(v2, 1.f) ) // yeah, there is some difference around gimbal lock, but that's as good as it gets
            {
                std::cout << "A: " << A.X << " " << A.Y << " " << A.Z << "\n";
                std::cout << "B: " << B.X << " " << B.Y << " " << B.Z << "\n";
            }
        }
    }
 
    std::cout << "done\n";
    int ch = std::cin.get();
}
 
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Post Reply