Android手机定位概述,包括指南针

我一直试图让我的头在Android定位传感器一段时间。 我以为我明白了 然后我意识到我没有。 现在我想(希望)我有一个更好的感觉,但我仍然不是100%。 我会试着解释一下我对它的不完整的理解,希望如果我错了或者填空,希望人们能纠正我。

我想我站在0度经度(初级经线)和0度纬度(赤道)。 这个地点实际上是在非洲海岸附近的海域,但是忍耐着我。 我把手机放在我的脸前,让手机的底部指向我的脚; 我面对北(朝格林威治),所以电话的右侧指向东非洲。 在这个方向上(参照下图),我的X轴指向东,Z轴指向南,Y轴指向天空。

现在,手机上的传感器可以让您在这种情况下确定设备的方向(而不是位置)。 这个部分一直让我感到困惑,可能是因为我想明白一件事情在我接受之前是如何运作的。 看起来,这款手机采用两种不同技术的组合来实现其定位。

在这之前,想象一下,在上述的方向上,在经度和纬度为0的​​那块土地上站立。 想象一下,你被蒙住眼睛,你的鞋子被固定在操场上。 如果有人把你推到后面,你会向前(向北)前进,双手伸出来打破你的摔倒。 同样,如果有人推你左肩,你会右手倒下。 你的内耳有“引力传感器” (youtube clip) ,它可以让你检测你是否前倾/后退,或左右/下降(或上升)。 因此,人类可以检测与手机相同的X轴和Z轴的alignment和旋转。

现在想象一下,现在有人在环岛上旋转你90度,这样你现在就可以面向东方了。 您正在绕Y轴旋转。 这个轴是不同的,因为我们无法在生物学上检测到它。 我们知道我们有一定的angular度,但是我们不知道与行星的磁北极有关的方向。 相反,我们需要使用外部工具…磁罗盘。 这使我们能够确定我们面对的是哪个方向。 我们的手机也是如此。

现在手机也有一个3轴加速度计。 我知道他们是如何实际工作的,但是我想象的方式是将重力想象成恒定的,一致的“雨”从天而降,并将上图中的轴想象成能够检测stream过的雨量的pipe。 当手机直立时,所有的雨都会stream经Y'pipe。 如果手机逐渐旋转,屏幕朝向天空,stream过Y的雨量将减less到零,而通过Z的音量将稳定增加,直到最大的雨量stream过。 同样,如果我们现在将手机放在侧面,Xpipe最终会收集到最大的雨量。 因此,根据手机的方向,通过测量stream经3根pipe子的雨量,可以计算出方向。

手机还有一个电子罗盘,就像一个普通的指南针 – 它的“虚拟针”指向磁北。 Android合并来自这两个传感器的信息,以便无论何时产生SensorEventTYPE_ORIENTATIONvalues[3]数组
值[0]:方位angular – (指北针在磁北以东)
值[1]:音高,围绕x轴旋转(是电话前倾还是后退)
值[2]:滚动,围绕y轴旋转(是电话左右倾斜)

所以我认为(即我不知道)Android给出方位angular(指南针方位)而不是第三个加速度计的读数的原因是指南针方位更有用。 我不知道为什么他们不推荐使用这种types的传感器,因为现在看来您需要向types为SensorEvent的系统注册监听TYPE_MAGNETIC_FIELD 。 该事件的value[]数组需要被传递到SensorManger.getRotationMatrix(..)方法来获得旋转matrix(见下文),然后传递到SensorManager.getOrientation(..)方法。 有谁知道为什么Android团队不推荐Sensor.TYPE_ORIENTATION ? 这是一个效率的东西? 这就是类似问题的意见之一,但是您仍然需要在development / samples / Compass / src / com / example / android / compass / CompassActivity.java示例中注册不同types的监听器。

现在我想谈谈旋转matrix。 (这是我最不确定的地方)所以上面我们有Android文档中的三个数字,我们称它们为A,B和C.

A = SensorManger.getRotationMatrix(..)方法图,表示世界坐标系

B = SensorEvent API使用的坐标系。

C = SensorManager.getOrientation(..)方法图

所以我的理解是,A代表“世界坐标系”,我认为这是指地球上的位置以(可选)(海拔)作为(纬度,经度)夫妇的方式。 X是“东向”坐标,Y是“北向”坐标。 Z指向天空并代表高度。

图B所示的电话坐标系是固定的。 它的Y轴始终指出顶部。 旋转matrix不断被电话计算,并允许两者之间的映射。 所以我正确地认为旋转matrix将B的坐标系转换为C? 因此,当您调用SensorManager.getOrientation(..)方法时,您可以使用values[]数组,其值与图C相对应。当手机指向天空时,旋转matrix是单位matrix(matrixmath等价值为1)意味着无需映射,因为该设备与世界坐标系alignment。

好。 我想我现在最好停下来。 就像我以前说过的那样,我希望人们会告诉我,我搞乱了什么或者帮助了什么人(或者让人更加困惑!)

你可能想看看一个屏幕转向值得另一篇文章。 它解释了为什么你需要旋转matrix。

简而言之,手机的传感器始终使用相同的坐标系统,即使设备旋转。

在未locking到单个方向的应用程序中,旋转设备时屏幕坐标系会发生变化。 因此,当设备从默认视图模式旋转时,传感器坐标系不再与屏幕坐标系相同。 在这种情况下,旋转matrix用于将A转换为C(B始终保持固定)。

这是一个代码片段,向您展示如何使用它。

 SensorManager sm = (SensorManager) getSystemService(SENSOR_SERVICE); // Register this class as a listener for the accelerometer sensor sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL); // ...and the orientation sensor sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_NORMAL); //... // The following code inside a class implementing a SensorEventListener // ... float[] inR = new float[16]; float[] I = new float[16]; float[] gravity = new float[3]; float[] geomag = new float[3]; float[] orientVals = new float[3]; double azimuth = 0; double pitch = 0; double roll = 0; public void onSensorChanged(SensorEvent sensorEvent) { // If the sensor data is unreliable return if (sensorEvent.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE) return; // Gets the value of the sensor that has been changed switch (sensorEvent.sensor.getType()) { case Sensor.TYPE_ACCELEROMETER: gravity = sensorEvent.values.clone(); break; case Sensor.TYPE_MAGNETIC_FIELD: geomag = sensorEvent.values.clone(); break; } // If gravity and geomag have values then find rotation matrix if (gravity != null && geomag != null) { // checks that the rotation matrix is found boolean success = SensorManager.getRotationMatrix(inR, I, gravity, geomag); if (success) { SensorManager.getOrientation(inR, orientVals); azimuth = Math.toDegrees(orientVals[0]); pitch = Math.toDegrees(orientVals[1]); roll = Math.toDegrees(orientVals[2]); } } } 

卷是重力的函数,90度卷将所有重力放入x寄存器。

沥青是相同的,一个90度俯仰把所有的重力成分放入ylogging。

偏航/航向/方位对重力没有影响,它始终与重力成直angular,因此无论你面对重力的哪种方式都是不可测量的。

这就是为什么你需要一个指南针来评估,也许这是有道理的?

看看这个: Stackoverflow.com:Q.5202147

你似乎大部分是正确的,直到3个图A,B,C。 之后,你已经感到困惑。

我遇到这个问题,所以我制定了不同的方向。 如果设备以景观方式安装,例如在汽车上,罗盘上的“度数”似乎在269(在西部和北部之间)从0-275(顺时针方向)运行,则从-90向后计数到0,然后从0转到269. 270变成-90

仍然在风景,但与设备躺在我的背上我的传感器给0-360。 而在肖像模式下,它将以0-360的速度在背部仰卧,竖起肖像。

希望能帮助别人