尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

基于MATLAB的无人船操纵性建模与仿真:回转试验与Z形试验

基于MATLAB的无人船操纵性建模与仿真:回转试验与Z形试验 做无人船项目的时候操纵性实验往往是绕不开的一块。真船海上试航成本高、天气窗口难等而且一条船改一次参数就要重跑一遍时间和费用都吃不消。于是我们一般会在设计阶段先做操纵性实验仿真——把回转试验、Z形试验搬到电脑里用MATLAB搭一套可以反复调整参数的仿真环境这几乎是入门无人船运动建模与控制系统开发最有效的一条路。这篇文章就把我实际搭建这套仿真环境的思路、模型取舍、代码实现和踩过的坑完整讲一遍适合刚接触无人船、想把操纵性实验仿真跑起来但不知道从哪下手的同学。1. 为什么操纵性实验仿真要先从MATLAB入手1.1 操纵性仿真的层次从设计初期到闭环控制很多人一听到“操纵性实验仿真”第一反应是上CFD觉得只有算出来流场才靠谱。但实际工程项目里操纵性仿真是分层次的。最底层的需求是设计初期的快速评估这条船大概能跑出多大的回转直径操舵后多久能响应这时候用CFD算一轮要几小时甚至几天根本不现实。更高一层的需求是给控制系统调试服务比如做路径跟踪、动力定位、自主避碰控制器需要的是包含主要动力学特征、但计算足够快的船舶模型而不是每一刻的流场细节。在这两层需求之间基于MMG模型或响应型K-T模型的分离式建模就非常合适。它把船体、螺旋桨、舵的作用分别建模保留操纵运动的主要特征参数可以通过经验公式、约束模试验或CFD标定。而MATLAB恰好是这个层次最顺手的工具矩阵运算方便、微分方程求解器现成、绘图和数据分析功能齐全后面接Simulink做闭环控制仿真也很自然。1.2 MATLAB在建模精度与上手成本之间的平衡我在实际项目中对比过几种方案。Python加NumPy/SciPy也可以做生态越来越好但船舶操纵性这个细分领域里大量现成的源码、论文代码、工具箱都是MATLAB写的遇到问题查起来方便太多。Simulink更是做控制器在环仿真时的利器同一个船模型可以直接拖进闭环系统里跑省掉手写接口的麻烦。另一个好处是调试效率。操纵性仿真最让人头疼的是参数设置不对导致结果乱七八糟MATLAB的工作区、实时变量查看、绘图窗口能让我很直观地看到每个状态量随时间的变化定位问题通常比纯命令行快很多。如果是学生或者刚入门的人MATLAB还帮你省掉了大量底层数据处理代码能更集中精力理解船舶动力学本身。1.3 需要的基础数学与工具做这个入门项目不需要很深的数学背景但有几样东西是必须扎实的向量和矩阵的基本运算、常微分方程数值解的概念、以及一点控制论里的传递函数意识。MATLAB脚本编程只需要会函数封装和矩阵操作就够了不需要用Simulink也能把整个流程跑通。工具方面我建议用MATLAB 2020以后的版本脚本和绘图交互更顺手。需要的工具箱主要是基础的MATLAB如果后续要做Z形试验数据拟合System Identification Toolbox会有帮助但哪怕没有手写最小二乘也能解决大部分问题。2. 仿真前必须定住的船舶数学模型MMG与响应型模型的选择2.1 坐标约定和基本状态量搞操纵性仿真第一步不是写代码而是把坐标系和状态量定义清楚。这里一旦搞混后面全乱。通常用两个坐标系固定在大地上的坐标系 O-XY以及固定在船体上的坐标系 o-xyz。船体坐标系原点一般在船舶重心Gx轴指向船首y轴指向右舷z轴向下。船在大地坐标系中的位置用(X, Y)表示船体坐标系相对大地坐标系的旋转角即艏向角ψ。我习惯把状态向量写成X [x, y, ψ, u, v, r]其中u是纵向速度前进速度v是横向速度漂移速度r是艏摇角速度。这个六维向量足够描述水面船舶在水平面内的三自由度运动。为什么是三自由度而不是六个因为无人船在水面的垂荡、横摇、纵摇对操纵性初步评估影响有限可以放到后面再扩展。2.2 MMG的力分解思路MMG模型的核心思想很简单把船体受到的合力和合力矩拆成船体力、螺旋桨力、舵力三个部分各自建模再叠加。船体运动方程的一般形式是忽略重力和浮力矩考虑平面运动(m mx) * udot - (m my) * v * r X_H X_P X_R (m my) * vdot (m mx) * u * r Y_H Y_P Y_R (Izz Jzz) * rdot N_H N_P N_R这里的mx、my是附加质量Jzz是附加惯性矩X_H、Y_H、N_H是船体水动力X_P等是螺旋桨产生的作用X_R等是舵的作用。附加质量可以理解成船体推动周围水一起运动时等效于多带了一部分水质量这个量可以按经验公式估算不是它的真实质量增加。船体水动力通常按速度线性项和非线性项展开。线性项就是Y_H Yv * v Yr * r N_H Nv * v Nr * r这些Yv、Yr、Nv、Nr就是线性水动力导数是整个模型里最核心的一组参数。非线性项可以根据要模拟的工况增加比如大漂角下用平方项或多项式拟合。螺旋桨力在简单仿真里可以只考虑推力甚至把转速固定、推力看作常数或按进速比变化的函数。舵力则和舵角、舵面积、来流速度有关可以用升力系数加阻力系数近似。2.3 响应型K-T模型什么时候用它MMG模型虽然物理意义清晰但参数多、整定麻烦。跑仿真的时候还有一个更简化的选择响应型船舶模型也就是常说的K-T模型。一阶形式是T * rdot r K * δ二阶形式是T1 * T2 * rdot (T1 T2) * rdot_r r K * (δ T3 * δdot)这里的K是舵效增益表示单位舵角能产生的稳定艏摇角速度T是操纵性时间常数反映操舵后船转头的快慢和惯性大小。K越大船越灵敏T越小船响应越快。K-T模型最大的好处是特别适合控制器设计。PID控制器、LOS导引、线性二次型控制器都可以直接基于K-T模型去设计。我在做无人船路径跟踪的时候通常先用K-T模型设计控制器再放到MMG模型里做高保真仿真验证这是一种很实用的降维流程。2.4 参数来源与无量纲化模型定了参数从哪来按可靠程度排序约束模试验和实船试验最准CFD次之经验公式再次。对于没条件做试验的入门项目我建议用经验公式估算初始参数再根据仿真结果是否符合常识去判断。常用的有Clarke经验公式和Kijima经验公式。它们都是根据大量船模试验数据回归得到的输入船型参数如船长、船宽、吃水、方形系数、重心位置等输出线性水动力导数。MATLAB里把这些公式写成函数输入船型尺寸直接返回一组无量纲导数非常方便。这里必须提醒一句水动力导数在文献里常常是无量纲的要恢复成有量纲值需要乘以特征量。比如Yv的无量纲形式Yv通过以下关系恢复Yv Yv * 0.5 * ρ * U0 * L * d其中ρ是水密度U0是航速L是船长d是吃水。这类无量纲恢复很容易出错我一开始跑发散就是从这儿开始的后面专门有一节讲这个坑。3. 数据准备与仿真环境搭建3.1 一条示例无人船的尺度参数为了把整个流程说清楚我用一条虚拟的小型无人船做示例。参数设置如下参数数值说明船长 L2.0 m总体长度船宽 B0.6 m型宽吃水 d0.3 m设计吃水排水量 Δ150 kg总质量设计航速 U01.5 m/s巡航速度舵角限幅 δmax±35°满舵角度最大舵速15°/s舵机速率这套参数是入门练习用的不代表任何真实产品。水动力导数的获取我采用了一个实用思路先用简化经验公式估算线性导数非线性项暂时用一个阻尼项近似等有了水池试验或CFD数据再替换。这样既不会因为参数缺失卡住又能跑出一个量级合理的仿真结果。3.2 水动力导数的估算思路对于入门项目我不建议上来就纠结超高精度参数关键是保证数量级正确、趋势符合物理直觉。线性水动力导数可以按细长体理论大概估计也可以用Kijima提供的回归公式。比如针对上述小船估算得到的无量纲线性导数量级大致是导数无量纲估算值说明Yv-0.03横向力对v的导数通常为负Yr0.01横向力对r的导数Nv-0.005艏摇力矩对v的导数通常为负Nr-0.01艏摇力矩对r的导数这里的数值仅用于演示真实无人船可能需要根据船型重新标定。恢复成有量纲值时注意把v和r也作无量纲处理通常v用U0归一化r用U0/L归一化。这一步不做模型动力学就会错得离谱。3.3 静水和规则波的处理入门阶段先把环境设为静水固定航速推进。螺旋桨转速给定推力用常数模拟这样整个仿真系统不受推力控制干扰能更准确地看到船体本身的操纵特性。如果后面要加环境扰动我建议按顺序来先加恒定流因为流本质上是一个匀速平移实现最简单再加风风压力与相对风速的平方成正比最后加规则波用一阶波浪力叠加到船体力里。顺序乱了问题就很难定位。3.4 MATLAB脚本结构设计一段代码写到尾不是好习惯我通常把脚本用%%分成几个区%% 1. 参数定义 L 2.0; B 0.6; d 0.3; U0 1.5; rho 1000; % ... 水动力导数等 %% 2. 状态方程函数定义 function dx ship_model(t, x, delta, param) % x [X; Y; psi; u; v; r] % 返回状态导数 end %% 3. 数值积分主程序 % 初始条件 末端执行舵角 RK4求解 %% 4. 绘图对比 figure; plot(y, x);这样的好处是每个区块可以单独运行调试参数调整不用反复找位置。我自己调试时最喜欢这个结构改一个导数值重跑第三区马上看第四区的图就行。4. 回转试验的MATLAB实现与结果解读4.1 回转试验设置回转试验是操纵性仿真第一个要跑的工况也是最直观的验证手段。标准做法是让船以设计航速直航稳定然后瞬间打满舵通常右满舵35°保持这个舵角让船完成回转直到艏向角变化超过360°或者轨迹形成近似圆。为什么先做这个试验因为回转轨迹能暴露出模型大部分问题。如果水动力导数符号不对轨迹会往错误方向转如果导数量级不对回转直径会明显异常如果积分步长不合适轨迹不会平滑收敛成圆而会越来越扭曲。4.2 状态方程与RK4数值积分我推荐自己写一个四阶龙格库塔积分器虽然MATLAB自带ode45但固定步长RK4更容易理解也方便后面和离散控制器衔接。核心代码如下dt 0.05; % 步长根据模型特征调整 T_final 120; % 仿真时长 t 0:dt:T_final; n_steps length(t); x zeros(6, n_steps); x(:,1) [0; 0; 0; U0; 0; 0]; % 初始直航状态 delta 35 * pi / 180; % 右满舵弧度 for k 1:n_steps-1 k1 ship_model(t(k), x(:,k), delta, param); k2 ship_model(t(k)dt/2, x(:,k)dt/2*k1, delta, param); k3 ship_model(t(k)dt/2, x(:,k)dt/2*k2, delta, param); k4 ship_model(t(k)dt, x(:,k)dt*k3, delta, param); x(:,k1) x(:,k) dt/6*(k1 2*k2 2*k3 k4); endship_model函数内部的加速度计算是核心。对模型状态方程求解udot、vdot、rdot时要注意质量矩阵不是简单的对角阵尤其是处理重心不在原点时会有惯性耦合项。严格做法是对2x2或3x3的质量矩阵求逆而不是直接逐行除否则高速回转时结果会出现偏差。4.3 轨迹绘制与指标提取跑完后画轨迹figure; plot(x(2,:), x(1,:), LineWidth, 1.5); axis equal; grid on; xlabel(Y [m]); ylabel(X [m]); title(35°右回转试验轨迹);axis equal这一步很多人会漏掉不用等比例坐标圆形的回转轨迹会显示成椭圆看起来像是模型错了实际只是绘图比例问题。从轨迹里提取关键指标时我一般用这个简单办法取轨迹后半段接近定常回转的部分用圆的直径近似定常回转直径。更严谨的做法是把轨迹北向和东向的最大最小值取出来直径大概是横向范围的一半左右但这只适用于近似圆形的轨迹。对入门验证看轨迹是不是光滑圆、直径是否在合理范围内就够了。4.4 从回转轨迹判断模型合理性回转轨迹除了能算出定常回转直径还能看出一些隐性问题。比如如果初始直航阶段船就开始偏航说明模型里的非线性阻尼项可能太小或者初始条件不是稳态。如果回转轨迹逐渐扩张而不是收敛成圆大概率是积分步长太大或数值发散。定常回转直径的经验值通常是船长的3到5倍。我这条示例船船长2米仿真出来回转直径在7到9米之间换算成船长倍率大概是3.5到4.5倍说明参数量级是合理的。这个常识性检查很重要比对着复杂公式算半天更有用。5. Z形试验求取K、T操纵性指数5.1 Z形试验的操纵逻辑回转试验验证了模型的整体正确性但要量化船的操纵响应快慢就得靠Z形试验也叫Zig-Zag试验最常用的是10°/10°工况。试验流程是这样的船以设计航速直航稳定后突然操右舵10°。艏向角达到右偏10°时舵回中。艏向角回到0°时立刻操左舵10°。艏向角左偏达到10°时舵再次回中。艏向角回到0°时再操右舵10°。如此反复通常执行5次轮转。这个过程画出来很像Z字所以叫Z形试验它比回转试验更关注瞬态响应特性。5.2 舵角切换的MATLAB实现Z形试验的难点在于舵角切换条件判断。连续系统里要用事件检测但入门阶段用步进逻辑更直观每一步判断当前艏向角与阈值关系决定下一时刻舵角。psi_now x(3,k); phase 0; % 0右舵, 1回中, 2左舵, 3回中(负向) cycle 0; thresh 10 * pi / 180; while cycle 5 switch phase case 0 delta 10 * pi / 180; if psi_now thresh phase 1; end case 1 delta 0; if psi_now 0 phase 2; end case 2 delta -10 * pi / 180; if psi_now -thresh phase 3; end case 3 delta 0; if psi_now 0 phase 0; cycle cycle 1; end end end这段逻辑最容易踩的坑是角度单位。MATLAB三角函数默认用弧度但人读数据常习惯度。我建议在参数区定义一个deg2rad转换所有阈值用度定义、转成弧度代码里不要混着来否则会出现舵角已经超了但判断条件永远不触发的问题。5.3 从Z形曲线提取K、T跑完Z形试验会得到艏向角、艏摇角速度、舵角随时间变化的曲线。处理这些数据能得到K和T。一阶K-T模型的稳态关系是 r∞ K * δ。所以在Z形试验的每个操舵阶段后期艏摇角速度趋于稳定取稳定段r的值除以舵角就是K。T的估计最常用的是初始响应斜率法。初始阶段艏摇角速度从零开始上升上升斜率大约是K/T * δ。用这个斜率和已经得到的K就能算出T。如果觉得手算不踏实也可以用系统辨识工具箱把舵角作为输入、艏摇角速度作为输出用tfest拟合一个一阶传递函数Ts 0.05; data iddata(r_data, delta_data, Ts); sys tfest(data, 1, 0);拟合出来的分子系数就是K分母时间常数就是T。这个方法特别适合处理带噪声的实测数据比手动量斜率稳健得多。5.4 K、T值怎么验证拿到K和T以后一定要做一个交叉验证把辨识出的K-T模型响应和原始MMG模型响应画在同一张图上。两条曲线趋势一致、延迟差不多说明辨识结果可信。如果差异很大多半是数据段截取有问题比如把操舵瞬间的瞬态也算进去了。我第一次做Z形仿真时K值算出来比MMG模型实际响应大一倍查了半天发现是数据里包含了舵角变化造成的尖峰把均值拉高了。从稳态段取值问题立刻消失。6. 数值稳定性与调试初学最常见的三个坑6.1 积分步长与数值振荡操纵性仿真看起来简单但数值积分步长没选对结果能离谱到怀疑人生。固定步长RK4对快速系统要求步长足够小一般原则是步长小于系统最小时间常数的十分之一。我这条示例船的时间常数在几秒到十几秒量级步长取0.05秒已经足够。如果步长取到0.5秒轨迹会发散因为每个积分步里状态变化太大RK4的局部截断误差迅速累积。如果仿真里出现高频振荡先用频谱分析一下艏向角或艏摇角速度曲线看看振荡频率大概是多少再反推需不需要缩小步长。盲目缩小步长会增加计算量但从操作上最保险一步一步从大往小试到结果稳定即可。6.2 初始条件让仿真“飞出去”的物理原因初始条件不是随便给的。直接从全零状态开始仿真水面船模型会因为初始攻角过大产生很大的瞬态力导致初始阶段出现非物理的震荡甚至让后续数据完全不可用。我的做法是分两个阶段第一阶段让船直航把u稳定到U0v和r稳定到0保存这个稳态作为第二阶段正式试验的起点。如果不想分两段也可以在初始条件里直接把u设为U0、v0、r0然后让模型自行过渡。后者简单但记录数据时要去掉前面一小段瞬态否则Z形试验的判向条件会提前触发。6.3 无量纲化错误与符号错位这个坑我印象最深。水动力导数恢复有量纲值时一定要把v、r也同时做无量纲处理。很多教材把方程写成无量纲形式v用U0归一化r用U0/L归一化如果你在代码里只对导数做了量纲恢复但v、r还在用有量纲值那么力和力矩的量级会差出去几个数量级结果必然是发散。再就是符号问题。Yv的取值通常是负的因为横向速度为正时船体受到的横向力应该是恢复力把它推回零位Nv对大多数船也是负的表示艏摇方向稳定性。如果这两个符号反了船会越来越偏仿真结果看起来像完全失去操纵性。我排查这类问题时习惯先画相图看速度分量是收敛还是发散一眼就能定位。6.4 从发散到收敛的排查清单症状可能原因处理建议轨迹发散、速度无限增长水动力导数量纲错误检查无量纲恢复、检查符号轨迹高频振荡积分步长过大减小dt或换ode45自适应初始阶段瞬态过大初始条件不是稳态预热阶段或从稳定直航状态记录Z形试验阈值判断不触发角度单位混用统一用弧度阈值写清楚回转轨迹不成圆非线性阻尼过小增加v或r的高次阻尼项这个表格里的问题我几轮调试基本都遇到过每次都能从这五个方向里找到答案。操纵性模型本身不复杂绝大多数问题都出在前面这几项基础设置上。7. 从静水回转走向真实海况与控制器仿真跑通了静水回转和Z形试验这个入门项目就基本完成了。但真实项目里仿真环境还会往两个方向扩展。第一个方向是加环境扰动。恒定流模型最简单把流的速度矢量变换到船体坐标系直接叠加到船体与水的相对速度上即可。风的模型稍微复杂一点用相对风速计算风压力和风力矩气压中心通常在船体侧面靠后的位置。波浪可以按规则波线性叠加或者用统计海浪谱生成不规则波后者更接近真实海况。第二个方向是接控制器。有了可以快速跑的船模型就可以在MATLAB里测试路径跟踪算法。LOS导引是最经典的直线路径跟踪方法逻辑简单、调参方便。控制器算出来的舵令直接喂给船模型形成闭环这时候就能看到控制器在外部扰动下的实际表现比单纯用理想K-T模型设计控制器要可靠得多。更进一步的扩展是把模型升级到四自由度或六自由度把横摇、纵摇也纳入进来。无人船在波浪中航行时横摇会影响舵效和乘员舒适性某些工况下甚至比艏摇更危险。这部分会用到更多参数和更复杂的模型但前面MMG三自由度模型的框架完全可以复用只是每个力模块里多几个耦合项。我在实际项目中最大的体会是一定要先跑通最基础的三自由度静水仿真再一步步往上加复杂度。很多人一上来就想把风浪流、六自由度全做进去结果模型复杂到参数根本整定不了最后连回转轨迹都对不上。先让回转试验和Z形试验结果合理再谈扩展这个顺序能帮你省下几周的排错时间。
返回列表