I'm trying to read the azimuth value off my device. This is done by the following code:
val accelerometerReading = FloatArray(3)
val magnetometerReading = FloatArray(3)
val rotationMatrix = FloatArray(9)
val orientationAngles = FloatArray(3)
val sensorEventListener = object : SensorEventListener {
override fun onSensorChanged(event: SensorEvent?) {
if (event?.sensor?.type == Sensor.TYPE_ACCELEROMETER) {
System.arraycopy(event.values, 0, accelerometerReading, 0, accelerometerReading.size)
} else if (event?.sensor?.type == Sensor.TYPE_MAGNETIC_FIELD) {
System.arraycopy(event.values, 0, magnetometerReading, 0, magnetometerReading.size)
}
// Update rotation matrix, which is needed to update orientation angles.
SensorManager.getRotationMatrix(
rotationMatrix,
null,
accelerometerReading,
magnetometerReading
)
// "rotationMatrix" now has up-to-date information.
SensorManager.getOrientation(rotationMatrix, orientationAngles)
val azimuth = orientationAngles[0]
val azimuth180Degrees = Math.toDegrees(azimuth.toDouble())
val azimuth360Degrees = (azimuth180Degrees + 360) % 360
Timber.d("azimuth $azimuth --- azimuth180Degrees $azimuth180Degrees --- azimuth360Degrees $azimuth360Degrees")
}
}
To check that the azimuth reading was correct i did a test where i put the device flat on my table. I started to turned it slowly until i had done a full 360 degrees turn.
The test did not go as expected. My azimuth ranged from around 1.1 to 2.2. I expected to see values ranging from -PI to PI.
After 2 days of googling, I've not been able to find a bug in my code, so i decided to test it on an emulator. I did a new test where i rotated the emulator to y = 180, x = -90 and i started sliding the z axis. This test did return ranges from -PI to PI.
To test my real device some more, i opened google maps and downloaded some compass apps. They all show my current direction as intended. So the hardware in my device must be working as intended.
I'm at a point where I'm not really sure how to get my azimuth working as intended (full range of -PI to PI), do i have a bug in my code? Am i missing anything?
Your code works fine for me, but I did need to calibrate the sensor by waving the phone around like this
otherwise north was off a fair bit and it thought south was 90 degrees from that! I get the same thing in Google Maps too (they used to show that diagram to get you to calibrate the compass) and a compass app on the phone too.
These sensors can be unreliable (and it depends on the device too) and often apps will use techniques to keep the display consistent, e.g. a navigation app could determine the way you're facing by your movement on GPS, or by the orientation of the part of the road you're on, and ignoring small changes to keep things smooth and stable. In reality the raw sensor data is extremely noisy and inconsistent! Unless it's on an emulator of course, where it can be unrealistically perfect. (btw your orientations should all be at zero to emulate a flat device, parallel to the ground, top facing north)
I don't know if there's a particular issue with your device (or if this explains the behaviour) but I'd check you're not seeing these calibration issues, compare with other apps by being careful not to lift the device, avoid being too close to devices with their own magnetic field etc