指南针方向因手机方向而异

时间:2011-12-24 16:59:18

标签: android orientation augmented-reality compass-geolocation android-sensors

我的增强现实应用程序需要摄像机视图的罗盘方位,并且有很多从传感器管理器获取方向的示例。

然而,根据手机方向,我发现结果值不同 - 向右旋转的景观与向左旋转的景观大约相差10度(ROTATION_0和ROTATION_180之间的差异较小,但仍然不同)。这种差异足以破坏任何AR效应。

是否与校准有关? (我不相信我正在做正确的8件事 - 我尝试过在youtube上找到的各种方法)。

任何想法为什么会有区别?我搞砸了旋转矩阵的东西吗?我可以选择将应用程序限制在一个方向,但仍然担心指南针读数仍然不是很准确(即使过滤后相当稳定)

public void onSensorChanged(SensorEvent event) {
        if (event.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE) {
            return;
        }

        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)  mGravity = event.values;
        if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) mGeomagnetic = event.values;

        if (mGravity != null && mGeomagnetic != null) {

            float[] rotationMatrixA = mRotationMatrixA;
            if (SensorManager.getRotationMatrix(rotationMatrixA, null, mGravity, mGeomagnetic)) {

                float[] rotationMatrixB = mRotationMatrixB;

                Display display = getWindowManager().getDefaultDisplay(); 
                int deviceRot = display.getRotation();

                switch (deviceRot)
                {
                // portrait - normal
                case Surface.ROTATION_0: SensorManager.remapCoordinateSystem(rotationMatrixA,
                        SensorManager.AXIS_X, SensorManager.AXIS_Z,
                        rotationMatrixB);
                break;
                // rotated left (landscape - keys to bottom)
                case Surface.ROTATION_90: SensorManager.remapCoordinateSystem(rotationMatrixA,
                        SensorManager.AXIS_Z, SensorManager.AXIS_MINUS_X,
                        rotationMatrixB); 
                break;
                // upside down
                case Surface.ROTATION_180: SensorManager.remapCoordinateSystem(rotationMatrixA,
                        SensorManager.AXIS_X, SensorManager.AXIS_Z,
                        rotationMatrixB); 
                break;
                // rotated right
                case Surface.ROTATION_270: SensorManager.remapCoordinateSystem(rotationMatrixA,
                        SensorManager.AXIS_MINUS_Z, SensorManager.AXIS_X,
                        rotationMatrixB); 
                break;

                default:  break;
                }

                float[] dv = new float[3]; 
                SensorManager.getOrientation(rotationMatrixB, dv);
                // add to smoothing filter
                fd.AddLatest((double)dv[0]); 
            }
            mDraw.invalidate();     
        }
    }

2 个答案:

答案 0 :(得分:10)

试试这个

public void onSensorChanged(SensorEvent event) {
    if (event.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE) {
        return;
    }

    if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)  mGravity = event.values.clone ();
    if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) mGeomagnetic =  event.values.clone ();

    if (mGravity != null && mGeomagnetic != null) {

        float[] rotationMatrixA = mRotationMatrixA;
        if (SensorManager.getRotationMatrix(rotationMatrixA, null, mGravity, mGeomagnetic)) {

            float[] rotationMatrixB = mRotationMatrixB;
            SensorManager.remapCoordinateSystem(rotationMatrixA,
                    SensorManager.AXIS_X, SensorManager.AXIS_Z,
                    rotationMatrixB);
            float[] dv = new float[3]; 
            SensorManager.getOrientation(rotationMatrixB, dv);
            // add to smoothing filter
            fd.AddLatest((double)dv[0]); 
        }
        mDraw.invalidate();     
    }
}

你不需要switch语句,似乎有很多关于getRotationMatrix,remapCoordinateSystem和来自stackoverflow问题的getOrientation的混淆。
我可能会在不久的将来写下这些的详细解释。

答案 1 :(得分:1)

Hoan的答案实际上是不正确的,因为它没有考虑到显示器的旋转。 This是正确答案。