神经网络观测器+自适应滑模的无人船轨迹跟踪仿真实战解析
发布时间:2026/10/17 8:58:37 锦皓数字建站

先给各位泼一盆冷水冷静一下无人船轨迹跟踪难点从来不在“走直线”而在“船不知道自己是谁、也不知道自己被谁推着走”。模型参数不准、风浪流导致的外部扰动、速度状态测不准这三座大山压在控制器头上单靠一个PID或者普通滑模很容易在仿真的理想世界里做得漂亮一放到有干扰的模型里就满屏振荡。我去年花了大半个学期复现了一篇基于“神经网络观测器自适应滑模”的无人船轨迹跟踪论文从理论到Matlab仿真完整走了一遍这中间踩过的坑、想通的原理、调参的经验今天一次性写清楚。这篇内容适合三类人一是做船舶控制方向、需要复现论文做对比实验的研究生二是做水面无人艇工程实现、想提升抗扰能力又担心抖振的工程师三是刚接触滑模和神经网络控制、想理解这两个工具怎么配合的初学者。我会从“为什么这个组合能打”讲到模型公式从观测器设计讲到Matlab代码骨架最后把自己的调参心得和踩坑经历全部摊开。1. 为什么这个控制方案总能同时“抗干扰”又“不抖振”1.1 单独用滑模最大的坎抖振先说滑模控制它的思路简单粗暴设计一个滑模面让系统状态一旦到达这个面上就被“强制”沿着它滑向原点。因为这种强制作用是通过切换项实现的——控制量在正负两个方向之间高速切换——所以它对匹配扰动有天然的免疫能力。这是滑模最大的优点也是它最出名的痛点的来源抖振。抖振是什么感觉就好比你开车为了防止路面侧滑方向盘一直在微秒级别来回纠偏车上的人被晃得七荤八素。仿真代码里表现为控制输入螺旋桨推力、舵角在滑模面附近高频振荡工程里就是执行器发热断裂、船体振动、噪声放大。为了抑制抖振常规做法是引入边界层用饱和函数代替符号函数让切换变得柔和但边界层一旦太宽稳态误差又会增大。你调这个宽度就像调一枚硬币的直径——调大了塞不进插座调小了又短路。更要命的是滑模的鲁棒性是有前提的它要求不确定性有界且边界已知。但真实船舶的建模不确定项科氏力、阻尼系数、附加质量随航速和吃水变化外部扰动风浪流更是随机你根本拿不到那个“已知界”。于是要么把切换增益取巨大值换来严重的抖振要么取小值结果鲁棒性不够轨迹漂移。1.2 神经网络到底补了哪块短板神经网络在控制领域最常用的身份不是控制器而是“函数逼近器”。它有一个很实用的性质只要隐含层神经元数量足够多层前馈网络就能以任意精度逼近紧集上的连续函数。什么意思就是说系统里那些你想建模但建不准的部分——M、C、D矩阵里的参数不确定性、未建模动力学、甚至外部扰动的综合作用——都可以当成一个未知的复合函数交给神经网络在线逼近。但这个逼近能力不是白给的。第一神经网络能逼近的是“有界的未知函数”逼近误差本身有界但不可忽略第二权值必须在线更新否则固定权值网络在扰动变化后就“学不进去”第三神经网络需要输入状态而状态往往不全可测。这三点环环相扣正好把观测器也拉进了方案里。1.3 三个模块的分工观测器、逼近器、鲁棒器把这三个模块放在一起看它们的角色其实非常清晰像一支配合默契的小队神经网络观测器是“眼睛侦察兵”用可测的位置和艏摇角重构出不可测的速度同时在线逼近未知动态的复合项把船的真实状态和模型不确定性都“估”出来。自适应滑模控制器是“执行者兜底层”根据观测器和期望轨迹生成控制力矩其中自适应律在线调节切换增益把它调到“刚好足以克服残余扰动”的水平避免过保守取值。神经网络是“动态地图”为滑模控制器提供一个实时更新的模型补偿项让控制器不需要依赖精确模型。我之前总以为这是个复杂的多控制器协同后来想明白了本质上就是“模型补偿滑模鲁棒项”的经典分层结构只不过模型补偿项不用人工建模而是让神经网络在闭环运行中自己学出来观测器则解决速度状态不可测的工程现实。这三件事没有一件是可有可无的少任何一个整体性能都会明显劣化。2. 先把船说清楚三自由度模型与不确定性建模2.1 运动学与动力学一个方程两个世界水面船舶的轨迹跟踪一般用三自由度模型忽略横摇和纵摇只考虑纵荡surge、横荡sway和艏摇yaw三个方向。定义两个坐标大地坐标系下的位姿向量η [x, y, ψ]^Tx和y是平面位置ψ是艏摇角。船体坐标系下的速度向量ν [u, v, r]^Tu是纵向速度v是横向速度r是艏摇角速度。运动学关系非常简单直接η̇ J(ψ) ν其中J(ψ)是旋转矩阵形式如下J(ψ) [cosψ -sinψ 0; sinψ cosψ 0; 0 0 1]注意这个矩阵是正交的有J^{-1}(ψ) J^T(ψ)这个性质后面推导控制律时经常用到代码里直接用转置而不是求逆可以省很多麻烦。动力学方程是三自由度下面最常用的矩阵形式M ν̇ C(ν)ν D(ν)ν g(η) τ τ_d其中M是包含附加质量的惯性矩阵C(ν)是科氏力和向心力矩阵D(ν)是线性加非线性阻尼矩阵g(η)是恢复力/力矩对水面船通常忽略τ是控制输入τ_d是外部环境扰动。实际建模时M、C、D都是标称值加不确定项的形式这就是控制器的麻烦来源。2.2 怎么把“未知的东西”剥离出来喂给神经网络控制设计里我们通常不喜欢上面那种“全矩阵形式”而会做一步重组。把动力学方程改写成M₀ ν̇ N(ν) τ_d τ这里M₀是标称惯性矩阵N(ν)整合了所有说不清楚的东西包括参数不确定、科氏阻尼、未建模动态、扰动等。控制器的目标就变成设计τ让系统能在“N(ν)完全未知”的情况下跟踪期望轨迹。为什么要这样重组因为神经网络要逼近的正是这个N(ν)。它是一个从速度状态ν到广义力的映射。只要输入给神经网络的信号速度估计值和参考速度是在一个合理的紧集内网络就能在线逼近这个复合未知项。我做仿真的经验是这里千万别把N(ν)拆回M、C、D然后分别估计那样既复杂又容易出错。直接把它当成一个整体丢给神经网络网络会自己学出一个“等效未知力”你再把它作为前馈补偿加进去就好。2.3 控制目标的数学表述轨迹跟踪的目标不是单纯的“位置到达终点”而是“船的位置和艏摇角始终跟上一条随时间变化的期望轨迹”。设期望位姿为η_d(t)它通常是时间参数化的路径比如圆形轨迹x_d(t) A sin(ωt)y_d(t) A cos(ωt)ψ_d(t) atan2(ẏ_d, ẋ_d)定义位姿跟踪误差e η - η_d定义虚拟速度误差在船体坐标系下表达便于控制器使用s ν - ν_d其中ν_d J^T(ψ) η̇_d 是一个“期望速度的投影”。这个变换很重要因为控制器生成的是船体坐标系下的力而跟踪误差是在大地坐标系下定义的两者必须通过旋转矩阵建立联系。综合下来控制目标可以精确表述为设计控制输入τ使得在N(ν)未知、速度状态不完全可测、外部扰动存在的情况下跟踪误差e和误差速度s都一致最终有界UUB并最终收敛到原点附近的小邻域内。注意“一致最终有界”这个词它和“渐进稳定”不一样在扰动和逼近误差作用下我们不能要求误差严格趋于零只能要求它趋向一个可调节的界以内。这个界的半径由边界层宽度、神经网络逼近误差上界、自适应律参数共同决定这也是调参的重要理论依据。3. 神经网络观测器状态不可测时怎么“猜”出船的实时速度3.1 为什么不能直接微分位置得到速度很多入门者第一个反应是位置可测那对时间求导不就是速度吗理论上可以工程上不行。GPS的位置输出频率低通常5到10Hz差分后噪声被急剧放大相位还滞后低成本惯性单元输出的加速度漂移严重积分一次速度就飞了。你要是把这个“带噪声的伪速度”直接喂给控制器滑模切换项会把噪声当成扰动放大控制输入高频抖动船还没走稳执行器先累了。所以工程里更靠谱的做法是把速度当成“需要重构的未知状态”基于模型和位置测量做观测器。观测器的好处是它自带滤波特性能把高频噪声压掉同时利用模型信息做预测比单纯微分准得多。3.2 观测器的结构设计与神经网络逼近观测器的设计思路不复杂就是“模型预测输出误差修正”。写成形式化一点的式子就是[ \begin{cases} \dot{\hat{\eta}} J(\psi)\hat{\nu} k_1 e_\eta \ M_0 \dot{\hat{\nu}} \tau \hat{W}^T \phi(\hat{\nu}) k_2 e_\eta \end{cases} ]其中e_η η - η̂是位置估计误差k₁和k₂是观测器增益通常取对角正定矩阵Ŵ^T φ(ν̂)是神经网络对未知复合项N(ν)的在线估计。解释一下这个结构的物理含义第一条方程是从估计速度重构位置第二条方程是从控制输入和神经网络补偿“积分”出估计速度而位置误差e_η作为反馈修正项实时纠正估计偏差。这里有一个很容易忽略的细节神经网络输入的其实是估计速度ν̂而不是真实速度ν。为什么因为我们根本测不到ν只有ν̂。这会导致网络输入和理想输入之间有偏差好在观测器有收敛性保证——只要观测器增益k₁、k₂取得合适ν̂会收敛到ν的小邻域内神经网络的逼近误差也就可控了。这个问题一定要在理论上想清楚否则仿真里看到观测器发散你都不知道是网络的问题还是增益的问题。3.3 高斯基函数参数与观测器增益怎么定神经网络部分我用的结构是RBF径向基函数网络激活函数是高斯基函数φ_j(ν̂) exp(-||ν̂ - c_j||² / b_j²)其中c_j是第j个隐含层节点的中心b_j是宽度。这里有两个参数的选择经验中心c_j的分布范围要覆盖速度状态的正常工作范围。比如u大约在0~2 m/sv在-1~1 m/sr在-0.5~0.5 rad/s那你取3×3×327个中心均匀分布在这个立方体内。我第一次复现时偷懒把中心全设在原点附近结果网络“学不进去”误差一直在高位徘徊。后来想明白了高斯基函数是局部响应的如果输入速度离所有中心都太远所有激活值都趋近于零网络输出也趋近于零补偿效果完全消失。宽度b²不宜太大也不宜太小。太大则各中心响应重叠严重网络分辨率下降太小则形成一个个孤岛输入稍偏离就激活不了。我的经验是取与中心间距相当的量级比如中心间距0.5宽度b²取0.5~1。观测器增益k₁和k₂的取值影响估计收敛速度。k₁太大位置估计对噪声敏感k₂太大速度估计容易振荡。我先给一组能用的保守值k₁ 2Ik₂ 5I然后再慢慢加大直到观测误差收敛时间短且无明显振荡为止。你复现时如果发现观测器输出毛刺很多第一件事是减小k₁而不是增大k₂。4. 自适应滑模控制器从Lyapunov推导到切换项消抖4.1 滑模面设计与等价控制控制器部分核心是设计滑模面。我采用一种比较顺手的定义把位姿误差e和虚拟速度误差s组合起来σ s λ e其中λ是一个正定对角矩阵决定了“位置误差”和“速度误差”在滑模面中的权重。σ 0意味着误差动态退化成s -λe这是一个指数收敛的动态所以只要把σ稳定到原点跟踪误差自然收敛。接下来设计控制律标准步骤是令σ̇ 0求出等价控制。推导的关键是把σ̇展开σ̇ ṡ λė代入运动学关系η̇ J(ψ)ν和动力学方程M₀ν̇ N(ν) τ整理后得到σ̇ -M₀^{-1}(C(ν)ν D(ν)ν N(ν) - τ) ...具体形式取决于你的中间变量直接处理太繁琐我给出最后设计出来的控制律典型形式τ Ŵ^T φ(ν̂) - K̂ sat(σ/Δ) - M₀ λ s三项的分工很明确第一项Ŵ^T φ(ν̂)是神经网络前馈补偿用来消除未知模型N(ν)的影响第二项K̂ sat(σ/Δ)是自适应滑模项用来抵抗残余扰动和逼近误差第三项M₀ λ s是误差动态整形项保证滑模面的收敛速度。4.2 自适应增益与边界层抖振的三种对策抖振问题在这个控制律里对应两个决策符号函数还是饱和函数固定增益还是自适应增益符号函数sgn(σ)在零点附近不连续数值仿真里会造成控制量在每步求解中来回跳变这就是抖振来源。我复现时试过sgnSimulink图形窗口里的控制输入曲线像一把梳子实测船体航向也在中高频摆动。后来改用饱和函数sat(σ/Δ)也就是把σ/Δ超过±1的部分钳位到±1在边界层内线性过渡。Δ取0.02~0.05时轨迹误差基本不受影响但控制输入平滑了一大截。代价是稳态误差从理论零变成与Δ相关的有界值不过在这个问题里完全可接受。但光是换成饱和函数还不够因为增益K̂如果固定取得很大边界层内的等效增益还是高控制输入依然偏“燥”。所以更优雅的做法是让K̂在线自适应更新常用更新律是[ \dot{\hat{K}} \gamma_K \left( |\sigma| - \rho_K \hat{K} \right) ]第一项是“误差大就加大增益”第二项是“防止增益无限漂移自动衰减”ρ_K就是一个很小的衰减系数。这个自适应律比固定增益好在哪它能让增益“按需分配”初始误差大时增益快速上升快速收敛稳态时误差小增益慢慢衰减到一个较低水平抖振随之减小。我实测中固定增益需要取到K8才能压住扰动而自适应增益稳定后只在4左右徘徊控制输入的最大幅值下降了将近三分之一。4.3 Lyapunov稳定性证明的思路整理这部分是论文的核心理论贡献也是复现时最容易懵的点。完整证明很长但思路并不复杂我把主线捋清楚构造一个Lyapunov候选函数把滑模面σ、神经网络权值估计误差W̃ W - Ŵ、自适应增益估计误差K̃ K* - K̂都装进去V (1/2)σ^T M₀ σ (1/2)tr(W̃^T Γ^{-1} W̃) (1/2γ_K)K̃²第一项对应滑模面能量第二项对应对权值估计误差的能量第三项对应增益估计误差的能量。对V求时间导数代入控制律和更新律目标是让V̇写成负定项加有界项的形式V̇ ≤ -cV ε̄其中c是一个由控制器参数决定的正数ε̄是神经网络逼近误差上界和扰动上界的组合。这个不等式推出的是“一致最终有界”而不是“渐近稳定”当时间趋于无穷时σ会收敛到半径为ε̄/c的球内。这意味着你无法让误差归零但可以通过增大λ、调节自适应律参数把界压小。复现论文时我犯过一个错误把注意力全放在控制器调参上忽略了稳定性证明里对“自适应律必须加入衰减项”的要求。结果仿真里权值一直增大超调越来越明显后来才发现是遗忘因子ρ_K和权值衰减项没加。所以我的建议是写代码之前先自己动手把Lyapunov流程走一遍哪怕你不追求严格证明也要理解哪些项是必须保留的。5. Matlab代码实现从S函数到Simulink的完整骨架5.1 整体仿真架构先说大框架。我复现时采用Simulink为主、S函数为辅的结构分四个模块期望轨迹生成模块用MATLAB Function块实现输入时间t输出η_d, η̇_d, η̈_d。船舶模型模块用S函数写三自由度动力学和运动学方程作为被控对象。这一步要特别注意模型得比你控制器里“以为”的模型多出不确定性否则闭环里神经网络没有用武之地对比实验也没有说服力。观测器模块S函数输入η、τ输出η̂、ν̂、Ŵ。控制器模块S函数或者MATLAB Function块输入η̂、ν̂、期望轨迹信息输出τ。模块之间的信号线不要搞乱尤其是η̂和η别接反。我第一次就是把观测器的估计位置接到了控制器里当真实位置用仿真曲线看起来“完美”后来一想这不是自欺欺人吗。做对比实验时真实位置只能用于船舶模型更新控制器和观测器一律只能用带噪声的测量输出。5.2 圆形轨迹生成与控制律核心代码期望轨迹我喜欢用圆形因为它的位置、速度和角速度都是周期光滑的便于观察稳态误差function [eta_d, eta_dot_d, eta_ddot_d] desired_trajectory(t) A 5.0; % 轨迹半径 w 0.1; % 角频率 x A * sin(w*t); y A * cos(w*t); psi w*t; % 艏摇角设为切线方向 x_dot A*w * cos(w*t); y_dot -A*w * sin(w*t); psi_dot w; x_ddot -A*w^2 * sin(w*t); y_ddot -A*w^2 * cos(w*t); psi_ddot 0; eta_d [x; y; psi]; eta_dot_d [x_dot; y_dot; psi_dot]; eta_ddot_d [x_ddot; y_ddot; psi_ddot]; end控制律核心部分我用一个简单的MATLAB Function块实现。注意这里的输入是观测器输出不是真实状态function tau controller(eta_hat, nu_hat, eta_d, eta_dot_d, W, t) % 参数 lam diag([2.0, 2.0, 2.0]); Delta 0.03; M0 diag([25, 25, 12]); % 跟踪误差 e eta_hat - eta_d; nu_d J(eta_hat(3)) * eta_dot_d; s nu_hat - nu_d; sigma s lam * e; % 神经网络前馈 phi gaussian_basis(nu_hat); u_nn W * phi; % 自适应滑模项 K_hat 4.0; % 自适应律更新后的增益作为外部状态传入 u_sw -K_hat * sat(sigma / Delta); % 误差动态整形 u_pd -M0 * lam * s; tau u_nn u_sw u_pd; end这里有一个可以优化的点饱和函数sat(x)在Matlab里可以写成max(-1, min(1, x))。你可以试试点符号函数和不点的区别仿真结束后对比两张控制输入曲线抖振问题一看就懂。高斯基函数部分我的建议是把中心和宽度预先算好并保存在结构体里不要每次仿真步都重新生成function phi gaussian_basis(nu) % nu是3x1列向量 N 27; % 3个方向各3个中心 centers zeros(3, N); % 预生成u ∈ [0,2], v ∈ [-1,1], r ∈ [-0.5,0.5] idx 1; for i 1:3 for j 1:3 for k 1:3 centers(:, idx) [0 (i-1)*1; -1 (j-1)*1; -0.5 (k-1)*0.5]; idx idx 1; end end end b2 0.8; phi zeros(N, 1); for j 1:N dist2 sum((nu - centers(:,j)).^2); phi(j) exp(-dist2 / b2); end end5.3 仿真参数总表与ode45步长选择整个仿真的核心参数我整理成一张表方便你起步时直接用参数值说明标称惯性矩阵 M₀diag([25, 25, 12])包含附加质量未知扰动上界2.0用于对比测试滑模面系数 λdiag([2.0, 2.0, 2.0])越大收敛越快过大则噪声敏感边界层宽度 Δ0.03越小越接近符号函数抖振越大自适应增益 γ_K0.5控制增益调整速度遗忘因子 ρ_K0.01防止增益无限积分观测器增益 k₁2.0位置修正项观测器增益 k₂5.0速度修正项神经网络节点数273个速度维度各取3个中心高斯基函数宽度 b²0.8与中心间距同量级求解器方面我用的是ode45最大步长设置为0.01秒相对误差1e-6。为什么强调最大步长因为切换项即使改成了饱和函数依然存在从线性区到饱和区的转折如果步长太大求解器可能“跳过”转折点导致积分误差累积。我第一次跑仿真时偷懒没设最大步长结果同样的参数跑两次结果不一样——这就是数值求解不稳定的典型信号。设成0.01秒后结果可复现曲线干净很多。6. 复现结果怎么看从三条曲线判断这组参数行不行6.1 误差曲线与控制输入曲线跑完仿真先别急着看轨迹拟合图那是“最会骗人”的图。我建议依次看三条曲线第一是位姿误差曲线e(t) η - η_d。这条曲线里能看到收敛时间、稳态误差、有没有超调。以我用的参数为例初始位置误差设定为(2, -2, 0.5)大约8秒后误差收敛到稳态带内x方向稳态误差±0.05米y方向±0.06米艏摇角误差±0.02弧度。这个水平对于圆形轨迹跟踪来说是可以接受的。第二是滑模面σ(t)的曲线。它应该快速收敛到边界层宽度Δ内并在其中小幅波动。如果σ曲线在仿真过程中反复冲出去再拉回来说明切换增益偏小或者边界层太窄。如果σ始终很大但控制输入很小那要回头查观测器是否收敛。第三是控制输入τ(t)的曲线。这条曲线最能反映工程可行性。一个健康的控制输入应该在误差大时有较大幅度稳态时平滑小幅波动没有高频梳齿状振荡。我用固定增益K8时τ的稳态波动幅度约为±2.5换成自适应增益后稳态波动降到±1.2而且频谱上高频成分明显减少。这就是“自适应”的价值量化体现。6.2 有神经网络和无神经网络的对比意义复现论文时对比实验一定要做几组才有说服力。我的建议是最少做三组组一全方案观测器神经网络自适应滑模作为基线。组二去掉神经网络前馈只用自适应滑模和观测器。组三固定滑模增益不用自适应对应传统滑模。这三组对比能分别说明神经网络的价值和自适应增益的价值。实际数据也支持这个结论组一稳态误差最小收敛时间最短组二收敛时间慢了近一倍、稳态误差变大——说明神经网络前馈确实在补偿模型不确定项上起了作用组三控制输入抖振幅值最大虽然稳态误差和组二接近但控制品质最差。这个对比结果写在论文里比任何理论分析都有说服力。6.3 我在调参时踩过的坑和最终推荐的流程最后说点实在的。复现过程中我至少踩过四个坑每个都让我浪费了整整一天第一个坑是高斯基函数中心设置不对。前面提过中心范围必须覆盖速度工作区间否则神经元“激活不了”网络形同虚设。解决办法是运行前先用开环仿真估计一下速度范围再据此设置中心。第二个坑是观测器初始状态偏差过大。如果在仿真开始瞬间把ν̂初始化为零而真实ν在2左右观测器需要花好几秒收敛期间控制器被“虚假误差”驱动输出巨大控制力容易让数值积分发散。解决方法是给观测器一个有偏但不算离谱的初始值比如把ν̂(0)设为ν(0)的±50%内。第三个坑是自适应增益发散。如果你在更新律里只保留γ_K||σ||项而不加遗忘因子ρ_KK̂那么只要σ有微小的稳态值K̂就会一路积分上升最终控制输入饱和并振荡。加上衰减项后K̂会在有界值附近自动平衡。第四个坑是权重初值设为全零没问题但如果你在仿真中途给权值一个大的随机扰动比如为了测试鲁棒性网络需要重新收敛期间误差会尖峰式跳变。这其实不算坑而是策略问题权值初值全零意味着“一开始假设没有未知项”后续靠自适应补齐这个策略是稳定的。所以最终我推荐的调参流程是先开环跑一遍模型确认模型本身不发散再把控制器接上滑模增益取小边界层取大目的是先保证稳定确认稳定后逐步增大λ加快收敛速度然后引入神经网络前馈观测误差会进一步减小最后再调自适应律增益和遗忘因子逐步压小抖振。每调整一个参数都跑一遍上面说的三条曲线对比观察变化趋势再把参数落定。从我自己的体会来说这套“神经网络观测器自适应滑模”的组合表面上看是三个模块拼在一起实际调试时它们之间会有很强的耦合关系不能当成三个独立的黑盒。观测器收敛快控制器的滑模面才干净神经网络逼近准滑模的切换项才不需要出大力自适应增益调得好抖振才压得住。回头再看那篇论文的标题它想要表达的并不是某个单一算法的胜利而是一个“感知—估计—执行”闭环的完整工程思路。最后再分享一个小技巧如果你想快速验证自己的控制器代码有没有写错先把神经网络和自适应增益都关掉整个闭环退化成“M₀ν̇ τ”的理想模型加PD控制如果这样都不稳定那必然是你运动学转换或J(ψ)转置用错了先把基础架子扶正再谈其他高级功能。这一步排查法我屡试不爽推荐你按这个顺序来。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。