0

縦向きのときにデバイスのピッチとロールを取得しようとしています。 軸がこのように見えると、それぞれ x 軸と z 軸についてになります。現在、デフォルトのように、SensorManager API を使用して、デバイスのピッチ、ロール、およびヨーをフラットに取得しています。

回転値をフラット デバイスから垂直方向に変換しようとすると、他の SO ユーザーがジンバル ロックと呼んでいる現象が発生します。これは、オイラー角が機能する方法に固有の問題です。問題は、他のユーザーが同様の問題を解決する必要があるため、回転マトリックスを実装しようとしたことですが、それでも同じジンバルロックの問題が発生しています。私は onSensorChanged メソッドを含めました。うまくいけば、誰かが何が問題なのかを見つけるのを手伝ってくれるでしょう。

public void onSensorChanged(SensorEvent se) {

    float degPitch = 0;
    float degRoll = 0;
    float degYaw = 0;
    float radPitch = 0;
    float radRoll = 0;
    float radYaw = 0;

    if (se.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
        mAccelerometerResult = se.values;
        Log.d("onSensorChanged", "Accelerometer: " + mAccelerometerResult.length);
    }

    if (se.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
        mMagneticFieldResult = se.values;
        Log.d("onSensorChanged", "Magnetic Field: " + mMagneticFieldResult.length);
    }

    if (mAccelerometerResult != null && mMagneticFieldResult != null) {
        float[] rotation = new float[9];
        float[] inclination = new float[9];

        boolean rotationMatrixCheck = mSensorManager.getRotationMatrix(rotation, inclination, mAccelerometerResult, mMagneticFieldResult);

        if (rotationMatrixCheck) {

            float[] orientation = new float[3];
            mSensorManager.getOrientation(rotation, orientation);


            radYaw = orientation[0];      //Yaw = Z axis
            radPitch = orientation[1];      //Pitch = X axis
            radRoll = orientation[2];      //Roll = Y axis

            degYaw = round((float) Math.toDegrees(radYaw), 2);
            degPitch = round((float)Math.toDegrees(radPitch), 2);
            degRoll = round((float)Math.toDegrees(radRoll), 2);


            if ((counter % 10) == 0) {
                //mYawTextView.setText(degYaw + "°");
                mPitchTextView.setText(degPitch + "°");
                mRollTextView.setText(degRoll + "°");
                counter = 0;
            } else {
                counter++;
            }
        }
    }

さらに、ポートレート軸を中心に適切な回転が得られる場合、探している回転値を理解しているかどうかさえわかりません。縦向きのデバイスのロール (元の画像から z 軸について) が必要な場合、それはデバイスを平らに置いたときのロール (フラット軸の画像から約 y) でしょうか?

ここで共有できる洞察をいただければ幸いです。

4

1 に答える 1

0

問題の解決策を見つけました。元の質問で説明したように、3x3 グリッドで回転行列を取得すると、オイラー角で回転行列が返されます。4x4 グリッドで行列を取得すると、回転行列のクォータニオン表現が返されます(SO ユーザー Stochastically の回答がここに見つかりました)。

さらに、その回転行列座標系は、ポートレート モードで使用するために再マッピングする必要がありました。コメントされた変更を以下に示します。

public void onSensorChanged(SensorEvent se) {

float degPitch = 0;
float degRoll = 0;
float degYaw = 0;
float radPitch = 0;
float radRoll = 0;
float radYaw = 0;

if (se.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
    mAccelerometerResult = se.values;
    Log.d("onSensorChanged", "Accelerometer: " + mAccelerometerResult.length);
}

if (se.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
    mMagneticFieldResult = se.values;
    Log.d("onSensorChanged", "Magnetic Field: " + mMagneticFieldResult.length);
}

if (mAccelerometerResult != null && mMagneticFieldResult != null) {

//~~~This is where the 3x3 matrix has changed to a 4x4.
    float[] rotation = new float[16];
    float[] inclination = new float[16];

    boolean rotationMatrixCheck = mSensorManager.getRotationMatrix(rotation, inclination, mAccelerometerResult, mMagneticFieldResult);

    if (rotationMatrixCheck) {

        float[] orientation = new float[3];

//~~~This is where the rotational matrix is remapped to be used in portrait mode.
        float[] remappedRotation = new float[16];
        SensorManager.remapCoordinateSystem(rotation, SensorManager.AXIS_X, SensorManager.AXIS_Z, remappedRotation);

        mSensorManager.getOrientation(rotation, orientation);


        radYaw = orientation[0];      //Yaw = Z axis
        radPitch = orientation[1];      //Pitch = X axis
        radRoll = orientation[2];      //Roll = Y axis

        degYaw = round((float) Math.toDegrees(radYaw), 2);
        degPitch = round((float)Math.toDegrees(radPitch), 2);
        degRoll = round((float)Math.toDegrees(radRoll), 2);


        if ((counter % 10) == 0) {
            //mYawTextView.setText(degYaw + "°");
            mPitchTextView.setText(degPitch + "°");
            mRollTextView.setText(degRoll + "°");
            counter = 0;
        } else {
            counter++;
        }
    }
}
于 2016-06-14T21:16:47.050 に答える