【问题标题】:How to get Android phone orientation matching human orientation?如何获得与人类方向匹配的Android手机方向?
【发布时间】:2012-04-30 14:00:00
【问题描述】:

我正在制作一个地图应用程序,包括显示你所面对方向的位置箭头,如下所示:

我直接从SensorManager.getOrientation() 获取方向,使用第一个返回值:方位角。当握住手机使屏幕指向地平线上方并且纵向时,箭头可以正常工作。然而:

  • 当手持手机使屏幕指向地平线以下时,箭头指向的方向与用户所面对的方向相差 180 度。
  • 当手机被握在屏幕的朝向与地平线齐平时,箭头不知道它指向哪个方向。 Azimuth 根本不会返回有意义的结果。
  • 当手机向左或向右倾斜(或以横向模式握住)时,箭头向左或向右倾斜。

下面精心构建且科学的图像显示了我的意思(其中蓝色是用户面向,红色是箭头方向,屏幕大致面向用户的面部,Google 地图正是我想要的):

(请注意,使用 Google 地图,如果关闭自动旋转,它不会成功执行列表中的最后两个操作。但我什至还没有到那个阶段。一次一件事。)

它看起来好像只是使用 Y 轴指向方向,如下所示:http://developer.android.com/reference/android/hardware/SensorEvent.html,当我希望它使用 Z 轴指向方向的反向时,大部分时间,以及手机时的 Y平坦的。但是,考虑到getOrientation() 返回的值,我必须编写复杂的案例来解决一些问题,而面向手机的水平用例是无法解决的。我确定有更简单的方法。

这是我的代码(lastAcceleration 和 lastMagneticField 都来自内部传感器):

float[] rotationMatrix = new float[9];
if(SensorManager.getRotationMatrix(rotationMatrix, null, lastAcceleration, lastMagneticField)){
    float[] orientMatrix = new float[3];
    SensorManager.getOrientation(rotationMatrix, orientMatrix);

    orientation = orientMat[0]*180/(float)Math.PI;
}

我做错了什么?有没有更简单的方法来做到这一点?

编辑:为了澄清,我假设用户将设备放在他们面前,并且屏幕指向他们。除此之外,我显然无法判断它们是否只有一个旋转。另外,我使用的是用户移动时的动作,但这是针对他们静止时的。

【问题讨论】:

  • 科学形象+1
  • 您的问题解决了吗?你是如何获得 lastAcceleration、lastMagneticField 的?
  • 不。一直没有解决。也许它永远无法解决,而且谷歌地图似乎没有我当时想的那么聪明。我早就把它从我需要做的任务列表中删除了,因为我不再为同一家公司工作,更不用说同一个项目了。无论如何,Android 现在的工作方式可能完全不同。

标签: android sensors


【解决方案1】:

这看起来很棘手。我正在为 Android 开发 PNS,并且面临着某种类似的问题,我仍然需要光:How to get the rotation between accelerometer's axis and motion vector?

在我看来,如果用户不移动,则绝对不可能找到用户面向的方向(而不是设备)。那就是人的身体上没有传感器,那么如果设备保持在绝对相同的位置但用户旋转了 90° 怎么办?我没有找到任何方法。

我可以建议(实际上适合我的问题)是您可以(我不知道您在代码中实际做了什么)使用用户的动作来确定他的标题。让我解释。假设您有第一个位置 A。用户前往 B。然后您可以构建 AB 向量并在用户停在 B 时获取用户的航向。然后您必须将代码限制为他所面临的方向到达目的地。

我知道这不如 Google Maps 提供的那么好,但您知道 Google 对此有何用途吗?我的意思是他们只使用加速和磁场传感器吗?

【讨论】:

  • 我假设用户将设备放在他们面前,屏幕指向他们。除此之外,我显然无能为力。另外,我正在采取用户的动作。只是,当它们停止时,加速度计和磁场应该会接管。
【解决方案2】:

你调用 remapCoordinateSystem 了吗?否则,您只能在垂直握住手机时获得正确的面值。对于这种情况,当手机被握住时,屏幕的朝向与地平线齐平,你无法获得用户的朝向。因为要获得朝向,您必须将传感器读数的 z 值投影到世界坐标中的 xy 平面中,并且当设备水平放置时它为零。

更准确地说,如果您想让手机面向,那么手机必须与水平方向至少倾斜 25 度,并且您必须调用 remapCoordinateSystem。以下代码将为您提供上面最后 2 张图片所需的内容。
代码

float[] rotationMatrix = new float[9];  

if(SensorManager.getRotationMatrix(rotationMatrix, null, lastAcceleration, lastMagneticField)){
    float[] orientMatrix = new float[3];
    float remapMatrix = new float[9];
    SensorManager.remapCoordinateSystem(rotationMatrix, SensorManager.AXIS_X, SensorManager.AXIS_Z, remapMatrix);
    SensorManager.getOrientation(remapMatrix, orientMatrix);

    orientation = orientMat[0]*180/(float)Math.PI;
}  

假设手机平放,getOrientation 会为您提供正确的值。因此,如果手机垂直握持,则必须重新映射坐标才能获得平坦位置。在几何上,您将手机 -z 轴向下投影到世界 xy 平面,然后计算此投影向量与世界 y 轴之间的角度。

【讨论】:

  • 我不确定我是否遵循。或者也许你没有。当屏幕水平时获得方向并非不可能,因为这既是谷歌所做的,也是我现在所拥有的。我想要在手机垂直时获得正面。和不。我还没有打电话给remapCoordinateSystem。文档并不完全清楚如何使用它。
  • 如果握住手机使屏幕朝向与地平线齐平,则可以获取指南针方向,但不能获取手机朝向。那就是手机面向地面,所以谈论北,南等没有意义......你可以获得“指南针方向”,但这个方向取决于手机的方向。也就是说,如果手机以纵向模式平放在您面前并且指南针显示 0 度,那么当您旋转到横向时,指南针将根据您旋转的方向显示 90 或 270 度。
【解决方案3】:

当用户垂直握住手机时,获得方位的适当方法似乎是使用这样的东西:

// after calling getRotationMatrix pass the rotationMatix below:
SensorManager.remapCoordinateSystem(inR, AXIS_X, AXIS_Z, outR);

如果您想同时处理两种方式(垂直和平面),您可能需要检测到这一点,然后仅在垂直时执行此重新映射。

请参阅 API 文档here

【讨论】:

    【解决方案4】:

    您应该进行宣传并确定用户是否接近垂直向上握住手机。

    我选择了从桌面向上或向下倾斜 45 度后,应重新映射坐标系。

    if (Math.round(Math.toDegrees(-orientation[1])) < 45 && Math.round(Math.toDegrees(-orientation[1])) > -45) {
    //do something while the phone is horizontal
    }else{
    //R below is the original rotation matrix
    float remapOut[] = new float[9];
    SensorManager.remapCoordinateSystem(R, SensorManager.AXIS_X, SensorManager.AXIS_Z, remapOut);
    //get the orientation with remapOut
    float remapOrientation[] = new float[3];
    SensorManager.getOrientation(remapOut, remapOrientation);
    

    效果很好。 让我知道是否有人可以建议对此进行改进。谢谢。

    【讨论】:

      【解决方案5】:

      我建议应用以下重映射。就我而言,它适用于前三个场景: SensorManager.remapCoordinateSystem(rMat, SensorManager.AXIS_Z, SensorManager.AXIS_Y, rMatRemapped);

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-30
        • 1970-01-01
        • 2015-08-03
        • 2019-10-03
        • 2011-11-30
        • 1970-01-01
        相关资源
        最近更新 更多