|
Point Cloud Library (PCL)
1.5.1
|
00001 #ifndef PCL_REGISTRATION_INCREMENTAL_REGISTRATION_H_ 00002 #define PCL_REGISTRATION_INCREMENTAL_REGISTRATION_H_ 00003 00004 #include <pcl/pcl_base.h> 00005 #include <pcl/filters/voxel_grid.h> 00006 00007 #include <pcl/registration/correspondence_estimation.h> 00008 #include <pcl/registration/gicp.h> 00009 #include <pcl/registration/correspondence_rejection_distance.h> 00010 #include <pcl/registration/correspondence_rejection_trimmed.h> 00011 #include <pcl/registration/correspondence_rejection_one_to_one.h> 00012 #include <pcl/registration/correspondence_rejection_sample_consensus.h> 00013 00014 #include <pcl/registration/transformation_estimation_svd.h> 00015 00016 namespace pcl 00017 { 00018 namespace registration 00019 { 00020 00021 template <typename PointT> 00022 class IncrementalRegistration : public PCLBase<PointT> 00023 { 00024 using PCLBase<PointT>::initCompute; 00025 using PCLBase<PointT>::deinitCompute; 00026 00027 public: 00028 00029 using PCLBase<PointT>::indices_; 00030 using PCLBase<PointT>::input_; 00031 00032 typedef pcl::PointCloud<PointT> PointCloud; 00033 typedef typename PointCloud::Ptr PointCloudPtr; 00034 typedef typename PointCloud::ConstPtr PointCloudConstPtr; 00035 00036 IncrementalRegistration() 00037 { 00038 transform_incremental_ = Eigen::Matrix4f::Identity(); 00039 00040 downsampling_leaf_size_input_ = 0.05; 00041 downsampling_leaf_size_model_ = 0.05; 00042 registration_distance_threshold_ = 1.0; 00043 00044 downsample_input_cloud = true; 00045 downsample_model_cloud = true; 00046 00047 number_clouds_processed_ = 0; 00048 }; 00049 00050 virtual ~IncrementalRegistration(){}; 00051 00052 inline void 00053 align(PointCloud &output, bool use_vanilla_ICP = false) 00054 { 00055 00057 if ( !initCompute() ) 00058 return; 00059 00060 00062 if ( downsample_input_cloud ) 00063 { 00064 sor_.setInputCloud(input_); 00065 sor_.setIndices(indices_); 00066 sor_.setLeafSize(downsampling_leaf_size_input_, downsampling_leaf_size_input_, downsampling_leaf_size_input_); 00067 sor_.filter(cloud_input_); 00068 cloud_input_ptr_ = cloud_input_.makeShared(); 00069 } 00070 else 00071 { 00072 cloud_input_ = *input_; 00073 cloud_input_ptr_ = cloud_input_.makeShared(); 00074 // cloud_input_ptr_ = input_; 00075 } 00076 00078 if (number_clouds_processed_ == 0) 00079 { 00080 // no registration needed 00081 output = cloud_input_; 00082 cloud_model_ = cloud_input_; 00083 cloud_model_ptr_ = cloud_model_.makeShared(); 00084 transform_incremental_.setIdentity(); 00085 } 00086 else 00087 { 00088 pcl::transformPointCloud(cloud_input_, cloud_input_, transform_incremental_); 00089 00090 Eigen::Matrix4f transform_current; 00091 transform_current.setIdentity(); 00092 00093 bool registration_successful = true; 00094 00095 if ( !use_vanilla_ICP ) 00096 { 00098 reg_.setInputCloud(cloud_input_ptr_); 00099 reg_.setInputTarget(cloud_model_ptr_); 00100 reg_.setMaxCorrespondenceDistance(registration_distance_threshold_); 00101 reg_.setMaximumIterations(25); 00102 reg_.align(output); 00103 00104 transform_current = reg_.getFinalTransformation(); 00105 00106 registration_successful = true; 00108 } 00109 else 00110 { 00112 output = cloud_input_; 00113 unsigned int max_iterations = 30, n_iter = 0, n_iter_linear = max_iterations - 5; 00114 00115 registration_successful = true; 00116 while ( ( n_iter++ < max_iterations ) && registration_successful ) 00117 { 00118 float max_dist = registration_distance_threshold_; 00119 00120 bool use_linear_distance_threshold = true; 00121 if ( use_linear_distance_threshold ) 00122 { 00123 float dist_start = registration_distance_threshold_; 00124 float dist_stop = 1.5f * downsampling_leaf_size_model_; 00125 if ( n_iter < n_iter_linear ) 00126 max_dist = dist_start - n_iter * (dist_start - dist_stop) / (float)(max_iterations); 00127 else 00128 max_dist = dist_stop; 00129 } 00130 00131 // determine correspondences 00132 PointCloudConstPtr cloud_output_ptr = output.makeShared(); 00133 00134 pcl::CorrespondencesPtr correspondences_ptr (new pcl::Correspondences); 00135 corr_est_.setInputTarget(cloud_model_ptr_); 00136 corr_est_.setInputCloud(cloud_output_ptr); 00137 corr_est_.determineCorrespondences (*correspondences_ptr, max_dist); 00138 00139 // remove one-to-n correspondences 00140 pcl::CorrespondencesPtr correspondeces_one_to_one_ptr (new pcl::Correspondences); 00141 cor_rej_one_to_one_.setInputCorrespondences (correspondences_ptr); 00142 cor_rej_one_to_one_.getCorrespondences (*correspondeces_one_to_one_ptr); 00143 00144 // SAC-based correspondence rejection 00145 double sac_threshold = max_dist; 00146 int sac_max_iterations = 100; 00147 pcl::Correspondences correspondences_sac; 00148 cor_rej_sac_.setInputCloud (cloud_output_ptr); 00149 cor_rej_sac_.setTargetCloud (cloud_model_ptr_); 00150 cor_rej_sac_.setInlierThreshold (sac_threshold); 00151 cor_rej_sac_.setMaxIterations (sac_max_iterations); 00152 cor_rej_sac_.setInputCorrespondences (correspondeces_one_to_one_ptr); 00153 cor_rej_sac_.getCorrespondences (correspondences_sac); 00154 00155 unsigned int nr_min_correspondences = 10; 00156 if (correspondences_sac.size() < nr_min_correspondences) 00157 { 00158 registration_successful = false; 00159 break; 00160 } 00161 00162 Eigen::Matrix4f transform_svd; 00163 trans_est_.estimateRigidTransformation(output, cloud_model_, correspondences_sac, transform_svd); 00164 00165 pcl::transformPointCloud(output, output, transform_svd); 00166 00167 transform_current = transform_svd * transform_current; 00168 } 00169 00170 } 00171 00172 if ( registration_successful ) 00173 { 00174 transform_incremental_ = transform_current * transform_incremental_; 00175 00176 // setting up new model 00177 addCloudToModel(output); 00178 if ( downsample_model_cloud ) 00179 subsampleModel(); 00180 } 00181 00182 } 00183 00184 ++number_clouds_processed_; 00185 00187 deinitCompute (); 00188 } 00189 00191 inline PointCloud* getModel() { return &cloud_model_; }; 00192 00194 inline void reset() { number_clouds_processed_ = 0; }; 00195 00197 inline Eigen::Matrix4f getTransformation() { return transform_incremental_; }; 00198 00199 00200 00202 inline void setDownsamplingLeafSizeInput(double leaf_size) { downsampling_leaf_size_input_ = leaf_size; }; 00204 inline double getDownsamplingLeafSizeInput() { return downsampling_leaf_size_input_; }; 00205 00207 inline void setDownsamplingLeafSizeModel(double leaf_size) { downsampling_leaf_size_model_ = leaf_size; }; 00209 inline void getDownsamplingLeafSizeModel() { return downsampling_leaf_size_model_; }; 00210 00212 inline void setRegistrationDistanceThreshold(double threshold) { registration_distance_threshold_ = threshold; }; 00214 inline void getRegistrationDistanceThreshold() { return registration_distance_threshold_; }; 00215 00217 inline void downsampleInputCloud(bool enable) { downsample_input_cloud = enable; }; 00219 inline void downsampleModelCloud(bool enable) { downsample_model_cloud = enable; }; 00220 00221 protected: 00222 00223 pcl::GeneralizedIterativeClosestPoint<PointT, PointT> reg_; 00224 pcl::VoxelGrid<PointT> sor_; 00225 PointCloud cloud_input_, cloud_model_; 00226 PointCloudConstPtr cloud_input_ptr_, cloud_model_ptr_; 00227 00228 Eigen::Matrix4f transform_incremental_; 00229 00230 inline void addCloudToModel(PointCloud& cloud) 00231 { 00232 cloud_model_ += cloud; 00233 cloud_model_ptr_ = cloud_model_.makeShared(); 00234 } 00235 00236 inline void subsampleModel() 00237 { 00238 PointCloud cloud_temp; 00239 sor_.setInputCloud(cloud_model_ptr_); 00240 sor_.setLeafSize(downsampling_leaf_size_model_, downsampling_leaf_size_model_, downsampling_leaf_size_model_); 00241 sor_.filter(cloud_temp); 00242 cloud_model_ = cloud_temp; 00243 cloud_model_ptr_ = cloud_model_.makeShared(); 00244 } 00245 00246 bool downsample_input_cloud; 00247 bool downsample_model_cloud; 00248 double downsampling_leaf_size_input_; 00249 double downsampling_leaf_size_model_; 00250 double registration_distance_threshold_; 00251 00252 unsigned int number_clouds_processed_; 00253 00254 pcl::registration::CorrespondenceEstimation<PointT, PointT> corr_est_; 00255 pcl::registration::CorrespondenceRejectorOneToOne cor_rej_one_to_one_; 00256 pcl::registration::CorrespondenceRejectorSampleConsensus<PointT> cor_rej_sac_; 00257 pcl::registration::TransformationEstimationSVD<PointT, PointT> trans_est_; 00258 }; 00259 } 00260 } 00261 00262 #endif /* PCL_REGISTRATION_INCREMENTAL_REGISTRATION_H_ */
1.8.0