如何让Android手机的方向符合人性化定位?

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

与一个蓝色箭头的地图

我直接从SensorManager.getOrientation()获取方向,使用第一个返回的值:方位angular。 当电话被拿着,以便屏幕指向地平线上方,纵向时,箭头正常工作。 然而:

  • 当手机被拿着以使屏幕指向地平线以下时,箭头指向离用户面对的方向180度。
  • 当手机被拿着,屏幕的朝向与地平线平齐时,箭头就不知道它指向哪个方向。 方位angular不会返回有意义的结果。
  • 当手机向左或向右倾斜(或处于横向模式)时,箭头向左或向右倾斜。

以下精心构build的科学图片展示了我的意思(用户所在的位置是蓝色,箭头方向是红色,屏幕大概面对用户的脸,Google Maps正是我所要的):

发生什么事情与我想要的图表

(请注意,使用Google地图,如果自动旋转closures,它不会成功执行列表中的最后两项操作,但是我甚至不在这个阶段,一次只能做一件事)。

它看起来好像只是使用Y轴的指向方向,如下所示: http : //developer.android.com/reference/android/hardware/SensorEvent.html ,当我想要它使用Z轴反指向的方向,大部分时间,和电话是平的时候。 但是,由于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; } 

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

编辑:只是为了澄清,我假设用户把设备在他们面前,屏幕指向他们。 除此之外,我显然不知道是否只有其中一人旋转。 另外,我正在使用用户在移动时的动作,但是这是在他们静止的时候。

Solutions Collecting From Web of "如何让Android手机的方向符合人性化定位?"

你叫了remapCoordinateSystem? 否则,只有手机垂直放置时,才能获得正确的价值。 对于这种情况当手机被拿着让屏幕的正面与地平线齐平时,你无法获得用户的正面。 因为要获得面对面,所以必须将传感器读数的z值投影到世界坐标系中的xy平面上,并且在器件被水平保持时为零。

更确切地说,如果你想要面对电话,那么手机必须与水平面至less倾斜大约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平面,然后计算此投影vector与世界y轴之间的angular度。

这看起来相当棘手。 我正在为Android开发一个PNS,并面临着一个类似的问题,我仍然需要这个灯光: 如何获得加速度计轴和运动vector之间的旋转?

事情是,如果他没有移动,那么在我看来,绝对不可能find用户面对的方向(而不是设备)。 那是人类身上没有传感器,那么如果设备停留在绝对的相同位置,但是用户旋转了90°呢? 我没有看到任何方式来find这个。

我可以build议的(这实际上适合于我的问题)是,你可以(我不知道你实际上在你的代码中做了什么)使用用户的运动来确定他的标题。 让我解释。 假设你有第一个位置A.用户转到B.然后你可以build立ABvector,并在用户停在B时得到用户的标题。然后,你必须限制你的代码到他面对的方向到达目的地。

我知道这不如Google地图获得的好,但是你知道Google用这个吗? 我的意思是他们只使用加速度传感器和磁场传感器?

看来,当用户垂直拿着手机时,获得方位的恰当方法是使用类似这样的东西:

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

如果你想处理两种方式(垂直和平面),你可能需要检测,然后只在垂直时执行这个重映射。

请参阅此处的API文档。

你应该采取行动,并确定用户是否接近垂直举起手机。

我select了从桌上平面上下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); 

它工作得很好。 让我知道是否有人可以提出一个改进。 谢谢。