ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

无人船路径跟踪控制:Fossen模型与观测器在Simulink中的实现

无人船路径跟踪控制:Fossen模型与观测器在Simulink中的实现 直接说结论无人船路径跟踪控制这个方向看着不复杂真正上手跑仿真的时候坑一个接一个。Fossen模型、MATLAB Simulink、基于观测器的控制器这几个关键词拆开看都熟悉合在一起就是我在项目里足足折腾了一个多月的组合。这篇文章我不打算写教科书我想把从模型选定、Simulink建模、观测器设计到最终效果调试这一步一步经历的东西包括踩过的坑都用大白话写清楚给正在做无人艇方向的朋友一个可以直接照抄的干活参照。适合刚接触水面无人艇、准备用Simulink做路径跟踪仿真或者已经能跑通基础模型但被干扰和噪声困扰的本科生和研究生。1. 为什么路径跟踪控制选了“Fossen模型观测器”这条路线1.1 先从三个关键词说起“路径跟踪”对比“轨迹跟踪”本质区别在于有没有时间约束。无人船要从A点到B点中间经过一系列航路点我们关心的是船是否走在规划好的路径上而不是“某一刻必须到某个位置”。这个区别直接决定控制策略的选型。做轨迹跟踪你需要把时间项加进参考信号系统会变得很拧巴做路径跟踪沿着路径的参数化速率可以自己设计这就是为什么很多工程落地都选LOS制导加独立的航速控制而不是硬套PID加轨迹规划。Fossen模型出现的频率极高原因很简单它把船舶在水中的刚体动力学、科氏力、阻尼、推进器推力用一个统一的结构表达出来而且还专门考虑了环境干扰这一项。T. I. Fossen的《Handbook of Marine Craft Hydrodynamics and Motion Control》是这一行绕不开的参考书。基于观测器设计控制器核心直指一个实际问题——我们根本测不到精确的环境干扰力。水面无人艇在湖面上受到的浪、流、风的干扰在数学模型里是一个变化缓慢但持续存在的“动态扰动”如果控制器只硬顶着干扰强上稳态误差会非常难看所以需要一个机制在模型内部把干扰估值出来再用估计值做前馈补偿让系统自己“消化”掉干扰而不是靠比例项在后面扛。1.2 欠驱动无人艇与LOS制导的关系大多数水面无人艇只有尾部一个推进器加一台舵机或者双差速推进横向没有直接推力。这种配置下的数学模型中横向速度自由度没有控制输入系统是典型的欠驱动系统。欠驱动系统有个特点位置控制不能既控航速又把横向位置拉到位所以经典做法是分层设计。外层用LOS视线制导律把“离路径的横向偏差”转成期望艏向角。内层控制器跟踪这个期望艏向角。这里面直觉上很顺——船想追上参考路径就沿着参考路径提前看一个距离Δ看过去把船艏对向那个视线点。Δ越大收敛越平滑Δ越小趋近越快但振荡越明显。内层艏向控制器用PD加前馈就可以当然好一点可以加积分项。实际工程中LOS参数和控制器参数需要在仿真里反复调因为船是欠驱动的横向误差是靠船的艏向变化间接消掉的有一环延迟和船体惯性效应存在就容易超调。1.3 干扰不可测观测器是刚需在Matlab的Simulink环境里搭建模型时很多人会把“环境干扰”直接用一个正弦波加白噪声怼到模型输入端图省事。但控制器本身并不知道这个干扰长什么样纯反馈控制会出问题船走直线路径时横向偏差稳定在0附近但如果有持续侧向流干扰船会以一个航向角顶住流才能保持航迹。没有观测器的话你就得靠误差积分项慢慢凑效果差而且响应慢。观测器的思路是从可测的模型输出——比如船的位置、艏向、速度——中间接推断出不可测的状态和干扰项的估值。如果模型匹配这个估值可以在数学上证明收敛到真实干扰值附近。在仿真中效果就是加了观测器之后的前馈补偿会让横向偏差比不加时小一个数量级而且对突变干扰的恢复时间大幅缩短。这也是“基于观测器的控制器”这个方向这些年这么热的原因不是搞形式主义是真的能解决工程里的痛点。2. 从模型到仿真参数选择、坐标系与方程落地2.1 坐标系的槽点与统一约定做船舶运动仿真坐标系不统一是基本功错误里最隐蔽的一种。Fossen模型常见的表述有两种坐标系北东地坐标系NED固定在某个当地参考点和附体坐标系B固定在船上以船艏为x正方向。理论上都会写但真正建模时速度、加速度这两项一定要明确做完换到哪个框架。我见过太多人把NED里算出来的位置误差直接塞进附体系控制律里结果系统一个劲发散还不知道怎么排查。我建议的约定是所有运动状态位置、艏向角用NED系表达速度和角速度用附体系表达动力学方程里的d/dt计算在附体系完成然后通过旋转矩阵转回NED系。这个约定在多数字符串计算工具里处理都会顺畅很多Simulink里也好梳理。旋转矩阵这里如果写成代码就是这个样子建议直接存成函数反复用function R Rz(psi) R [cos(psi), -sin(psi), 0; sin(psi), cos(psi), 0; 0, 0, 1]; end2.2 三自由度动力学方程怎么落到MATLAB里对于一个只考虑水平面运动的无人艇Fossen模型的简化版可以写为上面这行式子里M矩阵是刚体惯量加附加质量的合并C(v)矩阵是科氏力与向心力项D(v)是阻尼矩阵负号表示阻尼是耗散力。τ是推进器输入τ_env就是我们需要观测的环境干扰项。实际Simulink建模时我更推荐直接用M矩阵求逆的方式组织积分链。把加速度解出来然后逐次积分得到附体系速度再转换得到NED系位置。这样每一层都是最基本的模块排查中间信号是否异常特别直观。给你一个我正在用的参数参考一艘大约20 kg级别的水面无人艇模型小艇、双推进器差速参数数值单位m23.0kgI_z1.8kg·m²X_u纵向阻尼-4.0N·s/mY_v横向阻尼-8.0N·s/mN_r艏摇阻尼-0.9N·m·s/radX_udot纵向附加质量-2.5kgY_vdot横向附加质量-6.5kgN_rdot艏摇附加质量-1.2kg·m²是不是看起来挺随意这些参数真实来源要么是CFD仿真计算要么是实船进行平面运动机构试验初级仿真阶段完全可以先按经验值凑合先验证控制逻辑通不通再回头优化参数标定。这个顺序别反了我见过一开始就纠结水动力系数标定的人卡在建模阶段大半个月没碰控制器。2.3 参考路径与制导律参数怎么定开始做路径跟踪仿真时别一上来就搞复杂曲线。从直线路径开始跑通了再加转向段、圆形路径、甚至8字形路径。这样做的好处是每个阶段的误差特征一眼就能看透。直线路径的期望艏向角可以通过LOS法求计算当前船到直线路径的横向偏差e_y取前视距离Δ一般取船长的23倍期望艏向角就是路径方向角减去atan(e_y / Δ)。Δ太小船容易“画龙”Δ太大它拐弯时候又显得太钝削弯削得很厉害。再配合一个想要的前向速度比如0.5 m/s控制目标就是尽量保持这个速度同时把横向偏差压到零附近。这个办法看起来初级但工程实用度非常高。我后来跑圆形路径和弧形路径的时候把LOS里面的直线参考路径换成圆切线方向整个思路一点没变只是几何计算部分变了一下。3. Simulink搭建实操从空白模型到跑通3.1 先搭出整体架构打开Simulink之后不要直接拖模块先大概画出我要的六大块参考路径生成、LOS制导律、控制器、观测器、船体动力学模型、输出记录显示区。每块一个子系统整个顶层图干净得像一张架构图排查问题的时候按信号流向逆着找非常省事。子系统我建议每个都输出两组关键信号一组是正常的状态量另一组是留作调试用的中间量比如期望艏向、横向误差、干扰估计值。用Simulink的Outport可以标注不同颜色把调试信号放到一个单独的子总线里。这样不影响主控制线的整洁度。顶层结构大概是这样说个逻辑不用画图参考路径 - [LOS制导] - 期望艏向角 - [控制器] - 推进力/力矩 ↑ [船体动力学] - 状态输出 - [观测器] - 干扰估计状态估计3.2 观测器与控制器子系统怎么接线观测器我采用扩张状态观测器的标准形式。它的思想很简单把不可测干扰看成系统的一个“扩张状态”然后用估计器跟踪它。对于艏向子系统假设状态x[psi, r, d]其中d是等效干扰角加速度写成矩阵形式后观测器方程为dx_hat A * x_hat B * tau L * (psi - psi_hat);就是对模型状态的估计值按模型演化然后用实测艏向和估计艏向的误差乘以增益L去修正估计。L的取值决定了观测器估计的带宽与噪声抑制能力。增益太高估计值会像放大镜一样把量测噪声全放大增益太低干扰估计跟不上真实变化。我在仿真里经验值是让观测器带宽大概是控制器带宽的3到5倍。控制器子系统内部我用的是较为常规的PD艏向控制器加上基于干扰估计的前馈项。输入有期望艏向、实际艏向、以及观测器给出的干扰估计输出是推进力矩。干扰前馈的方向一定要和干扰的实际作用方向相反这个我一开始搞反过一次补偿变助攻输出直接发散排查了整整一下午罪魁祸首就是一个负号。控制器比例的增益Kp和阻尼增益Kd可以根据一个二阶系统来粗略估算如果希望艏向闭环自然频率ωn在0.8 rad/s左右阻尼比ζ在0.9左右那么Kp约等于I_z·ωn²Kd约等于2·I_z·ζ·ωn。这里I_z是总惯性矩包含附加质量。具体数值后面再微调这个初值能省很多时间。3.3 关键仿真参数与积分器选择Simulink里的积分器模块默认就是定步长的一个状态量功能上没有多大问题但有几个点需要养成习惯。我刚入行那会儿没太在意积分器的初值结果船从原地启动时位置跳变看起来就好像GPS瞬间漂了几百米一样让人一度怀疑是传感器模型写错了。所以任何积分器都要把初值设成与理想初始状态一致的数值特别是位置积分器的初始值与参考路径的起始点一致这样第一帧就不会有大跳变。速度积分器初始值设为0艏向角积分器初始值设为参考路径起点的方向角。再一个是在定步长仿真中用ODE4或ODE5算法对应四阶或五阶Runge-Kutta仿真精度够用且稳定不建议为了速度用ODE1除非你只做非常粗的示意。定步长固定下来之后整个模型在外部模式或者生成代码的阶段不会因为时间步长的问题出各种诡异差异。3.4 用结构体总线信号提高可读性前面说调试信号用Outport颜色区分但如果信号几十路全都拉线给Scope图会乱成一团。推荐用Bus Creator把状态信号打包成结构体总线。在一个多次联合仿真项目里我就是把船的状态全部收成一个bus对象输出的时候直接用Bus Selector挑选想看的信号后期处理可以一次性保存成一个timeseries结构体。热搜词里有人问“Simulink总线选择器没有可选信号”这基本是建模顺序问题Bus Creator创建信号打包之后后续的所有信号又变了或者总线对象没有在工作空间里正确更新。解决方法是编辑Bus对象之后立刻CtrlD刷新并且在MATLAB基础工作空间确认Bus类型的定义已经生效Simulink的总线选择器只认基础工作空间或数据字典里定义好的类型不是自动刷新到最新的。3.5 用S-Function还是基础模块船体动力学模块有两种实现路线全用基础积分器或者写一个Level-2 MATLAB S-Function。两种我都试过说说判断标准。如果模型就这一艘船结构比较单一用基础模块搭积分链足够优势是内部信号一目了然点击它就能看到所有中间状态。如果后面要做批量参数扫描不同船型、不同水动力系数要做联合仿真与上位机交互或要CSS代码生成那么S-Function更合适因为可以把整个动力学封装成一个黑盒对外只暴露状态和输入接口代码生成时也更接近实时环境下的实现方式。S-Function里把模型方程写成类似这样的结构function sys mdlDerivatives(t, x, u, param) % x: [north, east, psi, u, v, r] % u: [tau_u, tau_r] % param. ... 用struct存模型参数 ... sys [n_dot; e_dot; psi_dot; u_dot; v_dot; r_dot]; end建议不管选哪种路线顶层文件都放一份MATLAB script做参数初始化和后处理脚本每次在Matlab命令行运行这个脚本设定参数再开始Simulink仿真这样重复试验时改动都在一个地方不会散落在模型里。4. 常见问题排查与避坑心得4.1 仿真实战高频报错改良仿真报代数环错误多见于控制器输出直接反向回传模型输入或者观测器增益矩阵里有负号导致信号环路。解法是检查是否真的需要当前时刻的输出计算输入如果是尝试在环中串联一个memory模块或者离散传递函数但治本方案还是让控制器的每个信号路径都显式包含至少一个积分或延迟。仿真时间过长模型速度巨慢把范围驱动信号全部输出尤其是Scope模块每个步长都在存储全部波形的数据就会拖慢仿真。解决办法是用To Workspace模块只记录需要的信号或用模拟数据检查器Simulink Data Inspector设置记录周期。省下来的内存非常可观。期望信号突变导致抖动期望艏向角从-179度跳到179度e_y不连续控制器一下子不知道往哪个方向转了系统猛打舵。解法是对角度差做归一化到[-pi, pi]的处理这是艏向控制里最常见的一个细节。别问为什么做过的都懂。出现数值积分不稳定步长缩小后结果完全不同检查仿真步长是否大于系统最小时间常数的一半尤其是运行前手动算一下艏向闭环自然频率对应时间常数大概是0.1到0.5秒量级选步长0.01秒是安全区。4.2 从仿真到实船的几张“冷静票”仿真通过只是起点。我踩过最大的坑就是把仿真里的“理想控制效果”直接等同于实船效果。真船上传感器噪声比模型里复杂得多GPS的可观测性、IMU的漂移、推进器延迟都给控制闭环带来额外的相位滞后。从仿真走向实船至少需要做三件事第一给仿真里的状态量加合适的传感器模型。别只加白噪声要加位置传感器产生的一步延迟和量测更新频率限制看看控制器还能不能扛住。这个操作会深刻影响观测器的增益选择。第二把控制周期和传感器周期分开设置真实系统里不可能每个传感器都在同一频率更新Simulink里用不同的采样时间模块模拟这一点你会立刻看到抖动问题。第三在模型里加入推进器动态特征比如饱和与死区。我看到过一个仿真跑得很完美的航向控制器实船一开就原地画圈原因就是推进器饱和特性导致期望力矩输出根本执行不了。明确一点仿真效果很好不等于实船效果很好但仿真效果就很差实船一定更差。仿真脚本的角色是“挤出问题”不是“证明可行”。4.3 小技巧参数标定与可视化调参这事讲经验就是一次只动一个参数。很多人改三个参数同时变效果好了不知道是谁的功劳坏了也不知道该还原哪个。建议先在MATLAB脚本里准备一个参数结构体调参时直接在脚本里改数值再运行仿真然后快速看横向误差和艏向角的响应曲线。把每次调参记录下来数据积累多了你会逐渐理解这个船模型的“性格”。可视化方面我习惯把船的NED位置轨迹和参考路径一起画在同一个geom图里仿真结束后直接叠在一起一眼就能看出控制效果和收敛过程的形状。把仿真轨迹按时间着色在图上标出起点和终点还能直观看到船在哪里走偏、在哪里回正。figure; hold on; plot(ref_path_x, ref_path_y, k--, LineWidth, 1.5); plot(sim_x, sim_y, LineWidth, 1.2); legend(参考路径, 实际轨迹); xlabel(北向 (m)); ylabel(东向 (m)); axis equal; grid on;这个图我基本每次跑完必看它比看任何误差指标都直接。横向误差均方根是数值判断但轨迹图是空间直觉判断。两个结合起来才算真的会看仿真结果。尾声一个不聪明但最实用的收尾我自己走完这一整套流程的体会是Fossen模型本身并不难懂难的是把它用到“能干活”的状态中间隔着的都是各种工程细节。观测器不是玄学它只是把不可测干扰搬到可视范围里让控制器从被动挨打变成主动补偿。Simulink也不是关卡用熟了之后它就是记录想法和参数的工具。别指望第一天就复现论文里那种漂亮的收敛曲线我第一天连仿真步长影响都没意识到。真要说一句对后来者最有用的建议那就是先把一切复杂的东西拆成最小可行单元一个直线路径、一个LOS制导、一个PD控制器、一个基础上限的观测器跑通这一条线再一点点加复杂度。后续可以继续扩展自适应增益、路径参数化比如B样条路径、多艇协同方向都是从这个基础模型上长出来的。跑通一次之后那些正在折磨你的问题会变得异常简单。
返回列表