ROS2学习笔记(十一)-- ROS2 bag数据记录与回放

2023-05-16

        简介:ROS2提供了ros2 bag命令,可以记录指定主题的数据到文件中,也可以将记录下的内容再发布出来,相当于是数据的回放,除了通过命令行的方式实现数据记录以外,也可以通过编程实现主题数据记录以及而合成的主题数据记录


目录

1、ros2 bag命令行工具

1.1 ros2 bag record

1.2 ros2 bag info

1.3 ros2 bag play

2、ros2 bag record 编程实现

2.1 先实现基础的发布订阅功能

2.2 从节点中记录主题数据包

2.3 从节点中记录合成数据包

2.4 从可执行文件记录合成数据


1、ros2 bag命令行工具

1.1 ros2 bag record

命令功能:记录指定主题消息,消息数据包可通过play命令回放

命令格式:

ros2 bag record <topic_name> 记录单个主题消息

ros2 bag record -o <file_name> <topic_name_1> <topic_name_2>...<topic_name_n> 记录多个主题消息

ros2 bag record -a 记录系统内所有主题消息

启动所有节点,新开终端,创建新目录,查看主题列表,记录/ros2_robot/duckiebot_node/image主题消息

$ mkdir bag
$ cd bag
$ ros2 topic list
$ ros2 bag record /ros2_robot/duckiebot_node/image

        可以看到当前目录下创建了一个以rosbag2+时间戳的目录,目录下有一个metadata.yaml文件,内容是数据记录的相关信息介绍,另外一个db3格式文件,就是我们记录下来的主题数据。

$ ros2 bag record -o subset /ros2_robot/duckiebot_node/image /ros2_robot/control_node/action

$ ros2 bag record -a

1.2 ros2 bag info

命令功能:查看主题数据记录文件信息

命令格式:ros2 bag info <file_dir_name>

我们可以用之前的3各记录命令生成的数据文件来测试:

1.3 ros2 bag play

命令功能:回放记录下来的主题数据,可通过ros2 topic echo查看回放数据,也可以通过rqt工具查看

命令格式:ros2 bag play <file_dir_name>

例如:ros2 bag play subset

注:如果记录的主题数据有自定义消息,则需要配置环境变量。

2、ros2 bag record 编程实现

        上文介绍了ros2 bag的命令行操作,而主题数据记录也可以通过编程实现。为了不与之前的功能冲突,我们新建一个功能包来实现编程记录主题数据包。

2.1 先实现基础的发布订阅功能

        新建功能包ros2_bag,并创建两个节点image_pub和image_sub:

$ cd ~/ros2_ws/src
$ ros2 pkg create ros2_bag --build-type ament_python --dependencies rclpy rosbag2_py sensor_msgs

        在ros2_bag目录下新建image_pub.py和image_sub.py

        编辑image_pub.py,实现图像发布功能:

#!/usr/bin/env python3

import rclpy
from rclpy.node import Node
import gym
from pyglet.window import key
from gym_duckietown.envs import DuckietownEnv
import cv2
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
 
class ImagePub(Node):
 
    def __init__(self, name):
        super().__init__(name)
        self.env = DuckietownEnv(seed=1,map_name="udem1",draw_curve=False,draw_bbox=False,domain_rand=False,frame_skip=1,distortion=False,camera_rand=False,dynamics_rand=False)
        self.env.reset()
        self.pub_img = self.create_publisher(Image,"duckiebot_node/image",10)
        self.timer = self.create_timer(0.05, self.timer_callback)
        self.bridge = CvBridge()
    
    def timer_callback(self):
        action = self.env.action_space.sample()
        obs, reward, done, info = self.env.step(action)
        self.pub_img.publish(self.bridge.cv2_to_imgmsg(obs, 'rgb8'))
        if done:
            self.env.reset()
 
def main(args=None):
    rclpy.init(args=args)
    node = ImagePub(name="image_pub")
    rclpy.spin(node=node)
    rclpy.shutdown()

        编辑image_sub.py,实现图像订阅显示功能:

#!/usr/bin/env python3

import rclpy
from rclpy.node import Node
import cv2
import numpy as np
from sensor_msgs.msg import Image 
from cv_bridge import CvBridge

class ImageSub(Node):
    
    def __init__(self,name):
        super().__init__(name)
        self.sub_img = self.create_subscription(Image, "duckiebot_node/image", self.cb_image, 10)
        self.bridge = CvBridge()
    
    def cb_image(self,imgmsg):
        image = self.bridge.imgmsg_to_cv2(imgmsg, 'bgr8')
        cv2.imshow("image", image)
        cv2.waitKey(1)       
    
    
def main(args=None):
    rclpy.init(args=args)
    node = ImageSub(name="image_sub")
    rclpy.spin(node=node)
    rclpy.shutdown()

        修改setup.py,添加启动入口点配置:

entry_points={
        'console_scripts': [
            'image_pub = ros2_bag.image_pub:main',
            'image_sub = ros2_bag.image_sub:main',
        ],
    },

        返回工作空间,编译、配置并启动两个节点:

$ cd ~/ros2_ws
$ colcon build --packages-select ros2_bag
$ source install/setup.bash
$ ros2 run ros2_bag image_pub
$ ros2 run ros2_bag image_sub

2.2 从节点中记录主题数据包

        修改image_sub节点:

#!/usr/bin/env python3

import rclpy
from rclpy.node import Node
import cv2
import numpy as np
from sensor_msgs.msg import Image 
from cv_bridge import CvBridge

#引入rosbag2_py包,用于处理bag文件所需的函数和结构
from rclpy.serialization import serialize_message
import rosbag2_py

class ImageSub(Node):
    
    def __init__(self,name):
        super().__init__(name)
        self.sub_img = self.create_subscription(Image, "duckiebot_node/image", self.cb_image, 10)
        self.bridge = CvBridge()
        #首先创建将用于写入包的writer对象,类型是SequentialWriter,它将按照收到的顺序将消息写入包中
        self.writer = rosbag2_py.SequentialWriter()
        
        #指定要创建的包的URI和格式(sqlite3),其他选项保持默认值。
        storage_options = rosbag2_py._storage.StorageOptions(
            uri='my_bag',
            storage_id='sqlite3')
        #使用默认的转换选项,该选项将不执行转换,并以接收消息时使用的序列化格式存储消息。
        converter_options = rosbag2_py._storage.ConverterOptions('', '')
        #用writer对象以设定的配置打开包
        self.writer.open(storage_options, converter_options)
        #设置我们希望存储的主题,通过创建一个TopicMetadata对象并将其注册到编写器来完成。
        #指定此对象指定主题名称、主题数据类型和使用的序列化格式。
        topic_info = rosbag2_py._storage.TopicMetadata(
            name='duckiebot_node/image',
            type='sensor_msgs/msg/Image',
            serialization_format='cdr')
        self.writer.create_topic(topic_info)
    
    def cb_image(self,imgmsg):
        image = self.bridge.imgmsg_to_cv2(imgmsg, 'bgr8')
        cv2.imshow("image", image)
        cv2.waitKey(1)     
        #调用serialize_message()序列化消息并将结果传递给writer写入数据包中
        self.writer.write('duckiebot_node/image', serialize_message(imgmsg), self.get_clock().now().nanoseconds)  
    
    
def main(args=None):
    rclpy.init(args=args)
    node = ImageSub(name="image_sub")
    rclpy.spin(node=node)
    rclpy.shutdown()

        先启动image_pub节点,再启动image_sub节点

        image_sub节点需要rosbag2_py函数库,如果没有安装,提示No module named 'rosbag2_py',需要先进行安装:

$ sudo apt install ros-rolling-rosbag2
$ source /opt/ros/rolling/setup.bash

        然后再运行image_sub节点,运行一段时间后停止节点,在当前目录下就有了my_bag目录

        可以看到目录下的文件格式,与通过命令行方式生成的主题数据包相同,ros2 bag info查看信息,也可以通过ros2 bag play回放主题数据。

        注1:rosbag2_py函数库默认可能没有安装,安装后需要执行source /opt/ros/rolling/setup.bash 才能正常使用,每次开启新终端都需要执行,也可以直接写入~/.bashrc中,下面两个例程会有同样的问题。

        注2:编码时写死了生成的数据包名称,程序不会自动覆盖,重复运行时会报文件已存在错误,所以每次重复执行,都需要删除之前生成的数据包文件,下面两个例程会有同样的问题。

2.3 从节点中记录合成数据包

        除了从主题订阅进行数据记录以外,也可以在数据发布之前直接存储,我们修改image_pub节点来实现:

#!/usr/bin/env python3

import rclpy
from rclpy.node import Node
import gym
from pyglet.window import key
from gym_duckietown.envs import DuckietownEnv
import cv2
from sensor_msgs.msg import Image
from cv_bridge import CvBridge

import rosbag2_py
from rclpy.serialization import serialize_message
 
class ImagePub(Node):
 
    def __init__(self, name):
        super().__init__(name)
        self.env = DuckietownEnv(seed=1,map_name="udem1",draw_curve=False,draw_bbox=False,domain_rand=False,frame_skip=1,distortion=False,camera_rand=False,dynamics_rand=False)
        self.env.reset()
        self.pub_img = self.create_publisher(Image,"duckiebot_node/image",10)
        self.timer = self.create_timer(0.05, self.timer_callback)
        self.bridge = CvBridge()
        
        self.writer = rosbag2_py.SequentialWriter()
        storage_options = rosbag2_py._storage.StorageOptions(
            uri='my_bag1',
            storage_id='sqlite3')
        converter_options = rosbag2_py._storage.ConverterOptions('', '')
        self.writer.open(storage_options, converter_options)
        topic_info = rosbag2_py._storage.TopicMetadata(
            name='duckiebot_node/image',
            type='sensor_msgs/msg/Image',
            serialization_format='cdr')
        self.writer.create_topic(topic_info)
    
    def timer_callback(self):
        action = self.env.action_space.sample()
        obs, reward, done, info = self.env.step(action)
    	imgmsg = self.bridge.cv2_to_imgmsg(obs, 'rgb8')
        self.pub_img.publish(imgmsg)
        self.writer.write('duckiebot_node/image', serialize_message(imgmsg), self.get_clock().now().nanoseconds)
        if done:
            self.env.reset()
 
def main(args=None):
    rclpy.init(args=args)
    node = ImagePub(name="image_pub")
    rclpy.spin(node=node)
    rclpy.shutdown()

        与从主题订阅存储类似,只是在发布之前就把数据进行存储,重新编译并运行image_pub一段时间后停止节点,在当前目录下生成my_bag1目录,可以使用ros2 bag play回放:

2.4 从可执行文件记录合成数据

        在ros2_bag源码目录下新建action.py,编辑内容如下:

#!/usr/bin/env python3

from rclpy.clock import Clock
from rclpy.duration import Duration
from rclpy.serialization import serialize_message
from duckietown_interface.msg import Twist2D

import rosbag2_py

def main(args=None):
    writer = rosbag2_py.SequentialWriter()

    storage_options = rosbag2_py._storage.StorageOptions(
        uri='my_bag2',
        storage_id='sqlite3')
    converter_options = rosbag2_py._storage.ConverterOptions('', '')
    writer.open(storage_options, converter_options)

    topic_info = rosbag2_py._storage.TopicMetadata(
        name='action',
        type='duckietown_interface/msg/Twist2D',
        serialization_format='cdr')
    writer.create_topic(topic_info)

    time_stamp = Clock().now()
    for ii in range(0, 100):
        data = Twist2D
        data.v = 0.3
        data.omage = 0.2
        writer.write(
            'action',
            serialize_message(data),
            time_stamp.nanoseconds)
        time_stamp += Duration(seconds=1)

if __name__ == '__main__':
    main()

        在setup.py中添加入口配置:

'simple_action = ros2_bag.action:main',

        返回工作空间编译配置并运行simple_action:

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ROS2学习笔记(十一)-- ROS2 bag数据记录与回放 的相关文章

  • ubuntu开启SSH服务远程登录

    ssh secure shell xff0c 提供安全的远程登录 从事嵌入式开发搭建linux开发环境中 xff0c ssh的服务的安装是其中必不可少的一步 ssh方便一个开发小组中人员登录一台服务器 xff0c 从事代码的编写 编译 运行
  • Python实现让视频自动打码,再也不怕出现少儿不宜的画面了

    人生苦短 我用Python 序言准备工作代码解析完整代码 序言 我们在观看视频的时候 xff0c 有时候会出现一些奇怪的马赛克 xff0c 影响我们的观影体验 xff0c 那么这些马赛克是如何精确的加上去的呢 xff1f 本次我们就来用Py
  • Docker安装nextcloud实验

    Docker安装nextcloud实验 修改验证方式 xff1a 从密钥到密码 sudo passwd root su root vi etc ssh sshd config 去掉下面前的 或修改yes no port 22 Address
  • Tesseract-OCR 字符识别---样本训练

    Tesseract是一个开源的OCR xff08 Optical Character Recognition xff0c 光学字符识别 xff09 引擎 xff0c 可以识别多种格式的图像文件并将其转换成文本 xff0c 目前已支持60多种
  • FPGA与OPENCV的联合仿真

    对于初学者来说 xff0c 图像处理行业 xff0c 最佳仿真方式 xff1a FPGA 43 OPENCV xff0c 因为OPENCV适合商业化 xff0c 适合自己写算法 1 xff09 中间交互数据介质 txt文档 2 xff09
  • 华硕P8Z77-V LX老主板转换卡升级NVMe M2硬盘经验,老主机的福音,质的飞跃

    每年双十一都是淘货升级老家伙的时候 xff0c 今年也不例外 xff0c 随着日子长久 xff0c 软件的增多 xff0c 虽然已经尽量装在系统盘以外的盘 xff0c 但C盘还是日渐不够用 xff0c 从以前的30G系统盘升到60G xff
  • linux 更换 软件源后 GPG错误

    linux 更换 软件源后 GPG错误 linux 软件源 GPG 签名 密钥 linux 更换 软件源后 GPG错误 http my oschina net emptytimespace blog 83633 如文章 1 中提到 xff1
  • ROS2学习笔记(四)-- 用方向键控制小车行走

    简介 xff1a 在上一节的内容中 xff0c 我们通过ROS2的话题发布功能将小车实时视频信息发布了出来 xff0c 同时使用GUI工具进行查看 xff0c 在这一节内容中 xff0c 我们学习一下如何订阅话题并处理话题消息 xff0c
  • flume大数据框架数据采集系统

    flume是cloudera开源的数据采集系统 xff0c 现在是apache基金会下的子项目 xff0c 他是hadoop生态系统的日志采集系统 xff0c 用途广泛 xff0c 可以将日志 网络数据 kafka消息收集并存储在大数据hd
  • flume日志收集系统常见配置

    前面介绍了flume入门实例 xff0c 介绍了配置netcat信源 xff0c 以及memory信道 xff0c logger信宿 xff0c 其实flume常见的信源信道信宿有很多 xff0c 这里介绍flume常用信源的三种方式 xf
  • flume自定义拦截器实现定制收集日志需求

    flume默认提供了timestamp host static regex等几种类型的拦截器 xff0c timestamp host static等拦截器 xff0c 其实就是在消息头中增加了时间戳 xff0c 主机名 xff0c 键值对
  • Eclipse开发mapreduce程序环境搭建

    Eclipse作为一个常用的java IDE xff0c 其使用程度虽然比不上idea那么强大 xff0c 但是对于习惯使用eclipse开发的人来说 xff0c 也不失为一个可以选择的IDE 对于喜欢eclipse开发的人来说 xff0c
  • hdfs常见操作java示例

    我们学习hadoop xff0c 最常见的编程是编写mapreduce程序 xff0c 但是 xff0c 有时候我们也会利用java程序做一些常见的hdfs操作 比如删除一个目录 xff0c 新建一个文件 xff0c 从本地上传一个文件到h
  • MapReduce编程开发之数据去重

    MapReduce就是一个利用分而治之的思想做计算的框架 xff0c 所谓分 xff0c 就是将数据打散 xff0c 分成可以计算的小份 xff0c 治就是将数据合并 xff0c 相同键的数据合并成一个集合 MapReduce并不能解决所有
  • MapReduce编程开发之求平均成绩

    MapReduce计算平均成绩是一个常见的算法 xff0c 本省思路很简单 xff0c 就是将每个人的成绩汇总 xff0c 然后做除法 xff0c 在map阶段 xff0c 是直接将姓名做key 分数作为value输出 在shuffle阶段
  • MapReduce编程开发之数据排序

    MapReduce的数据排序 xff0c 其实没有很复杂的实现 xff0c 默认在shuffle阶段 xff0c MapReduce就帮我们将数据排好序了 xff0c 我们在Map和Reduce阶段 xff0c 无需做额外的操作 MapRe
  • MapReduce编程开发之倒排索引

    倒排索引是词频统计的一个变种 xff0c 其实也是做一个词频统计 xff0c 不过这个词频统计需要加上文件的名称 倒排索引被广泛用来做全文检索 倒排索引最终的结果是一个单词在文件中出现的次数的集合 xff0c 以下面的数据为例 xff1a
  • ROS2学习笔记(五)-- ROS2命令行操作常用指令总结(一)

    简介 xff1a 在前面的章节中 xff0c 我们先简单学习了ROS2的话题发布和订阅 xff0c 两种操作都是通过python代码实现的 xff0c 而在实际应用过程中 xff0c 我们会经常用到命令行操作来辅助调试 xff0c 更进一步
  • 实例演示ElasticSearch索引查询term,match,match_phase,query_string之间的区别

    通常在面试elasticsearch中 xff0c 面试官会问一个关于查询的问题 xff0c 就是term查询和match查询有什么区别 xff1f 如果你对这两个查询不清楚 xff0c 面试官会认为你没有用过elasticsearch x
  • Elasticsearch使用update_by_query

    elasticsearch中有一个方法是批量修改 xff0c 就是先查询出需要修改的索引记录 xff0c 然后批量修改 这个本来没什么 xff0c 但是使用过的都知道 xff0c 用java来调用这个方法很别扭 一般来说 xff0c 我们使

随机推荐

  • C++中实现字符串分隔split方法

    C 43 43 中 xff0c 除了没有直接的求数组长度的方法外 xff0c 也没有直接对字符串分隔的方法 xff0c 需要我们自己来实现 xff0c 下面结合字符串分隔的问题 xff0c 做一个面试题 xff0c 面试题是这样的 xff0
  • c++编程实现简单mapreduce程序

    hadoop提供了java版本的mapreduce编程API xff0c 我们需要自定义编写mapper和reducer xff0c 分别继承Mapper和Reducer xff0c 然后重写map和reduce方法 同时需要在main方法
  • windows下安装MongoDB压缩版

    MongoDB在windows上一般提供msi的安装方式 xff0c 这种安装方式相对简单 xff0c 界面安装 xff0c 这里介绍解压缩版本的安装 xff0c 我们需要下载的是zip包 xff0c 然后解压 xff0c 这里下载之后 x
  • python3安装以及安装pip之后出现的问题

    python3在windows10上的安装 xff0c 为了省事 xff0c 直接下载的是python 3 7 4 embed adm64 zip免安装版本 xff0c 下载解压 xff0c 然后将python目录加入环境变量的path中
  • eclipse安装pydev插件开发python程序

    做Java开发的 xff0c 想学习python xff0c 可以不用安装别的pycharm IDE xff0c 我们直接通过在eclipse中安装一个python插件pydev即可 xff0c 前提是你的机器上已经安装了python xf
  • docker私有镜像服务搭建

    docker容器技术已经在部署服务上使用的非常普遍 xff0c 主要是它的隔离性以及快速启动的特性 xff0c 一般启动一个容器 xff0c 如果镜像不存在会先去dockerhub仓库下载 xff0c 然后存储在本地 xff0c 后续可以继
  • vs2017开发第一个desktop应用程序

    desktop应用程序也叫窗口程序 xff0c 我们平时在电脑上安装的APP xff0c 都是桌面程序 xff0c 比如QQ xff0c 各种播放器 xff0c 包括浏览器 桌面程序最主要的特点 xff0c 就是点击运行之后 xff0c 会
  • 量子编程入门第一篇环境搭建dotnet-sdk+Microsoft.Quantum.IQSharp+python3.6+qsharp

    量子编程已经提上日程 xff0c 微软提供了quantum开发工具包 Microsoft Quantum Development Kit简称QDK xff0c 在visual studio 2019环境下 xff0c 可以安装quantum
  • ROS2学习笔记(十)-- ROS2 launch启动文件

    简介 xff1a 接触过ROS1的同学对launch肯定不陌生 xff0c 在ROS1中 xff0c 我们常用launch实现node和master同时启动 多节点同时启动配置等功能 xff0c ROS2中的launch也是用于多节点启动
  • 记录一次解决TypeError: 'NoneType' object is not callable的办法

    如题所示 xff0c 这是python运行时报错 xff0c 关键信息就是 xff1a TypeError 39 NoneType 39 object is not callable xff0c 错误栈信息如下 xff1a 有的文章提示 x
  • windows下VC++6.0编写c++程序连接mysql示例

    windows下通过c 43 43 编码连接mysql数据库 xff0c 需要做一些设置 xff0c 因为我们需要连接mysql并执行相关操作 xff0c 需要使用mysql提供的api xff0c 这api在mysql h头文件中定义了
  • windows修改cmd命令行字体

    默认情况下 xff0c windows命令行字体只有两种 xff0c 点阵字体和新宋体 如果你想使用系统自带的其他字体 xff0c 需要更改注册表 这里介绍如何修改 windows系统字体在目录C Windows Fonts 下 xff0c
  • centos7安装与配置DNS服务器

    centos7上安装DNS服务器可以实现域名与IP的双向解析 xff0c 即通过域名可以找到主机IP xff0c 也可以通过IP找到域名 在postfix搭建邮件服务器中 xff0c 需要用到DNS正向解析与反向解析 xff0c 因此DNS
  • springboot项目单元测试

    springboot项目和普通的spring项目一样也可以做单元测试 xff0c 一般是测试service层的方法 xff0c 在进行项目构建的时候 xff0c 需要在springboot默认依赖的基础上 xff0c 再加上spring b
  • ipfs星际文件系统初体验

    ipfs是InterPlanetary File System的简称 xff0c 即星际文件系统 xff0c 他不同于一般的操作系统文件系统 xff0c 也不同于分布式文件系统 xff0c 因为分布式文件系统最终访问文件还是采用的http协
  • truffle构建以太坊应用并测试第一个helloworld智能合约

    最近因为国家对区块链又重视起来了 xff0c 相信今年年底到明年年初会是一个区块链的新的爆发点 xff0c 也是碰巧学习了一下以太坊构建区块链应用 xff0c 以前都是简单的了解 xff0c 并没有实际动手演练 今天趁机会也学习一下区块链
  • docker启动报错:standard_init_linux.go:211: exec user process caused "no such file or directory"

    如题所示 xff0c 根据自己构建的镜像启动docker容器 xff0c 直接退出 xff0c 查看容器日志报错信息 xff0c 没有任何别的信息 网上搜索这个问题 xff0c 发现很多人都遇到过 xff0c 解决办法也各不相同 xff0c
  • windows下telnet回显解决办法

    telnet相信大家都用过 xff0c 在tcp连接中 xff0c 我们可以用来模拟发送客户端请求 xff0c 当我们输入telnet 127 0 0 1 8888连接本机的tcp 8888端口时 xff0c 连接成功后 xff0c 会进入
  • springboot与flyway集成做数据迁移

    flyway是一种用来做数据迁移的框架 xff0c 如果你的项目不是jpa 43 hibenate xff0c 比如使用的mybatis xff0c 那么你需要在实体创建之前 xff0c 在数据库中生成表结构 xff0c 然后逆向工程 xf
  • ROS2学习笔记(十一)-- ROS2 bag数据记录与回放

    简介 xff1a ROS2提供了ros2 bag命令 xff0c 可以记录指定主题的数据到文件中 xff0c 也可以将记录下的内容再发布出来 xff0c 相当于是数据的回放 xff0c 除了通过命令行的方式实现数据记录以外 xff0c 也可