1.数据集rosbag
1.1 录制所有话题的包
rosbag record -a
1.2 录制指定话题,设置 bag 包名为:bag_name
rosbag record -O bag_name.bag /topic1 /topic2 /xxx
1.3 录制包不设置 包名称,默认按照录制结束时间命名
rosbag record /topic1_name /topic2_name /xxx
例如:录制 topic 为 camera、imu、odom , 名字为 shuju.bag的包
rosbag record /camera/image_raw /imu /odom -O shuju.bag
2、回放
2.1 直接回放
rosbag play shuju.bag
2.2 设置以 0.5 倍速回放,也就是以录制频率的一半回放:
rosbag play -r 0.5 shuju.bag
此时,包内的 信息 以 topic 为 image_raw 、imu、odom不断地发布出来; 例如运行rviz, 选择 bytopic 为 image_raw; 便可以出来图像
3、 显示rosbag详细信息
rosbag info shuju.bag
4、提取bag文件中的数据并保存为csv/txt格式
对于非图片数据,大部分情况下都可用csv文件存储
rostopic echo -b shuju.bag -p /odom > odom.csv
rostopic echo -b shuju.bag -p /odom > odom.txt
5、从 rosbag包里提取图片
5.1提取包里带时间戳的图片数据
①单目 全部代码如下(python):取名为readbag.py
只要第10行、第14行、第16行根据自己的文件名进行更改就行了。
#coding:utf-8
import roslib;
import rosbag
import rospy
import cv2
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
from cv_bridge import CvBridgeError
path='/home/zxy/shu_ju/2021-03-03-15-57-52/image2/' #要存放图片的位置
class ImageCreator():
def __init__(self):
self.bridge = CvBridge()
with rosbag.Bag('MH01.bag', 'r') as bag: #要读取的bag文件;
for topic,msg,t in bag.read_messages():
if topic == "/image_raw": #图像的topic;
try:
cv_image = self.bridge.imgmsg_to_cv2(msg,"bgr8")
except CvBridgeError as e:
print(e)
timestr = "%.6f" % msg.header.stamp.to_sec()
#%.6f表示小数点后带有6位,可根据精确度需要修改;
image_name = timestr+ ".png" #图像命名:时间戳.jpg
cv2.imwrite(path+image_name, cv_image) #保存;
if __name__ == '__main__':
try:
image_creator = ImageCreator()
except rospy.ROSInterruptException:
pass
运行
python readbag.py
②双目
修改17.18.23.25.34行
# coding:utf-8
#!/usr/bin/python
# Extract images from a bag file.
import roslib; #roslib.load_manifest(PKG)
import rosbag
import rospy
import cv2
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
from cv_bridge import CvBridgeError
#Reading bag filename from command line or roslaunch parameter.
#import os
#import sys
cam0_path = '/home/hltt3838/vins/Dates/cam0/' # 已经建立好的存储cam0 文件的目录
cam1_path = '/home/hltt3838/vins/Dates/cam1/'
class ImageCreator():
def __init__(self):
self.bridge = CvBridge()
with rosbag.Bag('MH_01_easy.bag', 'r') as bag: #要读取的bag文件;
for topic,msg,t in bag.read_messages():
if topic == "/cam0/image_raw": #图像的topic;
try:
cv_image = self.bridge.imgmsg_to_cv2(msg,"bgr8")
except CvBridgeError as e:
print (e)
timestr = "%.6f" % msg.header.stamp.to_sec()
#%.6f表示小数点后带有6位,可根据精确度需要修改;
image_name = timestr+ ".jpg" #图像命名:时间戳.jpg
cv2.imwrite(cam0_path + image_name, cv_image) #保存;
elif topic == "/cam1/image_raw": #图像的topic;
try:
cv_image = self.bridge.imgmsg_to_cv2(msg,"bgr8")
except CvBridgeError as e:
print (e)
timestr = "%.6f" % msg.header.stamp.to_sec()
#%.6f表示小数点后带有6位,可根据精确度需要修改;
image_name = timestr+ ".jpg" #图像命名:时间戳.jpg
cv2.imwrite(cam1_path + image_name, cv_image) #保存;
if __name__ == '__main__':
#rospy.init_node(PKG)
try:
image_creator = ImageCreator()
except rospy.ROSInterruptException:
pass
5.2从 ros 的 bag 包里提取不带时间戳的图片数据
全部代码如下(后缀为 “.launch” 的文件):例如:export.launch
只要第2行、第4行根据自己的文件名和文件路径进行更改就行了。
终端1
roscore
终端2
roslaunch export.launch
5.3 从 ros 的 bag 包里提取带时间戳的 PointCloud 格式的点云数据,把提取出来的点云保存为 txt 格式
全部代码如下(python):
只要第9行、第11行、第12行根据自己的文件名和文件路径进行更改就行了。
#!/usr/bin/env python
#coding:utf-8
import sys
import argparse
from fnmatch import fnmatchcase
from rosbag import Bag
import rosbag
bag_file = '2021-03-03-15-57-52.bag'
bag = rosbag.Bag(bag_file, "r")
bag_data = bag.read_messages('/ruby128result')
save_path = "/home/zxy/pcd_result/"
j = 0
for topic, msg, t in bag_data:
timestr = "%.6f" % msg.header.stamp.to_sec()
#print(timestr)
#%.6f表示小数点后带有6位,可根据精确度需要修改;
cloud_name = save_path + timestr+ ".txt" #点云命名:时间戳.txt
with open(cloud_name,"w") as f:
#其中i为索引值,如下直接通过索引取得接收到的数据对象
for i in range(len(msg.points)):
msg.points[i].x;
msg.points[i].y;
msg.points[i].z;
f.writelines([str(msg.points[i].x), ' ', str(msg.points[i].y), ' ', str(msg.points[i].z), '\n']) # 自带文件关闭功能,不需要再写f.close()
if j % 10 == 0:
print('di ', j, ' zhen')
j += 1
#o3d.io.write_point_cloud(pcd_name, pcd)
#o3d.io.write_point_cloud("../../TestData/sync.ply", pcd)
5.4 如何将两个rosbag包合并或者提取rosbag包中某些或某一个话题到一个rosbag里
代码叫做merge_bag.py
运行的时候,命令行输入:
python merge_bag.py -v New_hebing.bag bag1.bag bag2.bag
就是把 bag1.bag 和bag2.bag 完全合并在一起了,合并的新bag包叫 New_hebing.bag,时间戳打的都是原来两个bag里原始的时间戳,而不是像一边rosbag play一边rosbag record一样录的是现在这个时间戳。
命令行输入:
python merge_bag.py -v –topics ‘/aft_mapped_to_init /gnss/data /imu/data vinReNoOutlier’ bag1.bag 2019-10-28-14-40-45.bag bag2.bag
全部代码如下(python):
#!/usr/bin/env python
import sys
import argparse
from fnmatch import fnmatchcase
from rosbag import Bag
def main():
parser = argparse.ArgumentParser(description='Merge one or more bag files with the possibilities of filtering topics.')
parser.add_argument('outputbag',
help='output bag file with topics merged')
parser.add_argument('inputbag', nargs='+',
help='input bag files')
parser.add_argument('-v', '--verbose', action="store_true", default=False,
help='verbose output')
parser.add_argument('-t', '--topics', default="*",
help='string interpreted as a list of topics (wildcards \'*\' and \'?\' allowed) to include in the merged bag file')
args = parser.parse_args()
topics = args.topics.split(' ')
total_included_count = 0
total_skipped_count = 0
if (args.verbose):
print("Writing bag file: " + args.outputbag)
print("Matching topics against patters: '%s'" % ' '.join(topics))
with Bag(args.outputbag, 'w') as o:
for ifile in args.inputbag:
matchedtopics = []
included_count = 0
skipped_count = 0
if (args.verbose):
print("> Reading bag file: " + ifile)
with Bag(ifile, 'r') as ib:
for topic, msg, t in ib:
if any(fnmatchcase(topic, pattern) for pattern in topics):
if not topic in matchedtopics:
matchedtopics.append(topic)
if (args.verbose):
print("Including matched topic '%s'" % topic)
o.write(topic, msg, t)
included_count += 1
if included_count % 10 == 0:
print("Included messages:", included_count)
else:
skipped_count += 1
total_included_count += included_count
total_skipped_count += skipped_count
if (args.verbose):
print("< Included %d messages and skipped %d" % (included_count, skipped_count))
if (args.verbose):
print("Total: Included %d messages and skipped %d" % (total_included_count, total_skipped_count))
if __name__ == "__main__":
main()
6、rosbag测评
evo是一款用于视觉里程计和slam问题的轨迹评估工具。核心功能是能够绘制相机的轨迹,或评估估计轨迹与真值的误差。支持多种数据集的轨迹格式(TUM、KITTI、EuRoC MAV、ROS的bag),同时支持这些数据格式之间进行相互转换。
6.1 将rosbag输出数据
rostopic echo -b bag_name.bag -p /odom > odom.txt
其中/odom为话题名 odom.txt为输出数据文件名
6.2 将bag文件输出保存为tum格式
evo_traj bag bag_name.bag /odom --save_as_tum
绘制
evo_traj tum odom.tum --plot --plot_mode xy
轨迹与地图融合
evo_traj bag bag1.bag --all_topic --plot --plot_mode xy --ros_map_yaml mymap.yaml #融合地图
其中mymap.yaml 参数文件名字需要与地图名字mymap.png一致
evo_traj tum odom.tum --plot --plot_mode xy --ros_map_yaml mymap.yaml
②对比
evo_traj tum KeyFrameTrajectory1.txt KeyFrameTrajectory2.txt --ref=data.tum -p --plot_mode=xz
③ape可视化测评
evo_ape tum KeyFrameTrajectory1.txt KeyFrameTrajectory2.txt -va --plot --plot_mode xz
④绘制MH01
evo_traj tum 1216LSD_ORB_KeyFrameTrajectory.txt --plot --plot_mode xz #二维绘制
evo_traj tum 1216LSD_ORB_KeyFrameTrajectory.txt --plot
参考文献
ROS 中 bag、txt、csv 格式文件的详细转换 和 图片的提取_贵在坚持,不忘初心的博客-CSDN博客_rosbag转txt
从 ros 的 bag 包里提取特定的数据_weixin_44832383的博客-CSDN博客_rosbag数据提取
轨迹评估工具使用总结(二) evo 绘图& ROS map_Techblog of HaoWANG的博客-CSDN博客_evo ros