Inconsistent Android orientation sensor values ​​for bearing / yaw and roll

I am having trouble getting good readings from the orientation sensor. The sensor readings seemed unreliable, so I checked my code for two free test applications for sensors ( Sensor Tester (Dicotomica) and Sensor Monitoring (R Software) ). I found that although my readings often agreed with sensor testing applications, sometimes the azimuth / yaw and roll values ​​differed by 40 degrees, although the pitch reading was mostly consistent. Two free apps always seemed to agree with each other.

I put my code in tiny Android activity and got the same inconsistency. The code is as follows:

public class MainActivity extends Activity implements  SensorEventListener {

    private SensorManager mSensorManager;
    private float[] AccelerometerValues;
    private float[] MagneticFieldValues;
    private float[] RotationMatrix;
    private long nextRefreshTime;           // used to ensure dump to LogCat occurs no more than 4 times a second
    private DecimalFormat df;               // used for dumping sensors to LogCat

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mSensorManager = (SensorManager)getSystemService(android.content.Context.SENSOR_SERVICE);
        Sensor SensorAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        mSensorManager.registerListener(this, SensorAccelerometer, SensorManager.SENSOR_DELAY_UI);  
        Sensor SensorMagField = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
        mSensorManager.registerListener(this, SensorMagField, SensorManager.SENSOR_DELAY_UI);
        AccelerometerValues = new float[3];
        MagneticFieldValues = new float[3];
        RotationMatrix = new float[9];
        nextRefreshTime = 0;
        df = new DecimalFormat("#.00");
    }

    @Override
    public void onSensorChanged(SensorEvent event) {

        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
            System.arraycopy(event.values, 0, AccelerometerValues, 0, AccelerometerValues.length);
        else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
                System.arraycopy(event.values, 0, MagneticFieldValues, 0, MagneticFieldValues.length);

        if (AccelerometerValues != null && MagneticFieldValues != null) {
            if(SensorManager.getRotationMatrix(RotationMatrix, null, AccelerometerValues, MagneticFieldValues)) {
                float[] OrientationValues = new float[3];
                SensorManager.getOrientation(RotationMatrix, OrientationValues);

                // chance conventions to match sample apps
                if (OrientationValues[0] < 0) OrientationValues[0] += 2*(float)Math.PI;
                OrientationValues[2] *= -1;

                // dump to logcat 4 times a second
                long currentTimeMillis = System.currentTimeMillis();
                if (currentTimeMillis > nextRefreshTime) {
                    nextRefreshTime = currentTimeMillis+250;
                    Log.i("Sensors",    // arrange output so that numbers line up in columns :-)
                            "(" + AngleToStr(OrientationValues[0]) + "," + AngleToStr(OrientationValues[1]) + "," + AngleToStr(OrientationValues[2])
                            + ") ("+FloatToStr(AccelerometerValues[0]) + "," + FloatToStr(AccelerometerValues[1]) + "," + FloatToStr(AccelerometerValues[2])
                            + ") ("+FloatToStr(MagneticFieldValues[0]) + "," + FloatToStr(MagneticFieldValues[1]) + "," + FloatToStr(MagneticFieldValues[2])+")");
                }               
            }
        }               
    }

    private String AngleToStr(double AngleInRadians) {
        String Str = "   "+Integer.toString((int)Math.toDegrees(AngleInRadians));
        return Str.substring(Str.length() - 3);
    }
    private String FloatToStr(float flt) {
        String Str = "      "+df.format(flt);
        return Str.substring(Str.length() - 6);
    }   

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mSensorManager.unregisterListener(this);
    }

    @Override
    public void onAccuracyChanged(Sensor arg0, int arg1) { }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

}

Im, Galaxy Note 2, Bean 4.1.1. - , ?

24 2013 : . (1) , getWindowManager(). GetDefaultDisplay(). GetRotation() . , remapCoordSystem, , , , , . (2) , , , .

, , (, , ) = (235, -52, -11), . (278, -58, -52), (256, -58, -26), , , .

+5
4

, , , - angular, , SensorManager.getOrientation(...). , , math.stackexchange.com. , .. , , , .

, . , , R SensorManager.getRotationMatrix(...) -

Definition of rotation matrix R

(E x, E y, E z), (N x, N y, N z) (G x, G y, G z) , , . , ,

Definition of azimuth angle phi

+4

. , , . remapCoordSystem getOrientation . .
. X, Y, Z
. XY Android

:

  • . 30 .
    : , , .

  • , , , ( , 1 2 ). . , , .
    : , , , . , , .

  • // logcat ,
    float rotation = (float) Math.atan2 (RotationMatrix [6], RotationMatrix [7]);
    , . , 0 ( ).
    1 2 .
    , , 1 2 .

  • , . , 25 -25 ( ).
    1 , .
    , . 4 .

, . ,

+5

. , , , - 90 , Gimbal lock. , undefined. , , , azumith + roll ( pitch = +90 ), - ( pitch = -90 ), . , , , + .

, android Sensor.TYPE_GRAVITY, . Sensor.TYPE_GRAVITY - , , . , , Android Sensor.TYPE_GRAVITY, .

+2

getOrientation(), :

azimuth = atan2((Ey-Nx), (Ex-Ny))

, Android,

azimuth = atan2(Ey, Ny)

-180 180.

SensorManager.class

public static float[] getOrientation(float[] R, float values[]) {
    /*
     * 4x4 (length=16) case:
     *   /  R[ 0]   R[ 1]   R[ 2]   0  \
     *   |  R[ 4]   R[ 5]   R[ 6]   0  |
     *   |  R[ 8]   R[ 9]   R[10]   0  |
     *   \      0       0       0   1  /
     *
     * 3x3 (length=9) case:
     *   /  R[ 0]   R[ 1]   R[ 2]  \
     *   |  R[ 3]   R[ 4]   R[ 5]  |
     *   \  R[ 6]   R[ 7]   R[ 8]  /
     *
     */
    if (R.length == 9) {
        values[0] = (float)Math.atan2(R[1], R[4]);
        values[1] = (float)Math.asin(-R[7]);
        values[2] = (float)Math.atan2(-R[6], R[8]);
    } else {
        values[0] = (float)Math.atan2(R[1], R[5]);
        values[1] = (float)Math.asin(-R[9]);
        values[2] = (float)Math.atan2(-R[8], R[10]);
    }
    return values;
}
0

All Articles