当前位置:网站首页>ROS2——node节点(七)
ROS2——node节点(七)
2022-07-05 06:35:00 【我与nano】
ROS2机器人操作系统
前言
机器人是各种功能的综合体,每一项功能就像机器人的一个工作细胞,众多细胞通过一些机制连接到一起,成为了一个机器人整体。
在ROS中,我们给这些 “细胞”取了一个名字,那就是节点。
一、通信模型
完整的机器人系统可能并不是一个物理上的整体,比如这样一个的机器人:
节点在机器人系统中的职责就是执行某些具体的任务,从计算机操作系统的角度来看,也叫做进程;
每个节点都是一个可以独立运行的可执行文件,比如执行某一个python程序,或者执行C++编译生成的结果,都算是运行了一个节点;
既然每个节点都是独立的执行文件,那自然就可以想到,得到这个执行文件的编程语言可以是不同的,比如C++、Python,乃至Java、Ruby等更多语言。
这些节点是功能各不相同的细胞,根据系统设计的不同,可能位于计算机A,也可能位于计算机B,还有可能运行在云端,这叫做分布式,也就是可以分布在不同的硬件载体上;
每一个节点都需要有唯一的命名,当我们想要去找到某一个节点的时候,或者想要查询某一个节点的状态时,可以通过节点的名称来做查询。
节点也可以比喻是一个一个的工人,分别完成不同的任务,他们有的在一线厂房工作,有的在后勤部门提供保障,他们互相可能并不认识,但却一起推动机器人这座“工厂”,完成更为复杂的任务。
二、具体使用
1.Hello World节点(面向过程)
ROS2中节点的实现当然是需要编写程序了,我们从Hello World例程开始,先来实现一个最为简单的节点,功能并不复杂,就是循环打印一个“Hello World”字符串到终端中。
ros2 run learning_node node_helloworld
代码解析:
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日志输出 类似print
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',节点.代码文件名.main
],
创建节点流程
编程接口初始化
创建节点并初始化
实现节点功能
销毁节点并关闭接口
2.Hello World节点(面向对象)
所以在ROS2的开发中,我们更推荐大家使用面向对象的编程方式,比如刚才的代码就可以改成这样,虽然看上去复杂了一些,但是代码会具备更好的可读性和可移植性,调试起来也会更加方便。
ros2 run learning_node node_helloworld_class
代码解析:
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',
],
运行一段代码之前要先进行编译,编译之后会把代码拷贝到install文件夹中,每次运行ros run 运行的都是install中的文件,不编译的话运行的就是旧代码。
编程接口初始化
创建节点并初始化
实现节点功能
销毁节点并关闭接口
3.物体识别节点
没错,接下来我们就以机器视觉的任务为例,模拟实际机器人中节点的实现过程。
我们先从网上找到一张苹果的图片,通过编写一个节点来识别图片中的苹果。
首先要安装opencv
sudo apt install python3-opencv
使用这条指令大概率不能用,我是跟着古月居得课程走得,然后踩了很多坑,可以使用下面两行代码进行安装。
pip3 install numpy
pip3 install opencv-python
然后就可以运行例程啦:
ros2 run learning_node node_object #注意修改图片路径后重新编译
运行前需要将learning_node/node_object.py代码中的图片路径,修改为实际路径,修改后重新编译运行即可:
image = cv2.imread('/home/qcx/dev_ws/src/ros2_21_tutorials/learning_node/learning_node/apple.jpg')
例程运行成功后,会弹出一个可视化窗口,可以看到苹果被成功识别啦,一个绿色框会把苹果的轮廓勾勒出来,中间的绿点表示中心点。
代码解析:
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/qcx/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摄像头的信息,并进行识别。
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接口
三、指令介绍
ls /dev/video* #查看摄像头的型号
ros2 node list # 查看节点列表
ros2 node info <node_name> # 查看节点信息
总结
在一个ROS机器人的系统中,节点并不是孤立的,他们之间会有很多种机制保持联系,下面就会介绍他们之间的联系。
边栏推荐
- The route of wechat applet jumps again without triggering onload
- H5内嵌App适配暗黑模式
- mysql设置触发器问题
- Xavier CPU & GPU high load power consumption test
- namespace
- Pycahrm reports an error: indentation error: unindent does not match any outer indentation
- PR automatically moves forward after deleting clips
- June 29, 2022 daily
- Log4qt usage of logbase in QT project
- Redis-01. First meet redis
猜你喜欢
Orin installs CUDA environment
Volcano 资源预留特性
Find the combination number acwing 889 01 sequence meeting conditions
Client use of Argo CD installation
[wustctf2020] plain_ WP
LSA Type Explanation - detailed explanation of lsa-2 (type II LSA network LSA) and lsa-3 (type III LSA network Summary LSA)
Idea debug failed
MPLS experiment
NVM Downloading npm version 6.7.0... Error
达梦数据库全部
随机推荐
时间很快,请多做有意义的事情
Page type
Integer to 8-bit binary explanation (including positive and negative numbers) scope of application -127~+127
UIO driven framework
Orin 安装CUDA环境
About vscode, "code unreachable" will be displayed when calling sendline series functions with pwntools“
Bit of MySQL_ OR、BIT_ Count function
Find the combination number acwing 887 Find combination number III
RecyclerView的应用
Vscode creates its own code template
Record of problems in ollvm compilation
How to answer when you encounter a jet on CSDN?
Configuration method and configuration file of SolidWorks GB profile library
vsCode创建自己的代码模板
Redis-01.初识Redis
Error: "mountvolume.setup failed for volume PVC fault handling
Ret2xx---- common CTF template proposition in PWN
MQClientException: No route info of this topic: type_ topic
Xavier CPU & GPU high load power consumption test
ollvm编译出现的问题纪录