3. ROS2核心概念速览
在把 UR 机械臂接入 ROS2 之前,必须先弄清 ROS2 的六个核心概念——节点、话题、服务、动作、参数、Launch 文件——它们不是孤立的知识点,而是 UR 驱动(ur_robot_driver)运行时彼此咬合的一整套通信骨架。理解它们各自“管什么、不管什么”,才能在后面配置驱动、写控制程序、排查故障时知道该看哪里。
一、六个概念各自解决什么问题
节点(Node)是 ROS2 中最小的可执行单元,一个进程里可以跑一个或多个节点。UR 驱动启动后,会形成若干节点:负责与控制器建立 TCP/IP 连接的驱动节点、负责把 UR 的关节状态转成 ROS2 消息的节点、以及可选的 robot_state_publisher、controller_manager 等。节点是“谁在干活”的答案。
话题(Topic)是异步、单向、多对多的数据流,采用发布/订阅模型。UR 驱动最典型的话题是 /joint_states(关节位置、速度、力矩)和 /tf(坐标变换)。话题适合高频、连续、不需要应答的数据,比如 125 Hz 的关节状态流。发布者只管发,订阅者只管收,双方互不知道对方存在。
服务(Service)是同步、双向、一对一的请求/响应模型。调用方发请求后会阻塞等待响应。UR 驱动中常见的服务包括 /io_and_status_controller/set_io(设置数字/模拟 IO)、/dashboard_client/play(通过 Dashboard 让机器人上电并进入运行态)。服务适合“做一件事并立刻知道结果”的短操作。
动作(Action)是带反馈、可取消、长时间运行的任务模型,底层由话题和服务组合实现。UR 驱动通过 /scaled_joint_trajectory_controller/follow_joint_trajectory 接收轨迹并执行,执行过程中持续发布进度反馈,允许中途取消。它适合“运动到某点”这类耗时且需要监控的任务。
参数(Parameter)是节点的配置项,在节点启动时或运行中可读写。UR 驱动的关键参数包括机器人 IP(robot_ip)、reverse_port、script_sender_port、kinematics 配置等。参数决定“节点以什么方式工作”,是集成时最需要核对的部分。
Launch 文件是启动编排脚本,用 Python 或 XML 描述“一次启动哪些节点、给什么参数、设什么命名空间、加载哪些控制器”。它把上面五个概念组织成一次可复现的启动过程。
二、它们如何串成一次完整的 UR 驱动集成
把六个概念放进一次真实启动里看,关系就清楚了。假设我们要用 UR5e 做关节空间运动控制,典型流程如下。
第一步,写 Launch 文件。在 ur_control.launch.py 中传入 ur_type:="ur5e"、robot_ip:="192.168.1.10"、reverse_port:=50001,并指定要加载的控制器列表。Launch 文件本身不干活,它只是把参数和节点声明组织起来。
第二步,Launch 启动后,ur_robot_driver 节点读取 robot_ip 参数,向 UR 控制器的 30001/30002 端口发起连接,同时通过 50001 反向端口接收 URScript 回传数据。这一步如果 IP 写错或端口被占用,节点会报连接超时——这是集成中最常见的第一个故障点。
第三步,controller_manager 根据 Launch 中声明的控制器配置,加载 joint_state_broadcaster 和 scaled_joint_trajectory_controller。前者把驱动收到的关节数据发布到 /joint_states 话题,后者提供 follow_joint_trajectory 动作接口。
第四步,控制程序(比如 MoveIt2 或自写节点)订阅 /joint_states 获取当前关节角,然后向 /scaled_joint_trajectory_controller/follow_joint_trajectory 发送动作目标。动作执行期间,程序可以收到进度反馈;如果发现异常,可以发送取消请求。
第五步,需要设置工具 IO 时,调用 /io_and_status_controller/set_io 服务,传入引脚号和电平值,服务返回成功或失败。需要让机器人从停止态恢复运行时,调用 /dashboard_client/play 服务。
整个过程中,参数决定了“连哪台机器人、用哪个端口”,Launch 决定了“启动哪些节点、加载哪些控制器”,话题承载了状态回传,动作承载了运动指令,服务承载了配置与状态切换。六者各司其职,缺一不可。
三、集成时最容易混淆的三个边界
话题与动作的边界。很多人会问:为什么关节状态用话题,而运动指令用动作?因为关节状态是持续、高频、不需要确认的流数据,用话题最自然;而运动指令是“发一次、执行一段时间、需要知道是否完成”的任务,用动作才能拿到反馈和取消能力。如果把运动指令硬塞进话题,就失去了执行进度和取消机制。
服务与动作的边界。服务适合毫秒级完成的短操作,比如设置一个 IO 电平;动作适合秒级甚至分钟级的任务,比如让机械臂走一条轨迹。判断标准很简单:操作是否需要持续反馈、是否可能中途取消。需要,就用动作;不需要,就用服务。
参数与话题的边界。参数是“启动前或运行中设定的配置”,话题是“运行中流动的数据”。robot_ip 是参数,因为它决定节点连哪台机器;/joint_states 是话题,因为它是运行中不断产生的数据。不要把应该做成参数的东西做成话题,也不要把应该做成话题的东西塞进参数。
ros2 node list # 确认驱动节点已启动
ros2 topic echo /joint_states --once # 确认关节状态话题有数据
ros2 param get /ur_robot_driver robot_ip # 确认参数已正确传入
ros2 service list | grep dashboard # 确认 Dashboard 服务可用
ros2 action list | grep trajectory # 确认轨迹动作接口已加载
如果某条命令没有输出或报错,就对应到上面六个概念中的某一环去排查。
四、一张对照表帮你快速定位
| 概念 | 通信模型 | UR 驱动中的典型实例 | 集成时关注点 |
|---|---|---|---|
| 节点 Node | 进程/可执行单元 | ur_robot_driver、controller_manager | 是否全部启动、命名空间是否冲突 |
| 话题 Topic | 异步、单向、多对多 | /joint_states、/tf | 频率是否正常、frame_id 是否正确 |
| 服务 Service | 同步、双向、一对一 | set_io、dashboard/play | 服务名是否匹配、调用是否超时 |
| 动作 Action | 异步、带反馈、可取消 | follow_joint_trajectory | 控制器是否加载、目标是否可达 |
| 参数 Parameter | 配置项、可读写 | robot_ip、reverse_port | IP/端口是否正确、类型是否匹配 |
| Launch 文件 | 启动编排 | ur_control.launch.py | 参数传递、控制器列表、命名空间 |
把这六个概念和它们在 UR 驱动中的具体实例对应起来,后面配置驱动、写控制程序、排查连接问题时,就能快速判断“现在该看节点、看话题、看服务,还是看参数”。这是从“知道概念”到“会用概念”的关键一步。