example2.cpp
Go to the documentation of this file.
00001 
00057 #include <pcl/console/parse.h>
00058 #include <pcl/point_types.h>
00059 #include <pcl/point_cloud.h>
00060 #include <pcl/point_representation.h>
00061 
00062 #include <pcl/io/pcd_io.h>
00063 #include <pcl/ros/conversions.h>
00064 #ifdef GICP_ENABLE
00065 #include <pcl/keypoints/uniform_sampling.h>
00066 #include <pcl/features/normal_3d.h>
00067 #include <pcl/features/fpfh.h>
00068 #include <pcl/registration/correspondence_estimation.h>
00069 #include <pcl/registration/correspondence_rejection_distance.h>
00070 #include <pcl/registration/transformation_estimation_svd.h>
00071 
00072 using namespace std;
00073 using namespace sensor_msgs;
00074 using namespace pcl;
00075 using namespace pcl::io;
00076 using namespace pcl::console;
00077 using namespace pcl::registration;
00078 PointCloud<PointXYZ>::Ptr src, tgt;
00079 
00081 void
00082 estimateKeypoints (const PointCloud<PointXYZ>::Ptr &src, 
00083                    const PointCloud<PointXYZ>::Ptr &tgt,
00084                    PointCloud<PointXYZ> &keypoints_src,
00085                    PointCloud<PointXYZ> &keypoints_tgt)
00086 {
00087   PointCloud<int> keypoints_src_idx, keypoints_tgt_idx;
00088   // Get an uniform grid of keypoints
00089   UniformSampling<PointXYZ> uniform;
00090   uniform.setRadiusSearch (1);  // 1m
00091 
00092   uniform.setInputCloud (src);
00093   uniform.compute (keypoints_src_idx);
00094   copyPointCloud<PointXYZ, PointXYZ> (*src, keypoints_src_idx.points, keypoints_src);
00095 
00096   uniform.setInputCloud (tgt);
00097   uniform.compute (keypoints_tgt_idx);
00098   copyPointCloud<PointXYZ, PointXYZ> (*tgt, keypoints_tgt_idx.points, keypoints_tgt);
00099 
00100   // For debugging purposes only: uncomment the lines below and use pcd_viewer to view the results, i.e.:
00101   // pcd_viewer source_pcd keypoints_src.pcd -ps 1 -ps 10
00102   savePCDFileBinary ("keypoints_src.pcd", keypoints_src);
00103   savePCDFileBinary ("keypoints_tgt.pcd", keypoints_tgt);
00104 }
00105 
00107 void
00108 estimateNormals (const PointCloud<PointXYZ>::Ptr &src, 
00109                  const PointCloud<PointXYZ>::Ptr &tgt,
00110                  PointCloud<Normal> &normals_src,
00111                  PointCloud<Normal> &normals_tgt)
00112 {
00113   NormalEstimation<PointXYZ, Normal> normal_est;
00114   normal_est.setInputCloud (src);
00115   normal_est.setRadiusSearch (0.5);  // 50cm
00116   normal_est.compute (normals_src);
00117 
00118   normal_est.setInputCloud (tgt);
00119   normal_est.compute (normals_tgt);
00120 
00121   // For debugging purposes only: uncomment the lines below and use pcd_viewer to view the results, i.e.:
00122   // pcd_viewer normals_src.pcd 
00123   PointCloud<PointNormal> s, t;
00124   copyPointCloud<PointXYZ, PointNormal> (*src, s);
00125   copyPointCloud<Normal, PointNormal> (normals_src, s);
00126   copyPointCloud<PointXYZ, PointNormal> (*tgt, t);
00127   copyPointCloud<Normal, PointNormal> (normals_tgt, t);
00128   savePCDFileBinary ("normals_src.pcd", s);
00129   savePCDFileBinary ("normals_tgt.pcd", t);
00130 }
00131 
00133 void
00134 estimateFPFH (const PointCloud<PointXYZ>::Ptr &src, 
00135               const PointCloud<PointXYZ>::Ptr &tgt,
00136               const PointCloud<Normal>::Ptr &normals_src,
00137               const PointCloud<Normal>::Ptr &normals_tgt,
00138               const PointCloud<PointXYZ>::Ptr &keypoints_src,
00139               const PointCloud<PointXYZ>::Ptr &keypoints_tgt,
00140               PointCloud<FPFHSignature33> &fpfhs_src,
00141               PointCloud<FPFHSignature33> &fpfhs_tgt)
00142 {
00143   FPFHEstimation<PointXYZ, Normal, FPFHSignature33> fpfh_est;
00144   fpfh_est.setInputCloud (keypoints_src);
00145   fpfh_est.setInputNormals (normals_src);
00146   fpfh_est.setRadiusSearch (1); // 1m
00147   fpfh_est.setSearchSurface (src);
00148   fpfh_est.compute (fpfhs_src);
00149 
00150   fpfh_est.setInputCloud (keypoints_tgt);
00151   fpfh_est.setInputNormals (normals_tgt);
00152   fpfh_est.setSearchSurface (tgt);
00153   fpfh_est.compute (fpfhs_tgt);
00154 
00155   // For debugging purposes only: uncomment the lines below and use pcd_viewer to view the results, i.e.:
00156   // pcd_viewer fpfhs_src.pcd 
00157   PointCloud2 s, t, out;
00158   //toROSMsg (*src, s); toROSMsg (fpfhs_src, t); concatenateFields (s, t, out);
00159   savePCDFile ("fpfhs_src.pcd", out);
00160   //toROSMsg (*tgt, s); toROSMsg (fpfhs_tgt, t); concatenateFields (s, t, out);
00161   savePCDFile ("fpfhs_tgt.pcd", out);
00162 }
00163 
00165 void
00166 findCorrespondences (const PointCloud<FPFHSignature33>::Ptr &fpfhs_src,
00167                      const PointCloud<FPFHSignature33>::Ptr &fpfhs_tgt,
00168                      Correspondences &all_correspondences)
00169 {
00170   CorrespondenceEstimation<FPFHSignature33, FPFHSignature33> est;
00171   est.setInputCloud (fpfhs_src);
00172   est.setInputTarget (fpfhs_tgt);
00173   est.determineReciprocalCorrespondences (all_correspondences);
00174 }
00175 
00177 void
00178 rejectBadCorrespondences (const CorrespondencesPtr &all_correspondences,
00179                           const PointCloud<PointXYZ>::Ptr &keypoints_src,
00180                           const PointCloud<PointXYZ>::Ptr &keypoints_tgt,
00181                           Correspondences &remaining_correspondences)
00182 {
00183   CorrespondenceRejectorDistance rej;
00184   rej.setInputCloud<PointXYZ> (keypoints_src);
00185   rej.setInputTarget<PointXYZ> (keypoints_tgt);
00186   rej.setMaximumDistance (1);    // 1m
00187   rej.setInputCorrespondences (all_correspondences);
00188   rej.getCorrespondences (remaining_correspondences);
00189 }
00190 
00191 
00193 void
00194 computeTransformation (const PointCloud<PointXYZ>::Ptr &src, 
00195                        const PointCloud<PointXYZ>::Ptr &tgt,
00196                        Eigen::Matrix4f &transform)
00197 {
00198   // Get an uniform grid of keypoints
00199   PointCloud<PointXYZ>::Ptr keypoints_src (new PointCloud<PointXYZ>), 
00200                             keypoints_tgt (new PointCloud<PointXYZ>);
00201 
00202   estimateKeypoints (src, tgt, *keypoints_src, *keypoints_tgt);
00203   print_info ("Found %zu and %zu keypoints for the source and target datasets.\n", keypoints_src->points.size (), keypoints_tgt->points.size ());
00204 
00205   // Compute normals for all points keypoint
00206   PointCloud<Normal>::Ptr normals_src (new PointCloud<Normal>), 
00207                           normals_tgt (new PointCloud<Normal>);
00208   estimateNormals (src, tgt, *normals_src, *normals_tgt);
00209   print_info ("Estimated %zu and %zu normals for the source and target datasets.\n", normals_src->points.size (), normals_tgt->points.size ());
00210 
00211   // Compute FPFH features at each keypoint
00212   PointCloud<FPFHSignature33>::Ptr fpfhs_src (new PointCloud<FPFHSignature33>), 
00213                                    fpfhs_tgt (new PointCloud<FPFHSignature33>);
00214   estimateFPFH (src, tgt, normals_src, normals_tgt, keypoints_src, keypoints_tgt, *fpfhs_src, *fpfhs_tgt);
00215 
00216   // Copy the data and save it to disk
00217 /*  PointCloud<PointNormal> s, t;
00218   copyPointCloud<PointXYZ, PointNormal> (*keypoints_src, s);
00219   copyPointCloud<Normal, PointNormal> (normals_src, s);
00220   copyPointCloud<PointXYZ, PointNormal> (*keypoints_tgt, t);
00221   copyPointCloud<Normal, PointNormal> (normals_tgt, t);*/
00222 
00223   // Find correspondences between keypoints in FPFH space
00224   CorrespondencesPtr all_correspondences (new Correspondences), 
00225                      good_correspondences (new Correspondences);
00226   findCorrespondences (fpfhs_src, fpfhs_tgt, *all_correspondences);
00227 
00228   // Reject correspondences based on their XYZ distance
00229   rejectBadCorrespondences (all_correspondences, keypoints_src, keypoints_tgt, *good_correspondences);
00230 
00231   for (int i = 0; i < good_correspondences->size (); ++i)
00232     std::cerr << good_correspondences->at (i) << std::endl;
00233   // Obtain the best transformation between the two sets of keypoints given the remaining correspondences
00234   TransformationEstimationSVD<PointXYZ, PointXYZ> trans_est;
00235   trans_est.estimateRigidTransformation (*keypoints_src, *keypoints_tgt, *good_correspondences, transform);
00236 }
00237 
00238 /* ---[ */
00239 int
00240 main (int argc, char** argv)
00241 {
00242   // Parse the command line arguments for .pcd files
00243   std::vector<int> p_file_indices;
00244   p_file_indices = parse_file_extension_argument (argc, argv, ".pcd");
00245   if (p_file_indices.size () != 2)
00246   {
00247     print_error ("Need one input source PCD file and one input target PCD file to continue.\n");
00248     print_error ("Example: %s source.pcd target.pcd\n", argv[0]);
00249     return (-1);
00250   }
00251 
00252   // Load the files
00253   print_info ("Loading %s as source and %s as target...\n", argv[p_file_indices[0]], argv[p_file_indices[1]]);
00254   src.reset (new PointCloud<PointXYZ>);
00255   tgt.reset (new PointCloud<PointXYZ>);
00256   if (loadPCDFile (argv[p_file_indices[0]], *src) == -1 || loadPCDFile (argv[p_file_indices[1]], *tgt) == -1)
00257   {
00258     print_error ("Error reading the input files!\n");
00259     return (-1);
00260   }
00261 
00262   // Compute the best transformtion
00263   Eigen::Matrix4f transform;
00264   computeTransformation (src, tgt, transform);
00265 
00266   std::cerr << transform << std::endl;
00267   // Transform the data and write it to disk
00268   PointCloud<PointXYZ> output;
00269   transformPointCloud (*src, output, transform);
00270   savePCDFileBinary ("source_transformed.pcd", output);
00271 }
00272 /* ]--- */
00273 #else
00274 int main() {return 0;}
00275 #endif


cob_3d_registration
Author(s): Joshua Hampp
autogenerated on Wed Aug 26 2015 11:02:36