43 #pragma GCC system_header
46 #include <pcl/PCLPointField.h>
47 #include <pcl/PCLPointCloud2.h>
48 #include <pcl/PCLImage.h>
49 #include <pcl/point_cloud.h>
50 #include <pcl/type_traits.h>
51 #include <pcl/for_each_type.h>
52 #include <pcl/console/print.h>
63 template<
typename Po
intT>
71 f.
name = pcl::traits::name<PointT, U>::value;
72 f.
offset = pcl::traits::offset<PointT, U>::value;
73 f.
datatype = pcl::traits::datatype<PointT, U>::value;
74 f.
count = pcl::traits::datatype<PointT, U>::size;
82 template<
typename Po
intT>
86 std::vector<FieldMapping>& map)
91 template<
typename Tag>
void
94 for (
const auto& field :
fields_)
100 mapping.
struct_offset = pcl::traits::offset<PointT, Tag>::value;
101 mapping.
size =
sizeof (
typename pcl::traits::datatype<PointT, Tag>::type);
102 map_.push_back (mapping);
107 PCL_WARN (
"Failed to find exact match for field '%s'.\n", pcl::traits::name<PointT, Tag>::value);
111 const std::vector<pcl::PCLPointField>&
fields_;
112 std::vector<FieldMapping>&
map_;
122 template<
typename Po
intT>
129 template<
typename Tag>
void
133 for (
const auto& field :
fields_) {
138 for (
const auto& field :
fields_)
141 if ((field.name == pcl::traits::name<PointT, Tag>::value) &&
142 (field.datatype != pcl::traits::datatype<PointT, Tag>::value) &&
143 ((field.count == pcl::traits::datatype<PointT, Tag>::size) ||
144 (field.count == 0 && pcl::traits::datatype<PointT, Tag>::size == 1))) {
145 #define PCL_CAST_POINT_FIELD(TYPE) case ::pcl::traits::asEnum_v<TYPE>: \
146 PCL_WARN("Will try to cast field '%s' (original type is " #TYPE "). You may loose precision during casting. Make sure that this is acceptable or choose a different point type.\n", pcl::traits::name<PointT, Tag>::value); \
147 for (std::size_t row = 0; row < msg_.height; ++row) { \
148 const std::uint8_t* row_data = msg_data_ + row * msg_.row_step; \
149 for (std::size_t col = 0; col < msg_.width; ++col) { \
150 const std::uint8_t* msg_data = row_data + col * msg_.point_step; \
151 for(std::uint32_t i=0; i<pcl::traits::datatype<PointT, Tag>::size; ++i) { \
152 *(reinterpret_cast<typename pcl::traits::datatype<PointT, Tag>::decomposed::type*>(cloud_data + pcl::traits::offset<PointT, Tag>::value) + i) = *(reinterpret_cast<const TYPE*>(msg_data + field.offset) + i); \
154 cloud_data += sizeof (PointT); \
161 switch(field.datatype) {
162 PCL_CAST_POINT_FIELD(
bool)
163 PCL_CAST_POINT_FIELD(std::int8_t)
164 PCL_CAST_POINT_FIELD(std::uint8_t)
165 PCL_CAST_POINT_FIELD(std::int16_t)
166 PCL_CAST_POINT_FIELD(std::uint16_t)
167 PCL_CAST_POINT_FIELD(std::int32_t)
168 PCL_CAST_POINT_FIELD(std::uint32_t)
169 PCL_CAST_POINT_FIELD(std::int64_t)
170 PCL_CAST_POINT_FIELD(std::uint64_t)
171 PCL_CAST_POINT_FIELD(
float)
172 PCL_CAST_POINT_FIELD(
double)
173 default: std::cout <<
"Unknown datatype: " << field.datatype << std::endl;
177 #undef PCL_CAST_POINT_FIELD
181 const std::vector<pcl::PCLPointField>&
fields_;
188 template<
typename Po
intT>
void
193 for_each_type< typename traits::fieldList<PointT>::type > (mapper);
196 if (field_map.size() > 1)
199 MsgFieldMap::iterator i = field_map.begin(), j = i + 1;
200 while (j != field_map.end())
205 if (j->serialized_offset - i->serialized_offset == j->struct_offset - i->struct_offset)
207 i->size += (j->struct_offset + j->size) - (i->struct_offset + i->size);
208 j = field_map.erase(j);
228 template <
typename Po
intT>
void
230 const MsgFieldMap& field_map,
const std::uint8_t* msg_data)
248 std::uint8_t* cloud_data =
reinterpret_cast<std::uint8_t*
>(cloud.
data());
253 if (field_map.size() == 1 &&
254 field_map[0].serialized_offset == 0 &&
255 field_map[0].struct_offset == 0 &&
257 field_map[0].size ==
sizeof(
PointT))
259 const auto cloud_row_step = (
sizeof (
PointT) * cloud.
width);
268 memcpy (cloud_data, msg_data, cloud_row_step);
275 for (std::size_t row = 0; row < msg.
height; ++row)
277 const std::uint8_t* row_data = msg_data + row * msg.
row_step;
278 for (std::size_t col = 0; col < msg.
width; ++col)
280 const std::uint8_t* msg_data = row_data + col * msg.
point_step;
283 std::copy(msg_data + mapping.serialized_offset, msg_data + mapping.serialized_offset + mapping.size,
284 cloud_data + mapping.struct_offset);
286 cloud_data +=
sizeof (
PointT);
292 for_each_type< typename traits::fieldList<PointT>::type > (caster);
308 template <
typename Po
intT>
void
319 template<
typename Po
intT>
void
323 createMapping<PointT> (msg.
fields, field_map);
330 template<
typename Po
intT>
335 memcpy(
msg_data_,
cloud_data_ + pcl::traits::offset<PointT, U>::value,
sizeof(
typename pcl::traits::datatype<PointT, U>::type));
336 msg_data_ +=
sizeof(
typename pcl::traits::datatype<PointT, U>::type);
345 template<
typename Po
intT>
353 f.
name = pcl::traits::name<PointT, U>::value;
354 f.
offset = pcl::traits::offset<PointT, U>::value;
355 f.
datatype = pcl::traits::datatype<PointT, U>::value;
356 f.
count = pcl::traits::datatype<PointT, U>::size;
358 field_sizes_.push_back (
sizeof(
typename pcl::traits::datatype<PointT, U>::type));
371 template<
typename Po
intT>
void
388 std::vector<std::size_t> field_sizes;
391 if (padding || std::accumulate(field_sizes.begin(), field_sizes.end(),
static_cast<std::size_t
>(0)) ==
sizeof (
PointT)) {
393 std::size_t data_size =
sizeof (
PointT) * cloud.
size ();
394 msg.
data.resize (data_size);
397 memcpy(msg.
data.data(), cloud.
data(), data_size);
403 std::size_t point_size = 0;
404 for(std::size_t i=0; i<msg.
fields.size(); ++i) {
405 msg.
fields[i].offset = point_size;
406 point_size += field_sizes[i];
408 msg.
data.resize (point_size * cloud.
size());
409 std::uint8_t* msg_data = &msg.
data[0];
410 const std::uint8_t* cloud_data=
reinterpret_cast<const std::uint8_t*
>(&cloud[0]);
411 const std::uint8_t* end = cloud_data +
sizeof (
PointT) * cloud.
size ();
413 for (; cloud_data<end; cloud_data+=
sizeof(
PointT)) {
414 for_each_type< typename traits::fieldList<PointT>::type > (copier);
429 template<
typename Po
intT>
void
441 template<
typename CloudT>
void
445 if (cloud.width == 0 && cloud.height == 0)
446 throw std::runtime_error(
"Needs to be a dense like cloud!!");
449 if (cloud.size () != cloud.width * cloud.height)
450 throw std::runtime_error(
"The width and height do not match the cloud size!");
451 msg.
height = cloud.height;
452 msg.
width = cloud.width;
456 msg.
header = cloud.header;
458 msg.
step = msg.
width *
sizeof (std::uint8_t) * 3;
460 for (std::size_t y = 0; y < cloud.height; y++)
462 for (std::size_t x = 0; x < cloud.width; x++)
464 std::uint8_t * pixel = &(msg.
data[y * msg.
step + x * 3]);
465 memcpy (pixel, &cloud (x, y).rgb, 3 *
sizeof(std::uint8_t));
478 const auto predicate = [](
const auto& field) {
return field.name ==
"rgb"; };
479 const auto result = std::find_if(cloud.
fields.cbegin (), cloud.
fields.cend (), predicate);
480 if (result == cloud.
fields.end ())
481 throw std::runtime_error (
"No rgb field!!");
485 throw std::runtime_error (
"Needs to be a dense like cloud!!");
491 auto rgb_offset = cloud.
fields[rgb_index].offset;
497 msg.
step = (msg.
width *
sizeof (std::uint8_t) * 3);
500 for (std::size_t y = 0; y < cloud.
height; y++)
502 for (std::size_t x = 0; x < cloud.
width; x++, rgb_offset += point_step)
504 std::uint8_t * pixel = &(msg.
data[y * msg.
step + x * 3]);
505 std::copy(&cloud.
data[rgb_offset], &cloud.
data[rgb_offset] + 3, pixel);
PointCloud represents the base class in PCL for storing collections of 3D points.
bool is_dense
True if no points are invalid (e.g., have NaN or Inf values in any of their floating point fields).
void resize(std::size_t count)
Resizes the container to contain count elements.
std::uint32_t width
The point cloud width (if organized as an image-structure).
pcl::PCLHeader header
The point cloud header.
std::uint32_t height
The point cloud height (if organized as an image-structure).
bool fieldOrdering(const FieldMapping &a, const FieldMapping &b)
float distance(const PointT &p1, const PointT &p2)
detail::int_type_t< detail::index_type_size, false > uindex_t
Type used for an unsigned index in PCL.
void fromPCLPointCloud2(const pcl::PCLPointCloud2 &msg, pcl::PointCloud< PointT > &cloud, const MsgFieldMap &field_map, const std::uint8_t *msg_data)
Convert a PCLPointCloud2 binary data blob into a pcl::PointCloud<T> object using a field_map.
void toPCLPointCloud2(const pcl::PointCloud< PointT > &cloud, pcl::PCLPointCloud2 &msg, bool padding)
Convert a pcl::PointCloud<T> object to a PCLPointCloud2 binary data blob.
void createMapping(const std::vector< pcl::PCLPointField > &msg_fields, MsgFieldMap &field_map)
std::vector< detail::FieldMapping > MsgFieldMap
std::vector< std::uint8_t > data
std::vector<::pcl::PCLPointField > fields
std::vector< std::uint8_t > data
A point structure representing Euclidean xyz coordinates, and the RGB color.
Used together with pcl::for_each_type, creates list of all fields, and list of size of each field.
FieldAdderAdvanced(std::vector< pcl::PCLPointField > &fields, std::vector< std::size_t > &field_sizes)
std::vector< std::size_t > & field_sizes_
std::vector< pcl::PCLPointField > & fields_
FieldAdder(std::vector< pcl::PCLPointField > &fields)
std::vector< pcl::PCLPointField > & fields_
std::uint8_t * cloud_data_
const pcl::PCLPointCloud2 & msg_
const std::uint8_t * msg_data_
FieldCaster(const std::vector< pcl::PCLPointField > &fields, const pcl::PCLPointCloud2 &msg, const std::uint8_t *msg_data, std::uint8_t *cloud_data)
const std::vector< pcl::PCLPointField > & fields_
Used together with pcl::for_each_type, copies all point fields from cloud_data (respecting each field...
FieldCopier(std::uint8_t *&msg_data, const std::uint8_t *&cloud_data)
const std::uint8_t *& cloud_data_
std::uint8_t *& msg_data_
FieldMapper(const std::vector< pcl::PCLPointField > &fields, std::vector< FieldMapping > &map)
const std::vector< pcl::PCLPointField > & fields_
std::vector< FieldMapping > & map_
std::size_t struct_offset
std::size_t serialized_offset