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数据记录与回放 的相关文章

  • 成功解决TypeError: a bytes-like object is required, not 'str'

    解决问题 TypeError a bytes like object is required not 39 str 39 解决思路 问题出在python3 5和Python2 7在套接字返回值解码上有区别 python bytes和str两
  • 计算机网络笔记:字节序与比特序

    1 字节序 所谓字节序是指多字节数据在内存中的存储顺序 xff0c 通常有两种 xff1a 小端字节序 大端字节序 xff1b 小端字节序 xff1a 低位字节存放在低位地址 xff0c 高位字节存放在高位地址 xff1b 大端字节序 xf
  • 全网最全的Postman接口自动化测试!(菜鸟级攻略)

    一 背景 该篇文章针对已经掌握 Postman 基本用法的读者 xff0c 即对接口相关概念有一定了解 已经会使用 Postman 进行模拟请求的操作 当前环境 xff1a Window 7 64Postman 版本 xff08 免费版 x
  • 接口测试之Postman使用全指南(原来使用 Postman测试API接口如此简单)

    Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件 Postman背景介绍 用户在开发或者调试网络程序或者是网页B S模式的程序的时候是需要一些方法来跟踪网页请求的 xff0c 用户可以使用一些网络的监视工具比如
  • 常用Qt类的继承图

  • extern “C”{}的含义及解决的问题

    C 与C 43 43 程序连接问题 它们之间的连接问题主要是因为c c 43 43 编绎器对函数名译码的方式不能所引起的 xff0c 考虑下面两个函数 c int strlen char string c 43 43 int strlen
  • ROS2学习笔记(四)-- 用方向键控制小车行走

    简介 xff1a 在上一节的内容中 xff0c 我们通过ROS2的话题发布功能将小车实时视频信息发布了出来 xff0c 同时使用GUI工具进行查看 xff0c 在这一节内容中 xff0c 我们学习一下如何订阅话题并处理话题消息 xff0c
  • C++实现简单的HTTP客户端(阻塞方式)

    项目中用到的HTTP请求功能 xff0c 自己简单写了个客户端 xff0c 实现了POST方式 xff0c GET方式实现应该也很简单 xff08 空接口已经写好 xff1a 61 xff09 应该支持多线程 xff08 这个很重要 xff
  • WSAWaitForMultipleEvents()

    简述 xff1a 只要指定事件对象中的一个或全部处于有信号状态 xff0c 或者超时间隔到 xff0c 则返回 include lt winsock2 h gt DWORD WSAAPI WSAWaitForMultipleEvents D
  • WSAEnumNetworkEvents()

    WSAEnumNetworkEvents 简述 xff1a 检测所指定的套接口上网络事件的发生 include lt winsock2 h gt int WSAAPI WSAEnumNetworkEvents SOCKET s WSAEVE
  • WSASend()

    WSASend 简述 xff1a 在一个已连接的套接口上发送数据 include lt winsock2 h gt int WSAAPI WSASend SOCKET s LPWSABUF lpBuffers DWORD dwBufferC
  • 临界区

    本文假定您熟悉 Win32 C 43 43 和多线程处理 下载本文的代码 xff1a CriticalSections exe 415KB 摘要 临界区是一种防止多个线程同时执行一个特定代码节的机制 xff0c 这一主题并没有引起太多关注
  • glBegin()用法小结

    glBegin 用法小结 1 在glBegin 和glEnd 之间可调用的函数 函数 函数意义 glVertex 设置顶点坐标 glColor 设置当前颜色 glIndex 设置当前颜色表 glNormal 设置法向坐标 glEvalCoo
  • C++中的显式构造函数

    以两个C 43 43 的小例子来说明怎样通过使用显式构造函数来防止隐式转换 有如下一个简单的复数类 xff1a class ClxComplex public ClxComplex double dReal 61 0 0 double dI
  • 类中的static关键字

    面向对象的static关键字 xff08 类中的static关键字 xff09 1 静态数据成员 在类内数据成员的声明前加上关键字static xff0c 该数据成员就是类内的静态数据成员 先举一个静态数据成员的例子 可以看出 xff0c
  • VS2005 常用快捷键

    2007 04 10 15 32 VS2005 常用快捷键 仁者无敌 2006 08 02 20 20 16 Shift 43 Alt 43 Enter 切换全屏编辑 Ctrl 43 B T Ctrl 43 K K 切换书签开关 Ctrl
  • const

    面向对象是C 43 43 的重要特性 但是c 43 43 在c的基础上新增加的几点优化也是很耀眼的 就const直接可以取代c中的 define 以下几点很重要 学不好后果也也很严重 const 1 限定符声明变量只能被读 const in
  • ROS2学习笔记(五)-- ROS2命令行操作常用指令总结(一)

    简介 xff1a 在前面的章节中 xff0c 我们先简单学习了ROS2的话题发布和订阅 xff0c 两种操作都是通过python代码实现的 xff0c 而在实际应用过程中 xff0c 我们会经常用到命令行操作来辅助调试 xff0c 更进一步
  • Ubuntu16.04配置Carla第三方egg库

    背景 CARLA软件是英特尔公司主导的 xff0c 基于虚幻4游戏引擎 xff0c 用于自动驾驶仿真的一款开源仿真软件 xff0c 该软件可以模拟激光雷达 xff0c 摄像头等等自动驾驶中常用的传感器的行为以及获取传感器数据 xff0c 从
  • 串口通信校验方式(even,odd,space,mark)

    无校验 xff08 no parity xff09 奇校验 xff08 odd parity xff09 xff1a 如果字符数据位中 34 1 34 的数目是偶数 xff0c 校验位为 34 1 34 xff0c 如果 34 1 34 的

随机推荐

  • 更改Ubuntu默认python版本的两种方法

    更改Ubuntu默认python版本的两种方法 没找到原文地址 xff0c 作者写的很实用的方法 xff0c 赞一个 当你安装 Debian Linux 时 xff0c 安装过程有可能同时为你提供多个可用的 Python 版本 xff0c
  • Franka+Realsense D435i Ubuntu 20.04-easyHandeye 手眼标定

    使用Panda 43 realsense D435i 43 easyhandeye 43 ROS neotic 全流程记录 安装环节 安装ros安装libfranka安装moveit panda moveit config 安装 visp安
  • CMake教程Step2(添加库)

    CMake官方文档 参考官方cmake3 24教程翻译 https cmake org cmake help v3 24 guide tutorial index html https gitlab kitware com cmake cm
  • ROS rplidar_ros package使用相关说明

    rplidar ros wiki http wiki ros org rplidar ros SDK详解 xff0c 参考blog xff1a https blog csdn net qq 16775293 article details
  • wireshark能抓到数据,调试工具却收不到数据问题

    网上查找原因 xff0c 有各种说法 xff0c 其中有说关闭防火墙的 xff0c 抱着试一试的心态 xff0c 结果成功了 wireshark有数据 xff1a 关闭防火墙 xff1a NetAssist收到数据 xff1a
  • RTKLIB之RTKRCV

    1 options file option file can be saved from rtknavi exe modify the options file to fit for ubuntu system remember to ch
  • 连接跟踪子系统之AF_INET协议族钩子函数

    如笔记连接跟踪子系统之AF INET初始化所述 xff0c 为了支持连接跟踪子系统 xff0c AF INET协议族在4个HOOK点共注册了8个钩子函数 xff0c 每个HOOK点有两个 这些钩子函数可分为入口 xff08 PRE ROUT
  • UML建模详解(9)—Rose将C++代码自动生成UML类图详解

    一 类图 nbsp class diagram nbsp 即 c 中的 class 聚合 nbsp Aggregation nbsp 即我们c 中的引用 表现为 class 头文件中的一个或多个指针成员 组合 nbsp Compositio
  • ROS2学习笔记(十)-- ROS2 launch启动文件

    简介 xff1a 接触过ROS1的同学对launch肯定不陌生 xff0c 在ROS1中 xff0c 我们常用launch实现node和master同时启动 多节点同时启动配置等功能 xff0c ROS2中的launch也是用于多节点启动
  • C++vector的使用总结及常用vector操作

    一 C vector类为内置数组提供了一种替代表示 与string类一样 vector 类是随标准 C 引入的标准库的一部分 使用时需包含头文件 include lt vector gt 二 C vector类有两种使用方式 第一种 STL
  • cc2640 基于官方从机修改的通过手机实现蓝牙点灯例程

    在TI官方从机例程中的simpleBLEPeripheral c进行代码修改 添加引脚驱动头文件 xff1a include lt ti drivers pin PINCC26XX h gt PIN driver 添加全局变量 xff1a
  • cadence 17.0 生成钻孔文件 cam350打不开的问题解决

    17 0生成钻孔文件后 xff0c cam350打不开 这时用记事本打开钻孔文件 对比发现相较于16 6的版本 xff0c 多了以下一行红色高亮的的代码 将其删除就可以用cam350打开了 LEADER 12 HEADER CODE ASC
  • matlab 串口读取设置

    本例代码运行于 MATLAB2015b xff0c 参照网上的代码修改而成 xff0c 可以自定义一次读取的数据 xff0c 并做简单处理 xff0c 随后绘图 实测可用 实用 读串口 clear clc obj 61 serial 39
  • 室内定位综述

    本篇文章是作者研究生毕设的前稿 xff0c 每周更新补充 xff0c 主要是中外关于室内定位的论文综述 xff0c 偏向于TDOA方向 xff0c 也会更新些其他的方向 有不当的地方欢迎有人指正 61 2016 7 20 1 Contrib
  • CC2630 TIMAC协议栈低功耗问题

    项目功能 采集5s数据发送 休眠5s 采集5s数据发送 xff0c 循环往复 平台 CC2630 协议栈 xff1a timac 1 05 02 43299 问题描述 在休眠5s的过程中 xff0c 整体电流在7 8ma xff0c 只比数
  • c++ 大小写转换&&字符转数字

    大小写转换 amp amp 字符转数字 xff0c 实验笔记 int main 其实就是对ASCii表的操作 string s char a 61 39 a 39 int b 61 a 39 0 39 字符转成数字 int c 61 int
  • 数组方式赋值字符串及字面值常量赋值字符串的区别

    c 43 43 实验笔记 数组赋值字符串时需要显示 39 0 39 xff0c 否则在某些时候会有问题 int main const char a 61 39 a 39 39 v 39 39 b 39 39 b 39 39 0 39 数组需
  • STL:: allocator之deallocate & destory的区别与联系

    c 43 43 中的allocator是标准库中的一个类 xff0c 负责内存分配管理 下面是 STL源码剖析 中一个简单allocator实现的部分源代码 xff1a deallocate xff1a template lt class
  • allocator简单实现

    allocator是c 43 43 标准库中用于管理内存的一个类 主要包括以下类方法 xff1a 代码如下 xff08 来源于 STL源码剖析 xff09 xff1a ifndef JJALLOC define JJALLOC includ
  • ROS2学习笔记(十一)-- ROS2 bag数据记录与回放

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