1. ArduPilot无人船导航模块概述
大家好,我是老张。做无人船导航这块有些年头了。今天咱们聊聊ArduPilot在无人船上的导航模块,说白了就是让船自己知道「我在哪、要去哪、怎么去」的那套东西。
我个人习惯把导航模块比作船的「小脑」——它不直接控制油门舵机,但所有决策都依赖它提供的位置和航向信息。嗯,这个比喻你记住就好,后面会反复用到。
1.1 无人船导航系统架构
先看整体架构。一个典型的无人船导航系统,从上到下分四层:
| 层级 | 名称 | 典型组件 | 我的理解 |
|---|---|---|---|
| L4 | 任务规划层 | Mission Planner、QGroundControl | 告诉船「去A点采样,再去B点返航」 |
| L3 | 导航决策层 | ArduPilot导航模块、EKF滤波器 | 核心大脑,算位置、算路径 |
| L2 | 传感器层 | GPS、IMU、磁罗盘、里程计 | 感知外界,提供原始数据 |
| L1 | 执行层 | 电机、舵机、推进器 | 听指令干活 |
这里有个关键点:导航模块位于L3层。它接收L2层传感器的数据,经过融合计算,输出位置、速度、姿态给L4层的任务规划器。我在项目中遇到过不少新手,上来就调PID,结果船跑偏了才发现是GPS数据没进EKF——这就是典型的跳过导航层直接搞控制。
核心逻辑:导航模块 = 传感器数据 + 状态估计 + 路径规划。缺一不可。
为了让你更直观地理解,我画了张架构图:
1.2 ArduPilot在无人船中的应用
ArduPilot最早是为无人机写的,但用在船上其实更合适——为什么?因为船的运动比飞机慢,控制周期可以更长,对实时性要求没那么变态。我2018年第一次把ArduPilot移植到一条1.2米的调查船上,当时心里也没底,结果跑起来发现比想象中稳得多。
ArduPilot在无人船上的典型应用场景:
- 水文测绘:按预设航线走「之」字形,采集水深数据。我做过一个项目,船在太湖跑了6小时,航线偏差不超过1.5米。
- 环境监测:定点采样或沿河巡航,实时回传水质参数。
- 搜救巡逻:配合视觉模块,在指定区域做全覆盖搜索。
- 管道巡检:沿水下管道走向自动航行,这个对导航精度要求比较高。
小提示:ArduPilot的固件有专门的「Rover」版本,但无人船建议用「Boat」分支。两者区别在于Boat分支对水流扰动做了额外补偿,我踩过这个坑——用Rover固件跑船,转弯时侧滑严重。
1.3 导航模块核心功能
导航模块到底干了哪些活?我拆成三个核心功能来讲:
1.3.1 状态估计
说白了就是「猜自己在哪」。GPS告诉你大概位置,IMU告诉你加速度和角速度,磁罗盘告诉你朝向。但每个传感器都有噪声,怎么办?ArduPilot用扩展卡尔曼滤波器(EKF)把这些数据揉在一起,输出一个最优估计。
核心代码片段(简化版EKF预测步骤):
// 预测步骤:根据IMU数据推算下一时刻状态
void ekf_predict(float dt, float ax, float ay, float wz) {
// 位置预测
x_pred = x_est + vx_est * dt + 0.5f * ax * dt * dt;
y_pred = y_est + vy_est * dt + 0.5f * ay * dt * dt;
// 速度预测
vx_pred = vx_est + ax * dt;
vy_pred = vy_est + ay * dt;
// 航向预测
yaw_pred = yaw_est + wz * dt;
// 协方差更新(略)
}
这段代码看着简单,但实际工程里坑很多。我曾经在一条铁壳船上调试,磁罗盘读数一直跳,后来发现是船体钢材影响了磁场——最后不得不加装外置罗盘支架。
1.3.2 路径规划
ArduPilot支持多种导航模式:
| 模式 | 说明 | 适用场景 |
|---|---|---|
| Auto | 按预设航点自动航行 | 测绘、巡检 |
| Guided | 接收外部指令(如点击地图) | 遥控干预、避障 |
| Loiter | 悬停/定点保持 | 定点采样、等待 |
| RTL | 自动返航 | 紧急情况、低电量 |
这里要注意:Loiter模式在船上和飞机上完全不同。飞机可以悬停,船不行——船会漂。所以ArduPilot的Loiter模式在船上其实是「动力定位」,靠推进器对抗水流。我见过有人把Loiter参数调得太激进,结果船在原地画圈。
1.3.3 传感器融合与容错
这是导航模块最值钱的部分。ArduPilot支持多传感器冗余:你有两个GPS?可以。你有双IMU?也可以。系统会自动检测哪个传感器数据异常,然后切换或加权。
警告:不要同时使用两个不同品牌的GPS模块!我试过Ublox配国产GPS,两个模块的时钟偏差导致EKF发散,船直接往岸上冲。要么用同型号,要么做好时钟同步。
1.4 定制化需求分析
为什么需要定制化?因为ArduPilot是通用平台,而无人船场景千差万别。我总结了几类常见需求:
- 传感器适配:有些船用RTK-GPS,有些用单点GPS;有些用光纤陀螺,有些用MEMS。参数配置完全不同。
- 运动模型调整:双体船和单体船的转弯特性不一样,喷水推进和螺旋桨推进的响应也不一样。
- 导航策略定制:比如在狭窄河道里,需要更激进的避障逻辑;在开阔湖面,可以更注重路径平滑。
- 通信协议对接:有些用户要求导航数据通过4G回传,有些用数传电台,还有些用卫星通信。
嗯,说到这里,你应该明白了:定制化不是推翻ArduPilot重写,而是在它的框架下做参数调优和模块替换。我个人的做法是:先跑通默认配置,再逐项替换成自己的模块。这样出了问题,你知道是哪里改坏了。
一句话总结:导航模块是无人船的「数字孪生」——它在软件里维护了一个虚拟的船,这个虚拟船跟着真实船一起动,然后告诉真实船该怎么走。
好,第一章就到这里。内容不少,但都是干货。你如果现在去打开ArduPilot的源码,找到libraries/AP_NavEKF目录,会发现我刚才讲的东西全在里面。动手看看,比光听我讲强得多。