point_cloud.h
Go to the documentation of this file.
1 #ifndef pcl_ROS_POINT_CLOUD_H_
2 #define pcl_ROS_POINT_CLOUD_H_
3 
4 #include <ros/ros.h>
5 #include <pcl/point_cloud.h>
6 #include <pcl/pcl_config.h> // for PCL_VERSION_COMPARE
7 #if PCL_VERSION_COMPARE(>=, 1, 11, 0)
8 #include <pcl/type_traits.h>
9 #else
10 #include <pcl/point_traits.h>
11 #endif // PCL_VERSION_COMPARE(>=, 1, 11, 0)
12 #include <pcl/for_each_type.h>
13 #include <pcl/conversions.h>
15 #include <sensor_msgs/PointCloud2.h>
16 #include <boost/foreach.hpp> // for BOOST_FOREACH
17 #include <boost/mpl/size.hpp>
18 #include <boost/ref.hpp>
19 #include <boost/thread/mutex.hpp>
20 
21 namespace pcl
22 {
23  namespace detail
24  {
25  template<typename Stream, typename PointT>
27  {
28  FieldStreamer(Stream& stream) : stream_(stream) {}
29 
30  template<typename U> void operator() ()
31  {
32  const char* name = pcl::traits::name<PointT, U>::value;
33  std::uint32_t name_length = strlen(name);
34  stream_.next(name_length);
35  if (name_length > 0)
36  memcpy(stream_.advance(name_length), name, name_length);
37 
38  std::uint32_t offset = pcl::traits::offset<PointT, U>::value;
39  stream_.next(offset);
40 
41  std::uint8_t datatype = pcl::traits::datatype<PointT, U>::value;
42  stream_.next(datatype);
43 
44  std::uint32_t count = pcl::traits::datatype<PointT, U>::size;
45  stream_.next(count);
46  }
47 
48  Stream& stream_;
49  };
50 
51  template<typename PointT>
52  struct FieldsLength
53  {
54  FieldsLength() : length(0) {}
55 
56  template<typename U> void operator() ()
57  {
58  std::uint32_t name_length = strlen(pcl::traits::name<PointT, U>::value);
59  length += name_length + 13;
60  }
61 
62  std::uint32_t length;
63  };
64  } // namespace pcl::detail
65 } // namespace pcl
66 
67 namespace ros
68 {
69  namespace message_traits
70  {
71  template<typename T> struct MD5Sum<pcl::PointCloud<T> >
72  {
73  static const char* value() { return MD5Sum<sensor_msgs::PointCloud2>::value(); }
74  static const char* value(const pcl::PointCloud<T>&) { return value(); }
75 
76  static const uint64_t static_value1 = MD5Sum<sensor_msgs::PointCloud2>::static_value1;
77  static const uint64_t static_value2 = MD5Sum<sensor_msgs::PointCloud2>::static_value2;
78 
79  // If the definition of sensor_msgs/PointCloud2 changes, we'll get a compile error here.
80  ROS_STATIC_ASSERT(static_value1 == 0x1158d486dd51d683ULL);
81  ROS_STATIC_ASSERT(static_value2 == 0xce2f1be655c3c181ULL);
82  };
83 
84  template<typename T> struct DataType<pcl::PointCloud<T> >
85  {
86  static const char* value() { return DataType<sensor_msgs::PointCloud2>::value(); }
87  static const char* value(const pcl::PointCloud<T>&) { return value(); }
88  };
89 
90  template<typename T> struct Definition<pcl::PointCloud<T> >
91  {
92  static const char* value() { return Definition<sensor_msgs::PointCloud2>::value(); }
93  static const char* value(const pcl::PointCloud<T>&) { return value(); }
94  };
95 
96  // pcl point clouds message don't have a ROS compatible header
97  // the specialized meta functions below (TimeStamp and FrameId)
98  // can be used to get the header data.
99  template<typename T> struct HasHeader<pcl::PointCloud<T> > : FalseType {};
100 
101  template<typename T>
102  struct TimeStamp<pcl::PointCloud<T> >
103  {
104  // This specialization could be dangerous, but it's the best I can do.
105  // If this TimeStamp struct is destroyed before they are done with the
106  // pointer returned by the first functions may go out of scope, but there
107  // isn't a lot I can do about that. This is a good reason to refuse to
108  // returning pointers like this...
109  static ros::Time* pointer(typename pcl::PointCloud<T> &m) {
110  header_.reset(new std_msgs::Header());
111  pcl_conversions::fromPCL(m.header, *(header_));
112  return &(header_->stamp);
113  }
114  static ros::Time const* pointer(const typename pcl::PointCloud<T>& m) {
115  header_const_.reset(new std_msgs::Header());
116  pcl_conversions::fromPCL(m.header, *(header_const_));
117  return &(header_const_->stamp);
118  }
119  static ros::Time value(const typename pcl::PointCloud<T>& m) {
120  return pcl_conversions::fromPCL(m.header).stamp;
121  }
122  private:
125  };
126 
127  template<typename T>
128  struct FrameId<pcl::PointCloud<T> >
129  {
130  static std::string* pointer(pcl::PointCloud<T>& m) { return &m.header.frame_id; }
131  static std::string const* pointer(const pcl::PointCloud<T>& m) { return &m.header.frame_id; }
132  static std::string value(const pcl::PointCloud<T>& m) { return m.header.frame_id; }
133  };
134 
135  } // namespace ros::message_traits
136 
137  namespace serialization
138  {
139  template<typename T>
140  struct Serializer<pcl::PointCloud<T> >
141  {
142  template<typename Stream>
143  inline static void write(Stream& stream, const pcl::PointCloud<T>& m)
144  {
145  stream.next(m.header);
146 
147  // Ease the user's burden on specifying width/height for unorganized datasets
148  uint32_t height = m.height, width = m.width;
149  if (height == 0 && width == 0) {
150  width = m.points.size();
151  height = 1;
152  }
153  stream.next(height);
154  stream.next(width);
155 
156  // Stream out point field metadata
157  typedef typename pcl::traits::fieldList<T>::type FieldList;
158  uint32_t fields_size = boost::mpl::size<FieldList>::value;
159  stream.next(fields_size);
160  pcl::for_each_type<FieldList>(pcl::detail::FieldStreamer<Stream, T>(stream));
161 
162  // Assume little-endian...
163  uint8_t is_bigendian = false;
164  stream.next(is_bigendian);
165 
166  // Write out point data as binary blob
167  uint32_t point_step = sizeof(T);
168  stream.next(point_step);
169  uint32_t row_step = point_step * width;
170  stream.next(row_step);
171  uint32_t data_size = row_step * height;
172  stream.next(data_size);
173  memcpy(stream.advance(data_size), m.points.data(), data_size);
174 
175  uint8_t is_dense = m.is_dense;
176  stream.next(is_dense);
177  }
178 
179  template<typename Stream>
180  inline static void read(Stream& stream, pcl::PointCloud<T>& m)
181  {
182  std_msgs::Header header;
183  stream.next(header);
184  pcl_conversions::toPCL(header, m.header);
185  stream.next(m.height);
186  stream.next(m.width);
187 
189  std::vector<sensor_msgs::PointField> fields;
190  stream.next(fields);
191 
192  // Construct field mapping if deserializing for the first time
193  static pcl::MsgFieldMap mapping;
194  static boost::mutex mutex;
195  if (mapping.empty())
196  {
197  boost::mutex::scoped_lock lock(mutex);
198  pcl::createMapping<T>(fields, mapping);
199  }
200 
201  uint8_t is_bigendian;
202  stream.next(is_bigendian); // ignoring...
203  uint32_t point_step, row_step;
204  stream.next(point_step);
205  stream.next(row_step);
206 
207  // Copy point data
208  uint32_t data_size;
209  stream.next(data_size);
210  assert(data_size == m.height * m.width * point_step);
211  m.points.resize(m.height * m.width);
212  uint8_t* m_data = reinterpret_cast<uint8_t*>(m.points.data());
213  // If the data layouts match, can copy a whole row in one memcpy
214  if (mapping.size() == 1 &&
215  mapping[0].serialized_offset == 0 &&
216  mapping[0].struct_offset == 0 &&
217  point_step == sizeof(T))
218  {
219  uint32_t m_row_step = sizeof(T) * m.width;
220  // And if the row steps match, can copy whole point cloud in one memcpy
221  if (m_row_step == row_step)
222  {
223  memcpy (m_data, stream.advance(data_size), data_size);
224  }
225  else
226  {
227  for (uint32_t i = 0; i < m.height; ++i, m_data += m_row_step)
228  memcpy (m_data, stream.advance(row_step), m_row_step);
229  }
230  }
231  else
232  {
233  // If not, do a lot of memcpys to copy over the fields
234  for (uint32_t row = 0; row < m.height; ++row) {
235  const uint8_t* stream_data = stream.advance(row_step);
236  for (uint32_t col = 0; col < m.width; ++col, stream_data += point_step) {
237  BOOST_FOREACH(const pcl::detail::FieldMapping& fm, mapping) {
238  memcpy(m_data + fm.struct_offset, stream_data + fm.serialized_offset, fm.size);
239  }
240  m_data += sizeof(T);
241  }
242  }
243  }
244 
245  uint8_t is_dense;
246  stream.next(is_dense);
247  m.is_dense = is_dense;
248  }
249 
250  inline static uint32_t serializedLength(const pcl::PointCloud<T>& m)
251  {
252  uint32_t length = 0;
253 
254  length += serializationLength(m.header);
255  length += 8; // height/width
256 
258  typedef typename pcl::traits::fieldList<T>::type FieldList;
259  pcl::for_each_type<FieldList>(boost::ref(fl));
260  length += 4; // size of 'fields'
261  length += fl.length;
262 
263  length += 1; // is_bigendian
264  length += 4; // point_step
265  length += 4; // row_step
266  length += 4; // size of 'data'
267  length += m.points.size() * sizeof(T); // data
268  length += 1; // is_dense
269 
270  return length;
271  }
272  };
273  } // namespace ros::serialization
274 
276 
277 } // namespace ros
278 
279 // test if testing machinery can be implemented
280 #if defined(__cpp_rvalue_references) && defined(__cpp_constexpr)
281 #define ROS_POINTER_COMPATIBILITY_IMPLEMENTED 1
282 #else
283 #define ROS_POINTER_COMPATIBILITY_IMPLEMENTED 0
284 #endif
285 
286 #if ROS_POINTER_COMPATIBILITY_IMPLEMENTED
287 #include <type_traits> // for std::is_same
288 #include <memory> // for std::shared_ptr
289 
290 #if PCL_VERSION_COMPARE(>=, 1, 11, 0)
291 #include <pcl/memory.h>
292 #elif PCL_VERSION_COMPARE(>=, 1, 10, 0)
293 #include <pcl/make_shared.h>
294 #endif
295 #endif
296 
297 namespace pcl
298 {
299  namespace detail
300  {
301 #if ROS_POINTER_COMPATIBILITY_IMPLEMENTED
302 #if PCL_VERSION_COMPARE(>=, 1, 10, 0)
303  template <class T>
304  constexpr static bool pcl_uses_boost = std::is_same<boost::shared_ptr<T>,
305  pcl::shared_ptr<T>>::value;
306 #else
307  template <class T>
308  constexpr static bool pcl_uses_boost = true;
309 #endif
310 
311  template<class SharedPointer> struct Holder
312  {
313  SharedPointer p;
314 
315  Holder(const SharedPointer &p) : p(p) {}
316  Holder(const Holder &other) : p(other.p) {}
317  Holder(Holder &&other) : p(std::move(other.p)) {}
318 
319  void operator () (...) { p.reset(); }
320  };
321 
322  template<class T>
323  inline std::shared_ptr<T> to_std_ptr(const boost::shared_ptr<T> &p)
324  {
325  typedef Holder<std::shared_ptr<T>> H;
326  if(H *h = boost::get_deleter<H>(p))
327  {
328  return h->p;
329  }
330  else
331  {
332  return std::shared_ptr<T>(p.get(), Holder<boost::shared_ptr<T>>(p));
333  }
334  }
335 
336  template<class T>
337  inline boost::shared_ptr<T> to_boost_ptr(const std::shared_ptr<T> &p)
338  {
339  typedef Holder<boost::shared_ptr<T>> H;
340  if(H * h = std::get_deleter<H>(p))
341  {
342  return h->p;
343  }
344  else
345  {
346  return boost::shared_ptr<T>(p.get(), Holder<std::shared_ptr<T>>(p));
347  }
348  }
349 #endif
350  } // namespace pcl::detail
351 
352 // add functions to convert to smart pointer used by ROS
353  template <class T>
355  {
356  return p;
357  }
358 
359 #if ROS_POINTER_COMPATIBILITY_IMPLEMENTED
360  template <class T>
361  inline boost::shared_ptr<T> ros_ptr(const std::shared_ptr<T> &p)
362  {
363  return detail::to_boost_ptr(p);
364  }
365 
366 // add functions to convert to smart pointer used by PCL, based on PCL's own pointer
367  template <class T, class = typename std::enable_if<!detail::pcl_uses_boost<T>>::type>
368  inline std::shared_ptr<T> pcl_ptr(const std::shared_ptr<T> &p)
369  {
370  return p;
371  }
372 
373  template <class T, class = typename std::enable_if<!detail::pcl_uses_boost<T>>::type>
374  inline std::shared_ptr<T> pcl_ptr(const boost::shared_ptr<T> &p)
375  {
376  return detail::to_std_ptr(p);
377  }
378 
379  template <class T, class = typename std::enable_if<detail::pcl_uses_boost<T>>::type>
380  inline boost::shared_ptr<T> pcl_ptr(const std::shared_ptr<T> &p)
381  {
382  return detail::to_boost_ptr(p);
383  }
384 
385  template <class T, class = typename std::enable_if<detail::pcl_uses_boost<T>>::type>
387  {
388  return p;
389  }
390 #else
391  template <class T>
393  {
394  return p;
395  }
396 #endif
397 } // namespace pcl
398 
399 #endif
static ros::Time * pointer(typename pcl::PointCloud< T > &m)
Definition: point_cloud.h:109
static ros::Time value(const typename pcl::PointCloud< T > &m)
Definition: point_cloud.h:119
static void write(Stream &stream, const pcl::PointCloud< T > &m)
Definition: point_cloud.h:143
static boost::shared_ptr< std_msgs::Header > header_const_
Definition: point_cloud.h:124
sensor_msgs::PointCloud2 PointCloud
Definition: bag_to_pcd.cpp:55
ROS_FORCE_INLINE uint8_t * advance(uint32_t len)
static const char * value(const pcl::PointCloud< T > &)
Definition: point_cloud.h:87
static uint32_t serializedLength(const pcl::PointCloud< T > &m)
Definition: point_cloud.h:250
#define ROS_STATIC_ASSERT(cond)
const char * datatype()
static std::string * pointer(pcl::PointCloud< T > &m)
Definition: point_cloud.h:130
FieldStreamer(Stream &stream)
Definition: point_cloud.h:28
static std::string const * pointer(const pcl::PointCloud< T > &m)
Definition: point_cloud.h:131
static boost::shared_ptr< std_msgs::Header > header_
Definition: point_cloud.h:123
void toPCL(const ros::Time &stamp, std::uint64_t &pcl_stamp)
static ros::Time const * pointer(const typename pcl::PointCloud< T > &m)
Definition: point_cloud.h:114
static const char * value(const pcl::PointCloud< T > &)
Definition: point_cloud.h:74
static std::string value(const pcl::PointCloud< T > &m)
Definition: point_cloud.h:132
static void read(Stream &stream, pcl::PointCloud< T > &m)
Definition: point_cloud.h:180
uint32_t serializationLength(const T &t)
static const char * value(const pcl::PointCloud< T > &)
Definition: point_cloud.h:93
TFSIMD_FORCE_INLINE tfScalar length(const Quaternion &q)
const std::string header
void fromPCL(const std::uint64_t &pcl_stamp, ros::Time &stamp)
boost::shared_ptr< T > pcl_ptr(const boost::shared_ptr< T > &p)
Definition: point_cloud.h:392
boost::shared_ptr< T > ros_ptr(const boost::shared_ptr< T > &p)
Definition: point_cloud.h:354


pcl_ros
Author(s): Open Perception, Julius Kammerl , William Woodall
autogenerated on Thu Feb 16 2023 03:08:02