rosbag的使用

bag文件包含tf信息和话题消息,没有rosparam参数和node。 /clock是由ROS的录包回放系统rosbag发布的主题,主要是提供一个仿真时间

rosbag本质也是个ROS节点,whereis rosbag的结果: /opt/ros/kinetic/bin/rosbag,运行rosbag play会出现一个play开头的节点,后面是当前的utc时间

rosbag record

基本使用:rosbag record topic,可以有多个话题:rosbag record topic1 topic2 topic3,话题可以用shell脚本列出来,例如: rosbag record rostopic list | grep plan

常用方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-o: 在文件名之前加指定的字符串, rosbag record -o test topic ,结果生成文件test_2019-06-24-14-32-08.bag

-node: 记录某节点订阅的所有话题,` rosbag record --node=/joy_teleop

-l: 只记录指定数量的消息, rosbag record -l 1000 /chatter,只记录1000条

--duration: 保持一定时间记录话题, rosbag record ---duration=30 /chatter, 即记录30秒,还可以有5m, 2h
rosbag record --split --duration=30 /chatter #持续时间到30s后分文件存储

-O: 大写O,指定完整文件名 rosbag record -O sess.bag /topic

--size: 指定文件大小,rosbag record --split --size=1024 /chatter #空间达到1024M后分文件存储

-e, -x: 用于正则表达式

我最常用的是rosbag record topic -o filename

rosbag info

显示指定bag文件的详细信息,rosbag info session*.bag

rosbag play

rosplay其实是重现话题数据传输的效果,比如向话题cmd_vel发数据的过程

rosbag回放过程中按空格暂停。默认模式下,rosbag play命令在公告每条消息后会等待0.2秒才真正开始发布bag文件中的消息。如果rosbag play在公告消息后立即发布,订阅器可能会接收不到几条最先发布的消息

如果同时回放两个单独的bag文件,则根据时间戳的间隔来播放。比如我先录制一个bag1,等待一个小时,然后录制另一个 bag2,在一起回放 bag1 和 bag2 时,实际是先回放bag1,然后等待1个小时才回放bag2

等待时间可以通过-d选项来指定,比如等待10秒再播放bag: rosbag play -d 10 realsense.bag

以暂停的方式启动,防止跑掉数据:

1
rosbag play --pause record.bag

要一帧一帧播放的效果,先用暂停方式启动,然后按S键,这个用的还比较少

设置以0.5倍速回放,也就是以录制频率的一半回放。可以加倍播放,但会增大CPU占用。

1
rosbag play -r 0.5 record.bag

循环播放:

1
rosbag play -l record.bag

use_sim_time的问题

播放bag时,运行算法程序,结果报警:

1
2
3
Warning: TF_OLD_DATA ignoring data from the past for frame base_footprint at time 1.59524e+09 according to authority unknown_publisher
Possible reasons are listed at http://wiki.ros.org/tf/Errors%20explained
at line 277 in /tmp/binarydeb/ros-kinetic-tf2-0.5.20/src/buffer_core.cpp

在其他节点之前运行rosbag play --clock ...,会设置好use_sim_time

--clock选项会让 rosbag play发布和订阅bag文件中的消息到/clock话题,这样会让你的其他节点运行在消息发布的时候。 如果use_sim_time是 true, /clock需要消息

这样一来launch文件里加入rosparam set use_sim_time true就不合适了,launch里常常不加入 rosbag play,即使加入了,也不一定先设置了use_sim_time,合适的执行顺序如下:

  1. 启动ROS,但是不包含你需要启动的节点
  2. rosparam set use_sim_time true
  3. 启动你需要的节点
  4. rosbag play —clock

有的资料说不用--clock才能正常,我估计这是数据集的问题,一般还是要有的

filter

可以实现对已有rosbag文件中的某些topic去除或者保留

1
rosbag filter input.bag output.bag 'topic == "/camera/image_raw/compressed" or topic == "/scan" or topic == "/timetag" or  topic == "/tf" and m.transforms[0].header.frame_id != "/odom" and m.transforms[0].child_frame_id != "/odom"'

结果是保留话题/camera/image_raw/compressed , /scan, /timetag, /tf。但是tf变换的frame_idchild_frame_id不是odom,这样的tf消息会被过滤

参考: How to remove a TF from a ROS bag

bag文件转txt csv

将file_name.bag文件中topic_name话题的消息转换到 file.txt文件中:

1
rostopic echo -b file.bag -p /topic_name > file.txt

-p 只能指定一个话题

rosbag可以直接转csv文件,用excel打开,跟转txt一样的

rosbag compress

如果录制的bag很大,我们可以压缩它,默认的压缩格式是bz2:

1
2
3
4
5
6
7
8
rosbag compress xxx.bag
# 可以添加`-j`手动指定压缩格式为bz2
rosbag compress -j xxx.bag
# 也可以使用LZ4来压缩数据
rosbag compress --lz4 xxx.bag

# 解压缩
rosbag decompress xxx.bag

实例

我们常常使用rosbag record命令录制机器人的建图或行走过程,一般先运行record命令,然后开始机器人的路径规划和行走,到达目标点后,在record命令的终端直接ctrl+C就可以保存bag文件.

这里涉及到一个时间戳的问题, bag文件的时间而非本机时间,在默认情况下,ROS使用ubuntu系统的时间,也就是wall clock time.但bag文件中记录的是历史时间,所以play之前要告诉ROS启用simulated time

1
rosparam set use_sim_time true

然后使用rosbag play --clock test.bag命令播放,当然要先打开rviz,添加对应的topic:

play结束之后,还要把参数还原:

1
rosparam set use_sim_time false

这样可以在rviz中离线分析问题了, 大大提升了效率

问题

我之前根据make_plan服务生成了路径,存放在bag文件里,在我使用rosbag play这些文件时,出现了报错:

不管怎么检查,文件命名也没有问题,不得其解。

使用rosbag info查看其信息,发现起始和终止时间相同,只有1个message。因为make_plan服务生成路径只是运行了一次回调函数,所以只有一个message,即使能在rviz显示,也只有几微妙的一瞬间,没什么意义

读取bag的大小不一致

录制bag包后可能没有正确结束掉程序,回放出现错误:

1
2
[ INFO] [1603677455.288200829]: Opening fuse_2020-10-24-18-01-07.bag
[FATAL] [1603677455.288476478]: Error reading from file: wanted 4 bytes, read 0 bytes

可使用如下命令修复:rosbag reindex xxx-xxx-xxx.bag

play时error reading version line

rosbag可能已损坏,你可以使用rosbag info XX.bag查看你想要读取的rosbag包的信息,如果无法读取到有效信息,说明该rosbag确实已损坏。