1. rosbag 命令行
rosbag
ros wiki:rosbagCommandline
在 ROS 系统中,可以使用 bag 文件来保存和恢复系统的运行状态,比如录制雷达和相机话题的 bag 包,然后回放进行数据处理。
rosbag 目前常用的命令如下:
- 录制:
rosbag record
将指定话题录制到一个 bag 文件。
# 录制完保存 bag 包名称为 session1 + 时间戳.bag 格式:
rosbag record -o session1 <topic_names>
# 录制完保存为指定文件名session2.bag:
rosbag record -O session2.bag <topic_names>
- 播放
rosbag play
rosbag play 读取一个或多个 bag 文件的内容,并以时间同步的方式回放,时间同步基于接收消息的全局时间戳。回放开始后,会根据相对偏移时间发布消息。
比如我先录制一个 bag1 包,等待一个小时,然后录制另一个 bag2 包,那我在一起回放 bag1 和 bag2 时,会先回放 bag1,然后等待 1 个小时才能回放 bag2。
# 在回放过程中按空格暂停,常见用法如下,回放单个 bag:
rosbag play record.bag
# 回放多个 bag,基于全局时间间隔播放:
rosbag play record1.bag record2.bag
#以录制的一半频率回放:
rosbag play -r 0.5 --pause record.bag
# 指定回放频率,默认 100HZ:
rosbag play --clock --hz=200 record.bag
# 循环播放:
rosbag play -l record.bag
- 压缩:
rosbag compress
# 指定压缩格式为 lz4,默认的压缩格式是 bz2
rosbag compress --lz4 xxx.bag
# 解压缩
rosbag decompress xxx.bag
- rosbag info
显示包文件内容的可读摘要,包括开始和结束时间,主题及其类型,消息计数、频率以及压缩统计信息。
rosbag info name.bag
# 输出 YAML 格式的信息:
rosbag info -y name.bag
2. rosbag 图像数据解析(python)
rosbag/Code API
python API Documentation
用 Azure-kinect相机,采用如下命令采集了一段rgb 图像和深度图话题的 rosbag。
rosbag record -O image.bag /rgb/image_raw /depth_to_rgb/image_raw
现需要将其解析为 rgb 图像和深度图的灰度图。
参考:
guikunchen/converter-between-rosbag-and-images给出了rosbag 与图像之间的相互转换完整的解决方案。
get_depth_rgb_from_rosbag.py 程序(有改动)如下:
import numpy
import rosbag
import cv2
import os
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
from cv_bridge import CvBridgeError
rgb_path = '/path/to/save/re-edit-bag/rgb/'# absolute path of extracted rgb images
depth_path = '/path/to/save/re-edit-bag/depth/'# absolute path of extracted depth images
bridge = CvBridge()
with rosbag.Bag('/path/to/image.bag', 'r') as bag:
num = 1
for topic,msg,t in bag.read_messages():
if topic == "/depth_to_rgb/image_raw":
cv_image = bridge.imgmsg_to_cv2(msg, '32FC1')
cv_image = cv_image * 255 # 不知为何转化的深度图显示不出来。将其乘以 255 才能看到显示效果.
# timestr = "%.8f" % msg.header.stamp.to_sec() # 时间戳命名
# image_name = timestr + '.png'# an extension is necessary
image_name = str(num) + '.png'# 编号命名
cv2.imwrite(depth_path + image_name, cv_image)
# 实际应用可直接保存为 numpy array
# np.save(depth_path + image_name, cv_image)
print(depth_path + image_name)
if topic == "/rgb/image_raw":
cv_image = bridge.imgmsg_to_cv2(msg, "bgr8")
timestr = "%.8f" % msg.header.stamp.to_sec()
image_name = str(num) + '.png'
cv2.imwrite(rgb_path + image_name, cv_image)
num += 1
正确设置文件路径,运行此代码即可。
注,相机采集的深度图是 32 位的浮点数。经bridge.imgmsg_to_cv2(msg, '32FC1')
转换得到是以米为单位的深度数值。而cv2.imwrite()
写入的则是 0-255 的数值,因此深度值都被取整了,导致直接保存的图片全黑了。显然简单的乘以 255 的处理方法会丢失大量的有效信息。
这个链接一定程度上解决了这个问题。核心代码如下:
# cv_image = self.bridge.imgmsg_to_cv2(msg_depth, "32FC1")
# depth_array = np.array(cv_image, dtype=np.float32)
# "passthrough"表示默认格式,即可得到np.float32,无需np.array语句。
depth_array = self.bridge.imgmsg_to_cv2(depth_data, "passthrough") # 此句等同于前两行
# Normalize the depth image to fall between 0 (black) and 1 (white)
cv2.normalize(depth_array, depth_array, 0, 1, cv2.NORM_MINMAX)
cv2.imwrite("depth.png", depth_array*255)