سؤال

لقد وجدت هذا الجزء من رمز C ++ في منتدى لا يمكنني فهمه تمامًا. نظرًا لأنني لا أملك مكتبتهم التي تؤدي الرياضيات المصفوفة/المتجهات ، فأنا بحاجة إلى اكتشاف الوظيفة وتكرارها يدويًا.

احسب زوايا دوران Euler بين 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;

هل تضيف جميع خصائص مصفوفة العين 3؟
هل تتضاعف مع جميع خصائص المصفوفة Axis_Skewed؟
وما هو ص؟ ناقل أو مصفوفة؟ أو الرقم؟

هذا بسيط.

    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);

هل تتكاثر المتجه مع المصفوفة للحصول على المتجه الناتج باستخدام المصفوفة القياسية المضاعفة؟
هل تضاعف المصفوفة ثم قم بتحويل النقطة باستخدام المصفوفة؟

هل كانت مفيدة؟

المحلول

أنا متأكد من أن هذا psuedocode. إنه بالتأكيد ليس C ++. جميع الوظائف هي توضيحية ذاتية جميلة.

ACOS () --- توضيحية الذات

$ v1 * $ v2 --- منتج DOT (ملاحظة:, ، عادةً ما يتم تفسير ذلك على أنه مضاعفة مصفوفة منتظمة ، ولكن في سياق "Float $ Angle = ACOS ($ v1*$ v2) ؛" ، لا معنى له مثل أي شيء آخر غير منتج DOT)

Cross () --- منتج متقاطع

NormalizeVector () --- التوضيح الذاتي

الخطيئة ($ angle)*$ AXIS_SKEWED --- هذا هو التعدد المضاعف

احصل عليه؟

تعديل

$ r = $ eare3 + sin ($ angle)*$ AXIS_SKEWED + (1-COS ($ angle))*$ AXIS_SKEWED*$ AXIS_SKEWED ؛

$ EY3 - مصفوفة 3 × 3

Sin ($ angle)*$ AXIS_SKEWED --- هذا هو التعدد المضاعف ، مما يؤدي إلى مصفوفة 3 × 3 أخرى

(1-COS ($ angle))*$ AXIS_SKEWED --- هذا هو التعدد الضاعف ، مما يؤدي إلى مصفوفة 3 × 3 أخرى

(سابق)*$ AXIS_SKEWED --- هذا مضاعفة مصفوفة منتظمة ، مما يؤدي إلى مصفوفة 3 × 3 أخرى

هذا يتركنا مع:

$ r = [3x3 Matrix] + [3x3 Matrix] + [3x3 Matrix

وهو مجرد إضافة مصفوفة دخول منتظمة.

نصائح أخرى

من ما يمكنني قول الجزء الأخير هو مضاعفة مصفوفة ستانادارد. A [3x3] مرات A [3x1] سوف تسفر عن [3x1]. لا أحب بناء الجملة ليس من السهل قراءته ...

تعديل:

$ r هي مصفوفة [3x3] كما أظهرت Pigpen ، r = [3x3]+sin (القياس)3x3]+(1-COS (القياس))3x3]*[3x3].

المصطلح الثاني هو [3x3] مع تحجيم كل عنصر بواسطة SIN (زاوية) ، المصطلح الثالث هو تكاثر المصفوفة لـ A [3x3]*[3x3] ، مما يؤدي إلى آخر [3x3].

يتم تحجيم هذا العنصر الثالث أيضًا بواسطة العامل (1-COS (الزاوية)).

يتم تنفيذ العنصر الناتج 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 - بناء الجملة الذي نشرته مربكًا ولا يمكن قراءته بسهولة.

في ملاحظة جانبية ، تتطلب Quaternions عمليات أقل لإجراء دوران ثلاثي الأبعاد من زوايا Euler (ولا تواجه مشكلات حول PI/2) ، لذلك إذا كان لديك بضعة أيام قضاء الوقت في القراءة عليها. لا يوجد الكثير وراء الرياضيات أيضًا ، لذا امنحها فرصة!

أنت تحاول القيام بالمصفوفة الأسية لـ $ AXIS_SKEWED [3] [3] ، والتي يكون رودريغز شكلًا مختصرة.

أقترح عليك فقط استخدام CV :: Rodrigues من OpenCV إذا كنت تضع هذا في C ++ ...


CV :: MAT AXIS_SKEWED ؛

..... // ضع القيم في AXIS_SKEWED

السيرة الذاتية :: حصيرة ص ؛ // سيكون 3x3 عند الانتهاء

السيرة الذاتية :: rodgrigues (AXIS_SKEWED ، R)


انتهى...

)

هذا مجرد اختصار لـ: r = proponential_of_matrix (AXIS_SKEWED)

على سبيل المثال في MATLAB ، كنت تستخدم EXPM (AXIS_SKEWED). هناك مجرد صيغة تحليلية لكتابة الإجابة ؛ بدلاً من ذلك ، يمكنك القيام بـ r = i + axis_skewed + axis_skewed / 2 + ... + axis_skewed ^ n / (n factorial) للحصول على مجموعة من المصطلحات والحصول على نفس الإجابة.

ثم بالطبع تتوسع ويكيبيديا على الرياضيات أكثر قليلاً من: 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];

أقترح عليك svn checkout opencv ، قم بإنشائها ، ثم قم بإجراء اختبار لنفسك للتحقق من السيرة الذاتية :: Rodrigues يمنحك نفس الإجابة مثل الرمز الآخر ، ثم قم بتنفيذ الوظيفة إلى مشروع C ++ الخاص بك. سيكون من الأسهل فقط الارتباط بـ OpenCV ، ولكن ربما لا تريد القيام بذلك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top