Gab*_*mas 14 android sensor orientation device-orientation
有两种方法可以获得3个旋转值(方位角,俯仰,滚动).
一个是注册TYPE_ORIENTATION类型的监听器.这是最简单的方法,我从每次旋转中得到正确的值范围,如文档所示:azimuth:[0,359] pitch:[ - 180,180] roll:[ - 90,90]
另一个,你第一次看到它时最精确和最复杂.Android推荐它,所以我想使用它,但我得到不同的值.
方位角:[ - 180,180].-180/180是S,0 i N,90 E和-90 W.
pitch:[ - 90,90 ].90为90,-90为-90,0为0但-180/180(屏幕向下)为0.
roll:[ - 180,180].
我应该得到相同的值,但有小数,对吧?
我有以下代码:
aValues = new float[3];
mValues = new float[3];
sensorListener = new SensorEventListener (){
public void onSensorChanged (SensorEvent event){
switch (event.sensor.getType ()){
case Sensor.TYPE_ACCELEROMETER:
aValues = event.values.clone ();
break;
case Sensor.TYPE_MAGNETIC_FIELD:
mValues = event.values.clone ();
break;
}
float[] R = new float[16];
float[] orientationValues = new float[3];
SensorManager.getRotationMatrix (R, null, aValues, mValues);
SensorManager.getOrientation (R, orientationValues);
orientationValues[0] = (float)Math.toDegrees (orientationValues[0]);
orientationValues[1] = (float)Math.toDegrees (orientationValues[1]);
orientationValues[2] = (float)Math.toDegrees (orientationValues[2]);
azimuthText.setText ("azimuth: " + orientationValues[0]);
pitchText.setText ("pitch: " + orientationValues[1]);
rollText.setText ("roll: " + orientationValues[2]);
}
public void onAccuracyChanged (Sensor sensor, int accuracy){}
};
Run Code Online (Sandbox Code Playgroud)
请帮忙.这非常令人沮丧.
我是否必须对待这些价值观或者我做错了什么?
谢谢.
Edw*_*alk 21
我知道我在这里玩线程死灵法师,但我最近一直在研究这些东西,所以我想我会投入2¢.
该设备不包含罗盘或倾角仪,因此它不直接测量方位角,俯仰或滚动.(我们称之为欧拉角,BTW).相反,它使用加速度计和磁力计,两者都产生3空间XYZ矢量.这些用于计算方位角等值.
向量位于设备坐标空间中:

世界坐标Y朝北,X朝东,Z朝上:

因此,设备的"中性"方向平放在桌子背面,设备顶部朝北.
加速度计在"向上"方向上产生矢量.磁力计在"北"方向上产生矢量.(请注意,在北半球,由于磁性下降,这往往指向下方.)
加速度计矢量和磁力计矢量可以通过SensorManager.getRotationMatrix()进行数学组合,它返回一个3x3矩阵,它将设备坐标中的矢量映射到世界坐标,反之亦然.对于处于中性位置的设备,此函数将返回单位矩阵.
该矩阵不随屏幕方向而变化.这意味着您的应用程序需要了解方向并相应地进行补偿.
SensorManager.getOrientation()获取变换矩阵并计算方位角,俯仰和滚动值.这些是相对于处于中立位置的设备.
我不知道调用此函数和仅使用TYPE_ORIENTATION传感器之间的区别是什么,除了该函数允许您首先操作矩阵.
如果设备向上倾斜90°或接近它,则欧拉角的使用会分开.这是数学上的退化情况.在这个领域,如果您正在改变方位角或滚动,设备应该如何知道?
函数SensorManager.remapCoordinateSystem()可用于操作变换矩阵,以补偿您可能了解的有关设备方向的信息.但是,我的实验表明,这并不包括所有情况,甚至包括一些常见情况.例如,如果要重新映射直立的设备(例如拍摄照片),您可能希望将变换矩阵乘以此矩阵:
1 0 0
0 0 1
0 1 0
Run Code Online (Sandbox Code Playgroud)
在调用getOrientation()之前,这不是remapCoordinateSystem()支持的方向重映射之一[如果我在这里错过了某些内容请有人纠正我].
好吧,所以这一直是一种冗长的说法,如果你使用方向,无论是从TYPE_ORIENTATION传感器还是从getOrientation(),你可能做错了.您实际想要欧拉角的唯一时间是以用户友好的形式显示方向信息,注释照片,驾驶飞行仪表显示或类似的东西.
如果你想进行与设备方向相关的计算,你几乎肯定会更好地使用变换矩阵并使用XYZ向量.
作为一名顾问,每当有人向我提出涉及欧拉角的问题时,我都会备份并询问他们他们真正想要做什么,然后找到一种方法来替代矢量.
回顾一下你原来的问题,getOrientation()应该在[-180 180] [-90 90]和[-180 180](从弧度转换后)中返回三个值.在实践中,我们将方位角视为[0 360]中的数字,因此您只需将360添加到您收到的任何负数.您的代码看起来是正确的.如果我确切地知道你期待什么结果以及你得到了什么,这将有所帮助.
编辑补充:更多的想法.Android的现代版本使用称为"传感器融合"的东西,这基本上意味着所有可用的输入 - 加速器,磁力计,陀螺仪 - 在数学黑盒子中组合在一起(通常是卡尔曼滤波器,但取决于供应商).所有不同的传感器 - 加速度,磁场,陀螺仪,重力,线性加速度和方向 - 都被视为此黑匣子的输出.
只要有可能,您应该使用TYPE_GRAVITY而不是TYPE_ACCELEROMETER作为getRotationMatrix()的输入.
我可能会在黑暗中拍摄,但如果我理解你的问题,你会想知道为什么你会这样做[-179..179]而不是[0..360]?
请注意,-180相同+180和相同180 + N*360,其中N是一个整数(整数).
换句话说,如果您想获得与方向传感器相同的数字,您可以这样做:
// x = orientationValues[0];
// y = orientationValues[1];
// z = orientationValues[2];
x = (x + 360.0) % 360.0;
y = (y + 360.0) % 360.0;
z = (z + 360.0) % 360.0;
Run Code Online (Sandbox Code Playgroud)
这将[0..360]根据您的需要为您提供范围内的值.
您的计算中遗漏了一项关键计算。在执行getRotationMatrix后
调用
remapCooperativeSystem 。
将其添加到您的代码中,一切都会好起来的。
你可以在这里读更多关于它的内容。
| 归档时间: |
|
| 查看次数: |
16712 次 |
| 最近记录: |