如何将安卓传感器方位角从(-180°;180°)转为0°-360°格式?
问题:将加速度计+磁力计获取的(-180,180)方位角转换为(0,360)格式
我用加速度计+磁力计在地图上绘制方位线,采用了谷歌示例代码,代码如下:
private val sensorManager by lazy { context.getSystemService(Context.SENSOR_SERVICE) as SensorManager } private val lastAccelerometerReading = FloatArray(3) private val latMagnetometerReading = FloatArray(3) private val rotationMatrix = FloatArray(9) private val orientationAngles = FloatArray(3) private var lastAccelerometerSet = false private var lastMagnetometerSet = false override fun onSensorChanged(event: SensorEvent) { if (event.sensor.type == Sensor.TYPE_ACCELEROMETER) { System.arraycopy(event.values, 0, lastAccelerometerReading, 0, lastAccelerometerReading.size) lastAccelerometerSet = true } else if (event.sensor.type == Sensor.TYPE_MAGNETIC_FIELD) { System.arraycopy(event.values, 0, latMagnetometerReading, 0, latMagnetometerReading.size) lastMagnetometerSet = true } if (lastAccelerometerSet && lastMagnetometerSet) updateOrientationAngles() Timber.d("!!! orientation = ${orientationAngles[0] * (180 / Math.PI)}") } override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) = Unit fun registerDeviceOrientationListener() { sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)?.also { accelerometer -> sensorManager.registerListener( this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI ) } sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD)?.also { magneticField -> sensorManager.registerListener( this, magneticField, SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI ) } } fun unregisterDeviceOrientationListener() { sensorManager.unregisterListener(this) } private fun updateOrientationAngles() { SensorManager.getRotationMatrix( rotationMatrix, null, lastAccelerometerReading, latMagnetometerReading ) SensorManager.getOrientation(rotationMatrix, orientationAngles) }
目前代码运行正常,但存在问题:将orientation从弧度转换为度数后,数值范围是(-180;180),而地图需要(0;360)范围的格式。当前方位角以正北为0°,沿东北方向到正南为180°,沿西北方向到正南为-180°;我需要调整为正北为0°,沿西北方向到正南为180°,沿东南方向回到正北为180°-360°,与Google Fused Location中的bearing格式一致,请问该如何实现这一转换?
解决方案
要实现从(-180, 180)到(0, 360)的转换,同时匹配Google Fused Location的bearing规则,只需两步处理:
- 反转方向:原始方位角是顺时针递增(东北→正南),目标是逆时针递增(西北→正南),所以先对原始角度取反。
- 归一化范围:将取反后的角度转换到
(0, 360)区间。
核心转换逻辑
可以直接用一行代码完成转换:
val bearing = ((-orientationAngles[0] * (180 / Math.PI)) + 360) % 360
修改后的代码示例
在onSensorChanged方法中替换原日志输出部分,加入转换逻辑:
override fun onSensorChanged(event: SensorEvent) { if (event.sensor.type == Sensor.TYPE_ACCELEROMETER) { System.arraycopy(event.values, 0, lastAccelerometerReading, 0, lastAccelerometerReading.size) lastAccelerometerSet = true } else if (event.sensor.type == Sensor.TYPE_MAGNETIC_FIELD) { System.arraycopy(event.values, 0, latMagnetometerReading, 0, latMagnetometerReading.size) lastMagnetometerSet = true } if (lastAccelerometerSet && lastMagnetometerSet) updateOrientationAngles() // 转换为Google Fused Location兼容的bearing格式 val bearing = ((-orientationAngles[0] * (180 / Math.PI)) + 360) % 360 Timber.d("!!! bearing = $bearing") }
逻辑说明
- 原始
orientationAngles[0](方位角)定义:正北为0°,顺时针转至正东90°、正南180°、正西-90°,回到正北为-180°。 - 取反后:正北为0°,逆时针转至正西90°、正南180°、正东-90°,回到正北为-180°。
- 加360再取模360:将负数角度转为正数,最终得到0°(正北)→90°(正西)→180°(正南)→270°(正东)→360°(等价于0°)的范围,完全匹配Google Fused Location的bearing格式。
内容的提问来源于stack exchange,提问作者SoulReaver313
相关产品推荐
相关产品推荐

