4

私は今後のプロジェクトのためにクォータニオンを研究しており、理解できない概念的な問題に遭遇しました。

四元数を正規化する方法は次のとおりです。

q_mag = sqrt(q0^2+q1^2+q2^2+q3^2)
q0 = q0/q_mag  
q1 = q1/q_mag   
q2 = q2/q_mag  
q3 = q3/q_mag

簡単に、他のベクトルを正規化するのと同じように。しかし、私の質問は、この正規化方法が同じ回転情報をどのように保持するかです。以下のような軸角度表現を表す四元数の定義を使用すると、

angle = 2 * acos(q0)
x = qx / sqrt(1-q0*q0)
y = qy / sqrt(1-q0*q0)
z = qz / sqrt(1-q0*q0)

正規化操作では x、y、z の値が均等にスケーリングされるため、回転する軸が変化することはありません。しかし、角度自体の値は、正規化操作によって大幅に変化します。

では、q0 の値を保持し、他のポイントのみを調整して正規化する方法を使用する方が理にかなっているのではないでしょうか?

4

2 に答える 2

5

数学の答え:単位クォータニオンは 3D 空間での回転を表します。他の (つまり、非単位の) クォータニオンは回転を表さないため、式 angle = 2 * acos(q0) はこれらのクォータニオンには適用されません。したがって、正規化するときに角度の変化はありません。正規化するクォータニオンはそもそも回転を表していないためです。

プログラミングの答え:浮動小数点演算には精度の問題があります。これらの問題が小さな誤差となり、それが積み重なると大きな誤差となる場合があります。2 つの単位四元数を乗算すると、数学的な結果は別の単位四元数になります。ただし、単位クォータニオン乗算の浮動小数点実装は、ノルムが 1 に近いが 1 に等しくないクォータニオンになる場合があります。この場合、クォータニオンを正規化してエラーを修正します。正規化するとき、q0 を 1 に非常に近いノルムで割るので、q0 の値に大きな変化はありません。早期に正規化するため、ノルムは常に 1 に非常に近く、精度について心配する必要はありません。

遅い回答ですが、お役に立てば幸いです。

于 2014-01-17T19:13:49.533 に答える
0

申し訳ありませんが、これは少しネクロであることは知っていますが、これは将来の読者にとって役立つかもしれないと思います.

私が完全に間違っていない限り、丸め誤差を考慮して正規化するときに角度を保持しない方が実際には望ましいです (特にゲームで四元数を使用して回転を表す場合)。理由を説明しましょう:

回転を表すはずの 2 つのクォータニオンがあり (以降、それらをQ1と呼びQ2ます)、丸め誤差のために単位ではなく、それらを乗算したいとします (結果を呼び出します)。Q3. これも単位四元数にしたい)。t1が変数であり、 のすべてのコンポーネントと乗算されると、単位四元数Q1Q1なります (つまり、t1は のユークリッド長で除算されQ1ますが、実際にはここでは関係ありません。はt2に対して同じことを行いQ2ます。正規化後のクォータニオン (つまりQ3 = (t1*Q1)(t2*Q2)) 次の結果が得られます。

Q3.w = t1*Q1.w*t2*Q2.w - t1*Q1.x*t2*Q2.x - t1*Q1.y*t2*Q2.y - t1*Q1.z*t2*Q2.z
Q3.x = t1*Q1.w*t2*Q2.x + t1*Q1.x*t2*Q2.w + t1*Q1.y*t2*Q2.z - t1*Q1.z*t2*Q2.y
Q3.y = t1*Q1.w*t2*Q2.y - t1*Q1.x*t2*Q2.z + t1*Q1.y*t2*Q2.w + t1*Q1.z*t2*Q2.x
Q3.z = t1*Q1.w*t2*Q2.z + t1*Q1.x*t2*Q2.y - t1*Q1.y*t2*Q2.x + t1*Q1.z*t2*Q2.w

これは次のように書き換えることができます

Q3.w = (t1*t2)*(Q1.w*Q2.w - Q1.x*Q2.x - Q1.y*Q2.y - Q1.z*Q2.z)
Q3.x = (t1*t2)*(Q1.w*Q2.x + Q1.x*Q2.w + Q1.y*Q2.z - Q1.z*Q2.y)
Q3.y = (t1*t2)*(Q1.w*Q2.y - Q1.x*Q2.z + Q1.y*Q2.w + Q1.z*Q2.x)
Q3.z = (t1*t2)*(Q1.w*Q2.z + Q1.x*Q2.y - Q1.y*Q2.x + Q1.z*Q2.w)

つまり、Q3=(t1*Q1)(t2*Q2)=(t1*t2)(Q1*Q2). ご覧のとおり、乗算後にこの方法で正規化すると、両方の入力を乗算前に正規化した場合と同じ四元数になります。これは、クォータニオンが単位からどれだけずれても同じ結果が得られるため、すべての計算の後ではなく、ベクトル/メッシュ/ポイントに回転を適用する直前に正規化するだけでよいことを意味します。

ここで、同じ計算を見てみましょうが、クォータニオン単位を作成する角度を維持する方法を使用します (t変数は、非実数 (別名 xyz) 部分のみを乗算したときにクォータニオン単位を作成します)。

Q3.w = Q1.w*Q2.w - t1*Q1.x*t2*Q2.x - t1*Q1.y*t2*Q2.y - t1*Q1.z*t2*Q2.z
Q3.x = Q1.w*Q2.x + t1*Q1.x*Q2.w + t1*Q1.y*t2*Q2.z - t1*Q1.z*t2*Q2.y
Q3.y = Q1.w*Q2.y - t1*Q1.x*t2*Q2.z + t1*Q1.y*Q2.w + t1*Q1.z*t2*Q2.x
Q3.z = Q1.w*Q2.z + t1*Q1.x*t2*Q2.y - t1*Q1.y*t2*Q2.x + t1*Q1.z*Q2.w

の非実数成分がQ3共通因子を持たなくなったことに注意してください。これは、この方法で事後操作を正規化すると、正規化してこの方法で事前操作を行ったQ3場合に得られるものとは異なる四元数になる可能性があることを意味します。Q2Q1

クォータニオンの正規化は安価な操作ではないため、特に多数の回転を合成する場合は、あまり頻繁に使用する必要がないため、ゲームのようなものには角度を保存しない方法を使用することをお勧めします。同じことが他のクォータニオン操作にも当てはまるかどうかはわかりませんが、おそらくクォータニオンをたくさん乗算することになると考えると、少なくとも私の意見では、角度を保存しない方法を使用することが望ましいです。

于 2019-05-09T12:35:30.020 に答える