5

I've searched a while about how to get the most accurate azimuth of device and came up with this:

//Activity members
private SensorManager sensorManager;
private float mAzimuth = 0.0f;
private float[] mRotation = null;
private float rMat[] = new float[16];
private float orientation[] = new float[3];
//Later inside the Activity: Rotation Listener
SensorEventListener rotationListener = new SensorEventListener() {
    public void onAccuracyChanged(Sensor sensor, int accuracy) {}
    public void onSensorChanged(SensorEvent event) {
        if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) {
            mRotation = event.values.clone();
            if (mRotation != null) {
                float RmatVector[] = new float[16];
                SensorManager.getRotationMatrixFromVector(RmatVector, mRotation);
                SensorManager.remapCoordinateSystem(RmatVector, SensorManager.AXIS_X, SensorManager.AXIS_Z, rMat); 
                SensorManager.getOrientation(rMat, orientation);
                mAzimuth = (float)Math.toDegrees((double)orientation[0]);  //azimuth
                if (mAzimuth < 0) {
                    mAzimuth = 360 + mAzimuth;
                }   
            }
            mRotation = null;
        }
    }
};

What I tried to do: Implement all newest guidelines of how to achieve the most accurate azimuth reading:

  1. When testing I well aware to all this (calibrating, biasing of electrical devices etc.)
  2. Also it can be seen in the code I've implemented this Google advice:

TYPE_ORIENTATION: This sensor was deprecated in Android 2.2 (API Level 8). The sensor framework provides alternate methods for acquiring device orientation, which are discussed in Using the Orientation Sensor.

The problem is that the resulted azimuth is not accurate significantly and it's something tested with several good devices.

So - Maybe I have some SW bug in my implementation? Or the whole method is wrong?

Thanks,

Community
  • 1
  • 1
michael
  • 3,835
  • 14
  • 53
  • 90
  • 1
    You can modify my code at http://stackoverflow.com/questions/17979238/android-getorientation-azimuth-gets-polluted-when-phone-is-tilted/17981374#17981374 Just remove any code above if (mGravity != null && mMagnetic != null) and change the preceding to if (mRotation != null) – Hoan Nguyen Nov 30 '15 at 17:33
  • @HoanNguyen Thanks, actually it's not seen here but I do smooth the result via Simple Moving Average etc. math tools. But I saw that the core problem is the raw data itself which is completely mess. I'll check your solution more deeply. – michael Nov 30 '15 at 20:58
  • 1
    If you expected the user rotate the device often then use what you have otherwise it is better to use TYPE_ACCELEROMETER and TYPE_GRAVITY. – Hoan Nguyen Dec 01 '15 at 18:00
  • @HoanNguyen Actually my app is "portrait only"... so what you did works really good!... Do you know how we can integrate also the roll and pitch in similar way? Thanks, – michael Dec 01 '15 at 19:22
  • 1
    What do you need roll and pitch for? They seem to be pretty stable without averaging. You might consider what I call inclination in the code. It measure the angle between the device screen and the world xy plane. – Hoan Nguyen Dec 01 '15 at 20:15
  • @HoanNguyen Actually you right - Pitch=inclination. Regarding roll: With what sensor you obtain it? Thanks, – michael Dec 01 '15 at 21:21
  • 1
    TYPE_ACCELEROMETER and TYPE_GRAVITY. Actually, I think if the device is in Lanscape then inclination = roll or roll and pitch switch values. It is better if you just want to know the device angle from earth surface then inclination is better because it is independent of orientation. – Hoan Nguyen Dec 01 '15 at 22:01

0 Answers0