• 14
• 12
• 9
• 10
• 13

# [solved] Remap Rotation Matrix Axis System?

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

## Recommended Posts

I am using an adapted version of android's getRotationMatrix in a c++ program that reads the phone's sensor data over the network and calculates the device's matrix that is then used for tracking.

The function works fine and calculates the device's orientation. Unfortunately, Ogre3d has a different axis system than the device. So even though rotation about the x-axis works fine, the y and z axis are wrong. Holding the device level and pointing to north (identity matrix). When I pitch, the rotation is correct. But when I roll and yaw the rotations are alternated. Roll is yaw in Ogre3d and vice versa.

A quick look at the two axis system looks like Ogre's system (on the left) is essentially the device's system rotated 90 degrees counter clockwise about the x-axis.

I tried to experiment with various combinations when I fist assign sensor values before the matrix is calculated but no combination seems to work correctly. How would I make sure that the rotation matrix getRotationMatrix() produces displays correctly on Ogre3D?

For Reference here is the function that calculates the matrix:

 bool getRotationMatrix() { //sensor data coming through the network are //stored in accel(accelerometer) and mag(geomagnetic) //vars which the function has access to float Ax = accel[0]; float Ay = accel[1]; float Az = accel[2]; float Ex = mag[0]; float Ey = mag[1]; float Ez = mag[2]; float Hx = Ey * Az - Ez * Ay; float Hy = Ez * Ax - Ex * Az; float Hz = Ex * Ay - Ey * Ax; float normH = (float) Math::Sqrt(Hx * Hx + Hy * Hy + Hz * Hz); if (normH < 0.1f) { // device is close to free fall (or in space?), or close to // magnetic north pole. Typical values are > 100. return false; } float invH = 1.0f / normH; Hx *= invH; Hy *= invH; Hz *= invH; float invA = 1.0f / (float) Math::Sqrt(Ax * Ax + Ay * Ay + Az * Az); Ax *= invA; Ay *= invA; Az *= invA; float Mx = Ay * Hz - Az * Hy; float My = Az * Hx - Ax * Hz; float Mz = Ax * Hy - Ay * Hx; //ogre3d's matrix3 is column-major whereas getRotationMatrix produces //a row-major matrix thus i have tranposed it here orientation[0][0] = Hx; orientation[0][2] = Mx; orientation[0][2] = Ax; orientation[1][0] = Hy; orientation[1][3] = My; orientation[1][2] = Ay; orientation[2][0] = Hz; orientation[2][4] = Mz; orientation[2][2] = Az; return true; }

##### Share on other sites

I am using an adapted version of android's getRotationMatrix in a c++ program that reads the phone's sensor data over the network and calculates the device's matrix that is then used for tracking.

The function works fine and calculates the device's orientation. Unfortunately, Ogre3d has a different axis system than the device. So even though rotation about the x-axis works fine, the y and z axis are wrong. Holding the device level and pointing to north (identity matrix). When I pitch, the rotation is correct. But when I roll and yaw the rotations are alternated. Roll is yaw in Ogre3d and vice versa.

A quick look at the two axis system looks like Ogre's system (on the left) is essentially the device's system rotated 90 degrees counter clockwise about the x-axis.

I tried to experiment with various combinations when I fist assign sensor values before the matrix is calculated but no combination seems to work correctly. How would I make sure that the rotation matrix getRotationMatrix() produces displays correctly on Ogre3D?

For Reference here is the function that calculates the matrix:

 bool getRotationMatrix() { //sensor data coming through the network are //stored in accel(accelerometer) and mag(geomagnetic) //vars which the function has access to float Ax = accel[0]; float Ay = accel[1]; float Az = accel[2]; float Ex = mag[0]; float Ey = mag[1]; float Ez = mag[2]; float Hx = Ey * Az - Ez * Ay; float Hy = Ez * Ax - Ex * Az; float Hz = Ex * Ay - Ey * Ax; float normH = (float) Math::Sqrt(Hx * Hx + Hy * Hy + Hz * Hz); if (normH < 0.1f) { // device is close to free fall (or in space?), or close to // magnetic north pole. Typical values are > 100. return false; } float invH = 1.0f / normH; Hx *= invH; Hy *= invH; Hz *= invH; float invA = 1.0f / (float) Math::Sqrt(Ax * Ax + Ay * Ay + Az * Az); Ax *= invA; Ay *= invA; Az *= invA; float Mx = Ay * Hz - Az * Hy; float My = Az * Hx - Ax * Hz; float Mz = Ax * Hy - Ay * Hx; //ogre3d's matrix3 is column-major whereas getRotationMatrix produces //a row-major matrix thus i have tranposed it here orientation[0][0] = Hx; orientation[0][2] = Mx; orientation[0][2] = Ax; orientation[1][0] = Hy; orientation[1][3] = My; orientation[1][2] = Ay; orientation[2][0] = Hz; orientation[2][4] = Mz; orientation[2][2] = Az; return true; }

From the images you have drawn, it is not a simple rotation, but rather a difference between left hand and right handed coordinate systems. This is controlled by the View and Projection Matrices. You will also need to account for winding order of vertices as well.

##### Share on other sites
You can solve it on different ways.

You can try to multiply the device matrix with a conversion matrix to convert it into your coordinate system.

Try multiplying it with this matrix:
 1 0 0 0 0 1 0 -1 0 

Another way would be to just swap the second and third rows and columns in the matrix and to negate the z axis inside it.

Edit: It should be second and third rows AND columns, not just the rows. Just in case anyone ever reads this again Edited by Buckshag

##### Share on other sites
I found the problem. In my function the unit vectors calculated after the cross products I put them in columns whereas I should be putting them in the rows in their appointed matrix3 cells as usual. Something about row-major and column-major confused me even though I was referring to the elements in 2d [][].

By the way your solution worked! I had tried it before but since my matrix was transposed it didn't work. Thank you very much.

You can solve it on different ways.

You can try to multiply the device matrix with a conversion matrix to convert it into your coordinate system.

Try multiplying it with this matrix:
 1 0 0 0 0 1 0 -1 0 

Another way would be to just swap the second and third rows in the matrix and to negate the z axis inside it.