Reading ROS Messages from a Bagfile in Python
By: Rahul Bhadani
Tags: Robotics, Ros, Autonomous Cars, Autonomous Vehicles, Robot Operating System

Chances are if you have worked with ROS, you know how painful it is to write code to decode ROS messages from the recorded bag files. There are only a few tools out there that offer full-fledged functionality to read rosbag files. One such tool that comes to mind is ROS Toolbox in MATLAB from Mathworks. Prior to the 2020a version, the toolbox was a part of the Robotics System Toolbox. However, if you don’t have a license to the Matlab or to the Toolbox, in particular, it is going to be hard. With this in mind, I recently produced a python package bagpy that enables reading large bag files of any message types. Python is open-source and comes with a rich suite of other data analysis and visualization packages.

Below, I am going to provide some code-snippets on how to use bagpy to decode ROS Messages. For the purpose of this post, I am going to use OS1–64 v1.13 Sample Data from https://data.ouster.io/sample-data-1.13/OS1-64/index.html that contains data from a vehicle drive in San Francisco. The drive contains information about pedestrians, sidewalks, road signs, trees, and parked cars.

I will use the Jupyter notebook language here.

Install bagpy package:

!pip install bagpy

Get the sample bag files

!wget https://data.ouster.io/sample-data-1.13/OS1-64/OS1-64_city1.bag

Read the bag file

import bagpy

from bagpy import bagreader

import pandas as pd

import seaborn as sea

import matplotlib.pyplot as plt

import numpy as np

b = bagreader('OS1-64_city1.bag')

Note that when bagreader is load, you might see a warning Failed to load Python extension for LZ4 support. LZ4 compression will not be available . This is due to some issues with the ROS library and it is beyond my scope to fix. However, I never had an issue because of this warning.

Check available topics

b.topic_table

Decode messages on every topic

Using the class method message_by_topic , you can decode ROS messages of every topic type. message_by_topic creates a CSV with Time and other information as columns in a directory of the same name as the bag file.

csvfiles = []

for t in b.topics:

data = b.message_by_topic(t)

csvfiles.append(data)

To decode a specific, type, I type the following:

data = b.message_by_topic('/os1_cloud_node/imu')

print("File saved: {}".format(data))

Next, I can read the data using in pandas DataFrame

df_imu = pd.read_csv(data)

df_imu

Last, we can visualize every component of the imu messages elegantly:

fig, ax = bagpy.create_fig(10)

ax[0].scatter(x = 'Time', y = 'orientation.x', data = df_imu, s= 1, label = 'orientation.x')

ax[1].scatter(x = 'Time', y = 'orientation.y', data = df_imu, s= 1, label ='orientation.y')

ax[2].scatter(x = 'Time', y = 'orientation.z', data = df_imu, s= 1, label = 'orientation.z')

ax[3].scatter(x = 'Time', y = 'orientation.w', data = df_imu, s= 1, label ='orientation.w')

ax[4].scatter(x = 'Time', y = 'angular_velocity.x', data = df_imu, s= 1, label = 'angular_velocity.x')

ax[5].scatter(x = 'Time', y = 'angular_velocity.y', data = df_imu, s= 1, label = 'angular_velocity.y')

ax[6].scatter(x = 'Time', y = 'angular_velocity.z', data = df_imu, s= 1, label = 'angular_velocity.z')

ax[7].scatter(x = 'Time', y = 'linear_acceleration.x', data = df_imu, s= 1, label = 'linear_acceleration.x')

ax[8].scatter(x = 'Time', y = 'linear_acceleration.y', data = df_imu, s= 1, label = 'linear_acceleration.y')

ax[9].scatter(x = 'Time', y = 'linear_acceleration.z', data = df_imu, s= 1, label = 'linear_acceleration.z')

for axis in ax:

axis.legend()

axis.set_xlabel('Time')



plt.show()

More detail on the package can be found at https://jmscslgroup.github.io/bagpy/index.html

If you have any specific questions on this, feel free to comment and let me know.