I am attempting to replicate the absolute rotation values provided by the Device Pose Emulator in Android Studio. Despite trying various sensors and calculation methods, I have been unable to achieve the exact same values.
Specifically, I am looking to obtain the same azimuth, pitch, and roll values as displayed in the Device Pose Emulator. I have experimented with different sensors, including the accelerometer, gyroscope, game rotation vector, and geomagnetic rotation vector, but none have produced the desired results.
Could someone provide guidance on the sensor types or calculation techniques necessary to accurately replicate the absolute rotation values seen in the Device Pose Emulator?
Thank you in advance for any assistance provided.
package com.example.myapplication
import android.content.Context
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import android.os.Bundle
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity(), SensorEventListener {
private lateinit var sensorManager: SensorManager
private lateinit var ivDroid: ImageView
private lateinit var tvX: TextView
private lateinit var tvY: TextView
private lateinit var tvZ: TextView
private var brightness = 0.5f // Initial brightness
private var mAccelerometerData = FloatArray(3)
private var mMagnetometerData = FloatArray(3)
private var mRotationMatrix = FloatArray(9)
private var mOrientationAngles = FloatArray(3)
private lateinit var tvGameRotationVector: TextView
private lateinit var tvGeomagneticRotationVector: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
ivDroid = findViewById(R.id.ivDroid)
tvX = findViewById(R.id.tvX)
tvY = findViewById(R.id.tvY)
tvZ = findViewById(R.id.tvZ)
// Initialize labels
tvGameRotationVector = findViewById(R.id.tvGameRotationVector)
tvGeomagneticRotationVector = findViewById(R.id.tvGeomagneticRotationVector)
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)?.also { accelerometer ->
sensorManager.registerListener(
this,
accelerometer,
SensorManager.SENSOR_DELAY_NORMAL
)
}
sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD)?.also { magneticField ->
sensorManager.registerListener(
this,
magneticField,
SensorManager.SENSOR_DELAY_NORMAL
)
}
}
override fun onResume() {
super.onResume()
sensorManager.registerListener(
this,
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL
)
sensorManager.registerListener(
this,
sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
SensorManager.SENSOR_DELAY_NORMAL
)
}
override fun onPause() {
super.onPause()
sensorManager.unregisterListener(this)
}
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
// Not relevant for this example
}
private var lastPitch: Float = 0.0f // Variable to store the last pitch angle
override fun onSensorChanged(event: SensorEvent?) {
if (event?.sensor?.type == Sensor.TYPE_ACCELEROMETER) {
mAccelerometerData = event.values.clone()
} else if (event?.sensor?.type == Sensor.TYPE_MAGNETIC_FIELD) {
mMagnetometerData = event.values.clone()
}
// Calculate the rotation matrix
val success = SensorManager.getRotationMatrix(
mRotationMatrix,
null,
mAccelerometerData,
mMagnetometerData
)
if (success) {
// Get the absolute orientation angles
SensorManager.getOrientation(mRotationMatrix, mOrientationAngles)
// Convert angles from radians to degrees
val azimuth = Math.toDegrees(mOrientationAngles[0].toDouble()).toInt()
val pitch = Math.toDegrees(mOrientationAngles[1].toDouble()).toInt()
val roll = Math.toDegrees(mOrientationAngles[2].toDouble()).toInt()
// Update labels with absolute angles
runOnUiThread {
tvX.text = "$azimuth"
tvY.text = "$pitch"
tvZ.text = "$roll"
}
}
}
}