【问题标题】:Getting Direction Vector in Android在 Android 中获取方向向量
【发布时间】:2012-06-17 02:49:28
【问题描述】:

如何获得表示设备背面相对于地球坐标的方向的方向矢量?

例如,如果放在桌子上(屏幕朝上),它应该显示为 [0,0,-1],如果垂直朝北放置,它应该显示为 [1,0,0],等等。

我知道如何根据航向、俯仰和滚动来计算它,只要它们是相对于地球坐标的。在这里要清楚,我不是在寻找角速度,而是在寻找相对于与地球相切的平面的实际当前角度。因此,如果设备垂直放置并朝北,角度“alpha”应该是 0 或 360,角度“beta”应该是 90,而“gamma”应该是 0。我不知道如何获得这些值要么。

我整天都在阅读 API,但我仍然找不到如何获得这些东西。

public void onSensorChanged(SensorEvent event) {
    // ?    
}

感谢您提供任何见解。

【问题讨论】:

    标签: android vector accelerometer sensors gyroscope


    【解决方案1】:

    SensorManager.getRotationMatrix() 做了下面概述的事情,在我发现之前就写好了。我将留下添加的解释,因为如果您想纠正磁北和真北之间的差异,您仍然需要它。

    粗略的算法是得到旋转矩阵,将向量[0,0,-1]乘以它,然后将其调整到您的坐标系。为什么? Android 文档给出了设备和世界的坐标系

    注意 Android 设备坐标中的 [0,0,-1] 点垂直向后远离屏幕。如果您将旋转矩阵 R 乘以该向量,当设备按照您的意愿朝上放在桌子上时,您将在世界坐标中得到 [0,0,-1]。当它直立朝北时,你会得到[0,-1,0],这表明你选择了一个坐标系,其中xy相对于Android系统交换,但这只是约定的改变。

    注意R * [0,0,-1]^T 只是R 否定的第三列。从这里我得到伪代码:

    getRotationMatrix(R);
    Let v = first three elements of third column of R.
    swap v[0] and v[1]
    

    这应该得到你想要的。

    关于getRotationMatrix() 正在做什么的其他信息如下。


    您需要加速度计数据来确定“向下”方向,并需要磁力计数据来确定“北”方向。您必须假设加速度计仅感应重力(设备静止或以稳定的速度移动)。然后您需要将磁力计矢量投影到垂直于重力矢量的平面上(因为磁场通常不与地球表面相切)。这为您提供了两个轴。第三个是正交的,因此可以通过叉积计算。这为您提供了设备系统中的地球坐标矢量。看起来你想要相反的:地球坐标中的设备坐标。为此,只需构造方向余弦矩阵并反转即可。

    我要补充一点,上面的讨论假设磁力计矢量指向北方。我认为(来自高中科学!)它实际上是朝着磁南方向,但手头没有设备所以不能尝试。当然,根据您在地球上的位置,磁北/南与真实的差异为零到 180 度。您可以检索 GPS 坐标并计算实际偏移量。

    如果您不熟悉执行这些操作所需的数学,我可以进一步解释,但必须稍后再说。

    【讨论】:

    • 非常感谢,这真的很有帮助。你们都给出了很好的答案,我希望有一种方法可以同时选择它们。看起来我可以只用 Sensor.TYPE_GRAVITY 获得重力矢量——他们为我工作。我希望得到一个“北”向量同样容易。
    • 我最终通过您的解释得到了它。结果我将重力传感器和磁场传感器返回的值直接传递到 getRotationMatrix() 中,一切都解决了。然后将该矩阵乘以 [0,0,-1] 并得到 dv。
    【解决方案2】:

    阅读本页:http://developer.android.com/reference/android/hardware/Sensor.html

    在 API 8 及更高版本中,存在“虚拟”传感器,它们是通过组合所有可用传感器的输入和适当的过滤器而生成的。 “TYPE_ORIENTATION”传感器为您提供设备的整体方向,但由于某些方向的故障状态,此界面已被弃用。新传感器是 TYPE_ROTATION_VECTOR(API 9 及更高版本),它将您的设备方向作为四元数。这确实是最好用的传感器,但它背后的数学运算有点繁琐。

    如果做不到这一点,你要做的是调用 SensorManager.getRotationMatrix(),传递最新的重力和磁力计数据。这将返回一个旋转矩阵,该矩阵可用于将向量从设备坐标转换为世界坐标,反之亦然(只需转置矩阵以反转它)。

    getOrientation() 函数可以为您提供航向、俯仰和滚动,但这些与 TYPE_ORIENTATION 传感器具有相同的故障状态。

    Examples:
    
      Device flat on a table, top facing north:
        1  0  0
        0  1  0
        0  0  1
    
      Tilted up 30 degrees (rotated about X axis)
        1   0      0
        0   0.86  -0.5
        0   0.5    0.86
    
      Device vertical (rotated about X axis), facing north:
        1  0  0
        0  0 -1
        0  1  0
    
      Device flat on a table, top facing west:
        0 -1  0
        1  0  0
        0  0  1
    
      Device rotated about its Y axis, onto its left side, top
      facing north:
        0  0 -1
        0  1  0
        1  0  0
    

    以下是一些您可能会觉得有用的示例代码:

    public void onSensorChanged(SensorEvent event) {
        long now = event.timestamp;     // ns
    
        switch( event.sensor.getType() ) {
          case Sensor.TYPE_ACCELEROMETER:
            gData[0] = event.values[0];
            gData[1] = event.values[1];
            gData[2] = event.values[2];
            break;
          case Sensor.TYPE_MAGNETIC_FIELD:
            mData[0] = event.values[0];
            mData[1] = event.values[1];
            mData[2] = event.values[2];
            haveData = true;
            break;
        }
    
        if( haveData ) {
            double dt = (now - last_time) * .000000001;
    
            SensorManager.getRotationMatrix(R1, Imat, gData, mData);
            getOrientation(R1, orientation);
            pfdView.newOrientation(orientation[2], (float)dt);
    
    
            Log.d(TAG, "yaw: " + (int)(orientation[0]*DEG));
            Log.d(TAG, "pitch: " + (int)(orientation[1]*DEG));
            Log.d(TAG, "roll: " + (int)(orientation[2]*DEG));
    
            acft.compass = orientation[0];
    
            last_time = now;
        }
    }
    

    【讨论】:

    • 感谢您的回复-我只有两个问题,如果我使用TYPE_ROTATION_VECTOR,量子数是用世界坐标表示的吗?是已经集成了,还是必须集成才能得到当前向量?
    • 设备的世界坐标,我相信。已转换为单位四元数,有时 w 项被省略。老实说,我自己从未使用过它。我上面显示的代码来自我为 1.5 编写的飞行导航应用程序,在新传感器类型可用之前。
    猜你喜欢
    • 1970-01-01
    • 2016-05-18
    • 1970-01-01
    • 2018-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-25
    • 1970-01-01
    相关资源
    最近更新 更多