-1

このC++コードは、完全には理解できないフォーラムで見つけました。行列/ベクトルの計算を実行するライブラリがないので、手動でそれを理解して機能を複製する必要があります。

2つのベクトル間のオイラー回転角を計算します..ロドリゲスの公式を使用します

    vector $V1 = << my first vector >>;
    vector $V2 = << my second vector >>;


    vector $axis;
    float $angle;

    $angle = acos($V1*$V2);
    $axis = normalizeVector((cross($V1,$V2)));


    matrix $axis_skewed[3][3] = <<
    0, (-$axis.z), ($axis.y) ;
    ($axis.z), 0, (-$axis.x) ;
    (-$axis.y), ($axis.x), 0 >>;

    matrix $eye3[3][3] = <<
    1, 0, 0;
    0, 1, 0;
    0, 0, 1 >>;

ここから先は物事がトリッキーになります:

    // here's Rodrigues
    $R = $eye3 + sin($angle)*$axis_skewed + (1-cos($angle))*$axis_skewed*$axis_skewed;

eye3マトリックスのすべてのプロパティを追加しますか?
axis_skewed行列のすべてのプロパティを乗算しますか?
そしてRとは何ですか?ベクトルまたは行列?または番号?

これは簡単です。

    matrix $vectorMatr[3][1];
    $vectorMatr[0][0] = ($V1.x);
    $vectorMatr[1][0] = ($V1.y);
    $vectorMatr[2][0] = ($V1.z);

繰り返しますが、これは注意が必要です。

    // $result is the resulting vector

    $result = ($R * $vectorMatr);

ベクトルと行列を乗算して、標準の行列乗算を使用して結果のベクトルを取得しますか?
2つの行列を乗算してから、行列を使用して点を変換しますか?

4

3 に答える 3

2

それが擬似コードだと確信しています。間違いなくC++ではありません。すべての機能はかなり自明です。

acos()---自明

$ V1 * $ V2 ---内積(注:、通常は通常の行列乗算として解釈されますが、「float $ angle = acos($ V1 * $ V2);」のコンテキストでは、そうではありません。ドット積以外のものとして意味があります)

cross()---外積

normalizeVector()---自明

sin($ angle)* $axis_skewed---これはスカラー乗法です

それを得る?

編集

$ R = $ eye3 + sin($ angle)* $ axis_skewed +(1-cos($ angle))* $ axis_skewed * $ axis_skewed;

$eye3-は3x3の行列です

sin($ angle)* $ axis_skewed ---これはスカラー乗法であり、別の3x3行列になります

(1-cos($ angle))* $ axis_skewed ---これはスカラー乗法であり、別の3x3行列になります

(前)* $ axis_skewed ---これは通常の行列の乗算であり、別の3x3行列になります

それは私たちに残します:

$ R=[3x3マトリックス]+[3x3マトリックス]+[3x3マトリックス]

これは、通常のエントリごとの行列の加算です。

于 2010-10-25T02:40:58.847 に答える
2

最後の部分からわかるのは、標準的な行列の乗算です。[3x3]×[3x1]は、[3x1]を生成します。読みにくい構文が好きではありません...

編集:

$ Rは、ピッグペンが示しているように[3x3]行列であり、R = [3x3] + sin(scalar)[3x3] +(1-cos(scalar)) [3x3]*[3x3]です。

2番目の項は[3x3]で、各要素はsin(angle)でスケーリングされ、3番目の項は[3x3] * [3x3]の行列乗算であり、別の[3x3]になります。

その3番目の要素も、係数(1-cos(angle))によってスケーリングされます。

結果のRは要素ごとに実行されます(つまり、R [3x3] = S [3x3] + T [3x3]、R [1,1] = S [1,1] + T [1,1]の場合、R [1,2] = S [1,2] + T[1,2]....など。


この例のようなことをしたい場合は、Matlabを使用してください。投稿した構文は混乱を招き、簡単には読めません。

ちなみに、クォータニオンはオイラー角よりも3D回転を実行するために必要な操作が少ないため(pi / 2の周りで問題が発生することはありません)、数日ある場合はそれらを読むのに時間を費やしてください。数学の裏側もそれほど多くないので、試してみてください。

于 2010-10-25T02:44:31.310 に答える
1

$ axis_skewed [3] [3]の行列指数を実行しようとしています。これは、Rodriguesが短縮形です。

これをC++に入れる場合は、OpenCVのcv::Rodrigues関数を使用することをお勧めします...


cv :: Mat axis_skewed;

.....//値をaxis_skewedに入れます

cv :: Mat R; //完了すると3x3になります

cv :: Rodgrigues(axis_skewed、R)


終わり...

//これがロドリゲスです$R= $ eye3 + sin($ angle)* $ axis_skewed +(1-cos($ angle))* $ axis_skewed * $ axis_skewed;

これは、次のショートカットにすぎません。R = exponential_of_matrix(axis_skewed)

たとえば、matlabではexpm(axis_skewed)を使用します。答えを書き留める分析式があります。あるいは、R = I + axis_skewed + axis_skewed / 2 + ... + axis_skewed ^ N /(N階乗)を実行して、同じ答えを得ることができます。

そしてもちろん、ウィキペディアは上記よりも少し数学を拡張します:http: //en.wikipedia.org/wiki/Rodrigues%27_rotation_formula

上記のコードのOpenCVバージョン(C ++ / C)、https://code.ros.org/svn/opencv/trunk/opencv/modules/calib3d/src/calibration.cpp

const double I[] = { 1, 0, 0, 0, 1, 0, 0, 0, 1 };

        double c = cos(theta);
        double s = sin(theta);
        double c1 = 1. - c;
        double itheta = theta ? 1./theta : 0.;

        rx *= itheta; ry *= itheta; rz *= itheta;

        double rrt[] = { rx*rx, rx*ry, rx*rz, rx*ry, ry*ry, ry*rz, rx*rz, ry*rz, rz*rz };
        double _r_x_[] = { 0, -rz, ry, rz, 0, -rx, -ry, rx, 0 };
        double R[9];
        CvMat matR = cvMat( 3, 3, CV_64F, R );

        // R = cos(theta)*I + (1 - cos(theta))*r*rT + sin(theta)*[r_x]
        // where [r_x] is [0 -rz ry; rz 0 -rx; -ry rx 0]
        for( k = 0; k < 9; k++ )
            R[k] = c*I[k] + c1*rrt[k] + s*_r_x_[k];

OpenCVをsvncheckoutしてビルドし、自分でテストしてcv :: Rodriguesが他のコードと同じ答えを返すことを確認してから、関数をC++プロジェクトに移植することをお勧めします。opencvにリンクする方がさらに簡単ですが、リンクしたくない場合もあります。

于 2010-10-25T03:18:26.380 に答える