在ROS中关于数据的留存以及读取实现,提供了一个专门的工具:rosbag;
概念:
用于录制和回放ROS主题的一个工具集。
作用:
实现了数据的复用,方便调试、测试
本质:
rosbag本质也是ros的节点,当录制时,rosbag是一个订阅节点,可以订阅话题消息并将订阅的数据写入磁盘文件;当回放时,rosbag是一个发布节点,可以读取磁盘文件,发布文件中的话题消息;
需求:ROS内置的乌龟,操作过程使用rosbag录制,录制结束后,实现重放。
实现:
1、创建目录保存录制的文件
mkdir ./bags
cd bags
2、开始录制
roscore
rosrun turtlesim turtlesim_node
rosrun turtlesim turtle_teleop_key
启动乌龟GUI以及键盘控制节点;
rosbag record -a -o bags/hello
操作小乌龟运行一段时间,结束录制使用ctrl+c,,在创建的目录中会生成bag后缀文件;
3、查看文件
rosbag info bags/hello_2022-11-16-21-32-41.bag
path: bags/hello_2022-11-16-21-32-41.bag
version: 2.0
duration: 21.3s
start: Nov 16 2022 21:32:41.60 (1668605561.60)
end: Nov 16 2022 21:33:02.89 (1668605582.89)
size: 216.7 KB
messages: 2902
compression: none [1/1 chunks]
types: geometry_msgs/Twist [9f195f881246fdfa2798d1d3eebca84a]
rosgraph_msgs/Log [acffd30cd6b6de30f120938c17c593fb]
turtlesim/Color [353891e354491c51aabe32df673fb446]
turtlesim/Pose [863b248d5016ca62ea2e895ae5265cf9]
topics: /rosout 3 msgs : rosgraph_msgs/Log
/turtle1/cmd_vel 265 msgs : geometry_msgs/Twist
/turtle1/color_sensor 1317 msgs : turtlesim/Color
/turtle1/pose 1317 msgs : turtlesim/Pose
4、回放文件
rosbag play bags/hello_2022-11-16-21-32-41.bag
重启乌龟节点,此时可以看见乌龟按照bag文件录制的轨迹运行
注:rosbag也是一个节点,因此也可使用rosrun操作。
命令行不够灵活,,因此使用编码的模式加强灵活性
1、写bag
实现流程:
初始化;
创建rosbag对象;
打开文件流;
写数据;
关闭文件流;
代码:
#include "ros/ros.h"
#include "rosbag/bag.h"
#include "std_msgs/String.h"
/*
需求:使用rosbag 向磁盘文件写入数据(话题+消息)
流程:
1、导包
2、初始化;
3、创建rosbag对象
4、打开文件流
5、写数据
6、关闭文件流
*/
int main(int argc, char *argv[])
{
// 2、初始化;
setlocale(LC_ALL,"");
ros::init(argc,argv,"bag_write");
ros::NodeHandle nh;
// 3、创建rosbag对象
rosbag::Bag bag;
// 4、打开文件流
bag.open("hello.bag",rosbag::BagMode::Write);
// 5、写数据
std_msgs::String msg;
msg.data="hello xxxx";
bag.write("", ros::Time::now(), msg);
bag.write("", ros::Time::now(), msg);
bag.write("", ros::Time::now(), msg);
bag.write("", ros::Time::now(), msg);
// 6、关闭文件流
bag.close();
return 0;
}
2、读bag
实现流程:
类似,本质操作磁盘文件
代码:
#include "ros/ros.h"
#include "rosbag/bag.h"
#include "rosbag/view.h"
#include "std_msgs/String.h"
/*
需求:使用rosbag 读取磁盘上的bag文件
流程:
1、导包
2、初始化;
3、创建rosbag对象
4、打开文件流(以读的方式打开)
5、读数据
6、关闭文件流
*/
int main(int argc, char *argv[])
{
// 2、初始化;
setlocale(LC_ALL,"");
ros::init(argc,argv,"bag_read");
ros::NodeHandle nh;
// 3、创建rosbag对象
rosbag::Bag bag;
// 4、打开文件流(以读的方式打开)
bag.open("hello.bag", rosbag::BagMode::Read);
// 5、读数据
//因为磁盘文件保存数据类型读也要读出来
//取出时间戳,话题和消息内容
//先获取消息的集合,再迭代取出消息的字段具体
for (auto &&m : rosbag::View(bag))
{
//解析
std::string topic = m.getTopic();
ros::Time time = m.getTime();
std_msgs::StringPtr p = m.instantiate<std_msgs::String>();
ROS_INFO("解析的内容,话题:%s,时间戳:%.2f,消息值:%s",topic.c_str(),time.toSec(),p->data.c_str());
}
// 6、关闭文件流
bag.close();
return 0;
}
出现错误:
terminate called after throwing an instance of 'ros::InvalidNameException'
what(): Character [ ] at element [7] is not valid in Graph Resource Name [dwadawd 1]. Valid characters are a-z, A-Z, 0-9, / and _.
已放弃 (核心已转储)
原因分析:cpp文件存在命名错误,删去空格或者改为下划线
解决问题:经检查发现初始化的过程中,话题的名称随意打成dwadawd 1出现空格,修改为bag_read 后重新编译运行通过;