【问题标题】:How can I better my results when measuring the roll of a device in portrait mode?在纵向模式下测量设备的滚动时如何改善结果?
【发布时间】:2023-03-13 19:40:01
【问题描述】:

我正在尝试在设备处于纵向时进行俯仰和滚动。 With the axes looking like this,它将分别关于 x 和 z 轴。现在我正在使用 SensorManager API 来获取设备的俯仰、滚动和偏航,as is default.

当我尝试将旋转值从平面设备转换为垂直方向时,我遇到了其他 SO 用户所说的万向节锁定,这是欧拉角工作方式固有的问题。问题是我尝试实现一个旋转矩阵as other users have 来解决类似的问题,但即使我仍然遇到相同的万向节锁定问题。我已经包含了我的 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)?

任何可以在这里分享的见解将不胜感激。

【问题讨论】:

    标签: java android rotation hardware-programming


    【解决方案1】:

    我找到了问题的解决方案。如原始问题中所述,获取 3x3 网格中的旋转矩阵会返回欧拉角的旋转矩阵。获取 4x4 网格中的矩阵会返回旋转矩阵的四元数表示 (According to SO user Stochastically's answer found here).

    此外,必须重新映射旋转矩阵坐标系才能在纵向模式下使用。注释的更改如下所示。

    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++;
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多