最近闲来无事,打算重温了一下ROS方面的相关知识。先前的学习都是一带而过,发现差不多都忘了,学习的不够深入。因此,在重温的同时,写下了这篇关于ROS通信实操的学习博客。
上一篇博客的链接为:ROS架构的学习【Noetic】-CSDN博客
主要简单介绍了一下ROS的基本架构,下面以实操的演示来进行后续的学习并记录。
本篇博客主要是通过ROS内置的turtlesim案例,结合ROS命令获取节点、话题、话题消息、服务、服务消息与参数的信息,最终再以编码的方式实现乌龟运动的控制、乌龟位姿的订阅、乌龟生成与乌龟窗体背景颜色的修改。
0 测试 ROS
在实操前,请先安装好ROS和相关配置。
我使用的是虚拟机Ubuntu20.04和ROS1(noetic)版本
ROS 内置了一些小程序,可以通过运行这些小程序以检测 ROS 环境是否可以正常运行:
-
首先启动三个命令行(ctrl + alt + T)
-
命令行1键入:roscore
-
命令行2键入:rosrun turtlesim turtlesim_node (此时会弹出图形化界面)
-
命令行3键入:rosrun turtlesim turtle_teleop_key (在3中可以通过上下左右控制2中乌龟的运动)
最终结果如下所示(注意:光标必须聚焦在键盘控制窗口,否则无法控制乌龟运动):
下面来试试控制乌龟做圆周运动(极简实现):
新开一个终端,输入指令:
rostopic pub -r 10 /turtle1/cmd_vel geometry_msgs/Twist "linear:
然后使用Tab进行补齐,出现如下图所示的终端:
然后再修改 linear: x为1.0 , angular: z为1.0,回车执行,发现乌龟转了起来:
1 实操: 话题发布
下面我们使用VScode编辑器IDE来进行实操环节的代码编写流程展示:
首先在src下新建一个功能包:
后面出现如下界面,输入包名 plumbing_test 后回车:
再输入依赖 roscpp rospy std_msgs geometry_msgs 后再次回车:
发现功能包创建成功:
实现方案A: C++
下面继续在这个功能包(plumbing_test)的src目录中创建一个文件:test01_pub_twist.cpp
将如下C++代码复制到 test01_pub_twist.cpp 文件当中:
/*编写 ROS 节点,控制小乌龟画圆准备工作:1.获取topic(已知: /turtle1/cmd_vel)2.获取消息类型(已知: geometry_msgs/Twist)3.运行前,注意先启动 turtlesim_node 节点实现流程:1.包含头文件2.初始化 ROS 节点3.创建发布者对象4.循环发布运动控制消息
*/#include "ros/ros.h"
#include "geometry_msgs/Twist.h"int main(int argc, char *argv[])
{setlocale(LC_ALL,"");// 2.初始化 ROS 节点ros::init(argc,argv,"control");ros::NodeHandle nh;// 3.创建发布者对象ros::Publisher pub = nh.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel",1000);// 4.循环发布运动控制消息//4-1.组织消息geometry_msgs::Twist msg;msg.linear.x = 1.0;msg.linear.y = 0.0;msg.linear.z = 0.0;msg.angular.x = 0.0;msg.angular.y = 0.0;msg.angular.z = 2.0;//4-2.设置发送频率ros::Rate r(10);//4-3.循环发送while (ros::ok()){pub.publish(msg);ros::spinOnce();}return 0;
}
下面还需要对同级目录下的CMakeLists.txt文件进行配置:
配置完成后,进行编译catkin_make:
必须确保编译成功。发现编译无误之后,我们继续新开一个终端:
我这里进行了终端分屏,左边启动roscore,右边启动乌龟的GUI,在终端内输入并执行:
rosrun turtlesim turtlesim_node
发现GUI界面启动成功,再开启一个终端后进入我们的工作空间内:
source一下,继续输入并回车:
source ./devel/setup.bash
下面运行一下我们刚刚编写的节点,继续输入并回车:
rosrun plumbing_test test01_pub_twist
发现小乌龟开始转了起来:
实现方案B: Python
下面在plumbing_test的目录中新建一个scripts目录;
继续在这个scripts目录中创建一个文件:test01_pub_twist_p.py
将如下Python代码复制到 test01_pub_twist_p.py 文件当中:
#! /usr/bin/env python
"""编写 ROS 节点,控制小乌龟画圆准备工作:1.获取topic(已知: /turtle1/cmd_vel)2.获取消息类型(已知: geometry_msgs/Twist)3.运行前,注意先启动 turtlesim_node 节点实现流程:1.导包2.初始化 ROS 节点3.创建发布者对象4.循环发布运动控制消息"""import rospy
from geometry_msgs.msg import Twistif __name__ == "__main__":# 2.初始化 ROS 节点rospy.init_node("control_circle_p")# 3.创建发布者对象pub = rospy.Publisher("/turtle1/cmd_vel",Twist,queue_size=1000)# 4.循环发布运动控制消息rate = rospy.Rate(10)msg = Twist()msg.linear.x = 1.0msg.linear.y = 0.0msg.linear.z = 0.0msg.angular.x = 0.0msg.angular.y = 0.0msg.angular.z = 0.5while not rospy.is_shutdown():pub.publish(msg)rate.sleep()
Python文件保存后,需要对其添加可执行权限,在scripts目录下开启一个终端后输入:
chmod +x *.py
查看文件权限已经给到:
下面还需要对同级目录下的CMakeLists.txt文件进行配置:
配置完成后,进行编译catkin_make:
必须确保编译成功。发现编译无误之后,我们继续新开一个终端:
我这里进行了终端分屏,左边启动roscore,右边启动乌龟的GUI,在终端内输入并执行:
rosrun turtlesim turtlesim_node
发现GUI界面启动成功后,再开启一个终端进入我们的工作空间内,source一下,继续输入并回车:
source ./devel/setup.bash
下面运行一下我们刚刚编写的节点,继续输入并回车:
rosrun plumbing_test test01_pub_twist_p.py
发现小乌龟开始转了起来:
2 实操: 话题订阅
为了方便起见,下面我们都使用python代码进行演示:
案例:已知turtlesim中的乌龟显示节点,会发布当前乌龟的位姿(窗体中乌龟的坐标以及朝向),要求控制乌龟运动,并时时打印当前乌龟的位姿。
首先在plunbing_test目录下编写一个launch文件夹,存放launch文件:
launch文件的代码如下:
<!-- 启动乌龟GUI与键盘控制节点 -->
<launch><!-- 乌龟GUI --><node pkg="turtlesim" type="turtlesim_node" name="turtle1" output="screen" /><!-- 键盘控制 --><node pkg="turtlesim" type="turtle_teleop_key" name="key" output="screen" /></launch>
接下来我们启动这个launch文件,在工作空间目录中source一下,继续输入并回车:
source ./devel/setup.bash
接下来执行launch文件:
roslaunch plumbing_test start_turtle.launch
可以发现,启动正常:
下面通过键盘控制运动,运行正常:
准备工作完毕后,我们开始和获取话题与其相关的格式
1.话题与消息获取
下面新开一个终端:
rostopic list
可以查看到话题信息:
如果想要查看话题的消息,输入:
rostopic info /turtle1/pose
可以看到相关信息:
下面再看一下消息类型,输入:
rosmsg info turtlesim/Pose
我们会发现,消息类型的格式就是下面的这5个字段
分别为:x,y的坐标;theta朝向;线速度;角速度
那么,上述的话题、消息、消息格式,我们就都获取到了
下面我们继续以命令的方式来获取乌龟的位姿:
rostopic echo /turtle1/pose
打印出的消息如下,由于乌龟没有运动,所以数据一直是固定不变的:
下面用键盘控制乌龟运动,可以发现数据发生了变化:
2.实现订阅节点
创建功能包需要依赖的功能包: roscpp rospy std_msgs turtlesim
下面需要追加turtlesim这个包,需要修改package.xml配置文件:
添加完上面的2行代码后,再进入CMakeLists.txt文件进行配置,添加turtlesim:
完成后相关的配置后,保存并编译:
发现编译无误后,下面可以开始编写代码了。
以python的方式来实现乌龟位姿的订阅:
在plumbing_test的目录中的scripts目录中创建一个文件:test02_sub_pose_p.py
将如下Python代码复制到 test02_sub_pose_p.py 文件当中,并添加可执行权限:
下面还需要对同级目录下的CMakeLists.txt文件进行配置,在此处添加下面这行代码:
保存后并进行编译。编译无误后,下面便可以开始执行代码了,开启乌龟的相关节点,执行下面的launch指令即可:
roslaunch plumbing_test start_turtle.launch
等待乌龟的GUI界面出现后,新开一个终端并cd到我们的工作空间,进行一下source后执行我们的python文件:
rosrun plumbing_test test02_sub_pose_p.py
由于乌龟目前处于静止状态,所以终端中的打印的数据是不变的
下面我们通过键盘控制乌龟的运动,发现终端的数据发生了改变:
3 实操: 服务调用
编码实现向 turtlesim 发送请求,在乌龟显示节点的窗体指定位置生成一乌龟,这是一个服务请求操作。
- 首先,需要启动乌龟显示节点。
- 要通过ROS命令,来获取乌龟生成服务的服务名称以及服务消息类型。
- 编写服务请求节点,生成新的乌龟。
1.服务名称与服务消息获取
下面我们新开一个终端,先调用之前写好的launch文件:
roslaunch plumbing_test start_turtle.launch
再新开一个终端,获取服务话题以及消息类型:
rosservice list
可以查看到ROS系统当中所有存在的服务:
我们需要生成新的小乌龟,需要用到 /spawn,可以查看一下相关信息:
rosservice info /spawn
可以进一步再了解Type的具体数据格式,输入:
rossrv info turtlesim/Spawn
那么,上述的服务话题、消息类型、消息格式,我们就都获取到了
下面我们用终端来进行一下简易的演示,新开一个终端输入:
rosservice call /spawn
再使用Tab进行补齐,得到:
对补齐后的数据进行赋值修改,如下图所示:
确认无误后回车,发现GUI界面中出现了一只新的小乌龟:
2.服务客户端实现
创建功能包需要依赖的功能包: roscpp rospy std_msgs turtlesim
下面需要追加turtlesim这个包,需要修改package.xml配置文件:
参考资料:
2.5 通信机制实操 · Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程