Углы Эйлера и ориентация в пространстве
Три числа, которыми задают ориентацию тела в трёхмерном пространстве — и подводные камни этого способа.
Углы Эйлера — три угла последовательных поворотов вокруг осей, задающие произвольную ориентацию тела в пространстве.
На плоскости ориентация — один угол. В пространстве нужно три. Популярная схема — roll-pitch-yaw (крен-тангаж-рыскание): поворот вокруг $z$ на угол $\psi$ (yaw), затем вокруг $y$ на $\phi$ (pitch), затем вокруг $x$ на $\gamma$ (roll). Итоговая матрица — произведение:
$$ R = R_z(\psi) \, R_y(\phi) \, R_x(\gamma) $$
где элементарные повороты, например:
$$ R_z(\psi) = \begin{bmatrix} \cos\psi & -\sin\psi & 0 \\\\ \sin\psi & \cos\psi & 0 \\\\ 0 & 0 & 1 \end{bmatrix} $$
Порядок имеет значение
В 3D повороты не коммутируют: повернуть сначала вокруг $z$, потом вокруг $y$ — не то же самое, что наоборот. Поэтому всегда указывают порядок осей (ZYX, XYZ и т.д.). Перемножим матрицы и повернём вектор $(1,0,0)$ только вокруг $z$ на $90^\circ$ — ждём $(0,1,0)$.
import math
def Rz(a):
c, s = math.cos(a), math.sin(a)
return [[c, -s, 0], [s, c, 0], [0, 0, 1]]
def Ry(a):
c, s = math.cos(a), math.sin(a)
return [[c, 0, s], [0, 1, 0], [-s, 0, c]]
def Rx(a):
c, s = math.cos(a), math.sin(a)
return [[1, 0, 0], [0, c, -s], [0, s, c]]
def mm(A, B):
return [[sum(A[i][k] * B[k][j] for k in range(3)) for j in range(3)] for i in range(3)]
def mv(A, v):
return [round(sum(A[i][k] * v[k] for k in range(3)), 4) for i in range(3)]
R = mm(mm(Rz(math.radians(90)), Ry(0)), Rx(0))
print("вектор (1,0,0) после yaw=90:", mv(R, [1, 0, 0]))Вывод:
вектор (1,0,0) после yaw=90: [0.0, 1.0, 0.0]
Как работает под капотом
У углов Эйлера есть болезнь — gimbal lock (складывание рамок): при некоторых ориентациях (например $\phi = 90^\circ$) две оси поворота совпадают, и одна степень свободы теряется. Из-за этого в реальных системах ориентацию чаще хранят в кватернионах — четырёх числах без сингулярностей; углы Эйлера оставляют для интерфейса с человеком, потому что их легко представить.
Частые ошибки
- Не указать порядок осей: «углы Эйлера» без последовательности (ZYX/XYZ) — неоднозначность.
- Менять порядок множителей и удивляться другому результату — в 3D это норма.
- Игнорировать gimbal lock в задачах с большими поворотами.
Итог
- Ориентацию в 3D задают тремя углами Эйлера (roll-pitch-yaw).
- Итоговая матрица — произведение трёх элементарных поворотов в заданном порядке.
- Повороты в 3D не коммутируют — порядок осей критичен.
- Углы Эйлера страдают от gimbal lock; для вычислений надёжнее кватернионы.