Существует ли алгоритм преобразования поворотов кватернионов в угловые повороты Эйлера?
Существует ли существующий алгоритм преобразования кватернионного представления вращения в представление угла Эйлера? Порядок вращения для представления Эйлера известен и может быть любой из шести перестановок (т.е. Xyz, xzy, yxz, yzx, zxy, zyx). Я видел алгоритмы для фиксированного порядка вращения (как правило, заголовок NASA, банк, соглашение о роуте), но не для произвольного порядка вращения.
Кроме того, поскольку существует несколько представлений угла Эйлера с одной ориентацией, этот результат будет неоднозначным. Это приемлемо (поскольку ориентация по-прежнему действительна, это может быть не тот, который пользователь ожидает увидеть), однако было бы еще лучше, если бы был алгоритм, который принимал ограничения на вращение (т.е. Количество степеней свободы и ограничения на каждую степень свободы) и дал "наиболее разумное" представление Эйлера с учетом этих ограничений.
У меня такое ощущение, что эта проблема (или что-то подобное) может существовать в доменах ИК или твердого тела.
Решено: Я только понял, что может быть неясно, что я решил эту проблему, следуя алгоритмам Ken Shoemake из Graphics Gems. В то время я отвечал на свой вопрос, но мне кажется, что не ясно, что я сделал это. Подробнее см. Ответ ниже.
Просто чтобы уточнить - я знаю, как преобразовать из кватерниона в так называемое представление Tait-Bryan - то, что я называл конвенции НАСА. Это порядок вращения (если предположить, что ось "Z" поднята) zxy. Мне нужен алгоритм для всех порядков вращения.
Возможно, решение состоит в том, чтобы принять преобразование порядка zxy и извлечь из него пять других преобразований для других порядков вращения. Наверное, я надеялся, что существует более "всеобъемлющее" решение. В любом случае, я удивлен, что я не смог найти существующие решения там.
Кроме того, и это, возможно, должно быть отдельным вопросом вообще, любое преобразование (при условии, конечно, порядок вращения, конечно) собирается выбрать одно представление Эйлера, но на самом деле много. Например, с учетом порядка вращения yxz два представления (0,0,180) и (180,180,0) эквивалентны (и будут давать тот же кватернион). Есть ли способ ограничить решение, используя ограничения на степени свободы? Как вы это делаете в ИК и динамике твердого тела? то есть в приведенном выше примере, если бы была только одна степень свободы относительно оси Z, тогда второе представление можно пренебречь.
Я отследил одну статью, которая могла бы быть алгоритмом в этом pdf, но я должен признаться, что мне очень трудно найти логику и математику следовать. Конечно, есть другие решения? Действительно ли случайный порядок вращения настолько редок? Несомненно, каждый крупный 3D-пакет, который позволяет скелетную анимацию вместе с интерполяцией кватернионов (т.е. Maya, Max, Blender и т.д.), Должен решить именно эту проблему?
Ответы
Ответ 1
Это похоже на классический случай игнорирования старой технологии - мне удалось выкопать копию Графического драгоценного камня IV из гаража, и похоже, что у Кен Шомейке есть не только алгоритм преобразования от углов Эйлера произвольного порядка вращения, но также отвечает на большинство моих других вопросов по этому вопросу. Ура для книг. Если бы я мог проголосовать за г-на Шомейка и вознаградить его за очки репутации.
Я думаю, что рекомендация о том, что любой, кто работает с углами Эйлера, должен получить копию Graphics Gems IV из своей локальной библиотеки и прочитать раздел, начинающийся со страницы 222. Это должно быть самое ясное и краткое объяснение проблемы, которую я прочитал еще.
Вот полезная ссылка, которую я нашел с тех пор - http://www.cgafaq.info/wiki/Euler_angles_from_matrix - Это следует за той же системой, что и Shoemake; 24 разных перестановки порядка вращения кодируются как четыре отдельных параметра - внутренняя ось, четность, повторение и кадр - что затем позволяет уменьшить алгоритм от 24 случаев до 2. Может быть полезной вики вообще - я не пришел через него раньше.
Поставленная старая ссылка кажется сломанной здесь - это еще одна копия "Вычисление углов Эйлера из матрицы вращения".
Ответ 2
В правой декартовой системе координат с направленной осью Z сделайте следующее:
struct Quaternion
{
double w, x, y, z;
};
void GetEulerAngles(Quaternion q, double& yaw, double& pitch, double& roll)
{
const double w2 = q.w*q.w;
const double x2 = q.x*q.x;
const double y2 = q.y*q.y;
const double z2 = q.z*q.z;
const double unitLength = w2 + x2 + y2 + z2; // Normalised == 1, otherwise correction divisor.
const double abcd = q.w*q.x + q.y*q.z;
const double eps = 1e-7; // TODO: pick from your math lib instead of hardcoding.
const double pi = 3.14159265358979323846; // TODO: pick from your math lib instead of hardcoding.
if (abcd > (0.5-eps)*unitLength)
{
yaw = 2 * atan2(q.y, q.w);
pitch = pi;
roll = 0;
}
else if (abcd < (-0.5+eps)*unitLength)
{
yaw = -2 * ::atan2(q.y, q.w);
pitch = -pi;
roll = 0;
}
else
{
const double adbc = q.w*q.z - q.x*q.y;
const double acbd = q.w*q.y - q.x*q.z;
yaw = ::atan2(2*adbc, 1 - 2*(z2+x2));
pitch = ::asin(2*abcd/unitLength);
roll = ::atan2(2*acbd, 1 - 2*(y2+x2));
}
}
Ответ 3
На моем веб-сайте noelhughes.net я опубликовал свой документ под названием "Кватернион для преобразования угла Эйлера для произвольной последовательности вращения с использованием геометрических методов". У меня также есть алгоритмы преобразования любого набора углов Эйлера в кватернион и кватернион в/из косинусной матрицы направления, которые я опубликую в эти выходные. Это также на веб-сайте Мартина Бейкерса, хотя немного сложно найти. Google мое имя, Ноэль Хьюз и кватернионы, и вы должны найти его.
Ответ 4
Я решаю это так:
Шаг 1. Убедитесь в том, какое соглашение для вращения Euler вы хотите, скажем, zyx.
Шаг 2. Вычислите аналитическую матрицу вращения для вращения.
Например, если вы хотите R (zyx),
** R *** zyx * = ** R *** x * (phi) * ** R *** y * (theta) * ** R *** z * (psi), где элементы становятся
R11 = cos(theta)*cos(psi)
R12 = -cos(theta)*sin(psi)
R13 = sin(theta)
R21 = sin(psi)*cos(phi) + sin(theta)*cos(psi)*sin(phi)
R22 = cos(psi)*cos(phi) - sin(theta)*sin(psi)*sin(phi)
R23 = -cos(theta)*sin(phi)
R31 = sin(psi)*sin(phi) - sin(theta)*cos(psi)*cos(phi)
R32 = cos(psi)sin(phi) + sin(theta)*sin(psi)*cos(phi)
R33 = cos(theta)*cos(phi)
Шаг 3. При осмотре вы можете найти грех или загар для трех углов, используя вышеприведенные элементы. В этом примере
tan(phi) = -R23/R33
sin(theta) = -R13
tan(psi) = -R12/R11
Шаг 4. Вычислите матрицу вращения из вашего кватерниона (см. wikipedia), для элементов вам нужно вычислить углы, как в 3) выше.
Другие соглашения могут быть вычислены с использованием той же процедуры.
Ответ 5
Вот статья, которую я написал о преобразовании кватерниона в углы Эйлера.
Ссылка 1
Я также поставил на этом месте ряд документов, в которых обсуждались различные аспекты кватернионов, углы Эйлера и матрицы вращения (DCM).
Ссылка 2
Ответ 6
Я искал несколько дней для подобного решения, и я, наконец, наткнулся на этот сайт, у которого есть алгоритм преобразования кватернионов в произвольные вращения Эйлера и Тейта-Брайана!
Здесь ссылка: http://bediyap.com/programming/convert-quaternion-to-euler-rotations/
И вот код:
///////////////////////////////
// Quaternion to Euler
///////////////////////////////
enum RotSeq{zyx, zyz, zxy, zxz, yxz, yxy, yzx, yzy, xyz, xyx, xzy,xzx};
void twoaxisrot(double r11, double r12, double r21, double r31, double r32, double res[]){
res[0] = atan2( r11, r12 );
res[1] = acos ( r21 );
res[2] = atan2( r31, r32 );
}
void threeaxisrot(double r11, double r12, double r21, double r31, double r32, double res[]){
res[0] = atan2( r31, r32 );
res[1] = asin ( r21 );
res[2] = atan2( r11, r12 );
}
void quaternion2Euler(const Quaternion& q, double res[], RotSeq rotSeq)
{
switch(rotSeq){
case zyx:
threeaxisrot( 2*(q.x*q.y + q.w*q.z),
q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
-2*(q.x*q.z - q.w*q.y),
2*(q.y*q.z + q.w*q.x),
q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
res);
break;
case zyz:
twoaxisrot( 2*(q.y*q.z - q.w*q.x),
2*(q.x*q.z + q.w*q.y),
q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
2*(q.y*q.z + q.w*q.x),
-2*(q.x*q.z - q.w*q.y),
res);
break;
case zxy:
threeaxisrot( -2*(q.x*q.y - q.w*q.z),
q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
2*(q.y*q.z + q.w*q.x),
-2*(q.x*q.z - q.w*q.y),
q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
res);
break;
case zxz:
twoaxisrot( 2*(q.x*q.z + q.w*q.y),
-2*(q.y*q.z - q.w*q.x),
q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
2*(q.x*q.z - q.w*q.y),
2*(q.y*q.z + q.w*q.x),
res);
break;
case yxz:
threeaxisrot( 2*(q.x*q.z + q.w*q.y),
q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
-2*(q.y*q.z - q.w*q.x),
2*(q.x*q.y + q.w*q.z),
q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
res);
break;
case yxy:
twoaxisrot( 2*(q.x*q.y - q.w*q.z),
2*(q.y*q.z + q.w*q.x),
q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
2*(q.x*q.y + q.w*q.z),
-2*(q.y*q.z - q.w*q.x),
res);
break;
case yzx:
threeaxisrot( -2*(q.x*q.z - q.w*q.y),
q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
2*(q.x*q.y + q.w*q.z),
-2*(q.y*q.z - q.w*q.x),
q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
res);
break;
case yzy:
twoaxisrot( 2*(q.y*q.z + q.w*q.x),
-2*(q.x*q.y - q.w*q.z),
q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
2*(q.y*q.z - q.w*q.x),
2*(q.x*q.y + q.w*q.z),
res);
break;
case xyz:
threeaxisrot( -2*(q.y*q.z - q.w*q.x),
q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
2*(q.x*q.z + q.w*q.y),
-2*(q.x*q.y - q.w*q.z),
q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
res);
break;
case xyx:
twoaxisrot( 2*(q.x*q.y + q.w*q.z),
-2*(q.x*q.z - q.w*q.y),
q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
2*(q.x*q.y - q.w*q.z),
2*(q.x*q.z + q.w*q.y),
res);
break;
case xzy:
threeaxisrot( 2*(q.y*q.z + q.w*q.x),
q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
-2*(q.x*q.y - q.w*q.z),
2*(q.x*q.z + q.w*q.y),
q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
res);
break;
case xzx:
twoaxisrot( 2*(q.x*q.z - q.w*q.y),
2*(q.x*q.y + q.w*q.z),
q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
2*(q.x*q.z + q.w*q.y),
-2*(q.x*q.y - q.w*q.z),
res);
break;
default:
std::cout << "Unknown rotation sequence" << std::endl;
break;
}
}
Ответ 7
Wikipedia показывает, как вы можете использовать части кватерниона и вычислять углы эйлеров.
Ответ 8
Для тех, кто наткнулся на эту страницу во время Googling, я недавно нашел вывод для этих преобразований для всех 12 собственных Тейт-Брайан (1-2-3, 3-2-1 и т.д.) и Правильного Эйлера (1-2 -1, 3-1-3 и т.д.) В следующих двух ссылках:
Благодаря frodo2975 для второй ссылки.