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

4

13

I am new in Android and I want to get direction according to my camera. How can I get direction information according to my camera? Could you give an idea for this?

Augusto answered 29/11, 2011 at 18:37 Comment(0)
M
14

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.

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);
Maidenhood answered 14/4, 2014 at 13:5 Comment(2)
The link doesn't seem to be working. Can you please give an example or another link.Toulon
Sure web.archive.org/web/20180501005730/http://…Maidenhood
N
1

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.

Norwich answered 29/11, 2011 at 19:10 Comment(1)
TYPE_ORIENTATION is deprecated, see https://mcmap.net/q/664889/-how-to-get-direction-in-android-such-as-north-westMaidenhood
E
1

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.

Elrod answered 7/8, 2016 at 15:35 Comment(2)
What is mGravity?Millihenry
It's a little over 5 years since I looked at this @AyushSth but I believe it's just an array. Look at the answer right before this one where mGravity & mGeomagnetic are defined.Elrod
P
1

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 an OpenGL-style rotation matrix. As the documentation says, the first value is the compass orientation in radians.

By itself, this doesn't solve your problem of knowing the compass direction from the perspective of your camera. Rather, it assumes the screen is parallel to the ground, like an old-fashioned pocket compass, and it reports which way the top of the screen is pointed. Thus, if the top of the screen is facing north, the orientation (event.values[0]) is 0. If the top of the screen is pointed straight up, the orientation is undefined. Unfortunately, this is a common case when using your camera.

In the example listener, I will use an enum to switch between Android's default pocket-compass style orientation and rear camera orientation, so you can see both the use case Android expects and the one you want.

enum class CompassCoordinateSystem { POCKET_COMPASS, REAR_CAMERA }

Then write a SensorEventListener to track changes. For clarity I did not import android.hardware.SensorManager.* in the code below. All the arrays defined below are populated by SensorManager static methods.

/** The latest compass orientation as a 3D vector. */
private var orientation3D = FloatArray(3)
private var coordinateSystem = CompassCoordinateSystem.REAR_CAMERA_ROTATION

fun compassDegrees(): Float = azimuthToDegrees(compassRadians())
fun compassRadians(): Float = orientation3D[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()
}

override fun onSensorChanged(event: SensorEvent?) {
    if (event?.sensor?.type == Sensor.TYPE_ROTATION_VECTOR) {
         val rotationMatrix = FloatArray(9)
         SensorManager.getRotationMatrixFromVector(rotationMatrix, event.values)
         when (coordinateSystem) {
            CompassCoordinateSystem.POCKET_COMPASS -> SensorManager.getOrientation(rotationMatrix, orientation3D)
            CompassCoordinateSystem.REAR_CAMERA -> {
                val rearCameraMatrix = FloatArray(9)
                // The axis parameters for remapCoordinateSystem() are
                // from an example in that method's documentation
                SensorManager.remapCoordinateSystem(rotationMatrix,
                    SensorManager.AXIS_X, 
                    SensorManager.AXIS_Z, 
                    rearCameraMatrix)
                SensorManager.getOrientation(rearCameraMatrix, orientation3D)
            }
        }
    }
}
Ploughshare answered 29/11, 2018 at 21:25 Comment(3)
It's not clear what your variables are referring to. rotationVector, mValuesOrientation etc.Oratorical
@JaswantSingh: I've rewritten the example, not just to fix the variables but to correct for camera orientation.Ploughshare
I found this answer extremely usefulAne

© 2022 - 2024 — McMap. All rights reserved.