small_gicp
pcl_registration_impl.hpp
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright 2024 Kenji Koide
2 // SPDX-License-Identifier: MIT
3 #pragma once
4 
5 #include <pcl/impl/pcl_base.hpp>
6 #include <pcl/search/impl/search.hpp>
7 #include <pcl/search/impl/kdtree.hpp>
8 #include <pcl/search/impl/flann_search.hpp>
9 
11 
15 
19 
20 namespace small_gicp {
21 
22 template <typename PointSource, typename PointTarget>
24  reg_name_ = "RegistrationPCL";
25 
26  num_threads_ = 4;
27  k_correspondences_ = 20;
28  corr_dist_threshold_ = 1000.0;
29  rotation_epsilon_ = 2e-3;
30  transformation_epsilon_ = 5e-4;
31 
32  voxel_resolution_ = 1.0;
33  verbose_ = false;
34  registration_type_ = "GICP";
35 }
36 
37 template <typename PointSource, typename PointTarget>
39 
40 template <typename PointSource, typename PointTarget>
42  if (input_ == cloud) {
43  return;
44  }
45 
46  pcl::Registration<PointSource, PointTarget, Scalar>::setInputSource(cloud);
47  source_tree_ = std::make_shared<KdTree<pcl::PointCloud<PointSource>>>(input_, KdTreeBuilderOMP(num_threads_));
48  source_covs_.clear();
49  source_voxelmap_.reset();
50 }
51 
52 template <typename PointSource, typename PointTarget>
54  if (target_ == cloud) {
55  return;
56  }
57 
58  pcl::Registration<PointSource, PointTarget, Scalar>::setInputTarget(cloud);
59  target_tree_ = std::make_shared<KdTree<pcl::PointCloud<PointTarget>>>(target_, KdTreeBuilderOMP(num_threads_));
60  target_covs_.clear();
61  target_voxelmap_.reset();
62 }
63 
64 template <typename PointSource, typename PointTarget>
65 void RegistrationPCL<PointSource, PointTarget>::setSourceCovariances(const std::vector<Eigen::Matrix4d>& covs) {
66  if (input_ == nullptr) {
67  PCL_ERROR("[RegistrationPCL::setSourceCovariances] Target cloud is not set\n");
68  return;
69  }
70 
71  if (covs.size() != input_->size()) {
72  PCL_ERROR("[RegistrationPCL::setSourceCovariances] Invalid number of covariances: %lu\n", covs.size());
73  return;
74  }
75 
76  source_covs_ = covs;
77 }
78 
79 template <typename PointSource, typename PointTarget>
80 void RegistrationPCL<PointSource, PointTarget>::setTargetCovariances(const std::vector<Eigen::Matrix4d>& covs) {
81  if (target_ == nullptr) {
82  PCL_ERROR("[RegistrationPCL::setTargetCovariances] Target cloud is not set\n");
83  return;
84  }
85 
86  if (covs.size() != target_->size()) {
87  PCL_ERROR("[RegistrationPCL::setTargetCovariances] Invalid number of covariances: %lu\n", covs.size());
88  return;
89  }
90 
91  target_covs_ = covs;
92 }
93 
94 template <typename PointSource, typename PointTarget>
95 const std::vector<Eigen::Matrix4d>& RegistrationPCL<PointSource, PointTarget>::getSourceCovariances() const {
96  if (source_covs_.empty()) {
97  PCL_WARN("[RegistrationPCL::getSourceCovariances] Covariances are not estimated\n");
98  }
99 
100  return source_covs_;
101 }
102 
103 template <typename PointSource, typename PointTarget>
104 const std::vector<Eigen::Matrix4d>& RegistrationPCL<PointSource, PointTarget>::getTargetCovariances() const {
105  if (target_covs_.empty()) {
106  PCL_WARN("[RegistrationPCL::getTargetCovariances] Covariances are not estimated\n");
107  }
108 
109  return target_covs_;
110 }
111 
112 template <typename PointSource, typename PointTarget>
114  input_.swap(target_);
115  source_tree_.swap(target_tree_);
116  source_covs_.swap(target_covs_);
117  source_voxelmap_.swap(target_voxelmap_);
118 }
119 
120 template <typename PointSource, typename PointTarget>
122  input_.reset();
123  source_tree_.reset();
124  source_covs_.clear();
125  source_voxelmap_.reset();
126 }
127 
128 template <typename PointSource, typename PointTarget>
130  target_.reset();
131  target_tree_.reset();
132  target_covs_.clear();
133  target_voxelmap_.reset();
134 }
135 
136 template <typename PointSource, typename PointTarget>
138  if (n <= 0) {
139  PCL_ERROR("[RegistrationPCL::setNumThreads] Invalid number of threads: %d\n", n);
140  n = 1;
141  }
142 
143  num_threads_ = n;
144 }
145 
146 template <typename PointSource, typename PointTarget>
148  setNumNeighborsForCovariance(k);
149 }
150 
151 template <typename PointSource, typename PointTarget>
153  if (k < 5) {
154  PCL_ERROR("[RegistrationPCL::setNumNeighborsForCovariance] Invalid number of neighbors: %d\n", k);
155  k = 5;
156  }
157  k_correspondences_ = k;
158 }
159 
160 template <typename PointSource, typename PointTarget>
162  if (voxel_resolution_ <= 0) {
163  PCL_ERROR("[RegistrationPCL::setVoxelResolution] Invalid voxel resolution: %f\n", r);
164  r = 1.0;
165  }
166 
167  voxel_resolution_ = r;
168 }
169 
170 template <typename PointSource, typename PointTarget>
172  rotation_epsilon_ = eps;
173 }
174 
175 template <typename PointSource, typename PointTarget>
177  if (type == "GICP") {
178  registration_type_ = type;
179  } else if (type == "VGICP") {
180  registration_type_ = type;
181  } else {
182  PCL_ERROR("[RegistrationPCL::setRegistrationType] Invalid registration type: %s\n", type.c_str());
183  }
184 }
185 
186 template <typename PointSource, typename PointTarget>
188  verbose_ = verbose;
189 }
190 
191 template <typename PointSource, typename PointTarget>
192 const Eigen::Matrix<double, 6, 6>& RegistrationPCL<PointSource, PointTarget>::getFinalHessian() const {
193  return result_.H;
194 }
195 
196 template <typename PointSource, typename PointTarget>
198  return result_;
199 }
200 
201 template <typename PointSource, typename PointTarget>
203  if (output.points.data() == input_->points.data() || output.points.data() == target_->points.data()) {
204  throw std::invalid_argument("FastGICP: destination cloud cannot be identical to source or target");
205  }
206 
207  PointCloudProxy<PointSource> source_proxy(*input_, source_covs_);
208  PointCloudProxy<PointTarget> target_proxy(*target_, target_covs_);
209 
210  if (source_covs_.size() != input_->size()) {
211  estimate_covariances_omp(source_proxy, *source_tree_, k_correspondences_, num_threads_);
212  }
213  if (target_covs_.size() != target_->size()) {
214  estimate_covariances_omp(target_proxy, *target_tree_, k_correspondences_, num_threads_);
215  }
216 
218  registration.criteria.rotation_eps = rotation_epsilon_;
219  registration.criteria.translation_eps = transformation_epsilon_;
220  registration.reduction.num_threads = num_threads_;
221  registration.rejector.max_dist_sq = corr_dist_threshold_ * corr_dist_threshold_;
222  registration.optimizer.verbose = verbose_;
223  registration.optimizer.max_iterations = max_iterations_;
224 
225  if (registration_type_ == "GICP") {
226  result_ = registration.align(target_proxy, source_proxy, *target_tree_, Eigen::Isometry3d(guess.template cast<double>()));
227  } else if (registration_type_ == "VGICP") {
228  if (!target_voxelmap_) {
229  target_voxelmap_ = std::make_shared<GaussianVoxelMap>(voxel_resolution_);
230  target_voxelmap_->insert(target_proxy);
231  }
232  if (!source_voxelmap_) {
233  source_voxelmap_ = std::make_shared<GaussianVoxelMap>(voxel_resolution_);
234  source_voxelmap_->insert(source_proxy);
235  }
236 
237  result_ = registration.align(*target_voxelmap_, source_proxy, *target_voxelmap_, Eigen::Isometry3d(guess.template cast<double>()));
238  } else {
239  PCL_ERROR("[RegistrationPCL::computeTransformation] Invalid registration type: %s\n", registration_type_.c_str());
240  return;
241  }
242 
243  converged_ = result_.converged;
244  final_transformation_ = result_.T_target_source.matrix().template cast<float>();
245  pcl::transformPointCloud(*input_, output, final_transformation_);
246 }
247 
248 } // namespace small_gicp
void setVoxelResolution(double r)
Set the voxel resolution for VGICP.
Definition: pcl_registration_impl.hpp:161
RegistrationPCL()
Definition: pcl_registration_impl.hpp:23
void setVerbosity(bool verbose)
Set the verbosity flag.
Definition: pcl_registration_impl.hpp:187
typename PointCloudSource::ConstPtr PointCloudSourceConstPtr
Definition: pcl_registration.hpp:22
typename pcl::Registration< PointSource, PointTarget, Scalar >::Matrix4 Matrix4
Definition: pcl_registration.hpp:18
const std::vector< Eigen::Matrix4d > & getTargetCovariances() const
Get target point covariances.
Definition: pcl_registration_impl.hpp:104
virtual ~RegistrationPCL()
Definition: pcl_registration_impl.hpp:38
const std::vector< Eigen::Matrix4d > & getSourceCovariances() const
Get source point covariances.
Definition: pcl_registration_impl.hpp:95
void setCorrespondenceRandomness(int k)
Set the number of neighbors for covariance estimation.
Definition: pcl_registration_impl.hpp:147
void setNumThreads(int n)
Set the number of threads to use.
Definition: pcl_registration_impl.hpp:137
void setSourceCovariances(const std::vector< Eigen::Matrix4d > &covs)
Set source point covariances.
Definition: pcl_registration_impl.hpp:65
typename pcl::Registration< PointSource, PointTarget, Scalar >::PointCloudSource PointCloudSource
Definition: pcl_registration.hpp:20
const Eigen::Matrix< double, 6, 6 > & getFinalHessian() const
Get the final Hessian matrix ([rx, ry, rz, tx, ty, tz]).
Definition: pcl_registration_impl.hpp:192
virtual void computeTransformation(PointCloudSource &output, const Matrix4 &guess) override
Definition: pcl_registration_impl.hpp:202
const RegistrationResult & getRegistrationResult() const
Get the detailed registration result.
Definition: pcl_registration_impl.hpp:197
void clearSource()
Clear source point cloud.
Definition: pcl_registration_impl.hpp:121
void clearTarget()
Clear target point cloud.
Definition: pcl_registration_impl.hpp:129
void setTargetCovariances(const std::vector< Eigen::Matrix4d > &covs)
Set target point covariances.
Definition: pcl_registration_impl.hpp:80
typename PointCloudTarget::ConstPtr PointCloudTargetConstPtr
Definition: pcl_registration.hpp:26
void swapSourceAndTarget()
Swap source and target point clouds and their augmented data (KdTrees, covariances,...
Definition: pcl_registration_impl.hpp:113
void setRegistrationType(const std::string &type)
Set registration type ("GICP" or "VGICP").
Definition: pcl_registration_impl.hpp:176
void setRotationEpsilon(double eps)
Set rotation epsilon for convergence check.
Definition: pcl_registration_impl.hpp:171
void setInputSource(const PointCloudSourceConstPtr &cloud) override
Set the input source (aligned) point cloud.
Definition: pcl_registration_impl.hpp:41
void setNumNeighborsForCovariance(int k)
Set the number of neighbors for covariance estimation.
Definition: pcl_registration_impl.hpp:152
void setInputTarget(const PointCloudTargetConstPtr &cloud) override
Set the input target (fixed) point cloud.
Definition: pcl_registration_impl.hpp:53
Definition: flat_container.hpp:12
void estimate_covariances_omp(PointCloud &cloud, int num_neighbors=20, int num_threads=4)
Estimate point covariances with OpenMP.
Definition: normal_estimation_omp.hpp:58
Kd-tree builder with OpenMP.
Definition: kdtree_omp.hpp:16
Proxy class to access PCL point cloud with external covariance matrices.
Definition: pcl_proxy.hpp:12
Registration result.
Definition: registration_result.hpp:11
Point cloud registration.
Definition: registration.hpp:23
RegistrationResult align(const TargetPointCloud &target, const SourcePointCloud &source, const TargetTree &target_tree, const Eigen::Isometry3d &init_T=Eigen::Isometry3d::Identity()) const
Align point clouds.
Definition: registration.hpp:33
TerminationCriteria criteria
Termination criteria.
Definition: registration.hpp:48
CorrespondenceRejector rejector
Correspondence rejector.
Definition: registration.hpp:49
Reduction reduction
Reduction.
Definition: registration.hpp:52
Optimizer optimizer
Optimizer.
Definition: registration.hpp:53
double rotation_eps
Translation tolerance.
Definition: termination_criteria.hpp:20
double translation_eps
Rotation tolerance [rad].
Definition: termination_criteria.hpp:19