从rotationMatrix中提取偏航,俯仰和滚动

eri*_*rik 20 android rotational-matrices android-sensors

我有一个传感器管理器,它rotationMatrix根据设备Magnetometer和Accelerometer 返回一个.我一直试图计算用户设备的偏航俯仰和滚动,但我发现俯仰和滚动相互干扰并给出不准确的结果.有没有办法从rotationMatrix?提取设备的YAW PITCH和ROLL ?

编辑 试着解释下面的blender的答案,我感谢但还没到那里,我试图从这样的旋转矩阵中获得角度:

       float R[] = phoneOri.getMatrix();
       double rmYaw = Math.atan2(R[4], R[0]);
       double rmPitch = Math.acos(-R[8]);
       double rmRoll = Math.atan2(R[9], R[10]);
Run Code Online (Sandbox Code Playgroud)

我不知道我是否引用矩阵的错误部分,但我没有得到我想的结果.

我希望得到度数的价值,但我得到奇怪的整数.

我的矩阵来自我的sensorManager看起来像这样:

public void onSensorChanged(SensorEvent evt) {
            int type=evt.sensor.getType();
            if(type == Sensor.TYPE_ORIENTATION){
                yaw = evt.values[0];
                pitch = evt.values[1];
                roll = evt.values[2];
            }
            if (type == Sensor.TYPE_MAGNETIC_FIELD) {
                orientation[0]=(orientation[0]*1+evt.values[0])*0.5f;
                orientation[1]=(orientation[1]*1+evt.values[1])*0.5f;
                orientation[2]=(orientation[2]*1+evt.values[2])*0.5f;
            } else if (type == Sensor.TYPE_ACCELEROMETER) {
                acceleration[0]=(acceleration[0]*2+evt.values[0])*0.33334f;
                acceleration[1]=(acceleration[1]*2+evt.values[1])*0.33334f;
                acceleration[2]=(acceleration[2]*2+evt.values[2])*0.33334f;
            }
            if ((type==Sensor.TYPE_MAGNETIC_FIELD) || (type==Sensor.TYPE_ACCELEROMETER)) {
                float newMat[]=new float[16];

                SensorManager.getRotationMatrix(newMat, null, acceleration, orientation);
                if(displayOri==0||displayOri==2){
                    SensorManager.remapCoordinateSystem(newMat,SensorManager.AXIS_X*-1, SensorManager.AXIS_MINUS_Y*-1,newMat);
                }else{
                    SensorManager.remapCoordinateSystem(newMat,SensorManager.AXIS_Y, SensorManager.AXIS_MINUS_X,newMat);
                }

                matrix=newMat;
Run Code Online (Sandbox Code Playgroud)

当设备面朝上放在桌子上时的样本矩阵

0.9916188,  -0.12448014, -0.03459576,  0.0
0.12525482,  0.9918981,   0.021199778, 0.0
0.031676512,-0.025355382, 0.9991765,   0.0
0.0,         0.0,         0.0,         1
Run Code Online (Sandbox Code Playgroud)

回答

double rmPitch = Math.toDegrees( Math.acos(R[10]));
Run Code Online (Sandbox Code Playgroud)

Aqu*_*ius 20

我相信Blender的答案是不正确的,因为他给出了从旋转矩阵到欧拉角(zxz extrinsic)的转换,而Roll Pitch Yaw是一种不同的欧拉角(zyx extrinsic).

实际的转换公式宁愿是:

yaw=atan2(R(2,1),R(1,1));
pitch=atan2(-R(3,1),sqrt(R(3,2)^2+R(3,3)^2)));
roll=atan2(R(3,2),R(3,3));
Run Code Online (Sandbox Code Playgroud)

资源

反馈:这种实现显示在表示的单一性(万向节锁定)附近缺乏数值稳定性.因此,在C++上,我建议使用具有以下代码行的Eigen库:

R.eulerAngles(2,1,0).reverse();
Run Code Online (Sandbox Code Playgroud)

(更多细节在这里)

  • 这个回复应该有一百万个+1。这是正确转换从 SensorManager.TYPE_ROTATION_VECTOR 获得的旋转矩阵的完美公式。 (2认同)

Ble*_*der 19

偏航,俯仰和滚动对应于欧拉角.您可以非常轻松地将变换矩阵转换为欧拉角:

在此输入图像描述

  • 好吧,那些*是*希腊字母;)`A_31`表示第3行和第1列的条目.Java内置了这些功能,因此您可以对其进行翻译. (17认同)
  • 谢谢,但说实话,希腊对我来说.你愿意为我翻译一下吗...喜欢java吗? (9认同)
  • 请注意,这些不是 XYZ 欧拉角,而是 3-1-3 转换中的欧拉角,如来源所述:https://en.wikipedia.org/wiki/Rotation_formalisms_in_three_dimensions#Rotation_matrix_.E2.86.94_Euler_angles (3认同)