ros_introspection.hpp
Go to the documentation of this file.
1 /*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright 2016-2017 Davide Faconti
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * * Neither the name of Willow Garage, Inc. nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 * *******************************************************************/
34 
35 #ifndef ROS_INTROSPECTION_HPP
36 #define ROS_INTROSPECTION_HPP
37 
38 #include <unordered_set>
42 
43 namespace RosIntrospection{
44 
45 struct FlatMessage {
46 
48  const StringTree* tree;
49 
52  std::vector< std::pair<StringTreeLeaf, Variant> > value;
53 
56  std::vector< std::pair<StringTreeLeaf, std::string> > name;
57 
61  std::vector< std::pair<StringTreeLeaf, Span<uint8_t>>> blob;
62 
63  std::vector<std::vector<uint8_t>> blob_storage;
64 };
65 
66 typedef std::vector< std::pair<std::string, Variant> > RenamedValues;
67 
68 class Parser{
69 
70 public:
71  Parser(): _rule_cache_dirty(true),
72  _global_warnings(&std::cerr),
73  _discard_large_array(DISCARD_LARGE_ARRAYS),
74  _blob_policy(STORE_BLOB_AS_COPY)
75  {}
76 
77  enum MaxArrayPolicy: bool {
78  DISCARD_LARGE_ARRAYS = true,
79  KEEP_LARGE_ARRAYS = false
80  };
81 
82  void setMaxArrayPolicy( MaxArrayPolicy discard_entire_array )
83  {
84  _discard_large_array = discard_entire_array;
85  }
86 
87  void setMaxArrayPolicy( bool discard_entire_array )
88  {
89  _discard_large_array = static_cast<MaxArrayPolicy>(discard_entire_array);
90  }
91 
93  {
94  return _discard_large_array;
95  }
96 
97  enum BlobPolicy {
99  STORE_BLOB_AS_REFERENCE};
100 
101  // If set to STORE_BLOB_AS_COPY, a copy of the original vector will be stored in the FlatMessage.
102  // This may have a large impact on performance.
103  // if STOR_BLOB_AS_REFERENCE is used instead, it is dramatically faster, but you must be careful with
104  // dangling pointers.
105  void setBlobPolicy( BlobPolicy policy )
106  {
107  _blob_policy = policy;
108  }
109 
111  {
112  return _blob_policy;
113  }
114 
128  void registerMessageDefinition(const std::string& message_identifier,
129  const ROSType &main_type,
130  const std::string& definition);
131 
138  void registerRenamingRules(const ROSType& type,
139  const std::vector<SubstitutionRule> &rules );
140 
147  const ROSMessageInfo* getMessageInfo(const std::string& msg_identifier) const;
148 
156  const ROSMessage *getMessageByType(const ROSType& type, const ROSMessageInfo &info) const;
157 
181  bool deserializeIntoFlatContainer(const std::string& msg_identifier,
182  Span<uint8_t> buffer,
183  FlatMessage* flat_container_output,
184  const uint32_t max_array_size ) const;
185 
206  void applyNameTransform(const std::string& msg_identifier,
207  const FlatMessage& container,
208  RenamedValues* renamed_value , bool dont_add_topicname = false);
209 
210  typedef std::function<void(const ROSType&, Span<uint8_t>&)> VisitingCallback;
211 
224  void applyVisitorToBuffer(const std::string& msg_identifier, const ROSType &monitored_type,
225  Span<uint8_t> &buffer,
226  VisitingCallback callback) const;
227 
228  template <typename T>
229  T extractField(const std::string& msg_identifier, const Span<uint8_t> &buffer);
230 
231 
233  void setWarningsStream(std::ostream* output) { _global_warnings = output; }
234 
235 private:
236 
237 
238  struct RulesCache{
240  rule( &r ), pattern_head(nullptr), alias_head(nullptr)
241  {}
245  bool operator==(const RulesCache& other) { return this->rule == other.rule; }
246  };
247 
248  std::unordered_map<std::string, ROSMessageInfo> _registered_messages;
249  std::unordered_map<ROSType, std::unordered_set<SubstitutionRule>> _registered_rules;
250  std::unordered_map<std::string, std::vector<RulesCache>> _rule_caches;
251 
252  void updateRuleCache();
253 
255 
256  void createTrees(ROSMessageInfo &info, const std::string &type_name) const;
257 
258  std::ostream* _global_warnings;
259 
260  std::vector<int> _alias_array_pos;
261  std::vector<std::string> _formatted_string;
262  std::vector<int8_t> _substituted;
265 };
266 
267 //---------------------------------------------------
268 
269 template<typename T> inline
270 T Parser::extractField(const std::string &msg_identifier,
271  const Span<uint8_t> &buffer)
272 {
273  T out;
274  bool found = false;
275 
276  const ROSMessageInfo* msg_info = getMessageInfo(msg_identifier);
277  if( msg_info == nullptr)
278  {
279  throw std::runtime_error("extractField: msg_identifier not registered. Use registerMessageDefinition" );
280  }
281 
282  const ROSType monitored_type (ros::message_traits::DataType<T>::value());
283 
284  if( getMessageByType( monitored_type, *msg_info) == nullptr)
285  {
286  throw std::runtime_error("extractField: message type doesn't contain this field type" );
287  }
288 
289  std::function<void(const MessageTreeNode*)> recursiveImpl;
290  size_t buffer_offset = 0;
291 
292  recursiveImpl = [&](const MessageTreeNode* msg_node)
293  {
294  if( found ) return;
295 
296  const ROSMessage* msg_definition = msg_node->value();
297  const ROSType& msg_type = msg_definition->type();
298 
299  size_t index_m = 0;
300 
301  if( msg_type == monitored_type )
302  {
303  ros::serialization::IStream is( buffer.data() + buffer_offset,
304  buffer.size() - buffer_offset );
306  found = true;
307  return;
308  }
309  // subfields
310  for (const ROSField& field : msg_definition->fields() )
311  {
312  if(field.isConstant() ) continue;
313 
314  const ROSType& field_type = field.type();
315 
316  int32_t array_size = field.arraySize();
317  if( array_size == -1)
318  {
319  ReadFromBuffer( buffer, buffer_offset, array_size );
320  }
321  //------------------------------------
322  if( field_type.isBuiltin() && field_type != monitored_type )
323  {
324  //fast skip
325  if( field_type.typeSize() >= 1 )
326  {
327  buffer_offset += field_type.typeSize() * array_size;
328  }
329  else{
330  ReadFromBufferToVariant( field_type.typeID(), buffer, buffer_offset );
331  }
332  }
333  else
334  {
335  for (int i=0; i<array_size; i++ )
336  {
337  recursiveImpl( msg_node->child(index_m) );
338  if( found ) return;
339  }
340  index_m++;
341  }
342  } // end for fields
343 
344  }; //end lambda
345 
346  //start recursion
347  recursiveImpl( msg_info->message_tree.croot() );
348 
349  return out;
350 }
351 
352 
353 
354 }
355 
356 #endif // ROS_INTROSPECTION_HPP
nonstd::span< T > Span
std::vector< std::string > _formatted_string
std::vector< std::pair< StringTreeLeaf, std::string > > name
const std::vector< ROSField > & fields() const
Vector of fields.
Definition: ros_message.hpp:60
const StringTree * tree
Tree that the StringTreeLeaf(s) refer to.
std::vector< int > _alias_array_pos
Variant ReadFromBufferToVariant(const Span< uint8_t > &buffer, size_t &offset)
Element of the tree. it has a single parent and N >= 0 children.
Definition: tree.hpp:54
int typeSize() const
If builtin, size of builtin, -1 means variable or undefined.
Definition: ros_type.hpp:132
std::unordered_map< std::string, std::vector< RulesCache > > _rule_caches
const TreeNode< T > * croot() const
Constant pointer to the root of the tree.
Definition: tree.hpp:98
void setBlobPolicy(BlobPolicy policy)
std::vector< std::vector< uint8_t > > blob_storage
void setMaxArrayPolicy(bool discard_entire_array)
T extractField(const std::string &msg_identifier, const Span< uint8_t > &buffer)
std::unordered_map< ROSType, std::unordered_set< SubstitutionRule > > _registered_rules
std::unordered_map< std::string, ROSMessageInfo > _registered_messages
std::vector< std::pair< StringTreeLeaf, Variant > > value
std::vector< int8_t > _substituted
const ROSType & type() const
Definition: ros_message.hpp:62
MaxArrayPolicy maxArrayPolicy() const
def msg_type(f)
def field_type(f)
std::vector< std::pair< std::string, Variant > > RenamedValues
std::vector< std::pair< StringTreeLeaf, Span< uint8_t > > > blob
bool operator==(const RulesCache &other)
A ROSMessage will contain one or more ROSField(s). Each field is little more than a name / type pair...
Definition: ros_field.hpp:52
void setWarningsStream(std::ostream *output)
Change where the warning messages are displayed.
const char * definition()
void deserialize(Stream &stream, T &t)
BuiltinType typeID() const
If type is builtin, returns the id. BuiltinType::OTHER otherwise.
Definition: ros_type.hpp:137
bool isBuiltin() const
True if the type is ROS builtin.
Definition: ros_type.hpp:127
std::function< void(const ROSType &, Span< uint8_t > &)> VisitingCallback
BlobPolicy blobPolicy() const
void setMaxArrayPolicy(MaxArrayPolicy discard_entire_array)
RulesCache(const SubstitutionRule &r)
void ReadFromBuffer(const Span< uint8_t > &buffer, size_t &offset, T &destination)


ros_type_introspection
Author(s): Davide Faconti
autogenerated on Sun Sep 6 2020 03:19:54