Как преобразовать углы Эйлера в направленный вектор?
У меня есть углы наклона, рулона и рыскания. Как бы преобразовать их в вектор направленности?
Было бы особенно здорово, если бы вы могли показать мне кватернион и / или матричное представление этого!
- Как эта побитовая операция проверяет мощность 2?
- Математика с фиксированной точкой в c #?
- Повышение точности решения трансцендентного уравнения
- Как узнать, является ли matrix единственной?
- Наименьшее расстояние между точками алгоритма
- Вычисление матрицы LookAt
- Является ли Big log (logn) базой базы?
- C ++ библиотека с фиксированной точкой?
- Как вы вычисляете ориентированную по оси ограничительную рамку эллипса?
- Вычисление ограничивающей frameworks на некотором расстоянии от координаты lat / long в Java
- Проецирование 3D-точек на двумерную плоскость
- Вычислить вторую точку, зная начальную точку и расстояние
- Как округлить до ближайшего 0,5?
К сожалению, существуют различные соглашения о том, как определять эти вещи (и рулон, шаг, рыскание не совсем такие же, как углы Эйлера), поэтому вам нужно быть осторожным.
Если мы определяем pitch = 0 как горизонтальный (z = 0) и yaw как против часовой стрелки от оси x, тогда вектор направления будет
x = cos (yaw) * cos (pitch) y = sin (yaw) * cos (pitch) z = sin (шаг)
Обратите внимание, что я не использовал roll; это вектор единицы направления, он не указывает отношения. Достаточно легко написать матрицу вращения, которая будет переносить вещи в кадр летающего объекта (если вы хотите знать, скажем, где указывает левый крыло), но это действительно хорошая идея, чтобы сначала определить соглашения. Не могли бы вы рассказать нам больше о проблеме?
EDIT: (Я хотел бы вернуться к этому вопросу в течение двух с половиной лет.)
Для полной матрицы вращения, если мы используем вышеприведенное соглашение, и сначала хотим, чтобы вектор был рывком, затем шаг, затем сверните, чтобы получить окончательные координаты в мировом координатном кадре, мы должны применить матрицы вращения в обратном порядке.
Первый бросок:
| 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 |
Объедините их, и общая matrix вращения:
| 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)
Существует шесть различных способов преобразования трех углов Эйлера в матрицу в зависимости от Приказа, который они применяют:
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). Если вы это сделаете, вы можете сделать это немного быстрее с тремя вызовами вместо 6, чтобы вычислить начальные значения sin & cos.
Обновление: Есть фактически 12 способов, зависящих, если вы хотите правша или левые результаты – вы можете изменить «ручность», отрицая углы.
Бета спасла мой день. Тем не менее, я использую немного другую систему координат, и мое определение шага вверх \ вниз (кивая головой в согласии), где положительный шаг приводит к отрицательному y-компоненту. Мой опорный вектор – это стиль OpenGl (вниз по оси -z), поэтому с yaw = 0, pitch = 0 результирующий единичный вектор должен быть равен (0, 0, -1). Если кто-то сталкивается с этим сообщением и испытывает трудности с переводом формул Беты на эту конкретную систему, я использую следующие уравнения:
vDir->X = sin(yaw); vDir->Y = -(sin(pitch)*cos(yaw)); vDir->Z = -(cos(pitch)*cos(yaw));
Обратите внимание на изменение знака и подмену тангажа <->. Надеюсь, это немного сэкономит.
Вы должны четко понимать свои определения здесь – в частности, какой вектор вы хотите? Если это направление, на которое указывает самолет, рулон даже не влияет на него, и вы используете сферические координаты (возможно, с перестановкой осей / углов).
Если, с другой стороны, вы хотите взять данный вектор и преобразовать его по этим углам, вы ищете матрицу вращения. В статье wiki о matrixх вращения содержится формула для поворота поворотного вала, основанная на matrixх вращения xyz. Я не собираюсь вводить его здесь, учитывая связанные с ним греческие буквы и матрицы.
Если кто-то наткнется на поиск в FreeCAD.
import FreeCAD, FreeCADGui from FreeCAD import Vector from math import sin, cos, pi cr = FreeCADGui.ActiveDocument.ActiveView.getCameraOrientation().toEuler() crx = cr[2] # Roll cry = cr[1] # Pitch crz = cr[0] # Yaw crx = crx * pi / 180.0 cry = cry * pi / 180.0 crz = crz * pi / 180.0 x = sin(crz) y = -(sin(crx) * cos(crz)) z = cos(crx) * cos(cry) view = Vector(x, y, z)