在Android应用中重新映射坐标系

时间:2013-12-13 10:53:42

标签: android android-sensors coordinate-transformation sensormanager

我正在实施一个简单的Android应用,我需要识别北方。

所以我实现了SensorEventListener,我使用了这样的东西:

@Override
public void onSensorChanged(SensorEvent event) {
    if(event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR)
    {
        SensorManager.getRotationMatrixFromVector(mRotationMatrix, event.values);
        SensorManager.remapCoordinateSystem(mRotationMatrix, SensorManager.AXIS_X, SensorManager.AXIS_Z, orientationVals);
        SensorManager.getOrientation(mRotationMatrix, orientationVals);

        orientationVals[0] = (float) Math.toDegrees(orientationVals[0]);
        orientationVals[1] = (float) Math.toDegrees(orientationVals[1]);
        orientationVals[2] = (float) Math.toDegrees(orientationVals[2]);

        tv.setText(" Yaw: "+ orientationVals[0] +"\n Pitch: "+ orientationVals[1]+"\n Roll: "+ orientationVals[2]);
    }

}

问题在于代码行

SensorManager.remapCoordinateSystem(mRotationMatrix, SensorManager.AXIS_X, SensorManager.AXIS_Z, orientationVals);

似乎行不通,因为在这两种情况下(有或没有此代码行),Yaw(方位角)的值取决于手机头部的方向(让它放在背面)

根据手机背面(后置摄像头)的方向改变,我的预期是,Yaw发生了变化。

为什么我的重新映射不起作用?

2 个答案:

答案 0 :(得分:2)

不确定你是否解决了这个问题,但你的问题是:

SensorManager.remapCoordinateSystem(mRotationMatrix, SensorManager.AXIS_X, SensorManager.AXIS_Z, orientationVals);

重新映射mRotationMatrix中的值,并将结果放入orientationVals。这是正确的(除了重新映射的坐标数组的令人困惑的变量名称)。

但是,然后通过调用:

直接覆盖此重映射

SensorManager.getOrientation(mRotationMatrix, orientationVals);

这将获取mRotationMatrix中的值,并根据这些(旧的,未重新映射的)值计算方向,并将其存储在orientationVals中。

因此,上面的代码只是获取mRotationMatrix的方向,其轴未重新映射,这可能解释了您的问题。

以下之类的内容可以解决您的问题:

float[] remapCoords = new float[16];
SensorManager.remapCoordinateSystem(mRotationMatrix, SensorManager.AXIS_X, SensorManager.AXIS_Z, remapCoords);
SensorManager.getOrientation(remapCoords, orientationVals);

假设您的轴重映射是您实际想要/正确的,但这是另一个问题。

我应该注意到,article cited虽然最优秀但没有明确提到重映射坐标系必须在每次计算旋转矩阵时调用,而不仅仅是在显示时变化(即onCreate,onSurfaceChanged等),对某些人来说可能是显而易见的,但对其他人来说则不然。

答案 1 :(得分:0)

我用过这个:

/* Compensate device orientation */
            float[] remappedRotationMatrix = new float[9];
            switch (getWindowManager().getDefaultDisplay()
                    .getRotation()) {
            case Surface.ROTATION_0:
                SensorManager.remapCoordinateSystem(rotationMatrix,
                        SensorManager.AXIS_X, SensorManager.AXIS_Y,
                        remappedRotationMatrix);
                break;
            case Surface.ROTATION_90:
                SensorManager.remapCoordinateSystem(rotationMatrix,
                        SensorManager.AXIS_Y,
                        SensorManager.AXIS_MINUS_X,
                        remappedRotationMatrix);
                break;
            case Surface.ROTATION_180:
                SensorManager.remapCoordinateSystem(rotationMatrix,
                        SensorManager.AXIS_MINUS_X,
                        SensorManager.AXIS_MINUS_Y,
                        remappedRotationMatrix);
                break;
            case Surface.ROTATION_270:
                SensorManager.remapCoordinateSystem(rotationMatrix,
                        SensorManager.AXIS_MINUS_Y,
                        SensorManager.AXIS_X, remappedRotationMatrix);
                break;
            }

            /* Calculate Orientation */
            float results[] = new float[3];
            SensorManager.getOrientation(remappedRotationMatrix,
                    results);

请告诉我它是否有效,因为我仍然遇到该解决方案的问题。这是我自己的here代码。我是根据this official post编写的。