Work with rosbag
Logfiles
This example enables you to load a rosbag, and learn how to select and retrieve the contained messages.
A rosbag or bag is a file format in ROS for storing message data. These bags are often created by subscribing to one or more ROS topics, and storing the received message data in an efficient file structure. MATLAB® can read these rosbag files and help with filtering and extracting message data. See ROS Log Files (rosbags) for more information about rosbag support in MATLAB.
Prerequisites: Work with Basic ROS Messages
Load a rosbag
Load an example file using the rosbag
command.
bag = rosbag("ex_multiple_topics.bag")
bag = BagSelection with properties: FilePath: 'C:\Users\csalzber\OneDrive - MathWorks\Documents\MATLAB\Examples\ros-ex71482057\ex_multiple_topics.bag' StartTime: 201.3400 EndTime: 321.3400 NumMessages: 36963 AvailableTopics: [4×3 table] AvailableFrames: {0×1 cell} MessageList: [36963×4 table]
The object returned from the rosbag
call is a BagSelection
object, which is a representation of all the messages in the rosbag.
The object display shows details about how many messages are contained in the file (NumMessages
) and the time when the first (StartTime
) and the last (EndTime
) message were recorded.
Evaluate the AvailableTopics
property to see more information about the topics and message types that are recorded in the bag:
bag.AvailableTopics
ans=4×3 table
NumMessages MessageType MessageDefinition
___________ ______________________ ____________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________
/clock 12001 rosgraph_msgs/Clock {0×0 char }
/gazebo/link_states 11999 gazebo_msgs/LinkStates {'geometry_msgs/Pose[] Pose↵ geometry_msgs/Point Position↵ double X↵ double Y↵ double Z↵ geometry_msgs/Quaternion Orientation↵ double X↵ double Y↵ double Z↵ double W↵geometry_msgs/Twist[] Twist↵ geometry_msgs/Vector3 Linear↵ double X↵ double Y↵ double Z↵ geometry_msgs/Vector3 Angular↵ double X↵ double Y↵ double Z↵' }
/odom 11998 nav_msgs/Odometry {' uint32 Seq↵ Time Stamp↵ char FrameId↵char ChildFrameId↵geometry_msgs/PoseWithCovariance Pose↵ geometry_msgs/Pose Pose↵ geometry_msgs/Point Position↵ double X↵ double Y↵ double Z↵ geometry_msgs/Quaternion Orientation↵ double X↵ double Y↵ double Z↵ double W↵ double[36] Covariance↵geometry_msgs/TwistWithCovariance Twist↵ geometry_msgs/Twist Twist↵ geometry_msgs/Vector3 Linear↵ double X↵ double Y↵ double Z↵ geometry_msgs/Vector3 Angular↵ double X↵ double Y↵ double Z↵ double[36] Covariance↵'}
/scan 965 sensor_msgs/LaserScan {' uint32 Seq↵ Time Stamp↵ char FrameId↵single AngleMin↵single AngleMax↵single AngleIncrement↵single TimeIncrement↵single ScanTime↵single RangeMin↵single RangeMax↵single[] Ranges↵single[] Intensities↵' }
The AvailableTopics
table contains the sorted list of topics that are included in the rosbag. The table stores the number of messages, the message type, and the message definition for the topic. For more information on the MATLAB table data type and what operations you can perform on it, see the documentation for Tables.
Initially the rosbag is only indexed by MATLAB and no actual message data is read.
You might want to filter and narrow the selection of messages as much as possible based on this index before any messages are loaded into MATLAB memory.
Select Messages
Before you retrieve any message data, you must select a set of messages based on criteria such as time stamp, topic name, and message type.
You can examine all the messages in the current selection:
bag.MessageList
ans=36963×4 table
Time Topic MessageType FileOffset
______ ___________________ ______________________ __________
201.34 /gazebo/link_states gazebo_msgs/LinkStates 9866
201.34 /odom nav_msgs/Odometry 7666
201.34 /clock rosgraph_msgs/Clock 4524
201.35 /clock rosgraph_msgs/Clock 10962
201.35 /clock rosgraph_msgs/Clock 12876
201.35 /odom nav_msgs/Odometry 12112
201.35 /gazebo/link_states gazebo_msgs/LinkStates 11016
201.36 /gazebo/link_states gazebo_msgs/LinkStates 12930
201.36 /odom nav_msgs/Odometry 14026
201.37 /odom nav_msgs/Odometry 14844
201.37 /gazebo/link_states gazebo_msgs/LinkStates 15608
201.37 /clock rosgraph_msgs/Clock 14790
201.38 /clock rosgraph_msgs/Clock 16704
201.38 /gazebo/link_states gazebo_msgs/LinkStates 16758
201.38 /odom nav_msgs/Odometry 17854
201.39 /gazebo/link_states gazebo_msgs/LinkStates 18672
⋮
The MessageList
table contains one row for each message in the bag (there are over 30,000 rows for the bag in this example). The rows are sorted by time stamp in the first column, which represents the time (in seconds) that the message was recorded.
Since the list is very large, you can also display a selection of rows with the familiar row and column selection syntax:
bag.MessageList(500:505,:)
ans=6×4 table
Time Topic MessageType FileOffset
____ ___________________ ______________________ __________
203 /clock rosgraph_msgs/Clock 339384
203 /gazebo/link_states gazebo_msgs/LinkStates 331944
203 /gazebo/link_states gazebo_msgs/LinkStates 333040
203 /gazebo/link_states gazebo_msgs/LinkStates 334136
203 /gazebo/link_states gazebo_msgs/LinkStates 335232
203 /odom nav_msgs/Odometry 336328
Use the select
function to narrow the selection of messages. The select
function operates on the bag
object.
You can filter the message list by time, topic name, message type, or any combination of the three.
To select all messages that were published on the /odom
topic, use the following select
command:
bagselect1 = select(bag,"Topic","/odom")
bagselect1 = BagSelection with properties: FilePath: 'C:\Users\csalzber\OneDrive - MathWorks\Documents\MATLAB\Examples\ros-ex71482057\ex_multiple_topics.bag' StartTime: 201.3400 EndTime: 321.3300 NumMessages: 11998 AvailableTopics: [1×3 table] AvailableFrames: {0×1 cell} MessageList: [11998×4 table]
Calls to the select
function return another BagSelection
object, which can be used to make further selections or retrieve message data. All selection objects are independent of each other, so you can clear them from the workspace once you are done.
You can make a different selection that combines two criteria. To get the list of messages that were recorded within the first 30 seconds of the rosbag and published on the /odom
topic, enter the following command:
start = bag.StartTime
start = 201.3400
bagselect2 = select(bag,"Time",[start start + 30],"Topic","/odom")
bagselect2 = BagSelection with properties: FilePath: 'C:\Users\csalzber\OneDrive - MathWorks\Documents\MATLAB\Examples\ros-ex71482057\ex_multiple_topics.bag' StartTime: 201.3400 EndTime: 231.3200 NumMessages: 2997 AvailableTopics: [1×3 table] AvailableFrames: {0×1 cell} MessageList: [2997×4 table]
Use the last selection to narrow down the time window even further:
bagselect3 = select(bagselect2,"Time",[205 206])
bagselect3 = BagSelection with properties: FilePath: 'C:\Users\csalzber\OneDrive - MathWorks\Documents\MATLAB\Examples\ros-ex71482057\ex_multiple_topics.bag' StartTime: 205.0200 EndTime: 205.9900 NumMessages: 101 AvailableTopics: [1×3 table] AvailableFrames: {0×1 cell} MessageList: [101×4 table]
The selection in this last step operated on the existing bagselect2
selection and returned a new bagselect3
object.
If you want to save a set of selection options, store the selection elements in a cell array and then re-use it later as an input to the select
function:
selectOptions = {"Time",[start, start+1; start+5, start+6],"MessageType",["sensor_msgs/LaserScan","nav_msgs/Odometry"]}; bagselect4 = select(bag,selectOptions{:})
bagselect4 = BagSelection with properties: FilePath: 'C:\Users\csalzber\OneDrive - MathWorks\Documents\MATLAB\Examples\ros-ex71482057\ex_multiple_topics.bag' StartTime: 201.3400 EndTime: 207.3300 NumMessages: 209 AvailableTopics: [2×3 table] AvailableFrames: {0×1 cell} MessageList: [209×4 table]
Read Selected Message Data
After you narrow your message selection, you might want to read the actual message data into MATLAB. Depending on the size of your selection, this can take a long time and consume a lot of your computer's memory. To improve time efficiency, read the messages from the rosbag in structure format.
To retrieve the messages in you selection as a cell array, use the readMessages
function:
msgs = readMessages(bagselect3,"DataFormat","struct"); size(msgs)
ans = 1×2
101 1
The resulting cell array contains as many elements as indicated in the NumMessages
property of the selection object.
In reading message data, you can also be more selective and only retrieve messages at specific indices. Here is an example of retrieving 4 messages:
msgs = readMessages(bagselect3,[1 2 3 7],"DataFormat","struct")
msgs=4×1 cell array
{1×1 struct}
{1×1 struct}
{1×1 struct}
{1×1 struct}
msgs{2}
ans = struct with fields:
MessageType: 'nav_msgs/Odometry'
Header: [1×1 struct]
ChildFrameId: 'base_footprint'
Pose: [1×1 struct]
Twist: [1×1 struct]
Each message in the cell array is a standard MATLAB ROS message structure. For more information on messages, see the Work with Basic ROS Messages example.
Extract Message Data as Time Series
Sometimes you are not interested in the complete messages, but only in specific properties that are common to all the messages in a selection. In this case, it is helpful to retrieve the message data as a time series instead. A time series is a data vector that is sampled over time and represents the time evolution of one or more dynamic properties. For more information on the MATLAB time series support, see the documentation for Time Series.
In the case of ROS messages within a rosbag, a time series can help to express the change in particular message elements through time. You can extract this information through the timeseries
function. This is memory-efficient, since the complete messages do not have to be stored in memory.
Use the same selection, but use the timeseries
function to only extract the properties for x-position and z-axis angular velocity:
ts = timeseries(bagselect3,"Pose.Pose.Position.X","Twist.Twist.Angular.Z")
timeseries Timeseries contains duplicate times. Common Properties: Name: '/odom Properties' Time: [101x1 double] TimeInfo: [1x1 tsdata.timemetadata] Data: [101x2 double] DataInfo: [1x1 tsdata.datametadata] More properties, Methods
The return of this call is a timeseries
object that can be used for further analysis or processing.
Note that this method of extracting data is only supported if the current selection contains a single topic with a single message type.
To see the data contained within the time series, access the Data
property:
ts.Data
ans = 101×2
0.0003 0.0003
0.0003 0.0003
0.0003 -0.0006
0.0003 -0.0006
0.0003 -0.0010
0.0003 -0.0010
0.0003 -0.0003
0.0003 -0.0003
0.0003 -0.0003
0.0003 -0.0003
⋮
There are many other possible ways to work with the time series data. Calculate the mean of the data columns:
mean(ts)
ans = 1×2
10-3 ×
0.3213 -0.4616
You can also plot the data of the time series:
figure
plot(ts,"LineWidth",3)