41 #ifndef IA_RANSAC_HPP_
42 #define IA_RANSAC_HPP_
45 #include <pcl/search/auto.h>
49 template <
typename Po
intSource,
typename Po
intTarget,
typename FeatureT>
54 if (features ==
nullptr || features->empty()) {
56 "[pcl::%s::setSourceFeatures] Invalid or empty point cloud dataset given!\n",
57 getClassName().c_str());
60 input_features_ = features;
63 template <
typename Po
intSource,
typename Po
intTarget,
typename FeatureT>
68 if (features ==
nullptr || features->empty()) {
70 "[pcl::%s::setTargetFeatures] Invalid or empty point cloud dataset given!\n",
71 getClassName().c_str());
74 target_features_ = features;
75 feature_tree_.reset(pcl::search::autoSelectMethod<FeatureT>(
79 template <
typename Po
intSource,
typename Po
intTarget,
typename FeatureT>
83 unsigned int nr_samples,
84 float min_sample_distance,
87 if (nr_samples > cloud.size()) {
88 PCL_ERROR(
"[pcl::%s::selectSamples] ", getClassName().c_str());
89 PCL_ERROR(
"The number of samples (%u) must not be greater than the number of "
92 static_cast<std::size_t
>(cloud.size()));
97 index_t iterations_without_a_sample = 0;
98 const auto max_iterations_without_a_sample = 3 * cloud.size();
99 sample_indices.clear();
100 while (sample_indices.size() < nr_samples) {
102 const auto sample_index = getRandomIndex(cloud.size());
105 bool valid_sample =
true;
106 for (
const auto& sample_idx : sample_indices) {
107 float distance_between_samples =
110 if (sample_index == sample_idx ||
111 distance_between_samples < min_sample_distance) {
112 valid_sample =
false;
119 sample_indices.push_back(sample_index);
120 iterations_without_a_sample = 0;
123 ++iterations_without_a_sample;
126 if (
static_cast<std::size_t
>(iterations_without_a_sample) >=
127 max_iterations_without_a_sample) {
128 PCL_WARN(
"[pcl::%s::selectSamples] ", getClassName().c_str());
129 PCL_WARN(
"No valid sample found after %zu iterations. Relaxing "
130 "min_sample_distance_ to %f\n",
131 static_cast<std::size_t
>(iterations_without_a_sample),
132 0.5 * min_sample_distance);
134 min_sample_distance_ *= 0.5f;
135 min_sample_distance = min_sample_distance_;
136 iterations_without_a_sample = 0;
141 template <
typename Po
intSource,
typename Po
intTarget,
typename FeatureT>
149 std::vector<float> nn_distances(k_correspondences_);
151 corresponding_indices.resize(sample_indices.size());
152 for (std::size_t i = 0; i < sample_indices.size(); ++i) {
154 feature_tree_->nearestKSearch(input_features,
161 const auto random_correspondence = getRandomIndex(k_correspondences_);
162 corresponding_indices[i] = nn_indices[random_correspondence];
166 template <
typename Po
intSource,
typename Po
intTarget,
typename FeatureT>
172 std::vector<float> nn_distance(1);
177 for (
const auto& point : cloud) {
180 tree_->nearestKSearch(point, 1, nn_index, nn_distance);
183 error += compute_error(nn_distance[0]);
188 template <
typename Po
intSource,
typename Po
intTarget,
typename FeatureT>
194 if (!input_features_) {
195 PCL_ERROR(
"[pcl::%s::computeTransformation] ", getClassName().c_str());
197 "No source features were given! Call setSourceFeatures before aligning.\n");
200 if (!target_features_) {
201 PCL_ERROR(
"[pcl::%s::computeTransformation] ", getClassName().c_str());
203 "No target features were given! Call setTargetFeatures before aligning.\n");
207 if (input_->size() != input_features_->size()) {
208 PCL_ERROR(
"[pcl::%s::computeTransformation] ", getClassName().c_str());
209 PCL_ERROR(
"The source points and source feature points need to be in a one-to-one "
210 "relationship! Current input cloud sizes: %ld vs %ld.\n",
212 input_features_->size());
216 if (target_->size() != target_features_->size()) {
217 PCL_ERROR(
"[pcl::%s::computeTransformation] ", getClassName().c_str());
218 PCL_ERROR(
"The target points and target feature points need to be in a one-to-one "
219 "relationship! Current input cloud sizes: %ld vs %ld.\n",
221 target_features_->size());
226 error_functor_.reset(
new TruncatedError(
static_cast<float>(corr_dist_threshold_)));
231 float lowest_error(0);
233 final_transformation_ = guess;
236 if (!guess.isApprox(Eigen::Matrix4f::Identity(), 0.01f)) {
240 computeErrorMetric(input_transformed,
static_cast<float>(corr_dist_threshold_));
244 for (; i_iter < max_iterations_; ++i_iter) {
246 selectSamples(*input_, nr_samples_, min_sample_distance_, sample_indices);
249 findSimilarFeatures(*input_features_, sample_indices, corresponding_indices);
252 transformation_estimation_->estimateRigidTransformation(
253 *input_, sample_indices, *target_, corresponding_indices, transformation_);
258 computeErrorMetric(input_transformed,
static_cast<float>(corr_dist_threshold_));
261 if (i_iter == 0 || error < lowest_error) {
262 lowest_error = error;
263 final_transformation_ = transformation_;
void computeTransformation(PointCloudSource &output, const Eigen::Matrix4f &guess) override
Rigid transformation computation method.
float computeErrorMetric(const PointCloudSource &cloud, float threshold)
An error metric for that computes the quality of the alignment between the given cloud and the target...
typename Registration< PointSource, PointTarget >::PointCloudSource PointCloudSource
void setTargetFeatures(const FeatureCloudConstPtr &features)
Provide a shared pointer to the target point cloud's feature descriptors.
void selectSamples(const PointCloudSource &cloud, unsigned int nr_samples, float min_sample_distance, pcl::Indices &sample_indices)
Select nr_samples sample points from cloud while making sure that their pairwise distances are greate...
void findSimilarFeatures(const FeatureCloud &input_features, const pcl::Indices &sample_indices, pcl::Indices &corresponding_indices)
For each of the sample points, find a list of points in the target cloud whose features are similar t...
typename FeatureCloud::ConstPtr FeatureCloudConstPtr
void setSourceFeatures(const FeatureCloudConstPtr &features)
Provide a shared pointer to the source point cloud's feature descriptors.
Define standard C methods to do distance calculations.
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.
@ many_knn_search
The search method will mainly be used for nearestKSearch where k is larger than 1.
detail::int_type_t< detail::index_type_size, detail::index_type_signed > index_t
Type used for an index in PCL.
float euclideanDistance(const PointType1 &p1, const PointType2 &p2)
Calculate the euclidean distance between the two given points.
IndicesAllocator<> Indices
Type used for indices in PCL.