1. 为什么非要用神经网络加滑模做船舶轨迹跟踪
做无人船控制的人应该都有体会:圈里人聊起船舶轨迹跟踪,第一反应往往是PID,最多加个模糊或者线性二次型调节器(LQR)。真到湖里、海里跑一圈,你会发现那些在仿真里漂漂亮亮的控制器,到了实船上完全不是那么回事。风浪流扰动的随机性、模型参数的偏差、执行机构饱和,任何一个环节都能让一套设计良好的线性控制器性能崩掉。这也是我当初做这个项目的出发点——用神经网络配合自适应滑模控制,专门处理模型不确定性和外界扰动,把圆轨迹跟踪的精度做到一个能实际落地参考的水平。
先说清楚这个项目能解决什么问题。常规的船舶运动控制,本质上是一个典型的非线性系统控制问题:船在水面上运动,受水动力、惯性力、阻尼力耦合作用,而且这些力的模型参数很难精确测定。同一个船模,空载和满载时惯性矩阵能差出百分之二三十;更别说海况变了,环境扰动力的幅值和频率都在实时变化。传统的滑模控制优势在于鲁棒性强——一旦系统进入滑模面,对外界扰动和参数不确定有天然的免疫能力,但它有个致命代价:抖振。控制器输出在滑模面两侧高频切换,执行机构受不了,实测中螺旋桨和舵机容易过热甚至损坏。
神经网络的价值正好补在这个痛点上。径向基函数(RBF)神经网络在理论上能以任意精度逼近连续函数,让它在线逼近船舶模型中的不确定项,把不确定项从“需要鲁棒性硬抗的大扰动”降级成“剩下一小撮边界余量”,滑模控制器就不需要那么高的切换增益,抖振幅度会显著下降。这就是“自适应滑模控制”和“神经网络”结合的核心逻辑:神经网络负责消除确定性误差,滑模负责处理残余的不确定边界,两者各干各的活。
这个项目适合谁来参考?如果你在学船舶运动控制、无人系统控制理论,或者做水下机器人、双体船、无人艇的轨迹跟踪仿真,这套方案都有直接的迁移价值。Simulink和Matlab实现需要一定基础,但不需要你精通控制理论的深层证明,把控制器结构和参数调法掌握住,一样能把仿真跑起来,而且能跑出接近论文级别的效果。
我当年做这个项目的时候,课题背景是某型号小型无人船的路径跟踪预研。因为条件所限,没法做真实的湖试,整个方案都依赖Matlab/Simulink闭环仿真来验证,所以我在模型可信度和仿真细节上下了不少功夫。这个过程中踩过的坑、试错出来的参数整定规律,正是这篇内容想重点分享的。
2. 船舶数学模型与圆轨迹任务设定
2.1 三自由度动力学子系统怎么建
要设计基于神经网络的控制方案,第一步绝对不是写控制器,而是把被控对象建准。仿真这行有句老话:模型不准,控制器白做。船舶在水面的实际运动有六个自由度,垂荡、横摇、纵摇这仨通常靠船体自身回复力矩自稳定,控制器关心的是平面内的三个自由度——纵荡(前进速度u)、横荡(侧向速度v)、艏摇(转艏角速度r)。这就是经典的船舶水平面三自由度模型。
标准的无人船动力学方程长这样:
M(v)·\dot{v} + C(v)·v + D(v)·v = τ + τ_d
看着抽象,拆开说就好懂了。M是惯性矩阵,包含船体质量和附加质量,所谓附加质量就是船推水、水跟着走的那个惯性效果,对无人船来说这部分往往比船体自身质量还大,而且很难精确计算。C是科氏力和向心力矩阵,由M产生,体现旋转和移动之间的耦合。D是阻尼矩阵,包含线性阻尼和非线性阻尼,比如水对船体的摩擦阻力、兴波阻力。τ是推进器和舵产生的控制力与力矩,τ_d是外界扰动。
综合起来,物理图像是这个意思:你给船一个力和力矩,船的加速度由自身的惯性决定,同时它动起来之后,水流会对它产生有方向性的阻力,转弯的时候,平动和转动还会互相牵连。这三个矩阵的参数,实体船的实测值往往和理论计算值有偏差,而且随着工况变换会变。这就是所谓的模型不确定性——精确模型不存在,或者说精确模型建了也白建,因为工况一变又不准了。
建模时一个可以接受的简化是忽略多船之间的流体干扰,只做单船运动。仿真中使用的是两自由度的简化模型——只保留前进速度u和横荡速度v,相当于假设船始终保持一个相对稳定的艏向角,或者把转艏动态简化处理掉。这种简化在验证控制算法、做概念可行性验证阶段完全够用,你要是想让结果更贴近真实,在三自由度模型基础上把转艏动力学加回来,控制器的结构并不用大改。
2.2 圆轨迹参考信号怎么设定
项目标题里点名了“圆轨迹”,这说明参考路径设计有明确意图。圆轨迹的好处在于它同时包含了恒定速度跟踪和恒定曲率转向两个特点:切向速度不变,法向曲率是定值,这就让跟踪误差分析变得非常直观。更关键的是,圆轨迹能有效暴露控制器的稳态跟踪能力——如果你设计的控制器在直线跟踪上表现尚可,但圆轨迹一直存在固定偏差,多半是转向时未建模动态或者控制器增益不足导致的,这种问题只有在曲率不为零的轨迹上才会显现。
圆轨迹参数方程用极坐标写就很顺:
x_d = R · cos(ω·t) y_d = R · sin(ω·t)
R是圆的半径,ω是角速度,决定船走一圈的周期。这两个参数要选得合理,不能随便拍脑袋。R太小,曲率太大,对无人船这种低速欠驱动平台来讲根本转不过弯;R太大,圆轨迹退化成近似直线,测试不出控制器转向时的性能。我当时用的参数是R=50米,切向参考速度U_d=5节(约2.57米每秒),这样算下来角速度ω=U_d/R ≈ 0.0514弧度每秒,绕一圈约122秒。这个参数组合对小型无人船来说,既不至于急转弯失速,又有足够的动态激励来检验控制器的跟踪表现。
实际仿真时,参考轨迹要生成连续可导的信号。你可以在Simulink中用Clock模块接三角函数直接生成x_d、y_d,也可以通过S-Function在线计算。我推荐用S-Function把轨迹生成封装起来,这样方便在切换不同轨迹模式(直线、圆、八字、样条)时不动主模型框架,只要改轨迹生成模块内部逻辑就行。
3. 自适应滑模控制器设计全流程
3.1 滑模面怎么选才顺手
滑模控制器设计中,滑模面就是系统的“安全边界”。设计思路说白了是这样:如果系统状态跑到滑模面上,那么控制律会强制它保持在这个面上滑动,直到收敛到平衡点;同时,只要在滑模面上,系统的动态行为只由滑模面本身的系数决定,不再受原系统参数影响,因此对模型不确定性有天然免疫力。
对于船舶轨迹跟踪,直观的做法是把跟踪误差定义为当前位置与参考位置的差,然后在误差空间里构造滑模面。我当时用的是带比例项的一阶滑模面:
s = \dot{e} + λ·e
其中e是跟踪误差向量,\dot{e}是误差变化率,λ是正定对角矩阵,决定收敛速率。这个滑模面的物理含义就是:你把误差和误差变化率加权结合成一个量s,控制目标就是让s趋近于零。s趋近于零等价于误差以指数速度收敛,而且收敛速度由λ决定,想让它快点就调大λ,但大了之后对噪声的放大也更明显,这个是后话。
λ取值有讲究。做过实际调参的人应该明白,滑模收敛速率过高会导致控制量频繁大幅变化,尤其在离散仿真里会出现数值振荡;太低则跟踪响应慢,圆轨迹上会出现明显的跟随迟滞。我的经验是从一个保守的初始值开始,比如λ取3到5,然后成倍倍增观察效果,找到跟踪超调和控制幅值的平衡点。
滑模面选完,下一步常规思路是推导等效控制律和切换控制律。等效控制处理系统的已知标称部分,切换控制处理模型误差和外界扰动。如果模型参数完全准确,等效控制就够了;但实际做不到,所以切换控制才是滑模控制鲁棒性的灵魂。
3.2 RBF神经网络凭什么能逼近不确定项
船舶动力学模型里的不确定项,理论来源很多:附加质量的估计误差、阻尼系数的测量偏差、风浪流的随机扰动。直接把这些加在一起当作一个总的集总不确定函数F,这个F就是神经网络要逼近的对象。RBF网络在理论上能够以任意精度逼近任意紧集上的连续函数,这是有严格数学证明的,工程上它比BP网络好用,因为它局部响应能力强——输出主要受距离中心最近的那几个节点激发,不太容易出现“改一个参数全网都动”的不可控局面。
RBF网络结构上就是三层。输入层送信号,隐藏层是一堆高斯径向基函数,输出层把隐藏层响应做线性加权求和。隐藏层每个节点都对应一个中心点——像是输入空间里一个“探测点”——输入向量离某个中心越近,那个节点的输出就越接近1,离得远则指数衰减到0。所有节点加权合起来,就对整个输入空间形成了局部平滑的逼近。
在网络实时工作的时候,输入一般是误差向量和速度向量这类可以直接测量的量。神经网络输出一个对不确定项F的估计值f_hat,然后控制器把这个估计值的前馈补偿项加进去。理想情况下,如果神经网络把F估准了,等效控制器就完美消除了模型误差的影响,切换控制器只需要很小幅度的输出就能维持滑模状态。这比单纯滑模控制中切换增益必须大于不确定项上界的条件宽松得多。
这里有个关键设计点:神经网络的权重不是预先离线训练的,而是在线更新,更新律由李雅普诺夫稳定性分析推导而来。在线更新的优势在于,不需要预先采集大量数据训练,仿真开始后系统自己会逐步“学”出一个可以用的逼近模型。实船工况变化时,权重跟着调,永远在做“当前工况下最合适的逼近”。
3.3 自适应律和稳定性是怎么保证的
很多做工程的朋友一看李雅普诺夫分析就头大,但我一直建议至少理解它的框架,因为最后给出的自适应律公式和参数取值策略,全都来自这一步。如果把所有推导过程压缩成一句话:先定义一个包含跟踪误差和神经网络权重误差的能量函数L,然后设计控制律和权重更新律,使得L的导数小于等于零,这样就用数学手段保证了系统资源持续下降,最终收敛到滑模面或滑模面附近的界内。
最终推导出来的控制律形式很规整:
τ = τ_eq + τ_sw + τ_nn
- τ_eq:等效控制,基于标称模型设计,负责系统名义动态的补偿
- τ_sw:切换控制,包含一个符号函数项,负责处理残余不确定性,增益设计为ρ·sgn(s)
- τ_nn:神经网络前馈补偿,输出对不确定项的估计,实时修正等效控制的不足
权重更新律则是典型的梯度型自适应格式,系数表现为学习率。这个学习率的物理意义是:神经网络参数每步朝“降低跟踪误差”方向自动调整的速度。学习率太小,网络学得太慢,初始阶段跟踪误差偏大;学习率太大,权重初值敏感度上升,系统可能出现高频振荡甚至发散。实际调试时,我会先设置一个中性值,比如0.1左右,然后看误差还是权重更新的波形走势去微调。
切换控制里的ρ取值是整个控制器调试中最需要手感的地方。ρ太大,抖振幅度跟着大,控制输出尖峰明显;ρ太小,对于突发扰动的抑制不足,系统会稳定在一个非零误差上。理论上ρ的取值要大于不确定项逼近误差的上界,但这个上界实际是未知的,只能靠仿真试验逐步逼近。核心经验是:先用偏大的ρ把系统跑稳定,确认整体框架没问题,再逐渐减小,观察误差变化曲线,找到一个“低抖振且误差微小波动”的临界点。
滑模控制中常见的抖振,一部分原因也是切换项里那个符号函数在理想滑模面上的不连续切换造成的。工程上几乎一致的做法是用饱和函数替代符号函数,就是把切换输出限制在一个正常数Δ内,让不连续的切换变成边界层内的线性过渡。这个Δ就是我说的“准滑模边界”,Δ越大抖振越小,但稳态误差也成比例放大,属于控制精度和控制平滑之间的经典权衡。
4. Simulink仿真搭建实战
4.1 闭环系统整体架构怎么搭
Simulink仿真搭建过程中最容易犯的错误是一上来就在Simulink里找各种现成模块,试图直接搭出闭环。我的做法是先用几分钟手动画一张系统闭环框图,把信号流向理清楚,再进Simulink动手。整个闭环系统分成三块:参考轨迹生成模块、控制器模块、船舶动力学模型模块。控制器模块输入是跟踪误差和当前速度状态,输出是力和力矩;船舶动力学模型模块输入是力和力矩,输出是位置和速度。两者接上就形成闭环。
Simulink里的具体落地方式,我强烈推荐使用Matlab Function块或者S-Function来写控制器和船舶模型,而不是用积分器、增益模块去搭一个纯模块化框图。原因有两个:第一,神经网络和滑模算法本身是高度的计算流程,用代码块写更直观,不容易在连线时出错;第二,仿真参数调整时改代码比改一堆模块参数快得多。说实话,纯模块化的框图在船舶模型这种多变量耦合系统里极容易连错线,排查起来让人崩溃。
船舶动力学模型可以用S-Function(Level-2)实现。Matlab Function块适合写控制器,因为控制器结构稳定,输入输出改动不频繁。S-Function写船舶模型的好处是你可以精确控制每一步的状态更新逻辑,尤其是处理矩阵运算和积分环节时,代码比模块直观得多。
整体仿真流程按照下面的顺序组织:
- 初始化脚本(.m文件)先运行,把所有参数写入Matlab工作区
- 参考轨迹生成器在每一个仿真步计算期望位置和期望速度
- 控制器模块读取当前位置、速度,计算控制力
- 船舶模型模块积分动力学方程,更新下一时刻的状态
- 示波器和数据输出模块记录整个过程的曲线
初始化脚本放置参数这件事很多人做到一半才想起来。包括船舶模型的M、C、D矩阵参数,滑模控制器的λ和ρ,神经网络的学习率和中心点布局,参考轨迹的半径和角速度——这些参数都应该在独立脚本里集中定义,方便做批量参数扫描实验。如果你把参数散落在各个模块的对话框里,后续调参就是噩梦,重复劳动且容易遗漏。
4.2 离散化设置和步长怎么选
仿真步长设置是第一个隐藏的坑。滑模控制本身是连续时间控制理论,但你拿Simulink仿真它的时候,如果用了固定步长,步长太大,控制律里的符号切换和神经网络更新在步与步之间产生“跳变”,系统会像关节炎一样一抖一抖的;步长太小,仿真时间又长得让人失去耐心,特别是你在跑参数扫描的时候。
我的实践结论是:验证算法的阶段用变步长求解器,选ode45(四阶五阶龙格-库塔法),相对误差设置1e-4,绝对误差1e-6。这样能在曲线剧烈变化阶段自动加密仿真步,在平稳阶段放宽步长,仿真精度和速度都能兼顾。但这里有个重要前提:如果你打算把控制器部署到实船上,那最终一定要换固定步长仿真,模拟真实控制器离散采样周期下的行为。这就是另一个故事了,涉及离散控制器的设计,一般来说控制系统采样周期选控制带宽的10到50倍。
神经网络和滑模这种包含符号函数和指数计算的算法,在变步长条件下表现很好,但你要留意示波器的数据存储——默认存太多点会导致绘制波形时卡顿甚至内存溢出。建议给示波器模块设置数据点上限,或者干脆把数据输出到工作区变量,仿真完再用Matlab统一绘图,这是我的习惯做法。
4.3 船舶模型和控制器参数一次给全
为了让整个项目在别人手里可以直接跑通,我给出我当初项目的一组基准参数。船舶模型用的是差动双桨无人船,控制输入包括前进推力和转艏力矩,这属于全驱动配置。推进器的最大输出限制在2000牛顿,转艏力矩限制在1000牛顿米——这些约束不加的话,仿真结果在无约束条件下很完美,实际执行器却完全无法复现。
模型参数大致这样设定:
- 船体质量:30公斤,附加质量等效在M矩阵中体现,比船体质量本身还要大一些
- 惯性矩阵M取对称正定:主对角线元素取45、50、8这三个级别
- 阻尼矩阵D主对角线元素取15、20,非线性阻尼系数加进来形成速度相关项
- 外界扰动:用一个随机风浪扰动信号,幅值约是控制力的5%到10%,保证仿真更真实
控制器的参数选择,我用了一组经过十几轮试验打磨出来的值,在误差收敛速度和控制平滑度之间取的折中。λ取5,ρ取12,Δ取0.5,神经网络学习率取0.08,RBF中心点按输入范围理解为从-1到1均匀分布。仿真时长直接设400秒,前50秒只给期望轨迹不给控制,相当于船从静止状态开始,控制器在50秒后激活。这模拟的是无人船起步阶段:系统在到达前有一段准备,起步后从初始位置误差较大的状态恢复跟踪。
给个操作性很强的提示:初次跑模型之前,先在初始化脚本里加一段参数合法性检查,比如检查M矩阵是正定对称、控制增益为正数这些条件。别小看这一步,很多调参失败其实是一开始参数值都不合法,系统在仿真第一步就输出NaN,你还对着波形怀疑自己写错了控制器,折腾半天。
5. 仿真结果分析与闭环调参方法论
5.1 圆轨迹跟踪效果怎么看数据
仿真跑完,最先要看的是跟踪轨迹图。船的实际运动轨迹应该从起始点开始,先拐一个弯,然后慢慢贴近参考圆,贴着圆周走。判断标准的顺序是:第一个看是否收敛——大约多少秒贴合到圆上;第二个看稳态时轨迹是否与参考圆几乎重合——放大看后差别有多大;第三个看有没有锯齿状突变——这往往对应控制量振荡或者求解器失效。
位置跟踪误差是最核心的技术指标。取当前位置与参考位置之差,计算它的欧几里得范数,画出的曲线应该在初始阶段有个尖峰,然后快速衰减到某个稳态值附近小幅波动。我当时的基准结果是:起步阶段最大误差约8米,在35秒到40秒左右收敛到0.4米以内,稳态误差波动幅度在正负0.2米左右。对一艘30公斤的小型无人船模型来说,这个水平的跟踪精度是可接受的。你这个结果也许比这个好或者差,重要的是理解各阶段受什么因素影响。
期望值得提出来的一个经验:光看位置误差曲线还不够,你得看控制力曲线。仿真中经常出现一种被低估的现象——位置误差看起来很小,但控制力在疯狂高频摆动,这种结果在理论仿真里是“及格”的,拿到实船上根本活不过一分钟。所以判断一个控制器设计得好不好,必须把“误差水平”和“控制平滑度”放在一起评价,抖振不是一种可以忍受的噪声,而是切切实实的执行机构损耗。
把初始阶段的曲线放大来看,你还会注意到一个特别有意思的现象:滑模控制的收敛过程不是光滑的指数衰减,而是带着“阶梯感”的,系统误差先快速冲向滑模面,然后贴着面滑动并逐渐收敛。这就是滑模控制最本质的物理特征——先趋近,再滑动。你如果看到误差收敛曲线像锯齿一样反复穿越滑模面,那就说明边界层设计得太小,或者仿真步长相对于控制器动态偏大了。
5.2 调试遇到过的坑
这个项目我从零到跑出理想结果,大概踩了七八个大坑,挑几个最有代表性的讲。
第一个坑是神经网络输入设计不当导致收敛很慢。最初我把网络输入设计成三维向量,只用了位置误差两维加权速度误差,训练效果很差,误差曲线在40秒附近出现一个平台期,好像系统“卡住”了。后来排查,原因是圆轨迹上的速度变化信息没有被网络充分感知。修正方案是把输入扩展为五维——位置误差两维、速度误差两维,再加一个时变参考速度项,网络有了足够的信息去逼近不确定项,平台期一扫而空。RBF网络的输入不能只凭感觉选,它的逼近能力和输入信号对不确定项的信息量直接挂钩,输入维度不够,网络再怎么调也不能凭空变出信息。
第二个坑是饱和函数的边界层参数Δ和切换增益ρ的搭配问题。我把Δ设得很小,想着稳态误差小一点,结果控制量高频抖振,整个仿真速度变得奇慢无比。后来改成把Δ加大到0.5,ρ从初始的35逐步降到12,抖振消失了,稳态误差反而因为神经网络补偿的作用维持在一个可以接受的范围内。这个过程验证了一个调参原则:ρ和Δ的调整顺序应该是先调ρ把系统稳定住,再调Δ平滑控制输出,不要同时动两个参数,否则你会分不清到底是哪个参数引起的现象变化。
第三个坑比较隐蔽:采样数据类型不一致导致神经网络输出异常。S-Function控制器里使用的信号如果是double,Matlab Function内部默认类型一致,看着没什么问题;但如果你从某个示波器或者总线选择器输出的信号带了总线类型,传到控制器里,运算时就有隐患。我遇到的现象是仿真开头几秒正常,突然控制输出跳到超大量级,检查半天发现是数据类型转换问题。传递信号一律用稀疏double类型的常规线,不要用总线签名机制,除非你需要管理大量总线信号。
最后再分享一个调参心得:神经网络权重初值不要设成全零,虽然理论上全零初值也能靠自适应律慢慢学出来,但收敛速度会慢不少。我常用的是在零附近加均匀分布的小随机扰动,幅度取0.05左右,相当于给网络一个微小的初始多样性“起跑速度”,让它从第一步就能朝各个方向探索,而不是被锁定在对称性导致的恒等映射上。这个细节在实船调试中更关键,因为真实系统不允许你有漫长的“学习期”,一开始就要能跟上参考轨迹。
另外一个实用的操作习惯是,把每次仿真结束后的误差均方根、最大控制力、平均抖振幅度自动存成一个结构体变量,每次调参都留档。回头对比上百组参数的时候,这个记录就是你做决策的最可靠依据,光靠肉眼对比示波器图像,看久了真的会判断麻木。