4

x、y、z 軸を中心とした回転という 3 つの角度を与える入力デバイスがあります。

ここで、これらの角度を使用して、ジンバル ロックなしで 3D 空間を回転させる必要があります。クォータニオンに変換できると思っていましたが、どうやらデータを 3 つの角度として取得しているので、これは役に立ちませんか?

その場合、入力データは単に x、y、z 軸の回転角度であることを念頭に置いて、スペースを正しく回転させるにはどうすればよいので、それを「回避」することはできません。同様に、軸の回転の順序を変更しても役に立ちません。とにかくすべての軸が使用されるため、順序を入れ替えても何も達成されません。しかし、確かにこれを行う方法があるに違いありませんか?

それが役立つ場合、問題はこの関数を実装することでかなり軽減できます。

void generateVectorsFromAngles(double &lastXRotation,
                                                      double &lastYRotation,
                                                      double &lastZRotation,
                                                      JD::Vector &up,
                                                      JD::Vector &viewing) {
    JD::Vector yaxis = JD::Vector(0,0,1);
    JD::Vector zaxis = JD::Vector(0,1,0);
    JD::Vector xaxis = JD::Vector(1,0,0);
    up.rotate(xaxis, lastXRotation);
    up.rotate(yaxis, lastYRotation);
    up.rotate(zaxis, lastZRotation);
    viewing.rotate(xaxis, lastXRotation);
    viewing.rotate(yaxis, lastYRotation);
    viewing.rotate(zaxis, lastZRotation);
}

ジンバルロックを回避する方法で。

4

2 に答える 2

2

デバイスが絶対 X/Y/Z 角度 (実際のジンバルのようなものを意味します) を提供している場合、回転が発生する順序を説明する特定のシーケンスがあります。

「順序は関係ありません」と言うので、これは、デバイスが (ほぼ確実に) 3 軸レート ジャイロのようなものであり、角度差を取得していることを示唆しています。この場合、次のように、3 つの微分角度を回転ベクトルに結合し、これを使用して方向クォータニオンを更新します。

given differential angles (in radians):
  dXrot, dYrot, dZrot

and current orientation quaternion Q such that:
  {r=0, ijk=rot(v)} = Q {r=0, ijk=v} Q*

construct an update quaternion:
  dQ = {r=1, i=dXrot/2, j=dYrot/2, k=dZrot/2}

and update your orientation:
  Q' = normalize( quaternion_multiply(dQ, Q) )

dQ は、単位四元数の大まかな近似にすぎないことに注意してください (これにより、normalize()操作が通常よりも重要になります)。ただし、微分角度が大きくない場合は、実際にはかなり適切な近似値です。微分角度大きい場合でも、この単純な近似は、他の多くの方法よりも無意味ではありません。大きな角度差に問題がある場合は、2 次補正を追加して精度を向上させてみてください (3 番目のセクションで説明)。

ただし、より可能性の高い問題は、このよう繰り返しの更新は、単に蓄積された算術誤差が原因でドリフトする傾向があることです。また、物理センサーには偏りがあります。たとえば、レート ジャイロにはオフセットがあり、これを修正しないと、方向推定Qの歳差運動が遅くなります。この種のドリフトがアプリケーションにとって重要な場合、安定したシステムを維持したい場合は、それを検出/修正する何らかの方法が必要になります。


大きな微分角度に問題がある場合は、正確な更新クォータニオンを計算するための三角関数の公式がありdQます。総回転角度は、入力ベクトルの大きさに線形に比例するはずです。これにより、次のように正確な更新クォータニオンを計算できます。

given differential half-angle vector (in radians):
  dV = (dXrot, dYrot, dZrot)/2

compute the magnitude of the half-angle vector:
  theta = |dV| = 0.5 * sqrt(dXrot^2 + dYrot^2 + dZrot^2)

then the update quaternion, as used above, is:
  dQ = {r=cos(theta), ijk=dV*sin(theta)/theta}
     = {r=cos(theta), ijk=normalize(dV)*sin(theta)}

sin(theta)/thetaまたは のいずれかを直接計算することは、ゼロに近い特異値ですが、最初のセクションの近似のように、ゼロに近いnormalize(dV)ベクトルの極限値ijkは単純に であることに注意してください。ijk = dV = (dXrot,dYrot,dZrot)この方法で更新クォータニオンを計算する場合、簡単な方法はこれを確認し、小さい近似を使用するthetaことです (これは非常に優れた近似です!)。


cos(theta)最後に、別のアプローチは、とにテイラー展開を使用することsin(theta)/thetaです。これは中間的なアプローチです。精度の範囲を広げる改善された近似です。

cos(x)    ~  1 - x^2/2 + x^4/24 - x^6/720 ...
sin(x)/x  ~  1 - x^2/6 + x^4/120 - x^6/5040 ...

したがって、最初のセクションで述べた「二次補正」は次のとおりです。

dQ = {r=1-theta*theta*(1.0/2), ijk=dV*(1-theta*theta*(1.0/6))}
Q' = normalize( quaternion_multiply(dQ, Q) )

項を追加すると近似の正確な範囲が広がりますが、更新ごとに +/-90 度以上が必要な場合は、2 番目のセクションで説明されている正確な三角関数を使用する必要があります。正確な三角解と組み合わせてテイラー展開を使用することもできます。近似と正確な式をシームレスに切り替えることができるため、役立つ場合があります。

于 2012-09-06T20:25:38.877 に答える
0

「ジンバルロック」は計算/数学の問題ではなく、物理的なデバイスの問題だと思います。

XYZ 回転で任意の向きを表すことができるとすれば、「ジンバル ロック ポイント」であっても考えられる向きの変化の XYZ 表現があります。あなたの物理的なジンバルはこのように回転できないかもしれませんが、数学はまだ機能します:)。

ここでの唯一の問題は入力デバイスです。ジンバルの場合はロックできますが、詳細は提供されていません。


編集:OK、関数を追加した後、必要なものがわかると思います。機能は完全に正しいです。しかし残念なことに、XYZ 軸の回転を使用して方向を編集するための簡単で継続的な方法を取得することはできません。プロの 3D パッケージでさえ、そのようなソリューションは見たことがありません。

私の頭に浮かぶ唯一のことは、入力を飛行機のステアリングのように扱うことです。最初の向きがいくつかあるだけで、X、Y、または Z 軸を中心にある程度回転させることができます。次に、新しい方向を保存し、入力をクリアします。3DMax/Maya/Blender での回転も同じ方法で行われます。

達成したい実際の使用法についてより多くの情報を提供していただければ、より良いアイデアが得られるかもしれません。

于 2012-09-06T09:55:11.457 に答える