ROS2 Humble 笔记(四)ROS 的最小工作单元-- Node 节点

这篇博客是 B 站《古月·ROS2入门21讲》的第七个视频的图文记录,主要介绍了一个常规 ROS 节点的结构是怎样的、如何配置 python 节点的程序入口、基于 opencv 本地与摄像头画面的识别实现。原始视频链接如下:


1. hello world 节点体验

在正式解析节点之前先运行一下古月的官方代码仓库提供的节点,进入到上一篇博客的 dev_ws 工作空间下编译该空间:

bash 复制代码
$ cd dev_ws
$ colcon build

编译完成后 source 一下 install 目录下的环境变量:

bash 复制代码
$ source source install/local_setup.sh 

使用下面的命令运行节点,该节点会以 1 Hz 的频率在终端打印 Hello World 字段:

bash 复制代码
$ ros2 run learning_node node_helloworld

2. 节点结构 - [面向过程]

该文件位于 src/ros2_21_tutorials/learning_node/learning_node/node_hello_world.py 处:

你可以用 vim 或者 vscode 打开这个文件以查看该文件中的内容,这个节点的内容非常短:

python 复制代码
#!/usr/bin/env python3 
# -*- coding: utf-8 -*-

import rclpy                                     # ROS2 Python接口库
from rclpy.node import Node                      # ROS2 节点类
import time

def 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接口

核心代码由三部分构成:

  1. 初始化节点rclpy.initNode("")
  2. 功能实现:functions;
  3. 销毁节点destory_node()rclpy.shutdown()

使用下面命令启动节点:

bash 复制代码
$ ros2 run learning_node node_helloworld

3. 节点结构 - [面向对象]

该文件位于 dev_ws/src/ros2_21_tutorials/learning_node/learning_node/node_helloworld_class.py 处:

python 复制代码
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import rclpy                                     # ROS2 Python接口库
from rclpy.node import Node                      # ROS2 节点类
import time

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节点对象并进行初始化
    node.destroy_node()                              # 销毁节点对象
    rclpy.shutdown()                                 # 关闭ROS2 Python接口

核心代码由三部分构成:

  1. 初始化节点rclpy.initNode("")
  2. 对象实例化:functions;
  3. 销毁节点destory_node()rclpy.shutdown()

使用下面的命令运行节点:

bash 复制代码
$ ros2 run learning_node node_helloworld_class 

4. python 程序入口点配置

只有当你的节点是以 python 形式实现的时候才需要配置程序入口点,C++ 实现的节点后面会介绍。

该文件位于 /dev_ws/src/ros2_21_tutorials/learning_node/setup.py 处,关注最下方 entry_points 字段:

python 复制代码
    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',
        ],
    },

其配置格式为,通常情况下会以脚本名作为可执行文件名,但这不是强制要求:

python 复制代码
可执行文件名 = 模块路径:main函数'
'node_name = learning_mix.node_name:main',

所有编译好的 python 节点会存储在 /home/orin/Desktop/dev_ws/install/learning_node/lib/learning_node 位置处:

【Note】:由于 python 本身是一个解释语言,因此即便是编译好的 lib 文件其本质上 仍是一个 python 文件,这和 C++ 生成一个二进制文件之间是有根本差异的。

你可以打开一个文件看看里面的内容,主要是写明了如何找到对应的 python 脚本位置。


5. 本地图像识别节点

作者在 src/ros2_21_tutorials/learning_node/learning_node/node_object.py 处提供了一个图像识别节点,你需要修改代码第 41 行附近的绝对路径,其原始文件就在当前目录下:

python 复制代码
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')  # 读取图像
    image = cv2.imread('/home/orin/Desktop/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接口

在你的环境中安装 python3-opencv

bash 复制代码
$ sudo apt-get install python3-opencv

运行该节点:

bash 复制代码
$ ros2 run learning_node node_object

如果你在运行后出现以下报错:

bash 复制代码
cv2.error: OpenCV(4.5.4) ./modules/imgproc/src/color.cpp:182: error: (-215:Assertion failed) !_src.empty() in function 'cvtColor'

可能是因为修改了 python 文件后没有重新编译的原因(这一点和 ROS1 存在显著区别),重新编译一下工作空间后再运行即可:

bash 复制代码
$ colcon build
$ ros2 run learning_node node_object

6. 摄像头图像识别节点

作者在该功能包下还提供了一个使用摄像头进行图像识别的节点,但由于我的设备上没有摄像头硬件,因此在这里就不进行演示了,有条件的读者可以直接运行下面的命令:

bash 复制代码
$ ros2 run learning_node node_object_webcam 
相关推荐
搞机械的假程序猿2 小时前
普中51单片机学习笔记-流水灯
笔记·学习·51单片机
lally.2 小时前
未来的一些想法和规划
笔记
xian_wwq3 小时前
【学习笔记】《孙子兵法》与网络安全
网络·笔记·学习
d111111111d3 小时前
STM32外设学习-ADC模数转换器(代码部分)四个模块,光敏,热敏,电位,反射式红外。
笔记·stm32·单片机·嵌入式硬件·学习
nenchoumi31193 小时前
ROS2 Humble 笔记(八)动作 action
笔记·机器人·ros2
三品吉他手会点灯4 小时前
STM32F103学习笔记-16-RCC(第3节)-使用HSE配置系统时钟并使用MCO输出监控系统时钟
c语言·笔记·stm32·单片机·嵌入式硬件·学习
摇滚侠4 小时前
Vue 项目实战《尚医通》,医院详情菜单与子路由,笔记17
前端·vue.js·笔记
CarmenHu4 小时前
IBM RAG挑战赛冠军方案学习笔记
笔记·学习
赶飞机偏偏下雨5 小时前
【MySQL笔记】索引 (非常重要)
笔记