ros2_introspection.cpp
Go to the documentation of this file.
2 
3 #include <rosidl_typesupport_introspection_cpp/message_introspection.hpp>
4 #include <rosidl_typesupport_introspection_cpp/field_types.hpp>
5 #include <rosbag2_cpp/typesupport_helpers.hpp>
6 #include <rosbag2_cpp/types/introspection_message.hpp>
7 #include <rcutils/time.h>
8 #include <functional>
9 #include <cmath>
10 #include <fastcdr/Cdr.h>
11 
12 namespace Ros2Introspection
13 {
14 rcutils_allocator_t TopicInfo::allocator = rcutils_get_default_allocator();
15 
16 TopicInfo::TopicInfo(const std::string& type)
17 {
18  topic_type = type;
19 
20  _introspection_library = rosbag2_cpp::get_typesupport_library(type, "rosidl_typesupport_introspection_cpp");
21  introspection_support = rosbag2_cpp::get_typesupport_handle(type, "rosidl_typesupport_introspection_cpp", _introspection_library);
22 
23  auto identifier = rosidl_typesupport_cpp::typesupport_identifier;
24  _support_library = rosbag2_cpp::get_typesupport_library(type, identifier);
25  type_support = rosbag2_cpp::get_typesupport_handle(type, identifier, _support_library);
26 
28 }
29 
30 template <typename T>
32 {
33  T tmp;
34  cdr.deserialize(tmp);
35  return tmp;
36 }
37 
38 bool TypeHasHeader(const rosidl_message_type_support_t* type_support)
39 {
40  auto members = static_cast<const rosidl_typesupport_introspection_cpp::MessageMembers *>(type_support->data);
41 
42  if (members->member_count_ >= 1 && members->members_)
43  {
44  const rosidl_typesupport_introspection_cpp::MessageMember& first_field = members->members_[0];
45  if (first_field.members_ == nullptr)
46  {
47  return false;
48  }
49  const auto* header_members = static_cast<const rosidl_typesupport_introspection_cpp::MessageMembers*>(first_field.members_->data);
50  if (strcmp(header_members->message_name_, "Header") == 0 && strcmp(header_members->message_namespace_, "std_msgs::"
51  "msg") == 0)
52  {
53  return true;
54  }
55  }
56  return false;
57 }
58 
59 Parser::Parser(const std::string& topic_name, const std::string& type_name)
60  : _discard_policy(DISCARD_LARGE_ARRAYS), _max_array_size(MAX_ARRAY_SIZE), _topic_info(type_name)
61 {
62  using TypeSupport = rosidl_message_type_support_t;
63  //------- create StringTree --------
64  using rosidl_typesupport_introspection_cpp::MessageMember;
65  using rosidl_typesupport_introspection_cpp::MessageMembers;
66  using rosidl_typesupport_introspection_cpp::ROS_TYPE_MESSAGE;
67 
68  std::function<void(StringTreeNode * node, const TypeSupport*)> recursivelyCreateTree;
69  recursivelyCreateTree = [&](StringTreeNode* node, const TypeSupport* type_data) {
70  const auto* members = static_cast<const MessageMembers*>(type_data->data);
71 
72  node->children().reserve(members->member_count_);
73 
74  for (size_t i = 0; i < members->member_count_; i++)
75  {
76  const MessageMember& member = members->members_[i];
77  StringTreeNode* new_node = node->addChild(member.name_);
78  if (member.is_array_)
79  {
80  new_node->children().reserve(1);
81  new_node = new_node->addChild("#");
82  }
83  if (member.type_id_ == ROS_TYPE_MESSAGE)
84  {
85  // recursion
86  recursivelyCreateTree(new_node, member.members_);
87  }
88  }
89  };
90 
91  _field_tree.root()->setValue(topic_name);
92  auto starting_node = _field_tree.root();
93 
94  // start building recursively
95  recursivelyCreateTree(starting_node, _topic_info.introspection_support);
96 }
97 
98 void Parser::setMaxArrayPolicy(MaxArrayPolicy discard_policy, size_t max_size)
99 {
100  _discard_policy = discard_policy;
101  _max_array_size = max_size;
102 }
103 
105 {
106  return _discard_policy;
107 }
108 
109 size_t Parser::maxArraySize() const
110 {
111  return _max_array_size;
112 }
113 
114 bool Parser::deserializeIntoFlatMessage(const rcutils_uint8_array_t* msg, FlatMessage* flat_container) const
115 {
116  eprosima::fastcdr::FastBuffer buffer(reinterpret_cast<char*>(msg->buffer), msg->buffer_length);
118  cdr.read_encapsulation();
119 
120  using TypeSupport = rosidl_message_type_support_t;
121 
122  std::function<void(const TypeSupport*, StringTreeLeaf&, bool)> recursiveParser;
123 
124  //---------- recursive function -------------
125  recursiveParser = [&](const TypeSupport* type_data, StringTreeLeaf& tree_leaf, bool skip_save) {
126  using namespace rosidl_typesupport_introspection_cpp;
127  const auto* members = static_cast<const MessageMembers*>(type_data->data);
128 
129  for (size_t index = 0; index < members->member_count_; index++)
130  {
131  const MessageMember& member = members->members_[index];
132 
133  auto new_tree_leaf = tree_leaf;
134  new_tree_leaf.node_ptr = tree_leaf.node_ptr->child(index);
135 
136  size_t array_size = 1;
137 
138  if (member.is_array_)
139  {
140  if (member.array_size_ == 0)
141  {
142  array_size = size_t(CastFromBuffer<uint32_t>(cdr));
143  }
144  else
145  {
146  array_size = member.array_size_;
147  }
148  }
149 
150  if (array_size > MAX_ARRAY_SIZE && (member.type_id_ == ROS_TYPE_INT8 || member.type_id_ == ROS_TYPE_UINT8))
151  {
152  if (!skip_save)
153  {
154  BufferView blob(cdr.getCurrentPosition(), array_size);
155  flat_container->blobs.push_back({ new_tree_leaf, std::move(blob) });
156  }
157  cdr.jump(array_size);
158 
159  continue;
160  }
161 
162  if (member.is_array_)
163  {
164  new_tree_leaf.index_array.push_back(0);
165  new_tree_leaf.node_ptr = new_tree_leaf.node_ptr->child(0);
166  }
167 
168  for (size_t a = 0; a < array_size; a++)
169  {
170  if (member.is_array_)
171  {
172  new_tree_leaf.index_array.back() = a;
173  }
174 
175  if ((_discard_policy == DISCARD_LARGE_ARRAYS && array_size >= _max_array_size) ||
177  {
178  skip_save = true;
179  }
180 
181  if (member.type_id_ != ROS_TYPE_MESSAGE && member.type_id_ != ROS_TYPE_STRING)
182  {
183  double value = 0;
184  switch (member.type_id_)
185  {
186  case ROS_TYPE_FLOAT:
187  value = double(CastFromBuffer<float>(cdr));
188  break;
189  case ROS_TYPE_DOUBLE:
190  value = double(CastFromBuffer<double>(cdr));
191  break;
192 
193  case ROS_TYPE_INT64:
194  value = double(CastFromBuffer<int64_t>(cdr));
195  break;
196  case ROS_TYPE_INT32:
197  value = double(CastFromBuffer<int32_t>(cdr));
198  break;
199  case ROS_TYPE_INT16:
200  value = double(CastFromBuffer<int16_t>(cdr));
201  break;
202  case ROS_TYPE_INT8:
203  value = double(CastFromBuffer<int8_t>(cdr));
204  break;
205 
206  case ROS_TYPE_UINT64:
207  value = double(CastFromBuffer<uint64_t>(cdr));
208  break;
209  case ROS_TYPE_UINT32:
210  value = double(CastFromBuffer<uint32_t>(cdr));
211  break;
212  case ROS_TYPE_UINT16:
213  value = double(CastFromBuffer<uint16_t>(cdr));
214  break;
215  case ROS_TYPE_UINT8:
216  value = double(CastFromBuffer<uint8_t>(cdr));
217  break;
218 
219  case ROS_TYPE_BOOLEAN:
220  value = double(CastFromBuffer<bool>(cdr));
221  break;
222  }
223  if (!skip_save)
224  {
225  flat_container->values.push_back({ new_tree_leaf, value });
226  }
227  }
228  else if (member.type_id_ == ROS_TYPE_STRING)
229  {
230  if (!skip_save)
231  {
232  std::string str;
233  cdr.deserialize(str);
234  flat_container->strings.push_back({ new_tree_leaf, std::move(str) });
235  }
236  else
237  {
238  static std::string tmp;
239  cdr.deserialize(tmp);
240  }
241  }
242  else if (member.type_id_ == ROS_TYPE_MESSAGE)
243  {
244  recursiveParser(member.members_, new_tree_leaf, skip_save);
245  }
246  } // end for array
247  } // end for members
248  };
249  //---------- END recursive function -------------
250  flat_container->blobs.clear();
251  flat_container->strings.clear();
252  flat_container->values.clear();
253  flat_container->tree = &_field_tree;
254 
255  StringTreeLeaf rootnode;
256  rootnode.node_ptr = _field_tree.root();
257  recursiveParser(_topic_info.introspection_support, rootnode, false);
258 
259  return true;
260 }
261 
263 {
264  return _topic_info;
265 }
266 
267 
268 } // namespace Ros2Introspection
TreeNode< T > * root()
Mutable pointer to the root of the tree.
const TopicInfo & topicInfo() const
bool deserializeIntoFlatMessage(const rcutils_uint8_array_t *msg, FlatMessage *flat_container_output) const
The StringTreeLeaf is, as the name suggests, a leaf (terminal node) of a StringTree. It provides the pointer to the node and a list of numbers that represent the index that corresponds to the placeholder "#".
Definition: stringtree.hpp:79
span_CONFIG_SIZE_TYPE size_t
Parser(const std::string &topic_name, const std::string &type_name)
MaxArrayPolicy maxArrayPolicy() const
type
static rcutils_allocator_t allocator
std::shared_ptr< rcpputils::SharedLibrary > _support_library
const StringTreeNode * node_ptr
Definition: stringtree.hpp:83
std::vector< std::pair< StringTreeLeaf, std::string > > strings
const rosidl_message_type_support_t * type_support
Element of the tree. it has a single parent and N >= 0 children.
std::shared_ptr< rcpputils::SharedLibrary > _introspection_library
static const Endianness DEFAULT_ENDIAN
const StringTree * tree
Tree that the StringTreeLeaf(s) refer to.
std::vector< std::pair< StringTreeLeaf, double > > values
std::size_t index
bool jump(size_t numBytes)
const rosidl_message_type_support_t * introspection_support
size_t & i
void setMaxArrayPolicy(MaxArrayPolicy discard_policy, size_t max_size)
std::vector< std::pair< StringTreeLeaf, BufferView > > blobs
bool TypeHasHeader(const rosidl_message_type_support_t *type_support)
T CastFromBuffer(eprosima::fastcdr::Cdr &cdr)
TopicInfo(const std::string &type)
Cdr & deserialize(uint8_t &octet_t)


plotjuggler_ros
Author(s): Davide Faconti
autogenerated on Fri Jun 23 2023 02:28:03