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