viso_stereo.cpp
Go to the documentation of this file.
00001 /*
00002    Copyright 2011. All rights reserved.
00003    Institute of Measurement and Control Systems
00004    Karlsruhe Institute of Technology, Germany
00005 
00006    This file is part of libviso2.
00007 Authors: Andreas Geiger
00008 
00009 libviso2 is free software; you can redistribute it and/or modify it under the
00010 terms of the GNU General Public License as published by the Free Software
00011 Foundation; either version 2 of the License, or any later version.
00012 
00013 libviso2 is distributed in the hope that it will be useful, but WITHOUT ANY
00014 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
00015 PARTICULAR PURPOSE. See the GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License along with
00018 libviso2; if not, write to the Free Software Foundation, Inc., 51 Franklin
00019 Street, Fifth Floor, Boston, MA 02110-1301, USA
00020 */
00021 
00022 #include "viso_stereo.h"
00023 #include "P3p.h"
00024 #include <eigen3/Eigen/Dense>
00025 #include "ceres/ceres.h"
00026 #include "glog/logging.h"
00027 
00028 #include <TooN/TooN.h>
00029 #include <algorithm>
00030 
00031 using ceres::AutoDiffCostFunction;
00032 using ceres::CostFunction;
00033 using ceres::Problem;
00034 using ceres::Solver;
00035 using ceres::Solve;
00036 using ceres::CauchyLoss;
00037 using ceres::ArctanLoss;
00038 using namespace std;
00039 
00040 //ceres solver
00041 struct ExponentialResidual {
00042     ExponentialResidual(double u, double v, double xp, double yp ,double zp)
00043         : u_(u), v_(v), xp_(xp), yp_(yp), zp_(zp)
00044     {}
00045 
00046     template <typename T> bool operator()(
00047             const T* const rx,
00048             const T* const ry,
00049             const T* const rz,
00050             const T* const tx,
00051             const T* const ty,
00052             const T* const tz,
00053             T* residual) const
00054     {
00055         // precompute sine/cosine
00056         T sx = sin(rx[0]); T cx = cos(rx[0]); T sy = sin(ry[0]);
00057         T cy = cos(ry[0]); T sz = sin(rz[0]); T cz = cos(rz[0]);
00058 
00059         // compute rotation matrix and derivatives
00060         T r00    = +cy*cz;          T r01    = -cy*sz;          T r02    = +sy;
00061         T r10    = +sx*sy*cz+cx*sz; T r11    = -sx*sy*sz+cx*cz; T r12    = -sx*cy;
00062         T r20    = -cx*sy*cz+sx*sz; T r21    = +cx*sy*sz+sx*cz; T r22    = +cx*cy;
00063 
00064         T point_Predicted_x = r00*xp_ + r01*yp_ + r02*zp_ + tx[0];
00065         T point_Predicted_y = r10*xp_ + r11*yp_ + r12*zp_ + ty[0];
00066         T point_Predicted_z = r20*xp_ + r21*yp_ + r22*zp_ + tz[0];
00067 
00068         T u_Predicted = 582.508667*point_Predicted_x/point_Predicted_z + 520.5;
00069         T v_Predicted = 582.508667*point_Predicted_y/point_Predicted_z + 506.5;
00070         residual[0] = (u_-u_Predicted);
00071         residual[1] = (v_-v_Predicted);
00072         return true;
00073     }
00074 
00075     private:
00076     const double u_;
00077     const double v_;
00078     const double xp_;
00079     const double yp_;
00080     const double zp_;
00081 };
00082 
00083 VisualOdometryStereo::VisualOdometryStereo (parameters param) : param(param), VisualOdometry(param) {
00084     rx_old = 0.0;
00085     ry_old = 0.0;
00086     rz_old = 0.0;
00087     tx_old = 0.0;
00088     ty_old = 0.0;
00089     tz_old = 0.0;
00090     matcher->setIntrinsics(param.calib.f,param.calib.cu,param.calib.cv,param.base);
00091 }
00092 
00093 VisualOdometryStereo::~VisualOdometryStereo() {}
00094 
00095 bool VisualOdometryStereo::process (uint8_t *I1,uint8_t *I2,int32_t* dims,bool replace) {
00096     matcher->pushBack(I1,I2,dims,replace);
00097     if (Tr_valid) matcher->matchFeatures(2,&Tr_delta);
00098     else          matcher->matchFeatures(2);
00099     p_matched = matcher->getMatches();
00100     int n = p_matched.size();
00101     p_matched.clear();
00102     matcher->bucketFeatures(param.bucket.max_features,param.bucket.bucket_width,param.bucket.bucket_height);
00103     int width = param.bucket.bucket_width;
00104     int height = param.bucket.bucket_height;
00105     int number_of_matches = 350;
00106     while(n > number_of_matches)
00107     {
00108         matcher->bucketFeatures(param.bucket.max_features, width, height);
00109         n = matcher->getMatches().size();
00110         width++;
00111         height++;
00112     }
00113 
00114     p_matched = matcher->getMatches();
00115     return updateMotion();
00116 }
00117 
00118 //justice if 2 matches fit the constraint of maxclique
00119 bool VisualOdometryStereo::justice2Matches(Matcher::p_match &m1,Matcher::p_match &m2)
00120 {
00121     double d1p = max(m1.u1p - m1.u2p,0.0001f);
00122     double d1c = max(m1.u1c - m1.u2c,0.0001f);
00123     double x1p = (m1.u1p-param.calib.cu)*param.base/d1p;
00124     double y1p = (m1.v1p-param.calib.cv)*param.base/d1p;
00125     double z1p = param.calib.f*param.base/d1p;
00126     double x1c = (m1.u1c-param.calib.cu)*param.base/d1c;
00127     double y1c = (m1.v1c-param.calib.cv)*param.base/d1c;
00128     double z1c = param.calib.f*param.base/d1c;
00129 
00130     double d2p = max(m2.u1p - m2.u2p,0.0001f);
00131     double d2c = max(m2.u1c - m2.u2c,0.0001f);
00132     double x2p = (m2.u1p-param.calib.cu)*param.base/d2p;
00133     double y2p = (m2.v1p-param.calib.cv)*param.base/d2p;
00134     double z2p = param.calib.f*param.base/d2p;
00135     double x2c = (m2.u1c-param.calib.cu)*param.base/d2c;
00136     double y2c = (m2.v1c-param.calib.cv)*param.base/d2c;
00137     double z2c = param.calib.f*param.base/d2c;
00138 
00139     double dist1 = sqrt(pow(x1p-x2p,2)+pow(y1p-y2p,2)+pow(z1p-z2p,2));
00140     double dist2 = sqrt(pow(x1c-x2c,2)+pow(y1c-y2c,2)+pow(z1c-z2c,2));
00141     double diff = fabs(dist1-dist2);
00142     if(diff< 0.25 && dist1<5.0)
00143         return true;
00144     else
00145         return false;
00146 }
00147 
00148 //Creat the adjmatrix, which is used in maxclique
00149 void VisualOdometryStereo::creatAdjMatrix(vector<Matcher::p_match>& p_matched,bool** &conn)
00150 {
00151     int size = p_matched.size();
00152     conn = new bool*[size];
00153     for (int i=0; i < size; i++) {
00154         conn[i] = new bool[size];
00155         memset(conn[i], 0, size * sizeof(bool));
00156     }
00157     for(int i=0;i<size;++i)
00158         for(int j=0;j<=i;++j)
00159             if(justice2Matches(p_matched[i],p_matched[j]))
00160             {
00161                 conn[i][j]=true;
00162                 conn[j][i]=true;
00163             }
00164 }
00165 
00166 //estimate motion with Maxclique
00167 vector<double> VisualOdometryStereo::estimateMotionMaxClique (vector<Matcher::p_match> p_matched)
00168 {
00169     /*//MaxClique +RANSAC + p3p
00170     int64_t N  = p_matched.size();
00171     double rx=rx_old,ry=ry_old,rz=rz_old,tx=tx_old,ty=ty_old,tz=tz_old;
00172     Problem problem;
00173 
00174     // loop variables
00175     TooN::Matrix<3,4> tr_delta,tr_delta_curr;
00176     tr_delta = TooN::Data(0,1,0,0,
00177             0,0,1,0,
00178             0,0,0,1);
00179     tr_delta_curr = TooN::Data(0,1,0,0,
00180             0,0,1,0,
00181             0,0,0,1);
00182 
00183     if (N<6)
00184         return vector<double>();
00185     bool** conn;
00186     int* qmax,qsize;
00187     creatAdjMatrix(p_matched,conn);
00188 
00189     Maxclique md(conn,N,0.1);
00190     md.mcqdyn(qmax, qsize);
00191 
00192     std::vector<int32_t> inliers_maxclique;
00193     for (int i = 0; i < qsize; i++)
00194         inliers_maxclique.push_back(qmax[i]);
00195     bool success=true;
00196 
00197     std::vector<Matcher::p_match> p_matched_maxclique;
00198     for(int i = 0; i<inliers_maxclique.size(); ++i)
00199     {
00200         p_matched_maxclique.push_back(p_matched[inliers_maxclique[i] ]);
00201     }
00202     int32_t N_ = p_matched_maxclique.size();
00203     p_matched.clear();
00204     p_matched = p_matched_maxclique;
00205     p_matched1 = p_matched_maxclique;
00206     // allocate dynamic memory
00207     X          = new double[N_];
00208     Y          = new double[N_];
00209     Z          = new double[N_];
00210     XC         = new double[N_];
00211     YC         = new double[N_];
00212     ZC         = new double[N_];
00213     J          = new double[4*N_*6];
00214     p_predict  = new double[4*N_];
00215     p_observe  = new double[4*N_];
00216     p_residual = new double[4*N_];
00217 
00218     for (int32_t i=0; i<N_; i++) {
00219         double d = max(p_matched_maxclique[i].u1p - p_matched_maxclique[i].u2p,0.0001f);
00220         X[i] = (p_matched_maxclique[i].u1p-param.calib.cu)*param.base/d;
00221         Y[i] = (p_matched_maxclique[i].v1p-param.calib.cv)*param.base/d;
00222         Z[i] = param.calib.f*param.base/d;
00223         XC[i] = (p_matched_maxclique[i].u1c-param.calib.cu)*param.base/d;
00224         YC[i] = (p_matched_maxclique[i].v1c-param.calib.cv)*param.base/d;
00225         ZC[i] = param.calib.f*param.base/d;
00226     }
00227     inliers.clear();
00228     // initial RANSAC estimate
00229     for (int32_t k=0;k<param.ransac_iters;k++) {
00230 
00231         // draw random sample set
00232         vector<int32_t> active = getRandomSample(N_,3);
00233 
00234         // minimize reprojection errors
00235         VisualOdometryStereo::result result = UPDATED;
00236         result = updateParametersP3p(p_matched1,active,tr_delta_curr,1,1e-6);
00237         if(result == CONVERGED)
00238         {
00239             vector<int32_t> inliers_curr = getInlier(p_matched1,tr_delta_curr);
00240             if (inliers_curr.size()>inliers.size()) {
00241                 inliers = inliers_curr;
00242                 tr_delta = tr_delta_curr;
00243             }
00244         }
00245     }
00246 
00247     vector<double> tr_delta_vec;
00248     tr_delta_vec.resize(6);
00249     tr_delta_vec[0] = tr_delta[2][2];
00250     tr_delta_vec[1] = tr_delta[2][1];
00251     tr_delta_vec[2] = tr_delta[1][1];
00252     tr_delta_vec[3] = tr_delta[0][0];
00253     tr_delta_vec[4] = tr_delta[0][1];
00254     tr_delta_vec[5] = tr_delta[0][2];
00255 
00256     std::cout<<"inliers of P3P-MaxClique:\t"<<inliers.size()<<"\tp_matched N N_:"<<N<<" "<<N_<<"\t"<<(double)inliers.size()*100/N_<<std::endl;
00257     rx = tr_delta_vec[0]; ry = tr_delta_vec[1]; rz = tr_delta_vec[2];
00258     tx = tr_delta_vec[3]; ty = tr_delta_vec[4]; tz = tr_delta_vec[5];
00259 
00260     for(int i=0;i<inliers.size();++i)
00261     {
00262         problem.AddResidualBlock(
00263                 new AutoDiffCostFunction<ExponentialResidual, 2, 1, 1,1,1,1,1>(
00264                     new ExponentialResidual(p_matched_maxclique[inliers[i]].u1c,p_matched_maxclique[inliers[i]].v1c,X[inliers[i]],Y[inliers[i]],Z[inliers[i]])),
00265                 new CauchyLoss(0.5),
00266                 //NULL,
00267                 &rx, &ry,&rz,&tx,&ty,&tz);
00268     }
00269 
00270     Solver::Options options;
00271     options.max_num_iterations = 100;
00272     options.linear_solver_type = ceres::DENSE_QR;
00273     options.minimizer_progress_to_stdout = false;
00274 
00275     Solver::Summary summary;
00276     Solve(options, &problem, &summary);
00277     if(summary.IsSolutionUsable()==false)
00278     {
00279         success = false;
00280         std::cout <<"UN CONVERGED!!!\n" <<summary.BriefReport() << "\n";
00281     }
00282 
00283     tr_delta_vec[0] = rx;
00284     tr_delta_vec[1] = ry;
00285     tr_delta_vec[2] = rz;
00286     tr_delta_vec[3] = tx;
00287     tr_delta_vec[4] = ty;
00288     tr_delta_vec[5] = tz;
00289 
00290     for (int i=0;i<N;i++)
00291         delete [] conn[i];
00292     delete [] conn;
00293     delete [] qmax;
00294     // release dynamic memory
00295     delete[] X;
00296     delete[] Y;
00297     delete[] Z;
00298     delete[] XC;
00299     delete[] YC;
00300     delete[] ZC;
00301     delete[] J;
00302     delete[] p_predict;
00303     delete[] p_observe;
00304     delete[] p_residual;
00305     // parameter estimate succeeded?
00306     if (success) return tr_delta_vec;
00307     else         return vector<double>();*/
00308 
00309     //MaxClique +RANSAC + ceres
00310     int32_t N  = p_matched.size();
00311     double rx=rx_old,ry=ry_old,rz=rz_old,tx=tx_old,ty=ty_old,tz=tz_old;
00312     Problem problem;
00313 
00314     // loop variables
00315     vector<double> tr_delta;
00316     tr_delta.resize(6);
00317     vector<double> tr_delta_curr;
00318     tr_delta_curr.resize(6);
00319 
00320     if (N<6)
00321         return vector<double>();
00322     bool** conn;
00323     int* qmax,qsize;
00324     creatAdjMatrix(p_matched,conn);
00325 
00326     Maxclique md(conn,N);
00327     md.mcq(qmax, qsize);
00328 
00329     std::vector<int32_t> inliers_maxclique;
00330     for (int i = 0; i < qsize; i++)
00331         inliers_maxclique.push_back(qmax[i]);
00332     bool success=true;
00333 
00334     std::vector<Matcher::p_match> p_matched_maxclique;
00335     for(int i = 0; i<inliers_maxclique.size(); ++i)
00336     {
00337         p_matched_maxclique.push_back(p_matched[inliers_maxclique[i] ]);
00338     }
00339     int32_t N_ = p_matched_maxclique.size();
00340     p_matched.clear();
00341     p_matched = p_matched_maxclique;
00342     p_matched1 = p_matched_maxclique;
00343     // allocate dynamic memory
00344     X          = new double[N_];
00345     Y          = new double[N_];
00346     Z          = new double[N_];
00347     XC         = new double[N_];
00348     YC         = new double[N_];
00349     ZC         = new double[N_];
00350     J          = new double[4*N_*6];
00351     p_predict  = new double[4*N_];
00352     p_observe  = new double[4*N_];
00353     p_residual = new double[4*N_];
00354 
00355     for (int32_t i=0; i<N_; i++) {
00356         double d = max(p_matched_maxclique[i].u1p - p_matched_maxclique[i].u2p,0.0001f);
00357         X[i] = (p_matched_maxclique[i].u1p-param.calib.cu)*param.base/d;
00358         Y[i] = (p_matched_maxclique[i].v1p-param.calib.cv)*param.base/d;
00359         Z[i] = param.calib.f*param.base/d;
00360         XC[i] = (p_matched_maxclique[i].u1c-param.calib.cu)*param.base/d;
00361         YC[i] = (p_matched_maxclique[i].v1c-param.calib.cv)*param.base/d;
00362         ZC[i] = param.calib.f*param.base/d;
00363     }
00364     inliers.clear();
00365     // initial RANSAC estimate
00366     for (int32_t k=0;k<param.ransac_iters;k++) {
00367 
00368         // draw random sample set
00369         vector<int32_t> active = getRandomSample(N_,3);
00370 
00371         // clear parameter vector
00372         for (int32_t i=0; i<6; i++)
00373             tr_delta_curr[i] = 0;
00374 
00375         // minimize reprojection errors
00376         VisualOdometryStereo::result result = UPDATED;
00377         int32_t iter=0;
00378         while (result==UPDATED) {
00379             result = updateParameters(p_matched_maxclique,active,tr_delta_curr,1,1e-8);
00380             if (iter++ > 100 || result==CONVERGED)
00381                 break;
00382         }
00383         // overwrite best parameters if we have more inliers
00384         if (result==CONVERGED) {
00385             vector<int32_t> inliers_curr = getInlier(p_matched_maxclique,tr_delta_curr);
00386             if (inliers_curr.size()>inliers.size()) {
00387                 inliers = inliers_curr;
00388                 tr_delta = tr_delta_curr;
00389             }
00390         }
00391     }
00392     rx = tr_delta[0]; ry = tr_delta[1]; rz = tr_delta[2];
00393     tx = tr_delta[3]; ty = tr_delta[4]; tz = tr_delta[5];
00394     std::cout<<"inliers of MaxClique:\t"<<inliers.size()<<"\tp_matched N N_:"<<N<<" "<<N_<<"\t"<<(double)inliers.size()*100/N_<<std::endl;
00395 
00396 
00397     for(int i=0;i<inliers.size();++i)
00398     {
00399         problem.AddResidualBlock(
00400                 new AutoDiffCostFunction<ExponentialResidual, 2, 1, 1,1,1,1,1>(
00401                     new ExponentialResidual(p_matched_maxclique[inliers[i]].u1c,p_matched_maxclique[inliers[i]].v1c,X[inliers[i]],Y[inliers[i]],Z[inliers[i]])),
00402                 new CauchyLoss(0.5),
00403                 //NULL,
00404                 &rx, &ry,&rz,&tx,&ty,&tz);
00405     }
00406 
00407     Solver::Options options;
00408     options.max_num_iterations = 100;
00409     options.linear_solver_type = ceres::DENSE_QR;
00410     options.minimizer_progress_to_stdout = false;
00411 
00412     Solver::Summary summary;
00413     Solve(options, &problem, &summary);
00414     if(summary.IsSolutionUsable()==false)
00415     {
00416         success = false;
00417         std::cout <<"UN CONVERGED!!!\n" <<summary.BriefReport() << "\n";
00418     }
00419 
00420     tr_delta[0] = rx;
00421     tr_delta[1] = ry;
00422     tr_delta[2] = rz;
00423     tr_delta[3] = tx;
00424     tr_delta[4] = ty;
00425     tr_delta[5] = tz;
00426 
00427     for (int i=0;i<N;i++)
00428         delete [] conn[i];
00429     delete [] conn;
00430     delete [] qmax;
00431     // release dynamic memory
00432     delete[] X;
00433     delete[] Y;
00434     delete[] Z;
00435     delete[] XC;
00436     delete[] YC;
00437     delete[] ZC;
00438     delete[] J;
00439     delete[] p_predict;
00440     delete[] p_observe;
00441     delete[] p_residual;
00442     // parameter estimate succeeded?
00443     if (success) return tr_delta;
00444     else         return vector<double>();
00445 
00446     //newton-gauss and Maxclique
00447     /*
00448      *        if(p_matched.size()>200)
00449      *        {
00450      *            partial_sort(p_matched.begin(),p_matched.begin()+200,p_matched.end());
00451      *            p_matched.resize(200);
00452      *        }
00453      *
00454      *    [>printf("after filter, the p_matched's size is %d\n",p_matched.size());<]
00455      *    int32_t N  = p_matched.size();
00456      *    // allocate dynamic memory
00457      *    X          = new double[N];
00458      *    Y          = new double[N];
00459      *    Z          = new double[N];
00460      *    XC         = new double[N];
00461      *    YC         = new double[N];
00462      *    ZC         = new double[N];
00463      *    J          = new double[4*N*6];
00464      *    p_predict  = new double[4*N];
00465      *    p_observe  = new double[4*N];
00466      *    p_residual = new double[4*N];
00467      *
00468      *    // project matches of previous image into 3d
00469      *    for (int32_t i=0; i<N; i++) {
00470      *        double d = max(p_matched[i].u1p - p_matched[i].u2p,0.0001f);
00471      *        X[i] = (p_matched[i].u1p-param.calib.cu)*param.base/d;
00472      *        Y[i] = (p_matched[i].v1p-param.calib.cv)*param.base/d;
00473      *        Z[i] = param.calib.f*param.base/d;
00474      *        XC[i] = (p_matched[i].u1c-param.calib.cu)*param.base/d;
00475      *        YC[i] = (p_matched[i].v1c-param.calib.cv)*param.base/d;
00476      *        ZC[i] = param.calib.f*param.base/d;
00477      *    }
00478      *
00479      *    // loop variables
00480      *    vector<double> tr_delta;
00481      *    tr_delta.resize(6);
00482      *    vector<double> tr_delta_curr;
00483      *    tr_delta_curr.resize(6);
00484      *
00485      *    if (N<6)
00486      *        return vector<double>();
00487      *    bool** conn;
00488      *    int* qmax,qsize;
00489      *    creatAdjMatrix(p_matched,conn);
00490      *    Maxclique md(conn,N,0.025);
00491      *    md.mcqdyn(qmax, qsize);
00492      *    inliers.clear();
00493      *    for (int i = 0; i < qsize; i++)
00494      *        inliers.push_back(qmax[i]);
00495      *    bool success=true;
00496      *
00497      *    [>printf("after Max Clique, the inliers's size is %d\n",inliers.size());<]
00498      *    if (inliers.size()>=6) {
00499      *        int32_t iter=0;
00500      *        VisualOdometryStereo::result result = UPDATED;
00501      *        while (result==UPDATED) {
00502      *            result = updateParameters(p_matched,inliers,tr_delta,1,1e-8);
00503      *            if (iter++ > 100 || result==CONVERGED)
00504      *                break;
00505      *        }
00506      *
00507      *        // not converged
00508      *        if (result!=CONVERGED)
00509      *            success = false;
00510      *
00511      *        // not enough inliers
00512      *    } else {
00513      *        success = false;
00514      *    }
00515      *
00516      *    for (int i=0;i<N;i++)
00517      *        delete [] conn[i];
00518     *    delete [] conn;
00519     *    delete [] qmax;
00520     *    // release dynamic memory
00521         *    delete[] X;
00522     *    delete[] Y;
00523     *    delete[] Z;
00524     *    delete[] XC;
00525     *    delete[] YC;
00526     *    delete[] ZC;
00527     *    delete[] J;
00528     *    delete[] p_predict;
00529     *    delete[] p_observe;
00530     *    delete[] p_residual;
00531     *
00532         *    // parameter estimate succeeded?
00533         *    if (success) return tr_delta;
00534     *    else         return vector<double>();
00535     */
00536 }
00537 vector<double> VisualOdometryStereo::estimateMotionLinear (vector<Matcher::p_match> p_matched)
00538 {
00539     if(p_matched.size()<6)
00540         return vector<double> ();
00541     TooN::Matrix<3,4> tr_delta,tr_delta_curr;
00542     tr_delta = TooN::Data(0,1,0,0,
00543             0,0,1,0,
00544             0,0,0,1);
00545     tr_delta_curr = TooN::Data(0,1,0,0,
00546             0,0,1,0,
00547             0,0,0,1);
00548 
00549     // return value
00550     bool success = true;
00551 
00552     // compute minimum distance for RANSAC samples
00553     double width=0,height=0;
00554     for (vector<Matcher::p_match>::iterator it=p_matched.begin(); it!=p_matched.end(); it++) {
00555         if (it->u1c>width)  width  = it->u1c;
00556         if (it->v1c>height) height = it->v1c;
00557     }
00558     double min_dist = min(width,height)/3.0;
00559 
00560     // get number of matches
00561     int32_t N  = p_matched.size();
00562     if (N<6)
00563         return vector<double>();
00564 
00565     // allocate dynamic memory
00566     X          = new double[N];
00567     Y          = new double[N];
00568     Z          = new double[N];
00569     XC         = new double[N];
00570     YC         = new double[N];
00571     ZC         = new double[N];
00572     J          = new double[4*N*6];
00573     p_predict  = new double[4*N];
00574     p_observe  = new double[4*N];
00575     p_residual = new double[4*N];
00576 
00577     // project matches of previous image into 3d
00578     for (int32_t i=0; i<N; i++) {
00579         double d = max(p_matched[i].u1p - p_matched[i].u2p,0.0001f);
00580         X[i] = (p_matched[i].u1p-param.calib.cu)*param.base/d;
00581         Y[i] = (p_matched[i].v1p-param.calib.cv)*param.base/d;
00582         Z[i] = param.calib.f*param.base/d;
00583         XC[i] = (p_matched[i].u1c-param.calib.cu)*param.base/d;
00584         YC[i] = (p_matched[i].v1c-param.calib.cv)*param.base/d;
00585         ZC[i] = param.calib.f*param.base/d;
00586     }
00587 
00588     inliers.clear();
00589     // initial RANSAC estimate
00590     for (int32_t k=0;k<param.ransac_iters;k++) {
00591 
00592         // draw random sample set
00593         vector<int32_t> active = getRandomSample(N,3);
00594 
00595         // clear parameter vector
00596 
00597         // minimize reprojection errors
00598         VisualOdometryStereo::result result = UPDATED;
00599         result = updateParametersP3p(p_matched,active,tr_delta_curr,1,1e-6);
00600         if(result == CONVERGED)
00601         {
00602             vector<int32_t> inliers_curr = getInlier(p_matched,tr_delta_curr);
00603             if (inliers_curr.size()>inliers.size()) {
00604                 inliers = inliers_curr;
00605                 tr_delta = tr_delta_curr;
00606             }
00607         }
00608     }
00609 
00610     vector<double> tr_delta_vec;
00611     tr_delta_vec.resize(6);
00612     tr_delta_vec[0] = tr_delta[2][2];
00613     tr_delta_vec[1] = tr_delta[2][1];
00614     tr_delta_vec[2] = tr_delta[1][1];
00615     tr_delta_vec[3] = tr_delta[0][0];
00616     tr_delta_vec[4] = tr_delta[0][1];
00617     tr_delta_vec[5] = tr_delta[0][2];
00618 
00619 
00620     std::cout<<"inliers of P3p:\t"<<inliers.size()<<"\tp_matched :\t"<<p_matched.size()<<"\t"<<(double)inliers.size()*100/p_matched.size()<<std::endl;
00621 
00622     double rx=rx_old,ry=ry_old,rz=rz_old,tx=tx_old,ty=ty_old,tz=tz_old;
00623     rx = tr_delta_vec[0]; ry = tr_delta_vec[1]; rz = tr_delta_vec[2];
00624     tx = tr_delta_vec[3]; ty = tr_delta_vec[4]; tz = tr_delta_vec[5];
00625     Problem problem;
00626     for(int i=0;i<inliers.size();++i)
00627     {
00628         problem.AddResidualBlock(
00629                 new AutoDiffCostFunction<ExponentialResidual, 2, 1, 1,1,1,1,1>(
00630                     new ExponentialResidual(p_matched[inliers[i]].u1c,p_matched[inliers[i]].v1c,X[inliers[i]],Y[inliers[i]],Z[inliers[i]])),
00631                 new CauchyLoss(2.0),
00632                 //NULL,
00633                 &rx, &ry,&rz,&tx,&ty,&tz);
00634     }
00635 
00636     Solver::Options options;
00637     options.max_num_iterations = 20;
00638     options.linear_solver_type = ceres::DENSE_QR;
00639     options.minimizer_progress_to_stdout = false;
00640 
00641     Solver::Summary summary;
00642     Solve(options, &problem, &summary);
00643     if(summary.IsSolutionUsable()==false)
00644     {
00645         success = false;
00646         std::cout <<"UN CONVERGED!!!\n" <<summary.BriefReport() << "\n";
00647     }
00648 
00649     tr_delta_vec[0] = rx;
00650     tr_delta_vec[1] = ry;
00651     tr_delta_vec[2] = rz;
00652     tr_delta_vec[3] = tx;
00653     tr_delta_vec[4] = ty;
00654     tr_delta_vec[5] = tz;
00655 
00656     p_matched1 = p_matched;
00657     // parameter estimate succeeded?
00658     if (success) return tr_delta_vec;
00659     else         return vector<double>();
00660     delete[] X;
00661     delete[] Y;
00662     delete[] Z;
00663     delete[] XC;
00664     delete[] YC;
00665     delete[] ZC;
00666     delete[] J;
00667     delete[] p_predict;
00668     delete[] p_observe;
00669     delete[] p_residual;
00670     return vector<double>();
00671 }
00672 
00673 vector<double> VisualOdometryStereo::estimateMotion (vector<Matcher::p_match> p_matched) {
00674 
00675     // return value
00676     bool success = true;
00677 
00678     // compute minimum distance for RANSAC samples
00679     double width=0,height=0;
00680     for (vector<Matcher::p_match>::iterator it=p_matched.begin(); it!=p_matched.end(); it++) {
00681         if (it->u1c>width)  width  = it->u1c;
00682         if (it->v1c>height) height = it->v1c;
00683     }
00684     double min_dist = min(width,height)/3.0;
00685 
00686     // get number of matches
00687     int32_t N  = p_matched.size();
00688     if (N<6)
00689         return vector<double>();
00690     double rx=rx_old,ry=ry_old,rz=rz_old,tx=tx_old,ty=ty_old,tz=tz_old;
00691     // allocate dynamic memory
00692     X          = new double[N];
00693     Y          = new double[N];
00694     Z          = new double[N];
00695     XC         = new double[N];
00696     YC         = new double[N];
00697     ZC         = new double[N];
00698     J          = new double[4*N*6];
00699     p_predict  = new double[4*N];
00700     p_observe  = new double[4*N];
00701     p_residual = new double[4*N];
00702 
00703     // project matches of previous image into 3d
00704     for (int32_t i=0; i<N; i++) {
00705         double d = max(p_matched[i].u1p - p_matched[i].u2p,0.0001f);
00706         X[i] = (p_matched[i].u1p-param.calib.cu)*param.base/d;
00707         Y[i] = (p_matched[i].v1p-param.calib.cv)*param.base/d;
00708         Z[i] = param.calib.f*param.base/d;
00709         XC[i] = (p_matched[i].u1c-param.calib.cu)*param.base/d;
00710         YC[i] = (p_matched[i].v1c-param.calib.cv)*param.base/d;
00711         ZC[i] = param.calib.f*param.base/d;
00712     }
00713 
00714     // loop variables
00715     vector<double> tr_delta;
00716     vector<double> tr_delta_curr;
00717     tr_delta_curr.resize(6);
00718 
00719     // clear parameter vector
00720     inliers.clear();
00721 
00722     // initial RANSAC estimate
00723     for (int32_t k=0;k<param.ransac_iters;k++) {
00724 
00725         // draw random sample set
00726         vector<int32_t> active = getRandomSample(N,3);
00727 
00728         // clear parameter vector
00729         for (int32_t i=0; i<6; i++)
00730             tr_delta_curr[i] = 0;
00731 
00732         // minimize reprojection errors
00733         VisualOdometryStereo::result result = UPDATED;
00734         int32_t iter=0;
00735         while (result==UPDATED) {
00736             result = updateParameters(p_matched,active,tr_delta_curr,1,1e-6);
00737             if (iter++ > 20 || result==CONVERGED)
00738                 break;
00739         }
00740         // overwrite best parameters if we have more inliers
00741         if (result==CONVERGED) {
00742             vector<int32_t> inliers_curr = getInlier(p_matched,tr_delta_curr);
00743             if (inliers_curr.size()>inliers.size()) {
00744                 inliers = inliers_curr;
00745                 tr_delta = tr_delta_curr;
00746             }
00747         }
00748     }
00749     /*
00750        std::cout<<"inliers of Gauss-Newton:"<<inliers.size()<<"p_matched :"<<p_matched.size()<<"\t"<<(double)100*inliers.size()/p_matched.size()<<std::endl;
00751        if (inliers.size()>=6) {
00752        int32_t iter=0;
00753        VisualOdometryStereo::result result = UPDATED;
00754        while (result==UPDATED) {
00755        result = updateParameters(p_matched,inliers,tr_delta,1,1e-8);
00756        if (iter++ > 100 || result==CONVERGED)
00757        break;
00758        }
00759 
00760 // not converged
00761 if (result!=CONVERGED)
00762 success = false;
00763 
00764 // not enough inliers
00765 } else {
00766 success = false;
00767 }
00768 */
00769 
00770 rx = tr_delta[0]; ry = tr_delta[1]; rz = tr_delta[2];
00771 tx = tr_delta[3]; ty = tr_delta[4]; tz = tr_delta[5];
00772 std::cout<<"inliers of newton-gauss:\t"<<inliers.size()<<"\tp_matched :\t"<<p_matched.size()<<"\t"<<(double)inliers.size()*100/p_matched.size()<<std::endl;
00773 Problem problem;
00774 
00775 for(int i=0;i<inliers.size();++i)
00776 {
00777     problem.AddResidualBlock(
00778             new AutoDiffCostFunction<ExponentialResidual, 2, 1, 1,1,1,1,1>(
00779                 new ExponentialResidual(p_matched[inliers[i]].u1c,p_matched[inliers[i]].v1c,X[inliers[i]],Y[inliers[i]],Z[inliers[i]])),
00780             new CauchyLoss(0.5),
00781             //NULL,
00782             &rx, &ry,&rz,&tx,&ty,&tz);
00783 }
00784 
00785 Solver::Options options;
00786 options.max_num_iterations = 100;
00787 options.linear_solver_type = ceres::DENSE_QR;
00788 options.minimizer_progress_to_stdout = false;
00789 
00790 Solver::Summary summary;
00791 Solve(options, &problem, &summary);
00792 if(summary.IsSolutionUsable()==false)
00793 {
00794     success = false;
00795     std::cout <<"UN CONVERGED!!!\n" <<summary.BriefReport() << "\n";
00796 }
00797 
00798 tr_delta[0] = rx;
00799 tr_delta[1] = ry;
00800 tr_delta[2] = rz;
00801 tr_delta[3] = tx;
00802 tr_delta[4] = ty;
00803 tr_delta[5] = tz;
00804 
00805 // release dynamic memory
00806 delete[] X;
00807 delete[] Y;
00808 delete[] Z;
00809 delete[] XC;
00810 delete[] YC;
00811 delete[] ZC;
00812 delete[] J;
00813 delete[] p_predict;
00814 delete[] p_observe;
00815 delete[] p_residual;
00816 
00817 p_matched1 = p_matched;
00818 // parameter estimate succeeded?
00819 if (success) return tr_delta;
00820 else         return vector<double>();
00821 }
00822 
00823 vector<int32_t> VisualOdometryStereo::getInlier(vector<Matcher::p_match> &p_matched,vector<double> &tr) {
00824 
00825     // mark all observations active
00826     vector<int32_t> active;
00827     for (int32_t i=0; i<(int32_t)p_matched.size(); i++)
00828         active.push_back(i);
00829 
00830     // extract observations and compute predictions
00831     computeObservations(p_matched,active);
00832     computeResidualsAndJacobian(tr,active);
00833 
00834     // compute inliers
00835     vector<int32_t> inliers;
00836     for (int32_t i=0; i<(int32_t)p_matched.size(); i++)
00837         if (pow(p_observe[4*i+0]-p_predict[4*i+0],2)+pow(p_observe[4*i+1]-p_predict[4*i+1],2) +
00838                 pow(p_observe[4*i+2]-p_predict[4*i+2],2)+pow(p_observe[4*i+3]-p_predict[4*i+3],2) < param.inlier_threshold*param.inlier_threshold)
00839             inliers.push_back(i);
00840     return inliers;
00841 }
00842 
00843 vector<int32_t> VisualOdometryStereo::getInlier(vector<Matcher::p_match> &p_matched,TooN::Matrix<3,4> &tr)
00844 {
00845     // mark all observations active
00846     vector<int32_t> active;
00847     for (int32_t i=0; i<(int32_t)p_matched.size(); i++)
00848         active.push_back(i);
00849 
00850     // extract observations and compute predictions
00851     computeObservations(p_matched,active);
00852     computeResidualsAndJacobianP3p(tr,active);
00853 
00854     // compute inliers
00855     vector<int32_t> inliers;
00856     for (int32_t i=0; i<(int32_t)p_matched.size(); i++)
00857         if (pow(p_observe[4*i+0]-p_predict[4*i+0],2)+pow(p_observe[4*i+1]-p_predict[4*i+1],2) +
00858                 pow(p_observe[4*i+2]-p_predict[4*i+2],2)+pow(p_observe[4*i+3]-p_predict[4*i+3],2) < param.inlier_threshold*param.inlier_threshold)
00859             inliers.push_back(i);
00860     return inliers;
00861 }
00862 VisualOdometryStereo::result VisualOdometryStereo::updateParametersP3p(vector<Matcher::p_match> &p_matched,vector<int32_t> &active,TooN::Matrix<3,4> &tr,double step_size,double eps)
00863 {
00864     if(active.size()!=3)
00865         return FAILED;
00866     TooN::Matrix<3,3> features;
00867     TooN::Matrix<3,3> worldPoints;
00868     TooN::Matrix<3,16> solutions;
00869     for(int i=0;i<3;++i)
00870     {
00871         double normPc = sqrt(pow(X[active[i]],2)+pow(Y[active[i]],2)+pow(Z[active[i]],2));
00872         worldPoints[0][i] = XC[active[i]];
00873         worldPoints[1][i] = YC[active[i]];
00874         worldPoints[2][i] = ZC[active[i]];
00875 
00876         features[0][i] = X[active[i]]/normPc;
00877         features[1][i] = Y[active[i]]/normPc;
00878         features[2][i] = Z[active[i]]/normPc;
00879     }
00880     P3p myP3p;
00881     if(myP3p.computePoses(features,worldPoints,solutions) != 0)
00882         return FAILED;
00883     for(int i=0;i<4;++i)
00884     {
00885         if(fabs(solutions[0][4*i])<0.3 && fabs(solutions[1][4*i])<0.3 && fabs(solutions[2][4*i])<0.3)
00886         {
00887             tr = solutions.slice(0,4*i,3,4);
00888             //std::cout<<tr[2][2]<<"\t"<<-tr[2][1]<<"\t"<<tr[1][1]<<"\t"<<tr[0][0]<<"\t"<<tr[1][0]<<"\t"<<tr[2][0]<<std::endl;
00889             //std::cout<<tr<<std::endl;
00890             return CONVERGED;
00891         }
00892     }
00893     return FAILED;
00894 }
00895 VisualOdometryStereo::result VisualOdometryStereo::updateParametersLinear(vector<Matcher::p_match> &p_matched,vector<int32_t> &active,vector<double> &tr,double step_size,double eps)
00896 {
00897     //Linear Version one
00898     /*
00899      *    if(active.size()<3)
00900      *        return FAILED;
00901      *    Eigen::MatrixXd A(3*active.size(),6);
00902      *    Eigen::VectorXd b(3*active.size());
00903      *    for(int i=0;i<active.size();++i)
00904      *    {
00905      *        if((Z[active[i]]>8)||(ZC[active[i]]>8))
00906      *            return FAILED;
00907      *        A(i*3+0,0) = 0;     A(i*3+1,0) = -Z[active[i]];      A(i*3+2,0) = Y[active[i]];
00908      *        A(i*3+0,1) = -Z[active[i]];     A(i*3+1,1) = 0;      A(i*3+2,1) = X[active[i]];
00909      *        A(i*3+0,2) = -Y[active[i]]; A(i*3+1,2) = X[active[i]];A(i*3+2,2) = 0;
00910      *        A(i*3+0,3) = 1; A(i*3+1,3) = 0; A(i*3+2,3) = 0;
00911      *        A(i*3+0,4) = 0; A(i*3+1,4) = 1; A(i*3+2,4) = 0;
00912      *        A(i*3+0,5) = 0; A(i*3+1,5) = 0; A(i*3+2,5) = 1;
00913      *        b(i*3+0) = XC[active[i]]-X[active[i]];
00914      *        b(i*3+1) = YC[active[i]]-Y[active[i]];
00915      *        b(i*3+2) = ZC[active[i]]-Z[active[i]];
00916      *    }
00917      *
00918      *    Eigen::VectorXd x = A.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(b);
00919      *    for(int i=0;i<6;++i)
00920      *        tr[i] = x(i);
00921      *    return CONVERGED;
00922      */
00923     /*
00924      *Matrix A(6,6);
00925      *Matrix B(6,1);
00926      */
00927     /*
00928      *    Eigen::MatrixXd A(2*active.size(),6);
00929      *    Eigen::VectorXd b(2*active.size());
00930      *    double f = param.calib.f;
00931      *
00932      *    for(int i=0;i<active.size();++i)
00933      *    {
00934      *        int uc = p_matched[active[i]].u1c;
00935      *        int vc = p_matched[active[i]].v1c;
00936      *        int up = p_matched[active[i]].u1p;
00937      *        int vp = p_matched[active[i]].v1p;
00938      *        double disparity = max(p_matched[i].u1p - p_matched[i].u2p,0.0001f);
00939      *        A(i*2+0,0) = uc*vp;
00940      *        A(i*2+0,1) = up*uc+f*f;
00941      *        A(i*2+0,2) = f*vp;
00942      *        A(i*2+0,3) = -f*disparity/param.base;
00943      *        A(i*2+0,4) = 0;
00944      *        A(i*2+0,5) = uc*disparity/param.base;
00945      *
00946      *        A(i*2+1,0) = vp*vc;
00947      *        A(i*2+1,1) = up*vc;
00948      *        A(i*2+1,2) = -f*up;
00949      *        A(i*2+1,3) = 0;
00950      *        A(i*2+1,4) = -f*disparity/param.base;
00951      *        A(i*2+1,5) = vc*disparity/param.base;
00952      *
00953      *        b(i*2+0) = f*(up-uc);
00954      *        b(i*2+1) = f*(vp-vc);
00955      */
00956     /*
00957      *
00958      *        A.val[i*2+0][0] = (double)uc*vp;
00959      *        A.val[i*2+0][1] = up*uc+f*f;
00960      *        A.val[i*2+0][2]= f*vp;
00961      *        A.val[i*2+0][3] = -f*disparity/param.base;
00962      *        A.val[i*2+0][4] = 0;
00963      *        A.val[i*2+0][5] = uc*disparity/param.base;
00964      *
00965      *        A.val[i*2+1][0] = vp*vc;
00966      *        A.val[i*2+1][1] = up*vc;
00967      *        A.val[i*2+1][2] = -f*up;
00968      *        A.val[i*2+1][3]= 0;
00969      *        A.val[i*2+1][4] = -f*disparity/param.base;
00970      *        A.val[i*2+1][5] = vc*disparity/param.base;
00971      *
00972      *        B.val[i*2+0][0] = f*(up-uc);
00973      *        B.val[i*2+1][0] = f*(vp-vc);
00974      */
00975     /*
00976      * if (B.solve(A)) {
00977      *    bool converged = true;
00978      *    for (int32_t m=0; m<6; m++) {
00979      *        tr[m] += step_size*B.val[m][0];
00980      *        if (fabs(B.val[m][0])>eps)
00981      *            converged = false;
00982      *    }
00983      *    if (converged)
00984      *        return CONVERGED;
00985      *    else
00986      *        return UPDATED;
00987      *} else {
00988      *    return FAILED;
00989      *}
00990      */
00991 }
00992 
00993 VisualOdometryStereo::result VisualOdometryStereo::updateParameters(vector<Matcher::p_match> &p_matched,vector<int32_t> &active,vector<double> &tr,double step_size,double eps) {
00994 
00995     // we need at least 3 observations
00996     if (active.size()<3)
00997         return FAILED;
00998 
00999     // extract observations and compute predictions
01000     computeObservations(p_matched,active);
01001     computeResidualsAndJacobian(tr,active);
01002     // init
01003     Matrix A(6,6);
01004     Matrix B(6,1);
01005     // fill matrices A and B
01006     for (int32_t m=0; m<6; m++) {
01007         for (int32_t n=0; n<6; n++) {
01008             double a = 0;
01009             for (int32_t i=0; i<4*(int32_t)active.size(); i++) {
01010                 a += J[i*6+m]*J[i*6+n];
01011             }
01012             A.val[m][n] = a;
01013         }
01014         double b = 0;
01015         for (int32_t i=0; i<4*(int32_t)active.size(); i++) {
01016             b += J[i*6+m]*(p_residual[i]);
01017         }
01018         B.val[m][0] = b;
01019     }
01020 
01021     // perform elimination
01022     if (B.solve(A)) {
01023         bool converged = true;
01024         for (int32_t m=0; m<6; m++) {
01025             tr[m] += step_size*B.val[m][0];
01026             if (fabs(B.val[m][0])>eps)
01027                 converged = false;
01028         }
01029         if (converged)
01030             return CONVERGED;
01031         else
01032             return UPDATED;
01033     } else {
01034         return FAILED;
01035     }
01036 }
01037 
01038 void VisualOdometryStereo::computeObservations(vector<Matcher::p_match> &p_matched,vector<int32_t> &active) {
01039 
01040 
01041     // set all observations
01042     for (int32_t i=0; i<(int32_t)active.size(); i++) {
01043         p_observe[4*i+0] = p_matched[active[i]].u1c; // u1
01044         p_observe[4*i+1] = p_matched[active[i]].v1c; // v1
01045         p_observe[4*i+2] = p_matched[active[i]].u2c; // u2
01046         p_observe[4*i+3] = p_matched[active[i]].v2c; // v2
01047     }
01048 }
01049 
01050 void VisualOdometryStereo::computeResidualsAndJacobianP3p(TooN::Matrix<3,4> &tr,vector<int32_t> &active)
01051 {
01052     // extract motion parameters
01053     double tx = tr[0][0]; double ty = tr[1][0]; double tz = tr[2][0];
01054 
01055     // compute rotation matrix and derivatives
01056     double r00 =  tr[0][1]; double r01 =  tr[0][2]; double r02 =  tr[0][3];
01057     double r10 =  tr[1][1]; double r11 =  tr[1][2]; double r12 =  tr[1][3];
01058     double r20 =  tr[2][1]; double r21 =  tr[2][2]; double r22 =  tr[2][3];
01059 
01060     // loop variables
01061     double X1p,Y1p,Z1p;
01062     double X1c,Y1c,Z1c,X2c;
01063     double X1cd,Y1cd,Z1cd;
01064 
01065     // for all observations do
01066     for (int32_t i=0; i<(int32_t)active.size(); i++) {
01067 
01068         // get 3d point in previous coordinate system
01069         X1p = X[active[i]];
01070         Y1p = Y[active[i]];
01071         Z1p = Z[active[i]];
01072 
01073         // compute 3d point in current left coordinate system
01074         X1c = r00*X1p+r01*Y1p+r02*Z1p+tx;
01075         Y1c = r10*X1p+r11*Y1p+r12*Z1p+ty;
01076         Z1c = r20*X1p+r21*Y1p+r22*Z1p+tz;
01077 
01078         // weighting
01079         // 越靠近中心权重越大
01080         double weight = 1.0;
01081         if (param.reweighting)
01082             weight = 1.0/(fabs(p_observe[4*i+0]-param.calib.cu)/fabs(param.calib.cu) + 0.05);
01083 
01084         // compute 3d point in current right coordinate system
01085         X2c = X1c-param.base;
01086 
01087         // for all paramters do
01088 
01089         // set prediction (project via K)
01090         p_predict[4*i+0] = param.calib.f*X1c/Z1c+param.calib.cu; // left u
01091         p_predict[4*i+1] = param.calib.f*Y1c/Z1c+param.calib.cv; // left v
01092         p_predict[4*i+2] = param.calib.f*X2c/Z1c+param.calib.cu; // right u
01093         p_predict[4*i+3] = param.calib.f*Y1c/Z1c+param.calib.cv; // right v
01094 
01095         // set residuals
01096         p_residual[4*i+0] = weight*(p_observe[4*i+0]-p_predict[4*i+0]);
01097         p_residual[4*i+1] = weight*(p_observe[4*i+1]-p_predict[4*i+1]);
01098         p_residual[4*i+2] = weight*(p_observe[4*i+2]-p_predict[4*i+2]);
01099         p_residual[4*i+3] = weight*(p_observe[4*i+3]-p_predict[4*i+3]);
01100     }
01101 }
01102 
01103 void VisualOdometryStereo::computeResidualsAndJacobian(vector<double> &tr,vector<int32_t> &active) {
01104 
01105     // extract motion parameters
01106     double rx = tr[0]; double ry = tr[1]; double rz = tr[2];
01107     double tx = tr[3]; double ty = tr[4]; double tz = tr[5];
01108 
01109     // precompute sine/cosine
01110     double sx = sin(rx); double cx = cos(rx); double sy = sin(ry);
01111     double cy = cos(ry); double sz = sin(rz); double cz = cos(rz);
01112 
01113     // compute rotation matrix and derivatives
01114     double r00    = +cy*cz;          double r01    = -cy*sz;          double r02    = +sy;
01115     double r10    = +sx*sy*cz+cx*sz; double r11    = -sx*sy*sz+cx*cz; double r12    = -sx*cy;
01116     double r20    = -cx*sy*cz+sx*sz; double r21    = +cx*sy*sz+sx*cz; double r22    = +cx*cy;
01117     double rdrx10 = +cx*sy*cz-sx*sz; double rdrx11 = -cx*sy*sz-sx*cz; double rdrx12 = -cx*cy;
01118     double rdrx20 = +sx*sy*cz+cx*sz; double rdrx21 = -sx*sy*sz+cx*cz; double rdrx22 = -sx*cy;
01119     double rdry00 = -sy*cz;          double rdry01 = +sy*sz;          double rdry02 = +cy;
01120     double rdry10 = +sx*cy*cz;       double rdry11 = -sx*cy*sz;       double rdry12 = +sx*sy;
01121     double rdry20 = -cx*cy*cz;       double rdry21 = +cx*cy*sz;       double rdry22 = -cx*sy;
01122     double rdrz00 = -cy*sz;          double rdrz01 = -cy*cz;
01123     double rdrz10 = -sx*sy*sz+cx*cz; double rdrz11 = -sx*sy*cz-cx*sz;
01124     double rdrz20 = +cx*sy*sz+sx*cz; double rdrz21 = +cx*sy*cz-sx*sz;
01125 
01126     // loop variables
01127     double X1p,Y1p,Z1p;
01128     double X1c,Y1c,Z1c,X2c;
01129     double X1cd,Y1cd,Z1cd;
01130 
01131     // for all observations do
01132     for (int32_t i=0; i<(int32_t)active.size(); i++) {
01133 
01134         // get 3d point in previous coordinate system
01135         X1p = X[active[i]];
01136         Y1p = Y[active[i]];
01137         Z1p = Z[active[i]];
01138 
01139         // compute 3d point in current left coordinate system
01140         X1c = r00*X1p+r01*Y1p+r02*Z1p+tx;
01141         Y1c = r10*X1p+r11*Y1p+r12*Z1p+ty;
01142         Z1c = r20*X1p+r21*Y1p+r22*Z1p+tz;
01143 
01144         // weighting
01145         // 越靠近中心权重越大
01146         double weight = 1.0;
01147         if (param.reweighting)
01148             weight = 1.0/(fabs(p_observe[4*i+0]-param.calib.cu)/fabs(param.calib.cu) + 0.05);
01149 
01150         // compute 3d point in current right coordinate system
01151         X2c = X1c-param.base;
01152 
01153         // for all paramters do
01154         for (int32_t j=0; j<6; j++) {
01155 
01156             // derivatives of 3d pt. in curr. left coordinates wrt. param j
01157             switch (j) {
01158                 case 0: X1cd = 0;
01159                         Y1cd = rdrx10*X1p+rdrx11*Y1p+rdrx12*Z1p;
01160                         Z1cd = rdrx20*X1p+rdrx21*Y1p+rdrx22*Z1p;
01161                         break;
01162                 case 1: X1cd = rdry00*X1p+rdry01*Y1p+rdry02*Z1p;
01163                         Y1cd = rdry10*X1p+rdry11*Y1p+rdry12*Z1p;
01164                         Z1cd = rdry20*X1p+rdry21*Y1p+rdry22*Z1p;
01165                         break;
01166                 case 2: X1cd = rdrz00*X1p+rdrz01*Y1p;
01167                         Y1cd = rdrz10*X1p+rdrz11*Y1p;
01168                         Z1cd = rdrz20*X1p+rdrz21*Y1p;
01169                         break;
01170                 case 3: X1cd = 1; Y1cd = 0; Z1cd = 0; break;
01171                 case 4: X1cd = 0; Y1cd = 1; Z1cd = 0; break;
01172                 case 5: X1cd = 0; Y1cd = 0; Z1cd = 1; break;
01173             }
01174 
01175             // set jacobian entries (project via K)
01176             J[(4*i+0)*6+j] = weight*param.calib.f*(X1cd*Z1c-X1c*Z1cd)/(Z1c*Z1c); // left u'
01177             J[(4*i+1)*6+j] = weight*param.calib.f*(Y1cd*Z1c-Y1c*Z1cd)/(Z1c*Z1c); // left v'
01178             J[(4*i+2)*6+j] = weight*param.calib.f*(X1cd*Z1c-X2c*Z1cd)/(Z1c*Z1c); // right u'
01179             J[(4*i+3)*6+j] = weight*param.calib.f*(Y1cd*Z1c-Y1c*Z1cd)/(Z1c*Z1c); // right v'
01180         }
01181 
01182         // set prediction (project via K)
01183         p_predict[4*i+0] = param.calib.f*X1c/Z1c+param.calib.cu; // left u
01184         p_predict[4*i+1] = param.calib.f*Y1c/Z1c+param.calib.cv; // left v
01185         p_predict[4*i+2] = param.calib.f*X2c/Z1c+param.calib.cu; // right u
01186         p_predict[4*i+3] = param.calib.f*Y1c/Z1c+param.calib.cv; // right v
01187 
01188         // set residuals
01189         p_residual[4*i+0] = weight*(p_observe[4*i+0]-p_predict[4*i+0]);
01190         p_residual[4*i+1] = weight*(p_observe[4*i+1]-p_predict[4*i+1]);
01191         p_residual[4*i+2] = weight*(p_observe[4*i+2]-p_predict[4*i+2]);
01192         p_residual[4*i+3] = weight*(p_observe[4*i+3]-p_predict[4*i+3]);
01193     }
01194 }
01195 


dlut_libvo
Author(s): Zhuang Yan
autogenerated on Thu Jun 6 2019 20:03:29