ndt_matcher_p2d.cpp
Go to the documentation of this file.
00001 #include "Eigen/Eigen"
00002 #include "ndt_map/ndt_cell.h"
00003 #include <fstream>
00004 #include <vector>
00005 #include <ndt_map/lazy_grid.h>
00006 #include <ndt_registration/ndt_matcher_p2d.h>
00007 
00008 namespace lslgeneric
00009 {
00010 
00011 //#define DO_DEBUG_PROC
00012 
00013 void NDTMatcherP2D::init(bool useDefaultGridResolutions, std::vector<double> _resolutions)
00014 {
00015 
00017     double lfc1,lfc2,lfd3;
00018     double integral, outlier_ratio, support_size;
00019     integral = 0.1;
00020     outlier_ratio = 0.01;
00021     //outlier_ratio = 0.5;
00022     support_size = 4; //???
00023     lfc1 = (1-outlier_ratio)/integral;
00024     lfc2 = outlier_ratio/pow(support_size,3);
00025     lfd3 = -log(lfc2);
00026     lfd1 = -log( lfc1 + lfc2 ) - lfd3;
00027     lfd2 = -log((-log( lfc1 * exp( -0.5 ) + lfc2 ) - lfd3 ) / lfd1);
00028     //d1 = 0.1;
00029     //d2 = 0.001;
00030     //cout<<lfd1<<" "<<lfd2<<endl;
00032     useSimpleDerivatives = false;
00033     Jest.setZero();
00034     Jest.block<3,3>(0,0).setIdentity();
00035     Hest.setZero();
00036     NUMBER_OF_ACTIVE_CELLS = 0;
00037     ITR_MAX = 100;
00038     subsample_size = 0.4;
00039 
00040     if(useDefaultGridResolutions)
00041     {
00042         resolutions.push_back(0.2);
00043         resolutions.push_back(0.5);
00044         resolutions.push_back(1);
00045         resolutions.push_back(2);
00046     }
00047     else
00048     {
00049         resolutions = _resolutions;
00050     }
00051     Eigen::Vector3d tt;
00052     tt.setZero();
00053     precomputeAngleDerivatives(tt);
00054 }
00055 
00056 void NDTMatcherP2D::generateScoreDebug(const char* out, pcl::PointCloud<pcl::PointXYZ>& fixed,
00057         pcl::PointCloud<pcl::PointXYZ>& moving)
00058 {
00059 
00060     std::ofstream lg(out,std::ios_base::out);
00061     int N_LINEAR = 100;
00062     int N_ROT    = 100;
00063 
00064     std::cout<<"generating scores...\n";
00065     for(int q = resolutions.size()-1; q>=0; q--)
00066     {
00067         current_resolution = resolutions[q];
00068         std::cout<<"res "<<current_resolution<<std::endl;
00069         double lfc1,lfc2,lfd3;
00070         double integral, outlier_ratio, support_size;
00071         integral = 0.1;
00072         outlier_ratio = 0.35;
00073         support_size = current_resolution;
00074         lfc1 = (1-outlier_ratio)/integral;
00075         lfc2 = outlier_ratio/pow(support_size,3);
00076         lfd3 = -log(lfc2);
00077         lfd1 = -(-log( lfc1 + lfc2 ) - lfd3);
00078         lfd2 = -log((-log( lfc1 * exp( -0.5 ) + lfc2 ) - lfd3 ) / -lfd1);
00079 
00080         double lmin=-2, lmax=2, rmin=-M_PI/2, rmax=M_PI/2;
00081         double lstep = (lmax-lmin)/(N_LINEAR-1);
00082         double rstep = (rmax-rmin)/(N_ROT-1);
00083         Eigen::MatrixXd S(6,N_LINEAR);
00084         Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> T;
00085 
00086         LazyGrid prototype(current_resolution);
00087         NDTMap ndt( &prototype );
00088         ndt.loadPointCloud( fixed );
00089         ndt.computeNDTCells();
00090 
00091         int k=0;
00092         for(double x=lmin; x<lmax; x+=lstep)
00093         {
00094             T = Eigen::Translation<double,3>(x,0,0);
00095             //T = Eigen::Transform<double,3>(x,0,0);
00096             pcl::PointCloud<pcl::PointXYZ> cloud = moving;
00097             lslgeneric::transformPointCloudInPlace(T,cloud);
00098 
00099             S(0,k) = scorePointCloud(cloud,ndt);
00100             k++;
00101         }
00102         k=0;
00103         for(double x=lmin; x<lmax; x+=lstep)
00104         {
00105             T = Eigen::Translation<double,3>(0,x,0);
00106             //T = Eigen::Transform<double,3>(0,x,0);
00107             pcl::PointCloud<pcl::PointXYZ> cloud = moving;
00108             lslgeneric::transformPointCloudInPlace(T,cloud);
00109 
00110             S(1,k) = scorePointCloud(cloud,ndt);
00111             k++;
00112         }
00113         k=0;
00114         for(double x=lmin; x<lmax; x+=lstep)
00115         {
00116             T = Eigen::Translation<double,3>(0.,0.,x);
00117             //T = Eigen::Transform<double,3>(0.,0.,x);
00118             pcl::PointCloud<pcl::PointXYZ> cloud = moving;
00119             lslgeneric::transformPointCloudInPlace(T,cloud);
00120 
00121             S(2,k) = scorePointCloud(cloud,ndt);
00122             k++;
00123         }
00124 
00125         k=0;
00126         for(double r=rmin; r<rmax; r+=rstep)
00127         {
00128             T = Eigen::AngleAxis<double>(r,Eigen::Vector3d::UnitX()) *
00129                 Eigen::AngleAxis<double>(0,Eigen::Vector3d::UnitY()) *
00130                 Eigen::AngleAxis<double>(0,Eigen::Vector3d::UnitZ()) ;
00131             pcl::PointCloud<pcl::PointXYZ> cloud = moving;
00132             lslgeneric::transformPointCloudInPlace(T,cloud);
00133             S(3,k) = scorePointCloud(cloud,ndt);
00134             k++;
00135         }
00136         k=0;
00137         for(double r=rmin; r<rmax; r+=rstep)
00138         {
00139             T = Eigen::AngleAxis<double>(0,Eigen::Vector3d::UnitX()) *
00140                 Eigen::AngleAxis<double>(r,Eigen::Vector3d::UnitY()) *
00141                 Eigen::AngleAxis<double>(0,Eigen::Vector3d::UnitZ()) ;
00142             pcl::PointCloud<pcl::PointXYZ> cloud = moving;
00143             lslgeneric::transformPointCloudInPlace(T,cloud);
00144 
00145             S(4,k) = scorePointCloud(cloud,ndt);
00146             k++;
00147         }
00148         k=0;
00149         for(double r=rmin; r<rmax; r+=rstep)
00150         {
00151             T = Eigen::AngleAxis<double>(0,Eigen::Vector3d::UnitX()) *
00152                 Eigen::AngleAxis<double>(0,Eigen::Vector3d::UnitY()) *
00153                 Eigen::AngleAxis<double>(r,Eigen::Vector3d::UnitZ()) ;
00154             pcl::PointCloud<pcl::PointXYZ> cloud = moving;
00155             lslgeneric::transformPointCloudInPlace(T,cloud);
00156 
00157             S(5,k) = scorePointCloud(cloud,ndt);
00158             k++;
00159         }
00160 
00161         lg<<"Sp2f"<<(int)current_resolution<<" = ["<<S<<"];\n";
00162     }
00163     lg.close();
00164 
00165 }
00166 
00167 bool NDTMatcherP2D::match( pcl::PointCloud<pcl::PointXYZ>& target,
00168         pcl::PointCloud<pcl::PointXYZ>& source,
00169         Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor>& T )
00170 {
00171 
00172     Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> Temp;
00173     T.setIdentity();
00174 
00175     bool ret;
00176     pcl::PointCloud<pcl::PointXYZ> moving;
00177     if(subsample_size > 0) {
00178         moving = subsample(source);
00179     } else {
00180         moving = source;
00181     }
00182     //std::cerr<<"subsampled points size is "<<moving.points.size()<<std::endl;
00183     //iterative regular grid
00184     for(int i=resolutions.size()-1; i>=0; i--) {
00185         current_resolution = resolutions[i];
00186         //std::cerr<<"RESOLUTION: "<<current_resolution<<std::endl;
00187         //for(current_resolution = 2; current_resolution >= 0.5; current_resolution = current_resolution/2)
00188 
00189         LazyGrid prototype(current_resolution);
00190         NDTMap ndt( &prototype );
00191         ndt.loadPointCloud( target );
00192         ndt.computeNDTCells();
00193 
00194         ret = this->match( ndt, moving, Temp );
00195         T = Temp*T;
00196         //transform moving
00197         lslgeneric::transformPointCloudInPlace(Temp,moving);
00198 #ifdef DO_DEBUG_PROC
00199         Eigen::Vector3d out = Temp.rotation().eulerAngles(0,1,2);
00200         std::cout<<"OUT: "<<out.transpose()<<std::endl;
00201         std::cout<<"translation "<<Temp.translation().transpose()<<std::endl;
00202         //cout<<"--------------------------------------------------------\n";
00203 #endif
00204     }
00205 
00206     return ret;
00207 }
00208 
00209 bool NDTMatcherP2D::covariance( pcl::PointCloud<pcl::PointXYZ>& target,
00210         pcl::PointCloud<pcl::PointXYZ>& source,
00211         Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor>& T,
00212         Eigen::Matrix<double,6,6> &cov
00213                                                        )
00214 {
00215 
00216     Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> TR;
00217     pcl::PointCloud<pcl::PointXYZ> cloud = source;
00218     lslgeneric::transformPointCloudInPlace(T,cloud);
00219 
00220     LazyGrid prototype(current_resolution);
00221     NDTMap ndt( &prototype );
00222     ndt.loadPointCloud( target );
00223     ndt.computeNDTCells();
00224 
00225     TR.setIdentity();
00226     Eigen::Matrix<double,6,1> sc;
00227     derivativesPointCloud(cloud,ndt,TR,sc,cov,true);
00228     // "cov", at this point, is the Hessian multiplied by -1
00229 
00230     // Make sure that the Hessian is invertible
00231     Eigen::FullPivLU<Eigen::Matrix<double,6,6> > dec(cov);
00232     Eigen::Matrix<double,6,6> invH;
00233     if (dec.isInvertible())
00234     {
00235       std::cout << "nice, we have invertible Hessian\n" << cov << "\n";
00236     }
00237     else
00238     {
00239       std::cerr << "Hessian is not invertible:\n" << cov << "\n";
00240       return false;
00241     }
00242     invH = dec.inverse();
00243     cov = 0.5*invH;    
00244     //cov = 0.5*cov.inverse();
00245 
00246 
00247     return true;
00248 }
00249 
00250 bool NDTMatcherP2D::match( NDTMap& targetNDT,
00251         pcl::PointCloud<pcl::PointXYZ>& source,
00252         Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor>& T )
00253 {
00255     double lfc1,lfc2,lfd3;
00256     double integral, outlier_ratio, support_size;
00257     integral = 0.1;
00258     outlier_ratio = 0.35;
00259     //outlier_ratio = 0.35;
00260     support_size = current_resolution; //???
00261     lfc1 = (1-outlier_ratio)/integral;
00262     lfc2 = outlier_ratio/pow(support_size,3);
00263     lfd3 = -log(lfc2);
00264     lfd1 = -log( lfc1 + lfc2 ) - lfd3;
00265     lfd2 = -log((-log( lfc1 * exp( -0.5 ) + lfc2 ) - lfd3 ) / lfd1);
00266     //d1 = 0.1;
00267     //d2 = 0.001;
00268     //cout<<lfd1<<" "<<lfd2<<endl;
00270     useSimpleDerivatives = true;
00271     Jest.setZero();
00272     Jest.block<3,3>(0,0).setIdentity();
00273     Hest.setZero();
00274 
00275     //locals
00276     //int ITR_MAX = 10;
00277     bool convergence = false;
00278     double score=0;
00279     double DELTA_SCORE = 0.0001;
00280 //    double NORM_MAX = support_size/8, ROT_MAX = M_PI/18; //
00281     double NORM_MAX = 4*support_size, ROT_MAX = M_PI/4; //
00282     int itr_ctr = 0;
00283     double step_size = 1;
00284     Eigen::Matrix<double,6,1> pose_increment_v, pose_increment_reg_v, score_gradient, scg; //column vectors
00285     Eigen::Matrix<double,6,6> Hessian;
00286     Eigen::Matrix3d cov;
00287     Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> TR, Tbest;
00288     Eigen::Vector3d transformed_vec, mean;
00289     bool ret = true;
00290 
00291     pcl::PointCloud<pcl::PointXYZ> prevCloud, nextCloud;
00292     prevCloud = source;
00293     nextCloud = source;
00294     T.setIdentity();
00295     TR.setIdentity();
00296     Eigen::Vector3d eulerAngles = T.rotation().eulerAngles(0,1,2);
00297 
00298     double scoreP = 0;
00299     double score_best = INT_MAX;
00300     
00301     while(!convergence)
00302     {
00303 
00304         score_gradient.setZero();
00305         Hessian.setZero();
00306         //derivativesPointCloud(source,targetNDT,T,score_gradient,Hessian,true);
00307 
00308         TR.setIdentity();
00309         derivativesPointCloud(prevCloud,targetNDT,TR,score_gradient,Hessian,true);
00310         scg = score_gradient;
00311 
00312         Eigen::SelfAdjointEigenSolver<Eigen::Matrix<double,6,6> > Sol (Hessian);
00313         Eigen::Matrix<double,6,1> evals = Sol.eigenvalues().real();
00314         double minCoeff = evals.minCoeff();
00315         double maxCoeff = evals.maxCoeff();
00316         if(minCoeff < 0)  //|| evals.minCoeff()) // < 10e-5*evals.maxCoeff()) 
00317         {
00318         //    std::cerr<<"Hessian near singular "<<evals.transpose()<<std::endl;
00319             Eigen::Matrix<double,6,6> evecs = Sol.eigenvectors().real();
00320             double regularizer = score_gradient.norm();
00321             regularizer = regularizer + minCoeff > 0 ? regularizer : 0.001*maxCoeff - minCoeff;
00322             //double regularizer = 0.001*maxCoeff - minCoeff;
00323             Eigen::Matrix<double,6,1> reg;
00324             //ugly
00325             reg<<regularizer,regularizer,regularizer,regularizer,regularizer,regularizer;
00326             evals += reg;
00327             Eigen::Matrix<double,6,6> Lam;
00328             Lam = evals.asDiagonal();
00329             Hessian = evecs*Lam*(evecs.transpose());
00330         }
00331         
00332         pose_increment_v = Hessian.ldlt().solve(-score_gradient);
00333 
00334         score = scorePointCloud(prevCloud,targetNDT);
00335         if(score < score_best) 
00336         {
00337             Tbest = T;
00338             score_best = score;
00339         }
00340         //std::cerr<<"iteration "<<itr_ctr<<" pose norm "<<(pose_increment_v.norm())<<" score "<<score<<std::endl;
00341         
00342 
00343 //step control...
00344 #if 0
00345         double pnorm = sqrt(pose_increment_v(0)*pose_increment_v(0) + pose_increment_v(1)*pose_increment_v(1)
00346                             +pose_increment_v(2)*pose_increment_v(2));
00347         if(pnorm > NORM_MAX)
00348         {
00349             pose_increment_v(0) = NORM_MAX*pose_increment_v(0)/pnorm;
00350             pose_increment_v(1) = NORM_MAX*pose_increment_v(1)/pnorm;
00351             pose_increment_v(2) = NORM_MAX*pose_increment_v(2)/pnorm;
00352         }
00353         pose_increment_v(3) = normalizeAngle(pose_increment_v(3));
00354         pose_increment_v(3) = (pose_increment_v(3) > ROT_MAX) ? ROT_MAX : pose_increment_v(3);
00355         pose_increment_v(3) = (pose_increment_v(3) < -ROT_MAX) ? -ROT_MAX : pose_increment_v(3);
00356         pose_increment_v(4) = normalizeAngle(pose_increment_v(4));
00357         pose_increment_v(4) = (pose_increment_v(4) > ROT_MAX) ? ROT_MAX : pose_increment_v(4);
00358         pose_increment_v(4) = (pose_increment_v(4) < -ROT_MAX) ? -ROT_MAX : pose_increment_v(4);
00359         pose_increment_v(5) = normalizeAngle(pose_increment_v(5));
00360         pose_increment_v(5) = (pose_increment_v(5) > ROT_MAX) ? ROT_MAX : pose_increment_v(5);
00361         pose_increment_v(5) = (pose_increment_v(5) < -ROT_MAX) ? -ROT_MAX : pose_increment_v(5);
00362 //      cout<<"H  =  ["<<Hessian<<"]"<<endl;
00363 //      cout<<"grad= ["<<score_gradient.transpose()<<"]"<<endl;
00364 //      cout<<"dg    "<<pose_increment_v.dot(score_gradient)<<endl;
00365 #endif
00366         TR.setIdentity();
00367         TR =  Eigen::Translation<double,3>(pose_increment_v(0),pose_increment_v(1),pose_increment_v(2))*
00368               Eigen::AngleAxis<double>(pose_increment_v(3),Eigen::Vector3d::UnitX()) *
00369               Eigen::AngleAxis<double>(pose_increment_v(4),Eigen::Vector3d::UnitY()) *
00370               Eigen::AngleAxis<double>(pose_increment_v(5),Eigen::Vector3d::UnitZ()) ;
00371 
00372     /*    double dginit = pose_increment_v.dot(scg);
00373         if (score_gradient.norm()<= DELTA_SCORE || dginit > 0)
00374         {
00375             //std::cerr<<"Termination\n";
00376             if(score > score_best) 
00377             {
00378                 T = Tbest;
00379             }
00380             return true;
00381         }
00382     */
00383         step_size = lineSearchMT(score_gradient,pose_increment_v,prevCloud,TR,targetNDT);
00384         if(step_size < 0)
00385         {
00386             //    cout<<"can't decrease in this direction any more, done \n";
00387             return true;
00388         }
00389         pose_increment_v = step_size*pose_increment_v;
00390 
00391 
00392 //      cout<<"incr= ["<<pose_increment_v.transpose()<<"]"<<endl;
00393         TR.setIdentity();
00394         TR =  Eigen::Translation<double,3>(pose_increment_v(0),pose_increment_v(1),pose_increment_v(2))*
00395               Eigen::AngleAxis<double>(pose_increment_v(3),Eigen::Vector3d::UnitX()) *
00396               Eigen::AngleAxis<double>(pose_increment_v(4),Eigen::Vector3d::UnitY()) *
00397               Eigen::AngleAxis<double>(pose_increment_v(5),Eigen::Vector3d::UnitZ()) ;
00398         T = TR*T;
00399 
00400         //eulerAngles<<pose_increment_v(3),pose_increment_v(4),pose_increment_v(5);
00401         //eulerAngles = T.rotation().eulerAngles(0,1,2);
00402 
00403         prevCloud = lslgeneric::transformPointCloud<pcl::PointXYZ>(T,source);
00404         scoreP = score;
00405         score = scorePointCloud(prevCloud,targetNDT);
00406         if(score < score_best) 
00407         {
00408             Tbest = T;
00409             score_best = score;
00410         }
00411 
00412         //cout<<"iteration "<<itr_ctr<<" pose norm "<<(pose_increment_v.norm())<<" score_prev "<<scoreP<<" scoreN "<<score<<endl;
00413         //cout<<"step size "<<step_size<<endl;
00414 
00415         if(itr_ctr>0)
00416         {
00417             convergence = ((pose_increment_v.norm()) < DELTA_SCORE);
00418         }
00419         if(itr_ctr>ITR_MAX)
00420         {
00421             convergence = true;
00422             ret = false;
00423         }
00424         itr_ctr++;
00425     }
00426 //    cout<<"res: "<<current_resolution<<" itr "<<itr_ctr<<endl;
00427 //    cout<<"T: \n t = "<<T.translation().transpose()<<endl;
00428 //    cout<<"r= \n"<<T.rotation()<<endl;
00429 
00430     T = Tbest;
00431     this->finalscore = score/NUMBER_OF_ACTIVE_CELLS;
00432     return ret;
00433 }
00434 
00435 
00436 void NDTMatcherP2D::check( pcl::PointCloud<pcl::PointXYZ>& fixed,
00437             pcl::PointCloud<pcl::PointXYZ>& moving,
00438             Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor>& T )
00439 {
00440   // init
00441   
00442   // check score
00443 
00444   // check hessian
00445 
00446   // output something
00447 }
00448             
00449 
00450 
00451 bool NDTMatcherP2D::update_score_gradient(Eigen::Matrix<double,6,1> &score_gradient,
00452         Eigen::Vector3d &transformed,
00453         Eigen::Matrix3d & Cinv)
00454 {
00455 
00456     Eigen::Vector3d CxX, CxdX;
00457     double factor = (-lfd2*transformed.dot(Cinv*transformed)/2);
00458 
00459     //these conditions were copied from martin's code
00460     if(factor < -120)
00461     {
00462         return false;
00463     }
00464     factor = lfd2*exp(factor);
00465     if(factor > 1 || factor < 0 || factor*0 !=0)
00466     {
00467         return false;
00468     }
00469     factor *=lfd1;
00470 
00471     for(int i=0; i<6; i++)
00472     {
00473         CxdX = Cinv*Jest.col(i);
00474         score_gradient(i) += transformed.dot(CxdX)*factor;
00475     }
00476     return true;
00477 
00478 }
00479 
00480 void NDTMatcherP2D::update_hessian(Eigen::Matrix<double,6,6> &Hessian,
00481         Eigen::Vector3d &transformed,
00482         Eigen::Matrix3d & Cinv)
00483 {
00484 
00485     Eigen::Vector3d CxX, CxdXdI, CxdXdJ, CxSecondOrder;
00486     CxX = Cinv*transformed;
00487     double factor = lfd1*lfd2*exp(-lfd2*transformed.dot(CxX)/2);
00488     for(int i=0; i<Hessian.rows(); i++)
00489     {
00490         for(int j=0; j<Hessian.cols(); j++)
00491         {
00492 
00493             CxdXdI = Cinv*Jest.col(i);
00494             CxdXdJ = Cinv*Jest.col(j);
00495             CxSecondOrder = Cinv*Hest.block<3,1>(3*i,j);
00496 
00497             Hessian(i,j) += factor*(-lfd2*transformed.dot(CxdXdI)*transformed.dot(CxdXdJ) +
00498                                     transformed.dot(CxSecondOrder) +
00499                                     Jest.col(j).dot(CxdXdI) );
00500         }
00501     }
00502 
00503 }
00504 
00505 void NDTMatcherP2D::precomputeAngleDerivatives(Eigen::Vector3d &eulerAngles)
00506 {
00507     if(fabsf(eulerAngles(0)) < 10e-5) eulerAngles(0) = 0;
00508     if(fabsf(eulerAngles(1)) < 10e-5) eulerAngles(1) = 0;
00509     if(fabsf(eulerAngles(2)) < 10e-5) eulerAngles(2) = 0;
00510     double cx,cy,cz, sx,sy,sz;
00511     cx = cos(eulerAngles(0));
00512     cy = cos(eulerAngles(1));
00513     cz = cos(eulerAngles(2));
00514     sx = sin(eulerAngles(0));
00515     sy = sin(eulerAngles(1));
00516     sz = sin(eulerAngles(2));
00517 
00518     jest13 << (-sx*sz+cx*sy*cz) , (-sx*cz - cx*sy*sz) , (-cx*cy) ;
00519     jest23 << (cx*sz+sx*sy*cz) , (cx*cz-sx*sy*sz) , (-sx*cy);
00520     jest04 << (-sy*cz) , sy*sz , cy;
00521     jest14 << sx*cy*cz , (-sx*cy*sz) , sx*sy;
00522     jest24 << (-cx*cy*cz) , cx*cy*sz , (-cx*sy);
00523     jest05 << (-cy*sz) , (-cy*cz), 0;
00524     jest15 << (cx*cz-sx*sy*sz) , (-cx*sz - sx*sy*cz), 0;
00525     jest25 << (sx*cz + cx*sy*sz) ,(cx*sy*cz - sx*sz), 0;
00526 /*
00527     std::cerr<<"jest13 "<<jest13.transpose() <<std::endl;
00528     std::cerr<<"jest23 "<<jest23.transpose() <<std::endl;
00529     std::cerr<<"jest04 "<<jest04.transpose() <<std::endl;
00530     std::cerr<<"jest14 "<<jest14.transpose() <<std::endl;
00531     std::cerr<<"jest24 "<<jest24.transpose() <<std::endl;
00532     std::cerr<<"jest05 "<<jest05.transpose() <<std::endl;
00533     std::cerr<<"jest15 "<<jest15.transpose() <<std::endl;
00534     std::cerr<<"jest25 "<<jest25.transpose() <<std::endl;
00535 */
00536     a2 << (-cx*sz-sx*sy*cz),(-cx*cz+sx*sy*sz),sx*cy;
00537     a3 << (-sx*sz+cx*sy*cz),(-cx*sy*sz-sx*cz),(-cx*cy);
00538     b2 << (cx*cy*cz),(-cx*cy*sz),(cx*sy);
00539     b3 << (sx*cy*cz),(-sx*cy*sz),(sx*sy);
00540     c2 << (-sx*cz-cx*sy*sz),(sx*sz-cx*sy*cz),0;
00541     c3 << (cx*cz-sx*sy*sz),(-sx*sy*cz-cx*sz),0;
00542     d1 << (-cy*cz),(cy*sz),(sy);
00543     d2 << (-sx*sy*cz),(sx*sy*sz),(sx*cy);
00544     d3 << (cx*sy*cz),(-cx*sy*sz),(-cx*cy);
00545     e1 << (sy*sz),(sy*cz),0;
00546     e2 << (-sx*cy*sz),(-sx*cy*cz),0;
00547     e3 << (cx*cy*sz),(cx*cy*cz),0;
00548     f1 << (-cy*cz),(cy*sz),0;
00549     f2 << (-cx*sz -sx*sy*cz),(-cx*cz+sx*sy*sz),0;
00550     f3 << (-sx*sz+cx*sy*cz),(-cx*sy*sz-sx*cz),0;
00551 /*
00552     std::cerr<<"a2 "<<a2.transpose() <<std::endl;
00553     std::cerr<<"a3 "<<a3.transpose() <<std::endl;
00554     std::cerr<<"b2 "<<b2.transpose() <<std::endl;
00555     std::cerr<<"b3 "<<b3.transpose() <<std::endl;
00556     std::cerr<<"c2 "<<c2.transpose() <<std::endl;
00557     std::cerr<<"c3 "<<c3.transpose() <<std::endl;
00558     std::cerr<<"d1 "<<d1.transpose() <<std::endl;
00559     std::cerr<<"d2 "<<d2.transpose() <<std::endl;
00560     std::cerr<<"d3 "<<d3.transpose() <<std::endl;
00561     std::cerr<<"e1 "<<e1.transpose() <<std::endl;
00562     std::cerr<<"e2 "<<e2.transpose() <<std::endl;
00563     std::cerr<<"e3 "<<e3.transpose() <<std::endl;
00564     std::cerr<<"f1 "<<f1.transpose() <<std::endl;
00565     std::cerr<<"f2 "<<f2.transpose() <<std::endl;
00566     std::cerr<<"f3 "<<f3.transpose() <<std::endl;
00567 */
00568 }
00569 void NDTMatcherP2D::computeDerivatives(pcl::PointXYZ &pt)
00570 {
00571 
00572     if(useSimpleDerivatives)
00573     {
00574         Jest(1,3) = -pt.z;
00575         Jest(2,3) = pt.y;
00576         Jest(0,4) = pt.z;
00577         Jest(2,4) = -pt.x;
00578         Jest(0,5) = -pt.y;
00579         Jest(1,5) = pt.x;
00580 
00581         //a     
00582         Hest(10,3) = -pt.y;
00583         Hest(11,3) = -pt.z;
00584         //b
00585         Hest(13,3) = pt.x;
00586         //c
00587         Hest(17,3) = pt.x;
00588         //b
00589         Hest(10,4) = pt.x;
00590         //d
00591         Hest(12,4) = -pt.x;
00592         Hest(14,4) = -pt.z;
00593         //e
00594         Hest(17,4) = pt.y;
00595         //c
00596         Hest(11,5) = pt.x;
00597         //e
00598         Hest(14,5) = pt.y;
00599         //f
00600         Hest(15,5) = -pt.x;
00601         Hest(16,5) = -pt.y;
00602         return;
00603     }
00604 
00605     Eigen::Vector3d x;
00606     x<<pt.x,pt.y,pt.z;
00607 
00608     //full derivatives
00609     Jest(1,3) = x.dot(jest13);
00610     Jest(2,3) = x.dot(jest23);
00611     Jest(0,4) = x.dot(jest04);
00612     Jest(1,4) = x.dot(jest14);
00613     Jest(2,4) = x.dot(jest24);
00614     Jest(0,5) = x.dot(jest05);
00615     Jest(1,5) = x.dot(jest15);
00616     Jest(2,5) = x.dot(jest25);
00617 
00618     Eigen::Vector3d a,b,c,d,e,f;
00619 
00620     a<<0,x.dot(a2),x.dot(a3);
00621     b<<0,x.dot(b2),x.dot(b3);
00622     c<<0,x.dot(c2),x.dot(c3);
00623     d<<x.dot(d1),x.dot(d2),x.dot(d3);
00624     e<<x.dot(e1),x.dot(e2),x.dot(e3);
00625     f<<x.dot(f1),x.dot(f2),x.dot(f3);
00626 
00627     //Hest
00628     Hest.block<3,1>(9,3) = a;
00629     Hest.block<3,1>(12,3) = b;
00630     Hest.block<3,1>(15,3) = c;
00631     Hest.block<3,1>(9,4) = b;
00632     Hest.block<3,1>(12,4) = d;
00633     Hest.block<3,1>(15,4) = e;
00634     Hest.block<3,1>(9,5) = c;
00635     Hest.block<3,1>(12,5) = e;
00636     Hest.block<3,1>(15,5) = f;
00637 
00638 }
00639 
00640 double NDTMatcherP2D::scorePointCloud(pcl::PointCloud<pcl::PointXYZ> &source,
00641         NDTMap &targetNDT)
00642 {
00643     double score_here = 0;
00644     double score_native = 0;
00645     NDTCell *cell;
00646     Eigen::Matrix3d icov;
00647     Eigen::Vector3d mean;
00648     Eigen::Vector3d point;
00649     NUMBER_OF_ACTIVE_CELLS = 0;
00650     for(unsigned int i=0; i<source.points.size(); i++)
00651     {
00652         point<<source.points[i].x,source.points[i].y,source.points[i].z;
00653 
00654         std::vector<NDTCell*> cells = targetNDT.getCellsForPoint(source.points[i],current_resolution);
00655         for(unsigned int j=0; j<cells.size(); j++)
00656         {
00657             cell = cells[j];
00658 
00659             //{
00660             //    if(!targetNDT.getCellForPoint(source.points[i],cell)) {
00661             //        continue;
00662             //  }
00663             if(cell == NULL)
00664             {
00665                 continue;
00666             }
00667             icov = cell->getInverseCov();
00668             mean = cell->getMean();
00669             double l = (point-mean).dot(icov*(point-mean));
00670             if(l*0 != 0) continue;
00671 
00672             if(l > 120) continue;
00673 
00674             score_here += (lfd1*exp(-lfd2*l/2));
00675             score_native += (targetNDT.getLikelihoodForPoint(source.points[i]));
00676             NUMBER_OF_ACTIVE_CELLS += 1;
00677         }
00678     }
00679 //    cout<<"here: "<<score_here<<" native: "<<score_native<<endl;
00680 //    score_here /= NUMBER_OF_POINTS;
00681     return score_here;
00682 }
00683 
00684 //compute the score gradient of a point cloud + transformation to an NDT
00685 void NDTMatcherP2D::derivativesPointCloud(pcl::PointCloud<pcl::PointXYZ> &source,
00686         NDTMap &targetNDT,
00687         Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> &transform,
00688 //      Eigen::Vector3d &eulerAngles,
00689         Eigen::Matrix<double,6,1> &score_gradient,
00690         Eigen::Matrix<double,6,6> &Hessian,
00691         bool computeHessian)
00692 {
00693 
00694     NDTCell *cell;
00695     Eigen::Vector3d transformed;
00696     Eigen::Matrix3d Cinv;
00697     //Eigen::Vector3d eulerAngles = transform.rotation().eulerAngles(0,1,2);
00698 
00699     Jest.setZero();
00700     Jest.block<3,3>(0,0).setIdentity();
00701     Hest.setZero();
00702 
00703     score_gradient.setZero();
00704     Hessian.setZero();
00705     //precompute angles for the derivative matrices
00706     //precomputeAngleDerivatives(eulerAngles);
00707 
00708     for(unsigned int i=0; i<source.points.size(); i++)
00709     {
00710         transformed<<source.points[i].x,source.points[i].y,source.points[i].z;
00711         //transformed = transform*transformed;
00712 
00713         // vector<NDTCell*> cells = targetNDT.getCellsForPoint(source.points[i],current_resolution);
00714         // for( int j=0; j<cells.size(); j++) {
00715         //      cell = cells[j];
00716         //
00717         {
00718             if(!targetNDT.getCellForPoint(source.points[i],cell))   //
00719             {
00720                 continue;
00721             }
00722 
00723             if(cell == NULL)
00724             {
00725                 continue;
00726             }
00727             transformed -=cell->getMean();
00728             Cinv = cell->getInverseCov();
00729 
00730             //compute Jest and Hest
00731             computeDerivatives(source.points[i]);
00732 
00733             //update score gradient
00734             if(!update_score_gradient(score_gradient, transformed, Cinv))
00735             {
00736                 continue;
00737             }
00738 
00739             //update hessian matrix
00740             if(computeHessian)
00741             {
00742                 update_hessian(Hessian, transformed, Cinv);
00743             }
00744             cell = NULL;
00745         }
00746     }    
00747     score_gradient = -score_gradient * (1.0 / source.points.size());
00748     Hessian = -Hessian * (1.0 / source.points.size());
00749 }
00750 
00751 //perform line search to find the best descent rate (More&Thuente)
00752 double NDTMatcherP2D::lineSearchMT(  Eigen::Matrix<double,6,1> &score_gradient_init,
00753         Eigen::Matrix<double,6,1> &increment,
00754         pcl::PointCloud<pcl::PointXYZ> &sourceCloud,
00755         Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> &globalT,
00756         NDTMap &targetNDT)
00757 {
00758 
00759     // default params
00760     double stp = 4.0; //default step
00761     double recoverystep = 0.05;
00762     double dginit = 0.0;
00763     double ftol = 0.0001; //epsilon 1
00764     double gtol = 0.9999; //epsilon 2
00765     double stpmax = 10.0;
00766     double stpmin = 0.0001;
00767     int maxfev = 10; //max function evaluations
00768     double xtol = 0.01; //window of uncertainty around the optimal step
00769 
00770     double direction = 1.0;
00771     //my temporary variables
00772     pcl::PointCloud<pcl::PointXYZ> cloudHere = sourceCloud;
00773     //cloudHere = lslgeneric::transformPointCloud(globalT,cloud);
00774     double score_init = 0.0;
00775 
00776     Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> ps,ps2;
00777     Eigen::Matrix<double,6,1> pincr, score_gradient_here;
00778     Eigen::Matrix<double,6,6> pseudoH;
00779     Eigen::Vector3d eulerAngles;
00781 
00782     int info = 0;                       // return code
00783     int infoc = 1;              // return code for subroutine cstep
00784 
00785     // Compute the initial gradient in the search direction and check
00786     // that s is a descent direction.
00787 
00788     //we want to maximize s, so we should minimize -s
00789     score_init = scorePointCloud(cloudHere,targetNDT);
00790 
00791     //gradient directions are opposite for the negated function
00792     //score_gradient_init = -score_gradient_init;
00793 
00794 //  cout<<"score_init "<<score_init<<endl;
00795 //  cout<<"score_gradient_init "<<score_gradient_init.transpose()<<endl;
00796 //  cout<<"increment "<<increment.transpose()<<endl;
00797 
00798     dginit = increment.dot(score_gradient_init);
00799 //  cout<<"dginit "<<dginit<<endl;
00800 
00801     if (dginit >= 0.0)
00802     {
00803 //    cout << "MoreThuente::cvsrch - wrong direction (dginit = " << dginit << ")" << endl;
00804         //return recoverystep; //TODO TSV -1; //
00805 
00806         increment = -increment;
00807         dginit = -dginit;
00808         direction = -1;
00809 
00810         if (dginit >= 0.0)
00811         {
00812 //    cout << "MoreThuente::cvsrch - Non-descent direction (dginit = " << dginit << ")" << endl;
00813             //stp = recoverystep;
00814             //newgrp.computeX(oldgrp, dir, stp);
00815             return recoverystep;
00816         }
00817     }
00818     else
00819     {
00820 //     cout<<"correct direction (dginit = " << dginit << ")" << endl;
00821     }
00822 
00823     // Initialize local variables.
00824 
00825     bool brackt = false;                // has the soln been bracketed?
00826     bool stage1 = true;         // are we in stage 1?
00827     int nfev = 0;                       // number of function evaluations
00828     double dgtest = ftol * dginit; // f for curvature condition
00829     double width = stpmax - stpmin; // interval width
00830     double width1 = 2 * width;  // ???
00831 
00832     //cout<<"dgtest "<<dgtest<<endl;
00833     // initial function value
00834     double finit = 0.0;
00835     finit = score_init;
00836 
00837     // The variables stx, fx, dgx contain the values of the step,
00838     // function, and directional derivative at the best step.  The
00839     // variables sty, fy, dgy contain the value of the step, function,
00840     // and derivative at the other endpoint of the interval of
00841     // uncertainty.  The variables stp, f, dg contain the values of the
00842     // step, function, and derivative at the current step.
00843 
00844     double stx = 0.0;
00845     double fx = finit;
00846     double dgx = dginit;
00847     double sty = 0.0;
00848     double fy = finit;
00849     double dgy = dginit;
00850 
00851     // Get the linear solve tolerance for adjustable forcing term
00852     double eta_original = -1.0;
00853     double eta = 0.0;
00854     eta = eta_original;
00855 
00856     // Start of iteration.
00857 
00858     double stmin, stmax;
00859     double fm, fxm, fym, dgm, dgxm, dgym;
00860 
00861     while (1)
00862     {
00863         // Set the minimum and maximum steps to correspond to the present
00864         // interval of uncertainty.
00865         if (brackt)
00866         {
00867             stmin = MoreThuente::min(stx, sty);
00868             stmax = MoreThuente::max(stx, sty);
00869         }
00870         else
00871         {
00872             stmin = stx;
00873             stmax = stp + 4 * (stp - stx);
00874         }
00875 
00876         // Force the step to be within the bounds stpmax and stpmin.
00877         stp = MoreThuente::max(stp, stpmin);
00878         stp = MoreThuente::min(stp, stpmax);
00879 
00880         // If an unusual termination is to occur then let stp be the
00881         // lowest point obtained so far.
00882 
00883         if ((brackt && ((stp <= stmin) || (stp >= stmax))) ||
00884                 (nfev >= maxfev - 1) || (infoc == 0) ||
00885                 (brackt && (stmax - stmin <= xtol * stmax)))
00886         {
00887             stp = stx;
00888         }
00889 
00890         // Evaluate the function and gradient at stp
00891         // and compute the directional derivative.
00893 
00894         pincr = stp*increment;
00895 
00896         ps = Eigen::Translation<double,3>(pincr(0),pincr(1),pincr(2))*
00897              Eigen::AngleAxisd(pincr(3),Eigen::Vector3d::UnitX())*
00898              Eigen::AngleAxisd(pincr(4),Eigen::Vector3d::UnitY())*
00899              Eigen::AngleAxisd(pincr(5),Eigen::Vector3d::UnitZ());
00900 
00901         //ps2 = ps*globalT;
00902         //eulerAngles = ps2.rotation().eulerAngles(0,1,2);
00903 
00904         //eulerAngles<<pincr(3),pincr(4),pincr(5);
00905         cloudHere = lslgeneric::transformPointCloud(ps,sourceCloud);
00906 
00907         double f = 0.0;
00908         f = scorePointCloud(cloudHere,targetNDT);
00909         score_gradient_here.setZero();
00910 
00911         ps2.setIdentity();
00912         derivativesPointCloud(cloudHere,targetNDT,ps2,score_gradient_here,pseudoH,false);
00913 
00914         //derivativesPointCloud(cloud,ndt,ps,score_gradient_here,pseudoH,false);
00915 
00916         //derivativesPointCloud(cloudHere,ndt,ps2,score_gradient_here,pseudoH,false);
00917         //negate score gradient
00918         //score_gradient_here = -score_gradient_here;
00919 
00920         //cout<<"incr " <<pincr.transpose()<<endl;
00921         //cout<<"scg  " <<score_gradient_here.transpose()<<endl;
00922         //cout<<"score (f) "<<f<<endl;
00923 
00924         //VALGRIND_CHECK_VALUE_IS_DEFINED(score_gradient_here);
00925         //VALGRIND_CHECK_VALUE_IS_DEFINED(increment);
00926         double dg = 0.0;
00927         dg = increment.dot(score_gradient_here);
00928 
00929 
00930         //VALGRIND_CHECK_VALUE_IS_DEFINED(dg);
00931         //cout<<"dg = "<<dg<<endl;
00932         nfev ++;
00933 
00935 
00936         //cout<<"consider step "<<stp<<endl;
00937         // Armijo-Goldstein sufficient decrease
00938         double ftest1 = finit + stp * dgtest;
00939         //cout<<"ftest1 is "<<ftest1<<endl;
00940 
00941         // Test for convergence.
00942 
00943         if ((brackt && ((stp <= stmin) || (stp >= stmax))) || (infoc == 0))
00944             info = 6;                   // Rounding errors
00945 
00946         if ((stp == stpmax) && (f <= ftest1) && (dg <= dgtest))
00947             info = 5;                   // stp=stpmax
00948 
00949         if ((stp == stpmin) && ((f > ftest1) || (dg >= dgtest)))
00950             info = 4;                   // stp=stpmin
00951 
00952         if (nfev >= maxfev)
00953             info = 3;                   // max'd out on fevals
00954 
00955         if (brackt && (stmax-stmin <= xtol*stmax))
00956             info = 2;                   // bracketed soln
00957 
00958         // RPP sufficient decrease test can be different
00959         bool sufficientDecreaseTest = false;
00960         sufficientDecreaseTest = (f <= ftest1);  // Armijo-Golstein
00961 
00962         //cout<<"ftest2 "<<gtol*(-dginit)<<endl;
00963         //cout<<"sufficientDecrease? "<<sufficientDecreaseTest<<endl;
00964         //cout<<"curvature ok? "<<(fabs(dg) <= gtol*(-dginit))<<endl;
00965         if ((sufficientDecreaseTest) && (fabs(dg) <= gtol*(-dginit)))
00966             info = 1;                   // Success!!!!
00967 
00968         if (info != 0)          // Line search is done
00969         {
00970             if (info != 1)              // Line search failed
00971             {
00972                 // RPP add
00973                 // counter.incrementNumFailedLineSearches();
00974 
00975                 //if (recoveryStepType == Constant)
00976                 stp = recoverystep;
00977 
00978                 //newgrp.computeX(oldgrp, dir, stp);
00979 
00980                 //message = "(USING RECOVERY STEP!)";
00981 
00982             }
00983             else                        // Line search succeeded
00984             {
00985                 //message = "(STEP ACCEPTED!)";
00986             }
00987 
00988             //print.printStep(nfev, stp, finit, f, message);
00989 
00990             // Returning the line search flag
00991             //cout<<"LineSearch::"<<message<<" info "<<info<<endl;
00992             return stp;
00993 
00994         } // info != 0
00995 
00996         // RPP add
00997         //counter.incrementNumIterations();
00998 
00999         // In the first stage we seek a step for which the modified
01000         // function has a nonpositive value and nonnegative derivative.
01001 
01002         if (stage1 && (f <= ftest1) && (dg >= MoreThuente::min(ftol, gtol) * dginit))
01003         {
01004             stage1 = false;
01005         }
01006 
01007         // A modified function is used to predict the step only if we have
01008         // not obtained a step for which the modified function has a
01009         // nonpositive function value and nonnegative derivative, and if a
01010         // lower function value has been obtained but the decrease is not
01011         // sufficient.
01012 
01013         if (stage1 && (f <= fx) && (f > ftest1))
01014         {
01015 
01016             // Define the modified function and derivative values.
01017 
01018             fm = f - stp * dgtest;
01019             fxm = fx - stx * dgtest;
01020             fym = fy - sty * dgtest;
01021             dgm = dg - dgtest;
01022             dgxm = dgx - dgtest;
01023             dgym = dgy - dgtest;
01024 
01025             // Call cstep to update the interval of uncertainty
01026             // and to compute the new step.
01027 
01028             //VALGRIND_CHECK_VALUE_IS_DEFINED(dgm);
01029             infoc = MoreThuente::cstep(stx,fxm,dgxm,sty,fym,dgym,stp,fm,dgm,
01030                                        brackt,stmin,stmax);
01031 
01032             // Reset the function and gradient values for f.
01033 
01034             fx = fxm + stx*dgtest;
01035             fy = fym + sty*dgtest;
01036             dgx = dgxm + dgtest;
01037             dgy = dgym + dgtest;
01038 
01039         }
01040 
01041         else
01042         {
01043 
01044             // Call cstep to update the interval of uncertainty
01045             // and to compute the new step.
01046 
01047             //VALGRIND_CHECK_VALUE_IS_DEFINED(dg);
01048             infoc = MoreThuente::cstep(stx,fx,dgx,sty,fy,dgy,stp,f,dg,
01049                                        brackt,stmin,stmax);
01050 
01051         }
01052 
01053         // Force a sufficient decrease in the size of the
01054         // interval of uncertainty.
01055 
01056         if (brackt)
01057         {
01058             if (fabs(sty - stx) >= 0.66 * width1)
01059                 stp = stx + 0.5 * (sty - stx);
01060             width1 = width;
01061             width = fabs(sty-stx);
01062         }
01063 
01064     } // while-loop
01065 
01066 }
01067 
01068 
01069 int NDTMatcherP2D::MoreThuente::cstep(double& stx, double& fx, double& dx,
01070         double& sty, double& fy, double& dy,
01071         double& stp, double& fp, double& dp,
01072         bool& brackt, double stmin, double stmax)
01073 {
01074     int info = 0;
01075 
01076     // Check the input parameters for errors.
01077 
01078     if ((brackt && ((stp <= MoreThuente::min(stx, sty)) || (stp >= MoreThuente::max(stx, sty)))) ||
01079             (dx * (stp - stx) >= 0.0) || (stmax < stmin))
01080         return info;
01081 
01082     // Determine if the derivatives have opposite sign.
01083 
01084     double sgnd = dp * (dx / fabs(dx));
01085 
01086     // First case. A higher function value.  The minimum is
01087     // bracketed. If the cubic step is closer to stx than the quadratic
01088     // step, the cubic step is taken, else the average of the cubic and
01089     // quadratic steps is taken.
01090 
01091     bool bound;
01092     double theta;
01093     double s;
01094     double gamma;
01095     double p,q,r;
01096     double stpc, stpq, stpf;
01097 
01098     if (fp > fx)
01099     {
01100         info = 1;
01101         bound = 1;
01102         theta = 3 * (fx - fp) / (stp - stx) + dx + dp;
01103         //VALGRIND_CHECK_VALUE_IS_DEFINED(theta);
01104         //VALGRIND_CHECK_VALUE_IS_DEFINED(dx);
01105         //VALGRIND_CHECK_VALUE_IS_DEFINED(dp);
01106         s = MoreThuente::absmax(theta, dx, dp);
01107         gamma = s * sqrt(((theta / s) * (theta / s)) - (dx / s) * (dp / s));
01108         if (stp < stx)
01109             gamma = -gamma;
01110 
01111         p = (gamma - dx) + theta;
01112         q = ((gamma - dx) + gamma) + dp;
01113         r = p / q;
01114         stpc = stx + r * (stp - stx);
01115         stpq = stx + ((dx / ((fx - fp) / (stp - stx) + dx)) / 2) * (stp - stx);
01116         if (fabs(stpc - stx) < fabs(stpq - stx))
01117             stpf = stpc;
01118         else
01119             stpf = stpc + (stpq - stpc) / 2;
01120 
01121         brackt = true;
01122     }
01123 
01124     // Second case. A lower function value and derivatives of opposite
01125     // sign. The minimum is bracketed. If the cubic step is closer to
01126     // stx than the quadratic (secant) step, the cubic step is taken,
01127     // else the quadratic step is taken.
01128 
01129     else if (sgnd < 0.0)
01130     {
01131         info = 2;
01132         bound = false;
01133         theta = 3 * (fx - fp) / (stp - stx) + dx + dp;
01134         s = MoreThuente::absmax(theta,dx,dp);
01135         gamma = s * sqrt(((theta/s) * (theta/s)) - (dx / s) * (dp / s));
01136         if (stp > stx)
01137             gamma = -gamma;
01138         p = (gamma - dp) + theta;
01139         q = ((gamma - dp) + gamma) + dx;
01140         r = p / q;
01141         stpc = stp + r * (stx - stp);
01142         stpq = stp + (dp / (dp - dx)) * (stx - stp);
01143         if (fabs(stpc - stp) > fabs(stpq - stp))
01144             stpf = stpc;
01145         else
01146             stpf = stpq;
01147         brackt = true;
01148     }
01149 
01150     // Third case. A lower function value, derivatives of the same sign,
01151     // and the magnitude of the derivative decreases.  The cubic step is
01152     // only used if the cubic tends to infinity in the direction of the
01153     // step or if the minimum of the cubic is beyond stp. Otherwise the
01154     // cubic step is defined to be either stmin or stmax. The
01155     // quadratic (secant) step is also computed and if the minimum is
01156     // bracketed then the the step closest to stx is taken, else the
01157     // step farthest away is taken.
01158 
01159     else if (fabs(dp) < fabs(dx))
01160     {
01161         info = 3;
01162         bound = true;
01163         theta = 3 * (fx - fp) / (stp - stx) + dx + dp;
01164         s = MoreThuente::absmax(theta, dx, dp);
01165 
01166         // The case gamma = 0 only arises if the cubic does not tend
01167         // to infinity in the direction of the step.
01168 
01169         gamma = s * sqrt(max(0,(theta / s) * (theta / s) - (dx / s) * (dp / s)));
01170         if (stp > stx)
01171             gamma = -gamma;
01172 
01173         p = (gamma - dp) + theta;
01174         q = (gamma + (dx - dp)) + gamma;
01175         r = p / q;
01176         if ((r < 0.0) && (gamma != 0.0))
01177             stpc = stp + r * (stx - stp);
01178         else if (stp > stx)
01179             stpc = stmax;
01180         else
01181             stpc = stmin;
01182 
01183         stpq = stp + (dp/ (dp - dx)) * (stx - stp);
01184         if (brackt)
01185         {
01186             if (fabs(stp - stpc) < fabs(stp - stpq))
01187                 stpf = stpc;
01188             else
01189                 stpf = stpq;
01190         }
01191         else
01192         {
01193             if (fabs(stp - stpc) > fabs(stp - stpq))
01194                 stpf = stpc;
01195             else
01196                 stpf = stpq;
01197         }
01198     }
01199 
01200     // Fourth case. A lower function value, derivatives of the same
01201     // sign, and the magnitude of the derivative does not decrease. If
01202     // the minimum is not bracketed, the step is either stmin or
01203     // stmax, else the cubic step is taken.
01204 
01205     else
01206     {
01207         info = 4;
01208         bound = false;
01209         if (brackt)
01210         {
01211             theta = 3 * (fp - fy) / (sty - stp) + dy + dp;
01212             s = MoreThuente::absmax(theta, dy, dp);
01213             gamma = s * sqrt(((theta/s)*(theta/s)) - (dy / s) * (dp / s));
01214             if (stp > sty)
01215                 gamma = -gamma;
01216             p = (gamma - dp) + theta;
01217             q = ((gamma - dp) + gamma) + dy;
01218             r = p / q;
01219             stpc = stp + r * (sty - stp);
01220             stpf = stpc;
01221         }
01222         else if (stp > stx)
01223             stpf = stmax;
01224         else
01225             stpf = stmin;
01226     }
01227 
01228     // Update the interval of uncertainty. This update does not depend
01229     // on the new step or the case analysis above.
01230 
01231     if (fp > fx)
01232     {
01233         sty = stp;
01234         fy = fp;
01235         dy = dp;
01236     }
01237     else
01238     {
01239         if (sgnd < 0.0)
01240         {
01241             sty = stx;
01242             fy = fx;
01243             dy = dx;
01244         }
01245         stx = stp;
01246         fx = fp;
01247         dx = dp;
01248     }
01249 
01250     // Compute the new step and safeguard it.
01251 
01252     stpf = MoreThuente::min(stmax, stpf);
01253     stpf = MoreThuente::max(stmin, stpf);
01254     stp = stpf;
01255     if (brackt && bound)
01256     {
01257         if (sty > stx)
01258             stp = min(stx + 0.66 * (sty - stx), stp);
01259         else
01260             stp = max(stx + 0.66 * (sty - stx), stp);
01261     }
01262 
01263     return info;
01264 
01265 }
01266 
01267 double NDTMatcherP2D::MoreThuente::min(double a, double b)
01268 {
01269     return (a < b ? a : b);
01270 }
01271 
01272 double NDTMatcherP2D::MoreThuente::max(double a, double b)
01273 {
01274     return (a > b ? a : b);
01275 }
01276 
01277 double NDTMatcherP2D::MoreThuente::absmax(double a, double b, double c)
01278 {
01279     a = fabs(a);
01280     b = fabs(b);
01281     c = fabs(c);
01282 
01283     if (a > b)
01284         return (a > c) ? a : c;
01285     else
01286         return (b > c) ? b : c;
01287 }
01288 
01289 pcl::PointCloud<pcl::PointXYZ> NDTMatcherP2D::subsample(pcl::PointCloud<pcl::PointXYZ>& original)
01290 {
01291 
01292     std::string subsampleType = "GRID";
01293     if(subsampleType == "NONE")
01294     {
01295         return original;
01296     }
01297     if(subsampleType == "GRID")
01298     {
01299         double subsampleRes = subsample_size;//current_resolution/2;
01300         pcl::PointCloud<pcl::PointXYZ> res;
01301         LazyGrid prototype(subsampleRes);
01302         NDTMap ndt( &prototype );
01303         ndt.loadPointCloud( original );
01304         std::vector<NDTCell*>::iterator it = ndt.getMyIndex()->begin();
01305 
01306         while(it!=ndt.getMyIndex()->end())
01307         {
01308             NDTCell* ndcell = (*it);
01309             if(ndcell!=NULL)
01310             {
01311                 if(ndcell->points_.size() > 0)
01312                 {
01313                     res.points.push_back(ndcell->points_.front());
01314                 }
01315             }
01316             it++;
01317         }
01318         return res;
01319 
01320     }
01321 
01322 #if 0
01323     if(subsampleType == "MEAN")
01324     {
01325         pcl::PointCloud<pcl::PointXYZ> res;
01326 
01327         NDTMap ndt( new OctTree<PointSource>() );
01328         ndt.loadPointCloud( original );
01329         ndt.computeNDTCells();
01330         typename std::vector<Cell<PointSource>*>::iterator it = ndt.getMyIndex()->begin();
01331 
01332         while(it!=ndt.getMyIndex()->end())
01333         {
01334             NDTCell<PointSource>* ndcell = dynamic_cast<NDTCell<PointSource>*>(*it);
01335             if(ndcell!=NULL)
01336             {
01337                 if(ndcell->points_.size() > 0)
01338                 {
01339                     PointSource pt;
01340                     Eigen::Vector3d m = ndcell->getMean();
01341                     pt.x = m(0);
01342                     pt.y = m(1);
01343                     pt.z = m(2);
01344                     res.points.push_back(pt);
01345                 }
01346             }
01347             it++;
01348         }
01349         return res;
01350 
01351     }
01352 
01353     if(subsampleType == "TREE")
01354     {
01355         //   double subsampleRes = 0.2;
01356         pcl::PointCloud<PointSource> res;
01357         //LazyGrid prototype(subsampleRes);
01358         //NDTMap ndt( &prototype );
01359 
01360         NDTMap<PointSource> ndt( new OctTree<PointSource>() );
01361         ndt.loadPointCloud( original );
01362         ndt.computeNDTCells();
01363         typename std::vector<Cell<PointSource>*>::iterator it = ndt.getMyIndex()->begin();
01364 
01365         while(it!=ndt.getMyIndex()->end())
01366         {
01367             NDTCell<PointSource>* ndcell = dynamic_cast<NDTCell<PointSource>*>(*it);
01368             if(ndcell!=NULL)
01369             {
01370                 if(ndcell->points_.size() > 0)
01371                 {
01372                     res.points.push_back(ndcell->points_.front());
01373                 }
01374             }
01375             it++;
01376         }
01377         return res;
01378     }
01379 #endif
01380 
01381     return original;
01382 }
01383 
01384 double NDTMatcherP2D::normalizeAngle(double a)
01385 {
01386     //set the angle between -M_PI and M_PI
01387     return atan2(sin(a), cos(a));
01388 
01389 }
01390 
01391 }


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