!

(!) Please ask about problems and questions regarding this tutorial on answers.ros.org. Don't forget to include in your question the link to this page, the versions of your OS & ROS, and also add appropriate tags.

Reading data from (any) Rosbag.

Description: Describes how to open any rosbag and extract data even if the stored topic are not known at compilation time.

Keywords: introspection, rosbag

Tutorial Level: BEGINNER

Next Tutorial: Subscribe to any topic and deserialize its content. Generic Topic Subscriber

When you open a rosbag, DataType and Definition can be accessed through rosbag::ConnectionInfo.

This allows us to deserialize the type-erased ROS containers: rosbag::MessageInstance; all the information we need is stored in the rosbag itself.

   1 #include "ros_type_introspection/ros_introspection.hpp"
   2 #include <ros/ros.h>
   3 #include <rosbag/bag.h>
   4 #include <rosbag/view.h>
   5 
   6 using namespace RosIntrospection;
   7 
   8 // usage: pass the name of the file as command line argument
   9 int main(int argc, char** argv)
  10 {
  11     if( argc != 2 ){
  12         printf("Usage: pass the name of a file as first argument\n");
  13         return 1;
  14     }
  15 
  16     Parser parser;
  17     rosbag::Bag bag;
  18 
  19     try{
  20         bag.open( argv[1] );
  21     }
  22     catch( rosbag::BagException&  ex)
  23     {
  24         printf("rosbag::open thrown an exception: %s\n", ex.what());
  25         return -1;
  26     }
  27     // this  rosbag::View will accept ALL the messages (no filter)
  28     rosbag::View bag_view ( bag );
  29 
  30     // register (only once at the beginning) the type of messages
  31     for(const rosbag::ConnectionInfo* connection: bag_view.getConnections() )
  32     {
  33         const std::string&  topic_name =  connection->topic;
  34         const std::string&  datatype   =  connection->datatype;
  35         const std::string&  definition =  connection->msg_def;
  36         // register the type using the topic_name as identifier.
  37         parser.registerMessageDefinition(topic_name, ROSType(datatype), definition);
  38     }
  39 
  40     // It is efficient to reuse the same instance of FlatMessage and RenamedValues
  41     // over and over again, to reduce the amount of memory allocations
  42     std::map<std::string, FlatMessage>   flat_containers;
  43     std::map<std::string, RenamedValues> renamed_vectors;
  44 
  45     for(rosbag::MessageInstance msg_instance: bag_view)
  46     {
  47         const std::string& topic_name  = msg_instance.getTopic();
  48 
  49         // This buffer will store the raw bytes where the message is encoded
  50         std::vector<uint8_t> buffer;
  51         // write the message into the buffer
  52         const size_t msg_size  = msg_instance.size();
  53         buffer.resize(msg_size);
  54         ros::serialization::OStream stream(buffer.data(), buffer.size());
  55         // the write method copy the serialized data into the buffer.
  56         msg_instance.write(stream);
  57 
  58         FlatMessage&   flat_container = flat_containers[topic_name];
  59         RenamedValues& renamed_values = renamed_vectors[topic_name];
  60 
  61         // deserialize and rename the vectors
  62         parser.deserializeIntoFlatContainer( topic_name,
  63                                              absl::Span<uint8_t>(buffer),
  64                                              &flat_container, 100 );
  65         // applyNameTransform will convert  flat_container.value into renamed_values
  66         // using, if previously registered, some "rules".
  67         // This particular example doesn't use any rule.
  68         parser.applyNameTransform( topic_name,
  69                                    flat_container,
  70                                    &renamed_values );
  71 
  72         // Print the content of the message
  73         printf("--------- %s ----------\n", topic_name.c_str() );
  74         for (auto it: renamed_values)
  75         {
  76             const std::string& key = it.first;
  77             const Variant& value   = it.second;
  78             printf(" %s = %f\n", key.c_str(), value.convert<double>() );
  79         }
  80         for (auto it: flat_container.name)
  81         {
  82             const std::string& key    = it.first.toStdString();
  83             const std::string& value  = it.second;
  84             printf(" %s = %s\n", key.c_str(), value.c_str() );
  85         }
  86     }
  87     return 0;
  88 }

Wiki: ros_type_introspection/Tutorials/ReadingRosbagUsingIntrospection (last edited 2019-01-19 15:35:26 by DavideFaconti)