Pull to refresh

Кручу-верчу, запутать хочу: углы Эйлера и Gimbal lock

Game developmentAlgorithmsUnity3D


Выставите любой палец левой руки вперед. Давайте, не стесняйтесь, никто не будет над вами смеяться. Это нужно для важного эксперимента. Выставили? Теперь представьте что вы — это ваш палец (ну и бред). Повернитесь под прямым углом направо, затем наверх, и наконец налево. Где вы оказались? Правильно, в том же месте, но уже на спине.

С некоторой натяжкой именно так работает вращение с помощью углов Эйлера. Немного непредсказуемо и неудобно, не правда ли? Углы Эйлера имеют несколько недостатков, но есть одно особенно нехорошее свойство из-за которого вы не захотите с ними связываться. Его имя — Gimbal lock.

В русском языке gimbal lock называют по-разному: шарнирный замок, блокировка осей, складывание рамок. К сожалению, по запросам в поисковике с такими ключевыми словами выдаётся много мусора, а статья в Википедии оставляет желать лучшего, поэтому я сам расскажу вам об этом феномене и предложу как с ним бороться.

Внимание! Заходя под кат вы подвергаетесь риску поломать голову.

Для начала напомню что такое углы Эйлера. Вы наверное помните, что это что-то вроде набора из трёх углов вращения вокруг осей X, Y и Z? Не совсем так. Предположим, вы хотите повернуть некий объект, и у вас есть набор конечных углов (X: 45°, Y: 45°, Z: 45°). Один из подвохов эйлеровых углов — необходимость выбора какого-то одного порядка поворотов. Если сначала повернуть на 45° вокруг оси X, затем вокруг Y и в конце вокруг Z, то получится результат как на левой половине картинки снизу. Если порядок будет Z-X-Y, то результат будет другой, как на правой половинке.


На самом деле…
На самом деле выше описаны не просто углы Эйлера, а углы Тэйта — Брайана. Эйлеровы углы имеют много сбивающих с толку вариаций, в одних из которых нужно вращать вокруг глобальных осей, в других оси поворачиваются после каждого шага, в третьих оси всегда закреплены на самом объекте и двигаются вместе с ним. Ко всему прочему добавляется разный порядок поворотов. Если есть возможность — не пользуйтесь углами Эйлера.

От выбора порядка поворотов зависит место появления шарнирного замка. Что же это такое? Возьмём к примеру такой порядок поворотов: Z-X-Y. Если вращение вокруг оси X будет равно 90° или -90°, то вращения вокруг Z и Y будут «есть» друг друга и останется только огрызок от большего из вращений. Например (X: 90°, Y: 90°, Z: 90°) превратится в просто (X: 90°, Y: 0°, Z: 0°). Внимание на иллюстрацию.



Так же можно подставить (X: 90°, Y: 130°, Z: 140°) или (X: 90°, Y: 30°, Z: 40°), но в результате всё равно будет получаться (X: 90°, Y: 0°, Z: 10°). Немного не интуитивно, вам не кажется? Это всё из-за шарнирного замка. Когда вращение вокруг оси X становится равным 90° или -90°, ещё не использованная локальная ось вращения Y становится параллельной оси Z, но с обратным направлением, поэтому вращение вокруг неё вступает в конфликт с предыдущим вращением вокруг Z.

*Бдыщ!*

Это взорвались головы особо впечатлительных читателей. Поясню то же самое со стрелочками.



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

Шарнирный замок появляется в середине иерархии поворотов. Если использовать порядок X-Y-Z или Z-Y-X, то поворот направо или налево будет заклинивать анимацию. Поскольку такой поворот встречается гораздо чаще чем, например, поворот в сторону зенита или надира, то во многих программах используют последовательность Z-X-Y. Такая иерархия поворотов используется в Unity3d, правда внутри все вращения всё равно хранятся в кватернионах. Что такое кватернионы? Об этом лучше рассказать отдельно. Кватернионы и матрицы вращения это один из способов избежать шарнирного замка. Также существуют хитрые алгоритмы, которые плавно обходят замок стороной, но это отражается на качестве анимации. Лучше всего использовать углы Эйлера только для простых случаев: пропеллеры, колёса, маятники. Иногда можно поменять иерархию поворотов, но тогда всё равно придётся помнить о замке.

По ссылкам ниже можете посмотреть интерактивную демонстрацию шарнирного замка на примере гироскопа. С ним понять иерархию поворотов и ситуации с замком намного проще.

WebGL | Windows | Linux | Mac | Исходники на GitHub

Мышкой вращать сцену, Esc — выход, остальные кнопки указаны на экране.

Для пользователей Linux:
Сделайте файл GimbalLock исполняемым с помощью «chmod +x GimbalLock» и запускайте.
Tags:углы эйлерашарнирный замокблокировка осейскладывание рамокgimbal lock
Hubs: Game development Algorithms Unity3D
Total votes 67: ↑60 and ↓7+53
Views110K

Popular right now

Top of the last 24 hours