7

私の拡張現実アプリには、カメラ ビューのコンパス方位が必要であり、センサー マネージャーから方向を取得する例はたくさんあります。

ただし、電話の向きによって結果の値が異なることがわかりました。右に回転した横向きは、左に回転した横向きと約 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();     
        }
    }
4

2 に答える 2

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 ステートメントは必要ありません。stackoverflow の質問から、getRotationMatrix、remapCoordinateSystem、および getOrientation に関して多くの混乱があるようです。
これらについては近いうちに詳細な説明を書こうと思います。

于 2012-05-21T01:27:06.563 に答える
1

Hoan の答えは、ディスプレイの回転を考慮していないため、実際には正しくありません。これが正解です。

于 2014-04-15T16:41:55.970 に答える