Jubei
Jubei

Reputation: 1825

Remap rotation matrix to different axis system

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.

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.

    (Ogre3d)                         ([Device][5])

   ^ +y-axis                       ^ +z-axis                                  
   *                               *                                 
   *                               *                                 
   *                               *    ^ +y-axis                             
   *                               *   *                               
   *                               *  *                                
   *                               * *                                 
   ************> + x-axis          ************> +x-axis                      
  *                                                                   
 *                                                                    
v +z-axis                                                                     

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 getrotatinomatrix 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;
}

Upvotes: 1

Views: 2623

Answers (3)

Jubei
Jubei

Reputation: 1825

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 [][].

multiplying the outcome of the matrix calculation function with this matrix:

1 0 0

0 0 1

0 -1 0

Then pitching the whole result by another p/2 about axis solved the remap problem but I fear my geometry is inverted.

Upvotes: 1

Jay
Jay

Reputation: 14471

Why not just add the one additional rotation you've already identified before you use it in ogre?

Upvotes: 1

J-Rou
J-Rou

Reputation: 2286

I don't know much about Matrix Rotation, but if the Systems rotates like you are showing, I think that youshould do the following:

X Axis stays the same way, so:

float Ax = accel[0];
float Ex = mag[0];

Y Axis in (Ogre3d) is Z axis in ([Device][5]), so:

float Ay = accel[2];
float Ey = mag[2];

Z Axis in (Ogre3d) is the oposite of Y axis in ([Device][5]), so:

float Az = accel[1] * (-1);
float Ez = mag[1] * (-1);

Try that

Upvotes: 0

Related Questions