How should I calculate azimuth, pitch, orientation when my Android device isn’t flat?

When the device is not flat, you have to call remapCoordinateSystem(inR, AXIS_X, AXIS_Z, outR); before calling getOrientation.

The azimuth returns by getOrientation is obtained by orthogonally project the device unit Y axis into the world East-North plane and then calculate the angle between the resulting projection vector and the North axis.

Now we normally think of direction as the direction where the back camera is pointing. That is the direction of -Z where Z is the device axis pointing out of the screen. When the device is flat we do not think of direction and accept what ever given. But when it is not flat we expect it is the direction of -Z. But getOrientation calculate the direction of the Y axis, thus we need to swap the Y and Z axes before calling getOrientation. That is exactly what remapCoordinateSystem(inR, AXIS_X, AXIS_Z, outR) does, it keep the X axis intact and map Z to Y.

Now so how do you know when to remap or not. You can do that by checking

float inclination = (float) Math.acos(rotationMatrix[8]);
if (result.inclination < TWENTY_FIVE_DEGREE_IN_RADIAN 
            || result.inclination > ONE_FIFTY_FIVE_DEGREE_IN_RADIAN)
{
    // device is flat just call getOrientation
}
else
{
    // call remap
}

The inclination above is the angle between the device screen and the world East-North plane. It shows how much the device is tilting.

Leave a Comment