【发布时间】:2011-01-27 17:20:33
【问题描述】:
一段时间以来,我一直试图了解 Android 方向传感器。 我以为我明白了。然后我意识到我没有。现在我想(希望)我再次对它有更好的感觉,但我仍然不是 100%。我将尝试解释我对它的不完整理解,如果我有部分错误或填写任何空白,希望人们能够纠正我。
我想我站在经度 0 度(本初子午线)和纬度 0 度(赤道)。这个位置实际上是在非洲海岸附近的海域,但请耐心等待。我把手机放在脸前,让手机底部指向我的脚;我面向北方(朝向格林威治),因此电话的右侧指向东方,指向非洲。在这个方向上(参考下图)我的 X 轴指向东方,Z 轴指向南方,Y 轴指向天空。
现在,手机上的传感器可让您在这种情况下计算出设备的方向(而不是位置)。这部分一直让我感到困惑,可能是因为在我接受它确实有效之前,我想了解它是如何工作的。手机似乎使用两种不同技术的组合来确定其方向。
在我开始之前,想象一下站在那块假想的 0 度纬度和经度的土地上,站在上面提到的方向。还想象一下,你被蒙上眼睛,你的鞋子被固定在操场上的环形交叉路口。如果有人从背后推你,你会向前(朝北)摔倒并伸出双手来阻止摔倒。同样,如果有人推你的左肩,你会用右手摔倒。你的内耳有“重力传感器”(youtube clip),它可以让你检测到你是向前/向后跌倒,还是向左/向右跌倒或跌倒(或向上!!)。因此,人类可以检测到与手机相同的 X 轴和 Z 轴周围的对齐和旋转。
现在想象有人现在在环形交叉路口将您旋转 90 度,这样您现在面向东方。您正在绕 Y 轴旋转。这个轴是不同的,因为我们无法从生物学上检测到它。我们知道我们有一定的角度,但我们不知道相对于地球磁北极的方向。 相反,我们需要使用外部工具……磁罗盘。这使我们能够确定我们所面对的方向。我们的手机也是如此。
现在手机还配备了 3 轴加速度计。我不知道它们实际上是如何工作的,但我想象它的方式是将重力想象为从天而降的恒定且均匀的“雨”,并将上图中的轴想象为可以检测到的管流过的雨水量。当手机直立时,所有的雨水都会流过 Y '管'。如果手机逐渐旋转,使其屏幕面向天空,流过 Y 的雨量将减少到零,而流过 Z 的音量将稳步增加,直到流过的雨量达到最大。同样,如果我们现在将手机倾斜到一侧,X 管最终将收集到最大量的雨水。因此,根据手机的方向,通过测量流过 3 个管子的雨水量,您可以计算出方向。
手机还有一个电子罗盘,其行为类似于普通罗盘——它的“虚拟指针”指向磁北。 Android 会合并来自这两个传感器的信息,以便每当生成 TYPE_ORIENTATION 的 SensorEvent 时,values[3] 数组就有
values[0]: 方位角 - (指南针方位在磁北以东)
values[1]:俯仰、绕 x 轴旋转(手机是向前还是向后倾斜)
values[2]:滚动,绕y轴旋转(手机是靠左还是靠右)
所以我认为(即我不知道)Android 给出方位角(罗盘方位)而不是第三个加速度计读数的原因是罗盘方位更有用。我不确定他们为什么不推荐使用这种类型的传感器,因为现在看来您需要在系统中为SensorEvents 类型为TYPE_MAGNETIC_FIELD 注册一个侦听器。事件的value[] 数组需要传递给SensorManger.getRotationMatrix(..) 方法以获取旋转矩阵(见下文),然后将其传递给SensorManager.getOrientation(..) 方法。
有谁知道为什么 Android 团队不推荐使用Sensor.TYPE_ORIENTATION?是效率问题吗?这就是其中一个 cmets 与类似的 question 所暗示的内容,但您仍然需要在 development/samples/Compass/src/com/example/android/compass/CompassActivity.java 示例中注册不同类型的侦听器。
我现在想谈谈旋转矩阵。 (这是我最不确定的地方) 所以上面我们有来自 Android 文档的三个数字,我们将它们称为 A、B 和 C。
A = SensorManger.getRotationMatrix(..) 方法图并表示世界坐标系
B = Coordinate system used by the SensorEvent API.
C= SensorManager.getOrientation(..) 方法图
所以我的理解是 A 代表“世界坐标系”,我认为它是指地球上的位置以(纬度,经度)和可选(高度)的形式给出的方式。 X 是"easting" 坐标,Y 是"northing" 坐标。 Z 指向天空,代表高度。
手机坐标系如图B所示,是固定的。它的 Y 轴总是指向顶部。手机不断计算旋转矩阵,并允许两者之间的映射。那么我认为旋转矩阵将 B 的坐标系转换为 C 的想法是否正确?因此,当您调用 SensorManager.getOrientation(..) 方法时,您使用的 values[] 数组的值对应于图 C。
当手机指向天空时,旋转矩阵是单位矩阵(矩阵数学等价于 1),这意味着不需要映射,因为设备与世界坐标系对齐。
好的。我想我现在最好停下来。就像我之前说的,我希望人们会告诉我我在哪里搞砸或帮助了人们(或者让人们更加困惑!)
【问题讨论】:
-
我真的很喜欢这个问题。我无法回答,但我喜欢它。
-
蒂姆,你得到答案了吗?我也一直在挠头。这是我见过的文档记录最差的 API 之一。
-
恐怕不是。我不得不继续前进。总有一天我会回到这个问题。
-
Here 我也有同样的问题,差不多吧?还有Response, solution。在 Github 上制作 public my code。
-
我想知道同样的事情,我已经在 android 设备上实现了一个指南针,如果我从互联网上获得帮助,它工作正常,但令人困惑的是......假设我的设备放在地面上,面向我,它指向北方,现在我拿起手机,垂直放在头顶上方,脸仍然朝向我。首先,针是否应该改变它的方向以及为什么。根据我的想法,它不应该因为我没有改变我的方向,但它正在我的应用程序和我下载的所有其他应用程序中发生变化。谁能解释一下为什么?
标签: android orientation device-orientation bearing compass-geolocation