1. ArduPilot无人船导航模块概述

大家好,我是老张。做无人船导航这块有些年头了。今天咱们聊聊ArduPilot在无人船上的导航模块,说白了就是让船自己知道「我在哪、要去哪、怎么去」的那套东西。

我个人习惯把导航模块比作船的「小脑」——它不直接控制油门舵机,但所有决策都依赖它提供的位置和航向信息。嗯,这个比喻你记住就好,后面会反复用到。

1.1 无人船导航系统架构

先看整体架构。一个典型的无人船导航系统,从上到下分四层:

层级 名称 典型组件 我的理解
L4 任务规划层 Mission Planner、QGroundControl 告诉船「去A点采样,再去B点返航」
L3 导航决策层 ArduPilot导航模块、EKF滤波器 核心大脑,算位置、算路径
L2 传感器层 GPS、IMU、磁罗盘、里程计 感知外界,提供原始数据
L1 执行层 电机、舵机、推进器 听指令干活

这里有个关键点:导航模块位于L3层。它接收L2层传感器的数据,经过融合计算,输出位置、速度、姿态给L4层的任务规划器。我在项目中遇到过不少新手,上来就调PID,结果船跑偏了才发现是GPS数据没进EKF——这就是典型的跳过导航层直接搞控制。

核心逻辑:导航模块 = 传感器数据 + 状态估计 + 路径规划。缺一不可。

为了让你更直观地理解,我画了张架构图:

无人船导航系统架构图 L4 任务规划层 Mission Planner / 自定义航点任务 L3 导航决策层(核心) ArduPilot导航模块 · EKF滤波器 · 路径规划 L2 传感器层 GPS · IMU · 磁罗盘 · 里程计 · 气压计 L1 执行层 电机 · 舵机 · 推进器 数据流向 →

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是通用平台,而无人船场景千差万别。我总结了几类常见需求:

  1. 传感器适配:有些船用RTK-GPS,有些用单点GPS;有些用光纤陀螺,有些用MEMS。参数配置完全不同。
  2. 运动模型调整:双体船和单体船的转弯特性不一样,喷水推进和螺旋桨推进的响应也不一样。
  3. 导航策略定制:比如在狭窄河道里,需要更激进的避障逻辑;在开阔湖面,可以更注重路径平滑。
  4. 通信协议对接:有些用户要求导航数据通过4G回传,有些用数传电台,还有些用卫星通信。

嗯,说到这里,你应该明白了:定制化不是推翻ArduPilot重写,而是在它的框架下做参数调优和模块替换。我个人的做法是:先跑通默认配置,再逐项替换成自己的模块。这样出了问题,你知道是哪里改坏了。

一句话总结:导航模块是无人船的「数字孪生」——它在软件里维护了一个虚拟的船,这个虚拟船跟着真实船一起动,然后告诉真实船该怎么走。

好,第一章就到这里。内容不少,但都是干货。你如果现在去打开ArduPilot的源码,找到libraries/AP_NavEKF目录,会发现我刚才讲的东西全在里面。动手看看,比光听我讲强得多。


专注资料整理