传感器之间的不同值TYPE_ACCELEROMETER / TYPE_MAGNETIC_FIELD和TYPE_ORIENTATION

有两种方法可以得到3个旋转值(方位angular,俯仰angular,滚转angular)。

一个是注册一个TYPE_ORIENTATIONtypes的监听器。 这是最简单的方法,我得到了每个旋转的正确值范围,如文档所述:方位angular:[0,359]间距:[-180,180]卷:[-90,90]

另一个,第一次看到它时最为精确和复杂。 Android推荐它,所以我想使用它,但我得到不同的值。

方位angular:[-180,180]。 -180/180是S,0,N,90E和-90W。
音高:[-90,90]。 90是90,-90是-90,0是0,但-180/180(与屏幕向下)是0。
卷:[-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){} }; 

请帮忙。 这是非常令人沮丧的。

我必须对待这些价值观还是我做错了什么?

谢谢。

Solutions Collecting From Web of "传感器之间的不同值TYPE_ACCELEROMETER / TYPE_MAGNETIC_FIELD和TYPE_ORIENTATION"

我知道我在这玩线程巫师,但最近我一直在做这个东西,所以我想我会扔我的2分。

该设备不包含指南针或倾斜仪,所以它不直接测量方位angular,俯仰angular或滚动angular。 (我们称之为欧拉angular,BTW)。 相反,它使用加速度计和磁力计,两者都产生三维空间的XYZ向量。 这些用来计算方位angular等值。

vector在设备坐标空间中:

设备坐标

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

世界坐标

因此,设备的“中性”方向平躺在桌子上,设备的顶部朝北。

加速度计产生“向上”方向的vector。 磁力计在“北”方向产生一个vector。 (请注意,在北半球,由于磁倾angular ,这倾向于下降 。)

加速度计vector和磁力计vector可以通过SensorManager.getRotationMatrix()math组合,该函数返回一个3x3matrix,该vector将设备坐标中的vector映射到世界坐标,反之亦然。 对于处于中立位置的设备,此函数将返回单位matrix。

该matrix不随屏幕方向而变化。 这意味着您的应用程序需要知道方向并进行相应的补偿。

SensorManager.getOrientation()获取转换matrix并计算方位angular,俯仰angular和滚转angular值。 这些是相对于处于中立位置的设备而被采取的。

我不知道调用这个函数和使用TYPE_ORIENTATION传感器之间有什么区别,除了该函数允许您先操作matrix。

如果设备向上倾斜90°或靠近它,则欧拉angular的使用会分开。 math上这是一个退化的情况。 在这个领域,设备应该如何知道你是在改变方位angular还是滚动angular?

SensorManager.remapCoordinateSystem()函数可用于操纵变换matrix,以补偿您可能了解的设备方向。 然而,我的实验表明,这并不包括所有的情况,甚至不包括一些常见的情况。 例如,如果您想重新绘制直立的设备(例如拍摄照片),则需要将变换matrix乘以该matrix:

 1 0 0 0 0 1 0 1 0 

在调用getOrientation()之前,这不是remapCoordinateSystem()支持的方向重新映射(如果我错过了某个东西,请纠正我)。

好的,所以说这是一个冗长的说法,如果你使用的是方向,无论是来自TYPE_ORIENTATION传感器还是来自getOrientation(),你都可能做错了。 唯一一次你真正想要欧拉angular的时候,是以一种用户友好的方式显示方向信息,注释照片,驱动飞行仪表显示,或类似的东西。

如果你想做与设备方向有关的计算,那么使用变换matrix和使用XYZ向量几乎肯定会更好。

作为一名顾问,当有人问我涉及欧拉angular的问题时,我回过头来问他们真的想做什么,然后find一种方法来做到这一点。

回顾一下你最初的问题,getOrientation()应该返回[-180 180] [-90 90]和[-180 180](从弧度转换之后)中的三个值。 在实践中,我们将方位angular视为[0 360]中的数字,因此您应该简单地将360添加到您收到的任何负数。 你的代码看起来像书面的正确。 如果我确切地知道你所期望的结果和你所得到的结果将会有所帮助。

编辑补充:多一些想法。 Android的现代版本使用了一种叫做“传感器融合”的东西,这基本上意味着所有可用的input – 加速度计,磁力计,陀螺仪 – 在一个math黑盒(通常是卡尔曼滤波器,但取决于供应商)组合在一起。 所有不同的传感器 – 加速度,磁场,陀螺仪,重力,线性加速度和方向 – 都被视为这个黑盒的输出。

只要有可能,您应该使用TYPE_GRAVITY而不是TYPE_ACCELEROMETER作为getRotationMatrix()的input。

我可能是在黑暗中拍摄的,但如果我正确地理解了你的问题,你想知道为什么你得到[-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; 

这会给你在[0..360]范围内的值,如你所想。

您在计算中缺less一个关键计算。
remapCoordinateSystem调用你做一个getRotationMatrix

添加到你的代码,一切都会好的。
你可以在这里阅读更多。