Преобразование кватернионов в эйлеровы углы. Проблемы с диапазоном угла Y

Я пытаюсь написать 3D-симуляцию на C ++, используя Irrlicht в качестве графического движка и ODE для физики. Затем я использую функцию для преобразования ODE-кватернионов в углы Ирлихта-Эйлера. Для этого я использую этот код.

void QuaternionToEuler(const dQuaternion quaternion, vector3df &euler)
{
dReal w,x,y,z;

w = quaternion[0];
x = quaternion[1];
y = quaternion[2];
z = quaternion[3];

double sqw = w*w;
double sqx = x*x;
double sqy = y*y;
double sqz = z*z;

euler.Z = (irr::f32) (atan2(2.0 * (x*y + z*w),(sqx - sqy - sqz + sqw)) * (180.0f/irr::core::PI));
euler.X = (irr::f32) (atan2(2.0 * (y*z + x*w),(-sqx - sqy + sqz + sqw)) * (180.0f/irr::core::PI));
euler.Y = (irr::f32) (asin(-2.0 * (x*z - y*w)) * (180.0f/irr::core::PI));

}

Он отлично работает для рисования моих вещей в правильном положении и повороте, но проблемы возникают с инструкцией «asin». Он возвращает только значения в диапазоне 0,90 — 0 ..- 90, и мне нужно получить диапазон от 0 до 360 градусов. По крайней мере, мне нужно получить вращение в диапазоне 0..360, когда я вызываю node-> getRotation (). Y

Может ли кто-нибудь помочь мне с этим, пожалуйста?

1

Решение

Углы Эйлера (любого типа) имеют особенность. В случае тех конкретных углов Эйлера, которые вы используете (которые выглядят как углы Тейта-Брайана или некоторые их вариации), особенность составляет плюс-минус 90 градусов шага (Y). Это неотъемлемое ограничение для углов Эйлера и одна из главных причин, почему они редко используются в каком-либо серьезном контексте (за исключением динамики самолета, потому что все самолеты имеют очень ограниченную способность отклоняться от вектора скорости (который может быть не горизонтальным), поэтому они редко приближаются к этой особенности).

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

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

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

6

Другие решения

Подумай о земном шаре. Каждая точка на нем может быть определена только в широте (в диапазоне [-90, 90]) и долгота (в диапазоне [-180, 180]). Таким образом, каждая точка на сфере может быть указана с использованием этих углов. Теперь точка на сфере определяет вектор, а все точки на сфере указывают все возможные векторы. Так же, как указано в Эта статья, формула, которую вы используете, будет генерировать все возможные направления.

Надеюсь это поможет.

1

По вопросам рекламы [email protected]