Android 从旋转矩阵中提取偏航、俯仰和滚转

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11514063/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 07:53:09  来源:igfitidea点击:

extract yaw, pitch, and roll from a rotationMatrix

androidandroid-sensorsrotational-matrices

提问by erik

I have a sensor manager that returns a rotationMatrixbased on the devices Magnetometer and Accelerometer. I have been trying to also calculate the yaw pitch and roll of the user's device but am finding that pitch and roll interfere with each other and give inaccurate results. Is there a way to extract YAW PITCH and ROLL of a device from the rotationMatrix?

我有一个传感器管理器,它rotationMatrix根据设备磁​​力计和加速度计返回一个。我一直在尝试计算用户设备的偏航俯仰和滚转,但我发现俯仰和滚转会相互干扰并给出不准确的结果。有没有办法从rotationMatrix? 中提取设备的 YAW PITCH 和 ROLL ?

EDITTrying to interpret blender's answer below, which i am thankful for but not quite there yet, i am trying to get the angle from a rotaion matrix like this:

编辑试图解释下面的搅拌机答案,我很感激但还没有完全到位,我试图从这样的旋转矩阵中获得角度:

       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]);

i don't know if i am referencing the wrong parts of the matrix or not but i am not getting the results i would think.

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

i was hoping to get values in degrees, but am getting weird integers.

我希望以度为单位获得值,但我得到了奇怪的整数。

my matrix is coming from my sensorManagerwhich looks like this:

我的矩阵来自我的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;

sample matrix when device is laying face up on table

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

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

ANSWER

回答

double rmPitch = Math.toDegrees( Math.acos(R[10]));

采纳答案by Blender

Yaw, pitch and roll correspond to Euler angles. You can convert a transformation matrix to Euler anglespretty easily:

偏航、俯仰和滚转对应于欧拉角。您可以很容易地将变换矩阵转换为欧拉角

enter image description here

在此处输入图片说明

回答by Aquadarius

I believe Blender's answer is not correct, since he gave a transformation from Rotation matrix to Euler angles (z-x-z extrinsic), and Roll Pitch Yaw are a different kind of Euler angles (z-y-x extrinsic).

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

The actual transformation formula would rather be:

实际的转换公式宁愿是:

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));

Source

来源

Feedback : this implementation revealed to lack numerical stability near the singularity of the representation (gimbal lock). Therefore on C++ I recommend using Eigen library with the following line of code:

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

R.eulerAngles(2,1,0).reverse();

(More details here)

(更多细节在这里

回答by Pikanshu Kumar

Sensor Manager provides a SensorManager.getOrientationto get all the three angle.

传感器管理器提供了一个SensorManager.getOrientation来获取所有三个角度。