34 #include <pcl/registration/icp.h> 35 #include <pcl/registration/transformation_estimation_2D.h> 36 #include <pcl/registration/transformation_estimation_svd.h> 37 #include <pcl/sample_consensus/sac_model_registration.h> 38 #include <pcl/sample_consensus/ransac.h> 39 #include <pcl/common/common.h> 51 const pcl::PointCloud<pcl::PointXYZ> & cloud1,
52 const pcl::PointCloud<pcl::PointXYZ> & cloud2)
54 pcl::registration::TransformationEstimationSVD<pcl::PointXYZ, pcl::PointXYZ> svd;
57 Eigen::Matrix4f matrix;
58 svd.estimateRigidTransformation(cloud1, cloud2, matrix);
64 const pcl::PointCloud<pcl::PointXYZ>::ConstPtr & cloud1,
65 const pcl::PointCloud<pcl::PointXYZ>::ConstPtr & cloud2,
66 double inlierThreshold,
70 std::vector<int> * inliersOut,
79 *covariance = cv::Mat::eye(6,6,CV_64FC1);
82 if(cloud1->size() >=3 && cloud1->size() == cloud2->size())
85 UDEBUG(
"iterations=%d inlierThreshold=%f", iterations, inlierThreshold);
86 std::vector<int> source_indices (cloud2->size());
87 std::vector<int> target_indices (cloud1->size());
90 for (
int i = 0; i < (int)cloud1->size(); ++i)
92 source_indices[i] = i;
93 target_indices[i] = i;
98 pcl::SampleConsensusModelRegistration<pcl::PointXYZ>::Ptr model;
99 model.reset(
new pcl::SampleConsensusModelRegistration<pcl::PointXYZ>(cloud2, source_indices));
101 model->setInputTarget (cloud1, target_indices);
103 pcl::RandomSampleConsensus<pcl::PointXYZ> sac (model, inlierThreshold);
104 sac.setMaxIterations(iterations);
107 if(sac.computeModel())
109 std::vector<int> inliers;
110 Eigen::VectorXf model_coefficients;
112 sac.getInliers(inliers);
113 sac.getModelCoefficients (model_coefficients);
115 if (refineIterations>0)
117 double error_threshold = inlierThreshold;
118 int refine_iterations = 0;
119 bool inlier_changed =
false, oscillating =
false;
120 std::vector<int> new_inliers, prev_inliers = inliers;
121 std::vector<size_t> inliers_sizes;
122 Eigen::VectorXf new_model_coefficients = model_coefficients;
126 model->optimizeModelCoefficients (prev_inliers, new_model_coefficients, new_model_coefficients);
127 inliers_sizes.push_back (prev_inliers.size ());
130 model->selectWithinDistance (new_model_coefficients, error_threshold, new_inliers);
131 UDEBUG(
"RANSAC refineModel: Number of inliers found (before/after): %d/%d, with an error threshold of %f.",
132 (
int)prev_inliers.size (), (int)new_inliers.size (), error_threshold);
134 if (new_inliers.empty ())
137 if (refine_iterations >= refineIterations)
145 double variance = model->computeVariance ();
146 error_threshold =
std::min (inlierThreshold, refineSigma *
sqrt(variance));
148 UDEBUG (
"RANSAC refineModel: New estimated error threshold: %f (variance=%f) on iteration %d out of %d.",
149 error_threshold, variance, refine_iterations, refineIterations);
150 inlier_changed =
false;
151 std::swap (prev_inliers, new_inliers);
154 if (new_inliers.size () != prev_inliers.size ())
157 if (inliers_sizes.size () >= 4)
159 if (inliers_sizes[inliers_sizes.size () - 1] == inliers_sizes[inliers_sizes.size () - 3] &&
160 inliers_sizes[inliers_sizes.size () - 2] == inliers_sizes[inliers_sizes.size () - 4])
166 inlier_changed =
true;
171 for (
size_t i = 0; i < prev_inliers.size (); ++i)
174 if (prev_inliers[i] != new_inliers[i])
176 inlier_changed =
true;
181 while (inlier_changed && ++refine_iterations < refineIterations);
184 if (new_inliers.empty ())
186 UWARN (
"RANSAC refineModel: Refinement failed: got an empty set of inliers!");
191 UDEBUG(
"RANSAC refineModel: Detected oscillations in the model refinement.");
194 std::swap (inliers, new_inliers);
195 model_coefficients = new_model_coefficients;
198 if (inliers.size() >= 3)
202 *inliersOut = inliers;
206 double variance = model->computeVariance();
208 *covariance *= variance;
212 Eigen::Matrix4f bestTransformation;
213 bestTransformation.row (0) = model_coefficients.segment<4>(0);
214 bestTransformation.row (1) = model_coefficients.segment<4>(4);
215 bestTransformation.row (2) = model_coefficients.segment<4>(8);
216 bestTransformation.row (3) = model_coefficients.segment<4>(12);
219 UDEBUG(
"RANSAC inliers=%d/%d tf=%s", (
int)inliers.size(), (int)cloud1->size(), transform.
prettyPrint().c_str());
225 UDEBUG(
"RANSAC: Model with inliers < 3");
230 UDEBUG(
"RANSAC: Failed to find model");
235 UDEBUG(
"Not enough points to compute the transform");
241 const pcl::PointCloud<pcl::PointNormal>::ConstPtr & cloudA,
242 const pcl::PointCloud<pcl::PointNormal>::ConstPtr & cloudB,
243 double maxCorrespondenceDistance,
244 double maxCorrespondenceAngle,
246 int & correspondencesOut)
249 correspondencesOut = 0;
250 pcl::registration::CorrespondenceEstimation<pcl::PointNormal, pcl::PointNormal>::Ptr est;
251 est.reset(
new pcl::registration::CorrespondenceEstimation<pcl::PointNormal, pcl::PointNormal>);
252 const pcl::PointCloud<pcl::PointNormal>::ConstPtr & target = cloudA->size()>cloudB->size()?cloudA:cloudB;
253 const pcl::PointCloud<pcl::PointNormal>::ConstPtr &
source = cloudA->size()>cloudB->size()?cloudB:cloudA;
254 est->setInputTarget(target);
255 est->setInputSource(source);
256 pcl::Correspondences correspondences;
257 est->determineCorrespondences(correspondences, maxCorrespondenceDistance);
259 if(correspondences.size())
261 std::vector<double> distances(correspondences.size());
262 correspondencesOut = 0;
263 for(
unsigned int i=0; i<correspondences.size(); ++i)
265 distances[i] = correspondences[i].distance;
266 if(maxCorrespondenceAngle <= 0.0)
268 ++correspondencesOut;
273 target->at(correspondences[i].index_match).normal_x,
274 target->at(correspondences[i].index_match).normal_y,
275 target->at(correspondences[i].index_match).normal_z,
278 source->at(correspondences[i].index_query).normal_x,
279 source->at(correspondences[i].index_query).normal_y,
280 source->at(correspondences[i].index_query).normal_z,
282 float angle = pcl::getAngle3D(v1, v2);
283 if(angle < maxCorrespondenceAngle)
285 ++correspondencesOut;
289 if(correspondencesOut)
291 distances.resize(correspondencesOut);
294 std::sort(distances.begin (), distances.end ());
295 double median_error_sqr = distances[distances.size () >> 1];
296 variance = (2.1981 * median_error_sqr);
302 const pcl::PointCloud<pcl::PointXYZ>::ConstPtr & cloudA,
303 const pcl::PointCloud<pcl::PointXYZ>::ConstPtr & cloudB,
304 double maxCorrespondenceDistance,
306 int & correspondencesOut)
309 correspondencesOut = 0;
310 pcl::registration::CorrespondenceEstimation<pcl::PointXYZ, pcl::PointXYZ>::Ptr est;
311 est.reset(
new pcl::registration::CorrespondenceEstimation<pcl::PointXYZ, pcl::PointXYZ>);
312 est->setInputTarget(cloudA->size()>cloudB->size()?cloudA:cloudB);
313 est->setInputSource(cloudA->size()>cloudB->size()?cloudB:cloudA);
314 pcl::Correspondences correspondences;
315 est->determineCorrespondences(correspondences, maxCorrespondenceDistance);
317 if(correspondences.size()>=3)
319 std::vector<double> distances(correspondences.size());
320 for(
unsigned int i=0; i<correspondences.size(); ++i)
322 distances[i] = correspondences[i].distance;
326 std::sort(distances.begin (), distances.end ());
327 double median_error_sqr = distances[distances.size () >> 1];
328 variance = (2.1981 * median_error_sqr);
331 correspondencesOut = (int)correspondences.size();
335 Transform icp(
const pcl::PointCloud<pcl::PointXYZ>::ConstPtr & cloud_source,
336 const pcl::PointCloud<pcl::PointXYZ>::ConstPtr & cloud_target,
337 double maxCorrespondenceDistance,
338 int maximumIterations,
340 pcl::PointCloud<pcl::PointXYZ> & cloud_source_registered,
344 pcl::IterativeClosestPoint<pcl::PointXYZ, pcl::PointXYZ>
icp;
346 icp.setInputTarget (cloud_target);
347 icp.setInputSource (cloud_source);
351 pcl::registration::TransformationEstimation2D<pcl::PointXYZ, pcl::PointXYZ>::Ptr est;
352 est.reset(
new pcl::registration::TransformationEstimation2D<pcl::PointXYZ, pcl::PointXYZ>);
353 icp.setTransformationEstimation(est);
357 icp.setMaxCorrespondenceDistance (maxCorrespondenceDistance);
359 icp.setMaximumIterations (maximumIterations);
361 icp.setTransformationEpsilon (epsilon*epsilon);
367 icp.align (cloud_source_registered);
368 hasConverged = icp.hasConverged();
374 const pcl::PointCloud<pcl::PointNormal>::ConstPtr & cloud_source,
375 const pcl::PointCloud<pcl::PointNormal>::ConstPtr & cloud_target,
376 double maxCorrespondenceDistance,
377 int maximumIterations,
379 pcl::PointCloud<pcl::PointNormal> & cloud_source_registered,
383 pcl::IterativeClosestPoint<pcl::PointNormal, pcl::PointNormal>
icp;
385 icp.setInputTarget (cloud_target);
386 icp.setInputSource (cloud_source);
388 pcl::registration::TransformationEstimationPointToPlaneLLS<pcl::PointNormal, pcl::PointNormal>::Ptr est;
389 est.reset(
new pcl::registration::TransformationEstimationPointToPlaneLLS<pcl::PointNormal, pcl::PointNormal>);
390 icp.setTransformationEstimation(est);
393 icp.setMaxCorrespondenceDistance (maxCorrespondenceDistance);
395 icp.setMaximumIterations (maximumIterations);
397 icp.setTransformationEpsilon (epsilon*epsilon);
403 icp.align (cloud_source_registered);
404 hasConverged = icp.hasConverged();
Transform RTABMAP_EXP transformFromXYZCorrespondencesSVD(const pcl::PointCloud< pcl::PointXYZ > &cloud1, const pcl::PointCloud< pcl::PointXYZ > &cloud2)
GLM_FUNC_DECL genType min(genType const &x, genType const &y)
GLM_FUNC_DECL vecType< T, P > sqrt(vecType< T, P > const &x)
Transform RTABMAP_EXP icpPointToPlane(const pcl::PointCloud< pcl::PointNormal >::ConstPtr &cloud_source, const pcl::PointCloud< pcl::PointNormal >::ConstPtr &cloud_target, double maxCorrespondenceDistance, int maximumIterations, bool &hasConverged, pcl::PointCloud< pcl::PointNormal > &cloud_source_registered, float epsilon=0.0f, bool icp2D=false)
void RTABMAP_EXP computeVarianceAndCorrespondences(const pcl::PointCloud< pcl::PointNormal >::ConstPtr &cloudA, const pcl::PointCloud< pcl::PointNormal >::ConstPtr &cloudB, double maxCorrespondenceDistance, double maxCorrespondenceAngle, double &variance, int &correspondencesOut)
Basic mathematics functions.
GLM_FUNC_DECL T angle(detail::tquat< T, P > const &x)
Transform RTABMAP_EXP transformFromXYZCorrespondences(const pcl::PointCloud< pcl::PointXYZ >::ConstPtr &cloud1, const pcl::PointCloud< pcl::PointXYZ >::ConstPtr &cloud2, double inlierThreshold=0.02, int iterations=100, int refineModelIterations=10, double refineModelSigma=3.0, std::vector< int > *inliers=0, cv::Mat *variance=0)
bool uIsFinite(const T &value)
#define UASSERT(condition)
Transform RTABMAP_EXP icp(const pcl::PointCloud< pcl::PointXYZ >::ConstPtr &cloud_source, const pcl::PointCloud< pcl::PointXYZ >::ConstPtr &cloud_target, double maxCorrespondenceDistance, int maximumIterations, bool &hasConverged, pcl::PointCloud< pcl::PointXYZ > &cloud_source_registered, float epsilon=0.0f, bool icp2D=false)
ULogger class and convenient macros.