Кватернион и нормализация

Я знаю, что кватернионы должны быть нормализованы, если я хочу, чтобы повернуть вектор.

но есть ли причины не нормализовать кватернион автоматически? И если есть, то какие операции кватернионов приводят к ненормализованным кватернионам?

  • умножение двух кватернионов?
  • скалярное произведение?

Извините, если этот вопрос немного нечеткий. Я все еще пытаюсь разобраться в кватернионах.

6 ответов


любая операция, которая производит кватернион, должна быть нормализована, потому что ошибки прецессии с плавающей запятой приведут к тому, что она не будет единицей длины.

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

то же верно для векторных операций.


поздний ответ; этот ответ предназначен для людей, которые сталкиваются с этим вопросом в будущем, а не для спрашивающего.

Я не согласен с двумя другими ответами, касающимися только нормализации кватерниона изредка. Стандартные формулы для использования кватерниона для вращения / преобразования вектора или для генерации матрицы вращения/преобразования неявно предполагают, что кватернион нормализован. Ошибки, возникающие в результате использования ненормированных кватернионов пропорциональны квадрат величины кватерниона. Квадратичного роста ошибок лучше избегать.

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

double qmagsq = quat.square_magnitude();
if (std::abs(1.0 - qmagsq) < 2.107342e-08) {
    quat.scale (2.0 / (1.0 + qmagsq));
}
else {
    quat.scale (1.0 / std::sqrt(qmagsq));
}

обратите внимание, что я использую аппроксимант паде первого порядка 2.0/(1.0+qmagsq) а не разложение Тейлора первого порядка 0.5*(3.0-qmagsq) оценить 1.0/std::sqrt(qmagsq). Это приближение, если оно действительно, заменяет квадрат корневой вызов простым делением. Ключ в том, чтобы найти, когда это приближение действительно, и где это магическое число 2.107342 e-08 вступает в игру.

почему паде аппроксимант? По двум причинам. Один из них-для значений qmagsq близко к одному,1+qmagsq теряет меньше точности, чем 3-qmagsq. Другой заключается в том, что аппроксимант паде сокращает ошибку в три раза по сравнению с разложением Тейлора. Для значений qmagsq между 0 и 2, Ошибка в этом приближении меньше, чем (1-qmagsq)^2 / 8. Магическое число 2.107342 e-08 представляет, где эта ошибка больше половины ULP для IEEE удваивается. Если вы делаете разумные небольшие шаги, квадрат величины кватерниона всегда будет находиться в пределах этого предела. Ты никогда не позвонишь sqrt.

единственным исключением из этой парадигмы "нормализовать всегда" может быть, если вы используете метод интеграции группы ли для распространения кватернионов. Если вы не знаете, что это значит, вы, вероятно, используете эквивалент из q(t+Δt) = q(t) + dq(t)/dt*Δt для распространения кватерниона. Вы все еще используете этот шаг Эйлера, даже если вы используете технику интеграции более высокого порядка, которая не является интегратором группы ли.


как ни странно, построение матриц вращения-это одна операция, где нормализация кватернионов не требуется, сохраняя вас один sqrt:

M = [w*w+x*x-y*y-z*z, 2*(-w*z+x*y),    2*(w*y+x*z);
     2*(w*z+x*y),     w*w-x*x+y*y-z*z, 2*(-w*x+y*z);
     2*(-w*y+x*z),    2*(w*x+y*z),     w*w-x*x-y*y+z*z] / (w*w+x*x+y*y+z*z)

(в нотации MATLAB-ish) для кватерниона w+x*i+y*j+z*k.

кроме того, если вы работаете с однородными координатами и матрицами преобразования 4x4, вы также можете сохранить некоторые операции деления: просто сделайте часть вращения 3x3, как если бы кватернион был нормализован, а затем поместите его квадратную длину в (4,4)-элемента:

M = [w*w+x*x-y*y-z*z, 2*(-w*z+x*y),    2*(w*y+x*z),     0;
     2*(w*z+x*y),     w*w-x*x+y*y-z*z, 2*(-w*x+y*z),    0;
     2*(-w*y+x*z),    2*(w*x+y*z),     w*w-x*x-y*y+z*z, 0;
     0,               0,               0,               w*w+x*x+y*y+z*z].

умножить на матрицу перевода и т. д. как обычно , для полной трансформации. Таким образом, вы можете сделать, например,

[xh yh zh wh]' = ... * OtherM * M * [xold yold zold 1]';
[xnew ynew znew] = [xh yh zh] / wh.

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


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

пусть q представляют собой матрицу 4 на 1 столбец кватернионов и dq его производная по времени. Тогда посылаю dq + 0.5(1-q.q) q/tau интегратору вместо dq и используя подходящую постоянную времени тау будет непрерывно нормализовать q. вопрос.вопрос представляет внутренний продукт.

я смоделировал консервативный, артикулирующий механизм Брикарда, плавающий в невесомости в течение 3,6 миллиона секунд, что составляет почти 42 дня. Кватернионы представляли собой ориентацию тела плавучего основания. Общая энергия оставалась постоянной в пределах одной части на миллион, используя постоянную времени тау 0,5 сек. Абсолютный допуск ошибки 10^-12 и относительный допуск ошибки нул были использованы в численном интеграторе DE.

http://www.amazon.com/Computer-Solution-Ordinary-Differential-Equations/dp/0716704617/

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


ваш вопрос неоднозначен, но если вам нужно нормализовать кватернион, это просто

q_normalized = q / square(norm (q))

with, q = q1 +q2i +q3 j +q4 k норма (q) = (q1)^2 + (q2)^2 + (q3)^2) + (q4)^4

если еще объясните мне ваш вопрос


использование Неунитарных кватернионов может быть эффективным.

только несколько операций требуют длины единицы, например интерполяции.

несколько советов:

  1. создание и преобразование в неунитарные кватернионы может быть более эффективным.
  2. преобразование в матрицу из неунитарного кватерниона по-прежнему происходит быстро. Просто компенсируйте масштаб кватерниона в квадрате.
  3. преобразование матрицы в неунитарный quat происходит быстрее.

поэтому это не требуется использовать только единичные кватернионы - обычная практика. Для каждого случая использования вы можете принять решение использовать или не нормализовать. Лично я предпочитаю использовать неунитарные кватернионы.

предупреждение: часто, работая с единичными кватернионами, мы забываем о числовых ошибках. Например, преобразование из / в матрицу кватерниона и думая, что он по-прежнему единица делают большую численную неустойчивость , матрица масштабируется, извлеченные кватернионы недействительны. Вы можете легко сделать такой эксперимент.