zoukankan      html  css  js  c++  java
  • CV学习日志:CV开发之位姿变换器

    1.本文要点说明

             介绍视觉定位导航中位姿变换的基础知识,包括:

                      (1)位姿变换模型

                      (2)左乘右乘法则

                      (3)模型几何解释

                      (4)基本运算公式

                      (5)旋转转换公式

    2.实验测试代码

             依赖于OpenCV、Ceres和Spdlog,封装在类ModelRotation:

                  (1)RVec2Quat、Quat2RMat、RVec2RMat、Euler2RMat

                  (2)Quat2RVec、RMat2Quat、RMat2RVec、RMat2Euler

                  (3)SolidPose:setPos、setRot、inv、mul、print

      1 #include <ceres/ceres.h>
      2 #include <ceres/rotation.h>
      3 #include <spdlog/spdlog.h>
      4 #include <opencv2/opencv.hpp>
      5 using namespace std;
      6 using namespace cv;
      7 
      8 class ModelRotation
      9 {
     10 public:
     11     static inline double L1EPS() { return 1E-12; }
     12     static inline double L2EPS() { return 1E-18; }
     13 
     14 public://RVec2Quat
     15     struct RVec2Quat
     16     {
     17         bool useCeres;
     18         RVec2Quat(bool useCeres0) : useCeres(useCeres0) {}
     19         template <typename tp> bool operator()(const tp* const src, tp* dst) const
     20         {
     21             if (useCeres) { ceres::AngleAxisToQuaternion(src, dst); return true; }
     22             tp theta2 = src[0] * src[0] + src[1] * src[1] + src[2] * src[2];
     23             if (theta2 > ModelRotation::L2EPS())
     24             {
     25                 tp theta = sqrt(theta2);
     26                 tp thetaa = theta * 0.5;
     27                 tp coeff = sin(thetaa) / theta;
     28                 dst[0] = cos(thetaa);
     29                 dst[1] = src[0] * coeff;
     30                 dst[2] = src[1] * coeff;
     31                 dst[3] = src[2] * coeff;
     32             }
     33             else //first order taylor
     34             {
     35                 dst[0] = tp(1.);
     36                 dst[1] = src[0] * 0.5;
     37                 dst[2] = src[1] * 0.5;
     38                 dst[3] = src[2] * 0.5;
     39             }
     40             return true;
     41         }
     42         static void TestMe(int argc = 0, char** argv = 0)
     43         {
     44             for (int k = 0; k < 999; ++k)
     45             {
     46                 //0.GenerateData
     47                 Matx31d r = r.randu(-999, 999);
     48 
     49                 //1.CalcByCeres
     50                 Vec4d q1;
     51                 Mat_<double> dqdr1(4, 3);
     52                 ceres::CostFunction* costFun1 = new ceres::AutoDiffCostFunction<RVec2Quat, 4, 3>(new RVec2Quat(true));
     53                 costFun1->Evaluate(vector<double*>{r.val}.data(), q1.val, vector<double*>{dqdr1.ptr<double>()}.data());
     54 
     55                 //2.CalcByManu
     56                 Vec4d q2;
     57                 Mat_<double> dqdr2(4, 3);
     58                 ceres::CostFunction* costFun2 = new ceres::AutoDiffCostFunction<RVec2Quat, 4, 3>(new RVec2Quat(false));
     59                 costFun2->Evaluate(vector<double*>{r.val}.data(), q2.val, vector<double*>{dqdr2.ptr<double>()}.data());
     60 
     61                 //3.AnalyzeError
     62                 double infq1q2 = cv::norm(q1, q2, NORM_INF);
     63                 double infdqdr1dqdr2 = cv::norm(dqdr1, dqdr2, NORM_INF);
     64 
     65                 //4.PrintError
     66                 cout << endl << "LoopCount: " << k << endl;
     67                 if (infq1q2 > 1E-12 || infdqdr1dqdr2 > 1E-12)
     68                 {
     69                     cout << endl << "infq1q2: " << infq1q2 << endl;
     70                     cout << endl << "infdqdr1dqdr2: " << infdqdr1dqdr2 << endl;
     71                     if (0)
     72                     {
     73                         cout << endl << "q1: " << q1 << endl;
     74                         cout << endl << "q2: " << q2 << endl;
     75                         cout << endl << "dqdr1: " << dqdr1 << endl;
     76                         cout << endl << "dqdr2: " << dqdr2 << endl;
     77                     }
     78                     cout << endl << "Press any key to continue" << endl; getchar();
     79                 }
     80             }
     81         }
     82     };
     83     struct Quat2RVec
     84     {
     85         bool useCeres;
     86         Quat2RVec(bool useCeres0) : useCeres(useCeres0) {}
     87         template <typename tp> bool operator()(const tp* const src, tp* dst) const
     88         {
     89             if (useCeres) { ceres::QuaternionToAngleAxis(src, dst); return true; }
     90             tp thetaa2 = src[1] * src[1] + src[2] * src[2] + src[3] * src[3];
     91             if (thetaa2 > ModelRotation::L2EPS())
     92             {
     93                 tp cs = src[0];
     94                 tp sn = sqrt(thetaa2);
     95                 tp theta = 2.0 * (cs < 0.0 ? atan2(-sn, -cs) : atan2(sn, cs));//refer to ceres comments
     96                 tp coeff = theta / sn;
     97                 dst[0] = src[1] * coeff;
     98                 dst[1] = src[2] * coeff;
     99                 dst[2] = src[3] * coeff;
    100             }
    101             else //first order taylor
    102             {
    103                 dst[0] = 2.0 * src[1];
    104                 dst[1] = 2.0 * src[2];
    105                 dst[2] = 2.0 * src[3];
    106             }
    107             return true;
    108         }
    109         static void TestMe(int argc = 0, char** argv = 0)
    110         {
    111             for (int k = 0; k < 999; ++k)
    112             {
    113                 //0.GenerateData
    114                 Matx41d q = q.randu(-999, 999);
    115 
    116                 //1.CalcByCeres
    117                 Matx33d r1;
    118                 Mat_<double> drdq1(3, 4);
    119                 ceres::CostFunction* costFun1 = new ceres::AutoDiffCostFunction<Quat2RVec, 3, 4>(new Quat2RVec(true));
    120                 costFun1->Evaluate(vector<double*>{q.val}.data(), r1.val, vector<double*>{drdq1.ptr<double>()}.data());
    121 
    122                 //2.CalcByManu
    123                 Matx33d r2;
    124                 Mat_<double> drdq2(3, 4);
    125                 ceres::CostFunction* costFun2 = new ceres::AutoDiffCostFunction<Quat2RVec, 3, 4>(new Quat2RVec(false));
    126                 costFun2->Evaluate(vector<double*>{q.val}.data(), r2.val, vector<double*>{drdq2.ptr<double>()}.data());
    127 
    128                 //3.AnalyzeError
    129                 double infr1r2 = cv::norm(r1, r2, NORM_INF);
    130                 double infdrdq1drdq2 = cv::norm(drdq1, drdq2, NORM_INF);
    131 
    132                 //4.PrintError
    133                 cout << endl << "LoopCount: " << k << endl;
    134                 if (infr1r2 > 1E-12 || infdrdq1drdq2 > 1E-12)
    135                 {
    136                     cout << endl << "infr1r2: " << infr1r2 << endl;
    137                     cout << endl << "infdrdq1drdq2: " << infdrdq1drdq2 << endl;
    138                     if (0)
    139                     {
    140                         cout << endl << "r1: " << r1 << endl;
    141                         cout << endl << "r2: " << r2 << endl;
    142                         cout << endl << "drdq1: " << drdq1 << endl;
    143                         cout << endl << "drdq2: " << drdq2 << endl;
    144                     }
    145                     cout << endl << "Press any key to continue" << endl; getchar();
    146                 }
    147             }
    148         }
    149     };
    150 
    151 public://Quat2RMat
    152     struct Quat2RMat
    153     {
    154         bool useCeres;
    155         Quat2RMat(bool useCeres0) : useCeres(useCeres0) {}
    156         template <typename tp> bool operator()(const tp* const src, tp* dst) const
    157         {
    158             if (useCeres) { ceres::QuaternionToRotation(src, dst); return true; }
    159             tp ww = src[0] * src[0];
    160             tp wx = src[0] * src[1];
    161             tp wy = src[0] * src[2];
    162             tp wz = src[0] * src[3];
    163 
    164             tp xx = src[1] * src[1];
    165             tp xy = src[1] * src[2];
    166             tp xz = src[1] * src[3];
    167 
    168             tp yy = src[2] * src[2];
    169             tp yz = src[2] * src[3];
    170 
    171             tp zz = src[3] * src[3];
    172             tp L2 = ww + xx + yy + zz;
    173             if (L2 < ModelRotation::L2EPS()) { dst[0] = dst[4] = dst[8] = tp(1.); dst[1] = dst[2] = dst[3] = dst[5] = dst[6] = dst[7] = tp(0.); return true; }
    174             tp iL2 = 1. / L2;
    175 
    176             dst[0] = ww + xx - yy - zz; dst[1] = 2.0 * (xy - wz); dst[2] = 2.0 * (wy + xz);
    177             dst[3] = 2.0 * (wz + xy); dst[4] = ww - xx + yy - zz; dst[5] = 2.0 * (yz - wx);
    178             dst[6] = 2.0 * (xz - wy); dst[7] = 2.0 * (wx + yz); dst[8] = ww - xx - yy + zz;
    179             for (int k = 0; k < 9; ++k) dst[k] = dst[k] * iL2;//for not unit quaternion
    180 
    181             return true;
    182         }
    183         static void TestMe(int argc = 0, char** argv = 0)
    184         {
    185             for (int k = 0; k < 999; ++k)
    186             {
    187                 //0.GenerateData
    188                 Matx41d q = q.randu(-999, 999);
    189 
    190                 //1.CalcByCeres
    191                 Matx33d R1;
    192                 Mat_<double> dRdq1(9, 4);
    193                 ceres::CostFunction* costFun1 = new ceres::AutoDiffCostFunction<Quat2RMat, 9, 4>(new Quat2RMat(true));
    194                 costFun1->Evaluate(vector<double*>{q.val}.data(), R1.val, vector<double*>{dRdq1.ptr<double>()}.data());
    195 
    196                 //2.CalcByManu
    197                 Matx33d R2;
    198                 Mat_<double> dRdq2(9, 4);
    199                 ceres::CostFunction* costFun2 = new ceres::AutoDiffCostFunction<Quat2RMat, 9, 4>(new Quat2RMat(false));
    200                 costFun2->Evaluate(vector<double*>{q.val}.data(), R2.val, vector<double*>{dRdq2.ptr<double>()}.data());
    201 
    202                 //3.AnalyzeError
    203                 double infR1R2 = cv::norm(R1, R2, NORM_INF);
    204                 double infdRdq1dRdq2 = cv::norm(dRdq1, dRdq2, NORM_INF);
    205 
    206                 //4.PrintError
    207                 cout << endl << "LoopCount: " << k << endl;
    208                 if (infR1R2 > 1E-12 || infdRdq1dRdq2 > 1E-12)
    209                 {
    210                     cout << endl << "infR1R2: " << infR1R2 << endl;
    211                     cout << endl << "infdRdq1dRdq2: " << infdRdq1dRdq2 << endl;
    212                     if (0)
    213                     {
    214                         cout << endl << "R1: " << R1 << endl;
    215                         cout << endl << "R2: " << R2 << endl;
    216                         cout << endl << "dRdq1: " << dRdq1 << endl;
    217                         cout << endl << "dRdq2: " << dRdq2 << endl;
    218                     }
    219                     cout << endl << "Press any key to continue" << endl; getchar();
    220                 }
    221             }
    222         }
    223     };
    224     struct RMat2Quat
    225     {
    226         bool useCeres;
    227         RMat2Quat(bool useCeres0) : useCeres(useCeres0) {}
    228         template <typename tp> bool operator()(const tp* const src, tp* dst) const
    229         {
    230             if (useCeres) { ceres::RotationMatrixToQuaternion(ceres::RowMajorAdapter3x3(src), dst); return true; }
    231             tp trace = src[0] + src[4] + src[8];//Strictly 1+trace>0 for rotation matrix. In ceres, This leads to different jacobians between ceres' rmat2rvec and cv::Rodrigues(rmat, rvec)
    232             if (trace >= 0.0)
    233             {
    234                 tp trace1 = sqrt(1. + trace);
    235                 dst[0] = 0.5 * trace1;
    236                 tp itrace1 = 0.5 / trace1;
    237                 dst[1] = (src[7] - src[5]) * itrace1;
    238                 dst[2] = (src[2] - src[6]) * itrace1;
    239                 dst[3] = (src[3] - src[1]) * itrace1;
    240             }
    241             else
    242             {
    243                 int a = 0;
    244                 if (src[4] > src[0]) a = 1;
    245                 if (src[8] > src[a * 3 + a]) a = 2;
    246                 int b = (a + 1) % 3;
    247                 int c = (b + 1) % 3;
    248 
    249                 tp trace1 = sqrt(1.0 + src[a * 3 + a] - src[b * 3 + b] - src[c * 3 + c]);
    250                 dst[a + 1] = 0.5 * trace1;
    251                 tp itrace1 = 0.5 / trace1;
    252                 dst[0] = (src[c * 3 + b] - src[b * 3 + c]) * itrace1;
    253                 dst[b + 1] = (src[b * 3 + a] + src[a * 3 + b]) * itrace1;
    254                 dst[c + 1] = (src[c * 3 + a] + src[a * 3 + c]) * itrace1;
    255             }
    256             return true;
    257         }
    258         static void TestMe(int argc, char** argv)
    259         {
    260             for (int k = 0; k < 999; ++k)
    261             {
    262                 //0.GenerateData
    263                 Matx33d R; ceres::EulerAnglesToRotationMatrix(Matx31d::randu(-180, 180).val, 0, R.val);
    264 
    265                 //1.CalcByCeres
    266                 Vec4d q1;
    267                 Mat_<double> dqdR1(4, 9);
    268                 ceres::CostFunction* costFun1 = new ceres::AutoDiffCostFunction<RMat2Quat, 4, 9>(new RMat2Quat(true));
    269                 costFun1->Evaluate(vector<double*>{R.val}.data(), q1.val, vector<double*>{dqdR1.ptr<double>()}.data());
    270 
    271                 //2.CalcByManu
    272                 Vec4d q2;
    273                 Mat_<double> dqdR2(4, 9);
    274                 ceres::CostFunction* costFun2 = new ceres::AutoDiffCostFunction<RMat2Quat, 4, 9>(new RMat2Quat(false));
    275                 costFun2->Evaluate(vector<double*>{R.val}.data(), q2.val, vector<double*>{dqdR2.ptr<double>()}.data());
    276 
    277                 //4.AnalyzeError
    278                 double infq1q2 = cv::norm(q1, q2, NORM_INF);
    279                 double infdqdR1dqdR2 = cv::norm(dqdR1, dqdR2, NORM_INF);
    280 
    281                 //5.PrintError
    282                 cout << endl << "LoopCount: " << k << endl;
    283                 if (infq1q2 > 1E-9 || infdqdR1dqdR2 > 1E-9)
    284                 {
    285                     cout << endl << "infq1q2: " << infq1q2 << endl;
    286                     cout << endl << "infdqdR1dqdR2: " << infq1q2 << endl;
    287                     if (0)
    288                     {
    289                         cout << endl << "q1:" << q1 << endl;
    290                         cout << endl << "q2:" << q2 << endl;
    291                         cout << endl << "dqdR1:" << dqdR1 << endl;
    292                         cout << endl << "dqdR2:" << dqdR2 << endl;
    293                     }
    294                     cout << endl << "Press any key to continue" << endl; getchar();
    295                 }
    296             }
    297         }
    298     };
    299 
    300 public://RVec2RMat
    301     struct RVec2RMat
    302     {
    303         bool useCeres;
    304         RVec2RMat(bool useCeres0) : useCeres(useCeres0) {}
    305         template <typename tp> bool operator()(const tp* const src, tp* dst) const
    306         {
    307             if (useCeres) { ceres::AngleAxisToRotationMatrix(src, ceres::RowMajorAdapter3x3(dst)); return true; }
    308             tp theta2 = src[0] * src[0] + src[1] * src[1] + src[2] * src[2];
    309             if (theta2 > ModelRotation::L2EPS())
    310             {
    311                 tp theta = sqrt(theta2);
    312                 tp itheta = 1. / theta;
    313                 tp cs = cos(theta);
    314                 tp sn = sin(theta);
    315                 tp nx = src[0] * itheta;
    316                 tp ny = src[1] * itheta;
    317                 tp nz = src[2] * itheta;
    318 
    319                 dst[0] = nx * nx * (1. - cs) + cs;
    320                 dst[3] = nx * ny * (1. - cs) + nz * sn;
    321                 dst[6] = nx * nz * (1. - cs) - ny * sn;
    322 
    323                 dst[1] = nx * ny * (1. - cs) - nz * sn;
    324                 dst[4] = ny * ny * (1. - cs) + cs;
    325                 dst[7] = ny * nz * (1. - cs) + nx * sn;
    326 
    327                 dst[2] = nx * nz * (1. - cs) + ny * sn;
    328                 dst[5] = ny * nz * (1. - cs) - nx * sn;
    329                 dst[8] = nz * nz * (1. - cs) + cs;
    330             }
    331             else //first order taylor
    332             {
    333                 dst[0] = tp(1.);
    334                 dst[3] = src[2];
    335                 dst[6] = -src[1];
    336 
    337                 dst[1] = -src[2];
    338                 dst[4] = tp(1.);
    339                 dst[7] = src[0];
    340 
    341                 dst[2] = src[1];
    342                 dst[5] = -src[0];
    343                 dst[8] = tp(1.);
    344             }
    345             return true;
    346         }
    347         static void TestMe(int argc = 0, char** argv = 0)
    348         {
    349             for (int k = 0; k < 999; ++k)
    350             {
    351                 //0.GenerateData
    352                 Matx31d r = r.randu(-999, 999);
    353 
    354                 //1.CalcByCeres
    355                 Matx33d R1;
    356                 Mat_<double> dRdr1(9, 3);
    357                 ceres::CostFunction* costFun1 = new ceres::AutoDiffCostFunction<RVec2RMat, 9, 3>(new RVec2RMat(true));
    358                 costFun1->Evaluate(vector<double*>{r.val}.data(), R1.val, vector<double*>{dRdr1.ptr<double>()}.data());
    359 
    360                 //2.CalcByManu
    361                 Matx33d R2;
    362                 Mat_<double> dRdr2(9, 3);
    363                 ceres::CostFunction* costFun2 = new ceres::AutoDiffCostFunction<RVec2RMat, 9, 3>(new RVec2RMat(false));
    364                 costFun2->Evaluate(vector<double*>{r.val}.data(), R2.val, vector<double*>{dRdr2.ptr<double>()}.data());
    365 
    366                 //3.CalcByOpenCV
    367                 Matx33d R3;
    368                 Mat_<double> dRdr3;
    369                 cv::Rodrigues(r, R3, dRdr3); dRdr3 = dRdr3.t();
    370 
    371                 //4.AnalyzeError
    372                 double infR1R2 = cv::norm(R1, R2, NORM_INF);
    373                 double infR1R3 = cv::norm(R1, R3, NORM_INF);
    374                 double infdRdr1dRdr2 = cv::norm(dRdr1, dRdr2, NORM_INF);
    375                 double infdRdr1dRdr3 = cv::norm(dRdr1, dRdr3, NORM_INF);
    376 
    377                 //5.PrintError
    378                 cout << endl << "LoopCount: " << k << endl;
    379                 if (infR1R2 > 1E-12 || infR1R3 > 1E-12 || infdRdr1dRdr2 > 1E-12 || infdRdr1dRdr3 > 1E-12)
    380                 {
    381                     cout << endl << "infR1R2: " << infR1R2 << endl;
    382                     cout << endl << "infR1R3: " << infR1R3 << endl;
    383                     cout << endl << "infdRdr3dRdr1: " << infdRdr1dRdr2 << endl;
    384                     cout << endl << "infdRdr3dRdr2: " << infdRdr1dRdr3 << endl;
    385                     if (0)
    386                     {
    387                         cout << endl << "R1: " << R1 << endl;
    388                         cout << endl << "R2: " << R2 << endl;
    389                         cout << endl << "R3: " << R3 << endl;
    390                         cout << endl << "dRdr1: " << dRdr1 << endl;
    391                         cout << endl << "dRdr2: " << dRdr2 << endl;
    392                         cout << endl << "dRdr3: " << dRdr3 << endl;
    393                     }
    394                     cout << endl << "Press any key to continue" << endl; getchar();
    395                 }
    396             }
    397         }
    398     };
    399     struct RMat2RVec
    400     {
    401         bool useCeres;
    402         RMat2RVec(bool useCeres0) : useCeres(useCeres0) {}
    403         template <typename tp> bool operator()(const tp* const src, tp* dst) const
    404         {
    405             if (useCeres) { ceres::RotationMatrixToAngleAxis(ceres::RowMajorAdapter3x3(src), dst); return true; }
    406             tp quat[4];
    407             RMat2Quat(false)(src, quat);
    408             Quat2RVec(false)(quat, dst);
    409             return true;
    410         }
    411         static void TestMe(int argc, char** argv)
    412         {
    413             for (int k = 0; k < 999; ++k)
    414             {
    415                 //0.GenerateData
    416                 Matx33d R; ceres::EulerAnglesToRotationMatrix(Matx31d::randu(-180, 180).val, 0, R.val);
    417 
    418                 //1.CalcByCeres
    419                 Vec3d r1;
    420                 Mat_<double> drdR1(3, 9);
    421                 ceres::CostFunction* costFun1 = new ceres::AutoDiffCostFunction<RMat2RVec, 3, 9>(new RMat2RVec(true));
    422                 costFun1->Evaluate(vector<double*>{R.val}.data(), r1.val, vector<double*>{drdR1.ptr<double>()}.data());
    423 
    424                 //2.CalcByManu
    425                 Vec3d r2;
    426                 Mat_<double> drdR2(3, 9);
    427                 ceres::CostFunction* costFun2 = new ceres::AutoDiffCostFunction<RMat2RVec, 3, 9>(new RMat2RVec(false));
    428                 costFun2->Evaluate(vector<double*>{R.val}.data(), r2.val, vector<double*>{drdR2.ptr<double>()}.data());
    429 
    430                 //3.AnalyzeError
    431                 double infr1r2 = cv::norm(r1, r2, NORM_INF);
    432                 double infdrdR1drdR2 = cv::norm(drdR1, drdR2, NORM_INF);
    433 
    434                 //5.PrintError
    435                 cout << endl << "LoopCount: " << k << endl;
    436                 if (infr1r2 > 1E-9 || infdrdR1drdR2 > 1E-9)
    437                 {
    438                     cout << endl << "infr1r2: " << infr1r2 << endl;
    439                     cout << endl << "infdrdR1drdR2: " << infdrdR1drdR2 << endl;
    440                     if (0)
    441                     {
    442                         cout << endl << "r1:" << r1 << endl;
    443                         cout << endl << "r2:" << r2 << endl;
    444                         cout << endl << "drdR1:" << drdR1 << endl;
    445                         cout << endl << "drdR2:" << drdR2 << endl;
    446                     }
    447                     cout << endl << "Press any key to continue" << endl; getchar();
    448                 }
    449             }
    450         }
    451     };
    452 
    453 public://Euler2RMat
    454     struct Euler2RMat
    455     {
    456         bool useCeres;
    457         Euler2RMat(bool useCeres0) : useCeres(useCeres0) {}
    458         template <typename tp> bool operator()(const tp* const src, tp* dst) const
    459         {
    460             //RPY indicates: first Yaw aroundZ, second Pitch aroundY, third Roll aroundX
    461             if (useCeres) { ceres::EulerAnglesToRotationMatrix(src, 0, dst); return true; }
    462             const double deg2rad = 3.14159265358979323846 * 0.0055555555555555556;
    463             tp sinR = sin(src[0] * deg2rad);
    464             tp sinP = sin(src[1] * deg2rad);
    465             tp sinY = sin(src[2] * deg2rad);
    466             tp cosR = cos(src[0] * deg2rad);
    467             tp cosP = cos(src[1] * deg2rad);
    468             tp cosY = cos(src[2] * deg2rad);
    469 
    470             dst[0] = cosY * cosP; dst[1] = cosY * sinP * sinR - sinY * cosR; dst[2] = cosY * sinP * cosR + sinY * sinR;
    471             dst[3] = sinY * cosP; dst[4] = sinY * sinP * sinR + cosY * cosR; dst[5] = sinY * sinP * cosR - cosY * sinR;
    472             dst[6] = -sinP;       dst[7] = cosP * sinR;                      dst[8] = cosP * cosR;
    473             return true;
    474         }
    475         static void TestMe(int argc = 0, char** argv = 0)
    476         {
    477             for (int k = 0; k < 999; ++k)
    478             {
    479                 //0.GenerateData
    480                 Matx31d e = e.randu(-999, 999);
    481 
    482                 //1.CalcByCeres
    483                 Matx33d R1;
    484                 Mat_<double> dRde1(9, 3);
    485                 ceres::CostFunction* costFun1 = new ceres::AutoDiffCostFunction<Euler2RMat, 9, 3>(new Euler2RMat(true));
    486                 costFun1->Evaluate(vector<double*>{e.val}.data(), R1.val, vector<double*>{dRde1.ptr<double>()}.data());
    487 
    488                 //2.CalcByManu
    489                 Matx33d R2;
    490                 Mat_<double> dRde2(9, 3);
    491                 ceres::CostFunction* costFun2 = new ceres::AutoDiffCostFunction<Euler2RMat, 9, 3>(new Euler2RMat(false));
    492                 costFun2->Evaluate(vector<double*>{e.val}.data(), R2.val, vector<double*>{dRde2.ptr<double>()}.data());
    493 
    494                 //3.AnalyzeError
    495                 double infR1R2 = cv::norm(R1, R2, NORM_INF);
    496                 double infdRde1dRde2 = cv::norm(dRde1, dRde2, NORM_INF);
    497 
    498                 //4.PrintError
    499                 cout << endl << "LoopCount: " << k << endl;
    500                 if (infR1R2 > 1E-12 || infdRde1dRde2 > 1E-12)
    501                 {
    502                     cout << endl << "infR1R2: " << infR1R2 << endl;
    503                     cout << endl << "infdRde2dRde1: " << infdRde1dRde2 << endl;
    504                     if (0)
    505                     {
    506                         cout << endl << "R1: " << R1 << endl;
    507                         cout << endl << "R2: " << R2 << endl;
    508                         cout << endl << "dRde1: " << dRde1 << endl;
    509                         cout << endl << "dRde2: " << dRde2 << endl;
    510                     }
    511                     cout << endl << "Press any key to continue" << endl; getchar();
    512                 }
    513             }
    514         }
    515     };
    516     struct RMat2Euler
    517     {
    518         bool useCeres;
    519         RMat2Euler(bool useCeres0) : useCeres(useCeres0) {}
    520         template <typename tp> bool operator()(const tp* const src, tp* dst) const
    521         {
    522             //RPY indicates: first Yaw aroundZ, second Pitch aroundY, third Roll aroundX
    523             if (useCeres) { ceres::RotationMatrixToEulerAngles(src, dst); return true; }
    524             const double rad2deg = 180 * 0.3183098861837906715;
    525             tp bound1 = abs(src[6] - 1.);
    526             tp bound2 = abs(src[6] + 1.);
    527             if (bound1 > ModelRotation::L1EPS() && bound2 > ModelRotation::L1EPS())
    528             {
    529                 dst[2] = atan2(src[3], src[0]); //Yaw aroundZ
    530                 dst[1] = asin(-src[6]);//Pitch aroundY
    531                 dst[0] = atan2(src[7], src[8]); //Roll aroundX
    532             }
    533             else if (bound2 <= ModelRotation::L1EPS())
    534             {
    535                 dst[2] = tp(0.); //Yaw aroundZ
    536                 dst[1] = tp(3.14159265358979323846 * 0.5);//Pitch aroundY
    537                 dst[0] = dst[2] + atan2(src[1], src[2]); //Roll aroundX
    538             }
    539             else
    540             {
    541                 dst[2] = tp(0.); //Yaw aroundZ
    542                 dst[1] = tp(-3.14159265358979323846 * 0.5);//Pitch aroundY
    543                 dst[0] = -dst[2] + atan2(-src[1], -src[2]); //Roll aroundX
    544             }
    545             dst[0] *= rad2deg; dst[1] *= rad2deg; dst[2] *= rad2deg;
    546             return true;
    547         }
    548         static void TestMe(int argc, char** argv)
    549         {
    550             for (int k = 0; k < 999; ++k)
    551             {
    552                 //0.GenerateData
    553                 Vec3d e0(Matx31d::randu(-180, 180).val);
    554                 Matx33d R; ceres::EulerAnglesToRotationMatrix(e0.val, 0, R.val);
    555 
    556                 //1.CalcByCeres
    557                 Vec3d e1;
    558                 Mat_<double> dedR1(3, 9);
    559                 ceres::CostFunction* costFun1 = new ceres::AutoDiffCostFunction<RMat2Euler, 3, 9>(new RMat2Euler(true));
    560                 costFun1->Evaluate(vector<double*>{R.val}.data(), e1.val, vector<double*>{dedR1.ptr<double>()}.data());
    561 
    562                 //2.CalcByManu
    563                 Vec3d e2;
    564                 Mat_<double> dedR2(3, 9);
    565                 ceres::CostFunction* costFun2 = new ceres::AutoDiffCostFunction<RMat2Euler, 3, 9>(new RMat2Euler(false));
    566                 costFun2->Evaluate(vector<double*>{R.val}.data(), e2.val, vector<double*>{dedR2.ptr<double>()}.data());
    567 
    568                 //3.CalcByOpenCV
    569                 Vec3d e3;
    570                 Mat_<double> dedR3(3, 9);
    571                 e3 = cv::RQDecomp3x3(R, Matx33d(), Matx33d());
    572 
    573                 //4.AnalyzeError
    574                 double infe0e1 = min(cv::norm(e0, e1, NORM_INF), cv::norm(cv::abs(Mat_<double>(3, 1, e0.val)) + cv::abs(Mat_<double>(3, 1, e1.val)), Vec3d(180, 180, 180), NORM_INF));
    575                 double infe0e2 = min(cv::norm(e0, e2, NORM_INF), cv::norm(cv::abs(Mat_<double>(3, 1, e0.val)) + cv::abs(Mat_<double>(3, 1, e2.val)), Vec3d(180, 180, 180), NORM_INF));
    576                 double infe0e3 = min(cv::norm(e0, e3, NORM_INF), cv::norm(cv::abs(Mat_<double>(3, 1, e0.val)) + cv::abs(Mat_<double>(3, 1, e3.val)), Vec3d(180, 180, 180), NORM_INF));
    577 
    578                 //5.PrintError
    579                 cout << endl << "LoopCount: " << k << endl;
    580                 if (infe0e1 > 1E-9 || infe0e2 > 1E-9 || infe0e3 > 1E-9)
    581                 {
    582                     cout << endl << "infe0e1: " << infe0e1 << endl;
    583                     cout << endl << "infe0e2: " << infe0e2 << endl;
    584                     cout << endl << "infe0e3: " << infe0e3 << endl;
    585                     if (0)
    586                     {
    587                         cout << endl << "e0: " << e0 << endl;
    588                         cout << endl << "e1: " << e1 << endl;
    589                         cout << endl << "e2: " << e2 << endl;
    590                         cout << endl << "e3: " << e3 << endl;
    591                     }
    592                     cout << endl << "Press any key to continue" << endl; getchar();
    593                 }
    594             }
    595         }
    596     };
    597 
    598 public:
    599     struct SolidPose
    600     {
    601         double data[22] = { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 };
    602         double* vdata = data; //Mat_<double> rvec = Mat_<double>(3, 1, vdata);
    603         double* tdata = vdata + 3; //Mat_<double> tvec = Mat_<double>(3, 1, tdata);
    604         double* qdata = tdata + 3; //Mat_<double> quat = Mat_<double>(4, 1, qdata);
    605         double* mdata = qdata + 4; //Mat_<double> rmat = Mat_<double>(3, 3, mdata);
    606         double* edata = mdata + 9; //Mat_<double> euler = Mat_<double>(3, 1, edata);
    607         SolidPose() {}
    608         SolidPose(const SolidPose& other) { memcpy(data, other.data, sizeof(data)); }
    609         void setPos(double* xyz) { memcpy(tdata, xyz, 3 * sizeof(double)); }
    610         void setRot(double* rot, int n = 0/*0 3 4 9 for euler rvec quat rmat*/)
    611         {
    612             if (n == 0)
    613             {
    614                 memcpy(edata, rot, 3 * sizeof(double));
    615                 ceres::EulerAnglesToRotationMatrix(rot, 0, mdata);
    616                 ceres::RotationMatrixToQuaternion(ceres::RowMajorAdapter3x3((const double*)(mdata)), qdata);
    617                 ceres::QuaternionToAngleAxis(qdata, vdata);//rmat->quat->rvec in ceres
    618             }
    619             else if (n == 3)
    620             {
    621                 memcpy(vdata, rot, 3 * sizeof(double));
    622                 ceres::AngleAxisToQuaternion(vdata, qdata);
    623                 ceres::AngleAxisToRotationMatrix(vdata, ceres::RowMajorAdapter3x3(mdata));
    624                 ceres::RotationMatrixToEulerAngles(mdata, edata);
    625             }
    626             else if (n == 4)
    627             {
    628                 memcpy(qdata, rot, 4 * sizeof(double));
    629                 ceres::QuaternionToAngleAxis(qdata, vdata);
    630                 ceres::QuaternionToRotation(qdata, mdata);
    631                 ceres::RotationMatrixToEulerAngles(mdata, edata);
    632             }
    633             else if (n == 9)
    634             {
    635                 memcpy(mdata, rot, 9 * sizeof(double));
    636                 ceres::RotationMatrixToQuaternion(ceres::RowMajorAdapter3x3((const double*)(mdata)), qdata);
    637                 ceres::QuaternionToAngleAxis(qdata, vdata);//rmat->quat->rvec in ceres
    638                 ceres::RotationMatrixToEulerAngles(mdata, edata);
    639             }
    640         }
    641         SolidPose inv()
    642         {
    643             SolidPose dst;
    644             dst.vdata[0] = -vdata[0]; dst.vdata[1] = -vdata[1]; dst.vdata[2] = -vdata[2];
    645             dst.qdata[0] = qdata[0]; dst.qdata[1] = -qdata[1]; dst.qdata[2] = -qdata[2]; dst.qdata[3] = -qdata[3];
    646             dst.mdata[0] = mdata[0]; dst.mdata[1] = mdata[3]; dst.mdata[2] = mdata[6];
    647             dst.mdata[3] = mdata[1]; dst.mdata[4] = mdata[4]; dst.mdata[5] = mdata[7];
    648             dst.mdata[6] = mdata[2]; dst.mdata[7] = mdata[5]; dst.mdata[8] = mdata[8];
    649             ceres::RotationMatrixToEulerAngles(dst.mdata, dst.edata);//no euler inversion operation
    650             dst.tdata[0] = -(dst.mdata[0] * tdata[0] + dst.mdata[1] * tdata[1] + dst.mdata[2] * tdata[2]);
    651             dst.tdata[1] = -(dst.mdata[3] * tdata[0] + dst.mdata[4] * tdata[1] + dst.mdata[5] * tdata[2]);
    652             dst.tdata[2] = -(dst.mdata[6] * tdata[0] + dst.mdata[7] * tdata[1] + dst.mdata[8] * tdata[2]);
    653             return dst;
    654         }
    655         SolidPose mul(SolidPose& other)
    656         {
    657             SolidPose dst;
    658             ceres::QuaternionProduct(qdata, other.qdata, dst.qdata);
    659             memcpy(dst.mdata, (Matx33d(mdata) * Matx33d(other.mdata)).val, 9 * sizeof(double));
    660             ceres::QuaternionToAngleAxis(dst.qdata, dst.vdata);//no rvec multiplication operation
    661             ceres::RotationMatrixToEulerAngles(dst.mdata, dst.edata);//no euler multiplication operation
    662             memcpy(dst.tdata, (Matx33d(mdata) * Matx31d(other.tdata) + Matx31d(tdata)).val, 3 * sizeof(double));
    663             return dst;
    664         }
    665         string print()
    666         {
    667             string str;
    668             str += fmt::format("rvec: [ {}, {}, {} ]
    ", vdata[0], vdata[1], vdata[2]);
    669             str += fmt::format("tvec: [ {}, {}, {} ]
    ", tdata[0], tdata[1], tdata[2]);
    670             str += fmt::format("quat: [ {}, {}, {}, {} ]
    ", qdata[0], qdata[1], qdata[2], qdata[3]);
    671             str += fmt::format("rmat: [ {}, {}, {}, {}, {}, {}, {}, {}, {} ]
    ", mdata[0], mdata[1], mdata[2], mdata[3], mdata[4], mdata[5], mdata[6], mdata[7], mdata[8]);
    672             str += fmt::format("euler: [ {}, {}, {} ]
    ", edata[0], edata[1], edata[2]);
    673             return str;
    674         }
    675     };
    676 };
    677 
    678 #if 0
    679 int main(int argc, char** argv)
    680 {
    681     ModelRotation::RVec2Quat::TestMe(argc, argv);
    682     ModelRotation::Quat2RVec::TestMe(argc, argv);
    683 
    684     ModelRotation::Quat2RMat::TestMe(argc, argv);
    685     ModelRotation::RMat2Quat::TestMe(argc, argv);
    686 
    687     ModelRotation::RVec2RMat::TestMe(argc, argv);
    688     ModelRotation::RMat2RVec::TestMe(argc, argv);
    689 
    690     ModelRotation::Euler2RMat::TestMe(argc, argv);
    691     ModelRotation::RMat2Euler::TestMe(argc, argv);
    692     return 0;
    693 }
    694 int main1(int argc, char** argv) { ModelRotation::RVec2Quat::TestMe(argc, argv); return 0; }
    695 int main2(int argc, char** argv) { ModelRotation::RVec2RMat::TestMe(argc, argv); return 0; }
    696 int main3(int argc, char** argv) { ModelRotation::Quat2RMat::TestMe(argc, argv); return 0; }
    697 int main7(int argc, char** argv) { ModelRotation::Euler2RMat::TestMe(argc, argv); return 0; }
    698 int main8(int argc, char** argv) { ModelRotation::RMat2Euler::TestMe(argc, argv); return 0; }
    699 #endif
    View Code


     

  • 相关阅读:
    寒武纪芯片——有自己的SDK,支持tf、caffe、MXNet
    专车降价滴滴快车使命终结?
    滴滴代驾骑虎难下 司机1人23部手机刷单
    柳青:再见!滴滴打车 其实这里面都是故事
    “专车”监管意见最快本月公布
    不少专车司机考虑退出
    专车新规或下周发布,估计有大量司机流失
    英媒:滴滴和优步每年烧钱64亿
    约租车管理办法近期公布 数量或受地方政府管控
    Uber上海公司被司机打上门
  • 原文地址:https://www.cnblogs.com/dzyBK/p/14311062.html
Copyright © 2011-2022 走看看