ROS基础内容2--通信方式之Topic以及node、topic和message的关系

时间:2024-04-12 18:52:28

本文参考了ROS_Kinetic_05 ROS基础内容,在本人的计算机环境ubuntu16.04 64bit+kinetic基础上进行实践。

1. ROS节点node的基本概念和操作

官网教程:http://wiki.ros.org/cn/ROS/Tutorials/UnderstandingNodes

涉及到的基本概念:

Nodes:节点,一个节点即为一个可执行文件,节点之间通过ROS这个系统进行通信。
Messages:消息,消息是一种ROS数据类型,用于主题的订阅或发布。
Topics:主题,节点可以发布消息到主题,也可以订阅某些主题以接收这些主题的消息。
Master:节点管理器,ROS名称服务。(在ROS2中取消了Master节点)
rosout: ROS中相当于stdout/stderr。
roscore: 主机+ rosout + 参数服务器。
rospy = python 客户端库
roscpp = c++ 客户端库

节点是ROS中最重要的概念之一。每个ROS运行实例被称为节点。换句话说,每个ROS程序运行的进程,就是一个节点。每个机器人程序,可以有非常多个节点。我们也可以运行同一个程序的多个副本(但要确保每个副本使用不同节点名),则每个副本都被当作一个独立节点。

节点(Node)可以用来提供某种数据或能力,比如读取某Sensor数据。也可以是一个获取这些数据并处理的节点(Node),例如从别的节点那拿到Sensor并处理。但他们之间如何知道对方存在与否呢?哪些node需要哪种数据呢?这就需要有个管理者,它就是NodeMaster/ Node Core。每个Node启动时,需要向它注册,申明自己提供什么服务或需要什么数据。

Node是ROS package中一个可执行文件。ROS node利用ROS用户库去和其他node进行通信。nodes也可以向topic发起发布或者订阅,nodes也可以提供或者使用一个service.

为何说Node是ROS核心,看看它通常被用来做什么:

控制电机速度,获取激光雷达数据,获取Camera数据,利用以上数据定位,路径规划。

启动一个Node

#rosrun package-name executable-name

两个参数,参数1:功能包名。 参数2:可执行文件名。(见后面的例子)

查看当前有哪些Node

#rosnode list

停止一个Node:

#rosnode kill node-name

虽然也可以ctrl-c停止,但此时Node master 可能会没有及时注销此node.造成误会。(当然这种情况可以:rosnode cleanup)

查看当前运行的node的信息:

#rosnode info Node_Name

--------------------------------------------------------------------------------------------------------------------------------------

1.1 实例

下面是一个运行node的例子

首先在一个terminal上启动ros

~$ roscore

在另一个terminal上启动一个turtlesim模拟器并启动一个turtlesim_node节点

~$ rosrun turtlesim turtlesim_node

在另一个terminal上查看节点列表

~$ rosnode list

如下图所示:

ROS基础内容2--通信方式之Topic以及node、topic和message的关系

此时只有rosout和turtlesim节点这两个,其中turtlesim就是通过turtlesim启动的那个节点,默认名字与模拟器相同。下面我们再启动一个terminal并启动一个turtlesim节点,并给它起个名字:

~$ rosrun turtlesim turtlesim_node __name:=kinetic_turtle

ROS基础内容2--通信方式之Topic以及node、topic和message的关系

然后我们再用rosnode list命令查看,发现多了一个叫kinetic_turtle节点。

如果启动两个同名的node,如下图的test1,则也会只保留一个,第一个创建的会被强制关闭:

ROS基础内容2--通信方式之Topic以及node、topic和message的关系

使用rosnode ping nodename可以测试能否ping通某个节点,

ROS基础内容2--通信方式之Topic以及node、topic和message的关系

删除节点:~$ rosnode kill nodename

ROS基础内容2--通信方式之Topic以及node、topic和message的关系

~$ rosnode cleanup

关闭turtlesim_node,请按下“Ctrl-C” 。

查看节点信息:

ROS基础内容2--通信方式之Topic以及node、topic和message的关系

这里可以看到节点订阅和发布的消息的类型。

-------------------------------------------------------------------------------------------------------------------------------------------

2. ROS中的主题topic

在开始topic相关讨论之前,我们先看通过turtlesim中的那个turtlesim(小海龟)的例子来了解一下ros中的topic是怎么一回事。

2.1 实例

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

(1)启动小乌龟turtle

ROS的资料中提到一只虚拟小乌龟:turtle,关于它的例子也十分简单,比如启动它

~$ roscore

在另一个terminal中启动一个turtle节点

~$ rosrun turtlesim turtlesim_node

另打开一个ternimal标签

~$ rosrun turtlesim turtle_teleop_key

将会得到蓝色背景下随机的一直小乌龟,并且可以使用方向键控制移动,但是turtle_teleop_key的节点系统里是没有源代码的,只有一个能够直接运行的文件.

ROS基础内容2--通信方式之Topic以及node、topic和message的关系

另起一个terminal,打开节点图可以更直观地看到这两个节点间传递消息的主题

~$ rqt_graph

ROS基础内容2--通信方式之Topic以及node、topic和message的关系

显然,/teleop_turtle这个节点单向传递速度的控制信息给turtlesim节点, 那么完全可以按照程序的意愿使小乌龟的运行处于脱机运行状态.

Node之间,是通过Message来传递消息的,每个Message就是一个数据结构,如geonetry_msgs/Twist.msg.

 ROS基础内容2--通信方式之Topic以及node、topic和message的关系

换句话说自己写一个可发布/turtle1/cmd_vel的程序.

我们必须知道/turtle1/cmd_vel里发布的msg是什么样的,执行如下命令,查看传递的消息:

~$ rostopic type /turtle1/cmd_vel | rosmsg show

geometry_msgs/Vector3 linear
float64 x
float64 y
float64 z
geometry_msgs/Vector3 angular
float64 x
float64 y
float64 z

ROS基础内容2--通信方式之Topic以及node、topic和message的关系

可以看到msg为geometry_msgs/Vector3,这个消息的原型在ROS中,/opt/ros/kinetic/share/geometry_msgs/Vector3 ,内容为

float64 x

float64 y

float64 z

(2)简单的自转

那么接下来自己写一个node,发布它们就可以了.

在catkin中建立一个package,如toldturtle,并创建一个node.(下面标注的红色的toldturtle和talk,也可以改成其他名称,只要保证一致即可)

~$ cd ~/catkin_ws/src/

~$ catkin_create_pkg toldturtle roscpp std_msgs geometry_msgs

在该package的src下创建一个名为talk.cpp的node.

#include <ros/ros.h>#include <geometry_msgs/Twist.h>ros::Publisher cmdVelPub;int main(int argc, char **argv){ ros::init(argc, argv, "talk"); //"talk"必须是nodename std::string topic = "/turtle1/cmd_vel"; //topic name ros::NodeHandle n; cmdVelPub = n.advertise<geometry_msgs::Twist>(topic, 1); //第一个参数也可以写成"/turtle1/cmd_vel"这样的topic name //第二个参数是发布的缓冲区大小,<geometry_msgs::Twist>是消息类型 ros::Rate loopRate(2); //与Rate::sleep();配合指定自循环频率 ROS_INFO("talk cpp start...");//输出显示信息 geometry_msgs::Twist speed; // 控制信号载体 Twist message while (ros::ok()){ speed.linear.x = 1; // 设置线速度为1m/s,正为前进,负为后退 speed.angular.z = 1; // 设置角速度为1rad/s,正为左转,负为右转 cmdVelPub.publish(speed); // 将刚才设置的指令发送给机器人 ros::spinOnce(); loopRate.sleep();//按loopRate(2)设置的2HZ将程序挂起 } return 0;}

并且修改cmake代码,让编译系统明白如何编译,这里我的package为toldturtle,node为talk.cpp:

cmake_minimum_required(VERSION 2.8.3)project(toldturtle)find_package(catkin REQUIRED COMPONENTS geometry_msgs roscpp rospy std_msgs)catkin_package( CATKIN_DEPENDS geometry_msgs roscpp rospy std_msgs)include_directories( ${catkin_INCLUDE_DIRS})## Declare a C++ executable add_executable(talk src/talk.cpp)## Specify libraries to link a library or executable target against target_link_libraries(talk ${catkin_LIBRARIES} )

这样在terminal里编译下整个catkin的package

~$ cd ~/catkin_ws/

~$ catkin_make

如果编译成功,就可以看到提示了.

ROS基础内容2--通信方式之Topic以及node、topic和message的关系

(3)效果

在终端运行写的node

~$ rosrun toldturtle talk

ROS基础内容2--通信方式之Topic以及node、topic和message的关系

此时,我们查看ros中的节点,

ROS基础内容2--通信方式之Topic以及node、topic和message的关系

这样就通过编写一个talk,来实现在ros中对turtle的控制.

此时,turtle也受前面的teleop_turtle控制,我们仍然可以通过键盘上的箭头控制小乌龟,只不过它目前受两个控制,在键盘箭头控制的同时,仍然受talk的控制进行画圆,即可以用方向键控制自旋转的turtle.

ROS基础内容2--通信方式之Topic以及node、topic和message的关系

此时查看节点之间的关系,我们发现talk和teleop_turtle都可以传递消息给turtlesim。

ROS基础内容2--通信方式之Topic以及node、topic和message的关系

通过这个例子,结合订阅/发布消息机制,我们可以认为turtlesim节点订阅了turtle1/cmd_vel这个主题,而只要某个节点发布了这个主题的消息,turtlesim节点都能接受并根据传过来的消息内容(即geometry_msgs/Vector3)更新乌龟的位置。

关于乌龟控制的例子,我们参考了:http://blog.****.net/under_maple/article/details/49430765

(4)通过rostopic命令发布topic消息来控制小乌龟

除了上面的方式,写一个package来实现对小乌龟的控制外,还有更方面的一种方式来实现对小乌龟的控制,就是在命令行里,借助rostopic命令,发布一条小乌龟控制所需要的消息

rostopic pub [topic] [msg_type] [args

~$ rostopic pub -1 /turtle1/cmd_vel geometry_msgs/Twist -- '[2.0, 0.0, 0.0]' '[0.0, 0.0, 1.8]'

publishing and latching message for 3.0 seconds

上面的命令告诉小海龟按照线速度2角速度1.8进行移动,时间为3s,如下图所示(忘记截图了,此图来源于http://blog.****.net/bobsweetie/article/details/43638797):

ROS基础内容2--通信方式之Topic以及node、topic和message的关系

小乌龟移动3s后停止了,我们可以用rostopic pub -r命令发布一个稳定的命令流。

~$ rostopic pub /turtle1/cmd_vel geometry_msgs/Twist -r 1 -- '[2.0, 0.0, 0.0]' '[0.0, 0.0, 1.8]

ROS基础内容2--通信方式之Topic以及node、topic和message的关系

~$ rostopic hz /turtle1/pose

subscribed to [/turtle1/pose]
average rate: 124.817
    min: 0.006s max: 0.010s std dev: 0.00141s window: 118
average rate: 125.015
    min: 0.006s max: 0.010s std dev: 0.00142s window: 243
average rate: 124.968
    min: 0.006s max: 0.010s std dev: 0.00142s window: 368
average rate: 125.009
    min: 0.006s max: 0.010s std dev: 0.00141s window: 493

~$ rostopic type /turtle1/cmd_vel | rosmsg show

~$ rosrun rqt_plot rqt_plot

ROS基础内容2--通信方式之Topic以及node、topic和message的关系

rostopic命令相关的内容,可以参考:http://blog.****.net/bobsweetie/article/details/43638797

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

2.2 ROS中的topic的理解(三种主要通信方式中的一种)

下面我们正式开始ros中的topic主题部分的理解。

ROS Node之间通讯方式主要依靠的就是主题(Topic)和服务(Service), 参数(parameter) 三种Message就是放在Topic中。这里需要注意,Topic只是ROS中的一种通信方式,而不是唯一的通信方式。

 Message传递的的理念

当一个节点想要分享信息时,它就会发布(publish)消息到对应的一个或多个Topic(主题);当一个节点想要接收消息时,它就会订阅(Subscribe)它所需要的一个或多个Topic。

ROS Topic: 

主题是由ROS网络对消息进行路由,对消息进行管理的数据总线。每一条消息都要发布到相应的主题上。当一个节点发送数据时,我们就说这个节点向某个主题发布了消息。

节点可以通过订阅某个主题,接受别的节点发布的消息。

ROS Master负责确保发布主题的Node和订阅主题的Node能找到对方。而Message是直接从发布Node传递到订阅Node.并不需要经过Node Master。

A:消息以一种publish/subscribe的方式传递。

B:节点可以在给定的主题中发布/订阅消息。

C:一个节点可以订阅/发布多个不同主题。

D:允许多个Node订阅/发布同一个主题。

E:订阅节点和发布节点并不知道相互之间的存在。

 Message注册和订阅过程:

ROS基础内容2--通信方式之Topic以及node、topic和message的关系

Talker这个Node,启动后注册了一个Topic,名为bar, 并告知Node Master,接收端口为:1234。

Listener这个Node启动后订阅了一个Topic,名为bar.

Node Master告知Listener,主题的端口为1234。

Listener去连接1234端口,Talker监听到有人连接。就告知对方,数据接口是2345。

于是两个Node就连通起来了。

同一个时刻,只有一个Node Master。所以可以共享数据。

ROS基础内容2--通信方式之Topic以及node、topic和message的关系

我们继续用上面的程序来查看Topic.

#roscore

#rosrun turtlesim turtlesim_node

#rosrun turtlesim turtlesim_node __name:=turtle2

#rosrun turtlesim turtle_teleop_key

1. 运行了roscore,

2. 运行了turtlesim包内的turtlesim_node这node两次,使用不同的node_Name.

3. 运行了turtlesim包内的turtle_teleop_key.

turtlesim_node和turtle_teleop_keynode之间用topic交流通信.

turtle_teleop_key在这个topic上发布按键敲击,而turtlesim订阅同样的topic接受按键敲击.

可以使用可视化工具查看Topic的数据传输。

#rosrun rqt_graph rqt_graph

图示:

ROS基础内容2--通信方式之Topic以及node、topic和message的关系

这个和我们原来研究的zeromq差不错,都是基于订阅/发布模式的消息传递机制。

3. 总结

要理解ROS topics、ROS nodes、ROS Messages之间的关系。目前个人的理解是:ROS topics是ROS nodes之间进行通信的枢纽,ROS messages是ROS nodes订阅和发布数据的载体。两个ROS nodes欲实现通信,则其中一个节点向ROS topic发布ROS messages,另一节点则通过订阅此topic来接收messages,两者的message类型一定要相同,而message的类型由主题确定,通过rostopic type命令可以查看topic的数据类型。

然后就是辅助查看ROS中节点关系和数据的工具:rqt_graph和rqt_plot,两者都是针对ROS类型的,其中rqt_graph工具会自动搜寻系统中正在运行的节点和主题,并动态绘制出关系图,rqt_plot则是绘制发布到topic上的数据的图形,因此两者使用的前提是有ROS的进程在运行。

运行节点:roscore
rosrun turtlesim turtlesim_node
rosrun turtlesim turtle_teleop_key
查看节点关系图:rosrun rqt_graph rqt_graph

显示topic1上所发布的数据:rostopic echo topic1
列出当前处于**状态的topic列表:rostopic list -v
显示topic1的数据类型:rostopic type topic1
显示类型更加详细的信息:rosmsg show type1
直接向主题topic1发布数据:rostopic pub [topic1] [msg_type] [args]
显示主题topic1上数据的发布速率:rostopic hz [topic1]