YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
PointCloud.cpp
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
7
8#include <algorithm>
9#include <type_traits>
10#include <cmath>
11
12namespace yarp::sig {
13
14template <class T>
15bool PointCloud<T>::compZ(const T& a, const T& b)
16{
17 if constexpr (has_member_z<T>::value)
18 {
19 return (a.z < b.z);
20 }
21 return false;
22}
23
24template <class T>
25void PointCloud<T>::resize(size_t width, size_t height)
26{
27 header.width = width;
28 header.height = height;
29 m_storage.resize(width * height);
30}
31
32template <class T>
33void PointCloud<T>::resize(size_t width)
34{
35 header.width = width;
36 header.height = 1;
37 m_storage.resize(width);
38}
39
40template <class T>
42{
43 m_storage.clear();
44 header.width = 0;
45 header.height = 0;
46}
47
48template <class T>
49void PointCloud<T>::fromExternalPC(const char* source, int type, size_t width, size_t height, bool isDense)
50{
51 yAssert(source);
52 header.isDense = isDense;
53 resize(width, height);
54 if (this->getPointType() == type) {
55 memcpy(const_cast<char*>(getRawData()), source, dataSizeBytes());
56 } else {
57 std::vector<int> recipe = getComposition(type);
58 copyFromRawData(getRawData(), source, recipe);
59 }
60}
61
62template <class T>
64{
65 connection.convertTextMode();
67 bool ok = connection.expectBlock((char*)&_header, sizeof(_header));
68 if (!ok) {
69 return false;
70 }
71
72 m_storage.resize(_header.height * _header.width);
73 std::memset((void*)m_storage.data(), 0, m_storage.size() * sizeof(T));
74
75 header.height = _header.height;
76 header.width = _header.width;
77 header.isDense = _header.isDense;
78
79 if (header.pointType == _header.pointType) {
80 return m_storage.read(connection);
81 }
82
83 T* tmp = m_storage.data();
84
85 yAssert(tmp != nullptr);
86
87 // Skip the vector header....
88 connection.expectInt32();
89 connection.expectInt32();
90
91 std::vector<int> recipe = getComposition(_header.pointType);
92
94 for (size_t i = 0; i < m_storage.size(); i++) {
95 for (size_t j = 0; j < recipe.size(); j++) {
96 size_t sizeToRead = pointType2Size(recipe[j]);
97 if ((header.pointType & recipe[j])) {
98 size_t offset = getOffset(header.pointType, recipe[j]);
99 connection.expectBlock((char*)&tmp[i] + offset, sizeToRead);
100 } else {
101 dummy.allocateOnNeed(sizeToRead, sizeToRead);
102 connection.expectBlock(dummy.bytes().get(), sizeToRead);
103 }
104 }
105 }
106
107 connection.convertTextMode();
108 return true;
109}
110
111template <class T>
113{
114 writer.appendBlock((char*)&header, sizeof(PointCloudNetworkHeader));
115 return m_storage.write(writer);
116}
117
118template <class T>
119std::string PointCloud<T>::toString(int precision, int width) const
120{
121 std::string ret;
122 if (isOrganized()) {
123 for (size_t r = 0; r < this->width(); r++) {
124 for (size_t c = 0; c < this->height(); c++) {
125 ret += (*this)(r, c).toString(precision, width);
126 }
127 if (r < this->width() - 1) // if it is not the last row
128 {
129 ret += "\n";
130 }
131 }
132
133 } else {
134 for (size_t i = 0; i < this->size(); i++) {
135 ret += (*this)(i).toString(precision, width);
136 }
137 }
138 return ret;
139}
140
141template <class T>
143{
145 ret.addInt32(width());
146 ret.addInt32(height());
147 ret.addInt32(getPointType());
148 ret.addInt32(isDense());
149
150 for (size_t i = 0; i < this->size(); i++) {
151 ret.addList().append((*this)(i).toBottle());
152 }
153 return ret;
154}
155
156template <class T>
158{
159 if (bt.isNull()) {
160 return false;
161 }
162
163 if (this->getPointType() != bt.get(2).asInt32()) {
164 return false;
165 }
166
167 this->resize(bt.get(0).asInt32(), bt.get(1).asInt32());
168 this->header.isDense = bt.get(3).asInt32();
169
170 if ((size_t)bt.size() != 4 + width() * height()) {
171 return false;
172 }
173
174 for (size_t i = 0; i < this->size(); i++) {
175 (*this)(i).fromBottle(bt, i + 4);
176 }
177
178 return true;
179}
180
181template <class T>
183{
184 if constexpr (has_member_z<T>::value)
185 {
186 //remove the points whose z value is nan
187 m_storage.erase(std::remove_if(m_storage.begin(), m_storage.end(), [](const T& point)
188 { return std::isnan(point.z); }),
189 m_storage.end());
190 //sort the points
191 std::sort(m_storage.begin(), m_storage.end(), compZ);
192 return true;
193 }
194
195 return false;
196}
197
198template <class T>
199bool PointCloud<T>::filterDataZ(double minZ, double maxZ)
200{
201 if constexpr (has_member_z<T>::value)
202 {
203 m_storage.erase(
204 std::remove_if(m_storage.begin(), m_storage.end(), [minZ, maxZ](const T& data) {
205 return data.z < minZ || data.z > maxZ;
206 }),
207 m_storage.end()
208 );
209 return true;
210 }
211
212 return false;
213}
214
215template <class T>
217{
218 if (std::is_same<T, DataXY>::value) {
219 header.pointType = PCL_POINT2D_XY;
220 return;
221 }
222
223 if (std::is_same<T, DataXYZ>::value) {
224 header.pointType = PCL_POINT_XYZ;
225 return;
226 }
227
228 if (std::is_same<T, DataNormal>::value) {
229 header.pointType = PCL_NORMAL;
230 return;
231 }
232
233 if (std::is_same<T, DataXYZRGBA>::value) {
234 header.pointType = PCL_POINT_XYZ_RGBA;
235 return;
236 }
237
238 if (std::is_same<T, DataXYZI>::value) {
239 header.pointType = PCL_POINT_XYZ_I;
240 return;
241 }
242
243 if (std::is_same<T, DataInterestPointXYZ>::value) {
244 header.pointType = PCL_INTEREST_POINT_XYZ;
245 return;
246 }
247
248 if (std::is_same<T, DataXYZNormal>::value) {
249 header.pointType = PCL_POINT_XYZ_NORMAL;
250 return;
251 }
252
253 if (std::is_same<T, DataXYZNormalRGBA>::value) {
254 header.pointType = PCL_POINT_XYZ_NORMAL_RGBA;
255 return;
256 }
257
258 // DataRGBA has sense to implement them?
259 // intensity has sense to implement them?
260 // DataViewpoint has sense to implement them?
261
262 header.pointType = 0;
263}
264
265template <class T>
267{
268 return BottleTagMap<T>();
269}
270
271template <class T>
273{
274 yAssert(getPointType() == rhs.getPointType());
275
276 size_t nr_points = m_storage.size();
277 m_storage.resize(nr_points + rhs.size());
278 for (size_t i = nr_points; i < m_storage.size(); ++i) {
279 m_storage[i] = rhs.m_storage[i - nr_points];
280 }
281
282 header.width = m_storage.size();
283 header.height = 1;
284 if (rhs.isDense() && isDense()) {
285 header.isDense = 1;
286 } else {
287 header.isDense = 0;
288 }
289 return (*this);
290}
291
292template <class T>
294{
295 return (PointCloud<T>(*this) += rhs);
296}
297
298template <class T>
300{
301 m_storage.push_back(pt);
302 header.width = m_storage.size();
303 header.height = 1;
304}
305
306} //namespace yarp::sig
307
std::string toString(const T &value)
convert an arbitrary type to string.
bool ret
#define yAssert(x)
Definition Log.h:388
A simple collection of objects that can be described and transmitted in a portable way.
Definition Bottle.h:64
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
void addInt32(std::int32_t x)
Places a 32-bit integer in the bottle, at the end of the list.
Definition Bottle.cpp:140
bool isNull() const override
Checks if the object is invalid.
Definition Bottle.cpp:343
void write(bool forceStrict=false)
Write the current object being returned by BufferedPort::prepare.
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...
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
virtual bool isDense() const
virtual int getPointType() const
The yarp::sig::PointCloudNetworkHeader class.
The PointCloud class.
Definition PointCloud.h:21
const PointCloud< T > operator+(const PointCloud< T > &rhs)
Concatenate a point cloud to another cloud.
bool fromBottle(const yarp::os::Bottle &bt)
Populate the PointCloud from a yarp::os::Bottle.
virtual void resize(size_t width, size_t height)
Resize the PointCloud.
void push_back(const T &pt)
Insert a new point in the cloud, at the end of the container.
virtual void fromExternalPC(const char *source, int type, size_t width, size_t height, bool isDense=true)
Copy the content of an external PointCloud.
bool read(yarp::os::ConnectionReader &connection) override
Read this object from a network connection.
yarp::os::Bottle toBottle() const
Generate a yarp::os::Bottle filled with the PointCloud data.
int getBottleTag() const override
PointCloud< T > & operator+=(const PointCloud< T > &rhs)
Concatenate a point cloud to the current cloud.
virtual void clear()
Clear the data.
bool write(yarp::os::ConnectionWriter &writer) const override
Write this object to a network connection.
virtual std::string toString(int precision=-1, int width=-1) const
bool filterDataZ(double minZ=0, double maxZ=std::numeric_limits< double >::infinity())
Filter out points which are not included in the specified range.
size_t size() const override
Definition PointCloud.h:99
bool sortDataZ()
Rearranges the pointcloud data so that the points are ordered from the nearest to the farthest.
@ PCL_POINT_XYZ_NORMAL_RGBA
#define YARP_sig_API
Definition api.h:18