web-dev-qa-db-ja.com

ロドリゲスからオイラー角へ、またはその逆

私はsolvePnPを使用しており、翻訳ベクトルを取得しています。ここで、いくつかのオイラー角をsolvePnPの結果と比較する必要があります。そして、私はオイラー角を「ロドリーグ」に変換したい/必要があります。

ResolvePnPからの並進ベクトルはオイラー角に等しいですか。変換行列は、ロドリゲスと関係がある唯一のものですか?または、3つのオイラー角とはまったく異なる特別なロドリゲ角がありますか?両方の間の数学はどうですか?見つからなかったOpenCV関数はありますか?

11
user1651460

まず、translationベクトルは、rotationとは関係がないため、忘れてください。 :平行移動は物事を動かし、回転はそれらの向きを変えます。

ロドリゲスパラメーターは 軸-角度回転 とも呼ばれます。それらは4つの数_[theta, x, y, z]_で形成されます。つまり、単位ベクトル_v=[x, y, z]_で表される軸を中心に角度「シータ」を回転させる必要があります。 cv :: Rodrigues 関数参照を見ると、OpenCVはロドリゲス表記の「コンパクト」表現を3つの要素_rod2=[a, b, c]_を持つベクトルとして使用しているようです。ここで:

  • 回転する角度thetaは、入力ベクトルtheta = sqrt(a^2 + b^2 + c^2)のモジュールです。
  • 回転軸vは、正規化された入力ベクトルです:_v = rod2/theta = [a/theta, b/theta, c/theta]_

したがって、solvePnPからのロドリゲスベクトルは、 オイラー角表記とわずかに関連していません。これは、 X、Y、Z軸。

両方の回転を比較する方法は?これは良い質問です。オイラー表現とロドリゲス表現の両方に、特異点やその他の問題があります。たとえば、2つのオイラーアジサシまたは2つのロドリゲスパラメーターを比較すると、完全に異なって見える場合がありますが、実際にはほぼ同じ回転を表しています。両方の回転が同じ(または約)であるかどうかを確認する必要がある場合は、次のアプローチに従うことができます。

  1. 両方の回転を行列表記に変換します(クォータニオンも有効です)
    • OpenCVロドリゲスベクトルは cv :: Rodrigues 関数を使用して行列に変換できます
    • オイラーを行列に変換するには、euclideanspace.comの 変換セクション を参照することをお勧めします。
  2. 一方の回転をもう一方の回転から「減算」します。つまり、一方を他方の逆に連結します
    • 回転行列を使用して、一方にもう一方の転置(逆回転)を掛けます。ヌル回転は単位行列です。
    • クォータニオンを使用して、一方に他方の複素共役を掛けます(最後の3つのコンポーネントを否定します)。
  3. 結果がヌル回転に近いかどうかを確認します:
    • ヌル回転行列は単位元です。
    • ヌルクォータニオンの最初のコンポーネントには1または-1があります
61
dunadar

@dunadarの優れた答えに追加:

Rodriguesは、rvecを回転行列Rに変換します(またはその逆)。回転している(平行移動)ベクトルと内積を取ることにより、オイラー角から構築された回転行列を使用するのと同じ方法で、Rを直接使用できます。v_rotate = R*v

あなたはロドリゲスの回転行列からオイラー角に変換できますが、複数の解決策があります。その理由は、オイラー回転の順序(ピッチ、ヨー、ロール)が重要であるため、ロドリゲスの回転を表す方法は複数あるためです。参照: http://www.staff.city.ac.uk/~sbbh653/publications/euler.pdf

3
Fraser Harris

ここで他の回答を補足するために、より具体的な回答を追加します。オイラー角の代わりに方向ベクトルが必要な場合は、行列の乗算を使用してプロセスを実際に簡略化できます。簡単な解決策は次のとおりです。

// The output is a direction vector in OpenGL coordinate system:
// +X is Right on the screen, +Y is Up, +Z is INTO the screen
static Vector3 ToDirectionVectorGL(const Mat& rodrigues1x3) noexcept
{
    Mat rotation3x3;
    cv::Rodrigues(rodrigues1x3, rotation3x3);

    // direction OUT of the screen in CV coordinate system, because we care
    // about objects facing towards us - you can change this to anything
    // OpenCV coordsys: +X is Right on the screen, +Y is Down on the screen,
    //                  +Z is INTO the screen
    Vec3d axis{ 0, 0, -1 }; 
    Mat direction = rotation3x3 * Mat(axis, false);

    // normalize to a unit vector
    double dirX = direction.at<double>(0);
    double dirY = direction.at<double>(1);
    double dirZ = direction.at<double>(2);
    double len = sqrt(dirX*dirX + dirY*dirY + dirZ*dirZ);
    dirX /= len;
    dirY /= len;
    dirZ /= len;
    // Convert from OpenCV to OpenGL 3D coordinate system
    return { float(dirX), float(-dirY), float(dirZ) };
}

これを頭のポーズの推定に使用している場合は、ロドリゲスの1x3回転が{0,0,0}の周りに正しく形成されていることを確認してください。そうしないと、奇妙な結果が得られる可能性があります。

1
Jorma Rebane