Почему при вращении кватерниона в определенных направлениях возникает внезапный поворот / крен?

Учитывая нормализованный кватернион, A_qи нормализованный вектор направления, B_vмы рассчитываем новое вращение, C_q, что будет вращаться A_q «лицом» в направлении B_v, Чтобы уточнить, давай D_q = C_q * A_qтакой, что (1,0,0) повернуто на D_q будет равен B_v,

Нотабене Для удобства обозначения отныне мы будем ссылаться на (1,0,0) повернутый любым кватернионом как символ этого кватерниона с суффиксом _vт.е. (1,0,0) повернуто на A_q становится A_v,

демонстрация

Я реализовал такой сценарий Вот (интерактивно), с источником Вот, и прикрепили gif ниже тоже.

введите описание изображения здесь

Моя проблема

Моя проблема в том, что когда A_v а также B_v близки к противоположным (или, казалось бы, приближаются к антипараллельным), D_q проявляет внезапный поворот / крен, что нежелательно. Изображение выше демонстрирует это.

Код в вопросе

Он находится в C ++ API UE4, но он должен быть достаточно независимым от языка / фреймворка для анализа:

FTransform UMWEUtil::FindNewRotation(FTransform A_t, FVector B_v)
{
FQuat A_q = A_t.GetRotation();
FVector A_v = A_q.GetForwardVector();

A_v.Normalize();
B_v.Normalize();

FVector AxisOfRotation = FVector::CrossProduct(A_v, B_v).GetSafeNormal();
float Rads = FMath::Acos(FVector::DotProduct(A_v, B_v));
FQuat C_q(AxisOfRotation, Rads);

FQuat D_q = C_q * A_q;

return FTransform(D_q);
}

Мои вопросы

  1. Почему возникает этот внезапный артефакт крена / закручивания?
  2. Я предполагаю, что это из-за перекрестного произведения A_v X B_v меняющиеся полушария. Но тогда, почему это происходит только один раз, а не дважды (перекрестное произведение, A_v X B_v виден переход полушарий дважды в полный оборот)?
  3. Наконец, решение, которое я нашел, состоит в том, чтобы разложить D_q в кватернионы качания / крутки и используйте только кватернионы качания (таким образом, удаляя внезапный поворот). Тем не менее, это похоже на пластырь из-за моего непонимания проблемы, есть ли другое решение, которое приведет к плавному переходу?

Мое решение (может быть, ненужное?)

FTransform UMWEUtil::FindNewRotation2(FTransform A_t, FVector B_v)
{
FQuat A_q = A_t.GetRotation();
FVector A_v = A_q.GetForwardVector();

A_v.Normalize();
B_v.Normalize();

FVector AxisOfRotation = FVector::CrossProduct(A_v, B_v).GetSafeNormal();
float Rads = FMath::Acos(FVector::DotProduct(A_v, B_v));
FQuat C_q(AxisOfRotation, Rads);

FQuat D_q = C_q * A_q;

FQuat OutSwing;
FQuat OutTwist;

D_q.ToSwingTwist(FVector::ForwardVector, OutSwing, OutTwist);

return FTransform(OutSwing);
}

3

Решение

Задача ещё не решена.

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

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector