YARP
Yet Another Robot Platform
PointCloud.h
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3  * SPDX-License-Identifier: BSD-3-Clause
4  */
5 
6 #ifndef YARP_SIG_POINTCLOUD_H
7 #define YARP_SIG_POINTCLOUD_H
8 
9 #include <yarp/sig/Vector.h>
13 
14 
15 
16 namespace yarp {
17 namespace sig {
18 
19 template <class T>
23 class PointCloud : public PointCloudBase
24 {
25  static_assert(std::is_same<T, DataXY>::value ||
26  std::is_same<T, DataXYZ>::value ||
27  std::is_same<T, DataNormal>::value ||
28  std::is_same<T, DataXYZRGBA>::value ||
29  std::is_same<T, DataXYZI>::value ||
30  std::is_same<T, DataInterestPointXYZ>::value ||
31  std::is_same<T, DataXYZNormal>::value ||
32  std::is_same<T, DataXYZNormalRGBA>::value, "yarp::sig::PointCloud<T>: T chosen is not supported");
33 public:
34 
39  {
40  m_storage.clear();
41  setPointType();
42  }
43 
49  template <class T1>
51  {
52  setPointType();
53  copy<T1>(alt);
54  }
55 
61  virtual void resize(size_t width, size_t height)
62  {
63  header.width = width;
65  m_storage.resize(width * height);
66  }
67 
75  virtual void resize(size_t width)
76  {
77  header.width = width;
78  header.height = 1;
79  m_storage.resize(width);
80  }
81 
82  const char* getRawData() const override
83  {
84  return m_storage.getMemoryBlock();
85  }
86 
92  size_t wireSizeBytes() const override
93  {
94  return sizeof(header) + dataSizeBytes();
95  }
96 
102  size_t dataSizeBytes() const override
103  {
104  return header.width * header.height * (sizeof(T));
105  }
106 
107  size_t size() const override
108  {
109  return m_storage.size();
110  }
111 
118  inline T& operator()(size_t u, size_t v)
119  {
120  return m_storage[u + v * width()];
121  }
122 
129  inline const T& operator()(size_t u, size_t v) const
130  {
131  return m_storage[u + v * width()];
132  }
133 
138  inline T& operator()(size_t i)
139  {
140  return m_storage[i];
141  }
142 
147  inline const T& operator()(size_t i) const
148  {
149  return m_storage[i];
150  }
151 
152  template <class T1>
159  {
160  copy(alt);
161  return *this;
162  }
163 
164 
170  inline PointCloud<T>&
172  {
173 
174  yAssert(getPointType() == rhs.getPointType());
175 
176  size_t nr_points = m_storage.size();
177  m_storage.resize(nr_points + rhs.size());
178  for (size_t i = nr_points; i < m_storage.size(); ++i) {
179  m_storage[i] = rhs.m_storage[i - nr_points];
180  }
181 
182  header.width = m_storage.size();
183  header.height = 1;
184  if (rhs.isDense() && isDense()) {
185  header.isDense = 1;
186  } else {
187  header.isDense = 0;
188  }
189  return (*this);
190  }
191 
197  inline const PointCloud<T>
199  {
200  return (PointCloud<T>(*this) += rhs);
201  }
202 
208  inline void push_back(const T& pt)
209  {
210  m_storage.push_back(pt);
211  header.width = m_storage.size();
212  header.height = 1;
213  }
214 
218  virtual inline void clear()
219  {
220  m_storage.clear();
221  header.width = 0;
222  header.height = 0;
223  }
224 
233  virtual void fromExternalPC(const char* source, int type, size_t width, size_t height, bool isDense = true)
234  {
235  yAssert(source);
237  resize(width, height);
238  if (this->getPointType() == type) {
239  memcpy(const_cast<char*>(getRawData()), source, dataSizeBytes());
240  } else {
241  std::vector<int> recipe = getComposition(type);
242  copyFromRawData(getRawData(), source, recipe);
243  }
244  }
245 
246 
247  template <class T1>
253  void copy(const PointCloud<T1>& alt)
254  {
255  resize(alt.width(), alt.height());
256  if (std::is_same<T, T1>::value) {
257  yAssert(dataSizeBytes() == alt.dataSizeBytes());
258  memcpy(const_cast<char*>(getRawData()), alt.getRawData(), dataSizeBytes());
259  } else {
260  std::vector<int> recipe = getComposition(alt.getPointType());
261  copyFromRawData(getRawData(), alt.getRawData(), recipe);
262  }
263  }
264 
265  bool read(yarp::os::ConnectionReader& connection) override
266  {
267  connection.convertTextMode();
269  bool ok = connection.expectBlock((char*)&_header, sizeof(_header));
270  if (!ok) {
271  return false;
272  }
273 
274  m_storage.resize(_header.height * _header.width);
275  std::memset((void*)m_storage.data(), 0, m_storage.size() * sizeof(T));
276 
277  header.height = _header.height;
278  header.width = _header.width;
279  header.isDense = _header.isDense;
280 
281  if (header.pointType == _header.pointType) {
282  return m_storage.read(connection);
283  }
284 
285  T* tmp = m_storage.data();
286 
287  yAssert(tmp != nullptr);
288 
289  // Skip the vector header....
290  connection.expectInt32();
291  connection.expectInt32();
292 
293  std::vector<int> recipe = getComposition(_header.pointType);
294 
296  for (size_t i = 0; i < m_storage.size(); i++) {
297  for (size_t j = 0; j < recipe.size(); j++) {
298  size_t sizeToRead = pointType2Size(recipe[j]);
299  if ((header.pointType & recipe[j])) {
300  size_t offset = getOffset(header.pointType, recipe[j]);
301  connection.expectBlock((char*)&tmp[i] + offset, sizeToRead);
302  } else {
303  dummy.allocateOnNeed(sizeToRead, sizeToRead);
304  connection.expectBlock(dummy.bytes().get(), sizeToRead);
305  }
306  }
307  }
308 
309  connection.convertTextMode();
310  return true;
311  }
312 
313  bool write(yarp::os::ConnectionWriter& writer) const override
314  {
315  writer.appendBlock((char*)&header, sizeof(PointCloudNetworkHeader));
316  return m_storage.write(writer);
317  }
318 
319  virtual std::string toString(int precision = -1, int width = -1) const
320  {
321  std::string ret;
322  if (isOrganized()) {
323  for (size_t r = 0; r < this->width(); r++) {
324  for (size_t c = 0; c < this->height(); c++) {
325  ret += (*this)(r, c).toString(precision, width);
326  }
327  if (r < this->width() - 1) // if it is not the last row
328  {
329  ret += "\n";
330  }
331  }
332 
333  } else {
334  for (size_t i = 0; i < this->size(); i++) {
335  ret += (*this)(i).toString(precision, width);
336  }
337  }
338  return ret;
339  }
340 
346  {
348  ret.addInt32(width());
349  ret.addInt32(height());
350  ret.addInt32(getPointType());
351  ret.addInt32(isDense());
352 
353  for (size_t i = 0; i < this->size(); i++) {
354  ret.addList().append((*this)(i).toBottle());
355  }
356  return ret;
357  }
358 
366  bool fromBottle(const yarp::os::Bottle& bt)
367  {
368  if (bt.isNull()) {
369  return false;
370  }
371 
372  if (this->getPointType() != bt.get(2).asInt32()) {
373  return false;
374  }
375 
376  this->resize(bt.get(0).asInt32(), bt.get(1).asInt32());
377  this->header.isDense = bt.get(3).asInt32();
378 
379  if ((size_t)bt.size() != 4 + width() * height()) {
380  return false;
381  }
382 
383  for (size_t i = 0; i < this->size(); i++) {
384  (*this)(i).fromBottle(bt, i + 4);
385  }
386 
387  return true;
388  }
389 
390  int getBottleTag() const override
391  {
392  return BottleTagMap<T>();
393  }
394 
395 private:
396  yarp::sig::VectorOf<T> m_storage;
397 
398  void setPointType()
399  {
400  if (std::is_same<T, DataXY>::value) {
402  return;
403  }
404 
405  if (std::is_same<T, DataXYZ>::value) {
407  return;
408  }
409 
410  if (std::is_same<T, DataNormal>::value) {
412  return;
413  }
414 
415  if (std::is_same<T, DataXYZRGBA>::value) {
417  return;
418  }
419 
420  if (std::is_same<T, DataXYZI>::value) {
422  return;
423  }
424 
425  if (std::is_same<T, DataInterestPointXYZ>::value) {
427  return;
428  }
429 
430  if (std::is_same<T, DataXYZNormal>::value) {
432  return;
433  }
434 
435  if (std::is_same<T, DataXYZNormalRGBA>::value) {
437  return;
438  }
439 
440 // DataRGBA has sense to implement them?
441 // intensity has sense to implement them?
442 // DataViewpoint has sense to implement them?
443 
444  header.pointType = 0;
445  }
446 };
447 
456 
457 } // namespace sig
458 } // namespace yarp
459 
460 template <>
461 inline int BottleTagMap<yarp::sig::DataXY>()
462 {
463  return BOTTLE_TAG_FLOAT64;
464 }
465 
466 template <>
467 inline int BottleTagMap<yarp::sig::DataXYZ>()
468 {
469  return BOTTLE_TAG_FLOAT64;
470 }
471 
472 template <>
473 inline int BottleTagMap<yarp::sig::DataNormal>()
474 {
475  return BOTTLE_TAG_FLOAT64;
476 }
477 
478 template <>
479 inline int BottleTagMap<yarp::sig::DataXYZRGBA>()
480 {
481  return BOTTLE_TAG_FLOAT64;
482 }
483 
484 template <>
485 inline int BottleTagMap<yarp::sig::DataXYZI>()
486 {
487  return BOTTLE_TAG_FLOAT64;
488 }
489 
490 template <>
491 inline int BottleTagMap<yarp::sig::DataInterestPointXYZ>()
492 {
493  return BOTTLE_TAG_FLOAT64;
494 }
495 
496 template <>
497 inline int BottleTagMap<yarp::sig::DataXYZNormal>()
498 {
499  return BOTTLE_TAG_FLOAT64;
500 }
501 
502 template <>
503 inline int BottleTagMap<yarp::sig::DataXYZNormalRGBA>()
504 {
505  return BOTTLE_TAG_FLOAT64;
506 }
507 
508 
509 #endif // YARP_SIG_POINTCLOUD_H
#define BOTTLE_TAG_FLOAT64
Definition: Bottle.h:25
bool ret
#define yAssert(x)
Definition: Log.h:294
contains the definition of a Vector type
A simple collection of objects that can be described and transmitted in a portable way.
Definition: Bottle.h:74
size_type size() const
Gets the number of elements in the bottle.
Definition: Bottle.cpp:251
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Definition: Bottle.cpp:246
bool isNull() const override
Checks if the object is invalid.
Definition: Bottle.cpp:370
const char * get() const
Definition: Bytes.cpp:27
An interface for reading from a network connection.
virtual bool expectBlock(char *data, size_t len)=0
Read a block of data from the network connection.
virtual std::int32_t expectInt32()=0
Read a 32-bit integer from the network connection.
virtual bool convertTextMode()=0
Reads in a standard description in text mode, and converts it to a standard description in binary.
An interface for writing to a network connection.
virtual void appendBlock(const char *data, size_t len)=0
Send a block of data to the network connection.
An abstraction for a block of bytes, with optional responsibility for allocating/destroying that bloc...
Definition: ManagedBytes.h:22
const Bytes & bytes() const
bool allocateOnNeed(size_t neededLen, size_t allocateLen)
virtual std::int32_t asInt32() const
Get 32-bit integer value.
Definition: Value.cpp:204
The PointCloudBase class.
yarp::sig::PointCloudNetworkHeader header
virtual std::vector< int > getComposition(int type_composite) const
virtual size_t width() const
virtual bool isDense() const
virtual void copyFromRawData(const char *dst, const char *source, std::vector< int > &recipe)
virtual bool isOrganized() const
virtual int getPointType() const
virtual size_t height() const
virtual size_t pointType2Size(int type) const
virtual size_t getOffset(int type_composite, int type_basic) const
The yarp::sig::PointCloudNetworkHeader class.
The PointCloud class.
Definition: PointCloud.h:24
T & operator()(size_t u, size_t v)
Obtain the point given by the (column, row) coordinates.
Definition: PointCloud.h:118
virtual void fromExternalPC(const char *source, int type, size_t width, size_t height, bool isDense=true)
Copy the content of an external PointCloud.
Definition: PointCloud.h:233
const PointCloud< T > operator+(const PointCloud< T > &rhs)
Concatenate a point cloud to another cloud.
Definition: PointCloud.h:198
bool fromBottle(const yarp::os::Bottle &bt)
Populate the PointCloud from a yarp::os::Bottle.
Definition: PointCloud.h:366
const T & operator()(size_t u, size_t v) const
Obtain the point given by the (column, row) coordinates (const version).
Definition: PointCloud.h:129
const T & operator()(size_t i) const
Obtain the point given by the index (const version).
Definition: PointCloud.h:147
T & operator()(size_t i)
Obtain the point given by the index.
Definition: PointCloud.h:138
void push_back(const T &pt)
Insert a new point in the cloud, at the end of the container.
Definition: PointCloud.h:208
virtual std::string toString(int precision=-1, int width=-1) const
Definition: PointCloud.h:319
PointCloud< T > & operator+=(const PointCloud< T > &rhs)
Concatenate a point cloud to the current cloud.
Definition: PointCloud.h:171
PointCloud()
PointCloud, default constructor.
Definition: PointCloud.h:38
bool read(yarp::os::ConnectionReader &connection) override
Read this object from a network connection.
Definition: PointCloud.h:265
const PointCloud< T > & operator=(const PointCloud< T1 > &alt)
Assignment operator.
Definition: PointCloud.h:158
PointCloud(const PointCloud< T1 > &alt)
PointCloud, copy constructor.
Definition: PointCloud.h:50
yarp::os::Bottle toBottle() const
Generate a yarp::os::Bottle filled with the PointCloud data.
Definition: PointCloud.h:345
int getBottleTag() const override
Definition: PointCloud.h:390
virtual void resize(size_t width)
Resize the PointCloud.
Definition: PointCloud.h:75
const char * getRawData() const override
Get the pointer to the data.
Definition: PointCloud.h:82
virtual void clear()
Clear the data.
Definition: PointCloud.h:218
bool write(yarp::os::ConnectionWriter &writer) const override
Write this object to a network connection.
Definition: PointCloud.h:313
virtual void resize(size_t width, size_t height)
Resize the PointCloud.
Definition: PointCloud.h:61
size_t dataSizeBytes() const override
Get the size of the data in terms of number of bytes.
Definition: PointCloud.h:102
void copy(const PointCloud< T1 > &alt)
Copy operator.
Definition: PointCloud.h:253
size_t wireSizeBytes() const override
Get the size of the data + the header in terms of number of bytes.
Definition: PointCloud.h:92
size_t size() const override
Definition: PointCloud.h:107
Provides:
Definition: Vector.h:119
@ PCL_INTEREST_POINT_XYZ
@ PCL_POINT_XYZ_NORMAL
@ PCL_POINT_XYZ_NORMAL_RGBA
The main, catch-all namespace for YARP.
Definition: dirs.h:16