ndt_matcher_sequential_d2d.hpp
Go to the documentation of this file.
00001 #include "ndt_map/oc_tree.h"
00002 #include "ndt_map/ndt_cell.h"
00003 #include "ndt_map/lazy_grid.h"
00004 #include "pointcloud_vrml/pointcloud_utils.h"
00005 #include "Eigen/Eigen"
00006 #include <fstream>
00007 #include <omp.h>
00008 
00009 #include <gsl/gsl_math.h>
00010 #include <gsl/gsl_deriv.h>
00011 #include <gsl/gsl_multimin.h>
00012 
00013 namespace lslgeneric
00014 {
00015 
00016 double transforms_objective_xyt (double &x, double &y, double&z, double&r,double&p,double &t, void *params) {
00017     double res = 0;
00018     TransformParams *tf = (TransformParams*) params;
00019     if (tf == NULL) return 0;
00020     Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> G,Temp;
00021     Eigen::Matrix<double,4,4> I;
00022     I.setIdentity();
00023     Eigen::Vector3d et;
00024     
00025     G =  Eigen::Translation<double,3>(x,y,z)*
00026         Eigen::AngleAxis<double>(r,Eigen::Vector3d::UnitX())*
00027         Eigen::AngleAxis<double>(p,Eigen::Vector3d::UnitY())*
00028         Eigen::AngleAxis<double>(t,Eigen::Vector3d::UnitZ()) ;
00029 
00030     for(int i=0; i<tf->fk.size(); i++) 
00031     {
00032         Temp = tf->fk[i]*tf->rg[i].inverse();
00033         if((Temp.translation()).norm() + Temp.rotation().eulerAngles(0,1,2).norm() > 0.5) 
00034         {
00035             std::cout<<"ignoring outlier at "<<i<<std::endl;
00036             continue;
00037         }
00038 
00039         Temp = G*tf->rg[i]*G.inverse()*tf->fk[i].inverse();
00040         //Temp = tf->fk[i]*G.inverse()*tf->rg[i].inverse()*G;
00041         //Temp = G*tf->fk[i]*G.inverse()*tf->rg[i].inverse();
00042         //r = (Temp.translation()).norm() + Temp.rotation().eulerAngles(0,1,2).norm();
00043 //      et = ((tf->rg[i].rotation())*(G.rotation().transpose())*(tf->fk[i].rotation().transpose()) - tf->rg[i].rotation())*G.translation() -
00044 //          tf->rg[i].rotation()*(G.rotation().transpose())*tf->fk[i].translation() + tf->rg[i].translation();
00045 
00046         //et = (G.inverse()*tf->fk[i]*G).translation() - tf->rg[i].translation();
00047         //this one seems nice in some way...
00048         //et = (G*tf->fk[i]*G.inverse()).translation() - tf->rg[i].translation();
00049 //      r = et.norm(); //
00050 //      std::cout<<i<<" : "<<Temp.translation().transpose()<<" "<<et.transpose()<<" R "<<r<<std::endl;
00051         
00052         //et = (G*tf->fk[i]).translation() - (tf->rg[i]*G).translation();
00053         //res +=et.norm();
00054         Eigen::AngleAxis<double> ax;
00055         ax.fromRotationMatrix(Temp.rotation());
00056         res += Temp.translation().norm();// + ax.angle();
00057     }
00058 
00059     return res;
00060 } 
00061 
00062 #if 0
00063 //define objective on two vectors of Eigen transforms and a 6-d pose
00064 double transforms_objective (const gsl_vector *v, void *params) {
00065     double res = 0, r=0;
00066     TransformParams *tf = (TransformParams*) params;
00067     if (tf == NULL) return 0;
00068     Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> G,Temp;
00069     Eigen::Matrix<double,4,4> I;
00070     I.setIdentity();
00071     Eigen::Vector3d et;
00072 /*
00073     G =  Eigen::Translation<double,3>(gsl_vector_get(v,0),gsl_vector_get(v,1),gsl_vector_get(v,2))*
00074         Eigen::AngleAxis<double>(gsl_vector_get(v,3),Eigen::Vector3d::UnitX()) *
00075         Eigen::AngleAxis<double>(gsl_vector_get(v,4),Eigen::Vector3d::UnitY()) *
00076         Eigen::AngleAxis<double>(gsl_vector_get(v,5),Eigen::Vector3d::UnitZ()) ;
00077         */
00078     G =  Eigen::Translation<double,3>(gsl_vector_get(v,0),gsl_vector_get(v,1),0)*
00079         Eigen::AngleAxis<double>(gsl_vector_get(v,2),Eigen::Vector3d::UnitZ()) ;
00080 
00081     for(int i=0; i<tf->fk.size(); i++) 
00082     {
00083         Temp = tf->fk[i]*tf->rg[i].inverse();
00084         if((Temp.translation()).norm() + Temp.rotation().eulerAngles(0,1,2).norm() > 0.2) 
00085         {
00086             std::cout<<"ignoring outlier at "<<i<<std::endl;
00087             continue;
00088         }
00089 
00090         Temp = G*tf->rg[i]*G.inverse()*tf->fk[i].inverse();
00091         //Temp = G*tf->fk[i].inverse()*G.inverse()*tf->rg[i];
00092         //Temp = G*tf->fk[i]*G.inverse()*tf->rg[i].inverse();
00093         //r = (Temp.translation()).norm() + Temp.rotation().eulerAngles(0,1,2).norm();
00094         et = ((tf->rg[i].rotation())*(G.rotation().transpose())*(tf->fk[i].rotation().transpose()) - tf->rg[i].rotation())*G.translation() -
00095             tf->rg[i].rotation()*(G.rotation().transpose())*tf->fk[i].translation() + tf->rg[i].translation();
00096         et = (G*tf->fk[i]*G.inverse()).translation() - tf->rg[i].translation();
00097         //r = Temp.translation().norm();//
00098         r = et.norm(); //
00099 //      std::cout<<i<<" : "<<Temp.translation().transpose()<<" "<<et.transpose()<<" R "<<r<<std::endl;
00100         
00101         res +=r;
00102     }
00103 
00104     return res;
00105 } 
00106 #endif
00107 
00108 template <typename PointSource>
00109 void deallocate(std::vector<NDTCell<PointSource>* > &ndts) {
00110             for(unsigned int i=0; i<ndts.size(); i++)
00111             {
00112                 if(ndts[i]!=NULL)
00113                     delete ndts[i];
00114             }
00115 }
00116 
00117 //#define DO_DEBUG_PROC
00118 
00119 template <typename PointSource>
00120 bool NDTMatcherSequentialD2D<PointSource>::add_cloud( pcl::PointCloud<PointSource>& cloud,
00121         Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor>& Tref) 
00122 {
00123     pcs.push_back(cloud);
00124     LazyGrid<PointSource> prototype(current_resolution);
00125     NDTMap<PointSource> *NDT = new NDTMap<PointSource>( &prototype );
00126     NDT->loadPointCloud( cloud );
00127     NDT->computeNDTCells();
00128 
00129     transforms.push_back(Tref);
00130     maps.push_back(NDT);
00131 }
00132 
00133 template <typename PointSource>
00134 bool NDTMatcherSequentialD2D<PointSource>::match_all(Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor>& RES, bool useInitialGuess) 
00135 {
00136 
00137     double __res[] = {0.1,0.2};
00138     //double __res[] = {0.5,1};
00139     std::vector<double> resolutions (__res, __res+sizeof(__res)/sizeof(double));
00140     std::vector<Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor>, 
00141         Eigen::aligned_allocator<Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> > > reg_transforms, rel_transforms, err_transforms;
00142 
00143     lslgeneric::NDTMatcherD2D<PointSource,PointSource> matcherD2D(false, false, resolutions);
00144     Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> Tout, tempT; 
00145     Tout.setIdentity();
00146 
00147     char fname[50];
00148     FILE *fout;
00149 
00150     for(int i=1; i<pcs.size(); ++i) 
00151     {
00152         Tout.setIdentity();
00153         Tout = (transforms[i-1].inverse()*transforms[i]);
00154         std::cout<<Tout.matrix()<<std::endl;
00155         bool ret = matcherD2D.match(pcs[i-1],pcs[i],Tout,true);
00156         reg_transforms.push_back(Tout);
00157         
00158         snprintf(fname,49,"c_offset_%02d.wrl",i);
00159         fout = fopen(fname,"w");
00160         fprintf(fout,"#VRML V2.0 utf8\n");
00161         lslgeneric::writeToVRML<PointSource>(fout,pcs[i-1],Eigen::Vector3d(1,0,0));
00162         //lslgeneric::writeToVRML<PointSource>(fout,pcs[i],Eigen::Vector3d(1,1,1));
00163         pcl::PointCloud<PointSource> tmp1 = pcs[i];
00164         tempT =  (transforms[i-1].inverse()*transforms[i]);
00165         lslgeneric::transformPointCloudInPlace<PointSource>(tempT,tmp1);
00166         lslgeneric::writeToVRML<PointSource>(fout,tmp1,Eigen::Vector3d(1,1,1));
00167         pcl::PointCloud<PointSource> tmp2 = pcs[i];
00168         lslgeneric::transformPointCloudInPlace<PointSource>(Tout,tmp2);
00169         lslgeneric::writeToVRML<PointSource>(fout,tmp2,Eigen::Vector3d(0,1,0));
00170         fclose(fout);
00171         
00172 /*        
00173 */
00174     }
00175 
00176     for(int i=1; i<transforms.size(); ++i) 
00177     {
00178         std::cout<<"rel: "<<i<<std::endl;
00179         rel_transforms.push_back( (transforms[i-1].inverse()*transforms[i]));
00180         std::cout<<rel_transforms[i-1].translation().transpose()<<" "<<rel_transforms[i-1].rotation().eulerAngles(0,1,2).transpose()<<std::endl;
00181         std::cout<<reg_transforms[i-1].translation().transpose()<<" "<<reg_transforms[i-1].rotation().eulerAngles(0,1,2).transpose()<<std::endl;
00182     }
00183 #if 0
00184     Eigen::Vector3d v,x;
00185     Eigen::Matrix3d M, U, L;
00186     //now the optimization part...
00187     //go through transforms vector and compute relative transforms
00188     for(int i=1; i<transforms.size(); ++i) 
00189     {
00190         Tout.setIdentity();
00191         U = (rel_transforms[i-1].rotation()).llt().matrixL();
00192         L = (reg_transforms[i-1].rotation()).llt().matrixL();
00193         Tout.rotate(U.transpose()*L);
00194         v = rel_transforms[i-1].translation() - Tout.rotation().transpose()*(reg_transforms[i-1].translation());
00195         M = Tout.rotation().transpose()*reg_transforms[i-1].rotation() - Eigen::Matrix3d::Identity();
00196 
00197         Eigen::JacobiSVD<Eigen::Matrix3d> svd(M, Eigen::ComputeFullU | Eigen::ComputeFullV);
00198         x = svd.solve(v);
00199         std::cout<<"M = "<<M<<std::endl;
00200         std::cout<<"v = "<<v.transpose()<<std::endl;
00201         std::cout<<"x = "<<x.transpose()<<std::endl;
00202         Tout.translation() = x; 
00203         
00204         std::cout<<Tout.translation().transpose()<<" "<<Tout.rotation().eulerAngles(0,1,2).transpose()<<std::endl;
00205         err_transforms.push_back(Tout);
00206     }
00207 
00208 #endif
00209 
00210 #if 0
00211     TransformParams tf;
00212     tf.fk = rel_transforms;
00213     tf.rg = reg_transforms;
00214 
00215     const gsl_multimin_fminimizer_type *T = 
00216         gsl_multimin_fminimizer_nmsimplex2;
00217     gsl_multimin_fminimizer *s = NULL;
00218     gsl_vector *ss, *x;
00219     gsl_multimin_function minex_func;
00220 
00221     size_t iter = 0;
00222     int status;
00223     double size;
00224 
00225     /* Starting point */
00226     x = gsl_vector_alloc (3);
00227     gsl_vector_set_all (x, 0.0);
00228  /*   gsl_vector_set(x, 0, 1.18);
00229     gsl_vector_set(x, 1, -0.3);
00230     gsl_vector_set(x, 2, 0);
00231  */ 
00232     /* Set initial step sizes to 1 */
00233     ss = gsl_vector_alloc (3);
00234     gsl_vector_set_all (ss, 1);
00235 
00236     /* Initialize method and iterate */
00237     minex_func.n = 3;
00238     minex_func.f = transforms_objective;
00239     minex_func.params = &tf;
00240 
00241     s = gsl_multimin_fminimizer_alloc (T, 3);
00242     gsl_multimin_fminimizer_set (s, &minex_func, x, ss);
00243 
00244     do
00245     {
00246         iter++;
00247         status = gsl_multimin_fminimizer_iterate(s);
00248 
00249         if (status) 
00250             break;
00251 
00252         size = gsl_multimin_fminimizer_size (s);
00253         status = gsl_multimin_test_size (size, 1e-2);
00254 
00255         if (status == GSL_SUCCESS)
00256         {
00257             printf ("converged to minimum at\n");
00258         }
00259 
00260         printf ("%5d %10.3e %10.3e %10.3ef() = %7.3f size = %.3f\n", 
00261                 iter,
00262                 gsl_vector_get (s->x, 0), 
00263                 gsl_vector_get (s->x, 1), 
00264                 gsl_vector_get (s->x, 2), 
00265 //              gsl_vector_get (s->x, 3), 
00266 //              gsl_vector_get (s->x, 4), 
00267 //              gsl_vector_get (s->x, 5), 
00268                 s->fval, size);
00269     }
00270     while (status == GSL_CONTINUE && iter < 200);
00271     RES =  Eigen::Translation<double,3>(gsl_vector_get(s->x,0),gsl_vector_get(s->x,1),0)* //gsl_vector_get(s->x,2))*
00272 //      Eigen::AngleAxis<double>(gsl_vector_get(s->x,3),Eigen::Vector3d::UnitX()) *
00273 //      Eigen::AngleAxis<double>(gsl_vector_get(s->x,4),Eigen::Vector3d::UnitY()) *
00274         Eigen::AngleAxis<double>(gsl_vector_get(s->x,2),Eigen::Vector3d::UnitZ()) ;
00275 
00276     gsl_vector_free(x);
00277     gsl_vector_free(ss);
00278     gsl_multimin_fminimizer_free (s);
00279 #endif
00280 
00281     TransformParams tf;
00282     tf.fk = rel_transforms;
00283     tf.rg = reg_transforms;
00284 
00285     double res_min = 0.004, res_max = 0.01;
00286     double res = res_max;
00287 
00288     double xmin = -0.1, xmax =0.1;
00289     double ymin = -0.1, ymax =0.1;
00290     double zmin = -0.1, zmax =0.1;
00291     double rmin = -0.1, rmax =0.1;
00292     double pmin = -0.1, pmax =0.1;
00293     double tmin = -0.1, tmax =0.1;
00294 
00295     double xx=0,yy=0,zz=0,rr=0,pp=0,tt=0;
00296     int ctr =0;
00297     double score_min = INT_MAX;
00298     double score_here;
00299 
00300     double y = 0;
00301 //    double z = 0;
00302     double r=0; 
00303     double p=0;
00304     while ( res > res_min) {
00305         for(double x=xmin; x<xmax; x+=res) {
00306 //          for(double y=ymin; y<ymax; y+=res) {
00307                 for(double z=zmin; z<zmax; z+=res) {
00308 //                  for(double r=rmin; r<rmax; r+=res) {
00309 //                      for(double p=pmin; p<pmax; p+=res) {
00310                             for(double t=tmin; t<tmax; t+=res) {
00311                                 score_here = transforms_objective_xyt (x,y,z,r,p,t,(void*)&tf);
00312                                 if(score_here < score_min) {
00313                                     xx = x;
00314                                     yy = y;
00315                                     zz = z;
00316                                     rr = r;
00317                                     pp = p;
00318                                     tt = t;
00319                                     score_min = score_here;
00320                                     std::cout<<"new min of "<<score_here<<" at "<<x<<" "<<y<<" "<<" "<<z<<" "<<r<<" "<<p<<" "<<t<<std::endl;
00321                                 }               
00322                                 //if(ctr%100 == 0) std::cout<<"x y t"<<x<<" "<<y<<" "<<t<<std::endl;
00323                                 ctr++;              
00324                             }
00325 //                      }
00326 //                  }
00327                 }
00328 //          }
00329         }
00330         res = res/2;
00331         xmin = xx-10*res;
00332         ymin = yy-10*res;
00333         zmin = zz-10*res;
00334         rmin = rr-2*res;
00335         pmin = pp-2*res;
00336         tmin = tt-10*res;
00337         xmax = xx+10*res;
00338         ymax = yy+10*res;
00339         zmax = zz+10*res;
00340         rmax = rr+2*res;
00341         pmax = pp+2*res;
00342         tmax = tt+10*res;
00343         std::cout<<"going to RES "<<res<<" bounds +/- "<<xmax<<" "<<ymax<<" "<<zmax<<" "<<rmax<<" "<<pmax<<" "<<tmax<<std::endl;
00344     }
00345     
00346     std::cout<<"FINAL min at "<<score_min<<" at "<<xx<<" "<<yy<<" "<<zz<<" "<<rr<<" "<<pp<<" "<<tt<<std::endl;
00347     Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> RES2;
00348     RES =  Eigen::Translation<double,3>(xx,yy,zz)* //gsl_vector_get(s->x,2))*
00349         Eigen::AngleAxis<double>(tt,Eigen::Vector3d::UnitZ()) ;
00350 
00351     for(int i=1; i<pcs.size(); ++i) 
00352     {
00353         snprintf(fname,49,"calib_offset_%02d.wrl",i);
00354         fout = fopen(fname,"w");
00355         fprintf(fout,"#VRML V2.0 utf8\n");
00356         pcl::PointCloud<PointSource> tmp0 = pcs[i-1];
00357         //RES2 = transforms[i-1].inverse()*RES*transforms[i-1];
00358         //std::cout<<"Rinv = "<<RES2.matrix()<<std::endl;
00359         //tempT = RES*transforms[i-1];
00360         tempT = transforms[i-1]*RES;
00361         lslgeneric::transformPointCloudInPlace<PointSource>(tempT,tmp0);
00362         lslgeneric::writeToVRML<PointSource>(fout,tmp0,Eigen::Vector3d(1,0,0));
00363         pcl::PointCloud<PointSource> tmp1 = pcs[i];
00364         //RES2 = transforms[i].inverse()*RES*transforms[i];
00365         tempT = transforms[i]*RES;
00366         lslgeneric::transformPointCloudInPlace<PointSource>(tempT,tmp1);
00367         lslgeneric::writeToVRML<PointSource>(fout,tmp1,Eigen::Vector3d(1,1,1));
00368         tmp0 = pcs[i-1];
00369         tempT = transforms[i-1];
00370         lslgeneric::transformPointCloudInPlace<PointSource>(tempT,tmp0);
00371         lslgeneric::writeToVRML<PointSource>(fout,tmp0,Eigen::Vector3d(1,1,0));
00372         tmp1 = pcs[i];
00373         tempT = transforms[i];
00374         lslgeneric::transformPointCloudInPlace<PointSource>(tempT,tmp1);
00375         lslgeneric::writeToVRML<PointSource>(fout,tmp1,Eigen::Vector3d(1,0,1));
00376         fclose(fout);
00377 
00378 
00379     }
00380 }
00381 
00382 #if 0
00383 template <typename PointSource>
00384 bool NDTMatcherSequentialD2D<PointSource>::match_all(Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor>& T, bool useInitialGuess) 
00385 {
00386 
00387     //locals
00388     bool convergence = false;
00389     //double score=0;
00390     double DELTA_SCORE = 10e-3*current_resolution;
00391     //double DELTA_SCORE = 0.0005;
00392     //double NORM_MAX = current_resolution, ROT_MAX = M_PI/10; //
00393     int itr_ctr = 0;
00394     //double alpha = 0.95;
00395     double step_size = 1;
00396     Eigen::Matrix<double,6,1>  pose_increment_v, pose_accum, scg;
00397     Eigen::MatrixXd Hessian(6,6), score_gradient(6,1); //column vectors, pose_increment_v(6,1)
00398     Eigen::MatrixXd Hessian_loc(6,6), score_gradient_loc(6,1); //column vectors, pose_increment_v(6,1)
00399 
00400     Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> TR, Tloc;
00401     Eigen::Vector3d transformed_vec, mean;
00402     bool ret = true;
00403     if(!useInitialGuess)
00404     {
00405         T.setIdentity();
00406     }
00407 
00408     Eigen::Array<double,6,1> weights;
00409     Eigen::Quaterniond qsum, qloc;
00410     Eigen::Vector4d qsum_vec, qloc_vec;
00411 
00412 //    std::cout<<"pose(:,"<<1<<") = ["<<T.translation().transpose()<<" "<<T.rotation().eulerAngles(0,1,2).transpose()<<"]';\n";
00413     while(!convergence)
00414     {
00415         pose_accum.setZero();
00416         double score_here = 0;
00417         int nsuccess =0;
00418         for(int i=0; i<maps.size(); i++) 
00419         {
00420             TR.setIdentity();
00421             Hessian.setZero();
00422             score_gradient.setZero();
00423             Tloc = transforms[i]*T;
00424             std::vector<NDTCell<PointSource>*> nextNDT = maps[i]->pseudoTransformNDT(Tloc);
00425             std::vector<NDTCell<PointSource>*> fixedNDT;
00426 //          for(int j=0; j<maps.size(); j++) 
00427             for(int j=i-3; j<i+3; j++) 
00428             {
00429                 if(j < 0 || j >= maps.size()) continue;
00430                 if(i == j) continue;
00431                 Tloc = transforms[j]*T;
00432                 std::vector<NDTCell<PointSource>*> locNDT = maps[j]->pseudoTransformNDT(Tloc);
00433                 fixedNDT.insert(fixedNDT.begin(), locNDT.begin(), locNDT.end());
00434             }
00435             score_here += derivativesNDT(nextNDT,fixedNDT,score_gradient,Hessian,true);
00436             
00437             scg = score_gradient;
00438             Eigen::SelfAdjointEigenSolver<Eigen::Matrix<double,6,6> > Sol (Hessian);
00439             Eigen::Matrix<double,6,1> evals = Sol.eigenvalues().real();
00440             double minCoeff = evals.minCoeff();
00441             double maxCoeff = evals.maxCoeff();
00442             if(minCoeff < 0 )   
00443             {
00444                 Eigen::Matrix<double,6,6> evecs = Sol.eigenvectors().real();
00445                 double regularizer = 0.01*maxCoeff - minCoeff;
00446                 Eigen::Matrix<double,6,1> reg;
00447                 //ugly
00448                 reg<<regularizer,regularizer,regularizer,regularizer,regularizer,regularizer;
00449                 evals += reg;
00450                 Eigen::Matrix<double,6,6> Lam;
00451                 Lam = evals.asDiagonal();
00452                 Hessian = evecs*Lam*(evecs.transpose());
00453                 std::cerr<<"regularizing\n";
00454             }
00455 
00456             //std::cout<<"s("<<itr_ctr+1<<") = "<<score_here<<";\n";
00457             //std::cout<<"H(:,:,"<<itr_ctr+1<<")  =  ["<< Hessian<<"];\n"<<std::endl;                             //
00458             //std::cout<<"grad (:,"<<itr_ctr+1<<")= ["<<score_gradient.transpose()<<"];"<<std::endl;         //
00459 
00460             if (score_gradient.norm()<= DELTA_SCORE)
00461             {
00462                 //          std::cout<<"incr(:,"<<itr_ctr+1<<") = [0 0 0 0 0 0]';\n";
00463                 std::cout<<"\%gradient vanished\n";
00464                 deallocate(nextNDT);
00465                 deallocate(fixedNDT);
00466                 continue;
00467             }
00468 
00469             pose_increment_v = -Hessian.ldlt().solve(score_gradient);
00470             double dginit = pose_increment_v.dot(scg);
00471             if(dginit > 0)
00472             {
00473                 std::cout<<"\%can't decrease in this direction any more, done \n";
00474                 deallocate(nextNDT);
00475                 deallocate(fixedNDT);
00476                 continue;
00477             }
00478 
00479             step_size = lineSearchMT(pose_increment_v,nextNDT,fixedNDT);
00480 //          step_size = 0.1;
00481             pose_increment_v = step_size*pose_increment_v;
00482             std::cout<<"\%iteration "<<itr_ctr<<" pose "<<(pose_increment_v.transpose())<<" score "<<score_here<<" step "<<step_size<<std::endl;
00483             if(pose_increment_v.norm() > 1) {
00484                 deallocate(nextNDT);
00485                 deallocate(fixedNDT);
00486                 continue;
00487             }
00488             qloc = Eigen::AngleAxis<double>(pose_increment_v(3),Eigen::Vector3d::UnitX()) *
00489                 Eigen::AngleAxis<double>(pose_increment_v(4),Eigen::Vector3d::UnitY()) *
00490                 Eigen::AngleAxis<double>(pose_increment_v(5),Eigen::Vector3d::UnitZ()) ;
00491 
00492             qloc_vec(0) = qloc.x();
00493             qloc_vec(1) = qloc.y();
00494             qloc_vec(2) = qloc.z();
00495             qloc_vec(3) = qloc.w();
00496             qsum_vec = qsum_vec+qloc_vec;
00497             std::cout<<"Q "<<qsum_vec.transpose()<<"--"<<qloc_vec.transpose()<<std::endl;
00498             pose_accum += pose_increment_v;
00499             nsuccess ++;
00500             
00501             deallocate(nextNDT);
00502             deallocate(fixedNDT);
00503 
00504         }
00505         pose_accum /= nsuccess;
00506         qsum_vec = qsum_vec/nsuccess;
00507 
00508         std::cout<<"qs "<<qsum_vec.transpose()<<std::endl;      
00509         qsum.x() = qsum_vec(0);
00510         qsum.y() = qsum_vec(1);
00511         qsum.z() = qsum_vec(2);
00512         qsum.w() = qsum_vec(3);
00513         qsum.normalize();
00514 
00515         TR.setIdentity();
00516         TR =  Eigen::Translation<double,3>(pose_accum(0),pose_accum(1),0)*qsum;
00517 
00518         T = TR*T;
00519         std::cout<<"incr(:,"<<itr_ctr+1<<") = ["<<TR.translation().transpose()<<" "<<TR.rotation().eulerAngles(0,1,2).transpose()<<"]';\n";
00520         std::cout<<"pose(:,"<<itr_ctr+2<<") = ["<<T.translation().transpose()<<" "<<T.rotation().eulerAngles(0,1,2).transpose()<<"]';\n";
00521 
00522         if(itr_ctr>0)
00523         {
00524             convergence = ((TR.translation().norm() + TR.rotation().eulerAngles(0,1,2).norm()) < DELTA_SCORE);
00525             //convergence = ((score_gradient.norm()) < DELTA_SCORE);
00526         }
00527         if(itr_ctr>ITR_MAX)
00528         {
00529             convergence = true;
00530             ret = false;
00531         }
00532         itr_ctr++;
00533         //step_size *= alpha;
00534         //std::cout<<"step size "<<step_size<<std::endl;
00535     }
00536 //    std::cout<<"incr(:,"<<itr_ctr+1<<") = [0 0 0 0 0 0]';\n";
00537 //    std::cout<<"grad(:,"<<itr_ctr+1<<") = [0 0 0 0 0 0]';\n";
00538     /*
00539         snprintf(fname,49,"final.wrl");
00540         fout = fopen(fname,"w");
00541         fprintf(fout,"#VRML V2.0 utf8\n");
00542         targetNDT.writeToVRML(fout,Eigen::Vector3d(1,0,0));
00543         for(unsigned int i=0; i<nextNDT.size(); i++)
00544         {
00545         if(nextNDT[i]!=NULL)
00546         {
00547             nextNDT[i]->writeToVRML(fout,Eigen::Vector3d(0,1,0));
00548         }
00549         }
00550         fclose(fout);
00551     */
00552 
00553     return ret;
00554 }
00555 #endif
00556 
00557 //iteratively update the score gradient and hessian
00558 template <typename PointSource>
00559 bool NDTMatcherSequentialD2D<PointSource>::update_gradient_hessian_local(
00560     Eigen::MatrixXd &score_gradient,
00561     Eigen::MatrixXd &Hessian,
00562     const Eigen::Vector3d & x,
00563     const Eigen::Matrix3d & B,
00564     const double &likelihood,
00565     const Eigen::Matrix<double,3,6> &_Jest,
00566     const Eigen::Matrix<double,18,6> &_Hest,
00567     const Eigen::Matrix<double,3,18> &_Zest,
00568     const Eigen::Matrix<double,18,18> &_ZHest,
00569     bool computeHessian)
00570 {
00571 
00572 
00573     //vars for gradient
00574     Eigen::Matrix<double,6,1> _xtBJ, _xtBZBx, _Q;
00575     //vars for hessian
00576     Eigen::Matrix<double,6,6> _xtBZBJ, _xtBH, _xtBZBZBx, _xtBZhBx;
00577     Eigen::Matrix<double,1,3> _TMP1, _xtB;
00578 
00579     _xtBJ.setZero();
00580     _xtBZBx.setZero();
00581     _Q.setZero();
00582     _xtBZBJ.setZero();
00583     _xtBH.setZero();
00584     _xtBZBZBx.setZero();
00585     _xtBZhBx.setZero();
00586     _TMP1.setZero();
00587     _xtB.setZero();
00588 
00589     _xtB = x.transpose()*B;
00590     _xtBJ = _xtB*_Jest;
00591 
00592     for(unsigned int i=0; i<6; i++)
00593     {
00594         _TMP1 = _xtB*_Zest.block<3,3>(0,3*i)*B;
00595         _xtBZBx(i) = _TMP1*x;
00596         if(computeHessian)
00597         {
00598             _xtBZBJ.col(i) = (_TMP1*_Jest).transpose(); //-
00599             for(unsigned int j=0; j<6; j++)
00600             {
00601                 _xtBH(i,j) = _xtB*_Hest.block<3,1>(3*i,j);
00602                 _xtBZBZBx(i,j) = _TMP1*_Zest.block<3,3>(0,3*j)*B*x;
00603                 _xtBZhBx(i,j) = _xtB*_ZHest.block<3,3>(3*i,3*j)*B*x;
00604             }
00605         }
00606     }
00607     _Q = 2*_xtBJ-_xtBZBx;
00608     double factor = -(lfd2/2)*likelihood;
00609     score_gradient += _Q*factor;
00610 
00611     if(computeHessian)
00612     {
00613         Hessian += factor*(2*_Jest.transpose()*B*_Jest+2*_xtBH -_xtBZhBx -2*_xtBZBJ.transpose()
00614                            -2*_xtBZBJ +_xtBZBZBx +_xtBZBZBx.transpose() -lfd2*_Q*_Q.transpose()/2 ); // + Eigen::Matrix<double,6,6>::Identity();
00615 
00616     }
00617     return true;
00618 }
00619 
00620 //pre-computes the derivative matrices Jest, Hest, Zest, ZHest
00621 template <typename PointSource>
00622 void NDTMatcherSequentialD2D<PointSource>::computeDerivativesLocal(Eigen::Vector3d &x, Eigen::Matrix3d C1,
00623         Eigen::Matrix<double,3,6> &_Jest,
00624         Eigen::Matrix<double,18,6> &_Hest,
00625         Eigen::Matrix<double,3,18> &_Zest,
00626         Eigen::Matrix<double,18,18> &_ZHest,
00627         bool computeHessian)
00628 {
00629 
00630     _Jest(0,4) = x(2);
00631     _Jest(0,5) = -x(1);
00632     _Jest(1,3) = -x(2);
00633     _Jest(1,5) = x(0);
00634     _Jest(2,3) = x(1);
00635     _Jest(2,4) = -x(0);
00636     Eigen::Vector3d a,b,c,d,e,f;
00637     a<<0,-x(1),-x(2);
00638     b<<0,x(0),0;
00639     c<<0,0,x(0);
00640     d<<-x(0),0,-x(2);
00641     e<<0,0,x(1);
00642     f<<-x(0),-x(1),0;
00643 
00644     Eigen::Matrix3d myBlock;
00645     //_Zest
00646     myBlock<<
00647            0,       -C1(0,2),      C1(0,1),
00648                     -C1(0,2),     -2*C1(1,2), -C1(2,2) + C1(1,1),
00649                     C1(0,1), -C1(2,2) + C1(1,1),    2*C1(1,2);
00650     _Zest.block<3,3>(0,9) = myBlock;
00651     myBlock<<
00652            2*C1(0,2), C1(1,2), -C1(0,0) + C1(2,2),
00653              C1(1,2),    0,       -C1(0,1),
00654              -C1(0,0) + C1(2,2),  -C1(0,1),     -2*C1(0,2);
00655     _Zest.block<3,3>(0,12) = myBlock;
00656     myBlock<<
00657            -2*C1(0,1), -C1(1,1) + C1(0,0),  -C1(1,2),
00658            -C1(1,1) + C1(0,0),    2*C1(0,1), C1(0,2),
00659            -C1(1,2),      C1(0,2),    0;
00660     _Zest.block<3,3>(0,15) = myBlock;
00661 
00662     if(computeHessian)
00663     {
00664         //Hest
00665         _Hest.block<3,1>(9,3) = a;
00666         _Hest.block<3,1>(12,3) = b;
00667         _Hest.block<3,1>(15,3) = c;
00668         _Hest.block<3,1>(9,4) = b;
00669         _Hest.block<3,1>(12,4) = d;
00670         _Hest.block<3,1>(15,4) = e;
00671         _Hest.block<3,1>(9,5) = c;
00672         _Hest.block<3,1>(12,5) = e;
00673         _Hest.block<3,1>(15,5) = f;
00674 
00675         //_ZHest
00676         myBlock<<
00677                0,          -C1(0,1),          -C1(0,2),
00678                            -C1(0,1), 2*C1(2,2) - 2*C1(1,1),        -4*C1(1,2),
00679                            -C1(0,2),        -4*C1(1,2), 2*C1(1,1) - 2*C1(2,2);
00680         _ZHest.block<3,3>(9,9) =   myBlock;
00681 
00682         myBlock<<
00683                0, C1(0,0) - C1(2,2),    C1(1,2),
00684                   C1(0,0) - C1(2,2),     2*C1(0,1),  2*C1(0,2),
00685                   C1(1,2),     2*C1(0,2), -2*C1(0,1);
00686         _ZHest.block<3,3>(9,12) = myBlock;
00687 
00688         myBlock<<
00689                0,    C1(1,2), C1(0,0) - C1(1,1),
00690                      C1(1,2), -2*C1(0,2),     2*C1(0,1),
00691                      C1(0,0) - C1(1,1),  2*C1(0,1),     2*C1(0,2);
00692         _ZHest.block<3,3>(9,15) = myBlock;
00693 
00694         myBlock<<
00695                2*C1(2,2) - 2*C1(0,0), -C1(0,1),        -4*C1(0,2),
00696                  -C1(0,1),    0,          -C1(1,2),
00697                  -4*C1(0,2), -C1(1,2), 2*C1(0,0) - 2*C1(2,2);
00698         _ZHest.block<3,3>(12,12) = myBlock;
00699 
00700         myBlock<<
00701                -2*C1(1,2),       C1(0,2),     2*C1(0,1),
00702                C1(0,2),         0, C1(1,1) - C1(0,0),
00703                2*C1(0,1), C1(1,1) - C1(0,0),     2*C1(1,2);
00704         _ZHest.block<3,3>(12,15) = myBlock;
00705 
00706         myBlock<<
00707                2*C1(1,1) - 2*C1(0,0),        -4*C1(0,1), -C1(0,2),
00708                  -4*C1(0,1), 2*C1(0,0) - 2*C1(1,1), -C1(1,2),
00709                  -C1(0,2),          -C1(1,2),    0;
00710         _ZHest.block<3,3>(15,15)= myBlock;
00711 
00712         _ZHest.block<3,3>(12,9) =    _ZHest.block<3,3>(9,12);
00713         _ZHest.block<3,3>(15,9) =    _ZHest.block<3,3>(9,15);
00714         _ZHest.block<3,3>(15,12)=    _ZHest.block<3,3>(12,15);
00715     }
00716 }
00717 
00718 
00719 template <typename PointSource>
00720 //compute the score gradient of a point cloud + transformation to an NDT
00721 double NDTMatcherSequentialD2D<PointSource>::derivativesNDT(
00722     const std::vector<NDTCell<PointSource>*> &sourceNDT,
00723     const std::vector<NDTCell<PointSource>*> &targetNDT,
00724     Eigen::MatrixXd &score_gradient,
00725     Eigen::MatrixXd &Hessian,
00726     bool computeHessian
00727 )
00728 {
00729 
00730 
00731     struct timeval tv_start, tv_end;
00732     double score_here = 0;
00733     int n_dimensions = score_gradient.rows();
00734 
00735     gettimeofday(&tv_start,NULL);
00736     score_gradient.setZero();
00737     Hessian.setZero();
00738 
00739     Eigen::MatrixXd score_gradient_omp;
00740     Eigen::MatrixXd score_here_omp;
00741     Eigen::MatrixXd Hessian_omp;
00742 
00743 #define n_threads 8
00744 
00745     //n_threads = omp_get_num_threads();
00746     score_gradient_omp.resize(n_dimensions,n_threads);
00747     score_here_omp.resize(1,n_threads);
00748     Hessian_omp.resize(n_dimensions,n_dimensions*n_threads);
00749 
00750     score_gradient_omp.setZero();
00751     score_here_omp.setZero();
00752     Hessian_omp.setZero();
00753     //std::cout<<n_threads<<" "<<omp_get_thread_num()<<std::endl;
00754 
00755     #pragma omp parallel num_threads(n_threads)
00756     {
00757         #pragma omp for
00758         for(unsigned int i=0; i<sourceNDT.size(); i++)
00759         {
00760             PointSource point;
00761             Eigen::Vector3d transformed;
00762             Eigen::Vector3d meanMoving, meanFixed;
00763             Eigen::Matrix3d CMoving, CFixed, CSum, Cinv, R;
00764             Eigen::MatrixXd score_gradient_omp_loc(n_dimensions,1);
00765             Eigen::MatrixXd Hessian_omp_loc(n_dimensions,n_dimensions);
00766             Eigen::Matrix<double,3,6> _Jest;
00767             Eigen::Matrix<double,18,6> _Hest;
00768             Eigen::Matrix<double,3,18> _Zest;
00769             Eigen::Matrix<double,18,18> _ZHest;
00770             double score_here_loc=0;
00771             int thread_id = omp_get_thread_num();
00772             NDTCell<PointSource> *cell;
00773             bool exists = false;
00774             double det = 0;
00775 
00776 
00777             score_gradient_omp_loc.setZero();
00778             Hessian_omp_loc.setZero();
00779             _Jest.setZero();
00780             _Jest.block<3,3>(0,0).setIdentity();
00781             _Hest.setZero();
00782             _Zest.setZero();
00783             _ZHest.setZero();
00784 
00785             meanMoving = sourceNDT[i]->getMean();
00786             CMoving= sourceNDT[i]->getCov();
00787             computeDerivativesLocal(meanMoving, CMoving, _Jest, _Hest, _Zest, _ZHest, computeHessian);
00788 
00789             point.x = meanMoving(0);
00790             point.y = meanMoving(1);
00791             point.z = meanMoving(2);
00792             std::vector<NDTCell<PointSource>*> cells = targetNDT; //targetNDT.getCellsForPoint(point,2); //targetNDT.getAllCells(); //
00793             for(int j=0; j<cells.size(); j++)
00794             {
00795                 cell = cells[j];
00796                 if(cell == NULL)
00797                 {
00798                     continue;
00799                 }
00800                 if(cell->hasGaussian_)
00801                 {
00802                     transformed = meanMoving - cell->getMean();
00803                     if(transformed.norm() > 8*current_resolution) continue;
00804                     CFixed = cell->getCov();
00805                     CSum = (CFixed+CMoving);
00806                     CSum.computeInverseAndDetWithCheck(Cinv,det,exists);
00807                     if(!exists)
00808                     {
00809                         continue;
00810                     }
00811                     double l = (transformed).dot(Cinv*(transformed));
00812                     if(l*0 != 0)
00813                     {
00814                         continue;
00815                     }
00816                     //if(l > 120) continue;
00817                     double sh = -lfd1*(exp(-lfd2*l/2));
00818                     if(!update_gradient_hessian_local(score_gradient_omp_loc,Hessian_omp_loc,transformed, Cinv, sh,
00819                                                       _Jest, _Hest, _Zest, _ZHest, computeHessian))
00820                     {
00821                         continue;
00822                     }
00823                     score_here_loc += sh;
00824                     cell = NULL;
00825                 }
00826             }
00827             //score_gradient_omp.block(0,thread_id,n_dimensions,1) += score_gradient_omp_loc;
00828             score_gradient_omp.col(thread_id) += score_gradient_omp_loc;
00829             Hessian_omp.block(0,n_dimensions*thread_id,n_dimensions,n_dimensions) += Hessian_omp_loc;
00830             score_here_omp(0,thread_id) += score_here_loc;
00831 
00832         }
00833     } //end pragma block
00834     //std::cout<<"sgomp: "<<score_gradient_omp<<std::endl;
00835     //std::cout<<"somp: "<<score_here_omp<<std::endl;
00836 
00837     score_gradient = score_gradient_omp.rowwise().sum();
00838     score_here = score_here_omp.sum();
00839     if(computeHessian)
00840     {
00841         //std::cout<<"Homp: "<<Hessian_omp<<std::endl;
00842         for(int i=0; i<n_threads; ++i)
00843         {
00844             Hessian += Hessian_omp.block(0,n_dimensions*i,n_dimensions,n_dimensions);
00845         }
00846     }
00847     /*
00848     if(computeHessian) {
00849 
00850         Eigen::SelfAdjointEigenSolver<Eigen::Matrix<double,6,6> > Sol (Hessian);
00851         Eigen::Matrix<double,6,1> evals = Sol.eigenvalues().real();
00852 
00853         double minCoeff = evals.minCoeff();
00854         double maxCoeff = evals.maxCoeff();
00855 
00856         if(minCoeff < 0 ) { //evals.minCoeff() < 0.01*evals.maxCoeff()) {
00857         Eigen::Matrix<double,6,6> evecs = Sol.eigenvectors().real();
00858         double regularizer = 0.01*maxCoeff - minCoeff;
00859         Eigen::Matrix<double,6,1> reg;
00860         //ugly
00861         reg<<regularizer,regularizer,regularizer,regularizer,regularizer,regularizer;
00862         evals += reg;
00863         Eigen::Matrix<double,6,6> Lam;
00864         Lam = evals.asDiagonal();
00865         Hessian = evecs*Lam*(evecs.transpose());
00866         std::cerr<<"regularizing\n";
00867         }
00868         */
00869     /*
00870     if(minCoeff < 0.001*maxCoeff) {
00871     Eigen::Matrix<double,6,6> evecs = Sol.eigenvectors().real();
00872     for(int q=0;q<6;++q) {
00873         if(evals(q) < 0.001*maxCoeff) {
00874         evals(q)=0.001*maxCoeff;
00875         } else{
00876         break;
00877         }
00878     }
00879     Eigen::Matrix<double,6,6> Lam;
00880     Lam = evals.asDiagonal();
00881     Hessian = evecs*Lam*(evecs.transpose());
00882     std::cerr<<"BAD_HESSIAN\n";
00883     }
00884     }
00885     */
00886     gettimeofday(&tv_end,NULL);
00887 
00888     double time_load = (tv_end.tv_sec-tv_start.tv_sec)*1000.+(tv_end.tv_usec-tv_start.tv_usec)/1000.;
00889     //std::cout<<"time derivatives took is: "<<time_load<<std::endl;
00890     return score_here;
00891 }
00892 
00893 //perform line search to find the best descent rate (More&Thuente)
00894 template <typename PointSource>
00895 double NDTMatcherSequentialD2D<PointSource>::lineSearchMT(
00896     Eigen::Matrix<double,6,1> &increment,
00897     std::vector<NDTCell<PointSource>*> &sourceNDT,
00898     std::vector<NDTCell<PointSource>*> &targetNDT
00899 )
00900 {
00901 
00902     // default params
00903     double stp = 1.0; //default step
00904     double recoverystep = 0.1;
00905     double dginit = 0.0;
00906     double ftol = 0.11111; //epsilon 1
00907     double gtol = 0.99999; //epsilon 2
00908     double stpmax = 4.0;
00909     double stpmin = 0.001;
00910     int maxfev = 40; //max function evaluations
00911     double xtol = 0.01; //window of uncertainty around the optimal step
00912 
00913     //my temporary variables
00914     std::vector<NDTCell<PointSource>*> sourceNDTHere;
00915     double score_init = 0.0;
00916 
00917     Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> ps;
00918     ps.setIdentity();
00919 
00920     Eigen::Matrix<double,6,1> scg_here;
00921     Eigen::MatrixXd pincr(6,1), score_gradient_here(6,1);
00922     Eigen::MatrixXd pseudoH(6,6);
00923     Eigen::Vector3d eulerAngles;
00925 
00926     int info = 0;                       // return code
00927     int infoc = 1;              // return code for subroutine cstep
00928 
00929     // Compute the initial gradient in the search direction and check
00930     // that s is a descent direction.
00931 
00932     //we want to maximize s, so we should minimize -s
00933     //score_init = scoreNDT(sourceNDT,targetNDT);
00934 
00935     //gradient directions are opposite for the negated function
00936     //score_gradient_init = -score_gradient_init;
00937 
00938 //  cout<<"score_init "<<score_init<<endl;
00939 //  cout<<"score_gradient_init "<<score_gradient_init.transpose()<<endl;
00940 //  cout<<"increment "<<increment.transpose()<<endl;
00941 
00942     score_gradient_here.setZero();
00943     score_init = derivativesNDT(sourceNDT,targetNDT,score_gradient_here,pseudoH,false);
00944     scg_here = score_gradient_here;
00945     dginit = increment.dot(scg_here);
00946 //  cout<<"dginit "<<dginit<<endl;
00947 
00948     if (dginit >= 0.0)
00949     {
00950         std::cout << "MoreThuente::cvsrch - wrong direction (dginit = " << dginit << ")" << std::endl;
00951         //return recoverystep; //TODO TSV -1; //
00952         //return -1;
00953 
00954         increment = -increment;
00955         dginit = -dginit;
00956 
00957         if (dginit >= 0.0)
00958         {
00959             for(unsigned int i=0; i<sourceNDTHere.size(); i++)
00960             {
00961                 if(sourceNDTHere[i]!=NULL)
00962                     delete sourceNDTHere[i];
00963             }
00964             return recoverystep;
00965         }
00966     }
00967     else
00968     {
00969 //     cout<<"correct direction (dginit = " << dginit << ")" << endl;
00970     }
00971 
00972     // Initialize local variables.
00973 
00974     bool brackt = false;                // has the soln been bracketed?
00975     bool stage1 = true;         // are we in stage 1?
00976     int nfev = 0;                       // number of function evaluations
00977     double dgtest = ftol * dginit; // f for curvature condition
00978     double width = stpmax - stpmin; // interval width
00979     double width1 = 2 * width;  // ???
00980 
00981     //cout<<"dgtest "<<dgtest<<endl;
00982     // initial function value
00983     double finit = 0.0;
00984     finit = score_init;
00985 
00986     // The variables stx, fx, dgx contain the values of the step,
00987     // function, and directional derivative at the best step.  The
00988     // variables sty, fy, dgy contain the value of the step, function,
00989     // and derivative at the other endpoint of the interval of
00990     // uncertainty.  The variables stp, f, dg contain the values of the
00991     // step, function, and derivative at the current step.
00992 
00993     double stx = 0.0;
00994     double fx = finit;
00995     double dgx = dginit;
00996     double sty = 0.0;
00997     double fy = finit;
00998     double dgy = dginit;
00999 
01000     // Get the linear solve tolerance for adjustable forcing term
01001     //double eta_original = -1.0;
01002     //double eta = 0.0;
01003     //eta = eta_original;
01004 
01005     // Start of iteration.
01006 
01007     double stmin, stmax;
01008     double fm, fxm, fym, dgm, dgxm, dgym;
01009 
01010     while (1)
01011     {
01012         // Set the minimum and maximum steps to correspond to the present
01013         // interval of uncertainty.
01014         if (brackt)
01015         {
01016             stmin = MoreThuente::min(stx, sty);
01017             stmax = MoreThuente::max(stx, sty);
01018         }
01019         else
01020         {
01021             stmin = stx;
01022             stmax = stp + 4 * (stp - stx);
01023         }
01024 
01025         // Force the step to be within the bounds stpmax and stpmin.
01026         stp = MoreThuente::max(stp, stpmin);
01027         stp = MoreThuente::min(stp, stpmax);
01028 
01029         // If an unusual termination is to occur then let stp be the
01030         // lowest point obtained so far.
01031 
01032         if ((brackt && ((stp <= stmin) || (stp >= stmax))) ||
01033                 (nfev >= maxfev - 1) || (infoc == 0) ||
01034                 (brackt && (stmax - stmin <= xtol * stmax)))
01035         {
01036             stp = stx;
01037         }
01038 
01039         // Evaluate the function and gradient at stp
01040         // and compute the directional derivative.
01042 
01043         pincr = stp*increment;
01044 
01045         ps = Eigen::Translation<double,3>(pincr(0),pincr(1),pincr(2))*
01046              Eigen::AngleAxisd(pincr(3),Eigen::Vector3d::UnitX())*
01047              Eigen::AngleAxisd(pincr(4),Eigen::Vector3d::UnitY())*
01048              Eigen::AngleAxisd(pincr(5),Eigen::Vector3d::UnitZ());
01049 
01050         for(unsigned int i=0; i<sourceNDTHere.size(); i++)
01051         {
01052             if(sourceNDTHere[i]!=NULL)
01053                 delete sourceNDTHere[i];
01054         }
01055         sourceNDTHere.clear();
01056         for(unsigned int i=0; i<sourceNDT.size(); i++)
01057         {
01058             NDTCell<PointSource> *cell = sourceNDT[i];
01059             if(cell!=NULL)
01060             {
01061                 Eigen::Vector3d mean = cell->getMean();
01062                 Eigen::Matrix3d cov = cell->getCov();
01063                 mean = ps*mean;
01064                 cov = ps.rotation()*cov*ps.rotation().transpose();
01065                 NDTCell<PointSource>* nd = (NDTCell<PointSource>*)cell->copy();
01066                 nd->setMean(mean);
01067                 nd->setCov(cov);
01068                 sourceNDTHere.push_back(nd);
01069             }
01070         }
01071 
01072         double f = 0.0;
01073         score_gradient_here.setZero();
01074 
01075         /*f = scoreNDT(sourceNDT,targetNDT,ps);
01076         derivativesNDT(sourceNDT,targetNDT,ps,score_gradient_here,pseudoH,false);
01077         std::cout<<"scg1  " <<score_gradient_here.transpose()<<std::endl;
01078         */
01079 
01080         //option 2:
01081         //f = scoreNDT(sourceNDTHere,targetNDT);
01082         f = derivativesNDT(sourceNDTHere,targetNDT,score_gradient_here,pseudoH,false);
01083         //std::cout<<"scg2  " <<score_gradient_here.transpose()<<std::endl;
01084 
01085 
01086         //cout<<"incr " <<pincr.transpose()<<endl;
01087         //cout<<"score (f) "<<f<<endl;
01088 
01089         double dg = 0.0;
01090         scg_here = score_gradient_here;
01091         dg = increment.dot(scg_here);
01092 
01093 
01094         //VALGRIND_CHECK_VALUE_IS_DEFINED(dg);
01095         //cout<<"dg = "<<dg<<endl;
01096         nfev ++;
01097 
01099 
01100         //cout<<"consider step "<<stp<<endl;
01101         // Armijo-Goldstein sufficient decrease
01102         double ftest1 = finit + stp * dgtest;
01103         //cout<<"ftest1 is "<<ftest1<<endl;
01104 
01105         // Test for convergence.
01106 
01107         if ((brackt && ((stp <= stmin) || (stp >= stmax))) || (infoc == 0))
01108             info = 6;                   // Rounding errors
01109 
01110         if ((stp == stpmax) && (f <= ftest1) && (dg <= dgtest))
01111             info = 5;                   // stp=stpmax
01112 
01113         if ((stp == stpmin) && ((f > ftest1) || (dg >= dgtest)))
01114             info = 4;                   // stp=stpmin
01115 
01116         if (nfev >= maxfev)
01117             info = 3;                   // max'd out on fevals
01118 
01119         if (brackt && (stmax-stmin <= xtol*stmax))
01120             info = 2;                   // bracketed soln
01121 
01122         // RPP sufficient decrease test can be different
01123         bool sufficientDecreaseTest = false;
01124         sufficientDecreaseTest = (f <= ftest1);  // Armijo-Golstein
01125 
01126         //cout<<"ftest2 "<<gtol*(-dginit)<<endl;
01127         //cout<<"sufficientDecrease? "<<sufficientDecreaseTest<<endl;
01128         //cout<<"curvature ok? "<<(fabs(dg) <= gtol*(-dginit))<<endl;
01129         if ((sufficientDecreaseTest) && (fabs(dg) <= gtol*(-dginit)))
01130             info = 1;                   // Success!!!!
01131 
01132         if (info != 0)          // Line search is done
01133         {
01134             if (info != 1)              // Line search failed
01135             {
01136                 // RPP add
01137                 // counter.incrementNumFailedLineSearches();
01138 
01139                 //if (recoveryStepType == Constant)
01140                 stp = recoverystep;
01141 
01142                 //newgrp.computeX(oldgrp, dir, stp);
01143 
01144                 //message = "(USING RECOVERY STEP!)";
01145 
01146             }
01147             else                        // Line search succeeded
01148             {
01149                 //message = "(STEP ACCEPTED!)";
01150             }
01151 
01152             //print.printStep(nfev, stp, finit, f, message);
01153 
01154             // Returning the line search flag
01155             //cout<<"LineSearch::"<<message<<" info "<<info<<endl;
01156             for(unsigned int i=0; i<sourceNDTHere.size(); i++)
01157             {
01158                 if(sourceNDTHere[i]!=NULL)
01159                     delete sourceNDTHere[i];
01160             }
01161 //      std::cout<<"nfev = "<<nfev<<std::endl;
01162             return stp;
01163 
01164         } // info != 0
01165 
01166         // RPP add
01167         //counter.incrementNumIterations();
01168 
01169         // In the first stage we seek a step for which the modified
01170         // function has a nonpositive value and nonnegative derivative.
01171 
01172         if (stage1 && (f <= ftest1) && (dg >= MoreThuente::min(ftol, gtol) * dginit))
01173         {
01174             stage1 = false;
01175         }
01176 
01177         // A modified function is used to predict the step only if we have
01178         // not obtained a step for which the modified function has a
01179         // nonpositive function value and nonnegative derivative, and if a
01180         // lower function value has been obtained but the decrease is not
01181         // sufficient.
01182 
01183         if (stage1 && (f <= fx) && (f > ftest1))
01184         {
01185 
01186             // Define the modified function and derivative values.
01187 
01188             fm = f - stp * dgtest;
01189             fxm = fx - stx * dgtest;
01190             fym = fy - sty * dgtest;
01191             dgm = dg - dgtest;
01192             dgxm = dgx - dgtest;
01193             dgym = dgy - dgtest;
01194 
01195             // Call cstep to update the interval of uncertainty
01196             // and to compute the new step.
01197 
01198             //VALGRIND_CHECK_VALUE_IS_DEFINED(dgm);
01199             infoc = MoreThuente::cstep(stx,fxm,dgxm,sty,fym,dgym,stp,fm,dgm,
01200                                        brackt,stmin,stmax);
01201 
01202             // Reset the function and gradient values for f.
01203 
01204             fx = fxm + stx*dgtest;
01205             fy = fym + sty*dgtest;
01206             dgx = dgxm + dgtest;
01207             dgy = dgym + dgtest;
01208 
01209         }
01210 
01211         else
01212         {
01213 
01214             // Call cstep to update the interval of uncertainty
01215             // and to compute the new step.
01216 
01217             //VALGRIND_CHECK_VALUE_IS_DEFINED(dg);
01218             infoc = MoreThuente::cstep(stx,fx,dgx,sty,fy,dgy,stp,f,dg,
01219                                        brackt,stmin,stmax);
01220 
01221         }
01222 
01223         // Force a sufficient decrease in the size of the
01224         // interval of uncertainty.
01225 
01226         if (brackt)
01227         {
01228             if (fabs(sty - stx) >= 0.66 * width1)
01229                 stp = stx + 0.5 * (sty - stx);
01230             width1 = width;
01231             width = fabs(sty-stx);
01232         }
01233 
01234     } // while-loop
01235 
01236 }
01237 
01238 template <typename PointSource>
01239 int NDTMatcherSequentialD2D<PointSource>::MoreThuente::cstep(double& stx, double& fx, double& dx,
01240         double& sty, double& fy, double& dy,
01241         double& stp, double& fp, double& dp,
01242         bool& brackt, double stmin, double stmax)
01243 {
01244     int info = 0;
01245 
01246     // Check the input parameters for errors.
01247 
01248     if ((brackt && ((stp <= MoreThuente::min(stx, sty)) || (stp >= MoreThuente::max(stx, sty)))) ||
01249             (dx * (stp - stx) >= 0.0) || (stmax < stmin))
01250         return info;
01251 
01252     // Determine if the derivatives have opposite sign.
01253 
01254     double sgnd = dp * (dx / fabs(dx));
01255 
01256     // First case. A higher function value.  The minimum is
01257     // bracketed. If the cubic step is closer to stx than the quadratic
01258     // step, the cubic step is taken, else the average of the cubic and
01259     // quadratic steps is taken.
01260 
01261     bool bound;
01262     double theta;
01263     double s;
01264     double gamma;
01265     double p,q,r;
01266     double stpc, stpq, stpf;
01267 
01268     if (fp > fx)
01269     {
01270         info = 1;
01271         bound = 1;
01272         theta = 3 * (fx - fp) / (stp - stx) + dx + dp;
01273         //VALGRIND_CHECK_VALUE_IS_DEFINED(theta);
01274         //VALGRIND_CHECK_VALUE_IS_DEFINED(dx);
01275         //VALGRIND_CHECK_VALUE_IS_DEFINED(dp);
01276         s = MoreThuente::absmax(theta, dx, dp);
01277         gamma = s * sqrt(((theta / s) * (theta / s)) - (dx / s) * (dp / s));
01278         if (stp < stx)
01279             gamma = -gamma;
01280 
01281         p = (gamma - dx) + theta;
01282         q = ((gamma - dx) + gamma) + dp;
01283         r = p / q;
01284         stpc = stx + r * (stp - stx);
01285         stpq = stx + ((dx / ((fx - fp) / (stp - stx) + dx)) / 2) * (stp - stx);
01286         if (fabs(stpc - stx) < fabs(stpq - stx))
01287             stpf = stpc;
01288         else
01289             stpf = stpc + (stpq - stpc) / 2;
01290 
01291         brackt = true;
01292     }
01293 
01294     // Second case. A lower function value and derivatives of opposite
01295     // sign. The minimum is bracketed. If the cubic step is closer to
01296     // stx than the quadratic (secant) step, the cubic step is taken,
01297     // else the quadratic step is taken.
01298 
01299     else if (sgnd < 0.0)
01300     {
01301         info = 2;
01302         bound = false;
01303         theta = 3 * (fx - fp) / (stp - stx) + dx + dp;
01304         s = MoreThuente::absmax(theta,dx,dp);
01305         gamma = s * sqrt(((theta/s) * (theta/s)) - (dx / s) * (dp / s));
01306         if (stp > stx)
01307             gamma = -gamma;
01308         p = (gamma - dp) + theta;
01309         q = ((gamma - dp) + gamma) + dx;
01310         r = p / q;
01311         stpc = stp + r * (stx - stp);
01312         stpq = stp + (dp / (dp - dx)) * (stx - stp);
01313         if (fabs(stpc - stp) > fabs(stpq - stp))
01314             stpf = stpc;
01315         else
01316             stpf = stpq;
01317         brackt = true;
01318     }
01319 
01320     // Third case. A lower function value, derivatives of the same sign,
01321     // and the magnitude of the derivative decreases.  The cubic step is
01322     // only used if the cubic tends to infinity in the direction of the
01323     // step or if the minimum of the cubic is beyond stp. Otherwise the
01324     // cubic step is defined to be either stmin or stmax. The
01325     // quadratic (secant) step is also computed and if the minimum is
01326     // bracketed then the the step closest to stx is taken, else the
01327     // step farthest away is taken.
01328 
01329     else if (fabs(dp) < fabs(dx))
01330     {
01331         info = 3;
01332         bound = true;
01333         theta = 3 * (fx - fp) / (stp - stx) + dx + dp;
01334         s = MoreThuente::absmax(theta, dx, dp);
01335 
01336         // The case gamma = 0 only arises if the cubic does not tend
01337         // to infinity in the direction of the step.
01338 
01339         gamma = s * sqrt(max(0,(theta / s) * (theta / s) - (dx / s) * (dp / s)));
01340         if (stp > stx)
01341             gamma = -gamma;
01342 
01343         p = (gamma - dp) + theta;
01344         q = (gamma + (dx - dp)) + gamma;
01345         r = p / q;
01346         if ((r < 0.0) && (gamma != 0.0))
01347             stpc = stp + r * (stx - stp);
01348         else if (stp > stx)
01349             stpc = stmax;
01350         else
01351             stpc = stmin;
01352 
01353         stpq = stp + (dp/ (dp - dx)) * (stx - stp);
01354         if (brackt)
01355         {
01356             if (fabs(stp - stpc) < fabs(stp - stpq))
01357                 stpf = stpc;
01358             else
01359                 stpf = stpq;
01360         }
01361         else
01362         {
01363             if (fabs(stp - stpc) > fabs(stp - stpq))
01364                 stpf = stpc;
01365             else
01366                 stpf = stpq;
01367         }
01368     }
01369 
01370     // Fourth case. A lower function value, derivatives of the same
01371     // sign, and the magnitude of the derivative does not decrease. If
01372     // the minimum is not bracketed, the step is either stmin or
01373     // stmax, else the cubic step is taken.
01374 
01375     else
01376     {
01377         info = 4;
01378         bound = false;
01379         if (brackt)
01380         {
01381             theta = 3 * (fp - fy) / (sty - stp) + dy + dp;
01382             s = MoreThuente::absmax(theta, dy, dp);
01383             gamma = s * sqrt(((theta/s)*(theta/s)) - (dy / s) * (dp / s));
01384             if (stp > sty)
01385                 gamma = -gamma;
01386             p = (gamma - dp) + theta;
01387             q = ((gamma - dp) + gamma) + dy;
01388             r = p / q;
01389             stpc = stp + r * (sty - stp);
01390             stpf = stpc;
01391         }
01392         else if (stp > stx)
01393             stpf = stmax;
01394         else
01395             stpf = stmin;
01396     }
01397 
01398     // Update the interval of uncertainty. This update does not depend
01399     // on the new step or the case analysis above.
01400 
01401     if (fp > fx)
01402     {
01403         sty = stp;
01404         fy = fp;
01405         dy = dp;
01406     }
01407     else
01408     {
01409         if (sgnd < 0.0)
01410         {
01411             sty = stx;
01412             fy = fx;
01413             dy = dx;
01414         }
01415         stx = stp;
01416         fx = fp;
01417         dx = dp;
01418     }
01419 
01420     // Compute the new step and safeguard it.
01421 
01422     stpf = MoreThuente::min(stmax, stpf);
01423     stpf = MoreThuente::max(stmin, stpf);
01424     stp = stpf;
01425     if (brackt && bound)
01426     {
01427         if (sty > stx)
01428             stp = min(stx + 0.66 * (sty - stx), stp);
01429         else
01430             stp = max(stx + 0.66 * (sty - stx), stp);
01431     }
01432 
01433     return info;
01434 
01435 }
01436 
01437 template <typename PointSource>
01438 double NDTMatcherSequentialD2D<PointSource>::MoreThuente::min(double a, double b)
01439 {
01440     return (a < b ? a : b);
01441 }
01442 
01443 template <typename PointSource>
01444 double NDTMatcherSequentialD2D<PointSource>::MoreThuente::max(double a, double b)
01445 {
01446     return (a > b ? a : b);
01447 }
01448 
01449 template <typename PointSource>
01450 double NDTMatcherSequentialD2D<PointSource>::MoreThuente::absmax(double a, double b, double c)
01451 {
01452     a = fabs(a);
01453     b = fabs(b);
01454     c = fabs(c);
01455 
01456     if (a > b)
01457         return (a > c) ? a : c;
01458     else
01459         return (b > c) ? b : c;
01460 }
01461 
01462 template <typename PointSource>
01463 double NDTMatcherSequentialD2D<PointSource>::normalizeAngle(double a)
01464 {
01465     //set the angle between -M_PI and M_PI
01466     return atan2(sin(a), cos(a));
01467 
01468 }
01469 
01470 
01471 
01472 }


ndt_registration
Author(s): Todor Stoyanov, Jari Saarinen, Henrik Andreasson
autogenerated on Mon Oct 6 2014 03:19:30