2. ROS2核心概念与ROV软件架构
ROV(Remotely Operated Vehicle,遥控水下机器人)的软件系统天然是分布式的:操纵杆输入、推进器输出、深度传感器、摄像头、机械臂、导航滤波、故障监控往往运行在不同进程甚至不同计算单元上。ROS2 提供的节点、话题、服务、动作、参数五种通信与配置机制,正好对应 ROV 软件中不同性质的数据流与控制流。理解它们各自“适合承载什么”,比记住 API 更重要。
五种机制在ROV系统中的映射
节点(Node)是功能的最小部署单元。一个合理的 ROV 系统通常拆分为:joy_driver(手柄采集)、thruster_mixer(推力分配)、depth_sensor(深度发布)、imu_driver、camera_driver、rov_state_monitor(状态监控)等。拆分原则是“一个节点只负责一类硬件或一类算法”,便于单独启停与排障。
话题(Topic)承载高频、单向、可丢帧的连续数据流,是 ROV 中最主要的通信方式。典型话题包括:/cmd_vel(期望速度,来自手柄或上层控制器)、/thruster_cmd(各推进器 PWM 或推力指令)、/depth(米,向下为正)、/imu/data、/camera/image_raw。话题采用发布/订阅模型,发布者不关心谁在听,天然支持多消费者(例如图像同时给显示与目标检测)。
服务(Service)用于“请求—应答”式的短时同步操作,适合不频繁、需要立即返回结果的动作,例如 /set_mode(切换手动/定深模式)、/arm(解锁推进器)、/calibrate_imu。服务会阻塞等待响应,因此不能用于高频控制回路。
动作(Action)用于“耗时较长、需要过程反馈、可中途取消”的任务,是 ROV 自主作业的关键机制。例如 /goto_depth(目标深度 5.0 m,持续反馈当前深度与误差,可取消)、/move_distance(前进 3 m)、/scan_area(区域扫描)。动作由目标、反馈、结果三部分组成,客户端可实时监控进度。
参数(Parameter)是节点的可动态配置项,适合标定值与运行阈值,例如 thruster_max_pwm、depth_kp、pressure_offset、leak_alarm_threshold。参数可在启动时由 YAML 加载,也可运行时通过 ros2 param set 调整,避免为改一个增益而重新编译。
工作空间与功能包组织
ROS2 采用工作空间(workspace)管理源码与构建产物。一个 ROV 项目建议按“硬件驱动 / 控制算法 / 任务应用 / 描述与仿真”四类功能包组织,放在 src/ 下:
rov_ws/
├── src/
│ ├── rov_bringup/ # 启动文件、参数 YAML、launch 组合
│ ├── rov_drivers/ # 推进器、深度、IMU、摄像头驱动
│ ├── rov_control/ # 定深/定航向控制器、推力分配
│ ├── rov_missions/ # 动作服务器:定深、定距、区域扫描
│ ├── rov_description/ # URDF/xacro 模型、TF 树
│ └── rov_msgs/ # 自定义 msg/srv/action 接口
├── build/ install/ log/ # colcon 生成,不纳入版本管理
接口包 rov_msgs 单独拆出很关键:驱动包与控制包都依赖它,但彼此不直接依赖,降低耦合。构建时在 rov_ws 根目录执行 colcon build --symlink-install,随后 source install/setup.bash 使环境生效。参数集中放在 rov_bringup/config/ 下的 YAML 中,由 launch 文件按节点名加载,避免参数散落在代码里。
分层设计与一个可运行的配置示例
推荐三层结构:驱动执行层只做硬件读写与单位换算(如把电压换算为米、把归一化推力换算为 PWM);决策控制层做闭环控制与推力分配,不直接碰硬件;人机交互层负责任务下发与状态显示。层间只通过话题、服务、动作交互,这样仿真与实机可以替换驱动层而不改控制层。
以定深动作为例,动作定义可写为:
# rov_msgs/action/GotoDepth.action
float32 target_depth # 目标深度,米,向下为正
---
float32 final_depth # 实际到达深度
bool success
---
float32 current_depth # 周期反馈
float32 error # target - current
控制器参数示例(rov_bringup/config/depth_control.yaml,数值为教学假设值):
depth_controller:
ros__parameters:
depth_kp: 1.8
depth_ki: 0.15
depth_kd: 0.4
max_thrust: 0.7 # 归一化推力上限
depth_tolerance: 0.10 # 到达判据,米
feedback_rate: 10.0 # 动作反馈频率,Hz
运行时可用 ros2 param set /depth_controller depth_kp 2.2 在线调整增益,再用 ros2 topic echo /depth 观察深度曲线是否出现超调或振荡。判断是否达标的标准应事先明确:例如要求 30 秒内进入 ±0.10 m 并保持 10 秒不越界,则视为定深成功;若持续振荡,优先降低 depth_kp 或增大 depth_kd,而不是盲目加大推力上限。
ros2 node list 确认节点在线,再用 ros2 topic hz /depth 检查数据频率是否正常,最后用 ros2 topic info /cmd_vel 核对发布者与订阅者数量是否匹配。多数“机器人不动”的问题,根源是话题名不一致或 QoS 不兼容,而非控制算法本身。把五种机制各归其位,再配合清晰的功能包边界与三层架构,ROV 软件才能在仿真与实机之间平滑迁移,也才便于多人协作与逐层排障。