test_registration_api.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Point Cloud Library (PCL) - www.pointclouds.org
00005  *  Copyright (c) 2010-2011, Willow Garage, Inc.
00006  *
00007  *  All rights reserved.
00008  *
00009  *  Redistribution and use in source and binary forms, with or without
00010  *  modification, are permitted provided that the following conditions
00011  *  are met:
00012  *
00013  *   * Redistributions of source code must retain the above copyright
00014  *     notice, this list of conditions and the following disclaimer.
00015  *   * Redistributions in binary form must reproduce the above
00016  *     copyright notice, this list of conditions and the following
00017  *     disclaimer in the documentation and/or other materials provided
00018  *     with the distribution.
00019  *   * Neither the name of Willow Garage, Inc. nor the names of its
00020  *     contributors may be used to endorse or promote products derived
00021  *     from this software without specific prior written permission.
00022  *
00023  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00026  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00027  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00028  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00029  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00032  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00033  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00034  *  POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  * $Id: test_registration_api.cpp 3499 2011-12-12 04:32:01Z rusu $
00037  *
00038  */
00039 
00040 #include <gtest/gtest.h>
00041 
00042 #include <pcl/point_types.h>
00043 #include <pcl/io/pcd_io.h>
00044 #include <pcl/registration/correspondence_estimation.h>
00045 #include <pcl/registration/correspondence_rejection_distance.h>
00046 #include <pcl/registration/correspondence_rejection_median_distance.h>
00047 #include <pcl/registration/correspondence_rejection_surface_normal.h>
00048 #include <pcl/registration/correspondence_rejection.h>
00049 #include <pcl/registration/correspondence_rejection_one_to_one.h>
00050 #include <pcl/registration/correspondence_rejection_sample_consensus.h>
00051 #include <pcl/registration/correspondence_rejection_trimmed.h>
00052 #include <pcl/registration/correspondence_rejection_var_trimmed.h>
00053 #include <pcl/registration/transformation_estimation_lm.h>
00054 #include <pcl/registration/transformation_estimation_svd.h>
00055 #include <pcl/features/normal_3d.h>
00056 
00057 #include "test_registration_api_data.h"
00058 
00059 pcl::PointCloud<pcl::PointXYZ> cloud_source, cloud_target, cloud_reg;
00060 
00062 TEST (PCL, CorrespondenceEstimation)
00063 {
00064   pcl::PointCloud<pcl::PointXYZ>::Ptr source (new pcl::PointCloud<pcl::PointXYZ>(cloud_source));
00065   pcl::PointCloud<pcl::PointXYZ>::Ptr target (new pcl::PointCloud<pcl::PointXYZ>(cloud_target));
00066 
00067   boost::shared_ptr<pcl::Correspondences> correspondences (new pcl::Correspondences);
00068   pcl::registration::CorrespondenceEstimation<pcl::PointXYZ, pcl::PointXYZ> corr_est;
00069   corr_est.setInputCloud (source);
00070   corr_est.setInputTarget (target);
00071   corr_est.determineCorrespondences (*correspondences);
00072 
00073   // check for correct order and number of matches
00074   EXPECT_EQ (int (correspondences->size ()), nr_original_correspondences);
00075   if (int (correspondences->size ()) == nr_original_correspondences)
00076   {
00077     for (int i = 0; i < nr_original_correspondences; ++i)
00078       EXPECT_EQ ((*correspondences)[i].index_query, i);
00079 
00080     // check for correct matches
00081     for (int i = 0; i < nr_original_correspondences; ++i)
00082       EXPECT_EQ ((*correspondences)[i].index_match, correspondences_original[i][1]);
00083   }
00084 }
00085 
00087 TEST (PCL, CorrespondenceEstimationReciprocal)
00088 {
00089   pcl::PointCloud<pcl::PointXYZ>::Ptr source (new pcl::PointCloud<pcl::PointXYZ>(cloud_source));
00090   pcl::PointCloud<pcl::PointXYZ>::Ptr target (new pcl::PointCloud<pcl::PointXYZ>(cloud_target));
00091 
00092   boost::shared_ptr<pcl::Correspondences> correspondences (new pcl::Correspondences);
00093   pcl::registration::CorrespondenceEstimation<pcl::PointXYZ, pcl::PointXYZ> corr_est;
00094   corr_est.setInputCloud (source);
00095   corr_est.setInputTarget (target);
00096   corr_est.determineReciprocalCorrespondences (*correspondences);
00097 
00098   // check for correct matches and number of matches
00099   EXPECT_EQ (int (correspondences->size ()), nr_reciprocal_correspondences);
00100   if (int (correspondences->size ()) == nr_reciprocal_correspondences)
00101     for (int i = 0; i < nr_reciprocal_correspondences; ++i)
00102       EXPECT_EQ ((*correspondences)[i].index_match, correspondences_reciprocal[i][1]);
00103 }
00104 
00106 TEST (PCL, CorrespondenceRejectorDistance)
00107 {
00108   pcl::PointCloud<pcl::PointXYZ>::Ptr source (new pcl::PointCloud<pcl::PointXYZ>(cloud_source));
00109   pcl::PointCloud<pcl::PointXYZ>::Ptr target (new pcl::PointCloud<pcl::PointXYZ>(cloud_target));
00110 
00111   // re-do correspondence estimation
00112   boost::shared_ptr<pcl::Correspondences> correspondences (new pcl::Correspondences);
00113   pcl::registration::CorrespondenceEstimation<pcl::PointXYZ, pcl::PointXYZ> corr_est;
00114   corr_est.setInputCloud (source);
00115   corr_est.setInputTarget (target);
00116   corr_est.determineCorrespondences (*correspondences);
00117 
00118   boost::shared_ptr<pcl::Correspondences>  correspondences_result_rej_dist (new pcl::Correspondences);
00119   pcl::registration::CorrespondenceRejectorDistance corr_rej_dist;
00120   corr_rej_dist.setInputCorrespondences(correspondences);
00121   corr_rej_dist.setMaximumDistance(rej_dist_max_dist);
00122   corr_rej_dist.getCorrespondences(*correspondences_result_rej_dist);
00123 
00124   // check for correct matches and number of matches
00125   EXPECT_EQ (int (correspondences_result_rej_dist->size ()), nr_correspondences_result_rej_dist);
00126   if (int (correspondences_result_rej_dist->size ()) == nr_correspondences_result_rej_dist)
00127     for (int i = 0; i < nr_correspondences_result_rej_dist; ++i)
00128       EXPECT_EQ ((*correspondences_result_rej_dist)[i].index_match, correspondences_dist[i][1]);
00129 }
00130 
00132 TEST (PCL, CorrespondenceRejectorOneToOne)
00133 {
00134   pcl::PointCloud<pcl::PointXYZ>::Ptr source (new pcl::PointCloud<pcl::PointXYZ>(cloud_source));
00135   pcl::PointCloud<pcl::PointXYZ>::Ptr target (new pcl::PointCloud<pcl::PointXYZ>(cloud_target));
00136 
00137   // re-do correspondence estimation
00138   boost::shared_ptr<pcl::Correspondences> correspondences (new pcl::Correspondences);
00139   pcl::registration::CorrespondenceEstimation<pcl::PointXYZ, pcl::PointXYZ> corr_est;
00140   corr_est.setInputCloud (source);
00141   corr_est.setInputTarget (target);
00142   corr_est.determineCorrespondences (*correspondences);
00143 
00144   boost::shared_ptr<pcl::Correspondences> correspondences_result_rej_one_to_one (new pcl::Correspondences);
00145   pcl::registration::CorrespondenceRejectorOneToOne corr_rej_one_to_one;
00146   corr_rej_one_to_one.setInputCorrespondences(correspondences);
00147   corr_rej_one_to_one.getCorrespondences(*correspondences_result_rej_one_to_one);
00148 
00149   // check for correct matches and number of matches
00150   EXPECT_EQ (int (correspondences_result_rej_one_to_one->size ()), nr_correspondences_result_rej_one_to_one);
00151   if (int (correspondences_result_rej_one_to_one->size ()) == nr_correspondences_result_rej_one_to_one)
00152     for (int i = 0; i < nr_correspondences_result_rej_one_to_one; ++i)
00153       EXPECT_EQ ((*correspondences_result_rej_one_to_one)[i].index_match, correspondences_one_to_one[i][1]);
00154 }
00155 
00157 TEST (PCL, CorrespondenceRejectorSampleConsensus)
00158 {
00159   pcl::PointCloud<pcl::PointXYZ>::Ptr source (new pcl::PointCloud<pcl::PointXYZ>(cloud_source));
00160   pcl::PointCloud<pcl::PointXYZ>::Ptr target (new pcl::PointCloud<pcl::PointXYZ>(cloud_target));
00161 
00162   // re-do correspondence estimation
00163   boost::shared_ptr<pcl::Correspondences> correspondences (new pcl::Correspondences);
00164   pcl::registration::CorrespondenceEstimation<pcl::PointXYZ, pcl::PointXYZ> corr_est;
00165   corr_est.setInputCloud (source);
00166   corr_est.setInputTarget (target);
00167   corr_est.determineCorrespondences (*correspondences);
00168   EXPECT_EQ (int (correspondences->size ()), nr_original_correspondences);
00169 
00170   boost::shared_ptr<pcl::Correspondences> correspondences_result_rej_sac (new pcl::Correspondences);
00171   pcl::registration::CorrespondenceRejectorSampleConsensus<pcl::PointXYZ> corr_rej_sac;
00172   corr_rej_sac.setInputCloud (source);
00173   corr_rej_sac.setTargetCloud (target);
00174   corr_rej_sac.setInlierThreshold (rej_sac_max_dist);
00175   corr_rej_sac.setMaxIterations (rej_sac_max_iter);
00176   corr_rej_sac.setInputCorrespondences (correspondences);
00177   corr_rej_sac.getCorrespondences (*correspondences_result_rej_sac);
00178   Eigen::Matrix4f transform_res_from_SAC = corr_rej_sac.getBestTransformation ();
00179 
00180   // check for correct matches and number of matches
00181   EXPECT_EQ (int (correspondences_result_rej_sac->size ()), nr_correspondences_result_rej_sac);
00182   if (int (correspondences_result_rej_sac->size ()) == nr_correspondences_result_rej_sac)
00183     for (int i = 0; i < nr_correspondences_result_rej_sac; ++i)
00184       EXPECT_EQ ((*correspondences_result_rej_sac)[i].index_match, correspondences_sac[i][1]);
00185 
00186   // check for correct transformation
00187   for (int i = 0; i < 4; ++i)
00188     for (int j = 0; j < 4; ++j)
00189       EXPECT_NEAR (transform_res_from_SAC (i, j), transform_from_SAC[i][j], 1e-4);
00190 }
00191 
00193 TEST (PCL, CorrespondenceRejectorSurfaceNormal)
00194 {
00195   pcl::PointCloud<pcl::PointXYZ>::Ptr source (new pcl::PointCloud<pcl::PointXYZ>(cloud_source));
00196   pcl::PointCloud<pcl::PointXYZ>::Ptr target (new pcl::PointCloud<pcl::PointXYZ>(cloud_target));
00197 
00198   // re-do correspondence estimation
00199   boost::shared_ptr<pcl::Correspondences> correspondences (new pcl::Correspondences);
00200   pcl::registration::CorrespondenceEstimation<pcl::PointXYZ, pcl::PointXYZ> corr_est;
00201   corr_est.setInputCloud (source);
00202   corr_est.setInputTarget (target);
00203   corr_est.determineCorrespondences (*correspondences);
00204 
00205 
00206   pcl::PointCloud<pcl::PointNormal>::Ptr source_normals(new pcl::PointCloud<pcl::PointNormal>);
00207   pcl::copyPointCloud(*source, *source_normals);
00208   pcl::PointCloud<pcl::PointNormal>::Ptr target_normals(new pcl::PointCloud<pcl::PointNormal>);
00209   pcl::copyPointCloud(*target, *target_normals);
00210 
00211   pcl::NormalEstimation<pcl::PointNormal, pcl::PointNormal> norm_est_src;
00212   norm_est_src.setSearchMethod (pcl::search::KdTree<pcl::PointNormal>::Ptr (new pcl::search::KdTree<pcl::PointNormal>));
00213   norm_est_src.setKSearch (10);
00214   norm_est_src.setInputCloud (source_normals);
00215   norm_est_src.compute (*source_normals);
00216 
00217   pcl::NormalEstimation<pcl::PointNormal, pcl::PointNormal> norm_est_tgt;
00218   norm_est_tgt.setSearchMethod (pcl::search::KdTree<pcl::PointNormal>::Ptr (new pcl::search::KdTree<pcl::PointNormal>));
00219   norm_est_tgt.setKSearch (10);
00220   norm_est_tgt.setInputCloud (target_normals);
00221   norm_est_tgt.compute (*target_normals);
00222 
00223   pcl::registration::CorrespondenceRejectorSurfaceNormal  corr_rej_surf_norm;
00224   corr_rej_surf_norm.initializeDataContainer <pcl::PointXYZ, pcl::PointNormal> ();
00225   corr_rej_surf_norm.setInputCloud <pcl::PointXYZ> (source);
00226   corr_rej_surf_norm.setInputTarget <pcl::PointXYZ> (target);
00227   corr_rej_surf_norm.setInputNormals <pcl::PointXYZ, pcl::PointNormal> (source_normals);
00228   corr_rej_surf_norm.setTargetNormals <pcl::PointXYZ, pcl::PointNormal> (target_normals);
00229 
00230   boost::shared_ptr<pcl::Correspondences>  correspondences_result_rej_surf_norm (new pcl::Correspondences);
00231   corr_rej_surf_norm.setInputCorrespondences (correspondences);
00232   corr_rej_surf_norm.setThreshold (0.5);
00233 
00234   corr_rej_surf_norm.getCorrespondences (*correspondences_result_rej_surf_norm);
00235 
00236   // check for correct matches
00237   if (int (correspondences_result_rej_surf_norm->size ()) == nr_correspondences_result_rej_dist)
00238     for (int i = 0; i < nr_correspondences_result_rej_dist; ++i)
00239       EXPECT_EQ ((*correspondences_result_rej_surf_norm)[i].index_match, correspondences_dist[i][1]);
00240 }
00242 TEST (PCL, CorrespondenceRejectorTrimmed)
00243 {
00244   pcl::PointCloud<pcl::PointXYZ>::Ptr source (new pcl::PointCloud<pcl::PointXYZ>(cloud_source));
00245   pcl::PointCloud<pcl::PointXYZ>::Ptr target (new pcl::PointCloud<pcl::PointXYZ>(cloud_target));
00246 
00247   // re-do correspondence estimation
00248   boost::shared_ptr<pcl::Correspondences> correspondences (new pcl::Correspondences);
00249   pcl::registration::CorrespondenceEstimation<pcl::PointXYZ, pcl::PointXYZ> corr_est;
00250   corr_est.setInputCloud (source);
00251   corr_est.setInputTarget (target);
00252   corr_est.determineCorrespondences (*correspondences);
00253 
00254   boost::shared_ptr<pcl::Correspondences> correspondences_result_rej_trimmed (new pcl::Correspondences);
00255   pcl::registration::CorrespondenceRejectorTrimmed corr_rej_trimmed;
00256   corr_rej_trimmed.setOverlapRadio(rej_trimmed_overlap);
00257   corr_rej_trimmed.setInputCorrespondences(correspondences);
00258   corr_rej_trimmed.getCorrespondences(*correspondences_result_rej_trimmed);
00259 
00260   // check for correct matches, number of matches, and for sorting (correspondences should be sorted w.r.t. distance)
00261   EXPECT_EQ (int (correspondences_result_rej_trimmed->size ()), nr_correspondences_result_rej_trimmed);
00262   if (int (correspondences_result_rej_trimmed->size ()) == nr_correspondences_result_rej_trimmed)
00263   {
00264     for (int i = 0; i < nr_correspondences_result_rej_trimmed; ++i)
00265       EXPECT_EQ ((*correspondences_result_rej_trimmed)[i].index_query, correspondences_trimmed[i][0]);
00266     for (int i = 0; i < nr_correspondences_result_rej_trimmed; ++i)
00267       EXPECT_EQ ((*correspondences_result_rej_trimmed)[i].index_match, correspondences_trimmed[i][1]);
00268   }
00269 }
00270 
00272 TEST (PCL, CorrespondenceRejectorVarTrimmed)
00273 {
00274   pcl::PointCloud<pcl::PointXYZ>::Ptr source (new pcl::PointCloud<pcl::PointXYZ>(cloud_source));
00275   pcl::PointCloud<pcl::PointXYZ>::Ptr target (new pcl::PointCloud<pcl::PointXYZ>(cloud_target));
00276 
00277   // re-do correspondence estimation
00278   boost::shared_ptr<pcl::Correspondences> correspondences (new pcl::Correspondences);
00279   pcl::registration::CorrespondenceEstimation<pcl::PointXYZ, pcl::PointXYZ> corr_est;
00280   corr_est.setInputCloud (source);
00281   corr_est.setInputTarget (target);
00282   corr_est.determineCorrespondences (*correspondences);
00283 
00284   boost::shared_ptr<pcl::Correspondences>  correspondences_result_rej_var_trimmed_dist (new pcl::Correspondences);
00285   pcl::registration::CorrespondenceRejectorVarTrimmed corr_rej_var_trimmed_dist;
00286   corr_rej_var_trimmed_dist.setInputCloud<pcl::PointXYZ> (source);
00287   corr_rej_var_trimmed_dist.setInputTarget<pcl::PointXYZ> (target);
00288   corr_rej_var_trimmed_dist.setInputCorrespondences(correspondences);
00289 
00290   corr_rej_var_trimmed_dist.getCorrespondences(*correspondences_result_rej_var_trimmed_dist);
00291 
00292   // check for correct matches
00293   if (int (correspondences_result_rej_var_trimmed_dist->size ()) == nr_correspondences_result_rej_dist)
00294     for (int i = 0; i < nr_correspondences_result_rej_dist; ++i)
00295       EXPECT_EQ ((*correspondences_result_rej_var_trimmed_dist)[i].index_match, correspondences_dist[i][1]);
00296 }
00297 
00299 TEST (PCL, TransformationEstimationSVD)
00300 {
00301   pcl::PointCloud<pcl::PointXYZ>::Ptr source (new pcl::PointCloud<pcl::PointXYZ>(cloud_source));
00302   pcl::PointCloud<pcl::PointXYZ>::Ptr target (new pcl::PointCloud<pcl::PointXYZ>(cloud_target));
00303 
00304   // re-do reciprocal correspondence estimation
00305   boost::shared_ptr<pcl::Correspondences> correspondences (new pcl::Correspondences);
00306   pcl::registration::CorrespondenceEstimation<pcl::PointXYZ, pcl::PointXYZ> corr_est;
00307   corr_est.setInputCloud (source);
00308   corr_est.setInputTarget (target);
00309   corr_est.determineReciprocalCorrespondences (*correspondences);
00310 
00311   Eigen::Matrix4f transform_res_from_SVD;
00312   pcl::registration::TransformationEstimationSVD<pcl::PointXYZ, pcl::PointXYZ> trans_est_svd;
00313   trans_est_svd.estimateRigidTransformation(*source, *target,
00314                                             *correspondences,
00315                                             transform_res_from_SVD);
00316 
00317   // check for correct transformation
00318   for (int i = 0; i < 4; ++i)
00319     for (int j = 0; j < 4; ++j)
00320       EXPECT_NEAR (transform_res_from_SVD(i, j), transform_from_SVD[i][j], 1e-4);
00321 }
00322 
00324 TEST (PCL, TransformationEstimationLM)
00325 {
00326   pcl::PointCloud<pcl::PointXYZ>::Ptr source (new pcl::PointCloud<pcl::PointXYZ>(cloud_source));
00327   pcl::PointCloud<pcl::PointXYZ>::Ptr target (new pcl::PointCloud<pcl::PointXYZ>(cloud_target));
00328 
00329   // re-do reciprocal correspondence estimation
00330   boost::shared_ptr<pcl::Correspondences> correspondences (new pcl::Correspondences);
00331   pcl::registration::CorrespondenceEstimation<pcl::PointXYZ, pcl::PointXYZ> corr_est;
00332   corr_est.setInputCloud (source);
00333   corr_est.setInputTarget (target);
00334   corr_est.determineReciprocalCorrespondences (*correspondences);
00335 
00336   Eigen::Matrix4f transform_res_from_LM;
00337   pcl::registration::TransformationEstimationLM<pcl::PointXYZ, pcl::PointXYZ> trans_est_lm;
00338   trans_est_lm.estimateRigidTransformation (*source, *target,
00339                                             *correspondences,
00340                                             transform_res_from_LM);
00341 
00342   // check for correct matches and number of matches
00343   EXPECT_EQ (int (correspondences->size ()), nr_reciprocal_correspondences);
00344   for (int i = 0; i < nr_reciprocal_correspondences; ++i)
00345   {
00346     EXPECT_EQ ((*correspondences)[i].index_query, correspondences_reciprocal[i][0]);
00347     EXPECT_EQ ((*correspondences)[i].index_match, correspondences_reciprocal[i][1]);
00348   }
00349 
00350 //  // check for correct transformation
00351 //  for (int i = 0; i < 4; ++i)
00352 //    for (int j = 0; j < 4; ++j)
00353 //      EXPECT_NEAR (transform_res_from_LM(i, j), transform_from_LM[i][j], 1e-4);
00354 }
00355 
00356 /* ---[ */
00357 int
00358   main (int argc, char** argv)
00359 {
00360   if (argc < 3)
00361   {
00362     std::cerr << "No test files given. Please download `bun0.pcd` and `bun4.pcd` and pass their path to the test." << std::endl;
00363     return (-1);
00364   }
00365 
00366   // Input
00367   if (pcl::io::loadPCDFile (argv[1], cloud_source) < 0)
00368   {
00369     std::cerr << "Failed to read test file. Please download `bun0.pcd` and pass its path to the test." << std::endl;
00370     return (-1);
00371   }
00372   if (pcl::io::loadPCDFile (argv[2], cloud_target) < 0)
00373   {
00374     std::cerr << "Failed to read test file. Please download `bun4.pcd` and pass its path to the test." << std::endl;
00375     return (-1);
00376   }
00377 
00378   testing::InitGoogleTest (&argc, argv);
00379   return (RUN_ALL_TESTS ());
00380 
00381   // Tranpose the cloud_model
00382   /*for (size_t i = 0; i < cloud_model.points.size (); ++i)
00383   {
00384   //  cloud_model.points[i].z += 1;
00385   }*/
00386 }
00387 /* ]--- */


pcl
Author(s): Open Perception
autogenerated on Mon Oct 6 2014 03:18:29