[fixed]Matrix4::getRotationDegrees() returning NaN values

You discovered a bug in the engine, and you are sure that it is not a problem of your code? Just post it in here. Please read the bug posting guidelines first.
Post Reply
fabietto
Posts: 93
Joined: Wed Sep 24, 2008 4:38 pm
Location: Plymouth, UK
Contact:

[fixed]Matrix4::getRotationDegrees() returning NaN values

Post by fabietto »

Dear all,

recently (I can't unfortunately track the exact moment in which this issue has first appeared) the Irrlicht-based application I'm working on has started to behave weirdly. After a lot of debugging, the issues seems to be caused by the Matrix4 method getRotationDegrees(), which, from time to time, returns some NaN values without an apparent reason.

I've been able to write a simple application that reproduces the problem I'm experiencing on both my machines (running MacOS X 10.5 and 10.6 respectively, with Irrlicht 1.7).

I paste the code here:

Code: Select all

#include <irrlicht/irrlicht.h>
#include <nnfw/nnfw.h>
#include <iostream>
#include <ctime>

using namespace std;
using namespace irr;
using namespace irr::core;

matrix4 m, n;
vector3df MAV_currentRotation;
float yaw;

void rotate(vector3df rot) {
	
	m.setRotationDegrees(MAV_currentRotation);
	n.setRotationDegrees(rot);
	m *= n;
	MAV_currentRotation = m.getRotationDegrees();

}

int main(int argc, char *argv[]) {
	
	nnfw::Random::setSeed(10);
	MAV_currentRotation = vector3df(-90.0f, 10.0f, 0.0f);
	
	for (int i=0; i<10000; i++) {
		
		yaw = nnfw::Random::flatReal(0,1); // Generates real values within [0;1]
		
		cout << "Original rotation: " << MAV_currentRotation.X << " " << MAV_currentRotation.Y << " " << MAV_currentRotation.Z << endl;
		rotate(vector3df(0.0f, 0.0f, yaw));
		cout << "New rotation: " << MAV_currentRotation.X << " " << MAV_currentRotation.Y << " " << MAV_currentRotation.Z << endl;
		
		if (isnan(MAV_currentRotation.X)) cout << "Error on iteration " << i << " (" << yaw << " rotation applied)" << endl;
	
	}

	return 0;

}
Please consider that, within the above application, I create random numbers relying on the random number generator provided by an external library (namely NNFW, which can be downloaded from http://www.nnfw.org).

Might be also interesting to note that if I cycle the application for a smaller number of iterations (let's say 100 or 1,000) no errors come out.
Dorth
Posts: 931
Joined: Sat May 26, 2007 11:03 pm

Post by Dorth »

Can't you log the previous result and see if you can reproduce with a minimal number of fixed input?
fabietto
Posts: 93
Joined: Wed Sep 24, 2008 4:38 pm
Location: Plymouth, UK
Contact:

Post by fabietto »

Dorth wrote:Can't you log the previous result and see if you can reproduce with a minimal number of fixed input?
Ups, I forgot to mention that. If I just copy and paste the values that in the application above trigger a NaN value and try to perform a rotation on a "fresh" Matrix4, the values returned by getRotationDegrees() are correct.
fabietto
Posts: 93
Joined: Wed Sep 24, 2008 4:38 pm
Location: Plymouth, UK
Contact:

Post by fabietto »

Ok, forget about what I said in my last message. I've been able to replicate the abnormal behaviour with manually-assigned values. See the code below:

Code: Select all

#include <irrlicht/irrlicht.h>
#include <iostream>

using namespace std;
using namespace irr;
using namespace irr::core;

matrix4 m, n;
vector3df MAV_currentRotation;
float yaw;

void rotate(vector3df rot) {
	
	m.setRotationDegrees(MAV_currentRotation);
	n.setRotationDegrees(rot);
	m *= n;
	MAV_currentRotation = m.getRotationDegrees();

}

int main(int argc, char *argv[]) {

	// Example I
	MAV_currentRotation = vector3df(90.0001f, 270.85f, 180.0f);
	cout << "Original rotation: " << MAV_currentRotation.X << ", " << MAV_currentRotation.Y << ", " << MAV_currentRotation.Z << endl;
	yaw = 0.860866;	
	rotate(vector3df(0.0f, 0.0f, yaw));	
	cout << "New rotation: " << MAV_currentRotation.X << ", " << MAV_currentRotation.Y << ", " << MAV_currentRotation.Z << endl << endl;
	
	// Example II
	MAV_currentRotation = vector3df(270.0f, 89.8264f, 0.000100879f);
	cout << "Original rotation: " << MAV_currentRotation.X << ", " << MAV_currentRotation.Y << ", " << MAV_currentRotation.Z << endl;
	yaw = 0.189398;	
	rotate(vector3df(0.0f, 0.0f, yaw));	
	cout << "New rotation: " << MAV_currentRotation.X << ", " << MAV_currentRotation.Y << ", " << MAV_currentRotation.Z << endl << endl;
	
	// Example III
	MAV_currentRotation = vector3df(270.0f, 89.0602f, 359.999f);
	cout << "Original rotation: " << MAV_currentRotation.X << ", " << MAV_currentRotation.Y << ", " << MAV_currentRotation.Z << endl;
	yaw = 0.949104;	
	rotate(vector3df(0.0f, 0.0f, yaw));	
	cout << "New rotation: " << MAV_currentRotation.X << ", " << MAV_currentRotation.Y << ", " << MAV_currentRotation.Z << endl << endl;

	return 0;

}
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Ok, with these values I could reproduce the problem. Due to rounding errors, the asin of something minimally larger than 1 was calculated, which caused this trouble. It's fixed now in SVN/trunk.
fabietto
Posts: 93
Joined: Wed Sep 24, 2008 4:38 pm
Location: Plymouth, UK
Contact:

Post by fabietto »

hybrid wrote:Ok, with these values I could reproduce the problem. Due to rounding errors, the asin of something minimally larger than 1 was calculated, which caused this trouble. It's fixed now in SVN/trunk.
Thanks for the very prompt fix, Hybrid! Might I ask you which was the file you have had to modify in order to solve this bug?
Sylence
Posts: 725
Joined: Sat Mar 03, 2007 9:01 pm
Location: Germany
Contact:

Post by Sylence »

Well you could have take a look at the svn repository to find out that hybrid commited a change.

The log says he changed 3 files. 2 of them are related to the tests so the third file (include/matrix4.h) is the file you look for.

Comparing the new and the old file you see that line 857 was changed from

Code: Select all

f64 Y = -asin(mat[2]*invScale.X);
to

Code: Select all

f64 Y = -asin(core::clamp(mat[2]*invScale.X, -1.0, 1.0));
Software documentation is like sex. If it's good you want more. If it's bad it's better than nothing.
fabietto
Posts: 93
Joined: Wed Sep 24, 2008 4:38 pm
Location: Plymouth, UK
Contact:

Post by fabietto »

Sylence wrote:Well you could have take a look at the svn repository to find out that hybrid commited a change.

The log says he changed 3 files. 2 of them are related to the tests so the third file (include/matrix4.h) is the file you look for.

Comparing the new and the old file you see that line 857 was changed from

Code: Select all

f64 Y = -asin(mat[2]*invScale.X);
to

Code: Select all

f64 Y = -asin(core::clamp(mat[2]*invScale.X, -1.0, 1.0));
Thanks Sylence. Im not familiar with SVN unfortunately. I've started to download the last trunk (if it's called that way) few minutes ago, just copying/pasting the syntax found in http://sourceforge.net/projects/irrlicht/develop. You've made it definitely easier to me... :)
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

You can also browse the SVN changes here:
http://irrlicht.svn.sourceforge.net/vie ... 0&view=rev
Post Reply