本篇讲述ROS2核心原理的节点与话题。
一.节点
1.概念
完整的机器人系统可能并不是一个物理上的整体,机器人的功能虽位于不同的计算机中,但都是这款机器人的工作细胞,也就是节点,他们共同组成了一个完整的机器人系统。
下面是关于节点的特性描述:
●节点在机器人系统中的职责就是执行某些具体的任务,从计算机操作系统的角度来看,也叫做进程;
●每个节点都是一个可以独立运行的可执行文件,比如执行某一个python程序,或者执行C++编译生成的结果,都算是运行了一个节点;
●既然每个节点都是独立的执行文件,那自然就可以想到,得到这个执行文件的编程语言可以是不同的,比如C++、Python,乃至Java、Ruby等更多语言。
●这些节点是功能各不相同的细胞,根据系统设计的不同,可能位于计算机A,也可能位于计算机B,还有可能运行在云端,这叫做分布式,也就是可以分布在不同的硬件载体上;
●每一个节点都需要有唯一的命名,当我们想要去找到某一个节点的时候,或者想要查询某一个节点的状态时,可以通过节点的名称来做查询。
2.节点实现
节点实现有分面向过程实现和面向对象实现。两者案例可分别参阅dev_ws/src/ros2_21_tutorials/learning_node/learning_node/node_helloworld.py和dev_ws/src/ros2_21_tutorials/learning_node/learning_node/node_helloworld_class.py。
面向过程
代码实现在learning_node/node_helloworld.py,完成代码的编写后需要设置功能包的编译选项,让系统知道Python程序的入口,打开功能包的setup.py文件。
运行节点命令如下:
- ros2 run learning_node node_helloworld
面相过程这种方式虽然实现简单,但是对于稍微复杂一点的机器人系统,就很难做到模块化编码。
面向对象
节点实现代码如下:
-
-
-
- """
- @作者: 古月居(www.guyuehome.com)
- @说明: ROS2节点示例-发布“Hello World”日志信息, 使用面向过程的实现方式
- """
-
- import rclpy
- from rclpy.node import Node
- import time
-
- def main(args=None):
- rclpy.init(args=args)
- node = Node("node_helloworld")
-
- while rclpy.ok():
- node.get_logger().info("Hello World")
- time.sleep(0.5)
-
- node.destroy_node()
- rclpy.shutdown()
-
运行节点命令如下:
- learning_node/node_helloworld_class.py
我们可以看到创建节点流程的代码实现过程如下,只是面向过程与面向对象编码方式不一样而已。
●编程接口初始化
●创建节点并初始化
●实现节点功能
●销毁节点并关闭接口
3.物体识别节点
首先安装OpenCV,指令如下:
- sudo apt install python3-opencv
其次将图片路径修改为实际路径,修改如下图代码红框。
最后运行例程,指令如下:
- ros2 run learning_node node_object
例程运行成功后,会弹出一个可视化窗口,可以看到苹果被成功识别,一个绿色框会把苹果的轮廓勾勒出来,中间的绿点表示中心点。结果如下
二.话题
1.概念与定义
话题是节点间传递数据的桥梁。
通信模型
A节点的功能是驱动相机这个硬件设备,获取得到相机拍摄的图像信息,B节点的功能是视频监控,将相机拍摄到的图像实时显示给用户查看。
从节点A到节点B传递图像数据的方式,在ROS中,我们就称之为话题,它作为一个桥梁,实现了节点之间某一个方向上的数据传输。
发布/订阅模型
话题数据传输的特性是从一个节点到另外一个节点,发送数据的对象称之为发布者,接收数据的对象称之为订阅者,每一个话题都需要有一个名字,传输的数据也需要有固定的数据类型。其框架如下:
多对多通信
ROS里的话题 发布者和订阅者的数量并不是唯一的,可以称之为是多对多的通信模型。如果存在多个发送指令的节点,要注意区分优先级,不然机器人可能不知道该听谁的了。
异步通信
话题通信还有一个特性,那就是异步。一步主要是指发布者发出数据后,并不知道订阅者什么时候可以收到。异步的特性也让话题更适合用于一些周期发布的数据,比如传感器的数据,运动控制的指令等等。
消息接口
在ROS中,话题通信数据的描述格式称之为消息,对应编程语言中数据结构的概念。比如这里的一个图像数据,就会包含图像的长宽像素值、每个像素的RGB等等,在ROS中都有标准定义。
消息是ROS中的一种接口定义方式,与编程语言无关,我们也可以通过.msg后缀的文件自行定义,有了这样的接口,各种节点就像积木块一样,通过各种各样的接口进行拼接,组成复杂的机器人系统。
2.话题通讯案例
Hello World话题通信
这里选用learning_topic工作空间里的发布者learning_topic/topic_helloworld_pub.py,订阅者learning_topic/topic_helloworld_sub.py,代码如下
启动第一个终端,运行话题的发布者节点:
- ros2 run learning_topic topic_helloworld_pub
启动第二个终端,运行话题的订阅者节点:
- ros2 run learning_topic topic_helloworld_sub
运行结果如下。可以看到发布者循环发布“Hello World”字符串消息,订阅者也以几乎同样的频率收到该话题的消息数据。
流程总结
实现一个发布者,流程如下:
●编程接口初始化
●创建节点并初始化
●创建发布者对象
●创建并填充话题消息
●发布话题消息
●销毁节点并关闭接口
实现一个订阅者,流程如下:
●编程接口初始化
●创建节点并初始化
●创建订阅者对象
●回调函数处理话题数据
●销毁节点并关闭接口
至此,梳理了解了ROS2节点与话题,并通过实验实践予以实现。