ROS Bag常用处理脚本

Feb 24,2021   3562 words   13 min

Tags: SLAM

0.背景

前段时间利用D435i采集了很多数据,都是ROS Bag格式,因此对Bag的数据后处理就是一个比较大的问题。比如有时候需要将Bag文件拆解成帧序列影像,或者提取Bag中的某一个Topic,或者改变某个Topic的帧率等等,这些很实际的需求。但是我在网上找了很久似乎并没有发现有什么可以对ROS Bag进行编辑的工具,无奈之下只好花了点时间自己写脚本了。初步测试基本都OK了,可以正常使用,上面提到的几个需求也都可以实现。当然由于写的比较匆忙,所以难免会有考虑不周的地方以及BUG,欢迎指出。所有代码都上传到了Github,方便使用,名字是ROS-Bag-Tools。最后,如果你知道有什么好的Bag编辑工具,欢迎告诉我。

插一句题外话,对于一个Bag,利用rosbag播放后,一般我个人习惯利用rqt_image_view来查看不同的Image Topic(当然有人习惯用RViz)。另外ROS自带了一个叫做rqt_bag的工具,这个工具可以用来在不播放的情况下大致查看Bag的内容,同时可以利用它播放并发布Bag内容。 另外,我们还可以用rqt的Topic Monitor工具来监控Topic的情况,比如实时的帧率等信息。使用方法也非常简单,在终端中输入rqt,然后在菜单栏中选择“Plugins”,再找到“Topics”,再选择“Topic Monitor”即可打开。然后在想要监控的Topic前面打勾,就可以监控实时信息了。 这个功能在检测我们录制的ROS Bag是否符合要求时尤其有用。比如我们设计的录制帧率是30,而实际播放Bag的帧率只有15,那就说明我们录制的这个包有问题了。

1.实现的功能简介

changeBagFramerate.py

将Bag中的指定Topic转换到目标帧率并输出为新的Bag文件。

用法:Input Format: Input_bag_path topic_name1 target_rate1 [topic_name2 target_rate2 … ] Output_bag_path

extractSelectedTopic.py

提取源Bag文件中的指定的Topic到新的Bag文件中。

用法:Input Format: Input_bag_path

parseBag.py

用于提取Bag文件中的Image类型Topic,并输出,包含多种模式:

(1)Output preview video

(2)Output general summary file

(3)Output preview video and general summary file

(4)Output frame images

(5)Output frames of all image topics

(6)Output preview video, summary file, frame images of all topics

(7)Show frame images

Mode 1: 将选择的Image Topic生成一段预览视频

Mode 2: 输出一个包含包起止时间、时长、所有Topic基本信息、Image Topic的帧率、大小、数据类型的文本文件

Mode 3:同时生成预览视频和信息汇总文件

Mode 4:将选择的Image Topic拆解成帧影像

Mode 5:将所有的Image Topic都拆解成帧影像

Mode 6: 同时生成预览视频、信息汇总文件、以及将所有Image Topic拆解成帧影像

Mode 7: 只展示指定Topic

用法:Input Format: Input_bag_path

parseBagAuto.py

用于批量提取Bag文件中的Image类型Topic,并输出,包含多种模式:

(1)Output preview video

(2)Output general summary file

(3)Output preview video and general summary file

(4)Output frames of all image topics

(5)Output preview video, summary file, frame images of all topics

Mode 1: 批量生成预览视频文件

Mode 2: 批量生成汇总信息文件

Mode 3: 同时批量生成预览视频文件和信息汇总文件

Mode 4: 批量将Bag中所有Image Topic拆解成帧影像

Mode 5: 同时批量生成预览视频文件、信息汇总文件,并将Bag中所有Image Topic拆解成帧影像

用法:Input Format: Input_bag_path

2.代码中值得注意的地方

其实,上面介绍了这么多功能,最最核心的就是rosbag这个包了,所有功能都是利用它实现的。它提供了Python的API,更多细节可以参考官网,点击查看

而除了使用的包,从代码实现角度,最需要注意的就是Bag中消息的遍历方式。这里选取一小段代码如下所示,完整代码见Github。

# 以这种方式打开Bag,如果打印对象,就对得到它的汇总信息,可以不用自己写
bag_in = rosbag.Bag(bag_path)

# read_messages()得到的是一个生成器对象
bag_data = bag_in.read_messages()

msg_counter = 0
# 需要注意,这种方式进行遍历,并非是某一个指定的topic个数,而是全部所有topic里面msg的个数
for topic, msg, t in bag_data:
	# 通过topic名称,这样来判断,得到的才是某一个topic的msg个数
	if topic == cur_name:
	    if msg_counter % step == 0:
		print("Iteration "+str(time_counter)+", converted ... "+ str(t.to_sec())+"/"+str(end_timestamp))
		bag_out.write(topic,msg,t)
	    msg_counter += 1
bag_in.close()

消息的遍历是通过生成器实现,而且遍历的时候并非按照Topic顺序来,先把Topic1的内容遍历完再找Topic2,而是混杂在一起。可能当前消息是Topic1,而下一个消息读取到的是Topic2。因此如果想获取某个指定的Topic,就必须要在遍历时根据Topic名称进行筛选。

3.实际测试

这里我们就以实际中常见的几个需求为例进行测试。比如我们拿到了一个ROS Bag,想用它来跑单目ORB-SLAM。

(1) 预览Bag内容

当拿到一个十几甚至几十个GB的Bag时,第一件想做的事就是看看它的内容是什么。我们可以使用parseBag.py的模式3,就可以同时得到一个预览视频以及一个信息汇总文件。 当然,如果再结合很久之前写的视频内容预览工具,还可以实现更方便的内容预览。

(2) 提取Bag中的Topic

在你大致了解了Bag内容以后,你发现你只想要某一个Topic,其它Topic对你来说是多余的。那么你就可以使用extractSelectedTopic.py脚本提取某个或多个Topic。 如上图所示,原始Bag包含了多个Topic,但我只想要彩色影像/camera/color/image_raw这一个Topic。利用脚本提取后,重新输出的Bag就只包含这个Topic了。

(3) 改变Topic帧率

当你提取到了想要的Topic以后,你发现这个Topic的帧率太高了,并不需要30帧,10帧就够了。这个时候你就可以使用changeBagFramerate.py脚本。 如上图所示,可以看到,包的总时长没有变化,但是消息个数从1646变成了549,变成了10帧每秒,达到了你的目的。

(4) Bag文件拆解成序列影像

最后,你忽然发现,你电脑的ROS环境似乎有点问题,ROS版的单目ORB-SLAM跑不起来,只能用普通方式跑ORB-SLAM。无奈,你还需要将Bag文件中的消息导出成序列影像。这时,你可以使用parseBag.py的模式4。 通过脚本,你就可以将Bag文件的消息,转成普通的图片文件了。一波三折,但最终,你也可以顺利跑ORB-SLAM了。

以上便是对ROS Bag处理脚本博客的全部内容了,感兴趣的话可以前往Github项目主页查看源码和更多细节,也欢迎Star或Fork,提出更多宝贵意见。

4.参考资料

  • [1] http://wiki.ros.org/rosbag/Cookbook

本文作者原创,未经许可不得转载,谢谢配合

返回顶部