IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> rosbag录制数据与解包 -> 正文阅读

[Python知识库]rosbag录制数据与解包


一、rosbag录制数据

使用rosbag record命令

rosbag record -O [bag_name] [topic1] [topic2] [...]    #不加中括号

-O大写,后面对录制的bag命名,再之后跟要录制的topic名字(用rostopic list查询当前所有的topic)。

录制结束后,在当前shell所在路径会生成后缀为.bag的数据包,使用rosbag info来查看该数据包的信息

rosbag info [bag_file]    #不加中括号

应该会输出该bag存储的topic名字和帧数,如果报错,说明该包有损坏(常见于U盘拷贝的情况)。正常输出类似于下面这样:
在这里插入图片描述

tips:这里顺便记录一下rostopic的用法
查看当前所有的topic:rostopic list
查看某个topic的输出:rostopic echo [topic_name]
查看某个topic的发布频率:rostopic hz [topic_name]
查看某个topic的数据格式:rostopic echo [topic_name]/encoding

二、bag数据播放

用rosbag play命令

rosbag play [bag_file]    #不加中括号

播放的意思是指将bag所记录的所有内容重新进行了一遍,按空格暂停和继续。播放时可在rviz里add相应的topic进行查看。

三、bag解包出图像数据(两种方式)

参考链接https://www.codeleading.com/article/11362024892/的内容,这里介绍两种解包的方法。

1.ROS Wiki提供的roslaunch文件解包

新建launch文件(文件在哪无所谓) : bag2img.launch

<launch>
  <node pkg="rosbag" type="play" name="rosbag" required="true" args="/home/user/test1.bag"/>
  <node name="extract" pkg="image_view" type="extract_images" respawn="false" required="true" output="screen" cwd="ROS_HOME">
  <remap from="image" to="/zed2/zed_node/depth/depth_registered"/>
  <param name="sec_per_frame" value="0.03"/>
  </node>
 </launch>

args="/home/user/test1.bag"是bag的存放路径,"/zed2/zed_node/depth/depth_registered"是要解析的topic名称。
**< param name=“sec_per_frame” value=“0.03”/>**这句话是说,以每一帧花费0.03s的时间,这个条件对你的bag文件进行图像提取,如果没有这句话,就是默认0.1s,也就是没秒10帧的速率对图像提取。经过我的测试发现,无论怎么调整这个值,都无法跟bag文件中的信息数目匹配,因此来说,这种方法存在一定的图像缺失的情况,只能无限接近袁原始图像的数目,比如我的原始数据有640帧,但经过调整sec_per_frame的值,最高的时候还是只能到639,多数情况下到637,默认值0.1的时候,只有200多张图像。原因是实际录制时相机的帧率不是绝对稳定的,而解析时设置了固定的时间间隔,这个误差会累积下去,帧数越多,最后漏掉的就越多。

运行roslaunch:

roslaunch bag2img.launch

提取成功的图像存储在home文件夹下的.ros文件夹下,一般是隐藏的文件夹,使用crtl+h可显示出来。

优点:操作简单,使用ros即可;缺点:提取信息与原始录制的信息并不完全一致,主要体现在提取的图片数量和ros录制的时候的信息数量不一致,会少。此外,不含有时间戳;

2.python解包

通过编写Python程序按照我们想要的信息及方式来提取,在与bag文件同级目录下建立.py文件(方便操作,若不是同级目录,下面代码中要写绝对路径)

代码如下(示例):

# coding:utf-8
#!/usr/bin/python
     
# Extract images from a bag file.
     
#PKG = 'beginner_tutorials'
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
     
rgb_path = '/home/david/workspace/bags/rgb/'   #已经建立好的存储rgb彩色图文件的目录
depth_path= '/home/david/workspace/bags/depth/' # 已经建立好的存储深度图文件的目录
     
class ImageCreator():
    def __init__(self):
        self.bridge = CvBridge()
        with rosbag.Bag('/home/andy/bag_folder/file_name.bag', 'r') as bag:  #要读取的bag文件;
            for topic,msg,t in bag.read_messages():
                if topic == "camera/rgb/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" #图像命名:时间戳.png
                        cv2.imwrite(rgb_path + image_name, cv_image)  #保存;
                elif topic == "camera/depth_registered/image_raw": #图像的topic;
                        try:
                            cv_image = self.bridge.imgmsg_to_cv2(msg,"16UC1")
                        except CvBridgeError as e:
                            print e
                        timestr = "%.6f" %  msg.header.stamp.to_sec()
                        #%.6f表示小数点后带有6位,可根据精确度需要修改;
                        image_name = timestr+ ".png" #图像命名:时间戳.png
                        cv2.imwrite(depth_path + image_name, cv_image)  #保存;
     
if __name__ == '__main__':
    #rospy.init_node(PKG)
    try:
        image_creator = ImageCreator()
    except rospy.ROSInterruptException:
        pass


上边这段代码是原博客给的,我又根据自己需求改了一份,同时解析双目rgb和深度图,其中深度图的存储格式由默认的uint8改为float(而且我的深度图是32FC1格式的,不是16UC1)
代码如下:

# coding:utf-8
#!/usr/bin/python
     
# Extract images from a bag file.
     
#PKG = 'beginner_tutorials'
import roslib;   #roslib.load_manifest(PKG)
import rosbag
import rospy
import cv2
import sys
import numpy as np
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
 
rgb_path_left = '/home/user/dynamic_data/left/'     
rgb_path_right = '/home/user/dynamic_data/right/'   #已经建立好的存储rgb彩色图文件的目录
depth_path= '/home/user/dynamic_data/depth_pfm/' # 已经建立好的存储深度图文件的目录
     
class ImageCreator():
    def __init__(self):
        self.bridge = CvBridge()
        with rosbag.Bag('/home/user/test1.bag', 'r') as bag:  #要读取的bag文件;
            for topic,msg,t in bag.read_messages():
                if topic == "/zed2/zed_node/left_raw/image_raw_color": #图像的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" #图像命名:时间戳.png
                        cv2.imwrite(rgb_path_left + image_name, cv_image)  #保存;
                elif topic == "/zed2/zed_node/right_raw/image_raw_color": #图像的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" #图像命名:时间戳.png
                        cv2.imwrite(rgb_path_right + image_name, cv_image)  #保存;
                elif topic == "/zed2/zed_node/depth/depth_registered": #图像的topic;
                        try:
                            cv_image = self.bridge.imgmsg_to_cv2(msg,"32FC1")
                        except CvBridgeError as e:
                            print (e)
                        timestr = "%.6f" %  msg.header.stamp.to_sec()
                        #%.6f表示小数点后带有6位,可根据精确度需要修改;
                        image_name = timestr+ ".pfm" #图像命名:时间戳.png
                        # print('image max:',np.max(cv_image))
                        # cv2.imwrite(depth_path + image_name, cv_image)  #保存;
                        write_pfm(depth_path + image_name, cv_image)
 
def write_pfm(path, image, scale=1):
    """Write pfm file.
    Args:
        path (str): pathto file
        image (array): data
        scale (int, optional): Scale. Defaults to 1.
    """

    with open(path, "wb") as file:
        color = None

        if image.dtype.name != "float32":
            raise Exception("Image dtype must be float32.")

        image = np.flipud(image)

        if len(image.shape) == 3 and image.shape[2] == 3:  # color image
            color = True
        elif (
            len(image.shape) == 2 or len(image.shape) == 3 and image.shape[2] == 1
        ):  # greyscale
            color = False
        else:
            raise Exception("Image must have H x W x 3, H x W x 1 or H x W dimensions.")

        file.write("PF\n" if color else "Pf\n".encode())
        file.write("%d %d\n".encode() % (image.shape[1], image.shape[0]))

        endian = image.dtype.byteorder

        if endian == "<" or endian == "=" and sys.byteorder == "little":
            scale = -scale

        file.write("%f\n".encode() % scale)

        image.tofile(file)
        
if __name__ == '__main__':
    #rospy.init_node(PKG)
    try:
        image_creator = ImageCreator()
    except rospy.ROSInterruptException:
        pass

优点:没有信息损失,完全按照你录制的数据完整提取,且具有时间戳。缺点:使用python2,要装一些库,如OpenCV

关于解包这块,问了高手,他们都是自己写的代码订阅某个topic,每收到一个message就做一次输出,避免了官方给的launch文件定时提取造成的漏帧BUG。自己写个也挺好,这玩意复用性还挺强的。


总结

算是记录一下rosbag的一些常见用法,包括录制,播放,解包。
这里还有个链接,里面介绍了rosbag一些更丰富的功能:
http://zhaoxuhui.top/blog/2021/02/24/ros-bag-processing-scripts.html.

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-07-14 10:49:15  更:2021-07-14 10:50:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 0:51:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码