Как преобразовать Euler углы в направленный вектор?

По-моему, высказывание, что стиль не важен, похоже на высказывание, что написание не важно. Если Ваш стиль (или отсутствие стиля) вызовет проблемы удобочитаемости, то для команды будет трудно работать с файлами, которые пишет/редактирует этот человек.

Точно так же, если программист не не торопится для произносить слов по буквам правильно в блоках комментария, именах функций, и т.д....., это вызовет проблемы с другими разработчиками, пытающимися дешифровать код. Я всегда спрашиваю меня, "сам при рассмотрении этого за 1 неделю Вы поймете его? При рассмотрении его в следующем году Вы все еще поймете его?" (или по крайней мере быть в состоянии прочитать документацию/комментарии для бега трусцой памяти).

мне, стиль не важен, когда Вы говорите о помещении изогнутой фигурной скобки на следующей строке Вашего если-блока по сравнению с помещением его в конце условного оператора..., пока он соответствует Вашим стандартам кодирования, внутренне последовательно, и остальная часть команды использует тот же подход; с этим сказанным, я чувствую, что стиль чрезвычайно важен, если он влияет на удобочитаемость кода.

С MS, являющимся такой крупной компанией, они, вероятно, ищут кого-то, кто может быть решателем задач, а также командным игроком. Кто-то, кто заявляет, что у них "нет времени для моделирования", столкнулся бы не командный игрок мне.

Хороший вопрос!

46
задан Makoto 19 September 2016 в 19:36
поделиться

3 ответа

К сожалению, существуют разные соглашения о том, как определять эти вещи (а крен, тангаж, рыскание - это не совсем то же самое, что углы Эйлера), поэтому будьте осторожны.

Если мы определим шаг = 0 как горизонтальный (z = 0) и рыскание против часовой стрелки от оси x, тогда вектор направления будет

x = cos(yaw)*cos(pitch)
y = sin(yaw)*cos(pitch)
z = sin(pitch)

Обратите внимание, что я не использовал крен; это единичный вектор направления, он не определяет отношения. Достаточно легко написать матрицу вращения, которая будет переносить вещи в кадр летающего объекта (если вы хотите знать, скажем, куда указывает кончик левого крыла), но действительно неплохо сначала указать условные обозначения. Не могли бы вы рассказать нам больше о проблеме?

РЕДАКТИРОВАТЬ: (Я собирался вернуться к этому вопросу в течение двух с половиной лет.)

Что касается матрицы полного вращения, если мы используем указанное выше соглашение и хотим, чтобы вектор сначала двигался по рысканию, затем по тангажу, затем по крену, чтобы получить окончательные координаты в мировой системе координат, мы должны применить матрицы вращения в обратном порядке.

Первый бросок:

| 1    0          0      |
| 0 cos(roll) -sin(roll) |
| 0 sin(roll)  cos(roll) |

, затем шаг:

| cos(pitch) 0 -sin(pitch) |
|     0      1      0      |
| sin(pitch) 0  cos(pitch) |

, затем рыскание:

| cos(yaw) -sin(yaw) 0 |
| sin(yaw)  cos(yaw) 0 |
|    0         0     1 |

Объедините их, и итоговое значение матрица вращения:

| cos(yaw)cos(pitch) -cos(yaw)sin(pitch)sin(roll)-sin(yaw)cos(roll) -cos(yaw)sin(pitch)cos(roll)+sin(yaw)sin(roll)|
| sin(yaw)cos(pitch) -sin(yaw)sin(pitch)sin(roll)+cos(yaw)cos(roll) -sin(yaw)sin(pitch)cos(roll)-cos(yaw)sin(roll)|
| sin(pitch)          cos(pitch)sin(roll)                            cos(pitch)sin(roll)|

Таким образом, для единичного вектора, который начинается с оси x, окончательные координаты будут:

x = cos(yaw)cos(pitch)
y = sin(yaw)cos(pitch)
z = sin(pitch)

А для единичного вектора, который начинается на оси y (кончик левого крыла), конечные координаты будет:

x = -cos(yaw)sin(pitch)sin(roll)-sin(yaw)cos(roll)
y = -sin(yaw)sin(pitch)sin(roll)+cos(yaw)cos(roll)
z =  cos(pitch)sin(roll)
74
ответ дан 26 November 2019 в 20:19
поделиться

Существует шесть различных способов преобразования трех углов Эйлера в матрицу в зависимости от порядка, в котором они применяются:

typedef float Matrix[3][3];
struct EulerAngle { float X,Y,Z; };

// Euler Order enum.
enum EEulerOrder
{
    ORDER_XYZ,
    ORDER_YZX,
    ORDER_ZXY,
    ORDER_ZYX,
    ORDER_YXZ,
    ORDER_XZY
};


Matrix EulerAnglesToMatrix(const EulerAngle &inEulerAngle,EEulerOrder EulerOrder)
{
    // Convert Euler Angles passed in a vector of Radians
    // into a rotation matrix.  The individual Euler Angles are
    // processed in the order requested.
    Matrix Mx;

    const FLOAT    Sx    = sinf(inEulerAngle.X);
    const FLOAT    Sy    = sinf(inEulerAngle.Y);
    const FLOAT    Sz    = sinf(inEulerAngle.Z);
    const FLOAT    Cx    = cosf(inEulerAngle.X);
    const FLOAT    Cy    = cosf(inEulerAngle.Y);
    const FLOAT    Cz    = cosf(inEulerAngle.Z);

    switch(EulerOrder)
    {
    case ORDER_XYZ:
        Mx.M[0][0]=Cy*Cz;
        Mx.M[0][1]=-Cy*Sz;
        Mx.M[0][2]=Sy;
        Mx.M[1][0]=Cz*Sx*Sy+Cx*Sz;
        Mx.M[1][1]=Cx*Cz-Sx*Sy*Sz;
        Mx.M[1][2]=-Cy*Sx;
        Mx.M[2][0]=-Cx*Cz*Sy+Sx*Sz;
        Mx.M[2][1]=Cz*Sx+Cx*Sy*Sz;
        Mx.M[2][2]=Cx*Cy;
        break;

    case ORDER_YZX:
        Mx.M[0][0]=Cy*Cz;
        Mx.M[0][1]=Sx*Sy-Cx*Cy*Sz;
        Mx.M[0][2]=Cx*Sy+Cy*Sx*Sz;
        Mx.M[1][0]=Sz;
        Mx.M[1][1]=Cx*Cz;
        Mx.M[1][2]=-Cz*Sx;
        Mx.M[2][0]=-Cz*Sy;
        Mx.M[2][1]=Cy*Sx+Cx*Sy*Sz;
        Mx.M[2][2]=Cx*Cy-Sx*Sy*Sz;
        break;

    case ORDER_ZXY:
        Mx.M[0][0]=Cy*Cz-Sx*Sy*Sz;
        Mx.M[0][1]=-Cx*Sz;
        Mx.M[0][2]=Cz*Sy+Cy*Sx*Sz;
        Mx.M[1][0]=Cz*Sx*Sy+Cy*Sz;
        Mx.M[1][1]=Cx*Cz;
        Mx.M[1][2]=-Cy*Cz*Sx+Sy*Sz;
        Mx.M[2][0]=-Cx*Sy;
        Mx.M[2][1]=Sx;
        Mx.M[2][2]=Cx*Cy;
        break;

    case ORDER_ZYX:
        Mx.M[0][0]=Cy*Cz;
        Mx.M[0][1]=Cz*Sx*Sy-Cx*Sz;
        Mx.M[0][2]=Cx*Cz*Sy+Sx*Sz;
        Mx.M[1][0]=Cy*Sz;
        Mx.M[1][1]=Cx*Cz+Sx*Sy*Sz;
        Mx.M[1][2]=-Cz*Sx+Cx*Sy*Sz;
        Mx.M[2][0]=-Sy;
        Mx.M[2][1]=Cy*Sx;
        Mx.M[2][2]=Cx*Cy;
        break;

    case ORDER_YXZ:
        Mx.M[0][0]=Cy*Cz+Sx*Sy*Sz;
        Mx.M[0][1]=Cz*Sx*Sy-Cy*Sz;
        Mx.M[0][2]=Cx*Sy;
        Mx.M[1][0]=Cx*Sz;
        Mx.M[1][1]=Cx*Cz;
        Mx.M[1][2]=-Sx;
        Mx.M[2][0]=-Cz*Sy+Cy*Sx*Sz;
        Mx.M[2][1]=Cy*Cz*Sx+Sy*Sz;
        Mx.M[2][2]=Cx*Cy;
        break;

    case ORDER_XZY:
        Mx.M[0][0]=Cy*Cz;
        Mx.M[0][1]=-Sz;
        Mx.M[0][2]=Cz*Sy;
        Mx.M[1][0]=Sx*Sy+Cx*Cy*Sz;
        Mx.M[1][1]=Cx*Cz;
        Mx.M[1][2]=-Cy*Sx+Cx*Sy*Sz;
        Mx.M[2][0]=-Cx*Sy+Cy*Sx*Sz;
        Mx.M[2][1]=Cz*Sx;
        Mx.M[2][2]=Cx*Cy+Sx*Sy*Sz;
        break;
    }
    return(Mx);
}

FWIW, некоторые процессоры могут вычислять Sin и Cos одновременно (например, fsincos на x86). Если вы сделаете это, вы можете немного ускорить вычисление начальных значений sin и cos с помощью трех вызовов, а не 6.

Обновление: на самом деле существует 12 способов в зависимости от того, хотите ли вы получить результаты для правшей или левшей - - вы можете изменить «руку», отрицая углы.

20
ответ дан 26 November 2019 в 20:19
поделиться

Вы должны четко сформулировать свои определения здесь - в частности, какой вектор вам нужен? Если это направление, в котором указывает самолет, то крен даже не влияет на него, и вы ' просто используйте сферические координаты (возможно, с переставленными осями / углами).

Если, с другой стороны, вы хотите взять заданный вектор и преобразовать его по этим углам, вы ищете матрицу вращения . В вики-статье о матрицах вращения содержится формула для вращения по рысканью-тангажу-крену, основанная на матрицах поворота xyz. Я не собираюсь вводить его здесь, учитывая задействованные греческие буквы и матрицы.

1
ответ дан 26 November 2019 в 20:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: