SensorManager.getOrientation returns values that are not in angles

437 Views Asked by At

I am trying to implement a business logic layer that tells me on what degree from 180 to -180 is the device currently is in the x axis. It will be used for a camera screen that requires the user to hold the phone vertically.

So in order to do so, I listens to both the TYPE_ACCELEROMETER and to the TYPE_MAGNETIC_FIELD sensors types as suggested in the official docs -

https://developer.android.com/guide/topics/sensors/sensors_position#sensors-pos-prox

And I ended up with the following code -

override fun onSensorChanged(event: SensorEvent?) {
         val value = event?.values ?: return@onSensorChanged
         var accelerometerReading = floatArrayOf()
         var magnetometerReading = floatArrayOf()

          when(event.sensor.type) {
                TYPE_ACCELEROMETER -> {
                    accelerometerReading = floatArrayOf(value[0], value[1], value[2])
                }
                TYPE_MAGNETIC_FIELD -> {
                    magnetometerReading = floatArrayOf(value[0], value[1], value[2])
                }
            }

            val rotationMatrix = FloatArray(9)
            if (magnetometerReading.isEmpty() || accelerometerReading.isEmpty()) return@setOnSensorValuesChangedListener
            SensorManager.getRotationMatrix(rotationMatrix, FloatArray(9), accelerometerReading, magnetometerReading)
            val orientationAngles = FloatArray(3)
            SensorManager.getOrientation(rotationMatrix, orientationAngles) //always returns the same values that are provided to it. why? 

As you can see, I implemented the exact same code as said to do in the official docs but the values I get have nothing to do in the range of 180 to -180 in both 3 of the elements in the orientationAngles array. I get values that are very similar to the input I give it, something like [-0.051408034, -0.007878973, 0.04735359] which is some random irrelevant data for me.

Any idea why would this happen and how to indeed get what I want which is the x axis angle of the device?

Edit:

I'll try to simplify what I want.

Imagine holding a device in portrait mode locked in with it facing you. In a perfect portrait stance I want to get a 90 degree value from the sensor. When the user tilts the device either left or right the values would either go down to 0 or up to 180 (which side it is doesn't matter). All I need is these 2 dimensional x axis values.

1

There are 1 best solutions below

7
Gabe Sechan On

It gives the angles in radians, not degrees. Almost nothing in math uses degrees beyond grade school math, radians is the norm. Radians generally go from 0 to 2*pi, equaling 0 to 360 degrees. The formula to convert is degrees= radians/pi * 180

According to docs, the angles returned by getOrientation returns radians in the range -PI to PI, where 0 is defined by the individual angles. From the docs:

values[0]: Azimuth, angle of rotation about the -z axis. This value represents the angle between the device's y axis and the magnetic north pole. When facing north, this angle is 0, when facing south, this angle is π. Likewise, when facing east, this angle is π/2, and when facing west, this angle is -π/2. The range of values is -π to π.
values[1]: Pitch, angle of rotation about the x axis. This value represents the angle between a plane parallel to the device's screen and a plane parallel to the ground. Assuming that the bottom edge of the device faces the user and that the screen is face-up, tilting the top edge of the device toward the ground creates a positive pitch angle. The range of values is -π/2 to π/2.
values[2]: Roll, angle of rotation about the y axis. This value represents the angle between a plane perpendicular to the device's screen and a plane perpendicular to the ground. Assuming that the bottom edge of the device faces the user and that the screen is face-up, tilting the left edge of the device toward the ground creates a positive roll angle. The range of values is -π to π.