ROS2基础:核心概念与开发环境搭建

核心原理:从“进程孤岛”到“分布式协作”

ROS2 的本质是一套分布式通信中间件,它让多个独立运行的进程(即可执行程序)能够以松耦合的方式协同完成复杂任务。在机器人路径规划项目中,我们通常需要同时运行传感器驱动、定位模块、全局规划器、局部规划器、底盘控制等多个程序。如果这些程序各自为政,数据交换将变得极其困难。ROS2 通过四种核心通信原语解决了这一问题:节点(Node)、话题(Topic)、服务(Service)和动作(Action)。

节点是 ROS2 中最基本的计算单元,一个节点通常负责一个单一职责,例如“激光雷达驱动节点”或“路径规划节点”。节点之间不直接调用代码,而是通过“话题”进行异步数据流传输(如传感器数据流),或通过“服务”进行同步请求-应答(如查询地图信息)。当任务需要长时间执行且可能被取消时(如导航到目标点),则使用“动作”接口,它提供了反馈和取消机制。理解这四种原语的区别与适用场景,是后续编写路径规划代码的基石。

核心记忆点:话题是“数据流”的管道(单向、持续);服务是“指令-响应”的握手(双向、短时);动作是“任务-反馈-结果”的协议(长时、可中断)。节点则是所有通信的“参与者”。
传感器节点 /sensor/laser 定位节点 /localization/pose 路径规划节点 /planner/core 订阅地图/位姿 底盘控制节点 /cmd_vel 可视化节点 /map /path 话题: /scan 话题: /pose 话题: /cmd_vel 话题: /plan 服务: /get_map 动作: /navigate_to_pose (反馈+取消) 话题(单向数据流) 服务(请求/响应) 动作(目标/反馈/结果)

方法流程:搭建开发环境与验证通信

在 Ubuntu 22.04 系统上,我们推荐使用 ROS2 Humble 发行版。环境搭建的核心步骤包括:设置软件源、安装 ROS2 基础包、配置环境变量、安装开发工具(如 colcon 和 turtlesim 用于验证)。以下是关键命令序列:

# 1. 设置编码与软件源
sudo apt update && sudo apt install locales
sudo locale-gen en_US en_US.UTF-8
sudo add-apt-repository universe

# 2. 添加 ROS2 GPG 密钥与仓库
sudo apt install curl -y
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null

# 3. 安装 ROS2 Humble 桌面版(包含可视化工具)
sudo apt update
sudo apt install ros-humble-desktop python3-colcon-common-extensions

# 4. 环境变量配置(写入 ~/.bashrc)
echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc
source ~/.bashrc

安装完成后,务必使用 ROS2 自带的“小乌龟”模拟器进行通信验证。打开两个终端,一个运行 ros2 run turtlesim turtlesim_node,另一个运行 ros2 run turtlesim turtle_teleop_key。如果能够通过键盘控制小乌龟移动,说明节点发现、话题通信机制已正常工作。此时可以运行 ros2 node list 和 ros2 topic list 查看当前活跃的节点与话题。

工具/命令 作用 路径规划中的典型用途
ros2 node list 列出所有活跃节点 确认规划节点与底盘节点是否正常注册
ros2 topic echo /scan 打印话题数据流 检查激光雷达数据是否发布
ros2 service list 列出所有服务 查看地图服务是否可用
ros2 action list 列出所有动作 确认导航动作服务器已启动
colcon build 编译工作空间 编译自定义的规划器与控制器包

案例/场景:用“话题”驱动一个简单的路径跟踪

假设我们已有一个发布机器人位姿的节点(/pose),现在要编写一个“直线跟踪节点”,它订阅 /pose 并发布速度指令 /cmd_vel。这个场景直接体现了节点与话题的配合。以下是一个极简的 Python 节点骨架:

import rclpy
from rclpy.node import Node
from geometry_msgs.msg import Twist
from nav_msgs.msg import Odometry

class StraightLineController(Node):
    def __init__(self):
        super().__init__('straight_line_controller')
        self.publisher = self.create_publisher(Twist, '/cmd_vel', 10)
        self.subscription = self.create_subscription(
            Odometry, '/odom', self.odom_callback, 10)

    def odom_callback(self, msg):
        # 简单逻辑:如果 x 坐标小于 2.0 则前进,否则停止
        if msg.pose.pose.position.x < 2.0:
            vel = Twist()
            vel.linear.x = 0.2
            self.publisher.publish(vel)
        else:
            self.publisher.publish(Twist())  # 发布空速度

def main(args=None):
    rclpy.init(args=args)
    node = StraightLineController()
    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()

在这个案例中,create_subscription 让节点订阅 /odom 话题,每当有新的里程计数据到达时,回调函数就会被触发。节点内部计算后通过 create_publisher 向 /cmd_vel 发布速度指令。这种“订阅-处理-发布”的模式是 ROS2 中绝大多数算法节点的基本骨架。

误区/复盘:新手最容易踩的四个“坑”

  • 混淆“话题”与“服务”的适用场景。 新手常试图用服务来传输高频传感器数据,这会导致严重的阻塞。传感器流必须使用话题;只有偶尔一次的请求(如“保存当前地图”)才适合用服务。
  • 忘记 source 环境变量。 新开终端后直接运行 ros2 run 会报“找不到包”的错误。务必先执行 source /opt/ros/humble/setup.bash,或确保它已写入 ~/.bashrc。
  • 节点名与话题名不匹配。 发布者与订阅者必须使用完全相同的话题名(包括命名空间)。例如发布到 /cmd_vel,而订阅者监听 /robot/cmd_vel,则永远无法通信。使用 ros2 topic info /cmd_vel 可以快速排查。
  • 忽视“动作”与“服务”的差异。 如果导航任务需要 10 秒才能完成,使用服务会导致客户端一直阻塞等待。此时必须使用动作,以便在任务执行过程中持续接收反馈,并允许用户取消任务。
特别提醒:在编写路径规划代码时,务必为每个节点设置唯一的节点名。如果两个节点同名,ROS2 会随机丢弃其中一个,导致难以排查的间歇性故障。建议在节点构造函数中显式传入节点名,例如 Node('global_planner')。