ROS2入门21讲__第07讲__节点:机器人的工作细胞
目录
前言
通信模型
案例一:Hello World节点(面向过程)
运行效果
代码解析
创建节点流程
案例二:Hello World节点(面向对象)
运行效果
代码解析
创建节点流程
案例三:物体识别节点
运行效果
代码解析
案例四:机器视觉识别节点
运行效果
代码解析
节点命令行操作
思考题
前言
机器人是各种功能的综合体,每一项功能就像机器人的一个工作细胞,众多细胞通过一些机制连接到一起,成为了一个机器人整体。
在ROS中,我们给这些 “细胞”取了一个名字,那就是节点。
通信模型
完整的机器人系统可能并不是一个物理上的整体,比如这样一个的机器人:
在机器人身体里搭载了一台计算机A,它可以通过机器人的眼睛——摄像头,获取外界环境的信息,也可以控制机器人的腿——轮子,让机器人移动到想要去的地方。除此之外,可能还会有另外一台计算机B,放在你的桌子上,它可以远程监控机器人看到的信息,也可以远程配置机器人的速度和某些参数,还可以连接一个摇杆,人为控制机器人前后左右运动。
这些功能虽然位于不同的计算机中,但都是这款机器人的工作细胞,也就是节点,他们共同组成了一个完整的机器人系统。
- 节点在机器人系统中的职责就是执行某些具体的任务,从计算机操作系统的角度来看,也叫做进程;
- 每个节点都是一个可以独立运行的可执行文件,比如执行某一个python程序,或者执行C++编译生成的结果,都算是运行了一个节点;
- 既然每个节点都是独立的执行文件,那自然就可以想到,得到这个执行文件的编程语言可以是不同的,比如C++、Python,乃至Java、Ruby等更多语言。
- 这些节点是功能各不相同的细胞,根据系统设计的不同,可能位于计算机A,也可能位于计算机B,还有可能运行在云端,这叫做分布式,也就是可以分布在不同的硬件载体上;
- 每一个节点都需要有唯一的命名,当我们想要去找到某一个节点的时候,或者想要查询某一个节点的状态时,可以通过节点的名称来做查询。
节点也可以比喻是一个一个的工人,分别完成不同的任务,他们有的在一线厂房工作,有的在后勤部门提供保障,他们互相可能并不认识,但却一起推动机器人这座“工厂”,完成更为复杂的任务。
接下来,我们就来看看, 节点这个工作细胞,到底该如何实现。
案例一:Hello World节点(面向过程)
ROS2中节点的实现当然是需要编写程序了,我们从Hello World例程开始,先来实现一个最为简单的节点,功能并不复杂,就是循环打印一个“Hello World”字符串到终端中。
运行效果
大家先不要着急看代码,是骡子是马,先拉出来溜溜,我们通过ros2 run命令,运行编译好的课程代码,看下这个节点执行的效果如何,然后再来分析代码的实现过程,做到知其然也知其所以然。
ros2 run learning_node node_helloworld
运行成功后,可以在终端中看到循环打印“Hello World”字符串的效果。
代码解析
这个节点是如何实现的呢?我们来看下代码。
learning_node/node_helloworld.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-"""
@作者: 古月居(www.guyuehome.com)
@说明: ROS2节点示例-发布“Hello World”日志信息, 使用面向过程的实现方式
"""import rclpy # ROS2 Python接口库
from rclpy.node import Node # ROS2 节点类
import timedef main(args=None): # ROS2节点主入口main函数rclpy.init(args=args) # ROS2 Python接口初始化node = Node("node_helloworld") # 创建ROS2节点对象并进行初始化while rclpy.ok(): # ROS2系统是否正常运行node.get_logger().info("Hello World") # ROS2日志输出time.sleep(0.5) # 休眠控制循环时间node.destroy_node() # 销毁节点对象 rclpy.shutdown() # 关闭ROS2 Python接口
完成代码的编写后需要设置功能包的编译选项,让系统知道Python程序的入口,打开功能包的setup.py文件,加入如下入口点的配置:
entry_points={'console_scripts': ['node_helloworld = learning_node.node_helloworld:main',],
创建节点流程
代码中出现的函数大家未来会经常用到,大家先不用纠结函数的具体使用方法,更重要的是理解节点的编码流程。
总结一下,想要实现一个节点,代码的实现流程是这样做:
- 编程接口初始化
- 创建节点并初始化
- 实现节点功能
- 销毁节点并关闭接口
大家如果有学习过C++或者Pyhton的话,应该可以发现这里我们使用的是面向过程的编程方法,这种方式虽然实现简单,但是对于稍微复杂一点的机器人系统,就很难做到模块化编码。
案例二:Hello World节点(面向对象)
所以在ROS2的开发中,我们更推荐大家使用面向对象的编程方式,比如刚才的代码就可以改成这样,虽然看上去复杂了一些,但是代码会具备更好的可读性和可移植性,调试起来也会更加方便。
运行效果
接下来运行一下调整后的节点:
ros2 run learning_node node_helloworld_class
代码解析
功能虽然一样,但是程序的结构发生了变化,我们具体看一下这份代码。
learning_node/node_helloworld_class.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-"""
@作者: 古月居(www.guyuehome.com)
@说明: ROS2节点示例-发布“Hello World”日志信息, 使用面向对象的实现方式
"""import rclpy # ROS2 Python接口库
from rclpy.node import Node # ROS2 节点类
import time"""
创建一个HelloWorld节点, 初始化时输出“hello world”日志
"""
class HelloWorldNode(Node):def __init__(self, name):super().__init__(name) # ROS2节点父类初始化while rclpy.ok(): # ROS2系统是否正常运行self.get_logger().info("Hello World") # ROS2日志输出time.sleep(0.5) # 休眠控制循环时间def main(args=None): # ROS2节点主入口main函数rclpy.init(args=args) # ROS2 Python接口初始化node = HelloWorldNode("node_helloworld_class") # 创建ROS2节点对象并进行初始化rclpy.spin(node) # 循环等待ROS2退出node.destroy_node() # 销毁节点对象rclpy.shutdown() # 关闭ROS2 Python接口
完成代码的编写后需要设置功能包的编译选项,让系统知道Python程序的入口,打开功能包的setup.py文件,加入如下入口点的配置:
entry_points={'console_scripts': ['node_helloworld = learning_node.node_helloworld:main','node_helloworld_class = learning_node.node_helloworld_class:main',],
创建节点流程
所以总体而言,节点的实现方式依然是这四个步骤,只不过编码方式做了一些改变而已。
- 编程接口初始化
- 创建节点并初始化
- 实现节点功能
- 销毁节点并关闭接口
到这里为止,大家是不是心里还有一个疑惑,机器人中的节点不能只是打印Hello World吧,是不是得完成一些具体的任务。
案例三:物体识别节点
没错,接下来我们就以机器视觉的任务为例,模拟实际机器人中节点的实现过程。
我们先从网上找到一张苹果的图片,通过编写一个节点来识别图片中的苹果。
运行效果
在这个例程中,我们将用到一个图像处理的库——OpenCV,运行前请使用如下指令安装:
sudo apt install python3-opencv
然后就可以运行例程啦:
ros2 run learning_node node_object #注意修改图片路径后重新编译
运行前需要将learning_node/node_object.py代码中的图片路径,修改为实际路径,修改后重新编译运行即可:
image = cv2.imread('/home/hcx/dev_ws/src/ros2_21_tutorials/learning_node/learning_node/apple.jpg')
例程运行成功后,会弹出一个可视化窗口,可以看到苹果被成功识别啦,一个绿色框会把苹果的轮廓勾勒出来,中间的绿点表示中心点。
代码解析
在这个例程中,我们加入了图像识别的处理过程,模拟一个节点的功能,关于图像处理的具体实现,并不是此处的重点,大家更多要关注我们是如何通过节点的概念来实现一个具体的机器人功能。
learning_node/node_object.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-"""
@作者: 古月居(www.guyuehome.com)
@说明: ROS2节点示例-通过颜色识别检测图片中出现的苹果
"""import rclpy # ROS2 Python接口库
from rclpy.node import Node # ROS2 节点类import cv2 # OpenCV图像处理库
import numpy as np # Python数值计算库lower_red = np.array([0, 90, 128]) # 红色的HSV阈值下限
upper_red = np.array([180, 255, 255]) # 红色的HSV阈值上限def object_detect(image):hsv_img = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) # 图像从BGR颜色模型转换为HSV模型mask_red = cv2.inRange(hsv_img, lower_red, upper_red) # 图像二值化contours, hierarchy = cv2.findContours(mask_red, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE) # 图像中轮廓检测for cnt in contours: # 去除一些轮廓面积太小的噪声if cnt.shape[0] < 150:continue(x, y, w, h) = cv2.boundingRect(cnt) # 得到苹果所在轮廓的左上角xy像素坐标及轮廓范围的宽和高cv2.drawContours(image, [cnt], -1, (0, 255, 0), 2)# 将苹果的轮廓勾勒出来cv2.circle(image, (int(x+w/2), int(y+h/2)), 5, (0, 255, 0), -1)# 将苹果的图像中心点画出来cv2.imshow("object", image) # 使用OpenCV显示处理后的图像效果cv2.waitKey(0)cv2.destroyAllWindows()def main(args=None): # ROS2节点主入口main函数rclpy.init(args=args) # ROS2 Python接口初始化node = Node("node_object") # 创建ROS2节点对象并进行初始化node.get_logger().info("ROS2节点示例:检测图片中的苹果")image = cv2.imread('/home/hcx/dev_ws/src/ros2_21_tutorials/learning_node/learning_node/apple.jpg') # 读取图像object_detect(image) # 苹果检测rclpy.spin(node) # 循环等待ROS2退出node.destroy_node() # 销毁节点对象rclpy.shutdown() # 关闭ROS2 Python接口
完成代码的编写后需要设置功能包的编译选项,让系统知道Python程序的入口,打开功能包的setup.py文件,加入如下入口点的配置:
entry_points={'console_scripts': ['node_helloworld = learning_node.node_helloworld:main','node_helloworld_class = learning_node.node_helloworld_class:main','node_object = learning_node.node_object:main',],
案例四:机器视觉识别节点
用图片进行识别好像还不太合理,机器人应该有眼睛呀,没问题,接下来我们就让节点读取摄像头的图像,动态识别其中的苹果,或者类似颜色的物体。
运行效果
启动一个终端,运行如下节点:
ros2 run learning_node node_object_webcam #注意设置摄像头
如果是在虚拟机中操作,需要进行以下设置: 1. 把虚拟机设置为兼容USB3.1; 2. 在可移动设备中将摄像头连接至虚拟机。
运行成功后,该节点就可以驱动摄像头,并且实时识别摄像头中的红色物体啦。
代码解析
相比之前的程序,这里最大的变化是修改了图片的来源,使用OpenCV中的VideoCapture()来驱动相机,并且周期read摄像头的信息,并进行识别。
learning_node/node_object_webcam.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-"""
@作者: 古月居(www.guyuehome.com)
@说明: ROS2节点示例-通过摄像头识别检测图片中出现的苹果
"""import rclpy # ROS2 Python接口库
from rclpy.node import Node # ROS2 节点类import cv2 # OpenCV图像处理库
import numpy as np # Python数值计算库lower_red = np.array([0, 90, 128]) # 红色的HSV阈值下限
upper_red = np.array([180, 255, 255]) # 红色的HSV阈值上限def object_detect(image):hsv_img = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) # 图像从BGR颜色模型转换为HSV模型mask_red = cv2.inRange(hsv_img, lower_red, upper_red) # 图像二值化contours, hierarchy = cv2.findContours(mask_red, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE) # 图像中轮廓检测for cnt in contours: # 去除一些轮廓面积太小的噪声if cnt.shape[0] < 150:continue(x, y, w, h) = cv2.boundingRect(cnt) # 得到苹果所在轮廓的左上角xy像素坐标及轮廓范围的宽和高cv2.drawContours(image, [cnt], -1, (0, 255, 0), 2) # 将苹果的轮廓勾勒出来cv2.circle(image, (int(x+w/2), int(y+h/2)), 5, (0, 255, 0), -1) # 将苹果的图像中心点画出来cv2.imshow("object", image) # 使用OpenCV显示处理后的图像效果cv2.waitKey(50)def main(args=None): # ROS2节点主入口main函数rclpy.init(args=args) # ROS2 Python接口初始化node = Node("node_object_webcam") # 创建ROS2节点对象并进行初始化node.get_logger().info("ROS2节点示例:检测图片中的苹果")cap = cv2.VideoCapture(0)while rclpy.ok():ret, image = cap.read() # 读取一帧图像if ret == True:object_detect(image) # 苹果检测node.destroy_node() # 销毁节点对象rclpy.shutdown() # 关闭ROS2 Python接口
完成代码的编写后需要设置功能包的编译选项,让系统知道Python程序的入口,打开功能包的setup.py文件,加入如下入口点的配置:
entry_points={'console_scripts': ['node_helloworld = learning_node.node_helloworld:main','node_helloworld_class = learning_node.node_helloworld_class:main','node_object = learning_node.node_object:main','node_object_webcam = learning_node.node_object_webcam:main',],
节点命令行操作
节点命令的常用操作如下:
$ ros2 node list # 查看节点列表
$ ros2 node info <node_name> # 查看节点信息
思考题
现在,大家应该熟悉节点这个工作细胞的概念和实现方法了,回到这个机器人系统的框架图,我们还会发现另外一个问题。
电脑B中的摇杆,要控制机器人运动,这两个节点岂不是应该有某种连接,比如摇杆节点发送一个速度指令给运动节点,收到后机器人开始运动。
同理,如果我们想要改变机器人的速度,负责配置参数的节点就得发送一个指令给运动节点,如果电脑B想要显示机器人看到的图像,电脑A中的摄像头节点就得把图像发送过来。
没错,在一个ROS机器人的系统中,节点并不是孤立的,他们之间会有很多种机制保持联系,下一节,我们将给大家介绍这些机制中最为常用的一种。
相关文章:

ROS2入门21讲__第07讲__节点:机器人的工作细胞
目录 前言 通信模型 案例一:Hello World节点(面向过程) 运行效果 代码解析 创建节点流程 案例二:Hello World节点(面向对象) 运行效果 代码解析 创建节点流程 案例三:物体识别节点 …...

k8s node NotReady后会发生什么?
K8s 是一种强大的容器编排和管理平台,能够高效地调度、管理和监控容器化应用程序;其本身使用声明式语义管理着集群内所有资源模型、应用程序、存储、网络等多种资源,Node 本身又属于 K8s 计算资源,上面承载运行着各种类型的应用程…...

uni-starter创建App项目最全流程(日后还有其他功能会不断更新)
一、创建项目 在HbuilderX中点击创建项目,选择uni-starter模板,选择阿里云、Vue3,填写项目名称后点击创建。如果没有下载过uni-starter会自动下载该插件,如下图: 二、 创建云服务器并关联项目 如果是第一次使用&#…...
动态IP和静态IP区别
1.可变性:当设备重新连接时,动态IP将分配新的IP地址,静态IP将保持不变。 2.适用场景:动态IP适用于普通用户或小型办公室,静态IP适用于需要特定IP地址的服务或应用。 3.价格:动态IP通常比静态IP更经济。 4.管理和配置:动…...

蓝牙(2):BR/EDR的连接过程;查询(发现)=》寻呼(连接)=》安全建立=》认证=》pair成功;类比WiFi连接过程。
4.2.1 BR/EDR 流程: 查询(发现)》寻呼(连接)》安全建立》认证》pair成功 4.2.1.1 查询(发现)流程Inquiry (discovering) 类比WiFi的probe request/response 蓝牙设备使用查询流程来发现附近的…...
源码部署EFK
目录 资源列表 基础环境 关闭防护墙 关闭内核安全机制 修改主机名 添加hosts映射 一、部署elasticsearch 修改limit限制 部署elasticsearch 修改配置文件 单节点 集群(3台节点集群为例) 启动 二、部署filebeat 部署filebeat 添加配置文件 启动 三、部署kiban…...

CSDN智能总结助手
github项目地址: https://github.com/anjude/little-demo/tree/master 获取CSDN的user name和user token 打开csdn,打开控制台 - Application - Cookies,找到domain为blog.csdn.net的cookie,复制user_name和user_token的值 把上…...
setImmediate是在当前事件循环的所有周期的末尾执行,还是再当前事件循环的当前周期的下一个周期执行?
实际上,setImmediate 的回调函数会在当前事件循环的当前周期的末尾执行,而不是下一个周期。 在事件循环中,任务分为宏任务(macrotask)和微任务(microtask)。setImmediate 的回调函数属于宏任务…...
建材行业工程设计资质动态核查不通过怎么办
详细了解核查结果:首先,需要仔细阅读核查结果,了解不通过的具体原因。这些原因可能涉及企业基本情况、技术负责人情况、主要人员情况、设备和厂房情况、业绩和信誉等方面。 针对问题制定整改计划:根据核查结果,针对存…...

二叉数之插入操作
首先是题目 给定二叉搜索树(BST)的根节点 root 和要插入树中的值 value ,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。 注意,可能存在多种有效…...
【Python】全局变量与init的区别
一个脚本里,设置全局变量,和初始化类时__init__中加载,有什么区别? 在Python脚本中,使用全局变量和在类的__init__方法中加载数据有几个关键区别: 作用域: 全局变量:全局变量在整个…...
JAVA学习-练习试用Java实现“位1的个数”
问题: 编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 1 的个数(也被称为汉明重量)。 提示: 请注意,在某些语言(如…...

HTML静态网页成品作业(HTML+CSS)——魅族商城首页网页(1个页面)
🎉不定期分享源码,关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 🏷️本套采用HTMLCSS,未使用Javacsript代码,共有1个页面。 二、作品演示 三、代…...

Windows DNS 服务器配置转发器
DNS服务器转发器 在企业中由于自身条件的限制, 可能本身的DNS新能并不是很好,这个时候通过使用转发器功能, 将收到的DNS请求转发给另外一台高性能的DNS服务器,让其做后面的迭代查询。 1. 选择DNS服务器, 右击选择属性…...

基于FPGA的VGA协议实现----条纹-文字-图片
基于FPGA的VGA协议实现----条纹-文字-图片 引言: 随着数字电子技术的飞速发展,现场可编程门阵列(FPGA)因其高度的灵活性和并行处理能力,在数字系统设计中扮演着越来越重要的角色。FPGA能够实现复杂的数字逻辑&#…...
hdfs中MapReduce中的shuffle,combine和partitioner(hadoop,Hdfs)
1- MapReduce中shuffle阶段的工作流程以及何如优化该阶段? 分区 ,排序 ,溢写 ,拷贝到对应reduce机器上 ,增加combiner ,压缩溢写的文件 2-MapReduce中combine的作用,一般使用情景,…...

Linux应用入门(二)
1. 输入系统应用编程 1.1 输入系统介绍 常见的输入设备有键盘、鼠标、遥控杆、书写板、触摸屏等。用户经过这些输入设备与Linux系统进行数据交换。这些设备种类繁多,如何去统一它们的接口,Linux为了统一管理这些输入设备实现了一套能兼容所有输入设备的…...

高仿果汁导航模板
参考原文:果汁导航风格模板_1234FCOM专注游戏工具及源码例子分享 极速云...
机器学习之一分类支持向量机(One-class SVM)
一分类支持向量机(One-class SVM)是一种用于异常检测(outlier detection)和新颖性检测(novelty detection)的无监督学习算法。与传统的SVM不同,一分类SVM仅使用一种类别的数据进行训练,目的是在高维空间中找到一个最大边界超平面,将大部分数据点包含在超平面的一侧,从…...

签发免费https证书的方式
目录 http访问和https访问的区别 实现https后有哪些好处: 如何申请、安装部署免费https证书: 在浏览网页时,最常见的是http访问,但是也有一部分网站前缀是https,且浏览器网址栏会出现“安全”字样,或是绿…...

大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...