我正在创建一个地图应用,包括显示您正面对的位置箭头,如下所示:
我直接从SensorManager.getOrientation()
获取方向,使用第一个返回值: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;
}
我做错了什么?有更简单的方法吗?
编辑:为了澄清,我假设用户正在将设备放在他们面前,屏幕指向他们。除此之外,我显然不知道是否只有其中一个旋转。此外,我正在使用用户移动时的动作,但这是在他们静止的时候。
答案 0 :(得分:6)
您是否调用了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轴之间的角度。
答案 1 :(得分:0)
这看起来很棘手。我正在为Android开发一个PNS,我正面临着一个类似的问题,我仍然需要这个问题:How to get the rotation between accelerometer's axis and motion vector?
事情是,如果他不动,我绝对不可能找到用户面向的方向(而不是设备)。那就是人体上没有传感器,那么如果设备保持在绝对相同位置但用户旋转了90°怎么办?我认为没有办法找到这个。
我可以建议(这实际上符合我的问题)是你可以(我不知道你在代码中实际做了什么)使用用户的动作来确定他的标题。让我解释。假设您有第一个位置A.用户转到B.然后您可以构建AB向量并在用户停止时获取用户的标题。然后,您必须将代码限制为他所面向的方向到达目的地。
我知道这不如谷歌地图那么好,但你知道谷歌使用什么吗?我的意思是他们只使用accelero和mag.field传感器吗?
答案 2 :(得分:0)
当用户垂直拿着手机时,似乎获得轴承的合适方法是使用以下内容:
// after calling getRotationMatrix pass the rotationMatix below:
SensorManager.remapCoordinateSystem(inR, AXIS_X, AXIS_Z, outR);
如果你想要处理两种方式(垂直和平面),你可能需要检测它,然后只在垂直时执行这种重映射。
请参阅API文档here。
答案 3 :(得分:0)
您应该调整音高并确定用户是否接近垂直向上握住手机。
我选择了从桌子上的平面向上或向下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);
它运作得很好。 让我知道是否有人可以提出改进建议。感谢。
答案 4 :(得分:0)
我建议应用以下重新映射。就我而言,它适用于前三种情况:
SensorManager.remapCoordinateSystem(rMat, SensorManager.AXIS_Z, SensorManager.AXIS_Y, rMatRemapped);