@@ -112,20 +112,47 @@ FastRobustIterativeClosestPoint<PointSource, PointTarget, Scalar>::
112112 nu_decay_ratio_ = 0.5 ;
113113}
114114
115+ template <typename PointSource, typename PointTarget, typename Scalar>
116+ typename FastRobustIterativeClosestPoint<PointSource, PointTarget, Scalar>::
117+ ConvergenceTrigger
118+ FastRobustIterativeClosestPoint<PointSource, PointTarget, Scalar>::
119+ getLastConvergenceTrigger () const
120+ {
121+ return last_convergence_trigger_;
122+ }
123+
115124template <typename PointSource, typename PointTarget, typename Scalar>
116125void
117126FastRobustIterativeClosestPoint<PointSource, PointTarget, Scalar>::
118127 computeTransformation (PointCloudSource& output, const Matrix4& guess)
119128{
120129 pcl::IterativeClosestPoint<PointSource, PointTarget, Scalar>::initComputeReciprocal ();
121130
131+ last_convergence_trigger_ = ConvergenceTrigger::NONE;
132+
133+ auto convergence_criteria = this ->getConvergeCriteria ();
134+ if (convergence_criteria) {
135+ convergence_criteria->setMaximumIterations (this ->max_iterations_ );
136+ convergence_criteria->setRelativeMSE (this ->euclidean_fitness_epsilon_ );
137+ convergence_criteria->setTranslationThreshold (this ->transformation_epsilon_ );
138+ if (this ->transformation_rotation_epsilon_ > 0 ) {
139+ convergence_criteria->setRotationThreshold (
140+ this ->transformation_rotation_epsilon_ );
141+ }
142+ convergence_criteria->setConvergenceState (
143+ pcl::registration::DefaultConvergenceCriteria<
144+ Scalar>::CONVERGENCE_CRITERIA_NOT_CONVERGED);
145+ }
146+
122147 if (!this ->input_ || !this ->target_ ) {
148+ last_convergence_trigger_ = ConvergenceTrigger::NO_CORRESPONDENCES;
123149 PCL_ERROR (" [pcl::%s::computeTransformation] Invalid input clouds.\n " ,
124150 this ->getClassName ().c_str ());
125151 return ;
126152 }
127153
128154 if (this ->input_ ->empty () || this ->target_ ->empty ()) {
155+ last_convergence_trigger_ = ConvergenceTrigger::NO_CORRESPONDENCES;
129156 PCL_ERROR (" [pcl::%s::computeTransformation] Empty input point clouds.\n " ,
130157 this ->getClassName ().c_str ());
131158 return ;
@@ -144,6 +171,12 @@ FastRobustIterativeClosestPoint<PointSource, PointTarget, Scalar>::
144171 PCL_ERROR (" [pcl::%s::computeTransformation] Not enough source points (%zu).\n " ,
145172 this ->getClassName ().c_str (),
146173 source_indices.size ());
174+ if (convergence_criteria) {
175+ convergence_criteria->setConvergenceState (
176+ pcl::registration::DefaultConvergenceCriteria<
177+ Scalar>::CONVERGENCE_CRITERIA_NO_CORRESPONDENCES);
178+ }
179+ last_convergence_trigger_ = ConvergenceTrigger::NO_CORRESPONDENCES;
147180 return ;
148181 }
149182
@@ -154,6 +187,12 @@ FastRobustIterativeClosestPoint<PointSource, PointTarget, Scalar>::
154187 PCL_ERROR (" [pcl::%s::computeTransformation] Not enough target points (%zu).\n " ,
155188 this ->getClassName ().c_str (),
156189 target_size);
190+ if (convergence_criteria) {
191+ convergence_criteria->setConvergenceState (
192+ pcl::registration::DefaultConvergenceCriteria<
193+ Scalar>::CONVERGENCE_CRITERIA_NO_CORRESPONDENCES);
194+ }
195+ last_convergence_trigger_ = ConvergenceTrigger::NO_CORRESPONDENCES;
157196 return ;
158197 }
159198
@@ -199,10 +238,17 @@ FastRobustIterativeClosestPoint<PointSource, PointTarget, Scalar>::
199238 target_mat,
200239 tree,
201240 matched_targets,
202- residuals)) {
241+ residuals,
242+ this ->correspondences_ .get ())) {
203243 PCL_ERROR (
204244 " [pcl::%s::computeTransformation] Failed to initialize correspondences.\n " ,
205245 this ->getClassName ().c_str ());
246+ if (convergence_criteria) {
247+ convergence_criteria->setConvergenceState (
248+ pcl::registration::DefaultConvergenceCriteria<
249+ Scalar>::CONVERGENCE_CRITERIA_NO_CORRESPONDENCES);
250+ }
251+ last_convergence_trigger_ = ConvergenceTrigger::NO_CORRESPONDENCES;
206252 return ;
207253 }
208254
@@ -253,10 +299,17 @@ FastRobustIterativeClosestPoint<PointSource, PointTarget, Scalar>::
253299 target_mat,
254300 tree,
255301 matched_targets,
256- residuals)) {
302+ residuals,
303+ this ->correspondences_ .get ())) {
257304 PCL_ERROR (" [pcl::%s::computeTransformation] Unable to recompute "
258305 " correspondences during fallback.\n " ,
259306 this ->getClassName ().c_str ());
307+ if (convergence_criteria) {
308+ convergence_criteria->setConvergenceState (
309+ pcl::registration::DefaultConvergenceCriteria<
310+ Scalar>::CONVERGENCE_CRITERIA_NO_CORRESPONDENCES);
311+ }
312+ last_convergence_trigger_ = ConvergenceTrigger::NO_CORRESPONDENCES;
260313 return ;
261314 }
262315 energy = use_welsch ? computeEnergy (residuals, nu_current) : residuals.sum ();
@@ -274,6 +327,10 @@ FastRobustIterativeClosestPoint<PointSource, PointTarget, Scalar>::
274327 svd_transform = candidate;
275328 transform_centered = candidate;
276329
330+ const Matrix4d delta_transform =
331+ transform_centered * previous_transform.inverse ();
332+ this ->transformation_ = delta_transform.template cast <Scalar>();
333+
277334 if (use_anderson_) {
278335 const Matrix4d log_matrix = matrixLog (transform_centered);
279336 const Eigen::VectorXd& accelerated = anderson_.compute (log_matrix.data ());
@@ -285,19 +342,38 @@ FastRobustIterativeClosestPoint<PointSource, PointTarget, Scalar>::
285342 target_mat,
286343 tree,
287344 matched_targets,
288- residuals)) {
345+ residuals,
346+ this ->correspondences_ .get ())) {
289347 PCL_ERROR (" [pcl::%s::computeTransformation] Failed to update "
290348 " correspondences.\n " ,
291349 this ->getClassName ().c_str ());
350+ if (convergence_criteria) {
351+ convergence_criteria->setConvergenceState (
352+ pcl::registration::DefaultConvergenceCriteria<
353+ Scalar>::CONVERGENCE_CRITERIA_NO_CORRESPONDENCES);
354+ }
355+ last_convergence_trigger_ = ConvergenceTrigger::NO_CORRESPONDENCES;
292356 return ;
293357 }
294358
295359 const double delta = (transform_centered - previous_transform).norm ();
296360 previous_transform = transform_centered;
297361 ++this ->nr_iterations_ ;
298362
363+ if (convergence_criteria && static_cast <bool >(*convergence_criteria)) {
364+ converged = true ;
365+ last_convergence_trigger_ = ConvergenceTrigger::DEFAULT_CRITERIA;
366+ break ;
367+ }
368+
299369 if (delta < stop_threshold) {
300370 converged = true ;
371+ if (convergence_criteria) {
372+ convergence_criteria->setConvergenceState (
373+ pcl::registration::DefaultConvergenceCriteria<
374+ Scalar>::CONVERGENCE_CRITERIA_TRANSFORM);
375+ }
376+ last_convergence_trigger_ = ConvergenceTrigger::FRICP_STOP_THRESHOLD;
301377 break ;
302378 }
303379 }
@@ -316,6 +392,15 @@ FastRobustIterativeClosestPoint<PointSource, PointTarget, Scalar>::
316392 }
317393
318394 this ->converged_ = converged;
395+ if (!converged && convergence_criteria &&
396+ convergence_criteria->getConvergenceState () ==
397+ pcl::registration::DefaultConvergenceCriteria<
398+ Scalar>::CONVERGENCE_CRITERIA_NOT_CONVERGED) {
399+ convergence_criteria->setConvergenceState (
400+ pcl::registration::DefaultConvergenceCriteria<
401+ Scalar>::CONVERGENCE_CRITERIA_ITERATIONS);
402+ last_convergence_trigger_ = ConvergenceTrigger::ITERATION_LIMIT;
403+ }
319404
320405 const Matrix4d final_transform =
321406 convertCenteredToActual (transform_centered, source_mean, target_mean);
@@ -362,14 +447,20 @@ FastRobustIterativeClosestPoint<PointSource, PointTarget, Scalar>::
362447 const Matrix3Xd& target,
363448 pcl::search::Search<pcl::PointXYZ>& tree,
364449 Matrix3Xd& matched_targets,
365- VectorXd& residuals) const
450+ VectorXd& residuals,
451+ pcl::Correspondences* correspondences) const
366452{
367453 const Eigen::Matrix3d R = transform.block <3 , 3 >(0 , 0 );
368454 const Eigen::Vector3d t = transform.block <3 , 1 >(0 , 3 );
369455 pcl::PointXYZ query;
370456 pcl::Indices nn_indices (1 );
371457 std::vector<float > nn_sqr_dists (1 );
372458
459+ if (correspondences) {
460+ correspondences->clear ();
461+ correspondences->reserve (static_cast <std::size_t >(source.cols ()));
462+ }
463+
373464 for (Eigen::Index i = 0 ; i < source.cols (); ++i) {
374465 const Eigen::Vector3d current = R * source.col (i) + t;
375466 query.x = static_cast <float >(current.x ());
@@ -382,6 +473,13 @@ FastRobustIterativeClosestPoint<PointSource, PointTarget, Scalar>::
382473 // Store squared distance reported by the search (avoid recomputing
383474 // the difference). Promote to double for internal computations.
384475 residuals (i) = static_cast <double >(nn_sqr_dists[0 ]);
476+ if (correspondences) {
477+ pcl::Correspondence corr;
478+ corr.index_query = static_cast <int >(i);
479+ corr.index_match = idx;
480+ corr.distance = nn_sqr_dists[0 ];
481+ correspondences->push_back (corr);
482+ }
385483 }
386484 return true ;
387485}
0 commit comments