24

ベクトルを回転させたい場合は、クォータニオンを正規化する必要があることを知っています。

しかし、クォータニオンを自動的に正規化しない理由はありますか?そして、ある場合、どのクォータニオン操作が正規化されていないクォータニオンになりますか?

  • 2つのクォータニオンを乗算しますか?
  • 内積?

申し訳ありませんが、この質問が少しあいまいな場合。私はまだ四元数に頭を包み込もうとしています。

4

6 に答える 6

40

遅い対応; この回答は、質問者ではなく、将来この質問に出くわす人々のためのものです。

たまにクォータニオンを正規化することだけに関して、他の2つの答えには同意しません。クォータニオンを使用してベクトルを回転/変換する、または回転/変換行列を生成するための標準式は、クォータニオンが正規化されていることを暗黙的に想定しています。正規化されていないクォータニオンを使用した結果として生じるエラーは、クォータニオンの大きさの2乗に比例します。二乗誤差の増加は避けるのが最善です。

頻繁に正規化する場合は、平方根は必要ありません。一次近似は非常にうまく機能します。IEEEが2倍になり、多少定型化されているため、クォータニオンに使用するものは次のとおりです。

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)は、1次のテイラー展開ではなく1次のパデ近似を使用していることに注意してください。この近似は、有効な場合、平方根呼び出しを単純な除算に置き換えます。重要なのは、その近似がいつ有効になるかを見つけることです。ここで、マジックナンバー2.107342e-08が機能します。0.5*(3.0-qmagsq)1.0/std::sqrt(qmagsq)

なぜパデ近似なのか?2つの理由。1つは、値がqmagsq1に近い場合、1+qmagsq精度の低下が。よりも低くなること3-qmagsqです。もう1つは、パデ近似がテイラー展開と比較して誤差を3分の1に削減することです。qmagsq0〜2の値の場合、この近似の誤差は。未満です(1-qmagsq)^2 / 8。マジックナンバー2.107342e-08は、このエラーがIEEE2倍のULPの半分以上である場所を表しています。妥当な小さなステップを踏んでいる場合、クォータニオンの大きさの2乗は常にその制限内になります。に電話することはありませんsqrt

この「常に正規化する」パラダイムの1つの例外は、リー群積分手法を使用してクォータニオンを伝播する場合です。それが何を意味するのかわからない場合は、おそらくq(t+Δt) = q(t) + dq(t)/dt*Δtクォータニオンを伝播するために同等のものを使用しています。リー群積分器ではない高階積分手法を使用している場合でも、どこかでそのオイラーステップを使用しています。

于 2012-10-17T12:52:07.417 に答える
11

浮動小数点歳差運動エラーにより単位長ではなくなるため、クォータニオンを生成する操作は正規化する必要があります。

パフォーマンス上の理由から、正規化を自動的に実行する標準ルーチンには反対することをお勧めします。有能なプログラマーは、精度の問題を認識し、必要に応じて数量を正規化できる必要があります。また、単位長のクォータニオンが常に必要なわけではありません。

ベクトル演算についても同じことが言えます。

于 2012-07-26T11:09:27.390 に答える
6

おかしなことに、回転行列の作成は、クォータニオンの正規化が不要な1つの操作であり、1つ節約できます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風の表記法で)クォータニオンの場合w+x*i+y*j+z*k

さらに、同次座標と4x4変換行列を使用している場合は、除算操作を節約することもできます。クォータニオンが正規化されているかのように3x3回転部分を作成し、その2乗の長さを(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.

もちろん、少なくとも時々クォータニオンを正規化することをお勧めします(他の操作でも必要になる場合があります)。

于 2012-07-31T19:58:08.967 に答える
2

単位クォータニオンがその1次導関数を数値積分することによって得られる場合、積分器は単純なエラーフィードバックを使用してそれを自動的に正規化できます。

qがクォータニオンの4行1列の行列を表し、dqがその時間微分を表すとします。次に、dqの代わりにdq + 0.5(1-qq)q / tauを積分器に送信適切な時定数tauを使用すると、 qが継続的に正規化されます。qqは内積を表します。

重力のない空間に360万秒間浮かんでいる、保守的で関節のあるブリカードメカニズムをシミュレートしました。これは約42日です。クォータニオンは、フローティングベースボディの方向を表しています。総エネルギーは、0.5秒の時定数タウを使用して100万分の1以内に一定のままでした。数値積分器DEでは、10^-12の絶対許容誤差とゼロの相対許容誤差が使用されました。

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

クォータニオンは、多くの場合、数値積分によって取得されます。それらが積分器内で正規化されていない場合、振幅と位相の誤差が蓄積されます。正規化されたクォータニオンは単位球に沿って移動し、その1次導関数はその球に接します。クォータニオンが単位球から離れる方向にドリフトすると、積分器の外部で正規化しても修正できない位相エラーが蓄積され始めます。したがって、位相誤差を最小限に抑えるために、クォータニオンは数値積分器内で連続的に正規化する必要があります。

于 2013-03-10T16:59:41.430 に答える
0

あなたの質問はあいまいですが、クォータニオンを正規化する必要がある場合は簡単です

q_normalized = q / square(norm(q))

で、q = q1 + q2i + q3 j + q4 kノルム(q)=(q1)^ 2 +(q2)^ 2 +(q3)^ 2)+(q4)^ 4

他にあなたの質問を私に説明するなら

于 2016-07-09T02:26:55.900 に答える
-1

NONunitクォータニオンの使用は効率的です。

補間など、単位長を必要とする操作はごくわずかです。

いくつかのヒント:

  1. 非ユニットクォータニオンの作成と変換は、より効率的になります。
  2. 非単位クォータニオンから行列への変換はまだ高速です。クォータニオンの2乗のスケールを補正するだけです。
  3. 非単位クアットへの変換行列はより高速です。

したがって、ユニットクォータニオンのみを使用する必要はなく、一般的な方法です。すべてのユースケースについて、正規化を使用するかどうかを決定できます。個人的には、非ユニットクォータニオンを使用することを好みます。

警告:ユニットクォータニオンを使用する場合、数値エラーを忘れることがよくあります。たとえば、行列のクォータニオンから/への変換で、それでも単位が大きな数値の不安定性をもたらすと考えると、行列はスケーリングされ、抽出されたクォータニオンは無効になります。あなたはそのような実験を簡単に行うことができます。

于 2014-03-17T12:01:15.877 に答える