draco_subscriber.cpp
Go to the documentation of this file.
1 // SPDX-License-Identifier: BSD-3-Clause
2 // SPDX-FileCopyrightText: Czech Technical University in Prague .. 2019, paplhjak
3 
4 #include <memory>
5 #include <string>
6 #include <vector>
7 
8 #include <draco/compression/decode.h>
9 
12 #include <sensor_msgs/PointCloud2.h>
13 
14 #include <draco_point_cloud_transport/CompressedPointCloud2.h>
17 
19 {
20 
22 cras::expected<bool, std::string> convertDracoToPC2(
23  const draco::PointCloud& pc,
24  const draco_point_cloud_transport::CompressedPointCloud2& compressed_PC2,
25  sensor_msgs::PointCloud2& PC2)
26 {
27  // number of all attributes of point cloud
28  int32_t number_of_attributes = pc.num_attributes();
29 
30  // number of points in pointcloud
31  draco::PointIndex::ValueType number_of_points = pc.num_points();
32 
33  PC2.data.resize(number_of_points * compressed_PC2.point_step);
34 
35  // for each attribute
36  for (int32_t att_id = 0; att_id < number_of_attributes; att_id++)
37  {
38  // get attribute
39  const draco::PointAttribute* attribute = pc.attribute(att_id);
40 
41  // check if attribute is valid
42  if (!attribute->IsValid())
43  return cras::make_unexpected("In point_cloud_transport::DracoToPC2, attribute of Draco pointcloud is not valid!");
44 
45  // get offset of attribute in data structure
46  uint32_t attribute_offset = compressed_PC2.fields[att_id].offset;
47 
48  // for each point in point cloud
49  for (draco::PointIndex::ValueType point_index = 0; point_index < number_of_points; point_index++)
50  {
51  // get pointer to corresponding memory in PointCloud2 data
52  uint8_t* out_data = &PC2.data[static_cast<int>(compressed_PC2.point_step * point_index + attribute_offset)];
53 
54  // read value from Draco pointcloud to out_data
55  attribute->GetValue(draco::AttributeValueIndex(point_index), out_data);
56  }
57  }
58 
59  // copy PointCloud2 description (header, width, ...)
60  copyCloudMetadata(PC2, compressed_PC2);
61 
62  return true;
63 }
64 
66 {
67  return "draco";
68 }
69 
71  const CompressedPointCloud2& compressed, const DracoSubscriberConfig& config) const
72 {
73  // get size of buffer with compressed data in Bytes
74  uint32_t compressed_data_size = compressed.compressed_data.size();
75 
76  // empty buffer
77  if (compressed_data_size == 0)
78  return cras::make_unexpected("Received compressed Draco message with zero length.");
79 
80  draco::DecoderBuffer decode_buffer;
81  std::vector<unsigned char> vec_data = compressed.compressed_data;
82 
83  // Sets the buffer's internal data. Note that no copy of the input data is
84  // made so the data owner needs to keep the data valid and unchanged for
85  // runtime of the decoder.
86  decode_buffer.Init(reinterpret_cast<const char*>(&vec_data[0]), compressed_data_size);
87 
88  // create decoder object
89  draco::Decoder decoder;
90  // set decoder from dynamic reconfiguration
91  if (config_.SkipDequantizationPOSITION)
92  {
93  decoder.SetSkipAttributeTransform(draco::GeometryAttribute::POSITION);
94  }
95  if (config_.SkipDequantizationNORMAL)
96  {
97  decoder.SetSkipAttributeTransform(draco::GeometryAttribute::NORMAL);
98  }
99  if (config_.SkipDequantizationCOLOR)
100  {
101  decoder.SetSkipAttributeTransform(draco::GeometryAttribute::COLOR);
102  }
103  if (config_.SkipDequantizationTEX_COORD)
104  {
105  decoder.SetSkipAttributeTransform(draco::GeometryAttribute::TEX_COORD);
106  }
107  if (config_.SkipDequantizationGENERIC)
108  {
109  decoder.SetSkipAttributeTransform(draco::GeometryAttribute::GENERIC);
110  }
111 
112  // decode buffer into draco point cloud
113  const auto res = decoder.DecodePointCloudFromBuffer(&decode_buffer);
114  if (!res.ok())
115  return cras::make_unexpected(
116  cras::format("Draco decoder returned code %i: %s.", res.status().code(), res.status().error_msg()));
117 
118  const std::unique_ptr<draco::PointCloud>& decoded_pc = res.value();
119 
120  sensor_msgs::PointCloud2Ptr message(new sensor_msgs::PointCloud2);
121  const auto convertRes = convertDracoToPC2(*decoded_pc, compressed, *message);
122  if (!convertRes)
123  return cras::make_unexpected(convertRes.error());
124 
125  return message;
126 }
127 
128 }
std::string getTransportName() const override
cras::expected< cras::optional< sensor_msgs::PointCloud2ConstPtr >, std::string > DecodeResult
void copyCloudMetadata(PC1 &target, const PC2 &source)
copies header, width, ... between clouds
DecodeResult decodeTyped(const CompressedPointCloud2 &compressed, const DracoSubscriberConfig &config) const override
inline ::std::string format(const char *format, ::va_list args)
cras::expected< bool, std::string > convertDracoToPC2(const draco::PointCloud &pc, const draco_point_cloud_transport::CompressedPointCloud2 &compressed_PC2, sensor_msgs::PointCloud2 &PC2)
Method for converting into sensor_msgs::PointCloud2.


draco_point_cloud_transport
Author(s): Jakub Paplham
autogenerated on Sat Jun 17 2023 02:29:18