Autoware.Auto
point_cloud_utils.hpp
Go to the documentation of this file.
1 // Copyright 2017-2020 the Autoware Foundation, Arm Limited
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // Co-developed by Tier IV, Inc. and Apex.AI, Inc.
18 
19 #ifndef LIDAR_UTILS__POINT_CLOUD_UTILS_HPP_
20 #define LIDAR_UTILS__POINT_CLOUD_UTILS_HPP_
21 
23 
24 #include <common/types.hpp>
26 #include <geometry_msgs/msg/transform_stamped.hpp>
27 #include <geometry/common_3d.hpp>
28 #include <sensor_msgs/msg/point_cloud2.hpp>
29 #include <sensor_msgs/point_cloud2_iterator.hpp>
30 
31 #include <Eigen/Core>
32 #include <Eigen/Geometry>
33 
34 #include <atomic>
35 #include <limits>
36 #include <memory>
37 #include <string>
38 #include <vector>
39 
40 
41 namespace autoware
42 {
43 namespace common
44 {
45 namespace comp = helper_functions::comparisons;
46 namespace lidar_utils
47 {
48 using sensor_msgs::msg::PointCloud2;
49 
53 
56 static const uint32_t MAX_SCAN_POINTS = 57872U;
57 
61 class LIDAR_UTILS_PUBLIC PointCloudIts
62 {
63 public:
66  PointCloudIts();
67 
71  void reset(sensor_msgs::msg::PointCloud2 & cloud, uint32_t idx = 0);
72 
74  inline sensor_msgs::PointCloud2Iterator<float32_t> & x_it()
75  {
76  return m_its[0];
77  }
78 
80  inline sensor_msgs::PointCloud2Iterator<float32_t> & y_it()
81  {
82  return m_its[1];
83  }
84 
86  inline sensor_msgs::PointCloud2Iterator<float32_t> & z_it()
87  {
88  return m_its[2];
89  }
90 
92  sensor_msgs::PointCloud2Iterator<float32_t> & intensity_it()
93  {
94  return m_its[3];
95  }
96 
97 private:
99  ::std::vector<sensor_msgs::PointCloud2Iterator<float32_t>> m_its;
100 };
101 
105 LIDAR_UTILS_PUBLIC
106 std::size_t index_after_last_safe_byte_index(const sensor_msgs::msg::PointCloud2 & msg) noexcept;
107 
109 {
110  std::size_t point_step;
111  std::size_t data_length;
112 };
113 
118 LIDAR_UTILS_PUBLIC SafeCloudIndices sanitize_point_cloud(const sensor_msgs::msg::PointCloud2 & msg);
119 
124 LIDAR_UTILS_PUBLIC void init_pcl_msg(
125  sensor_msgs::msg::PointCloud2 & msg,
126  const std::string & frame_id,
127  const std::size_t size = static_cast<std::size_t>(MAX_SCAN_POINTS));
128 
139 template<typename ... Fields>
140 LIDAR_UTILS_PUBLIC void init_pcl_msg(
141  sensor_msgs::msg::PointCloud2 & msg,
142  const std::string & frame_id,
143  const std::size_t size,
144  const uint32_t num_fields,
145  Fields const & ... fields
146 )
147 {
148  msg.height = 1U;
149  msg.is_bigendian = false;
150  msg.is_dense = false;
151  msg.header.frame_id = frame_id;
152  // set the fields
153  sensor_msgs::PointCloud2Modifier modifier(msg);
154  modifier.setPointCloud2Fields(num_fields, fields ...);
155  // allocate memory so that iterators can be used
156  modifier.resize(size);
157 }
158 
165 LIDAR_UTILS_PUBLIC bool8_t add_point_to_cloud_raw(
166  sensor_msgs::msg::PointCloud2 & cloud,
168  uint32_t point_cloud_idx);
169 
170 LIDAR_UTILS_PUBLIC bool8_t add_point_to_cloud(
171  PointCloudIts & cloud_its,
173  uint32_t & point_cloud_idx);
174 
175 LIDAR_UTILS_PUBLIC bool8_t add_point_to_cloud(
176  sensor_msgs::msg::PointCloud2 & cloud,
178  uint32_t & point_cloud_idx);
179 
180 LIDAR_UTILS_PUBLIC bool8_t add_point_to_cloud(
181  sensor_msgs::msg::PointCloud2 & cloud,
183  uint32_t & point_cloud_idx);
184 
185 LIDAR_UTILS_PUBLIC void reset_pcl_msg(
186  sensor_msgs::msg::PointCloud2 & msg,
187  const std::size_t size,
188  uint32_t & point_cloud_idx);
189 
190 LIDAR_UTILS_PUBLIC void resize_pcl_msg(
191  sensor_msgs::msg::PointCloud2 & msg,
192  const std::size_t new_size);
193 
197 LIDAR_UTILS_PUBLIC bool8_t
198 has_intensity_and_throw_if_no_xyz(const PointCloud2::SharedPtr & cloud);
199 
203 LIDAR_UTILS_PUBLIC bool8_t
204 has_intensity_and_throw_if_no_xyz(const PointCloud2 & cloud);
205 
206 template<typename T>
208 
209 template<>
211 {
212  static constexpr auto DATATYPE = sensor_msgs::msg::PointField::INT8;
213 };
214 
215 template<>
217 {
218  static constexpr auto DATATYPE = sensor_msgs::msg::PointField::UINT8;
219 };
220 
221 template<>
223 {
224  static constexpr auto DATATYPE = sensor_msgs::msg::PointField::INT16;
225 };
226 
227 template<>
229 {
230  static constexpr auto DATATYPE = sensor_msgs::msg::PointField::UINT16;
231 };
232 
233 template<>
235 {
236  static constexpr auto DATATYPE = sensor_msgs::msg::PointField::INT32;
237 };
238 
239 template<>
241 {
242  static constexpr auto DATATYPE = sensor_msgs::msg::PointField::UINT32;
243 };
244 
245 template<>
247 {
248  static constexpr auto DATATYPE = sensor_msgs::msg::PointField::FLOAT32;
249 };
250 
251 template<>
253 {
254  static constexpr auto DATATYPE = sensor_msgs::msg::PointField::FLOAT64;
255 };
256 
257 template<typename T>
258 LIDAR_UTILS_PUBLIC
259 sensor_msgs::msg::PointCloud2::SharedPtr create_custom_pcl(
260  const std::vector<std::string> & field_names,
261  const uint32_t cloud_size)
262 {
263  using sensor_msgs::msg::PointCloud2;
264  PointCloud2::SharedPtr msg = std::make_shared<PointCloud2>();
265  const auto field_size = field_names.size();
266  msg->height = 1U;
267  msg->width = cloud_size;
268  msg->fields.resize(field_size);
269  for (uint32_t i = 0U; i < field_size; i++) {
270  msg->fields[i].name = field_names[i];
271  }
272  msg->point_step = 0U;
273  for (uint32_t idx = 0U; idx < field_size; ++idx) {
274  msg->fields[idx].offset = static_cast<uint32_t>(idx * sizeof(T));
275  msg->fields[idx].datatype = _create_custom_pcl_datatype<T>::DATATYPE;
276  msg->fields[idx].count = 1U;
277  msg->point_step += static_cast<uint32_t>(sizeof(T));
278  }
279  const std::size_t capacity = msg->point_step * cloud_size;
280  msg->data.clear();
281  msg->data.reserve(capacity);
282  for (std::size_t i = 0; i < capacity; ++i) {
283  msg->data.emplace_back(0U); // initialize all values equal to 0
284  }
285  msg->row_step = msg->point_step * msg->width;
286  msg->is_bigendian = false;
287  msg->is_dense = false;
288  msg->header.frame_id = "base_link";
289  return msg;
290 }
291 
293 class LIDAR_UTILS_PUBLIC DistanceFilter
294 {
295 public:
299  DistanceFilter(float32_t min_radius, float32_t max_radius);
300  static constexpr auto FEPS = std::numeric_limits<float32_t>::epsilon();
301 
307  template<typename T>
308  bool8_t operator()(const T & pt) const
309  {
311  auto pt_radius = dot_3d(pt, pt);
312  return comp::abs_gte(pt_radius, m_min_r2, FEPS) &&
313  comp::abs_lte(pt_radius, m_max_r2, FEPS);
314  }
315 
316 private:
317  float32_t m_min_r2;
318  float32_t m_max_r2;
319 };
320 
322 class LIDAR_UTILS_PUBLIC StaticTransformer
323 {
324 public:
329 
334  template<typename T>
335  void transform(const T & ref, T & out) const //NOLINT (false positive: this is not std::transform)
336  {
343  Eigen::Matrix<float32_t, 3U, 1U> ref_mat({x_(ref), y_(ref), z_(ref)});
344  Eigen::Vector3f out_mat = m_tf * ref_mat;
345  xr_(out) = out_mat(0U, 0U);
346  yr_(out) = out_mat(1U, 0U);
347  zr_(out) = out_mat(2U, 0U);
348  }
349 
350 private:
351  Eigen::Transform<float32_t, 3U, Eigen::Affine, Eigen::ColMajor> m_tf;
352 };
353 
356 class LIDAR_UTILS_PUBLIC AngleFilter
357 {
358 public:
362  AngleFilter(float32_t start_angle, float32_t end_angle);
363 
365  static constexpr float32_t PI = 3.14159265359F;
366  static constexpr auto FEPS = std::numeric_limits<float32_t>::epsilon() * 1e2F;
367 
374  template<typename T>
375  bool8_t operator()(const T & pt) const
376  {
378  bool8_t ret = false;
379 
380  // Squared magnitude of the vector
381  const auto pt_len2 = dot_2d(pt, pt);
382  const auto proj_on_normal = dot_2d(pt, m_range_normal);
383  const auto proj_on_normal2 = proj_on_normal * proj_on_normal;
384  const auto is_proj_negative = (proj_on_normal + FEPS) < 0.0F;
385 
386  // Since the input vector's projection is scaled by the length of itself, the
387  // threshold is also scaled by the length of the input vector to make the comparison possible.
388 
389  // To avoid computing the length using sqrt, the expressions are kept in square form, hence
390  // the following sign checks are made to ensure the correctness of the comparisons in
391  // squared form.
392  if ((!m_threshold_negative) && (!is_proj_negative)) {
393  ret = (proj_on_normal2) >= (pt_len2 * (m_threshold2 - FEPS));
394  } else if (m_threshold_negative && (!is_proj_negative)) {
395  ret = true;
396  } else if ((!m_threshold_negative) && is_proj_negative) {
397  ret = false;
398  } else {
399  ret = (proj_on_normal2) <= (pt_len2 * (m_threshold2 + FEPS));
400  }
401  return ret;
402  }
403 
404 private:
405  VectorT m_range_normal;
406  bool8_t m_threshold_negative;
407  float32_t m_threshold2;
408 };
409 
410 class LIDAR_UTILS_PUBLIC IntensityIteratorWrapper
411 {
412 private:
413  sensor_msgs::PointCloud2ConstIterator<uint8_t> m_intensity_it_uint8;
414  sensor_msgs::PointCloud2ConstIterator<float32_t> m_intensity_it_float32;
415  decltype(sensor_msgs::msg::PointField::datatype) m_intensity_datatype;
416 
417 public:
418  explicit IntensityIteratorWrapper(const PointCloud2 & msg);
419 
420  void next();
421 
422  bool8_t eof();
423 
424  template<typename PointFieldValueT>
425  void get_current_value(PointFieldValueT & point_field_value)
426  {
427  switch (m_intensity_datatype) {
428  case sensor_msgs::msg::PointField::UINT8:
429  point_field_value = *m_intensity_it_uint8;
430  break;
431  case sensor_msgs::msg::PointField::FLOAT32:
432  point_field_value = *m_intensity_it_float32;
433  break;
434  default:
435  throw std::runtime_error("Intensity type not supported: " + m_intensity_datatype);
436  }
437  }
438 };
439 
440 } // namespace lidar_utils
441 } // namespace common
442 } // namespace autoware
443 
444 #endif // LIDAR_UTILS__POINT_CLOUD_UTILS_HPP_
autoware::common::lidar_utils::IntensityIteratorWrapper
Definition: point_cloud_utils.hpp:410
autoware::common::lidar_utils::DistanceFilter::operator()
bool8_t operator()(const T &pt) const
Check if the point is within the allowed range of the filter. Check is done in square form to avoid s...
Definition: point_cloud_utils.hpp:308
catr_diff.T
T
Definition: catr_diff.py:22
autoware::common::geometry::point_adapter::x_
auto x_(const PointT &pt)
Gets the x value for a point.
Definition: common_2d.hpp:47
autoware::common::lidar_utils::MAX_SCAN_POINTS
static const uint32_t MAX_SCAN_POINTS
Definition: point_cloud_utils.hpp:56
autoware::common::lidar_utils::SafeCloudIndices
Definition: point_cloud_utils.hpp:108
types.hpp
This file includes common type definition.
autoware::common::helper_functions::comparisons::abs_lte
bool abs_lte(const T &a, const T &b, const T &eps)
Check for approximate less than or equal in absolute terms.
Definition: float_comparisons.hpp:69
autoware::common::lidar_utils::PointCloudIts::x_it
sensor_msgs::PointCloud2Iterator< float32_t > & x_it()
Returns iterator for the "x" field.
Definition: point_cloud_utils.hpp:74
autoware::common::types::PointXYZF
Definition: types.hpp:66
autoware::common::lidar_utils::StaticTransformer
Transform to apply a constant transform to given points.
Definition: point_cloud_utils.hpp:322
autoware::common::lidar_utils::PointCloudIts::y_it
sensor_msgs::PointCloud2Iterator< float32_t > & y_it()
Returns iterator for the "y" field.
Definition: point_cloud_utils.hpp:80
autoware::common::lidar_utils::PointCloudIts
Definition: point_cloud_utils.hpp:61
autoware::common::lidar_utils::IntensityIteratorWrapper::get_current_value
void get_current_value(PointFieldValueT &point_field_value)
Definition: point_cloud_utils.hpp:425
autoware::common::geometry::dot_2d
auto dot_2d(const T1 &pt, const T2 &q)
compute p * q = p1 * q1 + p2 * q2
Definition: common_2d.hpp:147
autoware::common::types::PointXYZIF
Definition: types.hpp:56
autoware::common::lidar_utils::AngleFilter
Filter class to check if a point's azimuth lies within a range defined by a start and end angles....
Definition: point_cloud_utils.hpp:356
autoware::common::lidar_utils::AngleFilter::operator()
bool8_t operator()(const T &pt) const
Check if a point's azimuth lies in the range [start, end] in counter-clock-wise-direction....
Definition: point_cloud_utils.hpp:375
autoware::common::lidar_utils::DistanceFilter
Filter class to check if a point lies within a range defined by a min and max radius.
Definition: point_cloud_utils.hpp:293
autoware::common::types::bool8_t
bool bool8_t
Definition: types.hpp:39
autoware::common::geometry::dot_3d
auto dot_3d(const T1 &pt, const T2 &q)
compute p * q = p1 * q1 + p2 * q2 + p3 * 13
Definition: common_3d.hpp:37
autoware
This file defines the lanelet2_map_provider_node class.
Definition: quick_sort.hpp:24
common_3d.hpp
This file includes common functionality for 3D geometry, such as dot products.
autoware::localization::ndt::next
SerializedNDTMapPoint next(std::array< T, 9U > &pc_its)
Get the next voxel representation from the iterators of a serialized ndt map.
Definition: ndt_map.hpp:263
autoware::common::lidar_utils::_create_custom_pcl_datatype
Definition: point_cloud_utils.hpp:207
autoware::common::lidar_utils::has_intensity_and_throw_if_no_xyz
LIDAR_UTILS_PUBLIC bool8_t has_intensity_and_throw_if_no_xyz(const PointCloud2::SharedPtr &cloud)
Definition: point_cloud_utils.cpp:44
float_comparisons.hpp
autoware::common::lidar_utils::reset_pcl_msg
LIDAR_UTILS_PUBLIC void reset_pcl_msg(sensor_msgs::msg::PointCloud2 &msg, const std::size_t size, uint32_t &point_cloud_idx)
Definition: point_cloud_utils.cpp:308
autoware::common::geometry::point_adapter::yr_
auto & yr_(PointT &pt)
Gets a reference to the y value for a point.
Definition: common_2d.hpp:83
autoware::common::lidar_utils::init_pcl_msg
LIDAR_UTILS_PUBLIC void init_pcl_msg(sensor_msgs::msg::PointCloud2 &msg, const std::string &frame_id, const std::size_t size=static_cast< std::size_t >(MAX_SCAN_POINTS))
initializes header information for point cloud for x, y, z and intensity
Definition: point_cloud_utils.cpp:141
autoware::common::lidar_utils::PointCloudIts::z_it
sensor_msgs::PointCloud2Iterator< float32_t > & z_it()
Returns iterator for the "z" field.
Definition: point_cloud_utils.hpp:86
autoware::common::lidar_utils::index_after_last_safe_byte_index
LIDAR_UTILS_PUBLIC std::size_t index_after_last_safe_byte_index(const sensor_msgs::msg::PointCloud2 &msg) noexcept
Compute minimum safe length of point cloud access.
Definition: point_cloud_utils.cpp:114
motion::planning::recordreplay_planner_nodes::Transform
geometry_msgs::msg::TransformStamped Transform
Definition: recordreplay_planner_node.hpp:56
visibility_control.hpp
autoware::common::lidar_utils::add_point_to_cloud
LIDAR_UTILS_PUBLIC bool8_t add_point_to_cloud(PointCloudIts &cloud_its, const autoware::common::types::PointXYZIF &pt, uint32_t &point_cloud_idx)
Definition: point_cloud_utils.cpp:187
autoware::common::helper_functions::comparisons
Definition: bool_comparisons.hpp:32
autoware::common::lidar_utils::resize_pcl_msg
LIDAR_UTILS_PUBLIC void resize_pcl_msg(sensor_msgs::msg::PointCloud2 &msg, const std::size_t new_size)
Definition: point_cloud_utils.cpp:321
autoware::common::types::float32_t
float float32_t
Definition: types.hpp:45
autoware::common::lidar_utils::create_custom_pcl
LIDAR_UTILS_PUBLIC sensor_msgs::msg::PointCloud2::SharedPtr create_custom_pcl(const std::vector< std::string > &field_names, const uint32_t cloud_size)
Definition: point_cloud_utils.hpp:259
autoware::common::geometry::point_adapter::xr_
auto & xr_(PointT &pt)
Gets a reference to the x value for a point.
Definition: common_2d.hpp:74
autoware::common::lidar_utils::sanitize_point_cloud
LIDAR_UTILS_PUBLIC SafeCloudIndices sanitize_point_cloud(const sensor_msgs::msg::PointCloud2 &msg)
Definition: point_cloud_utils.cpp:131
autoware::common::lidar_utils::PointCloudIts::intensity_it
sensor_msgs::PointCloud2Iterator< float32_t > & intensity_it()
Returns iterator for the "intensity" field.
Definition: point_cloud_utils.hpp:92
autoware::common::helper_functions::comparisons::abs_gte
bool abs_gte(const T &a, const T &b, const T &eps)
Check for approximate greater than or equal in absolute terms.
Definition: float_comparisons.hpp:80
autoware::common::lidar_utils::SafeCloudIndices::point_step
std::size_t point_step
Definition: point_cloud_utils.hpp:110
autoware::common::lidar_utils::StaticTransformer::transform
void transform(const T &ref, T &out) const
Apply the transform to a point that has the proper point adapters defined.
Definition: point_cloud_utils.hpp:335
autoware::common::geometry::point_adapter::y_
auto y_(const PointT &pt)
Gets the y value for a point.
Definition: common_2d.hpp:56
autoware::common::lidar_utils::SafeCloudIndices::data_length
std::size_t data_length
Definition: point_cloud_utils.hpp:111
autoware::common::types::float64_t
double float64_t
Definition: types.hpp:47
autoware::common::geometry::point_adapter::z_
auto z_(const PointT &pt)
Gets the z value for a point.
Definition: common_2d.hpp:65
autoware::common::geometry::point_adapter::zr_
auto & zr_(PointT &pt)
Gets a reference to the z value for a point.
Definition: common_2d.hpp:92
autoware::common::lidar_utils::add_point_to_cloud_raw
LIDAR_UTILS_PUBLIC bool8_t add_point_to_cloud_raw(sensor_msgs::msg::PointCloud2 &cloud, const autoware::common::types::PointXYZIF &pt, uint32_t point_cloud_idx)
add a point in the cloud by memcpy instead of using iterators This version prioritize speed and ease ...
Definition: point_cloud_utils.cpp:154
autoware::common::types::PI
constexpr float32_t PI
pi = tau / 2
Definition: types.hpp:50