Search code examples
androidpositionandroid-sensorscompasscompass-geolocation

Get angle between phone's z axis and the magnetic north pole (instead of y axis)


I am aware how to get the orientation angle between the y-axis of the phone and the magnetic north using the getOrientation method (as described here https://developer.android.com/guide/topics/sensors/sensors_position). However, I would need the orientation between the z-axis of the phone and the magnetic north, so to get the direction of the phone's camera. I have tried writing my own code to calculate this angle from the angle between the y-axis and the magnetic north, but it gives me unreliable data, even if corrected with the gravity sensor data (e.g. when the phone is flipped over).

Is there a way to directly get the angle between the z-axis and the magnetic north?

enter image description here


Solution

  • Building on this question, I would suggest this:

        private val rotationMatrix = FloatArray(9)
    
        override fun onSensorChanged(event: SensorEvent) {
            if (event.sensor.type != Sensor.TYPE_ROTATION_VECTOR) return
            SensorManager.getRotationMatrixFromVector(rotationMatrix, event.values)
            val azimuth = atan2(-rotationMatrix[2], -rotationMatrix[5])
            ... use azimuth ...
        }
    

    Reasoning:

    (rotationMatrix[2], rotationMatrix[5]) describes the projection of the phone's z-vector on the Earth's horizontal plane, in terms of the (east, north) coordinates. You need the angle to the north axis, so the north-direction is your x and the east-direction is the y. atan2 takes the parameters in the (y, x) order, that's why I put the index 2 first and then 5. The z-vector points out of the front of the phone, but I presume you want the direction of the phone's back, where the main camera is. That's why I put the minus signs.