У меня есть два вектора u и v. Есть ли способ найти кватернион, представляющий поворот от u к v?
math
vector
quaternions
sdfqwerqaz1
источник
источник
crossproduct
не будет действительным в этих случаях, поэтому сначала необходимо проверитьdot(v1, v2) > 0.999999
иdot(v1, v2) < -0.999999
, соответственно, и либо вернуть идентификационный quat для параллельных векторов, либо вернуть поворот на 180 градусов (вокруг любой оси) для противоположных векторов.sqrt((v1.Length ^ 2) * (v2.Length ^ 2))
упрощает доv1.Length * v2.Length
. Я не мог найти никаких вариаций для получения разумных результатов.Векторное решение на полпути
Я придумал решение, которое, как мне кажется, пытался представить Имброндир (хотя и с небольшой ошибкой, вероятно, поэтому зловещему бурундуку было трудно его проверить).
Учитывая, что мы можем построить кватернион, представляющий вращение вокруг оси, например:
И что точечное произведение двух нормализованных векторов:
Поскольку поворот от u к v может быть достигнут путем поворота на тета (угол между векторами) вокруг перпендикулярного вектора, похоже, что мы можем напрямую построить кватернион, представляющий такое вращение, из результатов точечного и перекрестного произведения ; однако в его нынешнем виде theta = angle / 2 , что означает, что это приведет к удвоению желаемого поворота.
Одно из решений состоит в том, чтобы вычислить вектор на полпути между u и v и использовать точечное произведение и перекрестное произведение u и вектора половинного пути, чтобы построить кватернион, представляющий поворот, в два раза превышающий угол между u и вектором половины пути что ведет к v !
Есть особый случай, когда u == -v и уникальный вектор на полпути невозможно вычислить. Это ожидаемо, учитывая бесконечное количество поворотов по «кратчайшей дуге», которые могут привести нас от u к v , и мы должны просто повернуться на 180 градусов вокруг любого вектора, ортогонального к u (или v ) в качестве нашего специального решения. Для этого берется нормализованное произведение вектора u на любой другой вектор, не параллельный u .
Далее следует псевдокод (очевидно, что в действительности особый случай должен учитывать неточности с плавающей запятой - вероятно, путем проверки скалярных произведений на некоторый порог, а не на абсолютное значение).
Также обратите внимание, что нет особого случая, когда u == v (создается кватернион идентичности - проверьте и убедитесь сами).
orthogonal
Функция возвращает любой вектор , ортогональный к данному вектору. Эта реализация использует векторное произведение с наиболее ортогональным базисным вектором.Кватернионное решение на полпути
На самом деле это решение, представленное в принятом ответе, и оно кажется немного быстрее, чем векторное решение на полпути (примерно на 20% быстрее по моим измерениям, хотя не верьте мне на слово). Я добавляю его сюда на тот случай, если другие, как я, заинтересованы в объяснении.
По сути, вместо вычисления кватерниона с использованием вектора на полпути вы можете вычислить кватернион, который приводит к удвоению необходимого поворота (как подробно описано в другом решении), и найти кватернион на полпути между этим и нулевым градусом.
Как я объяснял ранее, кватернион для удвоения необходимого вращения:
И кватернион для нулевого вращения:
Вычисление кватерниона на полпути - это просто вопрос суммирования кватернионов и нормализации результата, как и с векторами. Однако, как и в случае с векторами, кватернионы должны иметь одинаковую величину, иначе результат будет искажен в сторону кватерниона с большей величиной.
Кватернион построен из точки и векторного произведения двух векторов будет иметь такую же величину , как и те продукты:
length(u) * length(v)
. Вместо того, чтобы делить все четыре компонента на этот коэффициент, мы можем масштабировать кватернион идентичности. И если вам интересно, почему принятый ответ, по-видимому, усложняет ситуацию при использованииsqrt(length(u) ^ 2 * length(v) ^ 2)
, это потому, что квадрат длины вектора вычисляется быстрее, чем длина, поэтому мы можем сэкономить одноsqrt
вычисление. Результат:А потом нормализовать результат. Псевдокод выглядит следующим образом:
источник
Проблема, как указано, четко не определена: для данной пары векторов не существует уникального поворота. Рассмотрим, например, случай, когда u = <1, 0, 0> и v = <0, 1, 0> . Один поворот от u до v будет поворотом на pi / 2 вокруг оси z. Другой поворот от u к v будет поворотом на пи вокруг вектора <1, 1, 0> .
источник
Почему бы не представить вектор с помощью чистых кватернионов? Возможно, лучше сначала их нормализовать.
q 1 = (0 u x u y u z ) '
q 2 = (0 v x v y v z )'
q 1 q rot = q 2
Предварительно умножить на q 1 -1
q rot = q 1 -1 q 2
где q 1 -1 = q 1 con / q norm
Это можно рассматривать как «левое деление». Правое деление, которое вам не нужно:
q rot, right = q 2 -1 q 1
источник
Я не очень хорошо разбираюсь в Кватернионе. Однако я часами бился над этим и не мог заставить решение Polaris878 работать. Я пробовал предварительно нормализовать v1 и v2. Нормализация q. Нормализация q.xyz. И все же я этого не понимаю. Результат все еще не дал мне правильного результата.
В конце концов, я нашел решение, которое сработало. Если это кому-то поможет, вот мой рабочий (на Python) код:
Особый случай должен быть сделан, если v1 и v2 параллельны, как v1 == v2 или v1 == -v2 (с некоторым допуском), где я считаю, что решения должны быть Quaternion (1, 0,0,0) (без вращения) или Quaternion (0, * v1) (поворот на 180 градусов)
источник
quat = diffVectors(v1, v2); assert quat * v1 == v2
.angle
его ценность определяется скалярным произведением.Некоторые ответы, похоже, не учитывают возможность того, что кросс-произведение может быть 0. В приведенном ниже фрагменте используется представление оси угла:
toQuaternion
Может быть реализован следующим образом :Если вы используете библиотеку Eigen, вы также можете просто:
источник
toQuaternion(axis, ang)
-> вы забыли указать, что этоang
angle
это часть осевого угла кватерниона, измеряемого в радианах.С точки зрения алгоритма, самое быстрое решение выглядит в псевдокоде.
Убедитесь, что вам нужны единичные кватернионы (обычно это требуется для интерполяции).
ПРИМЕЧАНИЕ. Неединичные кватернионы могут использоваться с некоторыми операциями быстрее, чем единицы.
источник