教程五 RoArm-M1 ROS2 串口通信节点
RoArm-M1 教程目录
- 教程一 RoArm-M1 产品使用教程
- 教程二 RoArm-M1 二次开发教程
- 教程三 RoArm-M1 VirtualBox ROS2入门教程
- 教程四 RoArm-M1 ROS2 URDF模型入门教程
- 教程五 RoArm-M1 ROS2 串口通信节点
- 教程六 RoArm-M1 视频组装教程
- 教程七 RoArm-M1 图文组装教程
- RoArm-M1 WIKI 主页
RoArm-M1 ROS2串口通信节点教程
本文档用于RoArm-M1 ROS2串口通信节点教学。
简介
在ROS2中,节点(Node)、话题(Topic)、订阅(Subscription)和发布(Publisher)是核心概念,用于实现分布式系统中的通信。ROS2中的每个节点负责的是一个单一的、模块化的任务,每个节点都可以通过话题、服务等与其他节点发送和接收数据。
在我们的ROS2例程中,提供了两个ROS2包(packages),都位于roarm_ws/src中,其中roarm是URDF模型相关的包,serial_ctrl是串口通信节点相关的包。serial_ctrl节点用于将URDF包发布的姿态信息通过串口发送给机械臂,从而控制机械臂动作,姿态信息指的是机械臂各个舵机的绝对角度度数。在本教程中,我们会介绍这个节点的程序结构,以及这个节点的工作原理。
代码介绍
串口通信节点的主程序位于 serial_ctrl 中,文件名称为 serial_ctrl_py.py,由 python 语言编写,本教程介绍这个文件中的代码。
import rclpy from rclpy.node import Node import array from sensor_msgs.msg import JointState from std_msgs.msg import Float64 import json import serial
前三行为负责ROS2的python接口和节点类。
中间两行为姿态信息的数据格式。
最后两行为用于串口通信的库和用于编码解码json数据的库(串口通信采用JSON数据格式通信)。
ser = serial.Serial("/dev/ttyUSB0",115200)
实例化串口通信对象,我们这里使用的串口设备为USB0(此处是数字0),如果你将此程序移植到了其它设备上,需要更改这里的设备以及波特率。
class MinimalSubscriber(Node): def __init__(self): super().__init__('serial_ctrl') self.position = [] self.subscription = self.create_subscription( JointState, 'joint_states', self.listener_callback, 10) self.subscription # prevent unused variable warning def posGet(self, radInput, direcInput, multiInput): if radInput == 0: return 2047 else: getPos = int(2047 + (direcInput * radInput / 3.1415926 * 2048 * multiInput) + 0.5) return getPos def listener_callback(self, msg): a = msg.position join1 = self.posGet(a[0], -1, 1) join2 = self.posGet(a[1], -1, 3) join3 = self.posGet(a[2], -1, 1) join4 = self.posGet(a[3], 1, 1) join5 = self.posGet(a[4], -1, 1) data = json.dumps({'T':3,'P1':join1,'P2':join2,'P3':join3,'P4':join4,'P5':join5,'S1':0,'S2':0,'S3':0,'S4':0,'S5':0,'A1':60,'A2':60,'A3':60,'A4':60,'A5':60}) ser.write(data.encode()) print(data)
MinimalSubscriber 继承自 Node,用于定义一个 ROS2 节点:
__init__(self) 中定义了节点的名称 serial_ctrl。
create_subscription():表示创建一个订阅器,订阅器名为“joint_states”的JointState消息,回调函数为listener_callback,消息的队列长度为10;
posGet()函数:用于计算关节位置的函数,输入弧度制的角度、方向,以及减速比的参数后计算关节位置;
listener_callback()函数:订阅器的回调函数,当接收到JointState消息时被调用,从消息中获取弧度制的角度信息,并且将弧度制的角度信息转换成舵机的位置数据,将舵机的位置数据封装成JSON格式并通过串口发送给机械臂
def main(args=None): rclpy.init(args=args) minimal_subscriber = MinimalSubscriber() rclpy.spin(minimal_subscriber) # Destroy the node explicitly # (optional - otherwise it will be done automatically # when the garbage collector destroys the node object) minimal_subscriber.destroy_node() rclpy.shutdown()
main()函数中,首先初始化 rclpy,再创建 MinimalPublisher对象,rclpy.spin()表示进入循环,minimal_subscriber.destroy_node()表示节点被销毁。
编译
如果您在教程三中安装ROS2采用的是方法一,那么接下来终端都是进入roarm_ws文件夹下操作;如果您使用的是方法二,那么终端是进入RoArm-M1文件夹下操作。我这里都是在roarm_ws文件夹下进行操作的。
cd roarm_ws 进入工作空间,此处空间名,根据自己的镜像不同空间名可能不同,若教程三中是根据方法二进行的环境部署此处应为 cd RoArm-m1 colcon build
运行串口通信节点
首先将机械臂接通电源,使用USB线将机械臂与电脑连接。连接后,回到虚拟机,点击“设备”>“USB”,选择自己电脑对应的接口连接,这样机械臂就会连接到虚拟机上了。
打开一个新的终端
sudo chmod 777 /dev/ttyUSB0 如果这里报错,很可能就是您的虚拟机没有与机械臂相连接。 cd roarm_ws 进入工作空间,此处空间名,根据自己的镜像不同空间名可能不同,若教程三中是根据方法二进行的环境部署此处应为 cd RoArm-m1 source install/setup.bash 配置源文件
启动rviz2,请在终端中输入以下命令:
ros2 launch roarm roarm.launch.py
rviz2窗口会出现,显示出这个机械臂的模型。
上述终端不用关闭,打开一个新的终端,运行以下命令:
cd roarm_ws 进入工作空间,此处空间名,根据自己的镜像不同空间名可能不同,若教程三中是根据方法二进行的环境部署此处应为 cd RoArm-m1 source install/setup.bash
使用以下命令来运行串口通信节点,第一个serial_ctrl是roarm/src目录下的包,第二个是serial_ctrl包里面的serial_ctrl节点:
ros2 run serial_ctrl serial_ctrl
此时您应该打开了四个窗口,一个运行roarm.launch.py的终端窗口,一个运行serial_ctrl节点的终端窗口,一个rviz2中的机械臂模型窗口,一个控制面板窗口。调整这些窗口的位置,使您可以看到机械臂模型窗口,并且确保运行serial_ctrl节点的终端处于活动状态,接下来就可以通过拖拽控制面板的滑块来控制rviz2中的机械臂模型运动了,现实中的机械臂产品将跟着一起运动。
再次打开一个新的窗口,运行以下命令来查看所有正在运行的节点列表:
ros2 node list
可以看见系统中正在运行的节点的名称,使用ros2 node info <node_name>命令来获取有关节点的更多信息,它会返回一系列的订阅者、发布者、服务和动作信息。
我们这里查看串口通信节点/serial_ctrl的信息,请运行以下命令:
ros2 node info /serial_ctrl
自此,我们可以通过运行串口通信节点来控制机械臂的运动了。接着,我们根据后续的教程做进一步的学习。