2. ROS2基础与船舶仿真环境搭建

ROS2 是智能船舶仿真开发的“操作系统层”。在真正让无人艇、无人船在虚拟海面上动起来之前,必须先理解 ROS2 的四个核心通信概念,并把工作空间、运行时环境和仿真依赖一次性配置正确。本节围绕“概念—环境—依赖”三条主线展开,目标是让你能独立搭出一个可编译、可运行、可扩展的船舶仿真工程骨架。

一、四个核心概念:节点、话题、服务、动作

ROS2 把机器人系统拆成大量松耦合的计算单元,这些单元之间通过四种机制协作,理解它们的差异是设计船舶软件架构的前提。

节点(Node)是计算的最小单位,一个进程内可以运行多个节点。船舶仿真中常见的节点划分是:船体运动学节点、推进器控制节点、传感器驱动节点(GPS、IMU、激光雷达)、环境力节点(风、浪、流)。每个节点只负责一件事,便于单独调试和替换。

话题(Topic)是异步、多对多的数据流,采用发布/订阅模型。发布者只管发,订阅者只管收,双方互不知道对方存在。船舶场景中,/gps/fix、/imu/data、/cmd_vel 都适合用话题传输——传感器数据和控制指令都是持续流动的,不需要等待应答。

服务(Service)是同步的请求/响应模型,一问一答,调用方会阻塞等待结果。它适合“瞬时、有明确结果”的操作,例如查询当前船舶的电池电量、切换控制模式、请求一次地图重载。服务不适合高频调用,也不适合长时间任务。

动作(Action)是带反馈的长任务机制,由目标、反馈、结果三部分组成,且可中途取消。船舶自主靠泊、航点巡航、螺旋桨定速爬升这类“需要几十秒甚至几分钟、过程中要持续汇报进度、可能被中止”的任务,正是动作的典型用武之地。

ROS2 四种通信机制与船舶仿真对应关系 节点 Node(计算单元) 船体运动学节点 推进器控制节点 传感器驱动节点 环境力节点 仿真时钟节点 话题 Topic · 异步发布/订阅 多对多 · 持续数据流 · 无应答 /gps/fix /imu/data /cmd_vel /scan(激光雷达) 服务 Service · 同步请求/响应 一问一答 · 阻塞等待 · 瞬时操作 /get_battery_level /set_control_mode /reload_map /reset_origin 动作 Action · 目标 + 反馈 + 结果(可取消) 长任务 · 周期反馈 · 支持中止 /dock(自主靠泊) /navigate_to_pose /cruise_waypoints /throttle_ramp 目标 Goal 反馈 Feedback 结果 Result 选择原则:持续流用话题,瞬时问答用服务,长任务带反馈用动作

选择哪种机制,判断标准很直接:数据是否持续流动(话题)、是否需要立即得到唯一结果(服务)、任务是否耗时且需要进度反馈(动作)。把靠泊写成话题会丢失进度和取消能力,把 GPS 数据写成服务则会造成高频阻塞,这是初学者最常见的架构错误。

二、创建工作空间与功能包

ROS2 使用 colcon 构建系统,工作空间是源码、构建产物和安装产物的容器。推荐目录结构如下,其中 src 存放你自己编写的包,build、install、log 由构建工具自动生成,不应提交到版本库。

mkdir -p ~/ship_ws/src
cd ~/ship_ws/src
ros2 pkg create --build-type ament_cmake ship_sim \
  --dependencies rclcpp std_msgs geometry_msgs sensor_msgs
cd ~/ship_ws
colcon build --symlink-install
source install/setup.bash

--symlink-install 让安装目录以符号链接指向源码,修改 Python 脚本或配置文件后无需重新构建即可生效,调试阶段非常实用。每次打开新终端都要 source install/setup.bash,否则 ros2 run 找不到你的包。建议把该命令写入 ~/.bashrc,但要注意多个工作空间叠加时的覆盖顺序。

三、Ubuntu 与 ROS2 安装要点

智能船舶仿真通常选择 Ubuntu 22.04 + ROS2 Humble 这一长期支持组合,Gazebo 与 Nav2 生态成熟。安装流程的关键不是逐条抄命令,而是理解三个环节:配置软件源(添加 ROS2 官方 apt 源与密钥)、安装桌面版(ros-humble-desktop 含 RViz2 与示例)、初始化环境(source /opt/ros/humble/setup.bash)。安装后用 ros2 doctor 自检,若网络、RMW 实现或环境变量有问题,它会给出明确提示。国内网络环境下 apt 下载可能较慢,可配置镜像源,但密钥必须与官方一致,否则会出现签名校验失败。

四、船舶仿真依赖配置

船舶仿真与普通地面机器人最大的差异在于水动力与环境扰动。除 ROS2 桌面版外,还需要安装 Gazebo 仿真器、ros_gz 桥接包(连接 Gazebo 与 ROS2 话题)、xacro 与 robot_state_publisher(描述船体模型)、以及 teleop_twist_keyboard 用于手动测试。水动力通常通过自定义 Gazebo 插件实现,需要 gz-plugin 开发头文件与 CMake 依赖。

建议在安装完成后立即验证依赖链:启动一个空世界 gz sim empty.sdf,另开终端运行 ros2 run ros_gz_bridge parameter_bridge /clock@rosgraph_msgs/msg/Clock[gz.msgs.Clock,再用 ros2 topic echo /clock 观察仿真时钟是否流入 ROS2。时钟通了,说明桥接链路正常,后续传感器桥接才有意义。

五、一个可运行的最小验证

环境搭好后,用官方示例做端到端验证:终端一运行 ros2 run demo_nodes_cpp talker,终端二运行 ros2 run demo_nodes_py listener,看到 listener 持续打印 “I heard: [Hello World: N]” 即说明节点发现、话题通信、DDS 中间件全部正常。随后用 ros2 node list、ros2 topic list、ros2 topic hz /chatter 观察节点与话题,hz 输出约 1 Hz 即符合 talker 的默认发布频率。这一步看似简单,却是排查后续仿真问题的基准线——如果示例都不通,问题一定在环境而非你的船舶代码。

常见坑:在 Docker 或 WSL2 中运行时,多播可能被禁用,导致节点互相发现失败。此时需设置 ROS_LOCALHOST_ONLY=1 或指定 ROS_DOMAIN_ID,并确保同一域内的节点使用相同的 RMW 实现。

完成本节后,你应当拥有一个可编译的 ship_ws 工作空间、一套可自检的 ROS2 运行时、以及一条经过验证的 Gazebo—ROS2 桥接链路。这三样东西构成了后续所有船舶建模、传感器仿真与控制算法开发的底座。