Utils.cpp
Go to the documentation of this file.
1 
19 #include <Utils.h>
20 #include <pcl/common/transforms.h>
21 #include <pcl/features/normal_3d.h>
22 #include <pcl/filters/extract_indices.h>
23 
24 const std::string TARGET_CLOUD_TOPIC = "/target/cloud";
25 const std::string SOURCE_CLOUD_TOPIC = "/source/cloud";
26 
27 bool Utils::getNormals(PointCloudRGB::Ptr& cloud, double normal_radius, PointCloudNormal::Ptr& normals)
28 {
29  ROS_INFO("Computing normals with radius: %f", normal_radius);
30  pcl::NormalEstimation<pcl::PointXYZRGB, pcl::Normal> ne;
31  ne.setInputCloud(cloud);
32 
33  pcl::search::KdTree<pcl::PointXYZRGB>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZRGB>());
34  ne.setSearchMethod(tree);
35 
36  PointCloudNormal::Ptr cloud_normals(new PointCloudNormal);
37  ne.setRadiusSearch(normal_radius);
38  ne.compute(*normals);
39 
40  // As we compute normal for each point in cloud, must have same size
41  bool success = normals->points.size() == cloud->points.size() ? true : false;
42 
43  return success;
44 }
45 
46 bool Utils::isValidCloud(PointCloudXYZ::Ptr cloud)
47 {
48  return (cloud->size() > 1);
49 }
50 
51 bool Utils::isValidCloud(PointCloudRGB::Ptr cloud)
52 {
53  return (cloud->size() > 1);
54 }
55 
56 bool Utils::isValidCloud(PointCloudNormal::Ptr normals)
57 {
58  return (normals->size() > 1);
59 }
60 
61 bool Utils::isValidMesh(pcl::PolygonMesh::Ptr mesh)
62 {
63  return ((mesh->cloud.row_step*mesh->cloud.height) != 0);
64 }
65 
66 bool Utils::isValidCloudMsg(const sensor_msgs::PointCloud2& cloud_msg)
67 {
68  return ((cloud_msg.row_step*cloud_msg.height) != 0);
69 }
70 
71 bool Utils::isValidTransform(Eigen::Matrix4f transform)
72 {
73  for (int i=0; i<transform.rows(); i++)
74  {
75  for (int j=0; j<transform.cols(); j++)
76  {
77  if (std::isnan(transform(i,j)))
78  return false;
79  }
80  }
81  return true;
82 }
83 
84 void Utils::colorizeCloud(PointCloudRGB::Ptr cloud_rgb, int R, int G, int B)
85 {
86  for (size_t i = 0; i < cloud_rgb->points.size(); i++)
87  {
88  cloud_rgb->points[i].r = R;
89  cloud_rgb->points[i].g = G;
90  cloud_rgb->points[i].b = B;
91  }
92 }
93 
94 void Utils::cloudToXYZRGB(PointCloudXYZ::Ptr cloud, PointCloudRGB::Ptr cloud_rgb, int R, int G, int B)
95 {
96  pcl::copyPointCloud(*cloud, *cloud_rgb);
97  colorizeCloud(cloud_rgb, R, G, B);
98 }
99 
100 void Utils::cloudToROSMsg(PointCloudRGB::Ptr cloud, sensor_msgs::PointCloud2& cloud_msg, const std::string& frameid)
101 {
102  pcl::toROSMsg(*cloud, cloud_msg);
103  cloud_msg.header.frame_id = frameid;
104  cloud_msg.header.stamp = ros::Time::now();
105 }
106 
107 void Utils::cloudToROSMsg(const pcl::PCLPointCloud2& cloud, sensor_msgs::PointCloud2& cloud_msg, const std::string& frameid)
108 {
109  pcl_conversions::fromPCL(cloud, cloud_msg);
110  cloud_msg.header.frame_id = frameid;
111  cloud_msg.header.stamp = ros::Time::now();
112 }
113 
114 double Utils::computeCloudResolution(PointCloudXYZ::Ptr cloud)
115 {
116  double res = 0.0;
117  int n_points = 0;
118  int nres;
119  std::vector<int> indices(2);
120  std::vector<float> sqr_distances(2);
121  pcl::search::KdTree<pcl::PointXYZ> tree;
122  tree.setInputCloud(cloud);
123 
124  for (std::size_t i = 0; i < cloud->size(); ++i)
125  {
126  if (!std::isfinite((*cloud)[i].x))
127  {
128  continue;
129  }
130  // Considering the second neighbor since the first is the point itself.
131  nres = tree.nearestKSearch(i, 2, indices, sqr_distances);
132  if (nres == 2)
133  {
134  res += sqrt(sqr_distances[1]);
135  ++n_points;
136  }
137  }
138  if (n_points != 0)
139  {
140  res /= n_points;
141  }
142  return res;
143 }
144 
145 double Utils::computeCloudResolution(PointCloudRGB::Ptr cloud)
146 {
147  double res = 0.0;
148  int n_points = 0;
149  int nres;
150  std::vector<int> indices(2);
151  std::vector<float> sqr_distances(2);
152  pcl::search::KdTree<pcl::PointXYZRGB> tree;
153  tree.setInputCloud(cloud);
154 
155  for (std::size_t i = 0; i < cloud->size(); ++i)
156  {
157  if (!std::isfinite((*cloud)[i].x))
158  {
159  continue;
160  }
161  // Considering the second neighbor since the first is the point itself.
162  nres = tree.nearestKSearch(i, 2, indices, sqr_distances);
163  if (nres == 2)
164  {
165  res += sqrt(sqr_distances[1]);
166  ++n_points;
167  }
168  }
169  if (n_points != 0)
170  {
171  res /= n_points;
172  }
173  return res;
174 }
175 
176 void Utils::printTransform(const Eigen::Matrix4f& transform)
177 {
178  Eigen::IOFormat CleanFmt(4, 0, ", ", "\n", "\t\t\t\t[", "]");
179  std::cout << transform.format(CleanFmt) << std::endl;
180 }
181 
182 void Utils::printMatrix(const Eigen::Ref<const Eigen::MatrixXf>& matrix, const int size)
183 {
184  Eigen::IOFormat CleanFmt(size, 0, ", ", "\n", "\t\t\t\t[", "]");
185  std::cout << matrix.format(CleanFmt) << std::endl;
186 }
187 
188 void Utils::onePointCloud(PointCloudRGB::Ptr cloud, int size,
189  PointCloudRGB::Ptr one_point_cloud)
190 {
191  // single point cloud
192  Eigen::Vector4f centroid;
193  pcl::compute3DCentroid(*cloud, centroid);
194  pcl::PointXYZRGB p;
195  p.x = centroid[0];
196  p.y = centroid[1];
197  p.z = centroid[2];
198 
199  for(int i=0; i<size; i++)
200  one_point_cloud->points.push_back(p);
201 }
202 
203 void Utils::translateCloud(PointCloudRGB::Ptr cloud_in, PointCloudRGB::Ptr cloud_out,
204  double x_offset, double y_offset, double z_offset)
205 {
206  pcl::copyPointCloud(*cloud_in, *cloud_out);
207  for (size_t i = 0; i < cloud_out->points.size(); i++)
208  {
209  cloud_out->points[i].x += x_offset;
210  cloud_out->points[i].y += y_offset;
211  cloud_out->points[i].z += z_offset;
212  }
213 }
214 
215 void Utils::rotateCloud(PointCloudRGB::Ptr cloud_in, PointCloudRGB::Ptr cloud_out,
216  double roll, double pitch, double yaw)
217 {
218  Eigen::AngleAxisf rollAngle(roll, Eigen::Vector3f::UnitX());
219  Eigen::AngleAxisf pitchAngle(pitch, Eigen::Vector3f::UnitY());
220  Eigen::AngleAxisf yawAngle(yaw, Eigen::Vector3f::UnitZ());
221 
222  Eigen::Quaternion<float> q = rollAngle * pitchAngle * yawAngle;
223 
224  Eigen::Matrix3f rotation = q.matrix();
225 
226  Eigen::Matrix4f T;
227  T.setIdentity();
228  T.block<3,3>(0,0) = rotation;
229  pcl::transformPointCloud(*cloud_in, *cloud_out, T);
230 
232 }
233 
234 void Utils::getVectorFromNormal(PointCloudNormal::Ptr normal, double idx,
235  Eigen::Vector3f& vector)
236 {
237  double x = normal->points[idx].normal_x;
238  double y = normal->points[idx].normal_y;
239  double z = normal->points[idx].normal_z;
240 
241  vector << x, y, z;
242  vector.normalize();
243 }
244 
245 bool Utils::searchForSameRows(Eigen::MatrixXd source_m, Eigen::MatrixXd target_m,
246  std::vector<int>& source_indx, std::vector<int>& target_indx)
247 {
248  double th = 4e-2;
249  int s_row_size = source_m.row(0).size();
250  int t_row_size = target_m.row(0).size();
251  int size = s_row_size < t_row_size ? s_row_size : t_row_size;
252 
253  int count=0;
254  int s_row, t_row;
255  for(int i=0; i<size && count<2; i++)
256  {
257  s_row = i;
258  t_row = findOnMatrix(source_m.row(s_row), target_m, th);
259  if(t_row != -1)
260  {
261  // if row found in matrix, both rows are coincident
262  source_indx.push_back(s_row);
263  target_indx.push_back(t_row);
264  count++;
265  }
266  }
267 
268  if(count<2) return false;
269 
270  return true;
271 }
272 
273 bool Utils::areSameVectors(const Eigen::VectorXd v1, const Eigen::VectorXd v2, double threshold)
274 {
275  if(v1.size() != v2.size())
276  return false;
277 
278  if (v1.isApprox(v2, threshold))
279  return true;
280 
281  return false;
282 }
283 
284 int Utils::findOnVector(double value, const Eigen::VectorXd v, double threshold)
285 {
286  int index;
287 
288  if (v.size()!=0 && (v.array() - value).abs().minCoeff(&index) <= threshold)
289  return index;
290 
291  return -1;
292 }
293 
294 int Utils::findOnMatrix(const Eigen::VectorXd v, const Eigen::MatrixXd m, double threshold)
295 {
296  int index = -1;
297 
298  for(int i=0; i<v.size() && index==-1; i++)
299  if(areSameVectors(v, m.row(i), threshold)) index = i;
300 
301  return index;
302 }
303 
304 void Utils::extractColFromMatrix(Eigen::MatrixXd& matrix, int col)
305 {
306  int nrows = matrix.rows();
307  int ncols = matrix.cols()-1;
308 
309  if(col < ncols)
310  matrix.block(0,col,nrows,ncols-col) = matrix.rightCols(ncols-col);
311 
312  matrix.conservativeResize(nrows,ncols);
313 }
314 
315 void Utils::extractRowFromMatrix(Eigen::MatrixXd& matrix, int row)
316 {
317  int nrows = matrix.rows()-1;
318  int ncols = matrix.cols();
319 
320  if(row < nrows)
321  matrix.block(row,0,nrows-row,ncols) = matrix.bottomRows(nrows-row);
322 
323  matrix.conservativeResize(nrows,ncols);
324 }
static void printTransform(const Eigen::Matrix4f &transform)
Print on console transform values with matrix format.
Definition: Utils.cpp:176
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
const std::string SOURCE_CLOUD_TOPIC
Definition: Utils.cpp:25
static bool isValidTransform(Eigen::Matrix4f transform)
Check whether transform contains valid data and is not NaN.
Definition: Utils.cpp:71
static void extractColFromMatrix(Eigen::MatrixXd &matrix, int col)
Supress col from matrix.
Definition: Utils.cpp:304
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
static void printMatrix(const Eigen::Ref< const Eigen::MatrixXf > &matrix, const int size)
Print on console matrix values with matrix format.
Definition: Utils.cpp:182
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
const std::string TARGET_CLOUD_TOPIC
Definition: Utils.cpp:24
static void cloudToXYZRGB(PointCloudXYZ::Ptr cloud, PointCloudRGB::Ptr cloud_rgb, int R, int G, int B)
Convert XYZ cloud to XYZRGB cloud with specified RGB values.
Definition: Utils.cpp:94
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
TFSIMD_FORCE_INLINE const tfScalar & y() const
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
static bool areSameVectors(const Eigen::VectorXd v1, const Eigen::VectorXd v2, double threshold)
Check if given vectors are equal with a given tolerance (threshold).
Definition: Utils.cpp:273
pcl::PointCloud< pcl::Normal > PointCloudNormal
Definition: Utils.h:36
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(...)
static int findOnMatrix(const Eigen::VectorXd v, const Eigen::MatrixXd m, double threshold)
Find vector as row on matrix with given threshold. Returns index of matrix row. If not found returns ...
Definition: Utils.cpp:294
TFSIMD_FORCE_INLINE const tfScalar & x() const
static void extractRowFromMatrix(Eigen::MatrixXd &matrix, int row)
Supress row from matrix.
Definition: Utils.cpp:315
TFSIMD_FORCE_INLINE const tfScalar & z() const
static void translateCloud(PointCloudRGB::Ptr cloud_in, PointCloudRGB::Ptr cloud_out, double x_offset=0, double y_offset=0, double z_offset=0)
Apply translation to Cloud. Values given in [m].
Definition: Utils.cpp:203
static double computeCloudResolution(PointCloudXYZ::Ptr cloud)
Obtain the resolution of the cloud.
Definition: Utils.cpp:114
static void rotateCloud(PointCloudRGB::Ptr cloud_in, PointCloudRGB::Ptr cloud_out, double roll, double pitch, double yaw)
Apply rotation to cloud. Values given in [rad].
Definition: Utils.cpp:215
static Time now()
static bool isValidMesh(pcl::PolygonMesh::Ptr mesh)
Check whether mesh contains data and is not empty.
Definition: Utils.cpp:61
static bool isValidCloudMsg(const sensor_msgs::PointCloud2 &cloud_msg)
Check whether PointCloud2 contains data and is not empty.
Definition: Utils.cpp:66


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