InitialAlignment.cpp
Go to the documentation of this file.
1 
18 #include <InitialAlignment.h>
19 #include <Filter.h>
20 #include <pcl/filters/voxel_grid.h>
21 #include <pcl/keypoints/harris_3d.h>
22 #include <pcl/features/boundary.h>
23 #include <pcl/features/multiscale_feature_persistence.h>
24 #include <pcl/features/fpfh.h>
25 #include <pcl/registration/correspondence_estimation.h>
26 #include <pcl/registration/correspondence_rejection_sample_consensus.h>
27 #include <pcl/registration/correspondence_rejection_one_to_one.h>
28 #include <pcl/registration/transformation_estimation_svd.h>
29 #include <pcl/segmentation/extract_clusters.h>
30 #include <pcl/common/common.h>
31 
32 InitialAlignment::InitialAlignment(PointCloudRGB::Ptr target_cloud, PointCloudRGB::Ptr source_cloud)
33  : aligned_cloud_(new PointCloudRGB),
34  source_normals_(new PointCloudNormal),
35  target_normals_(new PointCloudNormal),
36  source_dominant_normals_(new PointCloudNormal),
37  target_dominant_normals_(new PointCloudNormal),
38  target_keypoints_(new PointCloudRGB),
39  source_keypoints_(new PointCloudRGB),
40  target_features_(new PointCloudFPFH),
41  source_features_(new PointCloudFPFH),
42  correspondences_(new pcl::Correspondences)
43 {
44  target_cloud_ = target_cloud;
45  source_cloud_ = source_cloud;
46 
47  pcl::compute3DCentroid(*source_cloud_, source_centroid_);
48  pcl::compute3DCentroid(*target_cloud_, target_centroid_);
49 
50  ROS_INFO("Source cloud center: (%f, %f, %f)", source_centroid_[0], source_centroid_[1], source_centroid_[2]);
51  ROS_INFO("Target cloud center: (%f, %f, %f)", target_centroid_[0], target_centroid_[1], target_centroid_[2]);
52 
53  double target_res = Utils::computeCloudResolution(target_cloud_);
54  double source_res = Utils::computeCloudResolution(source_cloud_);
55  normal_radius_ = (target_res + source_res) * 10.0; // 10 times higher
56  transform_exists_ = false;
57  rigid_tf_ = Eigen::Matrix4f::Identity();
59  radius_factor_ = 1.4;
60 }
61 
63 {
65  ROS_INFO("Not running initial alignment method");
66 
67  else
68  {
71 
74  else
76  }
77 
79 }
80 
82 {
83  ROS_INFO("Initial alignment method: NORMALS");
84 
85  // filter edges from cloud
86  pcl::IndicesPtr source_non_boundary_indices(new std::vector<int>);
87  pcl::IndicesPtr target_non_boundary_indices(new std::vector<int>);
88  pcl::IndicesPtr keypoints_indices(new std::vector<int>);
89  PointCloudRGB::Ptr keypoints_cloud(new PointCloudRGB);
90  obtainBoundaryKeypoints(source_cloud_, source_normals_, keypoints_cloud, keypoints_indices, source_non_boundary_indices);
91  obtainBoundaryKeypoints(target_cloud_, target_normals_, keypoints_cloud, keypoints_indices, target_non_boundary_indices);
92 
93  PointCloudRGB::Ptr source_cloud_no_boundary(new PointCloudRGB);
94  PointCloudRGB::Ptr target_cloud_no_boundary(new PointCloudRGB);
95  PointCloudNormal::Ptr source_normals_no_boundary(new PointCloudNormal);
96  PointCloudNormal::Ptr target_normals_no_boundary(new PointCloudNormal);
97  Filter::extractIndices(source_cloud_, source_cloud_no_boundary, source_non_boundary_indices);
98  Filter::extractIndices(target_cloud_, target_cloud_no_boundary, target_non_boundary_indices);
99  Filter::extractIndices(source_normals_, source_normals_no_boundary, source_non_boundary_indices);
100  Filter::extractIndices(target_normals_, target_normals_no_boundary, target_non_boundary_indices);
101 
102  // start normal algorithm
103  std::vector<pcl::PointIndices> source_cluster_indices;
104  std::vector<pcl::PointIndices> target_cluster_indices;
105  obtainNormalsCluster(source_cloud_no_boundary, source_normals_no_boundary, source_cluster_indices);
106  obtainNormalsCluster(target_cloud_no_boundary, target_normals_no_boundary, target_cluster_indices);
107 
108  obtainDominantNormals(source_normals_no_boundary, source_cluster_indices, source_dominant_normals_);
109  obtainDominantNormals(target_normals_no_boundary, target_cluster_indices, target_dominant_normals_);
110 
113  else
114  ROS_ERROR("Failed to obtain dominant normals");
115 }
116 
118 {
121 
124  if (correspondences_->size() > (source_cloud_->size()/2))
126 
128 }
129 
130 void InitialAlignment::obtainNormalsCluster(PointCloudRGB::Ptr cloud,
131  PointCloudNormal::Ptr normals,
132  std::vector<pcl::PointIndices>& cluster_indices)
133 {
134  // move all points from cloud to cloud centroid
135  PointCloudRGB::Ptr cloud_one(new PointCloudRGB);
136  Utils::onePointCloud(cloud, cloud->size(), cloud_one);
137 
138  // parameters to cluster normals
139  const float tolerance = 0.05f; // 5cm tolerance
140  const double eps_angle = 20 * (M_PI / 180.0); // 20 degree tolerance
141  const double PERCENTAJE = 0.025;
142  const unsigned int min_cluster_size = (int)normals->size()*PERCENTAJE;
143 
144  pcl::KdTree<pcl::PointXYZRGB>::Ptr tree(new pcl::KdTreeFLANN<pcl::PointXYZRGB>());
145  tree->setInputCloud(cloud);
146  ROS_INFO("Clustering normals with min cluster size: %d...", min_cluster_size);
147 
148  pcl::extractEuclideanClusters(*cloud, *normals, tolerance, tree, cluster_indices, eps_angle, min_cluster_size);
149 
150  ROS_INFO("Clusters found: %zd", cluster_indices.size());
151 
152  if(cluster_indices.size() == 0)
153  {
154  ROS_ERROR("Failed to obtain normals cluster");
155  pcl::PointIndices::Ptr point_indices(new pcl::PointIndices);
156  for(int i=0; i<cloud->size(); i++)
157  point_indices->indices.push_back(i);
158 
159  cluster_indices.push_back(*point_indices);
160  }
161 }
162 
163 void InitialAlignment::obtainDominantNormals(PointCloudNormal::Ptr normals,
164  std::vector<pcl::PointIndices> cluster_indices,
165  PointCloudNormal::Ptr dominant_normals)
166 {
167  for (std::vector<pcl::PointIndices>::const_iterator it=cluster_indices.begin(); it!=cluster_indices.end(); it++)
168  {
169  PointCloudNormal::Ptr normal_cluster(new PointCloudNormal);
170  for (const auto &index : it->indices)
171  normal_cluster->push_back((*normals)[index]);
172 
173  Eigen::Vector4f vector_dominant_normal=normal_cluster->points[0].getNormalVector4fMap();
174  for (const auto &normal : normal_cluster->points)
175  {
176  Eigen::Vector4f vector_normal = normal.getNormalVector4fMap();
177  vector_dominant_normal += vector_normal;
178  }
179  vector_dominant_normal.normalize();
180  pcl::Normal p;
181  p.normal_x = vector_dominant_normal.x();
182  p.normal_y = vector_dominant_normal.y();
183  p.normal_z = vector_dominant_normal.z();
184 
185  dominant_normals->points.push_back(p);
186  }
187 }
188 
189 void InitialAlignment::getTransformationFromNormals(PointCloudNormal::Ptr source_normals,
190  PointCloudNormal::Ptr target_normals)
191 {
192  std::vector<int> s_idx, t_idx;
193  normalsCorrespondences(source_normals, target_normals, s_idx, t_idx);
194 
195  if(s_idx.size() != t_idx.size() || s_idx.size()<2) ROS_ERROR("Index sizes not match");
196  else
197  {
198  ROS_INFO("Found correspondent normals");
199 
200  Eigen::Matrix4f transform;
201  transform.setIdentity();
202  // set rotation
203  Eigen::Matrix3f source_rot = getCoordinateSystem(source_normals, s_idx);
204  Eigen::Matrix3f target_rot = getCoordinateSystem(target_normals, t_idx);
205  transform.block<3,3>(0,0) = target_rot * source_rot.transpose();
206  // set translation
207  Eigen::Vector4f diff_pose = target_centroid_ - source_centroid_;
208  Eigen::Vector4f translation = transform * diff_pose;
209  transform(0,3) = translation[0];
210  transform(1,3) = translation[1];
211  transform(2,3) = translation[2];
212  Utils::printTransform(transform);
213 
214  if(transform != Eigen::Matrix4f::Zero())
215  {
216  transform_exists_ = true;
217  rigid_tf_ = transform;
218  }
219  }
220 }
221 
222 
223 Eigen::VectorXd InitialAlignment::nextVector(Eigen::MatrixXd matrix,
224  int current_col, int current_row)
225 {
226  int ncols = matrix.row(0).size() - (current_col+1);
227  Eigen::MatrixXd v(1, ncols);
228  v = matrix.block(current_row, current_col+1, 1, ncols);
229 
230  return v.row(0);
231 }
232 
233 bool InitialAlignment::findIdx(Eigen::MatrixXd source_m, Eigen::MatrixXd target_m,
234  Eigen::MatrixXi source_idx_m, Eigen::MatrixXi target_idx_m,
235  std::vector<int>& source_indx, std::vector<int>& target_indx)
236 {
237  double th = 4e-2;
238 
239  if(source_m.rows()<2 || target_m.rows()<2)
240  {
241  ROS_WARN("Couldn't start findIdx on matrix of size < 2");
242  source_indx.push_back(0);
243  target_indx.push_back(0);
244  return false;
245  }
246 
247  int count = 0; // count number of coincidences
248  int t_col = -1;
249  for(int s_col=0; s_col<(source_m.cols()-2) && count<2; s_col++)
250  {
251  for (int s_row=0; s_row<source_m.rows(); s_row++)
252  {
253  bool found = false;
254  if (std::find(source_indx.begin(), source_indx.end(), s_row) == source_indx.end())
255  {
256  for (int t_row=0; t_row<target_m.rows() && !found; t_row++)
257  {
258  if (std::find(target_indx.begin(), target_indx.end(), t_row) == target_indx.end())
259  {
260  t_col = Utils::findOnVector(source_m(s_row, s_col), target_m.row(t_row), th);
261  if (t_col != -1)
262  {
263  // if value found, check for next value
264  Eigen::VectorXd v = nextVector(target_m, t_col, t_row);
265  if(Utils::findOnVector(source_m(s_row, s_col+1), v, th) == -1)
266  t_col = -1; // if next value not found, rows are not coincident
267  else
268  {
269  // if next value found, both rows are coincident
270  source_indx.push_back(s_row);
271  target_indx.push_back(t_row);
272  count++;
273  source_indx.push_back(source_idx_m(s_row,s_col));
274  target_indx.push_back(target_idx_m(t_row,t_col));
275  count++;
276  found = true;
277  }
278  }
279  }
280  }
281  }
282  }
283  }
284  if(count<2) return false;
285 
286  return true;
287 }
288 
289 bool InitialAlignment::normalsCorrespondences(PointCloudNormal::Ptr source_dominant_normal,
290  PointCloudNormal::Ptr target_dominant_normal,
291  std::vector<int>& source_idx, std::vector<int>& target_idx)
292 {
293  size_t source_size = source_dominant_normal->size();
294  int source_m_size = (int)source_size - 1 ;
295  size_t target_size = target_dominant_normal->size();
296  int target_m_size = (int)target_size - 1 ;
297 
298  if(source_m_size==1 || target_m_size==1) ROS_WARN("Matrix size=one could case some errors");
299 
300  std::vector<double> source_angle_vector, target_angle_vector;
301  Eigen::MatrixXd source_m(source_m_size, source_m_size);
302  Eigen::MatrixXd target_m(target_m_size, target_m_size);
303  Eigen::MatrixXi source_idx_m(source_m_size, source_m_size);
304  Eigen::MatrixXi target_idx_m(target_m_size, target_m_size);
305 
306  matrixFromAngles(source_dominant_normal, source_m_size, source_m, source_idx_m);
307  matrixFromAngles(target_dominant_normal, target_m_size, target_m, target_idx_m);
308 
309  if(source_m.row(0).size() == target_m.row(0).size())
310  if (Utils::searchForSameRows(source_m, target_m, source_idx, target_idx)) return true;
311 
312  ROS_INFO("No rows coincident. Search for approximations...");
313 
314  if(source_m.rows() < target_m.rows())
315  {
316  if(!findIdx(source_m, target_m, source_idx_m, target_idx_m, source_idx, target_idx))
317  return false;
318  }
319  else
320  {
321  if(!findIdx(target_m, source_m, target_idx_m, source_idx_m, target_idx, source_idx))
322  return false;
323  }
324  return true;
325 }
326 
327 Eigen::Matrix3f InitialAlignment::getCoordinateSystem(PointCloudNormal::Ptr normals,
328  std::vector<int>& index)
329 {
330  Eigen::Vector3f v1, v2;
331 
332  Utils::getVectorFromNormal(normals, index[0], v1);
333  Utils::getVectorFromNormal(normals, index[1], v2);
334 
335  Eigen::Vector3f orto_v = v1.cross(v2);
336  orto_v.normalize();
337 
338  Eigen::Matrix3f coord_sys;
339  coord_sys.col(0) = v1;
340  coord_sys.col(1) = orto_v;
341  coord_sys.col(2) = v1.cross(orto_v).normalized();
342  return coord_sys;
343 }
344 
345 void InitialAlignment::matrixFromAngles(PointCloudNormal::Ptr normal,
346  size_t size,
347  Eigen::MatrixXd& matrix,
348  Eigen::MatrixXi& index_matrix)
349 {
350  for (int row=0; row<size; row++)
351  {
352  pcl::Normal n = normal->points[row];
353  Eigen::Vector4f init_v = n.getNormalVector4fMap();
354 
355  for(int col=0, j=row+1; col<size; col++, j++)
356  {
357  if (j>size) j=0;
358  n = normal->points[j];
359  Eigen::Vector4f v = n.getNormalVector4fMap();
360  matrix(row,col) = pcl::getAngle3D(init_v, v);
361  index_matrix(row,col) = j;
362  }
363  }
364 }
365 
366 int InitialAlignment::obtainKeypointsAndFeatures(PointCloudRGB::Ptr cloud,
367  PointCloudNormal::Ptr normals,
368  PointCloudRGB::Ptr keypoints_cloud,
369  PointCloudFPFH::Ptr features_cloud)
370 {
371  pcl::IndicesPtr keypoints_indices(new std::vector<int>);
372 
374  {
375  ROS_INFO("Initial alignment method: HARRIS");
376  obtainHarrisKeypoints(cloud, normals, keypoints_cloud, keypoints_indices);
377  obtainFeatures(cloud, normals, keypoints_indices, features_cloud);
378  }
379 
381  {
382  ROS_INFO("Initial alignment method: BOUNDARY");
383  pcl::IndicesPtr non_keypoints_indices(new std::vector<int>);
384  if (obtainBoundaryKeypoints(cloud, normals, keypoints_cloud, keypoints_indices, non_keypoints_indices) == -1)
385  ROS_ERROR("obtainBoundaryKeypoints");
386  if (obtainFeatures(cloud, normals, keypoints_indices, features_cloud) == -1)
387  ROS_ERROR("obtainFeatures");
388  }
389 
391  {
392  ROS_INFO("Initial alignment method: MULTISCALE");
393  obtainMultiScaleKeypointsAndFeatures(cloud, normals, keypoints_cloud, keypoints_indices, features_cloud);
394  }
395 
396  Utils::colorizeCloud(keypoints_cloud, 0, 255, 0);
397 }
398 
399 int InitialAlignment::obtainHarrisKeypoints(PointCloudRGB::Ptr cloud,
400  PointCloudNormal::Ptr normals,
401  PointCloudRGB::Ptr keypoints_cloud,
402  pcl::IndicesPtr keypoints_indices)
403 {
404  double cloud_res = Utils::computeCloudResolution(cloud);
405  double keypoint_radius = cloud_res * radius_factor_;
406 
407  pcl::PointCloud<pcl::PointXYZI>::Ptr keypoints(new pcl::PointCloud<pcl::PointXYZI>);
408  pcl::HarrisKeypoint3D<pcl::PointXYZRGB, pcl::PointXYZI> detector;
409  detector.setNonMaxSupression(true);
410  // detector.setRefine(true);
411  detector.setInputCloud(cloud);
412  detector.setNormals(normals);
413  detector.setThreshold(1e-6); // Close to zero value
414  detector.setRadius(keypoint_radius);
415  detector.compute(*keypoints);
416  pcl::PointIndicesConstPtr k_indices = detector.getKeypointsIndices();
417 
418  if (k_indices->indices.empty()) return -1;
419 
420  *keypoints_indices = k_indices->indices;
421  Filter::extractIndices(cloud, keypoints_cloud, keypoints_indices);
422 
423  return 0;
424 }
425 
426 int InitialAlignment::obtainBoundaryKeypoints(PointCloudRGB::Ptr cloud,
427  PointCloudNormal::Ptr normals,
428  PointCloudRGB::Ptr keypoints_cloud,
429  pcl::IndicesPtr keypoints_indices,
430  pcl::IndicesPtr non_keypoints_indices)
431 {
432  pcl::PointCloud<pcl::Boundary> boundaries;
433  pcl::BoundaryEstimation<pcl::PointXYZRGB, pcl::Normal, pcl::Boundary> detector;
434  detector.setInputCloud(cloud);
435  detector.setInputNormals(normals);
436  detector.setKSearch(30);
437  detector.setAngleThreshold(1.047f); // angle close to 1.57rad to detect corners
438  detector.compute(boundaries);
439 
440  if(boundaries.size() != cloud->size()) return -1;
441 
442  for (int i=0; i<cloud->size(); i++)
443  {
444  if (boundaries.points[i].boundary_point == 1)
445  {
446  keypoints_indices->push_back(i);
447  keypoints_cloud->points.push_back(cloud->points[i]);
448  }
449  else
450  non_keypoints_indices->push_back(i);
451  }
452 
453  if(keypoints_indices->size() == 0) return -1;
454 
455  return 0;
456 }
457 
459  PointCloudNormal::Ptr normals,
460  PointCloudRGB::Ptr keypoints_cloud,
461  pcl::IndicesPtr keypoints_indices,
462  PointCloudFPFH::Ptr features)
463 {
464  pcl::FPFHEstimation<pcl::PointXYZRGB, pcl::Normal, pcl::FPFHSignature33>::Ptr fest(
465  new pcl::FPFHEstimation<pcl::PointXYZRGB, pcl::Normal, pcl::FPFHSignature33>);
466  fest->setInputCloud(cloud);
467  fest->setInputNormals(normals);
468  pcl::search::KdTree<pcl::PointXYZRGB>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZRGB>());
469  fest->setSearchMethod(tree);
470 
471  std::vector<float> scale_values{0.5f, 1.0f, 1.5f};
472  pcl::MultiscaleFeaturePersistence<pcl::PointXYZRGB, pcl::FPFHSignature33> fper;
473  fper.setScalesVector(scale_values);
474  fper.setAlpha(0.45f);
475  fper.setFeatureEstimator(fest);
476  fper.setDistanceMetric(pcl::CS);
477  fper.determinePersistentFeatures(*features, keypoints_indices);
478 
479  Filter::extractIndices(cloud, keypoints_cloud, keypoints_indices);
480 
481  if(keypoints_indices->size() == 0) return -1;
482  if(keypoints_indices->size() != features->size()) return -1;
483 
484  return 0;
485 }
486 
487 int InitialAlignment::obtainFeatures(PointCloudRGB::Ptr cloud,
488  PointCloudNormal::Ptr normals,
489  pcl::IndicesPtr keypoints_indices,
490  PointCloudFPFH::Ptr features)
491 {
492  double cloud_res = Utils::computeCloudResolution(cloud);
493  double feature_radius = cloud_res * radius_factor_;
494 
495  pcl::search::KdTree<pcl::PointXYZRGB>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZRGB>());
496  pcl::FPFHEstimation<pcl::PointXYZRGB, pcl::Normal, pcl::FPFHSignature33>::Ptr fest(
497  new pcl::FPFHEstimation<pcl::PointXYZRGB, pcl::Normal, pcl::FPFHSignature33>);
498  fest->setInputCloud(cloud);
499  fest->setInputNormals(normals);
500  fest->setIndices(keypoints_indices);
501  fest->setSearchMethod(tree);
502  fest->setRadiusSearch(feature_radius);
503  fest->compute(*features);
504 
505  if (features->size() == 0) return -1;
506 
507  return 0;
508 }
509 
511 {
512  pcl::registration::CorrespondenceEstimation<pcl::FPFHSignature33, pcl::FPFHSignature33> cest;
513  cest.setInputSource(source_features_);
514  cest.setInputTarget(target_features_);
515  cest.determineCorrespondences(*correspondences_);
516  ROS_INFO("Found %zd correspondences", correspondences_->size());
517 }
518 
520 {
521  pcl::registration::CorrespondenceRejectorSampleConsensus<pcl::PointXYZRGB> rejector;
522  rejector.setInputSource(source_keypoints_);
523  rejector.setInputTarget(target_keypoints_);
524  rejector.setInlierThreshold(1.5);
525  rejector.setRefineModel(true);
526  rejector.setInputCorrespondences(correspondences_);
527  rejector.getCorrespondences(*correspondences_);
528  ROS_INFO("th: %f", rejector.getInlierThreshold());
529  ROS_INFO("Filtered %zd correspondences", correspondences_->size());
530 }
531 
533 {
534  pcl::registration::CorrespondenceRejectorOneToOne rejector;
535  rejector.setInputCorrespondences(correspondences_);
536  rejector.getCorrespondences(*correspondences_);
537  ROS_INFO("Found %zd one to one correspondences:", correspondences_->size());
538 }
539 
541 {
542  pcl::registration::TransformationEstimationSVD<pcl::PointXYZRGB, pcl::PointXYZRGB> trans_est;
543  trans_est.estimateRigidTransformation(*source_keypoints_, *target_keypoints_, *correspondences_, rigid_tf_);
544  if(rigid_tf_ != Eigen::Matrix4f::Zero()) transform_exists_ = true;
545 }
546 
548 {
549  pcl::transformPointCloud(*source_cloud_, *aligned_cloud_, rigid_tf_);
550 }
551 
552 void InitialAlignment::applyTFtoCloud(PointCloudRGB::Ptr cloud)
553 {
554  pcl::transformPointCloud(*cloud, *cloud, rigid_tf_);
555 }
556 
557 void InitialAlignment::applyTFtoCloud(PointCloudRGB::Ptr cloud, Eigen::Matrix4f tf)
558 {
559  pcl::transformPointCloud(*cloud, *cloud, tf);
560 }
561 
562 void InitialAlignment::getAlignedCloud(PointCloudRGB::Ptr aligned_cloud)
563 {
564  pcl::copyPointCloud(*aligned_cloud_, *aligned_cloud);
565 }
566 
567 void InitialAlignment::getAlignedCloudROSMsg(sensor_msgs::PointCloud2& aligned_cloud_msg)
568 {
569  Utils::cloudToROSMsg(aligned_cloud_, aligned_cloud_msg);
570 }
571 
573 {
574  return rigid_tf_;
575 }
576 
578 {
579  method_ = method;
580 }
581 
582 void InitialAlignment::setRadiusFactor(double radius_factor)
583 {
584  radius_factor_ = radius_factor;
585 }
PointCloudNormal::Ptr target_normals_
Target normals.
static void printTransform(const Eigen::Matrix4f &transform)
Print on console transform values with matrix format.
Definition: Utils.cpp:176
Eigen::Vector4f source_centroid_
Source centroid computed.
PointCloudNormal::Ptr target_dominant_normals_
Target dominant normals. Just used int NORMALS method.
PointCloudRGB::Ptr source_keypoints_
Source keypoints.
void applyTFtoCloud()
Once initial alignment is finished, apply rigid transformation to source cloud.
static bool getNormals(PointCloudRGB::Ptr &cloud, double normal_radius, PointCloudNormal::Ptr &normals)
Get the normals for input cloud with specified normal&#39;s radius.
Definition: Utils.cpp:27
pcl::PointCloud< pcl::FPFHSignature33 > PointCloudFPFH
PointCloudFPFH::Ptr source_features_
Source features.
InitialAlignment(PointCloudRGB::Ptr target_cloud, PointCloudRGB::Ptr source_cloud)
Construct a new Initial Alignment object.
void estimateTransform()
Get transform from computed correspondences.
PointCloudRGB::Ptr aligned_cloud_
Source pointcloud aligned with target cloud.
Eigen::VectorXd nextVector(Eigen::MatrixXd matrix, int current_col, int current_row)
Get next matrix vector with extracted current col and row.
static bool searchForSameRows(Eigen::MatrixXd source_m, Eigen::MatrixXd target_m, std::vector< int > &source_indx, std::vector< int > &target_indx)
Check if both matrix have a coinciden row.
Definition: Utils.cpp:245
void obtainNormalsCluster(PointCloudRGB::Ptr cloud, PointCloudNormal::Ptr normals, std::vector< pcl::PointIndices > &cluster_indices)
Cluster clouds normals.
bool transform_exists_
If true, rigid transformation is complete.
f
void runNormalsBasedAlgorithm()
If set method is NORMALS run algorithm. Cluster normals and found correspondences between dominant no...
static int findOnVector(double value, const Eigen::VectorXd v, double threshold)
Find value on vector with given threshold. Returns index vector of value found. If not found returns ...
Definition: Utils.cpp:284
pcl::CorrespondencesPtr correspondences_
Correspondences between source and target.
AlignmentMethod
Define possible Alignment methods.
void getTransformationFromNormals(PointCloudNormal::Ptr source_normals, PointCloudNormal::Ptr target_normals)
Get transformation between cloud based on normals correspondences.
void rejectOneToOneCorrespondences()
Reject computed correspondences.
void getAlignedCloud(PointCloudRGB::Ptr aligned_cloud)
Get the aligned cloud object.
void obtainCorrespondences()
Get correspondences between clouds from computed features.
static void getVectorFromNormal(PointCloudNormal::Ptr normal, double idx, Eigen::Vector3f &vector)
Obtain normal values as a vector.
Definition: Utils.cpp:234
static void colorizeCloud(PointCloudRGB::Ptr cloud_rgb, int R, int G, int B)
Apply RGB values to cloud.
Definition: Utils.cpp:84
static bool isValidCloud(PointCloudXYZ::Ptr cloud)
Check whether cloud contains data and is not empty.
Definition: Utils.cpp:46
Eigen::Vector4f target_centroid_
Target centroid computed.
#define ROS_WARN(...)
static void onePointCloud(PointCloudRGB::Ptr cloud, int size, PointCloudRGB::Ptr one_point_cloud)
Apply extract indices filter to input cloud with given indices.
Definition: Utils.cpp:188
void obtainDominantNormals(PointCloudNormal::Ptr normals, std::vector< pcl::PointIndices > cluster_indices, PointCloudNormal::Ptr dominant_normals)
Obtain dominant normal in given cluster.
int obtainFeatures(PointCloudRGB::Ptr cloud, PointCloudNormal::Ptr normals, pcl::IndicesPtr keypoints_indices, PointCloudFPFH::Ptr features)
Obtain cloud features based on given keypoints.
Eigen::Matrix3f getCoordinateSystem(PointCloudNormal::Ptr normals, std::vector< int > &index)
Create coordinate system from corresponden normals.
void run()
Perform initial alignment.
int obtainBoundaryKeypoints(PointCloudRGB::Ptr cloud, PointCloudNormal::Ptr normals, PointCloudRGB::Ptr keypoints_cloud, pcl::IndicesPtr keypoints_indices, pcl::IndicesPtr non_keypoints_indices)
Obtain cloud keypoints based on boundary method.
Eigen::Matrix4f getRigidTransform()
Get the rigid transform object.
pcl::PointCloud< pcl::PointXYZRGB > PointCloudRGB
static void cloudToROSMsg(PointCloudRGB::Ptr cloud, sensor_msgs::PointCloud2 &cloud_msg, const std::string &frameid="world")
Convert XYZRGB cloud to PointCloud2.
Definition: Utils.cpp:100
#define ROS_INFO(...)
PointCloudRGB::Ptr target_keypoints_
Target keypoints.
AlignmentMethod method_
The alignment method.
PointCloudRGB::Ptr target_cloud_
Target pointcloud.
void matrixFromAngles(PointCloudNormal::Ptr normal, size_t size, Eigen::MatrixXd &matrix, Eigen::MatrixXi &index_matrix)
Construct matrix based on angles between normals.
pcl::PointCloud< pcl::Normal > PointCloudNormal
void getAlignedCloudROSMsg(sensor_msgs::PointCloud2 &aligned_cloud_msg)
Get the aligned cloud msg in PointCloud2 format.
bool normalsCorrespondences(PointCloudNormal::Ptr source_dominant_normal, PointCloudNormal::Ptr target_dominant_normal, std::vector< int > &source_idx, std::vector< int > &target_idx)
Found correspondences between dominant normals.
double normal_radius_
Radius to compute normals.
PointCloudNormal::Ptr source_dominant_normals_
Source dominant normals. Just used int NORMALS method.
static double computeCloudResolution(PointCloudXYZ::Ptr cloud)
Obtain the resolution of the cloud.
Definition: Utils.cpp:114
void rejectCorrespondences()
Reject computed correspondences.
int obtainHarrisKeypoints(PointCloudRGB::Ptr cloud, PointCloudNormal::Ptr normals, PointCloudRGB::Ptr keypoints_cloud, pcl::IndicesPtr keypoints_indices)
Obtain cloud keypoints based on harris method.
bool findIdx(Eigen::MatrixXd source_m, Eigen::MatrixXd target_m, Eigen::MatrixXi source_idx_m, Eigen::MatrixXi target_idx_m, std::vector< int > &source_indx, std::vector< int > &target_indx)
Function to get index for Source matrix value in Target matrix.
Eigen::Matrix4f rigid_tf_
Transformation matrix as result of initial alignment.
void setMethod(AlignmentMethod method)
Set the AlignmentMethod object.
void setRadiusFactor(double align_factor)
Set the Radius Factor object.
PointCloudFPFH::Ptr target_features_
Target features.
int obtainMultiScaleKeypointsAndFeatures(PointCloudRGB::Ptr cloud, PointCloudNormal::Ptr normals, PointCloudRGB::Ptr keypoints_cloud, pcl::IndicesPtr keypoints_indices, PointCloudFPFH::Ptr features)
Obtain cloud keypoints based on multiscale method.
#define ROS_ERROR(...)
PointCloudRGB::Ptr source_cloud_
Source pointcloud.
PointCloudNormal::Ptr source_normals_
Source normals.
int obtainKeypointsAndFeatures(PointCloudRGB::Ptr cloud, PointCloudNormal::Ptr normals, PointCloudRGB::Ptr keypoints_cloud, PointCloudFPFH::Ptr features_cloud)
Obtain keypoints and features based on set method.
void runKeypointsBasedAlgorithm()
Run keypoints based algorithm. Compute keypoints and features, found correspondences and get transfor...
double radius_factor_
Factor to apply to radius for computations.


leica_point_cloud_processing
Author(s): Ines Lara Sicilia
autogenerated on Fri Feb 5 2021 03:20:30