ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
5

How to read a bag file in ROS2?

asked 2020-08-04 15:47:48 -0600

Ana de Sousa gravatar image

Hello guys,

I have seen searching about it and found some discussions (123), but I couldn't make things work (I explain why below).

My problem

I have some bag files (db3 files) that I saved using rosbag2 record from here. Now, I would like to get information from the file and save it in a different format (.txt, .mat, it does not matter). For example, get messages from a specific topic and plot all data.

It seems that there is no python API ready yet, as there was for ROS1.

Possible solutions/Problems I found

I thought about some solutions, but faced a few limitations:

  1. Replay data, create a node that subscribes to all these topics, and then process this data in "real-time", saving it in a different format in the end.
    • The problem of doing this would be that it takes the time of the recorded data. If the experiment duration is 15minutes, it will take that long to get all data. And it does not make much sense for me.
  2. Create my own python API that opens the db3 file (sqlite3) and then process it.
    • I actually developed this quite a bit. I can open the file, see all topics, and get all messages on those topics. However, when it is time to interpret this data, it gets confusing as to how the cdr file is constructed. I explained that a little bit more here.
  3. Use the code that is being under development at the rosba2 github.
    • It seems that some packages (in cpp and in py) are starting to deserialize data. But I am really noob at this. I can build the rosbag2_cpp package, but I don't know how to test it. I don't know where to start from there actually.

Any help is really appreciated.

Using

  • Ubuntu 20.04
  • ROS2 foxy
  • rosbag2
edit retag flag offensive close merge delete

4 Answers

Sort by » oldest newest most voted
1

answered 2020-08-05 16:56:04 -0600

Ana de Sousa gravatar image

I solved this issue using sqlite3, get_message (from rosidl_runtime_py) and deserialize_message (from rclpy). In case others have similar issues, it is better explained here. This solution is temporary while there is no API ready (like we had in ROS1).

edit flag offensive delete link more
4

answered 2021-05-05 00:01:06 -0600

justinberi gravatar image

Here is an example using sqlite.

import sqlite3
from rosidl_runtime_py.utilities import get_message
from rclpy.serialization import deserialize_message

import matplotlib.pyplot as plt

class BagFileParser():
    def __init__(self, bag_file):
        self.conn = sqlite3.connect(bag_file)
        self.cursor = self.conn.cursor()

        ## create a message type map
        topics_data = self.cursor.execute("SELECT id, name, type FROM topics").fetchall()
        self.topic_type = {name_of:type_of for id_of,name_of,type_of in topics_data}
        self.topic_id = {name_of:id_of for id_of,name_of,type_of in topics_data}
        self.topic_msg_message = {name_of:get_message(type_of) for id_of,name_of,type_of in topics_data}

    def __del__(self):
        self.conn.close()

    # Return [(timestamp0, message0), (timestamp1, message1), ...]
    def get_messages(self, topic_name):

        topic_id = self.topic_id[topic_name]
        # Get from the db
        rows = self.cursor.execute("SELECT timestamp, data FROM messages WHERE topic_id = {}".format(topic_id)).fetchall()
        # Deserialise all and timestamp them
        return [ (timestamp,deserialize_message(data, self.topic_msg_message[topic_name])) for timestamp,data in rows]



if __name__ == "__main__":

        bag_file = '/workspaces/foxy_leg_ws/rosbag2_2021_04_28-04_42_07/rosbag2_2021_04_28-04_42_07_0.db3'

        parser = BagFileParser(bag_file)

        trajectory = parser.get_messages("/joint_trajectory")[0][1] 
        p_des_1 = [trajectory.points[i].positions[0] for i in range(len(trajectory.points))]
        t_des = [trajectory.points[i].time_from_start.sec + trajectory.points[i].time_from_start.nanosec*1e-9 for i in range(len(trajectory.points))]

        actual = parser.get_messages("/joint_states")

        plt.plot(t_des, p_des_1)

        plt.show()
edit flag offensive delete link more
4

answered 2022-07-20 10:44:21 -0600

lorepieri gravatar image

You can use the rosbags package: https://ternaris.gitlab.io/rosbags/

from rosbags.rosbag2 import Reader
from rosbags.serde import deserialize_cdr

# create reader instance and open for reading
with Reader('/home/ros/rosbag_2020_03_24') as reader:
    # topic and msgtype information is available on .connections list
    for connection in reader.connections:
        print(connection.topic, connection.msgtype)

    # iterate over messages
    for connection, timestamp, rawdata in reader.messages():
        if connection.topic == '/imu_raw/Imu':
            msg = deserialize_cdr(rawdata, connection.msgtype)
            print(msg.header.frame_id)
edit flag offensive delete link more
1

answered 2021-10-13 09:50:40 -0600

Praveen Nellihela gravatar image

updated 2021-10-13 09:51:56 -0600

There are some sample code offered in the official ros2/rosbag 2 repo found here: https://github.com/ros2/rosbag2/tree/...

the test_sequential_reader.py has some code that you can reuse to read data in the bag files using python. Hope you find this useful.

edit flag offensive delete link more

Question Tools

2 followers

Stats

Asked: 2020-08-04 15:47:48 -0600

Seen: 20,184 times

Last updated: Jul 20 '22