When using ros, rosbag is often used to record or playback algorithms, which is a very useful tool.
List of rosbag commands
Order | effect |
---|---|
record | Record a package and specify a topic |
info | Summarize the details of a package |
play | Play back one or more packages, and you can specify a topic |
check | Determine if a pack is playable on the current system, or if it can be migrated |
fix | Fix a package so that it can be played on the current system |
filter | Convert package content via python script |
compress | Archive |
decompress | Unzip the package |
reindex | Reindex one or more broken packages |
The record command uses
record <topic-names>
# Specify one or more topics to record
$ rosbag record body_status gnss_imu
record -a, --all
# Record all topics
$ rosbag record -a
record -e, --regex
# Record topics that match regular expressions
$ rosbag record -e "/(.*)_log/point"
rocord -p, -publish
# (Melodic new feature) When starting to record a package, publish a topic="begin_write"
$ rosbag record -p
record -x, --exclude
# Exclude topics that match regular expressions when recording
$ rosbag record -e "/(.*)_log/point" -x "(.*)/point"
record -q, --quiet
# Suppress the log output of the specified topic when recording
$ rosbag record -q /body_status
record -d, --duration
# Specify the maximum time for topic recording
$ rosbag record -d 30 /body_status
$ rosbag record -d 3m /body_status
$ rosbag record -d 3h /body_status
record -o, --output-prefix
# Add a prefix before the output package name
$ rosbag record -o output /topic_name /topic_name2
record -O, --output-name
# Specify the output package name
$ rosbag record -O output.bag /topic_name /topic_name2
record --split
# Split packet recording every set time or size
$ rosbag record --split --size=1024 /topic_name
$ rosbag record --split --duration=30 /topic_name
$ rosbag record --split --duration=5m /topic_name
$ rosbag record --split --duration=2h /topic_name
record --max-splits
# (Kinetic new feature) the maximum number of split packets
$ rosbag record --split --max-splits 3 --duration=30 /topic_name
record -b, --buffsize
# Use internal buffer (default: 256MB, 0 for infinite)
$ rosbag record -b 1024 /topic_name
record --chunksize
# Open up a buffer, more advanced than buffsize (default: 768KB, infinite is 0)
$ rosbag record --chunksize=1024 /topic_name
record -l, --limit
# Only record the specified number of messages in the topic
$ rosbag record -l 1000 /topic_name
record --node
# Record all messages subscribed by the specified node
$ rosbag record --node=/node
record -j, --bz2
# Set the recording to be compressed in bz2 format
$ rosbag record -j /topic_name
record --lz4
# Set the recording to be compressed in lz4 format
$ rosbag record --lz4 /topic_name
record --tcpnodelay
# Use TCP_NODELAY to transmit reference data when subscribing to topicsrecord --udp
# Use UDP transport when subscribing to topics
The info command uses
info <bag-files>
# View details of one or more packages
$ rosbag info test.bag
info -y, --yaml
# Output details of one or more packages in yaml format
$ rosbag info -y test.bag
info -k, --key
# View the output in yaml format, the data corresponding to the key value in the package
$ rosbag info -y -k topics test.bag
The play command uses
play <bag_name>
# Play one or more packets
$ rosbag play test.bag
play -p, --prefix
# Prefix all output topics
$ rosbag play -p test test.bag
play -q, --quiet
# suppress console output
$ rosbag play -q test.bag
play -i, --immediate
# Play package does not wait
$ rosbag play -i test.bag
play --pause
# Pause when starting to play a package
$ rosbag play --pause test.bag
play --queue
# Play with the set queue size when playing the package, the default value is 100
$ rosbag play --queue=1000 test.bag
play --clock
# Automatically publish a clocktopic
$ rosbag play --clock test.bag
play --hz
# Publish the clock topic at the specified Hz
$ rosbag play --hz=1 --clock test.bag
play -d, --delay
# Specify the time to delay playback
$ rosbag -d 5 test.bag
play -r, --rate
# Specify playback speed
$ rosbag -r 10 test.bag
play -s, --start
# Specify the start playback time
$ rosbag play -s 5 test.bag
play -u,--duration
# Set playback time
$ rosbag play -u 240 test.bag
play --skip-empty
# Set the time to skip data without messages
$ rosbag play --skip-empty=1 test.bag
play -l, --loop
# Loop
$ rosbag play -l test.bag
play -k, --keep-alive
# Keep active while playing
$ rosbag play -k test.bag
play --try-future-version
# You can open the bag even if you don't know the version number
$ rosbag play --try-future-version test.bag
play --topics
# Specify the corresponding topics to play
$ rosbag play test.bag --topics /topic1 /topic2
play --pause-topics
# When playing back data, pause the specified topics
$ rosbag play test.bag --topics /topic1 /topic2 --pause-topics
play --bags
# Specify multiple bags for playback
$ rosbag play --bags=test.bag
play --wait-for-subscribers
# Wait for each topic to have at least one subscriber before publishingplay --rate-control-topic=
# Watch a given topic, if the last posting time exceeds <Rate Control Max Delay>, wait for that topic to post again before continuing playbackplay --rate-control-max-delay=
# Maximum time difference from <rate control topic> before pausing
The check command uses
check <file>
# Determine if a package is playable on the current system.
$ rosbag check test.bag
check -g, --genrules
# Generate a migration rule file named RULEFILE
$ rosbag check -g diagnostics.bmr test.bag
check -a, --append
# Append to the end of the existing data migration rules file after loading.
$ rosbag check -a -g diagnostics.bmr test.bag
check -n, --noplugins
# Do not load the rules file
$ rosbag check -n test.bag
The fix directive uses
fix <in-bag> <out-bag> [rules.bmr]
# Fix packets using rules file
$ rosbag fix old.bag repaired.bag myrules.bmr
fix -n, --noplugins
# Fix packets without rules files
$ rosbag fix -n old.bag repaired.bag
The filter directive uses
filter <in-bag> <out-bag> <expression>
# Transform the data file using the given Python expression.
$ rosbag filter my.bag only-tf.bag "topic == '/tf'"
The compress command uses
compress <bag-files>
# Use BZ2 format to compress the package
$ rosbag compress *.bag
compress --output-dir=DIR
# Specify the path output file
$ rosbag compress *.bag --output-dir=compressed
compress -f, --force
# force overwrite if package already exists
$ rosbag compress -f *.bag
compress -q, --quiet
# Suppress non-critical information
$ rosbag compress -q *.bag
compress -j, --bz2
# Use bz2 format to compress the package
$ rosbag compress -j *.bag
compress --lz4
# Use the lz4 format to compress the package
$ rosbag compress --lz4 *.bag
The decompress command uses
decompress <bag-files>
# Unzip the package
$ rosbag decompress *.bag
decompress --output-dir=DIR
# Specify the path to decompress
$ rosbag decompress --output-dir=uncompressed *.bag
decompress -f, --force
# force overwrite if package already exists
$ rosbag decompress -f *.bag
decompress -q, --quiet
# Suppress non-critical information
$ rosbag decompress -q *.bag
The reindex command uses
reindex <bag-files>
# fix bad packages
$ rosbag reindex *.bag
reindex --output-dir=DIR
# specify the path
$ rosbag reindex --output-dir=reindexed *.bag
reindex -f, --force
# force overwrite if package already exists
$ rosbag reindex -f *.bag
reindex -q, --quiet
# Suppress non-critical information
$ rosbag reindex -q *.bag
2. Use Python to merge package code
#! /usr/bin/env python3
import os
import time
import argparse
from rosbag import Bag, Compression
def parse_compression(compression):
if compression == "none" or compression == "NONE":
compression = Compression.NONE
elif compression == "bz2":
compression = Compression.BZ2
elif compression == "lz4":
compression = Compression.LZ4
return compression
def get_files_list(arg_input, arg_select):
files = None
if " " in arg_input:
files = arg_input.split(" ")
elif "," in arg_input:
files = arg_input.split(",")
elif os.path.exists(args.input) or "*" in args.input:
rfind_index = arg_input.rfind("/")
dir_path = arg_input[:rfind_index]
files = os.listdir(dir_path)
files.sort() # 名称排序
files = [dir_path + "/" + file for file in files]
if arg_select:
files = select_bags(files)
print("bags list:")
for i in range(len(files)):
print(str(i) + "." + files[i])
return files
def select_bags(files):
for i in range(len(files)):
print(str(i) + "." + files[i])
print("Please input bag numbers to merge. split by , or space", end=":")
s_b = input()
s_b_list = []
if "," in s_b:
s_b_list = s_b.split(",")
elif " " in s_b:
s_b_list = s_b.split(" ")
files = [files[int(x)] for x in s_b_list]
return files
def show_process_bar(total, i, start):
a = "*" * i
b = "." * (total - i)
c = (i / total) * 100
dur = time.perf_counter() - start
print("\r{:^3.0f}%[{}->{}]{:.2f}s".format(c,a,b,dur), end="")
def merge_bags(args):
print("start merge bags.")
compression = parse_compression(args.compression)
print(f"bag's compression mode is {compression}.")
files = get_files_list(args.input, args.select)
with Bag(args.output, "w", compression=compression) as o:
start = time.perf_counter()
for i in range(len(files)):
show_process_bar(len(files), i+1, start)
with Bag(files[i], "r") as ib:
for topic, msg, t in ib:
o.write(topic, msg, t)
show_process_bar(len(files), i+1, start)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Merge one or more bag files to one file.")
parser.add_argument("-o", "--output", help="Output bag's file path.",
default="output.bag", required=True)
parser.add_argument("-i", "--input", help="Input files bags name or path, split by , .",
required=True)
parser.add_argument("-c", "--compression", help="Compress the bag by bz2 or lz4",
default="lz4", choices=["none", "lz4", "bz2"])
parser.add_argument("-s", "--select", help="Select bags to merge.",
default=False)
parser.add_argument("-v", "--verbose", help="Show the verbose msg.")
args = parser.parse_args()
merge_bags(args)