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

完成代码的编写后需要设置功能包的编译选项,让系统知道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机器人的系统中,节点并不是孤立的,他们之间会有很多种机制保持联系,下一节,我们将给大家介绍这些机制中最为常用的一种。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/637083.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

小蓝和小青在做数字破解游戏

小蓝和小青在做数字破解游戏,设某图案由m*n的0和1点阵组成&#xff0c;依照以下规则破解连续一组数值&#xff0c;从点阵图第一行第一个符号开始计算&#xff0c;从左到右&#xff0c;由上至下。第一个数表示连续有几个0&#xff0c;第二个数表示接下来连续有几个1&#xff0c;…

Nuxt3 实战 (七):配置 Supabase 数据库

前言 这个章节我们要先把数据库的环境配置好&#xff0c;古人云&#xff1a;工欲善其事&#xff0c;必先利其器。 这两天我一直在网上寻找最适合 Nuxt 的数据库&#xff0c;之前在做个人项目时经常用的是 Mysql 和 MongoDB&#xff0c;也用过 ORM 框架比如&#xff1a;Sequel…

flutter webview加载本地文件出现跨域解决方案

一直报错 [INFO:CONSOLE(17)] "Access to image at file:///android_asset/flutter_assets/assets/jump/box_bottom.png from origin null has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome…

留学服务平台应用架构的设计与优化

随着全球化进程的加速和人们对国际化教育的需求不断增长&#xff0c;留学服务平台在满足学生留学需求的同时也面临着诸多挑战。在这样的背景下&#xff0c;设计一个高效、稳定且安全可靠的留学服务平台应用架构显得尤为重要。本文将就留学服务平台应用架构的设计与优化进行探讨…

JKTECH柔性振动盘用途

柔性振动盘的作用与用途 在现代工业自动化领域&#xff0c;柔性振动盘凭借其独特的功能和广泛的应用场景&#xff0c;正逐渐成为生产线上的重要工具。柔性振动盘&#xff0c;又称柔性供料器&#xff0c;它结合了传统振动盘的高效性和现代自动化技术的灵活性&#xff0c;为各种…

vulhub——Aria2、bash、catic

文章目录 一、Aria2 任意文件写入漏洞二、CVE-2014-6271&#xff08;Bash Shell 漏洞&#xff09;三、CVE-2022-46169&#xff08;Cacti 前台命令注入漏洞&#xff09; 一、Aria2 任意文件写入漏洞 Aria2是一个命令行下轻量级、多协议、多来源的下载工具&#xff08;支持 HTTP…

【MySQL精通之路】InnoDB(10)-行格式

目录 1.表数据结构 1.1 聚集索引数据结构 1.2 辅助索引数据结构 2.行格式 2.1 REDUNDANT行格式 2.2 REDUNDANT存储特性 2.3 COMPACT行格式 2.4 COMPACT存储特性 2.5 DYNAMIC行格式 2.6 DYNAMIC存储特性 2.7 COMPRESSED行格式 2.8 COMPRESSED存储特性 3.定义表格的…

我怎么使用AI大语言模型学英语

今天已经是我开始英语拉练任务的第39天了&#xff0c;一直在笃定的、雷打不动的、机械笨拙的重复做一件事&#xff0c;那就是使用AI工具&#xff0c;将我想要说的话翻译成英文&#xff0c;生成语音文件&#xff0c;每天朗读三小时&#xff0c;最终整个背下来。我也在思考&#…

【人工智能】数据分析与机器学习——泰坦尼克号(更新中)

1912年4月15日&#xff0c;泰坦尼克号在首次航行期间撞上冰山后沉没&#xff0c;船上共有2224名乘客和乘务人员&#xff0c;最终有1502人遇难。沉船导致大量伤亡的重要原因之一是&#xff0c;没有足够的救生艇给乘客和船员。虽然从这样的悲剧性事故中幸存下来有一定的运气因素&…

Aware接口作用

介绍 Aware&#xff08;感知&#xff09;接口是一个标记&#xff0c;里面没有任何方法,实际方法定义都是子接口确定&#xff08;相当于定义了一套规则&#xff0c;并建议子接口中应该只有一个无返回值的方法&#xff09;。 我们知道spring已经定义好了很多对象&#xff0c;如…

半导体测试基础 - 基本概念

随着芯片集成度越来越高&#xff0c;手动测试已无法满足需求&#xff0c;因此要用到自动化测试设备&#xff08;ATE&#xff0c;Automated Test Equipment&#xff09;。因为现在的芯片原来越复杂&#xff0c;普通的 Bench 测试没法满足需求。ATE 可检测集成电路功能之完整性&a…

Joomla 3.7.0 (CVE-2017-8917) SQL注入漏洞环境

1 漏洞概述 Joomla是一个基于PHP的内容管理系统&#xff08;CMS&#xff09;&#xff0c;广泛应用于各类网站。2017年&#xff0c;Joomla 3.7.0版本被发现存在SQL注入漏洞&#xff08;CVE-2017-8917&#xff09;&#xff0c;攻击者可以利用该漏洞对数据库进行未授权查询或操作…

Centos 7.9 使用 iso 搭建本地 YUM 源

Centos 7.9 使用 iso 搭建本地 YUM 源 1 建立挂载点 [rootlocalhost ~]# mkdir -p /media/cdrom/ 2 创建光盘存储路径 [rootlocalhost ~]# mkdir -p /mnt/cdrom/ 3 上传 CentOS-7-x86_64-Everything-2207-02.iso 到 光盘存储路径 [rootlocalhost ~]# ls /mnt/cdrom/ CentOS-…

基于机器学习模型预测信用卡潜在用户(XGBoost、LightGBM和Random Forest)

基于机器学习模型预测信用卡潜在用户&#xff08;XGBoost、LightGBM和Random Forest&#xff09; 随着数据科学和机器学习的发展&#xff0c;越来越多的企业开始利用这些技术来提高运营效率。在这篇博客中&#xff0c;我将分享如何利用机器学习模型来预测信用卡的潜在客户。此…

如何设计足够可靠的分布式缓存体系,以满足大中型移动互联网系统的需要?no.31

传统 CAP 的突破 随着分布式系统的不断演进&#xff0c;会不断遇到各种问题&#xff0c;特别是当前&#xff0c;在大中型互联网系统的演进中&#xff0c;私有云、公有云并行发展且相互融合&#xff0c;互联网系统的部署早已突破单个区域&#xff0c;系统拓扑走向全国乃至全球的…

[深度学习]基于yolov8+bytetrack+pyqt5实现车辆进出流量统计+车辆实时测速实现

以前使用过yolov5deepsort实现过车辆进出流量统计车辆实时测速&#xff0c;可以看我往期视频&#xff0c;这回改成yolov8bytetrack实现&#xff0c;实时性更好&#xff0c;原理和原来一样。车流量进出统计车速测量优点&#xff1a; 使用目标检测算法考虑bbox抖动&#xff0c;解…

利用Python去除PDF水印

摘要 本文介绍了如何使用 Python 中的 PyMuPDF 和 OpenCV 库来从 PDF 文件中移除水印&#xff0c;并将每个页面保存为图像文件的方法。我们将深入探讨代码背后的工作原理&#xff0c;并提供一个简单的使用示例。 导言 简介&#xff1a;水印在许多 PDF 文件中都很常见&#x…

Spark项目实训(一)

目录 实验任务一&#xff1a;计算级数 idea步骤分步&#xff1a; 完整代码&#xff1a; linux步骤分布&#xff1a; 实验任务二&#xff1a;统计学生成绩 idea步骤分布&#xff1a; 完整代码&#xff1a; linux步骤分步&#xff1a; 实验任务一&#xff1a;计算级数 请…

【Linux001】centos常用命令总结总结(已更新)

1.熟悉、梳理、总结下centos知识体系。 2.Linux相关知识&#xff0c;在日常开发中必不可少&#xff0c;如一些必知必会的常用命令&#xff0c;如环境搭建、应用部署等。同时&#xff0c;也要谨慎使用一些命令&#xff0c;如rm -rf&#xff0c;防止一些生产事故的发生。 3.欢迎点…

洗衣行业在线预约小程序源码系统 在线下单+上门取件+订单状态跟踪 带网站的源代码包以及搭建部署教程

开发背景 在现代社会&#xff0c;人们越来越注重时间的利用和生活的便捷性。传统的洗衣服务模式往往需要消费者亲自将衣物送到洗衣店&#xff0c;然后再等待取衣&#xff0c;整个过程既耗时又不方便。此外&#xff0c;随着移动互联网的普及&#xff0c;人们更习惯于通过手机应…