Page 1 of 1

Quaternion::getYaw() returns NaN (not defined)

Posted: Thu Apr 28, 2011 12:28 pm
by Beauty
I found out that the function Quaternion::getYaw() returns a NaN (not defined) value for some special cases.

The special cases are:

Yaw = +/- 90 degree (positive 90 or negative 90)
Pitch = random
Roll = 0 degree


The result I got from a test code written in C#.
node is a SceneNode.
The Euler Angles are referenced by the variables yaw, pitch, roll.

Code: Select all

// create quaternion and apply rotations
node.Orientation = new Quaternion(new Degree(yaw), Vector3.UNIT_Y);
node.Pitch(new Degree(pitch), Node.TransformSpace.TS_LOCAL);
node.Roll(new Degree(roll), Node.TransformSpace.TS_LOCAL);

quat = node.Orientation; // get quaternion

result = quat.Yaw.ValueDegrees;  // get yaw value
Questions:
Is the return of a NaN (not defined) value a bug?
If not, what's the reason?

I think it's very bad, when Quaternion::getYaw() returns an undefined value in some special cases.
This behaviour was the reason of infrequently application crashes. It tooks some time to find out the reason. Similar problems could happen to other developers. So we should avoid NaN return if possible.

Note:
I use Ogre (Mogre) 1.6.5.
Maybe the bug is still fixed in newer version.

Re: Quaternion::getYaw() returns NaN (not defined)

Posted: Fri Apr 29, 2011 6:59 am
by Kojack
Does Mogre use Ogre's math code for quaternions? I think it used it's own vector math instead of wrapping ogre's for performance.
If so, it might not have the same protection.
getYaw does an asin operation. This MUST be given a value between -1 to 1. Outside of that range will cause a nan. Even slight floating point errors like 1.000001 will fail. Ogre provides Math::ASin, which protects asin from being called with bad values. The Ogre getYaw function calls Math::ASin, but maybe the Mogre getYaw is doing asin directly.
That's the only operation in there that could cause a nan, assuming that the quaternion didn't contain a nan to start with.

There are problems with the getYaw and related functions though. I was testing them a few days ago (while making a new version of my Euler class) and I found that the returned values are wrong in many cases. Not just the usual thing where several different combination of eulers result in the same quaternion, this was giving results that were mirrored along the x or y axes. Converting the quaternion to a matrix3, then calling one of the toeuler methods gave the correct results.

I haven't had time to look into it more yet.

Re: Quaternion::getYaw() returns NaN (not defined)

Posted: Fri Apr 29, 2011 3:09 pm
by Beauty
Thanks for your answer.
You got a good idea. I will look to the Mogre source code.

Also thanks for the hint to use the rotation matrix for better results.
Did you publish your Euler Angle class?

Re: Quaternion::getYaw() returns NaN (not defined)

Posted: Sat Apr 30, 2011 3:39 am
by Kojack
The euler class is on the wiki, but I'm rewriting it to be better. Work's been pretty heavy though, I haven't had much time for ogre coding (except when it's directly for work).

Re: Quaternion::getYaw() returns NaN (not defined)

Posted: Sat Aug 06, 2011 12:48 pm
by Beauty
Ok, I found it (and added some wiki tags):
http://www.ogre3d.org/tikiwiki/Euler+Angle+Class
Kojack wrote:I'm rewriting it to be better

Did you rewrite it in the last 3 months?

Re: Quaternion::getYaw() returns NaN (not defined)

Posted: Sat Aug 06, 2011 1:13 pm
by Beauty
Kojack wrote:Does Mogre use Ogre's math code for quaternions? [...]
Ogre provides Math::ASin, which protects asin from being called with bad values. The Ogre getYaw function calls Math::ASin, but maybe the Mogre getYaw is doing asin directly.
That's the only operation in there that could cause a nan [...]
Today I looked to the Mogre source code.
Your suggestion was a good point. :D
Radian Quaternion::Yaw::get()
{
return Radian(System::Math::Asin(-2*(x*z - w*y)));
}
I will post it in the Mogre forum.
Either we use the (wrapped) Ogre function instead or use it's improved code.

Thanks !!

Kojack wrote:I found that the returned values are wrong in many cases.
What do you think about integration of your improved Euler Class to the official Ogre code?
This would prevent headache of other users, too.

Re: Quaternion::getYaw() returns NaN (not defined)

Posted: Sun Aug 07, 2011 5:01 pm
by Kojack
What do you think about integration of your improved Euler Class to the official Ogre code?
I wouldn't mind having it added in.
But it needs some repairs first. It's angles are opposite direction compared to ogre (there were reasons for that, but I don't believe them any more).

I tend to get distracted thinking about ways to make it configurable (set each axis to wrapping, limited, etc) but fast, which usually ends up as a mess of template parameters.
I'm on holidays soon, I'll try fixing it up then.

Re: Quaternion::getYaw() returns NaN (not defined)

Posted: Mon Aug 08, 2011 3:10 pm
by Beauty
A configurable class would be fine.
I confirm that performance should be an important point.

Perhaps your class doesn't become "default".
But as optional class it could be useful.

It could be used as "converter" class, where each instance is responsible only for one quaternion (or a SceneNode).
The constructor could receive a reference to the quaternion or SceneNode. (Instead of creating a copy.)
Then you can apply optional configuration settings.
As result you just query values from this class instance.

For usage of multiple quaterions/SceneNodes you could offer a related update method.

Here is a code example

Code: Select all

// setup
EulerConverter ec = new EulerConverter(mySceneNode.Orientation);
ec.WrapXAxis = true;
ec.AngleUnit = Ogre.Math.AngleUnit.AU_DEGREE;
// query
Single myYaw = ec.getYaw();
// change usage to other quaternion
ec.relatedQuaternion(otherNode.Orientation);
Well, this is just an idea.
For now enjoy your holidays. :D

Re: Quaternion::getYaw() returns NaN (not defined)

Posted: Mon Aug 08, 2011 3:19 pm
by CABAListic
Is it necessary to add it to Ogre? Ogre doesn't need it, and if you want to use it, you can just add it to your project; from the looks of it the class is functioning on its own.
Just saying, the general consensus was to make Ogre leaner and more modular, so I'm not sure that adding additional utility classes is advisable.

Re: Quaternion::getYaw() returns NaN (not defined)

Posted: Mon Aug 08, 2011 4:18 pm
by Beauty
Kojack wrote:
What do you think about integration of your improved Euler Class to the official Ogre code?
I wouldn't mind having it added in. [...]
I tend to get distracted thinking about ways to make it configurable.
Well, my suggested solution also can be used as external class.
It was just an idea how a flexible query could be implemented.

Sometimes it's a good thing to add useful things to the Ogre core, although there is no absolutely need.
On the other hand you are right, that the core shouldn't be unnecessarily blowed up.

Re: Quaternion::getYaw() returns NaN (not defined)

Posted: Tue Aug 09, 2011 5:45 pm
by eddy
So, how is this getting along? I have implemented some Roll and Pitch joints, and so far I didn't get a NaN result. Now I am torn between using the inbuilt system vs making an own function.

And, can we expect the YAW co-domain return values to be fixed to give results like ROLL and PITCH?