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 
相关推荐
myw07120520 小时前
湘大头歌程-Ride to Office练习笔记
c语言·数据结构·笔记·算法
im_AMBER21 小时前
Leetcode 63 定长子串中元音的最大数目
c++·笔记·学习·算法·leetcode
箫笙默21 小时前
JS基础 - 正则笔记
开发语言·javascript·笔记
لا معنى له1 天前
残差网络论文学习笔记:Deep Residual Learning for Image Recognition全文翻译
网络·人工智能·笔记·深度学习·学习·机器学习
AGANCUDA1 天前
智能焊接机器人模拟器
机器人
张丶大帅1 天前
JS案例合集
开发语言·javascript·笔记
海伯森技术1 天前
赋予人形机器人“细腻触觉”:海伯森六维力传感器的材质与集成改革
人工智能·机器人·材质
就叫飞六吧1 天前
“电子公章”:U盾(U-Key)实现身份认证、财务支付思路
网络·笔记
郭庆汝1 天前
(七)自然语言处理笔记——Ai医生
人工智能·笔记·自然语言处理
czhc11400756631 天前
Winform笔记1129 checkbox listbox combabox checkedlistbox datapacker
笔记