Вытягивать рыскание, шаг и рулон с помощью вращения. Матрица - программирование
Подтвердить что ты не робот

Вытягивать рыскание, шаг и рулон с помощью вращения. Матрица

У меня есть диспетчер датчиков, который возвращает rotationMatrix на основе магнитометра и акселерометра. Я также пытаюсь вычислить шаг и рулон вождения пользовательского устройства, но я обнаружил, что шаг и бросок мешают друг другу и дают неточные результаты. Есть ли способ извлечь YAW PITCH и ROLL устройства из rotationMatrix?

ИЗМЕНИТЬ Пытаясь интерпретировать ответ блендера ниже, за что я благодарен, но не совсем там, я пытаюсь получить угол от матрицы рояля следующим образом:

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

Я не знаю, ссылаюсь ли я на неправильные части матрицы или нет, но я не получаю результаты, о которых я думаю.

Я надеялся получить значения в градусах, но я получаю странные целые числа.

моя матрица исходит из моего 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;

матрица образца, когда устройство кладет лицевую стороной вверх на стол

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

ОТВЕТ

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

Ответ 2

Я полагаю, что ответ Блендера не верен, так как он дал преобразование матрицы вращения в углы Эйлера (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));

Обратная связь: эта реализация показала отсутствие численной устойчивости вблизи особенности представления (карданный замок). Поэтому на C++ я рекомендую использовать библиотеку Eigen со следующей строкой кода:

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

Источник