37 #ifndef PCL_REGISTRATION_IMPL_IA_KFPCS_H_
38 #define PCL_REGISTRATION_IMPL_IA_KFPCS_H_
44 namespace registration {
46 template <
typename Po
intSource,
typename Po
intTarget,
typename NormalT,
typename Scalar>
51 reg_name_ =
"pcl::registration::KFPCSInitialAlignment";
54 template <
typename Po
intSource,
typename Po
intTarget,
typename NormalT,
typename Scalar>
59 if (normalize_delta_) {
60 PCL_WARN(
"[%s::initCompute] Delta should be set according to keypoint precision! "
61 "Normalization according to point cloud density is ignored.\n",
63 normalize_delta_ =
false;
71 max_pair_diff_ = delta_ * 1.414f;
72 coincidation_limit_ = delta_ * 2.828f;
77 powf(delta_ * 4.f, 2.f);
78 max_inlier_dist_sqr_ =
83 if (upper_trl_boundary_ < 0)
84 upper_trl_boundary_ = diameter_ * (1.f - approx_overlap_) * 0.5f;
86 if (!(lower_trl_boundary_ < 0) && upper_trl_boundary_ > lower_trl_boundary_)
87 use_trl_score_ =
true;
93 if (indices_->size() <=
static_cast<std::size_t
>(ransac_iterations_) ||
94 ransac_iterations_ <= 0)
95 indices_validation_ = indices_;
101 random_sampling.
setSample(ransac_iterations_);
102 random_sampling.
filter(*indices_validation_);
105 PCL_DEBUG(
"[%s::initCompute] delta_=%g, max_inlier_dist_sqr_=%g, "
106 "coincidation_limit_=%g, max_edge_diff_=%g, max_pair_diff_=%g\n",
109 max_inlier_dist_sqr_,
116 template <
typename Po
intSource,
typename Po
intTarget,
typename NormalT,
typename Scalar>
120 std::vector<pcl::Indices>& matches,
126 for (
auto& match : matches) {
127 Eigen::Matrix4f transformation_temp;
129 float fitness_score =
130 std::numeric_limits<float>::max();
133 correspondences_temp.emplace_back(match[0], base_indices[0], 0.0);
134 correspondences_temp.emplace_back(match[1], base_indices[1], 0.0);
135 correspondences_temp.emplace_back(match[2], base_indices[2], 0.0);
136 correspondences_temp.emplace_back(match[3], base_indices[3], 0.0);
139 if (validateMatch(base_indices, match, correspondences_temp, transformation_temp) <
145 validateTransformation(transformation_temp, fitness_score);
148 candidates.emplace_back(fitness_score, correspondences_temp, transformation_temp);
152 if (!candidates.empty()) {
153 auto best_candidate = candidates.begin();
154 for (
auto iter = candidates.begin(); iter < candidates.end(); ++iter)
155 if (iter->fitness_score < best_candidate->fitness_score)
156 best_candidate = iter;
157 if (best_candidate != candidates.begin())
158 std::swap(*best_candidate, *candidates.begin());
162 template <
typename Po
intSource,
typename Po
intTarget,
typename NormalT,
typename Scalar>
170 *input_, *indices_validation_, source_transformed, transformation);
172 const std::size_t nr_points = source_transformed.
size();
173 float score_a = 0.f, score_b = 0.f;
177 std::vector<float> dists_sqr(1);
178 for (
const auto& source : source_transformed) {
180 tree_->nearestKSearch(source, 1, ids, dists_sqr);
181 score_a += (dists_sqr[0] < max_inlier_dist_sqr_ ? dists_sqr[0]
182 : max_inlier_dist_sqr_);
185 score_a /= (max_inlier_dist_sqr_ * nr_points);
191 if (use_trl_score_) {
192 float trl = transformation.rightCols<1>().head<3>().norm();
194 (trl - lower_trl_boundary_) / (upper_trl_boundary_ - lower_trl_boundary_);
197 (trl_ratio < 0.f ? 1.f
198 : (trl_ratio > 1.f ? 0.f
199 : 0.5f * sin(M_PI * trl_ratio + M_PI_2) +
205 float fitness_score_temp = (score_a + lambda_ * score_b) / scale;
206 if (fitness_score_temp > fitness_score)
209 fitness_score = fitness_score_temp;
213 template <
typename Po
intSource,
typename Po
intTarget,
typename NormalT,
typename Scalar>
216 const std::vector<MatchingCandidates>& candidates)
219 std::size_t total_size = 0;
220 for (
const auto& candidate : candidates)
221 total_size += candidate.size();
224 candidates_.reserve(total_size);
226 for (
const auto& candidate : candidates)
227 for (
const auto& match : candidate)
228 candidates_.push_back(match);
231 std::sort(candidates_.begin(), candidates_.end(),
by_score());
235 if (candidates_[0].fitness_score == std::numeric_limits<float>::max()) {
243 fitness_score_ = candidates_[0].fitness_score;
244 final_transformation_ = candidates_[0].transformation;
245 *correspondences_ = candidates_[0].correspondences;
246 PCL_DEBUG(
"[%s::finalCompute] best score is %g, out of %zu candidate solutions.\n",
252 converged_ = fitness_score_ < score_threshold_;
255 template <
typename Po
intSource,
typename Po
intTarget,
typename NormalT,
typename Scalar>
263 for (
const auto& candidate : candidates_) {
265 if (candidate.fitness_score == std::numeric_limits<float>::max())
271 for (
const auto& c2 : candidates) {
272 Eigen::Matrix4f diff =
273 candidate.transformation.colPivHouseholderQr().solve(c2.transformation);
274 const float angle3d = Eigen::AngleAxisf(diff.topLeftCorner<3, 3>()).angle();
275 const float translation3d = diff.block<3, 1>(0, 3).norm();
276 unique = angle3d > min_angle3d && translation3d > min_translation3d;
284 candidates.push_back(candidate);
287 if (candidates.size() == n)
292 template <
typename Po
intSource,
typename Po
intTarget,
typename NormalT,
typename Scalar>
300 for (
const auto& candidate : candidates_) {
302 if (candidate.fitness_score > t)
308 for (
const auto& c2 : candidates) {
309 Eigen::Matrix4f diff =
310 candidate.transformation.colPivHouseholderQr().solve(c2.transformation);
311 const float angle3d = Eigen::AngleAxisf(diff.topLeftCorner<3, 3>()).angle();
312 const float translation3d = diff.block<3, 1>(0, 3).norm();
313 unique = angle3d > min_angle3d && translation3d > min_translation3d;
321 candidates.push_back(candidate);
328 #endif // PCL_REGISTRATION_IMPL_IA_KFPCS_H_
virtual bool initCompute()
Internal computation initialization.
bool initCompute() override
Internal computation initialization.
Sorting of candidates based on fitness score value.
void setSample(unsigned int sample)
Set number of indices to be sampled.
void getNBestCandidates(int n, float min_angle3d, float min_translation3d, MatchingCandidates &candidates)
Get the N best unique candidate matches according to their fitness score.
void getTBestCandidates(float t, float min_angle3d, float min_translation3d, MatchingCandidates &candidates)
Get all unique candidate matches with fitness scores above a threshold t.
int validateTransformation(Eigen::Matrix4f &transformation, float &fitness_score) override
Validate the transformation by calculating the score value after transforming the input source cloud...
void handleMatches(const pcl::Indices &base_indices, std::vector< pcl::Indices > &matches, MatchingCandidates &candidates) override
Method to handle current candidate matches.
KFPCSInitialAlignment()
Constructor.
IndicesAllocator<> Indices
Type used for indices in PCL.
void finalCompute(const std::vector< MatchingCandidates > &candidates) override
Final computation of best match out of vector of matches.
virtual void setIndices(const IndicesPtr &indices)
Provide a pointer to the vector of indices that represents the input data.
virtual void setInputCloud(const PointCloudConstPtr &cloud)
Provide a pointer to the input dataset.
std::string reg_name_
The registration method name.
std::vector< pcl::Correspondence, Eigen::aligned_allocator< pcl::Correspondence > > Correspondences
void filter(Indices &indices)
Calls the filtering method and returns the filtered point cloud indices.
std::vector< MatchingCandidate, Eigen::aligned_allocator< MatchingCandidate >> MatchingCandidates
RandomSample applies a random sampling with uniform probability.
void transformPointCloud(const pcl::PointCloud< PointT > &cloud_in, pcl::PointCloud< PointT > &cloud_out, const Eigen::Matrix< Scalar, 4, 4 > &transform, bool copy_all_fields)
Apply a rigid transform defined by a 4x4 matrix.