00001 #include <pointcloud_vrml/pointcloud_utils.h>
00002 #include <Eigen/Eigen>
00003
00004 #include "pcl/point_cloud.h"
00005 #include "pcl/io/pcd_io.h"
00006 #include "pcl/features/feature.h"
00007 #include "pcl/registration/icp.h"
00008 #include "pcl/filters/voxel_grid.h"
00009
00010 namespace lslgeneric
00011 {
00012
00013
00014 template <typename PointT>
00015 bool NDTMapBuilder<PointT>::matchICP(pcl::PointCloud<PointT> &target, pcl::PointCloud<PointT> &source,
00016 Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> &Tout, double &finalscore)
00017 {
00018
00019 typename pcl::PointCloud<PointT>::Ptr cloud_in (new pcl::PointCloud<PointT>);
00020 typename pcl::PointCloud<PointT>::Ptr cloud_out (new pcl::PointCloud<PointT>);
00021
00022 typename pcl::PointCloud<PointT>::ConstPtr m (new pcl::PointCloud<PointT>(source) );
00023 typename pcl::PointCloud<PointT>::ConstPtr f (new pcl::PointCloud<PointT>(target) );
00024
00025 typename pcl::VoxelGrid<PointT> gr1;
00026 typename pcl::VoxelGrid<PointT> gr2;
00027 gr1.setLeafSize(0.1,0.1,0.1);
00028 gr2.setLeafSize(0.1,0.1,0.1);
00029
00030 gr1.setInputCloud(m);
00031 gr2.setInputCloud(f);
00032
00033 cloud_in->height = 1;
00034 cloud_in->width = cloud_in->points.size();
00035 cloud_out->height = 1;
00036 cloud_out->width = cloud_out->points.size();
00037 cloud_in->is_dense = false;
00038 cloud_out->is_dense = false;
00039
00040 gr1.filter(*cloud_in);
00041 gr2.filter(*cloud_out);
00042
00043 pcl::IterativeClosestPoint<PointT, PointT> icp;
00044
00045 icp.setMaximumIterations(1000);
00046 std::cout<<"max itr are "<<icp.getMaximumIterations()<<std::endl;
00047 icp.setInputCloud(cloud_in);
00048 icp.setInputTarget(cloud_out);
00049
00050 icp.setRANSACOutlierRejectionThreshold (2);
00051 icp.setMaxCorrespondenceDistance(10);
00052 icp.setTransformationEpsilon(0.00001);
00053 pcl::PointCloud<PointT> Final;
00054 icp.align(Final);
00055
00056
00057 finalscore = icp.getFitnessScore();
00058 Tout = (icp.getFinalTransformation()).template cast<double>();
00059 return icp.hasConverged();
00060 }
00061
00062
00063 template <typename PointT>
00064 bool NDTMapBuilder<PointT>::addScan(pcl::PointCloud<PointT> scan, int id)
00065 {
00066
00067 if(id == -1)
00068 {
00069 id = vertices.size();
00070 }
00071
00072 if(id == 0)
00073 {
00074 MapVertex<PointT> mv;
00075 mv.scan = scan;
00076 mv.pose.setIdentity();
00077 mv.id = id;
00078
00079 vertices.push_back(mv);
00080 return true;
00081 }
00082
00083
00084 if(id-1 <0 || id-1 > vertices.size())
00085 return false;
00086
00087 std::cout<<"Matching scans with ids "<<vertices.back().id<<" and "<<id<<std::endl;
00088
00089 Eigen::Transform<double,3,Eigen::Affine,Eigen::ColMajor> T, Tout, Tndt;
00090 Eigen::Matrix<double,6,6> cov;
00091 bool succ = false;
00092 struct timeval tv_start, tv_end;
00093 double bestscore = INT_MAX;
00094 double finalscore;
00095 double time_match = 0;
00096 Tout.setIdentity();
00097
00098
00099 lslgeneric::NDTMap<PointT> fixed(&tr);
00100 fixed.loadPointCloud(vertices.back().scan);
00101 lslgeneric::NDTMap<PointT> moving(&tr);
00102 moving.loadPointCloud(scan);
00103
00104 moving.computeNDTCells();
00105 fixed.computeNDTCells();
00106
00107 lslgeneric::NDTHistogram<PointT> fixedH(fixed);
00108 lslgeneric::NDTHistogram<PointT> movingH(moving);
00109
00110 movingH.bestFitToHistogram(fixedH,T);
00111 pcl::PointCloud<PointT> cloud3;
00112
00113
00114
00115 for(int q=0; q<4; q++)
00116 {
00117 if(!doHistogram && q != 3) continue;
00118 if(q!=3)
00119 {
00120 movingH.getTransform(q,T);
00121 }
00122 else
00123 {
00124 T.setIdentity();
00125 }
00126
00127 Tndt.setIdentity();
00128 cloud3 = lslgeneric::transformPointCloud(T,scan);
00129
00130 bool ret;
00131 gettimeofday(&tv_start,NULL);
00132 if(isF2F)
00133 {
00134 ret = matcherF2F->match(vertices.back().scan,cloud3,Tndt);
00135 finalscore = matcherF2F->finalscore;
00136 }
00137 else if(isP2F)
00138 {
00139 ret = matcherP2F->match(vertices.back().scan,cloud3,Tndt);
00140 finalscore = matcherP2F->finalscore;
00141 }
00142 else
00143 {
00144
00145 ret = this->matchICP(vertices.back().scan,cloud3,Tndt,finalscore);
00146 }
00147 gettimeofday(&tv_end,NULL);
00148
00149 if(finalscore < bestscore)
00150 {
00151 Tout = Tndt*T;
00152 bestscore = finalscore;
00153 if(isF2F)
00154 {
00155
00156 }
00157 else if(isP2F)
00158 {
00159
00160 }
00161 else
00162 {
00163 cov.setIdentity();
00164 cov = 0.1*cov;
00165 }
00166 std::cout<<"score = "<<bestscore<<"best is "<<q<<std::endl;
00167 }
00168 std::cout<<"T fin "<<Tout.translation().transpose()<<" r "<<Tout.rotation().eulerAngles(0,1,2).transpose()<<std::endl;
00169 time_match += (tv_end.tv_sec-tv_start.tv_sec)*1000.+(tv_end.tv_usec-tv_start.tv_usec)/1000.;
00170 }
00171
00172 std::cout<<" TIME: (MATCHING ONLY) "<< time_match << std::endl;
00173
00174
00175
00176
00177 MapVertex<PointT> vert;
00178 vert.scan = scan;
00179 vert.pose = vertices.back().pose*Tout;
00180 vert.id = id;
00181 vert.hist = movingH;
00182 vert.timeRegistration = time_match;
00183
00184
00185
00186 MapEdge edge;
00187 edge.idFirst = vertices.back().id;
00188 edge.idSecond = id;
00189 edge.relative_pose = Tout;
00190 edge.covariance = cov;
00191
00192
00193 vertices.push_back(vert);
00194 edges.push_back(edge);
00195
00196
00197 #if 0
00198 for(int i=0; i<vertices.size()-2; i++)
00199 {
00200
00201
00202
00203 lslgeneric::NDTHistogram<PointT> fH = vertices[i].hist;
00204
00205
00206 double sim = movingH.getSimilarity(fH);
00207
00208 if(sim < 0.22)
00209 {
00210
00211 std::cout<<"Trying to match.. "<<id<<" to "<<vertices[i].id<<" at i "<<i<<" scan similarity "<<sim<<std::endl;
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 movingH.getTransform(0,T);
00232 pcl::PointCloud<PointT> cloud3 = lslgeneric::transformPointCloud(T,scan);
00233
00234 bool ret;
00235 if(isF2F)
00236 {
00237 ret = matcherF2F->match(vertices[i].scan,cloud3,Tndt);
00238 finalscore = matcherF2F->finalscore;
00239 }
00240 else if(isP2F)
00241 {
00242 finalscore = 0;
00243 }
00244 else
00245 {
00246
00247 finalscore = 0;
00248 }
00249
00250 if(finalscore < -0.8)
00251 {
00252 std::cout<<"NEW EDGE!\n";
00253
00254 edge.idFirst = vertices[i].id;
00255 edge.idSecond = id;
00256 edge.relative_pose = Tout;
00257 edge.covariance = cov;
00258 edges.insert(edges.begin(),edge);
00259 }
00260 }
00261 }
00262 #endif
00263
00264 }
00265
00266 template <typename PointT>
00267 void NDTMapBuilder<PointT>::saveG2OlogFile(const char* fname)
00268 {
00269
00270 FILE *fout = fopen(fname,"w");
00271 Eigen::Matrix<double,6,6> eye;
00272 eye.setIdentity();
00273 double reg = 1e-4;
00274
00275
00276 for(int i=0; i<vertices.size(); i++)
00277 {
00278 Eigen::Vector3d t = vertices[i].pose.translation();
00279 Eigen::Quaternion<double> q;
00280 q = vertices[i].pose.rotation();
00281 fprintf(fout,"VERTEX_SE3:QUAT %d %lf %lf %lf %lf %lf %lf %lf\n",vertices[i].id,
00282 t(0),t(1),t(2),q.x(),q.y(),q.z(),q.w());
00283 }
00284
00285
00286 for(int i=0; i<edges.size(); i++)
00287 {
00288 Eigen::Vector3d t = edges[i].relative_pose.translation();
00289 Eigen::Quaterniond q;
00290 q = edges[i].relative_pose.rotation();
00291 fprintf(fout,"EDGE_SE3:QUAT %d %d %lf %lf %lf %lf %lf %lf %lf ",edges[i].idFirst,edges[i].idSecond,
00292 t(0),t(1),t(2),q.x(),q.y(),q.z(),q.w());
00293
00294 Eigen::Matrix<double,6,6> information = (edges[i].covariance+reg*eye).inverse();
00295 for(int p=0; p<6; p++)
00296 {
00297 for(int q=p; q<6; q++)
00298 {
00299 fprintf(fout,"%lf ",information(p,q));
00300 }
00301 }
00302 fprintf(fout,"\n");
00303 }
00304 fclose(fout);
00305 }
00306
00307 template <typename PointT>
00308 void NDTMapBuilder<PointT>::saveDatlogFile(const char* fname)
00309 {
00310
00311 FILE *fout = fopen(fname,"w");
00312
00313
00314 for(int i=0; i<vertices.size(); i++)
00315 {
00316 Eigen::Vector3d t = vertices[i].pose.translation();
00317 Eigen::Quaternion<double> q;
00318 q = vertices[i].pose.rotation();
00319 fprintf(fout,"%d %lf %lf %lf %lf %lf %lf %lf\n",vertices[i].id,
00320 t(0),t(1),t(2),q.x(),q.y(),q.z(),q.w());
00321 }
00322 fclose(fout);
00323
00324 char fn[500];
00325 snprintf(fn,499,"%s.times",fname);
00326
00327 fout = fopen(fn,"w");
00328 fprintf(fout,"Tr = [");
00329 for( int i=1; i<vertices.size(); i++)
00330 {
00331 fprintf(fout,"%lf ",vertices[i].timeRegistration);
00332 }
00333 fprintf(fout,"];\n");
00334
00335 fclose(fout);
00336 }
00337
00338 template <typename PointT>
00339 void NDTMapBuilder<PointT>::printNodePositions()
00340 {
00341
00342 for(int i=0; i<vertices.size(); i++)
00343 {
00344 std::cout<<vertices[i].pose.translation().transpose()<<" "<<vertices[i].pose.rotation().eulerAngles(0,1,2)<<std::endl;
00345 }
00346 }
00347
00348 template <typename PointT>
00349 void NDTMapBuilder<PointT>::theMotherOfAllPointClouds(const char* fname)
00350 {
00351
00352 FILE *fout = fopen(fname,"w");
00353 fprintf(fout,"#VRML V2.0 utf8\n");
00354 for( int i=0; i<vertices.size(); i++)
00355 {
00356 pcl::PointCloud<PointT> cloud3 = lslgeneric::transformPointCloud(vertices[i].pose,vertices[i].scan);
00357 pcl::PointCloud<PointT> cloud3SS;
00358 for(int q=0; q<cloud3.points.size(); q++)
00359 {
00360 if(q%10 == 0) cloud3SS.points.push_back(cloud3.points[q]);
00361 }
00362
00363
00364 if(i%2)
00365 {
00366
00367 lslgeneric::writeToVRML(fout,cloud3SS,Eigen::Vector3d(0,1,0));
00368 }
00369 else
00370 {
00371
00372 lslgeneric::writeToVRML(fout,cloud3SS,Eigen::Vector3d(1,1,1));
00373 }
00374 }
00375 fclose(fout);
00376
00377 }
00378 }