How to get Direction in Android (Such as North, West)

随声附和 提交于 2019-11-28 11:23:57

TYPE_ORIENTATION is deprecated

We cannot use the Orientation Sensor anymore, we can use the Magnetic Field Sensor and Accelerometer Sensors in tandem to get equivalent functionality. It's more work but it does allow to continue to use a callback to handle orientation changes.

Here is a compass sample : http://www.codingforandroid.com/2011/01/using-orientation-sensors-simple.html

Conversion from accelerometer and magnetic field to azimut :

float[] mGravity;
float[] mGeomagnetic;

public void onSensorChanged(SensorEvent event) {

    if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
        mGravity = event.values;

    if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
        mGeomagnetic = event.values;

    if (mGravity != null && mGeomagnetic != null) {
        float R[] = new float[9];
        float I[] = new float[9];

        if (SensorManager.getRotationMatrix(R, I, mGravity, mGeomagnetic)) {

            // orientation contains azimut, pitch and roll
            float orientation[] = new float[3];
            SensorManager.getOrientation(R, orientation);

            azimut = orientation[0];
        }
    }
}

To point the north you can calculate a rotation in degrees :

float rotation = -azimut * 360 / (2 * 3.14159f);

Here's what I have so far that's somewhat working for me, values returned are between 0 - 360 but I don't think north is properly calibrated? I'm using this on an LG G Pad running Android 5.0.1

public void onSensorChanged(SensorEvent event) {
    if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
        mGravity = event.values;
    if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
        mGeomagnetic = event.values;
    if (mGravity != null && mGeomagnetic != null) {
        float R[] = new float[9];
        float outR[] = new float[9];
        float I[] = new float[9];

        boolean success = SensorManager.getRotationMatrix(R, I, mGravity, mGeomagnetic);
        if (success) {
            float orientation[] = new float[3];

            SensorManager.remapCoordinateSystem(R, SensorManager.AXIS_X, SensorManager.AXIS_Y, outR);

            SensorManager.getOrientation(outR, orientation);
            azimut = orientation[0];

            float degree = (float)(Math.toDegrees(azimut)+360)%360;

            System.out.println("degree " + degree);

I'm sure there are things I've missed but hopefully this is a decent starting point for others. I reviewed a good number of other questions, comments, etc. to get to this point.

Joe

Not sure what you mean by according to your camera, but you can get it based on the hardware sensors. See the following links:

Compass Example

Also check out the Sensor TYPE_ORIENTATION on this page.

Use the Rotation Vector sensor, which combines the geomagnetic and gravitational sensors. Then use SensorManager.getOrientation to convert from an array of 5 values to a rotation matrix. As the documentation says, the first value is the compass orientation in radians.

var positionDegrees = Float.NaN

override fun onSensorChanged(event: SensorEvent?) {
    if (event?.sensor?.type == Sensor.TYPE_ROTATION_VECTOR) {
         val rotationMatrix = FloatArray(9)
         SensorManager.getRotationMatrixFromVector(rotationMatrix, rotationVector)
         val orientationValues = FloatArray(3)
         positionDegrees = azimuthToDegrees(mValuesOrientation[0])
    }
}

/** Convert such that North=0, East=90, South=180, West=270. */
fun azimuthToDegrees(azimuth: Float): Float {
    return ((Math.toDegrees(azimuth.toDouble())+360) % 360).toFloat()
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!