ndt_fuser_hmt.h
Go to the documentation of this file.
00001 #ifndef NDT_FUSER_HMT_HH
00002 #define NDT_FUSER_HMT_HH
00003 
00004 #include <ndt_viz.h>
00005 #include <ndt_map_hmt.h>
00006 #include <ndt_map.h>
00007 #include <ndt_matcher_d2d_2d.h>
00008 #include <ndt_matcher_d2d.h>
00009 #include <pointcloud_utils.h>
00010 
00011 #include <Eigen/Eigen>
00012 #include <pcl/point_cloud.h>
00013 
00014 //#define BASELINE
00015 
00016 namespace lslgeneric {
00022 template <typename PointT>
00023 class NDTFuserHMT{
00024     public:
00025         Eigen::Affine3d Tnow, Tlast_fuse, Todom; 
00026         //lslgeneric::NDTMapHMT<PointT> *map;  ///< da map
00027         lslgeneric::NDTMap<PointT> *map;  
00028         bool checkConsistency;            
00029         double max_translation_norm, max_rotation_norm;
00030         double sensor_range;
00031         bool be2D, doMultires, fuseIncomplete, beHMT;
00032         int ctr;
00033         std::string prefix;
00034         std::string hmt_map_dir;
00035         NDTViz<PointT> *viewer;
00036         FILE *fAddTimes, *fRegTimes;
00037 
00038         NDTFuserHMT(double map_resolution, double map_size_x_, double map_size_y_, double map_size_z_, double sensor_range_ = 3, 
00039                     bool visualize_=false, bool be2D_=false, bool doMultires_=false, bool fuseIncomplete_=false, int max_itr=30, 
00040                     std::string prefix_="", bool beHMT_=true, std::string hmt_map_dir_="map", bool _step_control=true){
00041             isInit = false;
00042             resolution = map_resolution;
00043             sensor_pose.setIdentity();
00044             checkConsistency = false;
00045             visualize = true;
00046             translation_fuse_delta = 0.05;
00047             rotation_fuse_delta = 0.01;
00048             max_translation_norm = 1.;
00049             max_rotation_norm = M_PI/4;
00050             map_size_x = map_size_x_;
00051             map_size_y = map_size_y_;
00052             map_size_z = map_size_z_;
00053             visualize = visualize_;
00054             be2D = be2D_;
00055             sensor_range = sensor_range_;
00056             prefix = prefix_;
00057             doMultires = doMultires_;
00058             ctr =0;
00059             viewer = new NDTViz<PointT>(visualize);
00060             localMapSize<<sensor_range_,sensor_range_,map_size_z_;
00061             fuseIncomplete = fuseIncomplete_;
00062             matcher.ITR_MAX = max_itr;
00063             matcher2D.ITR_MAX = max_itr;
00064             matcher.step_control=_step_control;
00065             matcher2D.step_control=_step_control;
00066             beHMT = beHMT_;
00067             hmt_map_dir=hmt_map_dir_;
00068 
00069             
00070             char fname[1000];
00071             snprintf(fname,999,"%s_addTime.txt",prefix.c_str());
00072             fAddTimes = fopen(fname,"w");
00073 
00074             std::cout<<"MAP: resolution: "<<resolution<<" size "<<map_size_x<<" "<<map_size_y<<" "<<map_size_z<<" sr "<<sensor_range<<std::endl;
00075         }
00076         ~NDTFuserHMT()
00077         {
00078             delete map;
00079             delete viewer;
00080             if(fAddTimes!=NULL) fclose(fAddTimes);
00081             if(fRegTimes!=NULL) fclose(fRegTimes);
00082         }
00083 
00084         double getDoubleTime()
00085         {
00086             struct timeval time;
00087             gettimeofday(&time,NULL);
00088             return time.tv_sec + time.tv_usec * 1e-6;
00089         }
00090         void setSensorPose(Eigen::Affine3d spose){
00091             sensor_pose = spose;
00092         }
00093         
00094         bool wasInit()
00095         {
00096             return isInit;
00097         }
00098 
00099         bool saveMap() {
00100             if(!isInit) return false;
00101             if(map == NULL) return false;
00102             if(beHMT) {
00103                 lslgeneric::NDTMapHMT<PointT> *map_hmt = dynamic_cast<lslgeneric::NDTMapHMT<PointT>*> (map);
00104                 if(map_hmt==NULL) return false;
00105                 return (map_hmt->writeTo()==0);
00106             } else {
00107                 char fname[1000];
00108                 snprintf(fname,999,"%s/%s_map.jff",hmt_map_dir.c_str(),prefix.c_str());
00109                 return (map->writeToJFF(fname) == 0);
00110             }
00111         }
00112 
00116         void initialize(Eigen::Affine3d initPos, pcl::PointCloud<PointT> &cloud, bool preLoad=false){
00118             lslgeneric::transformPointCloudInPlace(sensor_pose, cloud);
00119             lslgeneric::transformPointCloudInPlace(initPos, cloud);
00120             Tnow = initPos;
00121 //#ifdef BASELINE
00122 //#else
00123             if(beHMT) {
00124                 map = new lslgeneric::NDTMapHMT<PointT>(resolution,
00125                         Tnow.translation()(0),Tnow.translation()(1),Tnow.translation()(2),
00126                         map_size_x,map_size_y,map_size_z,sensor_range,hmt_map_dir,true);
00127                 if(preLoad) {
00128                     lslgeneric::NDTMapHMT<PointT> *map_hmt = dynamic_cast<lslgeneric::NDTMapHMT<PointT>*> (map);
00129                     std::cout<<"Trying to pre-load maps at "<<initPos.translation()<<std::endl;
00130                     map_hmt->tryLoadPosition(initPos.translation());
00131                 }
00132             } else {
00133                 map = new lslgeneric::NDTMap<PointT>(new lslgeneric::LazyGrid<PointT>(resolution));
00134                 map->initialize(Tnow.translation()(0),Tnow.translation()(1),Tnow.translation()(2),map_size_x,map_size_y,map_size_z);
00135             }
00136 //#endif
00137             map->addPointCloud(Tnow.translation(),cloud, 0.1, 100.0, 0.1);
00138             //map->addPointCloudMeanUpdate(Tnow.translation(),cloud,localMapSize, 1e5, 1250, map_size_z/2, 0.06);
00139             //map->addPointCloudMeanUpdate(Tnow.translation(),cloud,localMapSize, 0.1, 100.0, 0.1);
00140             map->computeNDTCells(CELL_UPDATE_MODE_SAMPLE_VARIANCE, 1e5, 255, Tnow.translation(), 0.1);
00141             isInit = true;
00142             Tlast_fuse = Tnow;
00143             Todom = Tnow;
00144             if(visualize) 
00145             {
00146                 viewer->plotNDTSAccordingToOccupancy(-1,map); 
00147                 viewer->plotLocalNDTMap(cloud,resolution);
00148                 viewer->addTrajectoryPoint(Tnow.translation()(0),Tnow.translation()(1),Tnow.translation()(2),1,0,0);
00149                 viewer->addTrajectoryPoint(Todom.translation()(0),Todom.translation()(1),Todom.translation()(2),0,1,0);
00150                 viewer->displayTrajectory();
00151                 viewer->repaint();      
00152             }
00153         }
00154 
00159         Eigen::Affine3d update(Eigen::Affine3d Tmotion, pcl::PointCloud<PointT> &cloud){
00160             if(!isInit){
00161                 fprintf(stderr,"NDT-FuserHMT: Call Initialize first!!\n");
00162                 return Tnow;
00163             }
00164             Todom = Todom * Tmotion; //we track this only for display purposes!
00165             double t0=0,t1=0,t2=0,t3=0,t4=0,t5=0,t6=0;
00167             lslgeneric::transformPointCloudInPlace(sensor_pose, cloud);
00168             t0 = getDoubleTime();
00170             lslgeneric::NDTMap<PointT> ndlocal(new lslgeneric::LazyGrid<PointT>(resolution));
00171             ndlocal.guessSize(0,0,0,sensor_range,sensor_range,map_size_z);
00172             ndlocal.loadPointCloud(cloud,sensor_range);
00173             ndlocal.computeNDTCells(CELL_UPDATE_MODE_SAMPLE_VARIANCE);
00174             //pass through ndlocal and set all cells with vertically pointing normals to non-gaussian :-O
00175             /*SpatialIndex<PointT> *index = ndlocal.getMyIndex();
00176             typename SpatialIndex<PointT>::CellVectorItr it = index->begin();
00177             while (it != index->end())
00178             {
00179                 NDTCell<PointT> *cell = dynamic_cast<NDTCell<PointT>*> (*it);
00180                 if(cell!=NULL)
00181                 {
00182                     if(cell->hasGaussian_)
00183                     {
00184                         if(cell->getClass() == NDTCell<PointT>::HORIZONTAL) {
00185                             cell->hasGaussian_ = false;
00186                         }
00187                     }
00188                 }
00189                 it++;
00190             }*/
00191 
00192             t1 = getDoubleTime();
00193             Eigen::Affine3d Tinit = Tnow * Tmotion;
00194             if(doMultires) {
00195                 //create two ndt maps with resolution = 3*resolution (or 5?)
00196                 lslgeneric::NDTMap<PointT> ndlocalLow(new lslgeneric::LazyGrid<PointT>(3*resolution));
00197                 ndlocalLow.guessSize(0,0,0,sensor_range,sensor_range,map_size_z);
00198                 ndlocalLow.loadPointCloud(cloud,sensor_range);
00199                 ndlocalLow.computeNDTCells(CELL_UPDATE_MODE_SAMPLE_VARIANCE);
00200 
00201                 lslgeneric::NDTMap<PointT> mapLow(new lslgeneric::LazyGrid<PointT>(3*resolution));
00202                 //add distros
00203                 double cx,cy,cz;
00204                 if(!map->getCentroid(cx, cy, cz)){
00205                     fprintf(stderr,"Centroid NOT Given-abort!\n");
00206                 }
00207                 mapLow.initialize(cx,cy,cz,3*map_size_x,3*map_size_y,map_size_z);
00208 
00209                 std::vector<lslgeneric::NDTCell<PointT>*> ndts;
00210                 ndts = map->getAllCells(); //this copies cells?
00211         
00212                 for(int i=0; i<ndts.size(); i++)        
00213                 {
00214                     NDTCell<PointT> *cell = ndts[i];
00215                     if(cell!=NULL)
00216                     {
00217                         if(cell->hasGaussian_)
00218                         {
00219                             Eigen::Vector3d m = cell->getMean();        
00220                             Eigen::Matrix3d cov = cell->getCov();
00221                             unsigned int nump = cell->getN();
00222                             mapLow.addDistributionToCell(cov, m,nump);
00223                         }
00224                     }
00225                     delete cell;
00226                 }
00227                 //do match
00228                 if(matcher2D.match( mapLow, ndlocalLow,Tinit,true)){
00229                     //if success, set Tmotion to result
00230                     t2 = getDoubleTime();
00231                     //std::cout<<"success: new initial guess! t= "<<t2-t1<<std::endl;
00232                 } else {
00233                     Tinit = Tnow * Tmotion;
00234                 }           
00235             }
00236             
00237             if(be2D) {
00238                 t2 = getDoubleTime();
00239                 if(matcher2D.match( *map, ndlocal,Tinit,true) || fuseIncomplete){
00240                     t3 = getDoubleTime();
00241                     Eigen::Affine3d diff = (Tnow * Tmotion).inverse() * Tinit;
00242                     if((diff.translation().norm() > max_translation_norm || 
00243                                 diff.rotation().eulerAngles(0,1,2).norm() > max_rotation_norm) && checkConsistency){
00244                         fprintf(stderr,"****  NDTFuserHMT -- ALMOST DEFINATELY A REGISTRATION FAILURE *****\n");
00245                         Tnow = Tnow * Tmotion;
00246                     }else{
00247                         Tnow = Tinit;
00248                         lslgeneric::transformPointCloudInPlace(Tnow, cloud);
00249                         Eigen::Affine3d spose = Tnow*sensor_pose;
00250                         Eigen::Affine3d diff_fuse = Tlast_fuse.inverse()*Tnow;
00251                         if(diff_fuse.translation().norm() > translation_fuse_delta ||
00252                                 diff_fuse.rotation().eulerAngles(0,1,2).norm() > rotation_fuse_delta)
00253                         {
00254                             //std::cout<<"F: "<<spose.translation().transpose()<<" "<<spose.rotation().eulerAngles(0,1,2).transpose()<<std::endl;
00255                             t4 = getDoubleTime();
00256                             map->addPointCloudMeanUpdate(spose.translation(),cloud,localMapSize, 1e5, 1250, map_size_z/2, 0.06);
00257                             t5 = getDoubleTime();
00258                             //map->addPointCloudMeanUpdate(spose.translation(),cloud,localMapSize, 1e5, 25, 2*map_size_z, 0.06);
00259                             //map->addPointCloud(spose.translation(),cloud, 0.06, 25);
00260                             //map->computeNDTCells(CELL_UPDATE_MODE_SAMPLE_VARIANCE, 1e5, 255, spose.translation(), 0.1);
00261                             //t4 = getDoubleTime();
00262                             //std::cout<<"match: "<<t3-t2<<" addPointCloud: "<<t5-t4<<" ndlocal "<<t1-t0<<" total: "<<t5-t0<<std::endl;
00263                             Tlast_fuse = Tnow;
00264                             if(visualize) //&&ctr%20==0) 
00265                             {
00266                                 if(ctr%20==0) {
00267                                     viewer->plotNDTSAccordingToOccupancy(-1,map); 
00268                                     viewer->plotLocalNDTMap(cloud,resolution); 
00269                                 }
00270                                 viewer->addTrajectoryPoint(Tnow.translation()(0),Tnow.translation()(1),Tnow.translation()(2),1,0,0);
00271                                 viewer->addTrajectoryPoint(Todom.translation()(0),Todom.translation()(1),Todom.translation()(2),0,1,0);
00272                                 viewer->displayTrajectory();
00273                                 viewer->repaint();      
00274                             }
00275                             ctr++;
00276                         }
00277                     }
00278                 }else{
00279                     t3 = getDoubleTime();
00280                     Tnow = Tnow * Tmotion;
00281                 }
00282 
00283             }
00284             else
00285             {
00286                 
00287                 t2 = getDoubleTime();
00288                 if(matcher.match( *map, ndlocal,Tinit,true) || fuseIncomplete){
00289                     t3 = getDoubleTime();
00290                     Eigen::Affine3d diff = (Tnow * Tmotion).inverse() * Tinit;
00291                     
00292                     if((diff.translation().norm() > max_translation_norm || 
00293                                 diff.rotation().eulerAngles(0,1,2).norm() > max_rotation_norm) && checkConsistency){
00294                         fprintf(stderr,"****  NDTFuserHMT -- ALMOST DEFINATELY A REGISTRATION FAILURE *****\n");
00295                         Tnow = Tnow * Tmotion;
00296                         //save offending map:
00297                         //map->writeToJFF("map.jff");
00298                         //ndlocal.writeToJFF("local.jff");
00299                     }else{
00300                         Tnow = Tinit;
00301                         //Tnow = Tnow * Tmotion;
00302                         lslgeneric::transformPointCloudInPlace(Tnow, cloud);
00303                         Eigen::Affine3d spose = Tnow*sensor_pose;
00304                         Eigen::Affine3d diff_fuse = Tlast_fuse.inverse()*Tnow;
00305                         if(diff_fuse.translation().norm() > translation_fuse_delta ||
00306                                 diff_fuse.rotation().eulerAngles(0,1,2).norm() > rotation_fuse_delta)
00307                         {
00308                             //std::cout<<"F: "<<spose.translation().transpose()<<" "<<spose.rotation().eulerAngles(0,1,2).transpose()<<std::endl;
00309                             t4 = getDoubleTime();
00310                             map->addPointCloudMeanUpdate(spose.translation(),cloud,localMapSize, 1e5, 1250, map_size_z/2, 0.06);
00311                             t5 = getDoubleTime();
00312                             //map->addPointCloudMeanUpdate(spose.translation(),cloud,localMapSize, 1e5, 25, 2*map_size_z, 0.06);
00313                             //map->addPointCloud(spose.translation(),cloud, 0.06, 25);
00314                             //map->computeNDTCells(CELL_UPDATE_MODE_SAMPLE_VARIANCE, 1e5, 255, spose.translation(), 0.1);
00315                             //t4 = getDoubleTime();
00316                             //std::cout<<"match: "<<t3-t2<<" addPointCloud: "<<t5-t4<<" ndlocal "<<t1-t0<<" total: "<<t5-t0<<std::endl;
00317                             Tlast_fuse = Tnow;
00318                             if(visualize) //&&ctr%20==0) 
00319                             {
00320                                 viewer->plotNDTSAccordingToOccupancy(-1,map); 
00321                                 viewer->plotLocalNDTMap(cloud,resolution); 
00322                             }
00323                             ctr++;
00324                         }
00325                     }
00326                 }else{
00327                     t3 = getDoubleTime();
00328                     Tnow = Tnow * Tmotion;
00329                 }
00330             }
00331             
00332             t6 = getDoubleTime();
00333             if(fAddTimes!=NULL) {
00334                 fprintf(fAddTimes,"%lf %lf %lf\n",t3-t2,t5-t4,t6-t0);
00335                 fflush(fAddTimes);
00336             }
00337 
00338             return Tnow;
00339         }
00340 
00341     private:
00342         bool isInit;
00343 
00344         double resolution; 
00345         double map_size;
00346         
00347         double translation_fuse_delta, rotation_fuse_delta;
00348         double map_size_x;
00349         double map_size_y;
00350         double map_size_z;
00351         bool visualize;
00352 
00353         Eigen::Affine3d sensor_pose;
00354         lslgeneric::NDTMatcherD2D<PointT,PointT> matcher;
00355         lslgeneric::NDTMatcherD2D_2D<PointT,PointT> matcher2D;
00356         Eigen::Vector3d localMapSize;
00357 
00358     public:
00359         EIGEN_MAKE_ALIGNED_OPERATOR_NEW
00360 
00361 };
00362 }
00363 #endif


ndt_fuser
Author(s): Todor Stoyanov and Jari Saarinen
autogenerated on Mon Jan 6 2014 11:35:58