1. 课程导入

自动驾驶系统的开发有一个典型矛盾:算法迭代速度很快,但实车验证成本极高、风险极大。一次实车测试往往需要预约场地、准备车辆、安排安全员,还要承担碰撞与误触发带来的硬件损坏风险。ROS2 仿真与实车联调这门课,正是围绕“如何用仿真把大部分问题提前暴露,再用一套统一的软件架构把仿真成果平滑迁移到实车”这一工程主线展开。

本课程不是单纯讲某个仿真器怎么用,也不是只讲 ROS2 的语法,而是把 ROS2 通信机制、仿真环境、传感器建模、控制算法、实车接口、联调排障 串成一条完整的工程链路。学完之后,你应当具备独立搭建一个“仿真可跑、实车可接、问题可查”的自动驾驶小系统能力。

一、学习目标:从“会跑 demo”到“能交付系统”

本课程的学习目标分为四个层次,逐层递进:

  • 概念层:理解 ROS2 节点、话题、服务、动作、参数、TF 变换、QoS 等核心概念,并能说清它们与自动驾驶模块的对应关系。
  • 工具层:掌握 Gazebo、RViz2、ros2 bag、ros2 topic、ros2 launch、rqt 等工具在仿真与联调中的实际用法。
  • 系统层:能搭建“感知—定位—规划—控制”最小闭环,并在仿真中完成端到端验证。
  • 工程层:能把仿真节点替换为实车节点,处理时间同步、坐标系、通信延迟、传感器噪声等真实问题。
核心判断标准:一个合格的联调工程师,不是看仿真跑得多漂亮,而是看仿真到实车切换时,系统行为是否仍然可控、可解释、可复现。

二、核心概念:仿真与实车共享同一套“软件骨架”

ROS2 在自动驾驶中的价值,本质上是提供了一套分布式、可替换、可观测的软件骨架。仿真与实车的差异,主要发生在“传感器输入”和“执行器输出”两端,而中间的算法节点应当尽量保持一致。

几个必须建立直觉的核心概念:

  • 节点(Node):一个功能单元,例如激光雷达驱动、障碍物检测、路径规划、底盘控制。
  • 话题(Topic):节点之间异步传输数据的通道,如 /scan、/odom、/cmd_vel。
  • QoS:决定消息可靠性、历史深度和实时性策略,仿真与实车对 QoS 的要求常常不同。
  • TF 变换:描述坐标系之间的位姿关系,是感知、定位、控制能否对齐的关键。
  • 时间源:仿真常用 /clock 虚拟时间,实车使用系统时间,混用会导致严重时序问题。

下面这张图展示了仿真与实车联调的整体信号链与替换关系,是本课程后续所有章节的“总地图”:

ROS2 自动驾驶仿真与实车联调总览 仿真侧(Gazebo / 虚拟时间) 虚拟传感器 LiDAR / Camera / IMU / GNSS 仿真车辆模型 差速 / 阿克曼 / 动力学 /clock 虚拟时间 use_sim_time = true ros2 bag 录制 数据回放与复现 RViz2 可视化 调试与验证 共享算法层(ROS2 节点) 感知:检测 / 分割 / 跟踪 /perception/objects 定位:NDT / EKF / 里程计 /localization/pose 规划:全局 / 局部路径 /planning/trajectory 控制:Pure Pursuit / MPC /cmd_vel TF 树与坐标系管理 map → odom → base_link QoS / 参数 / Launch 统一管理 实车侧(真实传感器 / 系统时间) 真实传感器驱动 LiDAR / Camera / IMU / GNSS 底盘 CAN 接口 转向 / 驱动 / 制动 系统时间同步 PTP / NTP / 硬件触发 安全监控与急停 看门狗 / 遥控接管 实车日志与回放 问题定位与复盘 仿真 ↔ 实车 联调与数据回灌

三、整体框架:四层结构,两端替换

把上面的图抽象成工程语言,本课程采用“四层结构、两端替换”的框架:

层级 仿真侧 实车侧 联调关注点
传感器层 Gazebo 插件生成虚拟点云/图像 真实驱动发布原始数据 话题名、帧率、QoS、时间戳
算法层 尽量保持同一套 ROS2 节点 参数配置、坐标系、时间源
执行层 仿真车辆模型接收 cmd_vel CAN 网关转发到底盘 控制量范围、延迟、死区
工具层 RViz2 / ros2 bag / rqt 日志系统 / 远程监控 可观测性与问题复现

这个框架的关键思想是:算法层不动,两端可替换。只要传感器和执行器的接口约定清楚,仿真中验证过的规划控制逻辑,就可以以最小改动迁移到实车。

四、典型场景:从仿真到实车的第一次联调

假设你已经在 Gazebo 中完成了一个简单的循迹闭环:虚拟 LiDAR 发布 /scan,感知节点输出障碍物,规划节点生成路径,控制节点发布 /cmd_vel,仿真车能沿路径行驶。现在要把这套系统接到实车上,典型流程如下:

  1. 关闭 Gazebo 和虚拟传感器节点,启动真实 LiDAR 驱动,确认 /scan 话题有数据且 frame_id 正确。
  2. 检查 use_sim_time 参数,实车必须设为 false,否则节点会等待不存在的 /clock。
  3. 用 ros2 topic hz /scan 和 ros2 topic echo /scan --once 确认频率与字段。
  4. 启动算法层节点,观察 RViz2 中障碍物与路径是否正常。
  5. 将 /cmd_vel 先接入一个“空跑”节点打印数值,确认无误后再接入底盘 CAN。
  6. 低速、小范围、有人值守条件下进行首次实车运动测试。
# 实车联调常用检查命令
ros2 topic list
ros2 topic hz /scan
ros2 topic echo /odom --once
ros2 param get /controller use_sim_time
ros2 run tf2_tools view_frames
ros2 bag record /scan /odom /cmd_vel -o real_test_01
建议在实车联调前,先用 ros2 bag 录制一段仿真数据,再在实车上回放对比。这样可以把“算法问题”和“传感器/执行器问题”分开定位。

五、常见误区与复盘

初学者在仿真与实车联调阶段最容易踩的坑,往往不是算法本身,而是工程细节:

  • 误区一:仿真能跑,实车一定行。仿真传感器过于理想,实车噪声、延迟、遮挡会直接破坏感知与定位。
  • 误区二:忽略时间源。仿真用 /clock,实车用系统时间,混用会导致 TF 查询失败、消息超时。
  • 误区三:QoS 不匹配。传感器用 Best Effort,算法订阅用 Reliable,结果收不到数据。
  • 误区四:坐标系没对齐。LiDAR、IMU、车体之间的外参错误,会让障碍物“飘”在错误位置。
  • 误区五:直接全速接底盘。没有限速、没有急停、没有安全员,是实车调试的大忌。
实车联调的第一原则是安全:先空跑、再低速、再逐步放开。任何一次“应该没问题”的侥幸,都可能变成硬件损坏或人身风险。