2つの四元数を論理的に等しいかどうか比較するにはどうすればよいですか?


9

私はいくつかの単体テストを書こうとしていますが、四元数を比較する方法がわかりません。2つの四元数が同じ方向を表すかどうかを知る必要があります(オブジェクトは同じ方向を向いています)。位置のようなベクトルを使用して、パーツを比較し、それらが十分に近いことを確認しますが、四元数の場合、値が大きく異なる可能性があります。

2つの四元数を比較するにはどうすればよいですか?


標準的な方法であるかどうかはわかりませんが、たとえばJavaやUnityでは、四元数は4つの浮動小数点値として格納されます。これらの記事で説明したよう単にお互いにこれらを比較: answers.unity3d.com/questions/288338/... stackoverflow.com/questions/5803627/quaternion-comparision
Tholle

1
@Tholleユーザーは、クォータニオンを適用して3Dエンティティを変換/回転する(つまり、ポーズごとに)ことの影響にも関心があります。2つの異なるクォータニオンで同じ回転を実現できます(例:qおよび-q)。(計算上ワイズ)素朴な方法は、同じベクトルに両方の四元数を適用し、そのベクトルの結果が異なっているかどうかを確認することです。..
teodron

回答:


7

2つの四元数がq1and q2である場合、次の2つの条件のいずれかが当てはまる場合、それらは同じ回転を表します。

  1. q1コンポーネントに関してはq2ORにほぼ等しい
  2. q1 構成要素に関してはほぼ等しい -q2

これを知っていれば、目的に合ったかなり単純な等価テスターを書くことができます。


9
+1、ただし1つのnitpickであり、同じ方向(要求されていました)q-q表しますが、同じローテーションではありません。これは補間の際に重要です。
-falstro

@falstro、私はあなたが何を意味するのか理解していると思います:回転軸は逆になりますが、引数の角度も、角度軸回転演算子として表される場合qとの間で否定され-qます。したがって、実際には、技術的にはこれらのローテーションの効果は同じですが、演算子は異なります。そして、はい、SLERPINGするとき、slerpが最短の経路をとるようにするために、S3超球の同じ半球に確認q1してq2横になる必要があります。
teodron、2014年

1
正確に言えば、どちらかの回転を実行すると、最終的に同じ方向になりますが、それを補間します(lerpかslerpか、その他の派手な補間かを問わず)、さまざまな方向に回転していることがわかります。そして、はい、角度の引数は否定されますが、それはと同じな2pi-angleので、否定された軸を中心に長い道のりを回っています。ただし、これが必要な場合もあります。それは注意すべきことであり、q1 dot q2 > 0短いターンの結果q1 dot q2 < 0、長いターンの結果となります。
falstro

12

それが言及されていないからといって。空間方向に使用される四元数は常に単位長である(またはそうである必要がある)ため、以下も機能します。

abs(q1.dot(q2)) > 1-EPS

ここでEPSは、浮動小数点の精度が制限されているために小さなエラーを許容するためのファッジファクターです。両方のクォータニオンが同じ方向を表す場合(そしてその場合のみ)q1 = +- q2、したがってq1.dot(q2) = +- 1。(向きだけでなく)同じ回転であることを確認したい場合は、を削除しabsます。


@bogglez true。tl; drテキストに隠されていました。:)
falstro

+1、かなりエレガントで、おそらく私の答えよりも数値的にさらに効率的です(ただし、SIMD演算が使用されていることが前提です:))。
teodron 2014年

これの数学的な正当化は何ですか?
fabian789

"数学"(引用符は数学者ではない:))正当化:2つの単位長ベクトルは、互いに垂直の場合は0であるドット積(別名内積)を持ちます。同じ方向、一般的なケースでは1 * 1 * cos(phi)、phiの角度...
ntg

2

クォータニオンは4つの浮動小数点数または倍精度数として保存され、x、y、z、wと呼ばれます。最初の3つは軸を表し、wはその軸の周りの回転の度合いを表します。

素朴なアプローチは、2つの四元数の数を比較して、等しいかどうかを調べることです。ただし、浮動小数点計算にはエラーが含まれるため、少なくともeps(イプシロン)と呼ばれるエラーを使用し、各コンポーネントを次のように比較する必要があります

    double const eps = 1e-12; // some error threshold
    abs(quat1_x - quat2_x) < eps // similar enough?
    // repeat for other values..

より良いテストは、2つの四元数のドット積を計算し、それが1.0に近いかどうかをテストすることです。sinとcosを使用してクォータニオンの方程式を調べ、2つのクォータニオンに点を打つだけで、これが機能する理由がすぐにわかります。


0

Dotとepsを使用するためのすべての提案に基づいて、(単一で)使用していることがわかりました:

Mathf.Approximately(Mathf.Abs(Quaternion.Dot(transform.rotation, to)), 1.0f)

私はepsのサイズを決定する必要がなくてもうまくいきました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.