ndt_matcher_d2d.cpp
Go to the documentation of this file.
00001 #include "ndt_map/ndt_cell.h"
00002 #include "ndt_map/lazy_grid.h"
00003 #include "ndt_map/pointcloud_utils.h"
00004 #include "ndt_registration/ndt_matcher_d2d.h"
00005 
00006 #include "Eigen/Eigen"
00007 #include <fstream>
00008 #include <omp.h>
00009 #include <sys/time.h>
00010 namespace lslgeneric
00011 {
00012 
00013 //#define DO_DEBUG_PROC
00014 
00015 void NDTMatcherD2D::init(bool _isIrregularGrid,
00016         bool useDefaultGridResolutions, std::vector<double> _resolutions)
00017 {
00018     Jest.setZero();
00019     Jest.block<3,3>(0,0).setIdentity();
00020     Hest.setZero();
00021     Zest.setZero();
00022     ZHest.setZero();
00023 
00024     isIrregularGrid = _isIrregularGrid;
00025     if(useDefaultGridResolutions)
00026     {
00027         resolutions.push_back(0.2);
00028         resolutions.push_back(0.5);
00029         resolutions.push_back(1);
00030         resolutions.push_back(2);
00031     }
00032     else
00033     {
00034         resolutions = _resolutions;
00035     }
00036 
00037     current_resolution = 0.1; // Argggg!!! This is very important to have initiated! (one day debugging later) :-) TODO do we need to set it to anything better?
00038     lfd1 = 1; //lfd1/(double)sourceNDT.getMyIndex()->size(); //current_resolution*2.5;
00039     lfd2 = 0.05; //0.1/current_resolution;
00040     ITR_MAX = 30;
00041     DELTA_SCORE = 10e-3*current_resolution;
00042     step_control = true;
00043     //should we try to regularize the hessian or just give up?
00044     regularize = true;
00045     //how many neighbours to use in the objective
00046     n_neighbours =2;
00047 
00048 }
00049 
00050 bool NDTMatcherD2D::match( pcl::PointCloud<pcl::PointXYZ>& target,
00051         pcl::PointCloud<pcl::PointXYZ>& source,
00052         Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor>& T ,
00053         bool useInitialGuess)
00054 {
00055 
00056     struct timeval tv_start, tv_end;
00057     struct timeval tv_start0, tv_end0;
00058     double time_load =0, time_match=0, time_combined=0;
00059 
00060     gettimeofday(&tv_start0,NULL);
00061 
00062     //initial guess
00063     pcl::PointCloud<pcl::PointXYZ> sourceCloud = source;
00064     Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> Temp, Tinit;
00065     Tinit.setIdentity();
00066     if(useInitialGuess)
00067     {
00068         lslgeneric::transformPointCloudInPlace(T,sourceCloud);
00069         Tinit = T;
00070     }
00071 
00072     T.setIdentity();
00073     bool ret = false;
00074 
00075 #if 0
00076     if(isIrregularGrid)
00077     {
00078 
00079         OctTree<PointTarget> pr1;
00080         NDTMap<PointTarget> targetNDT( &pr1 );
00081         targetNDT.loadPointCloud( target );
00082         targetNDT.computeNDTCells();
00083 
00084         OctTree<PointSource> pr2;
00085         NDTMap<PointSource> sourceNDT( &pr2 );
00086         sourceNDT.loadPointCloud( source );
00087         sourceNDT.computeNDTCells();
00088 
00089         ret = this->match( targetNDT, sourceNDT, T );
00090 
00091     }
00092     else
00093 #endif
00094     {
00095 
00096         //iterative regular grid
00097         for(int r_ctr = resolutions.size()-1; r_ctr >=0;  r_ctr--)
00098         {
00099 
00100             current_resolution = resolutions[r_ctr];
00101 
00102             LazyGrid prototypeSource(current_resolution);
00103             LazyGrid prototypeTarget(current_resolution);
00104 
00105             gettimeofday(&tv_start,NULL);
00106             NDTMap targetNDT( &prototypeTarget );
00107             targetNDT.loadPointCloud( target );
00108             targetNDT.computeNDTCells();
00109 
00110             NDTMap sourceNDT( &prototypeSource );
00111             sourceNDT.loadPointCloud( sourceCloud );
00112             sourceNDT.computeNDTCells();
00113             gettimeofday(&tv_end,NULL);
00114 
00115             time_load += (tv_end.tv_sec-tv_start.tv_sec)*1000.+(tv_end.tv_usec-tv_start.tv_usec)/1000.;
00116             Temp.setIdentity();
00117 
00118             gettimeofday(&tv_start,NULL);
00119             ret = this->match( targetNDT, sourceNDT, Temp );
00120             lslgeneric::transformPointCloudInPlace(Temp,sourceCloud);
00121             gettimeofday(&tv_end,NULL);
00122 
00123             time_match += (tv_end.tv_sec-tv_start.tv_sec)*1000.+(tv_end.tv_usec-tv_start.tv_usec)/1000.;
00124 
00125             //transform moving
00126             T = Temp*T; //ORIGINAL
00127             //T = T*Temp;
00128 
00129 #ifdef DO_DEBUG_PROC
00130             std::cout<<"RESOLUTION: "<<current_resolution<<std::endl;
00131             std::cout<<"rotation   : "<<Temp.rotation().eulerAngles(0,1,2).transpose()<<std::endl;
00132             std::cout<<"translation: "<<Temp.translation().transpose()<<std::endl;
00133             std::cout<<"--------------------------------------------------------\nOverall Transform:\n";
00134             std::cout<<"rotation   : "<<T.rotation().eulerAngles(0,1,2).transpose()<<std::endl;
00135             std::cout<<"translation: "<<T.translation().transpose()<<std::endl;
00136 
00137 #endif
00138         }
00139     }
00140     if(useInitialGuess)
00141     {
00142         T = T*Tinit;
00143     }
00144     gettimeofday(&tv_end0,NULL);
00145     time_combined = (tv_end0.tv_sec-tv_start0.tv_sec)*1000.+(tv_end0.tv_usec-tv_start0.tv_usec)/1000.;
00146     //std::cout<<"load: "<<time_load<<" match "<<time_match<<" combined "<<time_combined<<std::endl;
00147     return ret;
00148 }
00149 
00150 bool NDTMatcherD2D::match( NDTMap& targetNDT,
00151         NDTMap& sourceNDT,
00152         Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor>& T ,
00153         bool useInitialGuess)
00154 {
00155 
00156     //locals
00157     bool convergence = false;
00158     //double score=0;
00159     double score_best = INT_MAX;
00160     //double DELTA_SCORE = 0.0005;
00161     //double NORM_MAX = current_resolution, ROT_MAX = M_PI/10; //
00162     int itr_ctr = 0;
00163     //double alpha = 0.95;
00164     double step_size = 1;
00165     Eigen::Matrix<double,6,1>  pose_increment_v, scg;
00166     Eigen::MatrixXd Hessian(6,6), score_gradient(6,1); //column vectors, pose_increment_v(6,1)
00167 
00168     Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> TR, Tbest;
00169     Eigen::Vector3d transformed_vec, mean;
00170     bool ret = true;
00171     if(!useInitialGuess)
00172     {
00173         T.setIdentity();
00174     }
00175     Tbest = T;
00176 
00177 
00178     Eigen::Array<double,6,1> weights;
00179     std::vector<NDTCell*> nextNDT = sourceNDT.pseudoTransformNDT(T);
00180 
00181     //std::cout<<"pose(:,"<<1<<") = ["<<T.translation().transpose()<<" "<<T.rotation().eulerAngles(0,1,2).transpose()<<"]';\n";
00182     while(!convergence)
00183     {
00184         TR.setIdentity();
00185         Hessian.setZero();
00186         score_gradient.setZero();
00187 
00188         double score_here = derivativesNDT(nextNDT,targetNDT,score_gradient,Hessian,true);
00189         //derivativesNDT(nextNDT,targetNDT,score_gradient,Hessian,true);
00190         scg = score_gradient;
00191 //      std::cout<<"itr "<<itr_ctr<<std::endl;
00192         if(score_here < score_best) 
00193         {
00194             Tbest = T;
00195             score_best = score_here;
00196 //          std::cout<<"best score "<<score_best<<" at "<<itr_ctr<<std::endl;
00197         }
00198 
00199 //      Hessian = Hessian + score_gradient.norm()*Eigen::Matrix<double,6,6>::Identity();
00200         Eigen::SelfAdjointEigenSolver<Eigen::Matrix<double,6,6> > Sol (Hessian);
00201         Eigen::Matrix<double,6,1> evals = Sol.eigenvalues().real();
00202         double minCoeff = evals.minCoeff();
00203         double maxCoeff = evals.maxCoeff();
00204         if(minCoeff < 0)  //|| evals.minCoeff()) // < 10e-5*evals.maxCoeff()) 
00205         {
00206             if(regularize) {
00207                 Eigen::Matrix<double,6,6> evecs = Sol.eigenvectors().real();
00208                 double regularizer = score_gradient.norm();
00209                 regularizer = regularizer + minCoeff > 0 ? regularizer : 0.001*maxCoeff - minCoeff;
00210                 //double regularizer = 0.001*maxCoeff - minCoeff;
00211                 Eigen::Matrix<double,6,1> reg;
00212                 //ugly
00213                 reg<<regularizer,regularizer,regularizer,regularizer,regularizer,regularizer;
00214                 evals += reg;
00215                 Eigen::Matrix<double,6,6> Lam;
00216                 Lam = evals.asDiagonal();
00217                 Hessian = evecs*Lam*(evecs.transpose());
00218             } else {
00219                 if(score_here > score_best) 
00220                 {
00221                     T = Tbest;
00222                 }
00223                 //de-alloc nextNDT
00224                 for(unsigned int i=0; i<nextNDT.size(); i++)
00225                 {
00226                     if(nextNDT[i]!=NULL)
00227                         delete nextNDT[i];
00228                 }
00229                 return true;
00230             }
00231 //            std::cerr<<"regularizing\n";
00232         }
00233 //      std::cout<<"s("<<itr_ctr+1<<") = "<<score_here<<";\n";
00234 //      std::cout<<"H(:,:,"<<itr_ctr+1<<")  =  ["<< Hessian<<"];\n"<<std::endl;                           //
00235 //      std::cout<<"grad (:,"<<itr_ctr+1<<")= ["<<score_gradient.transpose()<<"];"<<std::endl;         //
00236         if (score_gradient.norm()<= DELTA_SCORE)
00237         {
00238 //          std::cout<<"incr(:,"<<itr_ctr+1<<") = [0 0 0 0 0 0]';\n";
00239 //            std::cout<<"\%gradient vanished\n";
00240             if(score_here > score_best) 
00241             {
00242 //              std::cout<<"crap iterations, best was "<<score_best<<" last was "<<score_here<<std::endl;
00243                 T = Tbest;
00244             }
00245             //de-alloc nextNDT
00246             for(unsigned int i=0; i<nextNDT.size(); i++)
00247             {
00248                 if(nextNDT[i]!=NULL)
00249                     delete nextNDT[i];
00250             }
00251 //          std::cout<<"itr "<<itr_ctr<<" dScore "<< 0 <<std::endl;
00252             return true;
00253         }
00254 //      pose_increment_v.block<3,1>(0,0) = -Hessian.block<3,3>(0,0).ldlt().solve(score_gradient.block<3,1>(0,0));
00255 //      pose_increment_v.block<3,1>(3,0) = -Hessian.block<3,3>(3,3).ldlt().solve(score_gradient.block<3,1>(3,0));
00256         /*
00257                 Eigen::SelfAdjointEigenSolver<Eigen::Matrix<double,6,6> > Sol (Hessian);
00258                 Eigen::Matrix<double,6,1> evals = Sol.eigenvalues().real();
00259                 if(evals.minCoeff() < 0 ) {
00260                     std::cout<<"\%negative hessian\n";
00261                     std::cout<<"incr(:,"<<itr_ctr+1<<") = [0 0 0 0 0 0]';\n";
00262                     //de-alloc nextNDT
00263                     for(unsigned int i=0; i<nextNDT.size(); i++) {
00264                         if(nextNDT[i]!=NULL)
00265                             delete nextNDT[i];
00266                     }
00267                     return true;
00268                 } else {
00269                 }
00270         */
00271 
00272         pose_increment_v = -Hessian.ldlt().solve(score_gradient);
00273         //pose_increment_v =-0.0001*scg; //
00274         /*      if(itr_ctr%2) {
00275                     pose_increment_v(0) = 0;
00276                     pose_increment_v(1) = 0;
00277                     pose_increment_v(2) = 0;
00278                 } else {
00279                 pose_increment_v(3) = 0;
00280                 pose_increment_v(4) = 0;
00281                 pose_increment_v(5) = 0;
00282                 }
00283                 */
00284         /*
00285         weights = scg.array().abs();
00286         weights.block(0,0,3,1) /= weights.block(0,0,3,1).maxCoeff();
00287         weights.block(3,0,3,1) /= weights.block(3,0,3,1).maxCoeff();
00288         std::cout<<"w = ["<<weights<<"];\n";
00289         std::cout<<"pose_increment_v= ["<<pose_increment_v.transpose()<<"];"<<std::endl;       //
00290         pose_increment_v = weights*pose_increment_v.array();
00291         //if(pose_increment_v.norm() > 1)
00292         //    pose_increment_v.normalize();
00293         //scg.normalize();
00294         //pose_increment_v = -0.00001*scg;
00295          */
00296         /*
00297         pose_increment_v /= pv;
00298         */
00299 
00300         //pose_increment_v = Hessian.jacobiSvd(Eigen::ComputeFullU|Eigen::ComputeFullV).solve(-score_gradient);
00301         double dginit = pose_increment_v.dot(scg);
00302         if(dginit > 0)
00303         {
00304 //          std::cout<<"incr(:,"<<itr_ctr+1<<") = ["<<pose_increment_v.transpose()<<"]';\n";
00305 //          std::cout<<"\%dg  =  "<<dginit<<std::endl;     //
00306 //            std::cout<<"\%can't decrease in this direction any more, done \n";
00307             //de-alloc nextNDT
00308             if(score_here > score_best) 
00309             {
00310 //              std::cout<<"crap iterations, best was "<<score_best<<" last was "<<score_here<<std::endl;
00311                 T = Tbest;
00312             }
00313             for(unsigned int i=0; i<nextNDT.size(); i++)
00314             {
00315                 if(nextNDT[i]!=NULL)
00316                     delete nextNDT[i];
00317             }
00318 //          std::cout<<"itr "<<itr_ctr<<" dScore "<< 0 <<std::endl;
00319             return true;
00320         }
00321 //      std::cout<<"score("<<itr_ctr+1<<") = "<<score_here<<";\n";
00322         /*
00323                 */
00324 
00325 
00326 //      if(dginit > 0) {
00327 //          std::cout<<"pose_increment_v= ["<<pose_increment_v.transpose()<<"]"<<std::endl;       //
00328 //          std::cout<<"dg  =  "<<dginit<<std::endl;     //
00329 //      }
00330         /*
00331         */
00332         /*
00333                 std::cout<<"pose_increment_v= ["<<pose_increment_v.transpose()<<"]"<<std::endl;       //
00334                 pose_increment_v = Hessian.jacobiSvd(Eigen::ComputeFullU|Eigen::ComputeFullV).solve(-score_gradient);
00335                 std::cout<<"dg    "<<pose_increment_v.dot(score_gradient)<<std::endl;     //
00336                 //make the initial increment reasonable...
00337                 //cout<<"incr_init = ["<<pose_increment_v.transpose()<<"]"<<endl;
00338                 double pnorm = sqrt(pose_increment_v(0)*pose_increment_v(0) + pose_increment_v(1)*pose_increment_v(1)
00339                                     +pose_increment_v(2)*pose_increment_v(2));
00340                 if(pnorm > NORM_MAX) {
00341                     pose_increment_v(0) = NORM_MAX*pose_increment_v(0)/pnorm;
00342                     pose_increment_v(1) = NORM_MAX*pose_increment_v(1)/pnorm;
00343                     pose_increment_v(2) = NORM_MAX*pose_increment_v(2)/pnorm;
00344                 }
00345                 pose_increment_v(3) = normalizeAngle(pose_increment_v(3));
00346                 pose_increment_v(3) = (pose_increment_v(3) > ROT_MAX) ? ROT_MAX : pose_increment_v(3);
00347                 pose_increment_v(3) = (pose_increment_v(3) < -ROT_MAX) ? -ROT_MAX : pose_increment_v(3);
00348                 pose_increment_v(4) = normalizeAngle(pose_increment_v(4));
00349                 pose_increment_v(4) = (pose_increment_v(4) > ROT_MAX) ? ROT_MAX : pose_increment_v(4);
00350                 pose_increment_v(4) = (pose_increment_v(4) < -ROT_MAX) ? -ROT_MAX : pose_increment_v(4);
00351                 pose_increment_v(5) = normalizeAngle(pose_increment_v(5));
00352                 pose_increment_v(5) = (pose_increment_v(5) > ROT_MAX) ? ROT_MAX : pose_increment_v(5);
00353                 pose_increment_v(5) = (pose_increment_v(5) < -ROT_MAX) ? -ROT_MAX : pose_increment_v(5);
00354         //      cout<<"H  =  ["<<Hessian<<"]"<<endl;
00355         //      cout<<"grad= ["<<score_gradient.transpose()<<"]"<<endl;
00356         //      cout<<"dg    "<<pose_increment_v.dot(score_gradient)<<endl;
00357 
00358         */
00359         //check direction here:
00360 
00361         if(step_control) {
00362             step_size = lineSearchMT(pose_increment_v,nextNDT,targetNDT);
00363         } else {
00364             step_size = 1;
00365         }
00366         pose_increment_v = step_size*pose_increment_v;
00367         //std::cout<<"\%iteration "<<itr_ctr<<" pose norm "<<(pose_increment_v.norm())<<" score "<<score_here<<" step "<<step_size<<std::endl;
00368         /*
00369         pose_increment_v(2) = 0;
00370         pose_increment_v(3) = 0;
00371         pose_increment_v(4) = 0;
00372         pose_increment_v(5) = 0;
00373         */
00374 
00375 
00376         TR.setIdentity();
00377         TR =  Eigen::Translation<double,3>(pose_increment_v(0),pose_increment_v(1),pose_increment_v(2))*
00378               Eigen::AngleAxis<double>(pose_increment_v(3),Eigen::Vector3d::UnitX()) *
00379               Eigen::AngleAxis<double>(pose_increment_v(4),Eigen::Vector3d::UnitY()) *
00380               Eigen::AngleAxis<double>(pose_increment_v(5),Eigen::Vector3d::UnitZ()) ;
00381 
00382         //std::cout<<"incr= ["<<pose_increment_v.transpose()<<"]"<<std::endl;
00383         //transform source NDT
00384         T = TR*T;
00385 //      std::cout<<"incr(:,"<<itr_ctr+1<<") = ["<<pose_increment_v.transpose()<<"]';\n";
00386 //      std::cout<<"pose(:,"<<itr_ctr+2<<") = ["<<T.translation().transpose()<<" "<<T.rotation().eulerAngles(0,1,2).transpose()<<"]';\n";
00387 
00388         for(unsigned int i=0; i<nextNDT.size(); i++)
00389         {
00390             //TRANSFORM
00391             Eigen::Vector3d meanC = nextNDT[i]->getMean();
00392             Eigen::Matrix3d covC = nextNDT[i]->getCov();
00393             meanC = TR*meanC;
00394             covC = TR.rotation()*covC*TR.rotation().transpose();
00395             nextNDT[i]->setMean(meanC);
00396             nextNDT[i]->setCov(covC);
00397         }
00398 
00399         if(itr_ctr>0)
00400         {
00401             convergence = ((pose_increment_v.norm()) < DELTA_SCORE);
00402             //convergence = ((score_gradient.norm()) < DELTA_SCORE);
00403         }
00404         if(itr_ctr>ITR_MAX)
00405         {
00406             convergence = true;
00407             ret = false;
00408         }
00409         itr_ctr++;
00410         //step_size *= alpha;
00411         //std::cout<<"step size "<<step_size<<std::endl;
00412     }
00413     
00414 //    std::cout<<"itr "<<itr_ctr<<" dScore "<< pose_increment_v.norm()<<std::endl;
00415     //std::vector<NDTCell<PointSource>*> nextNDT = sourceNDT.pseudoTransformNDT(T);
00416     score_gradient.setZero();
00417     double score_here = derivativesNDT(nextNDT,targetNDT,score_gradient,Hessian,false);
00418     if(score_here > score_best) 
00419     {
00420 //      std::cout<<"crap iterations, best was "<<score_best<<" last was "<<score_here<<std::endl;
00421         T = Tbest;
00422     }
00423     for(unsigned int i=0; i<nextNDT.size(); i++)
00424     {
00425         if(nextNDT[i]!=NULL)
00426             delete nextNDT[i];
00427     }
00428 
00429 //    std::cout<<"incr(:,"<<itr_ctr+1<<") = [0 0 0 0 0 0]';\n";
00430 //    std::cout<<"grad(:,"<<itr_ctr+1<<") = [0 0 0 0 0 0]';\n";
00431     //std::cout<<"res "<<current_resolution<<" itr "<<itr_ctr<<std::endl;
00432 
00433 //    this->finalscore = score/NUMBER_OF_ACTIVE_CELLS;
00434 
00435     return ret;
00436 }
00437 
00438 //iteratively update the score gradient and hessian
00439 bool NDTMatcherD2D::update_gradient_hessian_local(
00440     Eigen::MatrixXd &score_gradient,
00441     Eigen::MatrixXd &Hessian,
00442     const Eigen::Vector3d & x,
00443     const Eigen::Matrix3d & B,
00444     const double &likelihood,
00445     const Eigen::Matrix<double,3,6> &_Jest,
00446     const Eigen::Matrix<double,18,6> &_Hest,
00447     const Eigen::Matrix<double,3,18> &_Zest,
00448     const Eigen::Matrix<double,18,18> &_ZHest,
00449     bool computeHessian)
00450 {
00451 
00452 
00453     //vars for gradient
00454     Eigen::Matrix<double,6,1> _xtBJ, _xtBZBx, _Q;
00455     //vars for hessian
00456     Eigen::Matrix<double,6,6> _xtBZBJ, _xtBH, _xtBZBZBx, _xtBZhBx;
00457     Eigen::Matrix<double,1,3> _TMP1, _xtB;
00458 
00459     _xtBJ.setZero();
00460     _xtBZBx.setZero();
00461     _Q.setZero();
00462     _xtBZBJ.setZero();
00463     _xtBH.setZero();
00464     _xtBZBZBx.setZero();
00465     _xtBZhBx.setZero();
00466     _TMP1.setZero();
00467     _xtB.setZero();
00468 
00469     _xtB = x.transpose()*B;
00470     _xtBJ = _xtB*_Jest;
00471 
00472     for(unsigned int i=0; i<6; i++)
00473     {
00474         _TMP1 = _xtB*_Zest.block<3,3>(0,3*i)*B;
00475         _xtBZBx(i) = _TMP1*x;
00476         if(computeHessian)
00477         {
00478             _xtBZBJ.col(i) = (_TMP1*_Jest).transpose(); //-
00479             for(unsigned int j=0; j<6; j++)
00480             {
00481                 _xtBH(i,j) = _xtB*_Hest.block<3,1>(3*i,j);
00482                 _xtBZBZBx(i,j) = _TMP1*_Zest.block<3,3>(0,3*j)*B*x;
00483                 _xtBZhBx(i,j) = _xtB*_ZHest.block<3,3>(3*i,3*j)*B*x;
00484             }
00485         }
00486     }
00487     _Q = 2*_xtBJ-_xtBZBx;
00488     double factor = -(lfd2/2)*likelihood;
00489     score_gradient += _Q*factor;
00490 
00491     if(computeHessian)
00492     {
00493         Hessian += factor*(2*_Jest.transpose()*B*_Jest+2*_xtBH -_xtBZhBx -2*_xtBZBJ.transpose()
00494                            -2*_xtBZBJ +_xtBZBZBx +_xtBZBZBx.transpose() -lfd2*_Q*_Q.transpose()/2 ); // + Eigen::Matrix<double,6,6>::Identity();
00495 
00496     }
00497     return true;
00498 }
00499 
00500 bool NDTMatcherD2D::update_gradient_hessian(
00501     Eigen::MatrixXd &score_gradient,
00502     Eigen::MatrixXd &Hessian,
00503     const Eigen::Vector3d & x,
00504     const Eigen::Matrix3d & B,
00505     const double &likelihood,
00506     bool computeHessian)
00507 {
00508 
00509     /*
00510         double lmax = 1;
00511         if(fabsf(likelihood) > lmax) {
00512         return false;
00513         }
00514          */
00515 
00516     Eigen::MatrixXd Hloc(6,6), sg(6,1);
00517 
00518     Hloc.setZero();
00519     sg.setZero();
00520     xtBJ.setZero();
00521     xtBZBx.setZero();
00522     Q.setZero();
00523     JtBJ.setZero();
00524     xtBZBJ.setZero();
00525     xtBH.setZero();
00526     xtBZBZBx.setZero();
00527     xtBZhBx.setZero();
00528     TMP1.setZero();
00529     xtB.setZero();
00530 
00531     xtB = x.transpose()*B;
00532     xtBJ = xtB*Jest;
00533 
00534     for(unsigned int i=0; i<6; i++)
00535     {
00536         TMP1 = xtB*Zest.block<3,3>(0,3*i)*B;
00537         xtBZBx(i) = TMP1*x;
00538         if(computeHessian)
00539         {
00540             xtBZBJ.col(i) = (TMP1*Jest).transpose(); //-
00541             for(unsigned int j=0; j<6; j++)
00542             {
00543                 xtBH(i,j) = xtB*Hest.block<3,1>(3*i,j);
00544                 xtBZBZBx(i,j) = TMP1*Zest.block<3,3>(0,3*j)*B*x;
00545                 xtBZhBx(i,j) = xtB*ZHest.block<3,3>(3*i,3*j)*B*x;
00546             }
00547         }
00548     }
00549     Q = 2*xtBJ-xtBZBx;
00550     /*
00551     std::cout<<"Zest = ["<<Zest<<"];\n";
00552     std::cout<<"Jest = ["<<Jest<<"];\n";
00553     std::cout<<"Q = ["<<Q.transpose()<<"]';\n";
00554     std::cout<<"xtBJ = ["<<xtBJ.transpose()<<"]';\n";
00555     std::cout<<"xtBZBx = ["<<xtBZBx.transpose()<<"]';\n";
00556     std::cout<<"Hest = ["<<Hest<<"];\n";
00557     std::cout<<"ZHest = ["<<ZHest<<"];\n";
00558     std::cout<<"xtBZBJ = ["<<xtBZBJ<<"];\n";
00559     std::cout<<"xtBH = ["<<xtBH<<"];\n";
00560     std::cout<<"xtBZBZBx = ["<<xtBZBZBx<<"];\n";
00561     std::cout<<"xtBZhBx = ["<<xtBZhBx<<"];\n";
00562     */
00563     //double factor = -(lfd2/2)*pow(1 - pow(likelihood/lmax,2),2);
00564     double factor = -(lfd2/2)*likelihood;
00565     sg = Q*factor;
00566 //    double weight = pow(1 - pow(likelihood,2),2)
00567     score_gradient += sg;
00568 
00569     if(computeHessian)
00570     {
00571         Hloc= factor*(2*Jest.transpose()*B*Jest+2*xtBH -xtBZhBx -2*xtBZBJ.transpose()
00572                       -2*xtBZBJ +xtBZBZBx +xtBZBZBx.transpose() -lfd2*Q*Q.transpose()/2 ); // + Eigen::Matrix<double,6,6>::Identity();
00573         Hessian += Hloc;// + Eigen::Matrix<double,6,6>::Identity();
00574         //Hessian += Jest.transpose()*Jest;
00575     }
00576 
00577     /*
00578      std::cout<<"B = ["<<B<<"];\n x = ["<<x.transpose()<<"]';\n";
00579      std::cout<<"l = "<<likelihood<<";\nscg = ["
00580     <<sg.transpose()<<"]';\n H = ["
00581     << Hloc<<"];\n H2 = ["<<Jest.transpose()*Jest<<"];\n H3 = ["
00582     << sg*sg.transpose() <<"];\n";
00583      */
00584     return true;
00585 
00586 }
00587 
00588 //pre-computes the derivative matrices Jest, Hest, Zest, ZHest
00589 void NDTMatcherD2D::computeDerivativesLocal(Eigen::Vector3d &x, Eigen::Matrix3d C1,
00590         Eigen::Matrix<double,3,6> &_Jest,
00591         Eigen::Matrix<double,18,6> &_Hest,
00592         Eigen::Matrix<double,3,18> &_Zest,
00593         Eigen::Matrix<double,18,18> &_ZHest,
00594         bool computeHessian)
00595 {
00596 
00597     _Jest(0,4) = x(2);
00598     _Jest(0,5) = -x(1);
00599     _Jest(1,3) = -x(2);
00600     _Jest(1,5) = x(0);
00601     _Jest(2,3) = x(1);
00602     _Jest(2,4) = -x(0);
00603 
00604     Eigen::Matrix3d myBlock;
00605     //_Zest
00606     myBlock<<
00607            0,       -C1(0,2),      C1(0,1),
00608                     -C1(0,2),     -2*C1(1,2), -C1(2,2) + C1(1,1),
00609                     C1(0,1), -C1(2,2) + C1(1,1),    2*C1(1,2);
00610     _Zest.block<3,3>(0,9) = myBlock;
00611     myBlock<<
00612            2*C1(0,2), C1(1,2), -C1(0,0) + C1(2,2),
00613              C1(1,2),    0,       -C1(0,1),
00614              -C1(0,0) + C1(2,2),  -C1(0,1),     -2*C1(0,2);
00615     _Zest.block<3,3>(0,12) = myBlock;
00616     myBlock<<
00617            -2*C1(0,1), -C1(1,1) + C1(0,0),  -C1(1,2),
00618            -C1(1,1) + C1(0,0),    2*C1(0,1), C1(0,2),
00619            -C1(1,2),      C1(0,2),    0;
00620     _Zest.block<3,3>(0,15) = myBlock;
00621 
00622     if(computeHessian)
00623     {
00624         Eigen::Vector3d a,b,c,d,e,f;
00625         a<<0,-x(1),-x(2);
00626         b<<0,x(0),0;
00627         c<<0,0,x(0);
00628         d<<-x(0),0,-x(2);
00629         e<<0,0,x(1);
00630         f<<-x(0),-x(1),0;
00631         //Hest
00632         _Hest.block<3,1>(9,3) = a;
00633         _Hest.block<3,1>(12,3) = b;
00634         _Hest.block<3,1>(15,3) = c;
00635         _Hest.block<3,1>(9,4) = b;
00636         _Hest.block<3,1>(12,4) = d;
00637         _Hest.block<3,1>(15,4) = e;
00638         _Hest.block<3,1>(9,5) = c;
00639         _Hest.block<3,1>(12,5) = e;
00640         _Hest.block<3,1>(15,5) = f;
00641 
00642         //_ZHest
00643         myBlock<<
00644                0,          -C1(0,1),          -C1(0,2),
00645                            -C1(0,1), 2*C1(2,2) - 2*C1(1,1),        -4*C1(1,2),
00646                            -C1(0,2),        -4*C1(1,2), 2*C1(1,1) - 2*C1(2,2);
00647         _ZHest.block<3,3>(9,9) =   myBlock;
00648 
00649         myBlock<<
00650                0, C1(0,0) - C1(2,2),    C1(1,2),
00651                   C1(0,0) - C1(2,2),     2*C1(0,1),  2*C1(0,2),
00652                   C1(1,2),     2*C1(0,2), -2*C1(0,1);
00653         _ZHest.block<3,3>(9,12) = myBlock;
00654 
00655         myBlock<<
00656                0,    C1(1,2), C1(0,0) - C1(1,1),
00657                      C1(1,2), -2*C1(0,2),     2*C1(0,1),
00658                      C1(0,0) - C1(1,1),  2*C1(0,1),     2*C1(0,2);
00659         _ZHest.block<3,3>(9,15) = myBlock;
00660 
00661         myBlock<<
00662                2*C1(2,2) - 2*C1(0,0), -C1(0,1),        -4*C1(0,2),
00663                  -C1(0,1),    0,          -C1(1,2),
00664                  -4*C1(0,2), -C1(1,2), 2*C1(0,0) - 2*C1(2,2);
00665         _ZHest.block<3,3>(12,12) = myBlock;
00666 
00667         myBlock<<
00668                -2*C1(1,2),       C1(0,2),     2*C1(0,1),
00669                C1(0,2),         0, C1(1,1) - C1(0,0),
00670                2*C1(0,1), C1(1,1) - C1(0,0),     2*C1(1,2);
00671         _ZHest.block<3,3>(12,15) = myBlock;
00672 
00673         myBlock<<
00674                2*C1(1,1) - 2*C1(0,0),        -4*C1(0,1), -C1(0,2),
00675                  -4*C1(0,1), 2*C1(0,0) - 2*C1(1,1), -C1(1,2),
00676                  -C1(0,2),          -C1(1,2),    0;
00677         _ZHest.block<3,3>(15,15)= myBlock;
00678 
00679         _ZHest.block<3,3>(12,9) =    _ZHest.block<3,3>(9,12);
00680         _ZHest.block<3,3>(15,9) =    _ZHest.block<3,3>(9,15);
00681         _ZHest.block<3,3>(15,12)=    _ZHest.block<3,3>(12,15);
00682     }
00683 }
00684 
00685 void NDTMatcherD2D::computeDerivatives(Eigen::Vector3d &x, Eigen::Matrix3d C1, bool computeHessian)
00686 {
00687 
00688     Jest(0,4) = x(2);
00689     Jest(0,5) = -x(1);
00690     Jest(1,3) = -x(2);
00691     Jest(1,5) = x(0);
00692     Jest(2,3) = x(1);
00693     Jest(2,4) = -x(0);
00694 
00695     Eigen::Matrix3d myBlock;
00696     //Zest
00697     myBlock<<
00698            0,       -C1(0,2),      C1(0,1),
00699                     -C1(0,2),     -2*C1(1,2), -C1(2,2) + C1(1,1),
00700                     C1(0,1), -C1(2,2) + C1(1,1),    2*C1(1,2);
00701     Zest.block<3,3>(0,9) = myBlock;
00702     myBlock<<
00703            2*C1(0,2), C1(1,2), -C1(0,0) + C1(2,2),
00704              C1(1,2),    0,       -C1(0,1),
00705              -C1(0,0) + C1(2,2),  -C1(0,1),     -2*C1(0,2);
00706     Zest.block<3,3>(0,12) = myBlock;
00707     myBlock<<
00708            -2*C1(0,1), -C1(1,1) + C1(0,0),  -C1(1,2),
00709            -C1(1,1) + C1(0,0),    2*C1(0,1), C1(0,2),
00710            -C1(1,2),      C1(0,2),    0;
00711     Zest.block<3,3>(0,15) = myBlock;
00712 
00713     if(computeHessian)
00714     {
00715         Eigen::Vector3d a,b,c,d,e,f;
00716         a<<0,-x(1),-x(2);
00717         b<<0,x(0),0;
00718         c<<0,0,x(0);
00719         d<<-x(0),0,-x(2);
00720         e<<0,0,x(1);
00721         f<<-x(0),-x(1),0;
00722         //Hest
00723         Hest.block<3,1>(9,3) = a;
00724         Hest.block<3,1>(12,3) = b;
00725         Hest.block<3,1>(15,3) = c;
00726         Hest.block<3,1>(9,4) = b;
00727         Hest.block<3,1>(12,4) = d;
00728         Hest.block<3,1>(15,4) = e;
00729         Hest.block<3,1>(9,5) = c;
00730         Hest.block<3,1>(12,5) = e;
00731         Hest.block<3,1>(15,5) = f;
00732 
00733         //ZHest
00734         myBlock<<
00735                0,          -C1(0,1),          -C1(0,2),
00736                            -C1(0,1), 2*C1(2,2) - 2*C1(1,1),        -4*C1(1,2),
00737                            -C1(0,2),        -4*C1(1,2), 2*C1(1,1) - 2*C1(2,2);
00738         ZHest.block<3,3>(9,9) =   myBlock;
00739 
00740         myBlock<<
00741                0, C1(0,0) - C1(2,2),    C1(1,2),
00742                   C1(0,0) - C1(2,2),     2*C1(0,1),  2*C1(0,2),
00743                   C1(1,2),     2*C1(0,2), -2*C1(0,1);
00744         ZHest.block<3,3>(9,12) = myBlock;
00745 
00746         myBlock<<
00747                0,    C1(1,2), C1(0,0) - C1(1,1),
00748                      C1(1,2), -2*C1(0,2),     2*C1(0,1),
00749                      C1(0,0) - C1(1,1),  2*C1(0,1),     2*C1(0,2);
00750         ZHest.block<3,3>(9,15) = myBlock;
00751 
00752         myBlock<<
00753                2*C1(2,2) - 2*C1(0,0), -C1(0,1),        -4*C1(0,2),
00754                  -C1(0,1),    0,          -C1(1,2),
00755                  -4*C1(0,2), -C1(1,2), 2*C1(0,0) - 2*C1(2,2);
00756         ZHest.block<3,3>(12,12) = myBlock;
00757 
00758         myBlock<<
00759                -2*C1(1,2),       C1(0,2),     2*C1(0,1),
00760                C1(0,2),         0, C1(1,1) - C1(0,0),
00761                2*C1(0,1), C1(1,1) - C1(0,0),     2*C1(1,2);
00762         ZHest.block<3,3>(12,15) = myBlock;
00763 
00764         myBlock<<
00765                2*C1(1,1) - 2*C1(0,0),        -4*C1(0,1), -C1(0,2),
00766                  -4*C1(0,1), 2*C1(0,0) - 2*C1(1,1), -C1(1,2),
00767                  -C1(0,2),          -C1(1,2),    0;
00768         ZHest.block<3,3>(15,15)= myBlock;
00769 
00770         ZHest.block<3,3>(12,9) =    ZHest.block<3,3>(9,12);
00771         ZHest.block<3,3>(15,9) =    ZHest.block<3,3>(9,15);
00772         ZHest.block<3,3>(15,12)=    ZHest.block<3,3>(12,15);
00773     }
00774 }
00775 
00776 double NDTMatcherD2D::scoreNDT(std::vector<NDTCell*> &sourceNDT, NDTMap &targetNDT)
00777 {
00778     NUMBER_OF_ACTIVE_CELLS = 0;
00779     NDTCell *cell;
00780     Eigen::Vector3d transformed, eps;
00781     Eigen::Vector3d meanMoving, meanFixed;
00782     Eigen::Matrix3d CMoving, CFixed, CSum, Cinv, R;
00783 //      eps<<0.01,0.01,0.01;
00784     bool exists = false;
00785     double det = 0;
00786     double score_here = 0;
00787 
00788     pcl::PointXYZ point;
00789     for(unsigned int i=0; i<sourceNDT.size(); i++)
00790     {
00791         meanMoving = sourceNDT[i]->getMean();
00792         CMoving= sourceNDT[i]->getCov();
00793         point.x = meanMoving(0);
00794         point.y = meanMoving(1);
00795         point.z = meanMoving(2);
00796         std::vector<NDTCell*> cells = targetNDT.getCellsForPoint(point,2); //targetNDT.getAllCells(); //
00797         for(unsigned int j=0; j<cells.size(); j++)
00798         {
00799             cell = cells[j];
00800             if(cell == NULL)
00801             {
00802                 continue;
00803             }
00804             if(cell->hasGaussian_)
00805             {
00806                 transformed = meanMoving - cell->getMean();
00807                 CFixed = cell->getCov();
00808                 CSum = (CFixed+CMoving);
00809                 CSum.computeInverseAndDetWithCheck(Cinv,det,exists);
00810                 if(!exists)
00811                 {
00812                     continue;
00813                 }
00814                 double l = (transformed).dot(Cinv*(transformed));// + (eps).dot(Cinv*(eps));
00815                 if(l*0 != 0)
00816                 {
00817                     continue;
00818                 }
00819                 //if(l > 120) continue;
00820                 double sh = -lfd1*(exp(-lfd2*l/2));
00821                 NUMBER_OF_ACTIVE_CELLS++;
00822                 score_here += sh;
00823                 cell = NULL;
00824             }
00825             else
00826             {
00827                 //delete cell;
00828                 //std::cout << "had not gaussian!" << std::endl;
00829             }
00830         }
00831     }
00832 
00833     return score_here;
00834 }
00835 
00836 double NDTMatcherD2D::scoreNDT_OM(NDTMap &sourceNDT, NDTMap &targetNDT)
00837 {
00838     NUMBER_OF_ACTIVE_CELLS = 0;
00839     Eigen::Vector3d transformed;
00840     Eigen::Vector3d meanMoving, meanFixed;
00841     Eigen::Matrix3d CMoving, CFixed, CSum, Cinv, R;
00842     bool exists = false;
00843     double det = 0;
00844     double score_here = 0;
00845     double importance_free = 0.1;
00846 
00847     pcl::PointXYZ point;
00848     LazyGrid* lz = dynamic_cast<LazyGrid*> (sourceNDT.getMyIndex());
00849     if(lz==NULL) return INT_MAX;
00850     std::vector<NDTCell*>::iterator it = lz->begin();
00851 
00852     //std::vector<NDTCell<PointSource>*> source = sourceNDT.getAllInitializedCells();
00853 
00854     //for(unsigned int i=0; i<source.size(); i++) {
00855     while(it!=lz->end()) {
00856         if(*it == NULL) {
00857             it++;
00858             continue;
00859         }
00860         NDTCell* source =(*it);
00861         if(source==NULL) {
00862             it++;
00863             continue;
00864         }
00865         source->consistency_score = 0;
00866         NDTCell* cell=NULL;
00867         point = source->getCenter();
00868         //SWITCHME
00869         std::vector<NDTCell*> all_cells = targetNDT.getCellsForPoint(point,2,false);
00870 
00871         for(unsigned int j=0; j<all_cells.size(); j++) {
00872             cell = all_cells[j];
00873             if(cell == NULL) {
00874                 it++;
00875                 continue;
00876             }
00877             double o1,o2;
00878             o1 = source->getOccupancyRescaled();
00879             o2 = cell->getOccupancyRescaled();
00880             //std::cout<<"o1 "<<o1<<" o2 "<<o2<<std::endl;
00881 
00882             if(source->hasGaussian_) {
00883                 meanMoving = source->getMean();
00884                 CMoving= source->getCov();
00885                 //point.x = meanMoving(0); point.y = meanMoving(1); point.z = meanMoving(2);
00886                 //targetNDT.getCellForPoint(point,cell,false);
00887                 if(cell->hasGaussian_) {
00888                     //both have Gaussians
00889                     transformed = meanMoving - cell->getMean();
00890                     CFixed = cell->getCov();
00891                     CSum = (CFixed+CMoving);
00892                     CSum.computeInverseAndDetWithCheck(Cinv,det,exists);
00893                     if(!exists)
00894                     {
00895                         it++;
00896                         continue;
00897                     }
00898                     double l = (transformed).dot(Cinv*(transformed));
00899                     if(l*0 != 0) {
00900                         it++;
00901                         continue;
00902                     }
00903                     double sh = -lfd1*(exp(-lfd2*l/2));
00904                     //std::cout<<"sh: "<<sh<<std::endl;
00905                     score_here += o1*o2*sh;
00906                     //SWITCHME
00907                     //source->consistency_score += o1*o2*sh;
00908                     source->consistency_score += -o1*o2*sh;
00909                 }
00910             }
00911             //add the part of score updates based on occupancy alone
00912             pcl::PointXYZ cen1 = cell->getCenter();
00913             pcl::PointXYZ cen2 = source->getCenter();
00914             double cell_dist = std::sqrt(pow(cen1.x-cen2.x,2)+pow(cen1.y-cen2.y,2)+pow(cen1.z-cen2.z,2));
00915             double lambda = 1 - cell_dist/(cell->getDiagonal());
00916             lambda = lambda < 0 ? 0 : importance_free*lambda;
00917             //std::cout<<"lam "<<lambda<<" comp "<<-lambda*((1-o1)*(1-o2) - o1*(1-o2) -o2*(1-o1))<<std::endl;
00918             score_here += -lambda*((1-o1)*(1-o2) - o1*(1-o2) -o2*(1-o1));
00919 
00920             //SWITCHME
00921             //source->consistency_score += -lambda*((1-o1)*(1-o2) - o1*(1-o2) -o2*(1-o1));
00922             double ll = cell->isInside(cen2) ? 1 : 0;
00923             //std::cout<<"j "<<j<<" sc "<<source->consistency_score<<" ll "<<ll<<" incr "<<ll*((1-o1)*(1-o2) - o1*(1-o2) -o2*(1-o1))<<std::endl;
00924             source->consistency_score += ll*((1-o1)*(1-o2) - o1*(1-o2) -o2*(1-o1));
00925         }
00926         it++;
00927     }
00928 //cleanup
00929     /*
00930     for(unsigned int i=0; i<source.size(); i++) {
00931         if(source[i]==NULL) {
00932         continue;
00933         }
00934         delete source[i];
00935         source[i] = NULL;
00936     }
00937     */
00938     return score_here;
00939 }
00940 
00947 double NDTMatcherD2D::scoreNDTPositive(std::vector<NDTCell*> &sourceNDT, NDTMap &targetNDT,
00948         Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor>& T)
00949 {
00950 
00951     NUMBER_OF_ACTIVE_CELLS = 0;
00952     double score_here = 0;
00953     double det = 0;
00954     bool exists = false;
00955     NDTCell *cell;
00956     Eigen::Matrix3d covCombined, icov, R;
00957     Eigen::Vector3d meanFixed;
00958     Eigen::Vector3d meanMoving;
00959     pcl::PointXYZ point;
00960 
00961     R = T.rotation();
00962     for(unsigned int i=0; i<sourceNDT.size(); i++)
00963     {
00964         meanMoving = T*sourceNDT[i]->getMean();
00965         point.x = meanMoving(0);
00966         point.y = meanMoving(1);
00967         point.z = meanMoving(2);
00968 
00969         if(!targetNDT.getCellForPoint(point,cell))
00970         {
00971             score_here += 0.1;
00972             continue;
00973         }
00974 
00975         if(cell == NULL)
00976         {
00977             score_here += 0.1;
00978             continue;
00979         }
00980         if(cell->hasGaussian_)
00981         {
00982             meanFixed = cell->getMean();
00983             covCombined = cell->getCov() + R.transpose()*sourceNDT[i]->getCov()*R;
00984             covCombined.computeInverseAndDetWithCheck(icov,det,exists);
00985             if(!exists)
00986             {
00987                 score_here+=0.1;
00988                 continue;
00989             }
00990             double l = (meanMoving-meanFixed).dot(icov*(meanMoving-meanFixed));
00991             if(l*0 != 0)
00992             {
00993                 score_here+=0.1;
00994                 continue;
00995             }
00996             if(l > 120)
00997             {
00998                 score_here+=0.1;
00999                 continue;
01000             }
01001 
01002             double sh = lfd1*(exp(-lfd2*l/2));
01003 
01004             if(fabsf(sh) > 1e-10)
01005             {
01006                 NUMBER_OF_ACTIVE_CELLS++;
01007             }
01008             score_here += (1.0 - sh);
01009             //fprintf(stderr," '[i]=%lf' ", (1.0-sh));
01010         }
01011         else
01012         {
01013             score_here+=0.1;
01014         }
01015 
01016     }
01017     return score_here;
01018 }
01019 
01023 
01024 
01025 
01026 #define USE_OMP
01027 
01028 //compute the score gradient of a point cloud + transformation to an NDT
01029 double NDTMatcherD2D::derivativesNDT(
01030     const std::vector<NDTCell*> &sourceNDT,
01031     const NDTMap &targetNDT,
01032     Eigen::MatrixXd &score_gradient,
01033     Eigen::MatrixXd &Hessian,
01034     bool computeHessian
01035 )
01036 {
01037 
01038 //    struct timeval tv_start, tv_end;
01039     double score_here = 0;
01040     int n_dimensions = score_gradient.rows();
01041 
01042 //    gettimeofday(&tv_start,NULL);
01043     NUMBER_OF_ACTIVE_CELLS = 0;
01044     score_gradient.setZero();
01045     Hessian.setZero();
01046 
01047 #ifdef USE_OMP
01048     Eigen::MatrixXd score_gradient_omp;
01049     Eigen::MatrixXd score_here_omp;
01050     Eigen::MatrixXd Hessian_omp;
01051 
01052 #define n_threads 6
01053 
01054     //n_threads = omp_get_num_threads();
01055     score_gradient_omp.resize(n_dimensions,n_threads);
01056     score_here_omp.resize(1,n_threads);
01057     Hessian_omp.resize(n_dimensions,n_dimensions*n_threads);
01058 
01059     score_gradient_omp.setZero();
01060     score_here_omp.setZero();
01061     Hessian_omp.setZero();
01062     //std::cout<<n_threads<<" "<<omp_get_thread_num()<<std::endl;
01063 
01064     #pragma omp parallel num_threads(n_threads)
01065     {
01066         #pragma omp for
01067         for(unsigned int i=0; i<sourceNDT.size(); i++)
01068         {
01069             if(sourceNDT[i] == NULL) continue;
01070             if(!sourceNDT[i]->hasGaussian_) continue;
01071             pcl::PointXYZ point;
01072             Eigen::Vector3d transformed;
01073             Eigen::Vector3d meanMoving, meanFixed;
01074             Eigen::Matrix3d CMoving, CFixed, CSum, Cinv, R;
01075             Eigen::MatrixXd score_gradient_omp_loc(n_dimensions,1);
01076             Eigen::MatrixXd Hessian_omp_loc(n_dimensions,n_dimensions);
01077             Eigen::Matrix<double,3,6> _Jest;
01078             Eigen::Matrix<double,18,6> _Hest;
01079             Eigen::Matrix<double,3,18> _Zest;
01080             Eigen::Matrix<double,18,18> _ZHest;
01081             double score_here_loc=0;
01082             int thread_id = omp_get_thread_num();
01083             NDTCell *cell;
01084             bool exists = false;
01085             double det = 0;
01086 
01087 
01088             score_gradient_omp_loc.setZero();
01089             Hessian_omp_loc.setZero();
01090             _Jest.setZero();
01091             _Jest.block<3,3>(0,0).setIdentity();
01092             _Hest.setZero();
01093             _Zest.setZero();
01094             _ZHest.setZero();
01095 
01096             meanMoving = sourceNDT[i]->getMean();
01097             CMoving= sourceNDT[i]->getCov();
01098             computeDerivativesLocal(meanMoving, CMoving, _Jest, _Hest, _Zest, _ZHest, computeHessian);
01099 
01100             point.x = meanMoving(0);
01101             point.y = meanMoving(1);
01102             point.z = meanMoving(2);
01103             std::vector<NDTCell*> cells = targetNDT.getCellsForPoint(point,n_neighbours); //targetNDT.getAllCells(); //
01104             for(unsigned int j=0; j<cells.size(); j++)
01105             {
01106                 cell = cells[j];
01107                 if(cell == NULL)
01108                 {
01109                     continue;
01110                 }
01111                 if(cell->hasGaussian_)
01112                 {
01113                     transformed = meanMoving - cell->getMean();
01114                     CFixed = cell->getCov();
01115                     CSum = (CFixed+CMoving);
01116                     CSum.computeInverseAndDetWithCheck(Cinv,det,exists);
01117                     if(!exists)
01118                     {
01119                         continue;
01120                     }
01121                     double l = (transformed).dot(Cinv*(transformed));
01122                     if(l*0 != 0)
01123                     {
01124                         continue;
01125                     }
01126                     //if(l > 120) continue;
01127                     double sh = -lfd1*(exp(-lfd2*l/2));
01128                     if(!update_gradient_hessian_local(score_gradient_omp_loc,Hessian_omp_loc,transformed, Cinv, sh,
01129                                                       _Jest, _Hest, _Zest, _ZHest, computeHessian))
01130                     {
01131                         continue;
01132                     }
01133                     score_here_loc += sh;
01134                     cell = NULL;
01135                 }
01136             }
01137             //score_gradient_omp.block(0,thread_id,n_dimensions,1) += score_gradient_omp_loc;
01138             score_gradient_omp.col(thread_id) += score_gradient_omp_loc;
01139             Hessian_omp.block(0,n_dimensions*thread_id,n_dimensions,n_dimensions) += Hessian_omp_loc;
01140             score_here_omp(0,thread_id) += score_here_loc;
01141 
01142         }
01143     } //end pragma block
01144     //std::cout<<"sgomp: "<<score_gradient_omp<<std::endl;
01145     //std::cout<<"somp: "<<score_here_omp<<std::endl;
01146 
01147     score_gradient = score_gradient_omp.rowwise().sum();
01148     score_here = score_here_omp.sum();
01149     if(computeHessian)
01150     {
01151         //std::cout<<"Homp: "<<Hessian_omp<<std::endl;
01152         for(int i=0; i<n_threads; ++i)
01153         {
01154             Hessian += Hessian_omp.block(0,n_dimensions*i,n_dimensions,n_dimensions);
01155         }
01156     }
01157 #else
01158     pcl::PointXYZ point;
01159     Eigen::Vector3d transformed;
01160     Eigen::Vector3d meanMoving, meanFixed;
01161     Eigen::Matrix3d CMoving, CFixed, CSum, Cinv, R;
01162     NDTCell *cell;
01163     bool exists = false;
01164     double det = 0;
01165     for(unsigned int i=0; i<sourceNDT.size(); i++)
01166     {
01167         meanMoving = sourceNDT[i]->getMean();
01168         CMoving= sourceNDT[i]->getCov();
01169         computeDerivatives(meanMoving, CMoving, computeHessian);
01170 
01171         point.x = meanMoving(0);
01172         point.y = meanMoving(1);
01173         point.z = meanMoving(2);
01174         std::vector<NDTCell*> cells = targetNDT.getCellsForPoint(point,n_neighbours); //targetNDT.getAllCells(); //
01175         for(int j=0; j<cells.size(); j++)
01176         {
01177             cell = cells[j];
01178             if(cell == NULL)
01179             {
01180                 continue;
01181             }
01182             if(cell->hasGaussian_)
01183             {
01184                 transformed = meanMoving - cell->getMean();
01185                 CFixed = cell->getCov();
01186                 CSum = (CFixed+CMoving);
01187                 CSum.computeInverseAndDetWithCheck(Cinv,det,exists);
01188                 if(!exists)
01189                 {
01190                     //delete cell;
01191                     continue;
01192                 }
01193                 double l = (transformed).dot(Cinv*(transformed));
01194                 if(l*0 != 0)
01195                 {
01196                     //delete cell;
01197                     continue;
01198                 }
01199                 //if(l > 120) continue;
01200                 double sh = -lfd1*(exp(-lfd2*l/2));
01201                 //compute Jest, Hest, Zest, ZHest
01202                 //update score gradient
01203                 //std::cout<<"m1 = ["<<meanMoving.transpose()<<"]';\n m2 = ["<<cell->getMean().transpose()<<"]';\n";
01204                 //std::cout<<"C1 = ["<<CMoving<<"];\n C2 = ["<<CFixed<<"];\n";
01205 //                  if(!update_gradient_hessian(score_gradient, Hessian, transformed, Cinv, sh, computeHessian))
01206                 if(!update_gradient_hessian(score_gradient,Hessian,transformed, Cinv, sh, computeHessian))
01207                 {
01208                     //delete cell;
01209                     continue;
01210                 }
01211                 //NUMBER_OF_ACTIVE_CELLS++;
01212                 score_here += sh;
01213                 //delete cell;
01214                 cell = NULL;
01215             }
01216         }
01217     }
01218 #endif
01219     /*
01220     if(computeHessian) {
01221 
01222         //regularization 0.01*NUMBER_OF_ACTIVE_CELLS*
01223         //Hessian = Hessian + 0.1*NUMBER_OF_ACTIVE_CELLS*Eigen::Matrix<double,6,6>::Identity();
01224         Eigen::SelfAdjointEigenSolver<Eigen::Matrix<double,6,6> > Sol (Hessian);
01225         Eigen::Matrix<double,6,1> evals = Sol.eigenvalues().real();
01226 
01227         double minCoeff = evals.minCoeff();
01228         double maxCoeff = evals.maxCoeff();
01229 
01230         if(minCoeff < 0 ) { //evals.minCoeff() < 0.01*evals.maxCoeff()) {
01231         Eigen::Matrix<double,6,6> evecs = Sol.eigenvectors().real();
01232         double regularizer = 0.01*maxCoeff - minCoeff;
01233         Eigen::Matrix<double,6,1> reg;
01234         //ugly
01235         reg<<regularizer,regularizer,regularizer,regularizer,regularizer,regularizer;
01236         evals += reg;
01237         Eigen::Matrix<double,6,6> Lam;
01238         Lam = evals.asDiagonal();
01239         Hessian = evecs*Lam*(evecs.transpose());
01240         std::cerr<<"regularizing\n";
01241         }
01242         */
01243     /*
01244     if(minCoeff < 0.001*maxCoeff) {
01245     Eigen::Matrix<double,6,6> evecs = Sol.eigenvectors().real();
01246     for(int q=0;q<6;++q) {
01247         if(evals(q) < 0.001*maxCoeff) {
01248         evals(q)=0.001*maxCoeff;
01249         } else{
01250         break;
01251         }
01252     }
01253     Eigen::Matrix<double,6,6> Lam;
01254     Lam = evals.asDiagonal();
01255     Hessian = evecs*Lam*(evecs.transpose());
01256     std::cerr<<"BAD_HESSIAN\n";
01257     }
01258     }
01259     */
01260 
01261 //    gettimeofday(&tv_end,NULL);
01262 //    double time_load = (tv_end.tv_sec-tv_start.tv_sec)*1000.+(tv_end.tv_usec-tv_start.tv_usec)/1000.;
01263 //    std::cout<<"3D::: time derivatives took is: "<<time_load<<std::endl;
01264     return score_here;
01265 }
01266 
01267 
01268 //perform line search to find the best descent rate (More&Thuente)
01269 double NDTMatcherD2D::lineSearchMT(
01270     Eigen::Matrix<double,6,1> &increment,
01271     std::vector<NDTCell*> &sourceNDT,
01272     NDTMap &targetNDT
01273 )
01274 {
01275 
01276     // default params
01277     double stp = 1.0; //default step
01278     double recoverystep = 0.1;
01279     double dginit = 0.0;
01280     double ftol = 0.11111; //epsilon 1
01281     double gtol = 0.99999; //epsilon 2
01282     double stpmax = 4.0;
01283     double stpmin = 0.001;
01284     int maxfev = 40; //max function evaluations
01285     double xtol = 0.01; //window of uncertainty around the optimal step
01286 
01287     //my temporary variables
01288     std::vector<NDTCell*> sourceNDTHere;
01289     double score_init = 0.0;
01290 
01291     Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> ps;
01292     ps.setIdentity();
01293 
01294     Eigen::Matrix<double,6,1> scg_here;
01295     Eigen::MatrixXd pincr(6,1), score_gradient_here(6,1);
01296     Eigen::MatrixXd pseudoH(6,6);
01297     Eigen::Vector3d eulerAngles;
01299 
01300     int info = 0;                       // return code
01301     int infoc = 1;              // return code for subroutine cstep
01302 
01303     // Compute the initial gradient in the search direction and check
01304     // that s is a descent direction.
01305 
01306     //we want to maximize s, so we should minimize -s
01307     //score_init = scoreNDT(sourceNDT,targetNDT);
01308 
01309     //gradient directions are opposite for the negated function
01310     //score_gradient_init = -score_gradient_init;
01311 
01312 //  cout<<"score_init "<<score_init<<endl;
01313 //  cout<<"score_gradient_init "<<score_gradient_init.transpose()<<endl;
01314 //  cout<<"increment "<<increment.transpose()<<endl;
01315 
01316     score_gradient_here.setZero();
01317     score_init = derivativesNDT(sourceNDT,targetNDT,score_gradient_here,pseudoH,false);
01318     scg_here = score_gradient_here;
01319     dginit = increment.dot(scg_here);
01320 //  cout<<"dginit "<<dginit<<endl;
01321 
01322     if (dginit >= 0.0)
01323     {
01324         std::cout << "MoreThuente::cvsrch - wrong direction (dginit = " << dginit << ")" << std::endl;
01325         //return recoverystep; //TODO TSV -1; //
01326         //return -1;
01327 
01328         increment = -increment;
01329         dginit = -dginit;
01330 
01331         if (dginit >= 0.0)
01332         {
01333             for(unsigned int i=0; i<sourceNDTHere.size(); i++)
01334             {
01335                 if(sourceNDTHere[i]!=NULL)
01336                     delete sourceNDTHere[i];
01337             }
01338             return recoverystep;
01339         }
01340     }
01341     else
01342     {
01343 //     cout<<"correct direction (dginit = " << dginit << ")" << endl;
01344     }
01345 
01346     // Initialize local variables.
01347 
01348     bool brackt = false;                // has the soln been bracketed?
01349     bool stage1 = true;         // are we in stage 1?
01350     int nfev = 0;                       // number of function evaluations
01351     double dgtest = ftol * dginit; // f for curvature condition
01352     double width = stpmax - stpmin; // interval width
01353     double width1 = 2 * width;  // ???
01354 
01355     //cout<<"dgtest "<<dgtest<<endl;
01356     // initial function value
01357     double finit = 0.0;
01358     finit = score_init;
01359 
01360     // The variables stx, fx, dgx contain the values of the step,
01361     // function, and directional derivative at the best step.  The
01362     // variables sty, fy, dgy contain the value of the step, function,
01363     // and derivative at the other endpoint of the interval of
01364     // uncertainty.  The variables stp, f, dg contain the values of the
01365     // step, function, and derivative at the current step.
01366 
01367     double stx = 0.0;
01368     double fx = finit;
01369     double dgx = dginit;
01370     double sty = 0.0;
01371     double fy = finit;
01372     double dgy = dginit;
01373 
01374     // Get the linear solve tolerance for adjustable forcing term
01375     //double eta_original = -1.0;
01376     //double eta = 0.0;
01377     //eta = eta_original;
01378 
01379     // Start of iteration.
01380 
01381     double stmin, stmax;
01382     double fm, fxm, fym, dgm, dgxm, dgym;
01383 
01384     while (1)
01385     {
01386         // Set the minimum and maximum steps to correspond to the present
01387         // interval of uncertainty.
01388         if (brackt)
01389         {
01390             stmin = MoreThuente::min(stx, sty);
01391             stmax = MoreThuente::max(stx, sty);
01392         }
01393         else
01394         {
01395             stmin = stx;
01396             stmax = stp + 4 * (stp - stx);
01397         }
01398 
01399         // Force the step to be within the bounds stpmax and stpmin.
01400         stp = MoreThuente::max(stp, stpmin);
01401         stp = MoreThuente::min(stp, stpmax);
01402 
01403         // If an unusual termination is to occur then let stp be the
01404         // lowest point obtained so far.
01405 
01406         if ((brackt && ((stp <= stmin) || (stp >= stmax))) ||
01407                 (nfev >= maxfev - 1) || (infoc == 0) ||
01408                 (brackt && (stmax - stmin <= xtol * stmax)))
01409         {
01410             stp = stx;
01411         }
01412 
01413         // Evaluate the function and gradient at stp
01414         // and compute the directional derivative.
01416 
01417         pincr = stp*increment;
01418 
01419         ps = Eigen::Translation<double,3>(pincr(0),pincr(1),pincr(2))*
01420              Eigen::AngleAxisd(pincr(3),Eigen::Vector3d::UnitX())*
01421              Eigen::AngleAxisd(pincr(4),Eigen::Vector3d::UnitY())*
01422              Eigen::AngleAxisd(pincr(5),Eigen::Vector3d::UnitZ());
01423 
01424         for(unsigned int i=0; i<sourceNDTHere.size(); i++)
01425         {
01426             if(sourceNDTHere[i]!=NULL)
01427                 delete sourceNDTHere[i];
01428         }
01429         sourceNDTHere.clear();
01430         for(unsigned int i=0; i<sourceNDT.size(); i++)
01431         {
01432             NDTCell *cell = sourceNDT[i];
01433             if(cell!=NULL)
01434             {
01435                 Eigen::Vector3d mean = cell->getMean();
01436                 Eigen::Matrix3d cov = cell->getCov();
01437                 mean = ps*mean;
01438                 cov = ps.rotation()*cov*ps.rotation().transpose();
01439                 NDTCell* nd = (NDTCell*)cell->copy();
01440                 nd->setMean(mean);
01441                 nd->setCov(cov);
01442                 sourceNDTHere.push_back(nd);
01443             }
01444         }
01445 
01446         double f = 0.0;
01447         score_gradient_here.setZero();
01448 
01449         /*f = scoreNDT(sourceNDT,targetNDT,ps);
01450         derivativesNDT(sourceNDT,targetNDT,ps,score_gradient_here,pseudoH,false);
01451         std::cout<<"scg1  " <<score_gradient_here.transpose()<<std::endl;
01452         */
01453 
01454         //option 2:
01455         //f = scoreNDT(sourceNDTHere,targetNDT);
01456         f = derivativesNDT(sourceNDTHere,targetNDT,score_gradient_here,pseudoH,false);
01457         //std::cout<<"scg2  " <<score_gradient_here.transpose()<<std::endl;
01458 
01459 
01460         //cout<<"incr " <<pincr.transpose()<<endl;
01461         //cout<<"score (f) "<<f<<endl;
01462 
01463         double dg = 0.0;
01464         scg_here = score_gradient_here;
01465         dg = increment.dot(scg_here);
01466 
01467 
01468         //VALGRIND_CHECK_VALUE_IS_DEFINED(dg);
01469         //cout<<"dg = "<<dg<<endl;
01470         nfev ++;
01471 
01473 
01474         //cout<<"consider step "<<stp<<endl;
01475         // Armijo-Goldstein sufficient decrease
01476         double ftest1 = finit + stp * dgtest;
01477         //cout<<"ftest1 is "<<ftest1<<endl;
01478 
01479         // Test for convergence.
01480 
01481         if ((brackt && ((stp <= stmin) || (stp >= stmax))) || (infoc == 0))
01482             info = 6;                   // Rounding errors
01483 
01484         if ((stp == stpmax) && (f <= ftest1) && (dg <= dgtest))
01485             info = 5;                   // stp=stpmax
01486 
01487         if ((stp == stpmin) && ((f > ftest1) || (dg >= dgtest)))
01488             info = 4;                   // stp=stpmin
01489 
01490         if (nfev >= maxfev)
01491             info = 3;                   // max'd out on fevals
01492 
01493         if (brackt && (stmax-stmin <= xtol*stmax))
01494             info = 2;                   // bracketed soln
01495 
01496         // RPP sufficient decrease test can be different
01497         bool sufficientDecreaseTest = false;
01498         sufficientDecreaseTest = (f <= ftest1);  // Armijo-Golstein
01499 
01500         //cout<<"ftest2 "<<gtol*(-dginit)<<endl;
01501         //cout<<"sufficientDecrease? "<<sufficientDecreaseTest<<endl;
01502         //cout<<"curvature ok? "<<(fabs(dg) <= gtol*(-dginit))<<endl;
01503         if ((sufficientDecreaseTest) && (fabs(dg) <= gtol*(-dginit)))
01504             info = 1;                   // Success!!!!
01505 
01506         if (info != 0)          // Line search is done
01507         {
01508             if (info != 1)              // Line search failed
01509             {
01510                 // RPP add
01511                 // counter.incrementNumFailedLineSearches();
01512 
01513                 //if (recoveryStepType == Constant)
01514                 stp = recoverystep;
01515 
01516                 //newgrp.computeX(oldgrp, dir, stp);
01517 
01518                 //message = "(USING RECOVERY STEP!)";
01519 
01520             }
01521             else                        // Line search succeeded
01522             {
01523                 //message = "(STEP ACCEPTED!)";
01524             }
01525 
01526             //print.printStep(nfev, stp, finit, f, message);
01527 
01528             // Returning the line search flag
01529             //cout<<"LineSearch::"<<message<<" info "<<info<<endl;
01530             for(unsigned int i=0; i<sourceNDTHere.size(); i++)
01531             {
01532                 if(sourceNDTHere[i]!=NULL)
01533                     delete sourceNDTHere[i];
01534             }
01535 //      std::cout<<"nfev = "<<nfev<<std::endl;
01536             return stp;
01537 
01538         } // info != 0
01539 
01540         // RPP add
01541         //counter.incrementNumIterations();
01542 
01543         // In the first stage we seek a step for which the modified
01544         // function has a nonpositive value and nonnegative derivative.
01545 
01546         if (stage1 && (f <= ftest1) && (dg >= MoreThuente::min(ftol, gtol) * dginit))
01547         {
01548             stage1 = false;
01549         }
01550 
01551         // A modified function is used to predict the step only if we have
01552         // not obtained a step for which the modified function has a
01553         // nonpositive function value and nonnegative derivative, and if a
01554         // lower function value has been obtained but the decrease is not
01555         // sufficient.
01556 
01557         if (stage1 && (f <= fx) && (f > ftest1))
01558         {
01559 
01560             // Define the modified function and derivative values.
01561 
01562             fm = f - stp * dgtest;
01563             fxm = fx - stx * dgtest;
01564             fym = fy - sty * dgtest;
01565             dgm = dg - dgtest;
01566             dgxm = dgx - dgtest;
01567             dgym = dgy - dgtest;
01568 
01569             // Call cstep to update the interval of uncertainty
01570             // and to compute the new step.
01571 
01572             //VALGRIND_CHECK_VALUE_IS_DEFINED(dgm);
01573             infoc = MoreThuente::cstep(stx,fxm,dgxm,sty,fym,dgym,stp,fm,dgm,
01574                                        brackt,stmin,stmax);
01575 
01576             // Reset the function and gradient values for f.
01577 
01578             fx = fxm + stx*dgtest;
01579             fy = fym + sty*dgtest;
01580             dgx = dgxm + dgtest;
01581             dgy = dgym + dgtest;
01582 
01583         }
01584 
01585         else
01586         {
01587 
01588             // Call cstep to update the interval of uncertainty
01589             // and to compute the new step.
01590 
01591             //VALGRIND_CHECK_VALUE_IS_DEFINED(dg);
01592             infoc = MoreThuente::cstep(stx,fx,dgx,sty,fy,dgy,stp,f,dg,
01593                                        brackt,stmin,stmax);
01594 
01595         }
01596 
01597         // Force a sufficient decrease in the size of the
01598         // interval of uncertainty.
01599 
01600         if (brackt)
01601         {
01602             if (fabs(sty - stx) >= 0.66 * width1)
01603                 stp = stx + 0.5 * (sty - stx);
01604             width1 = width;
01605             width = fabs(sty-stx);
01606         }
01607 
01608     } // while-loop
01609 
01610 }
01611 
01612 int NDTMatcherD2D::MoreThuente::cstep(double& stx, double& fx, double& dx,
01613         double& sty, double& fy, double& dy,
01614         double& stp, double& fp, double& dp,
01615         bool& brackt, double stmin, double stmax)
01616 {
01617     int info = 0;
01618 
01619     // Check the input parameters for errors.
01620 
01621     if ((brackt && ((stp <= MoreThuente::min(stx, sty)) || (stp >= MoreThuente::max(stx, sty)))) ||
01622             (dx * (stp - stx) >= 0.0) || (stmax < stmin))
01623         return info;
01624 
01625     // Determine if the derivatives have opposite sign.
01626 
01627     double sgnd = dp * (dx / fabs(dx));
01628 
01629     // First case. A higher function value.  The minimum is
01630     // bracketed. If the cubic step is closer to stx than the quadratic
01631     // step, the cubic step is taken, else the average of the cubic and
01632     // quadratic steps is taken.
01633 
01634     bool bound;
01635     double theta;
01636     double s;
01637     double gamma;
01638     double p,q,r;
01639     double stpc, stpq, stpf;
01640 
01641     if (fp > fx)
01642     {
01643         info = 1;
01644         bound = 1;
01645         theta = 3 * (fx - fp) / (stp - stx) + dx + dp;
01646         //VALGRIND_CHECK_VALUE_IS_DEFINED(theta);
01647         //VALGRIND_CHECK_VALUE_IS_DEFINED(dx);
01648         //VALGRIND_CHECK_VALUE_IS_DEFINED(dp);
01649         s = MoreThuente::absmax(theta, dx, dp);
01650         gamma = s * sqrt(((theta / s) * (theta / s)) - (dx / s) * (dp / s));
01651         if (stp < stx)
01652             gamma = -gamma;
01653 
01654         p = (gamma - dx) + theta;
01655         q = ((gamma - dx) + gamma) + dp;
01656         r = p / q;
01657         stpc = stx + r * (stp - stx);
01658         stpq = stx + ((dx / ((fx - fp) / (stp - stx) + dx)) / 2) * (stp - stx);
01659         if (fabs(stpc - stx) < fabs(stpq - stx))
01660             stpf = stpc;
01661         else
01662             stpf = stpc + (stpq - stpc) / 2;
01663 
01664         brackt = true;
01665     }
01666 
01667     // Second case. A lower function value and derivatives of opposite
01668     // sign. The minimum is bracketed. If the cubic step is closer to
01669     // stx than the quadratic (secant) step, the cubic step is taken,
01670     // else the quadratic step is taken.
01671 
01672     else if (sgnd < 0.0)
01673     {
01674         info = 2;
01675         bound = false;
01676         theta = 3 * (fx - fp) / (stp - stx) + dx + dp;
01677         s = MoreThuente::absmax(theta,dx,dp);
01678         gamma = s * sqrt(((theta/s) * (theta/s)) - (dx / s) * (dp / s));
01679         if (stp > stx)
01680             gamma = -gamma;
01681         p = (gamma - dp) + theta;
01682         q = ((gamma - dp) + gamma) + dx;
01683         r = p / q;
01684         stpc = stp + r * (stx - stp);
01685         stpq = stp + (dp / (dp - dx)) * (stx - stp);
01686         if (fabs(stpc - stp) > fabs(stpq - stp))
01687             stpf = stpc;
01688         else
01689             stpf = stpq;
01690         brackt = true;
01691     }
01692 
01693     // Third case. A lower function value, derivatives of the same sign,
01694     // and the magnitude of the derivative decreases.  The cubic step is
01695     // only used if the cubic tends to infinity in the direction of the
01696     // step or if the minimum of the cubic is beyond stp. Otherwise the
01697     // cubic step is defined to be either stmin or stmax. The
01698     // quadratic (secant) step is also computed and if the minimum is
01699     // bracketed then the the step closest to stx is taken, else the
01700     // step farthest away is taken.
01701 
01702     else if (fabs(dp) < fabs(dx))
01703     {
01704         info = 3;
01705         bound = true;
01706         theta = 3 * (fx - fp) / (stp - stx) + dx + dp;
01707         s = MoreThuente::absmax(theta, dx, dp);
01708 
01709         // The case gamma = 0 only arises if the cubic does not tend
01710         // to infinity in the direction of the step.
01711 
01712         gamma = s * sqrt(max(0,(theta / s) * (theta / s) - (dx / s) * (dp / s)));
01713         if (stp > stx)
01714             gamma = -gamma;
01715 
01716         p = (gamma - dp) + theta;
01717         q = (gamma + (dx - dp)) + gamma;
01718         r = p / q;
01719         if ((r < 0.0) && (gamma != 0.0))
01720             stpc = stp + r * (stx - stp);
01721         else if (stp > stx)
01722             stpc = stmax;
01723         else
01724             stpc = stmin;
01725 
01726         stpq = stp + (dp/ (dp - dx)) * (stx - stp);
01727         if (brackt)
01728         {
01729             if (fabs(stp - stpc) < fabs(stp - stpq))
01730                 stpf = stpc;
01731             else
01732                 stpf = stpq;
01733         }
01734         else
01735         {
01736             if (fabs(stp - stpc) > fabs(stp - stpq))
01737                 stpf = stpc;
01738             else
01739                 stpf = stpq;
01740         }
01741     }
01742 
01743     // Fourth case. A lower function value, derivatives of the same
01744     // sign, and the magnitude of the derivative does not decrease. If
01745     // the minimum is not bracketed, the step is either stmin or
01746     // stmax, else the cubic step is taken.
01747 
01748     else
01749     {
01750         info = 4;
01751         bound = false;
01752         if (brackt)
01753         {
01754             theta = 3 * (fp - fy) / (sty - stp) + dy + dp;
01755             s = MoreThuente::absmax(theta, dy, dp);
01756             gamma = s * sqrt(((theta/s)*(theta/s)) - (dy / s) * (dp / s));
01757             if (stp > sty)
01758                 gamma = -gamma;
01759             p = (gamma - dp) + theta;
01760             q = ((gamma - dp) + gamma) + dy;
01761             r = p / q;
01762             stpc = stp + r * (sty - stp);
01763             stpf = stpc;
01764         }
01765         else if (stp > stx)
01766             stpf = stmax;
01767         else
01768             stpf = stmin;
01769     }
01770 
01771     // Update the interval of uncertainty. This update does not depend
01772     // on the new step or the case analysis above.
01773 
01774     if (fp > fx)
01775     {
01776         sty = stp;
01777         fy = fp;
01778         dy = dp;
01779     }
01780     else
01781     {
01782         if (sgnd < 0.0)
01783         {
01784             sty = stx;
01785             fy = fx;
01786             dy = dx;
01787         }
01788         stx = stp;
01789         fx = fp;
01790         dx = dp;
01791     }
01792 
01793     // Compute the new step and safeguard it.
01794 
01795     stpf = MoreThuente::min(stmax, stpf);
01796     stpf = MoreThuente::max(stmin, stpf);
01797     stp = stpf;
01798     if (brackt && bound)
01799     {
01800         if (sty > stx)
01801             stp = min(stx + 0.66 * (sty - stx), stp);
01802         else
01803             stp = max(stx + 0.66 * (sty - stx), stp);
01804     }
01805 
01806     return info;
01807 
01808 }
01809 
01810 double NDTMatcherD2D::MoreThuente::min(double a, double b)
01811 {
01812     return (a < b ? a : b);
01813 }
01814 
01815 double NDTMatcherD2D::MoreThuente::max(double a, double b)
01816 {
01817     return (a > b ? a : b);
01818 }
01819 
01820 double NDTMatcherD2D::MoreThuente::absmax(double a, double b, double c)
01821 {
01822     a = fabs(a);
01823     b = fabs(b);
01824     c = fabs(c);
01825 
01826     if (a > b)
01827         return (a > c) ? a : c;
01828     else
01829         return (b > c) ? b : c;
01830 }
01831 
01832 double NDTMatcherD2D::normalizeAngle(double a)
01833 {
01834     //set the angle between -M_PI and M_PI
01835     return atan2(sin(a), cos(a));
01836 
01837 }
01838 
01839 /*
01840 void NDTMatcherD2D<PointSource,PointTarget>::generateScoreDebug(const char* out, pcl::PointCloud<pcl::PointXYZ>& fixed, pcl::PointCloud<pcl::PointXYZ>& moving) {
01841 
01842     std::ofstream lg(out,std::ios_base::out);
01843     int N_LINEAR = 100;
01844     int N_ROT    = 100;
01845     //lfd1 = 1;
01846     //lfd2 = 1;
01847 
01848     cout<<"generating scores...\n";
01849     for(current_resolution = 4; current_resolution>=0.5; current_resolution/=2) {
01850         cout<<"res "<<current_resolution<<endl;
01851         double lfc1,lfc2,lfd3;
01852         double integral, outlier_ratio, support_size;
01853         integral = 0.1;
01854         outlier_ratio = 0.3;
01855         support_size = current_resolution;
01856         lfc1 = (1-outlier_ratio)/integral;
01857         lfc2 = outlier_ratio/pow(support_size,3);
01858         lfd3 = -log(lfc2);
01859         lfd1 = -(-log( lfc1 + lfc2 ) - lfd3);
01860         lfd2 = -log((-log( lfc1 * exp( -0.5 ) + lfc2 ) - lfd3 ) / -lfd1);
01861 
01862         lfd1 = 1;//lfd1;
01863         lfd2 = 0.05;//0.8*lfd2;
01864 
01865         double lmin=-2, lmax=2, rmin=-M_PI/2, rmax=M_PI/2;
01866         double lstep = (lmax-lmin)/(N_LINEAR-1);
01867         double rstep = (rmax-rmin)/(N_ROT-1);
01868         Eigen::MatrixXd S(6,N_LINEAR);
01869         Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> T;
01870         std::vector<NDTCell*> nextNDT;
01871 
01872         LazzyGrid prototype(current_resolution);
01873         NDTMap ndt( &prototype );
01874         ndt.loadPointCloud( fixed );
01875         ndt.computeNDTCells();
01876 
01877         double z=0, r=0, pitch=0, yaw=0;
01878         int k=0;
01879         for(double x=lmin; x<lmax; x+=lstep) {
01880             T = Eigen::Translation<double,3>(x,0,0);
01881             pcl::PointCloud<pcl::PointXYZ> cloud = moving;
01882             lslgeneric::transformPointCloudInPlace(T,cloud);
01883             NDTMap mov( &prototype );
01884             mov.loadPointCloud( cloud );
01885             mov.computeNDTCells();
01886             T.setIdentity();
01887             nextNDT = mov.pseudoTransformNDT(T);
01888 
01889             S(0,k) = scoreNDT(nextNDT,ndt);
01890             for(unsigned int i=0; i<nextNDT.size(); i++) {
01891                 if(nextNDT[i]!=NULL) delete nextNDT[i];
01892             }
01893             k++;
01894         }
01895         k=0;
01896         for(double x=lmin; x<lmax; x+=lstep) {
01897             T = Eigen::Translation<double,3>(0,x,0);
01898             pcl::PointCloud<pcl::PointXYZ> cloud = moving;
01899             lslgeneric::transformPointCloudInPlace(T,cloud);
01900             NDTMap mov( &prototype );
01901             mov.loadPointCloud( cloud );
01902             mov.computeNDTCells();
01903             T.setIdentity();
01904             nextNDT = mov.pseudoTransformNDT(T);
01905 
01906             S(1,k) = scoreNDT(nextNDT,ndt);
01907             for(unsigned int i=0; i<nextNDT.size(); i++) {
01908                 if(nextNDT[i]!=NULL) delete nextNDT[i];
01909             }
01910             k++;
01911         }
01912         k=0;
01913         for(double x=lmin; x<lmax; x+=lstep) {
01914             T = Eigen::Translation<double,3>(0,0,x);
01915             pcl::PointCloud<pcl::PointXYZ> cloud = moving;
01916             lslgeneric::transformPointCloudInPlace(T,cloud);
01917             NDTMap mov( &prototype );
01918             mov.loadPointCloud( cloud );
01919             mov.computeNDTCells();
01920             T.setIdentity();
01921             nextNDT = mov.pseudoTransformNDT(T);
01922 
01923             S(2,k) = scoreNDT(nextNDT,ndt);
01924             for(unsigned int i=0; i<nextNDT.size(); i++) {
01925                 if(nextNDT[i]!=NULL) delete nextNDT[i];
01926             }
01927             k++;
01928         }
01929 
01930         k=0;
01931         for(double r=rmin; r<rmax; r+=rstep) {
01932             T = Eigen::AngleAxis<double>(r,Eigen::Vector3d::UnitX()) *
01933                 Eigen::AngleAxis<double>(0,Eigen::Vector3d::UnitY()) *
01934                 Eigen::AngleAxis<double>(0,Eigen::Vector3d::UnitZ()) ;
01935             pcl::PointCloud<pcl::PointXYZ> cloud = moving;
01936             lslgeneric::transformPointCloudInPlace(T,cloud);
01937             NDTMap mov( &prototype );
01938             mov.loadPointCloud( cloud );
01939             mov.computeNDTCells();
01940             T.setIdentity();
01941             nextNDT = mov.pseudoTransformNDT(T);
01942 
01943             S(3,k) = scoreNDT(nextNDT,ndt);
01944             for(unsigned int i=0; i<nextNDT.size(); i++) {
01945                 if(nextNDT[i]!=NULL) delete nextNDT[i];
01946             }
01947             k++;
01948         }
01949         k=0;
01950         for(double r=rmin; r<rmax; r+=rstep) {
01951             T = Eigen::AngleAxis<double>(0,Eigen::Vector3d::UnitX()) *
01952                 Eigen::AngleAxis<double>(r,Eigen::Vector3d::UnitY()) *
01953                 Eigen::AngleAxis<double>(0,Eigen::Vector3d::UnitZ()) ;
01954             pcl::PointCloud<pcl::PointXYZ> cloud = moving;
01955             lslgeneric::transformPointCloudInPlace(T,cloud);
01956             NDTMap mov( &prototype );
01957             mov.loadPointCloud( cloud );
01958             mov.computeNDTCells();
01959             T.setIdentity();
01960             nextNDT = mov.pseudoTransformNDT(T);
01961 
01962             S(4,k) = scoreNDT(nextNDT,ndt);
01963             for(unsigned int i=0; i<nextNDT.size(); i++) {
01964                 if(nextNDT[i]!=NULL) delete nextNDT[i];
01965             }
01966             k++;
01967         }
01968         k=0;
01969         for(double r=rmin; r<rmax; r+=rstep) {
01970             T = Eigen::AngleAxis<double>(0,Eigen::Vector3d::UnitX()) *
01971                 Eigen::AngleAxis<double>(0,Eigen::Vector3d::UnitY()) *
01972                 Eigen::AngleAxis<double>(r,Eigen::Vector3d::UnitZ()) ;
01973             pcl::PointCloud<pcl::PointXYZ> cloud = moving;
01974             lslgeneric::transformPointCloudInPlace(T,cloud);
01975             NDTMap mov( &prototype );
01976             mov.loadPointCloud( cloud );
01977             mov.computeNDTCells();
01978             T.setIdentity();
01979             nextNDT = mov.pseudoTransformNDT(T);
01980 
01981             S(5,k) = scoreNDT(nextNDT,ndt);
01982             for(unsigned int i=0; i<nextNDT.size(); i++) {
01983                 if(nextNDT[i]!=NULL) delete nextNDT[i];
01984             }
01985             k++;
01986         }
01987 
01988         lg<<"Sf2f"<<(int)current_resolution<<" = ["<<S<<"];\n";
01989     }
01990     lg.close();
01991 
01992 }*/
01993 
01994 bool NDTMatcherD2D::covariance( NDTMap& targetNDT,
01995         NDTMap& sourceNDT,
01996         Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor>& T,
01997         Eigen::MatrixXd &cov
01998                                                        )
01999 {
02000 
02001     double sigmaS = (0.03)*(0.03);
02002     Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> TR;
02003     TR.setIdentity();
02004 
02005     std::vector<NDTCell*> sourceNDTN = sourceNDT.pseudoTransformNDT(T);
02006     std::vector<NDTCell*> targetNDTN = targetNDT.pseudoTransformNDT(T);
02007 
02008     Eigen::MatrixXd scg(6,1); //column vectors
02009     int NM = sourceNDTN.size() + targetNDTN.size();
02010 
02011     Eigen::MatrixXd Jdpdz(NM,6);
02012 
02013     NDTCell *cell;
02014     Eigen::Vector3d transformed;
02015     Eigen::Vector3d meanMoving, meanFixed;
02016     Eigen::Matrix3d CMoving, CFixed, Cinv;
02017     bool exists = false;
02018     double det = 0;
02019     Eigen::Matrix<double,6,1> ones;
02020     ones<<1,1,1,1,1,1;
02021     //TODO
02022     derivativesNDT(sourceNDTN,targetNDT,scg,cov,true);
02023 
02024     Eigen::Matrix3d Q;
02025     Jdpdz.setZero();
02026     Q.setZero();
02027 
02028     pcl::PointXYZ point;
02029     //now compute Jdpdz
02030     for(int i=0; i<sourceNDTN.size(); i++)
02031     {
02032         meanMoving = sourceNDTN[i]->getMean();
02033         point.x = meanMoving(0);
02034         point.y = meanMoving(1);
02035         point.z = meanMoving(2);
02036 
02037         if(!targetNDT.getCellForPoint(point,cell))
02038         {
02039             continue;
02040         }
02041         if(cell == NULL)
02042         {
02043             continue;
02044         }
02045         if(cell->hasGaussian_)
02046         {
02047 
02048             meanFixed = cell->getMean();
02049             transformed = meanMoving-meanFixed;
02050             CFixed = cell->getCov();
02051             CMoving= sourceNDTN[i]->getCov();
02052 
02053             (CFixed+CMoving).computeInverseAndDetWithCheck(Cinv,det,exists);
02054             if(!exists) continue;
02055 
02056             //compute Jdpdz.col(i)
02057             double factor = (-transformed.dot(Cinv*transformed)/2);
02058             //these conditions were copied from martin's code
02059             if(factor < -120)
02060             {
02061                 continue;
02062             }
02063             factor = exp(lfd2*factor)/2;
02064             if(factor > 1 || factor < 0 || factor*0 !=0)
02065             {
02066                 continue;
02067             }
02068 
02069             Q = -sigmaS*Cinv*Cinv;
02070 
02071             Eigen::Matrix<double,6,1> G, xtQJ;
02072 
02073             G.setZero();
02074             for(int q=3; q<6; q++)
02075             {
02076                 G(q) =  -transformed.transpose()*Q*Zest.block<3,3>(0,3*q)*Cinv*transformed;
02077                 G(q) = G(q) -transformed.transpose()*Cinv*Zest.block<3,3>(0,3*q)*Q*transformed;
02078             }
02079 
02080             xtQJ = transformed.transpose()*Q*Jest;
02081 
02082             double f1 = (transformed.transpose()*Q*transformed);
02083             G = G + xtQJ + (-lfd2/2)*f1*ones;
02084             G = G*factor*lfd1*lfd2/2;
02085 
02086             Jdpdz.row(i) = G.transpose();
02087 
02088             for(int j=0; j<targetNDTN.size(); j++)
02089             {
02090                 if(targetNDTN[j]->getMean() == meanFixed)
02091                 {
02092 
02093                     Jdpdz.row(j+sourceNDTN.size()) = Jdpdz.row(j+sourceNDTN.size())+G.transpose();
02094                     continue;
02095                 }
02096             }
02097 
02098             cell = NULL;
02099         }
02100     }
02101 
02102 
02103     //cout<<Jdpdz.transpose()<<endl;
02104 
02105     Eigen::MatrixXd JK(6,6);
02106     JK = sigmaS*Jdpdz.transpose()*Jdpdz;
02107 
02108     //cout<<"J*J'\n"<<JK<<endl;
02109     //cout<<"H\n"<<cov<<endl;
02110 
02111     cov = cov.inverse()*JK*cov.inverse();
02112     //cov = cov.inverse();//*fabsf(scoreNDT(sourceNDTN,targetNDT)*2/3);
02113     //cout<<"cov\n"<<cov<<endl;
02114 
02115     for(unsigned int q=0; q<sourceNDTN.size(); q++)
02116     {
02117         delete sourceNDTN[q];
02118     }
02119     sourceNDTN.clear();
02120 
02121     return true;
02122 }
02123 bool NDTMatcherD2D::covariance( pcl::PointCloud<pcl::PointXYZ>& target,
02124         pcl::PointCloud<pcl::PointXYZ>& source,
02125         Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor>& T,
02126         Eigen::MatrixXd &cov
02127                                                        )
02128 {
02129 
02130     Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> TR;
02131     TR.setIdentity();
02132 
02133     pcl::PointCloud<pcl::PointXYZ> sourceCloud = lslgeneric::transformPointCloud(T,source);
02134 
02135     LazyGrid prototypeSource(resolutions.front());
02136     LazyGrid prototypeTarget(resolutions.front());
02137 
02138     NDTMap targetNDT( &prototypeTarget );
02139     targetNDT.loadPointCloud( target );
02140     targetNDT.computeNDTCells();
02141 
02142     NDTMap sourceNDT( &prototypeSource );
02143     sourceNDT.loadPointCloud( sourceCloud );
02144     sourceNDT.computeNDTCells();
02145 
02146     this->covariance(targetNDT,sourceNDT,TR,cov);
02147 
02148     return true;
02149 }
02150 
02151 
02152 }


ndt_registration
Author(s): Todor Stoyanov, Jari Saarinen, Henrik Andreasson
autogenerated on Wed Aug 26 2015 15:24:52