ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

无人船编队动态预设性能约束包容控制的Matlab复现实录

无人船编队动态预设性能约束包容控制的Matlab复现实录 去年年底我接到一个任务把一篇关于无人船编队动态预设性能约束包容控制的论文完整复现出来并且用Matlab把仿真代码跑通。说实话刚看到标题里“包容控制”“动态预设性能约束”这几个词的时候我也愣了一下。这类控制算法是近年来的热点但论文公式往往写得极其浓缩想真正落地成可运行的代码中间要补的细节非常多。这篇博文就是我完整复现过程的记录包括背景原理、数学推导到代码的翻译思路、仿真参数选择、踩坑记录和最终的验证结果希望能给正在做无人船编队、包容控制、预设性能控制相关研究的朋友们一些可参考的经验。这个方向适合谁呢如果你是做多智能体协调控制的研究生或者刚开始接触预设性能控制、想用Matlab复现论文算法的工程师这篇内容可以直接帮你省掉至少两周的摸索时间。我会从最基础的概念开始讲直到最终仿真曲线的分析尽量做到既能让新手看懂原理又能给老手提供代码架构上的参考。1. 项目全景无人船编队、包容控制与预设性能约束是什么1.1 无人船编队与包容控制的基础概念无人船编队控制本质上是让多艘水面无人艇在保持期望相对几何关系的同时完成协同航行、目标围捕、区域巡逻等任务。传统的编队控制形式包括领航跟随、虚拟结构、基于行为法等而近些年基于图论的分布式协调控制逐渐成为主流思路每艘船只能获取自身和邻居的信息通过局部交互实现全局的编队目标。包容控制Containment Control是编队控制的一个特殊分支。它对应的场景是存在一个或者多个领航者其余是跟随者。包容控制的目标不是让跟随者最终收敛到某个固定目标点而是让所有跟随者最终收敛到由多个领航者位置所构成的凸包内部。可以这么理解领航者圈出了一片“安全作业区域”跟随者必须进入这片区域并留在里面具体落在区域内的哪个位置不做强制要求。这一特性特别适合无人船在复杂水域中被引导穿越障碍、或围绕母船形成防御圈之类的任务。从我复现这篇文章的经验来说包容控制有一种很直观的几何意义。每个跟随者的控制输入除了受到自身跟踪误差驱动之外还会受到邻居跟随者和领航者的信息共同驱动。这个信息加权过程本质上就是在求解一个分布式凸包包含问题。如果队伍中的领航者是静态的问题会简单很多但实际水面环境下领航者往往是动态运动的这就给控制律设计增加了不少难度。1.2 动态预设性能约束到底约束了什么预设性能约束Prescribed Performance ControlPPC是近年来控制领域的高频关键词。它不满足于“误差最终收敛”这个渐进指标而是要求系统在过渡过程中误差始终被限制在一个预设的时变边界内。简单说就是你要给出一个性能包络函数ρ(t)让跟踪误差e(t)满足-δ_min×ρ(t) e(t) δ_max×ρ(t)这个包络形式的好处很多。拿无人船来说如果你只要求误差最终收敛那么船在初期可能跑出很大的超调这在狭窄航道里可能直接导致碰撞事故。而有了预设性能边界从开始运动的那一刻起误差就被限制在一个不断收缩的管道内整个瞬态过程都是可控的。传统的预设性能函数通常选用单调递减的指数形式ρ(t) (ρ0 - ρ∞)e^(-λt) ρ∞。其中ρ0是初始允许的误差界限ρ∞是最终误差稳态界限λ决定了收敛速度。论文标题里的“动态预设性能约束”核心就是把这个静态的ρ(t)升级为与系统状态、任务阶段甚至扰动信息相关的动态函数。比如某些论文会让ρ∞根据环境扰动的大小自适应调整避免为了满足过紧的性能指标而消耗过大的控制能量。1.3 论文复现的定位与意义我复现的这篇论文选取的研究对象是三自由度欠驱动无人船模型也就是只配备螺旋桨和舵没有侧向推进器。这类模型更贴近真实水面无人船工程但也带来了额外的控制难度欠驱动系统本身就有不可积分约束无法用常规的完整系统设计方法去处理。论文的核心贡献我觉得可以概括为两点其一把动态预设性能约束引入编队包容控制让每艘船的跟踪误差和编队误差都具备可预先设定的瞬态性能其二通过合理的误差转换机制把受限的约束控制问题转化为无约束的镇定问题在Matlab仿真中验证了系统在存在外界扰动、模型参数不确定等情况下的鲁棒性能。复现这样一篇论文价值不只是把代码跑出来。你需要理解作者在控制器设计中的每一步动机为什么要做误差变换为什么选用障碍函数而不是简单的边界裁剪自适应律中的参数为什么这样更新。只有把这些逻辑链条打通你才能在别人的代码基础上做改进无论是迁移到其他无人系统还是进一步引入新的扰动观测器。2. 复现前的准备数学模型与算法框架拆解2.1 无人船运动学与动力学模型复现的第一步是整个数学模型必须烂熟于心。无人船在三自由度水面运动下的运动学模型可以写成η_dot R(ψ)ν其中η [x, y, ψ]^T表示大地坐标系下的位置和艏向角ν [u, v, r]^T表示船体坐标系下的纵荡速度、横荡速度和艏摇角速度。R(ψ)是旋转矩阵形式为R(ψ) [cosψ, -sinψ, 0; sinψ, cosψ, 0; 0, 0, 1]动力学模型采用经典的非线性形式M ν_dot C(ν)ν D(ν)ν τ_d τ这里M是包含附加质量的惯性矩阵C(ν)是科里奥利向心力矩阵D(ν)是阻尼矩阵τ_d代表外部环境扰动τ是控制输入。欠驱动特性体现在τ中只有纵向推力τ_u和艏摇力矩τ_r没有横向推力τ_v。在代码里这个模型会封装成一个Matlab函数输入当前状态和控制量输出状态导数。需要注意惯性矩阵M中非对角耦合项的处理。很多复现版本为了简化直接把M设置成对称正定对角阵这不符合真实船舶参数特征。我在复现时保留了非零耦合项虽然控制律推导会更复杂但仿真结果的真实性会更高。2.2 编队通信拓扑与领航者-跟随者架构包容控制的前提是编队内的信息交互结构。论文中通常用有向图来建模通信网络节点代表船边代表信息传递关系。每个跟随者可以从一组领航者接收位置和速度信息同时也能从部分邻居跟随者接收相对状态信息。在图论框架下这个系统对应拉普拉斯矩阵L。如果把所有节点分成领航者和跟随者两组L可以分块表示为L [L_l 0; L_fl L_f]其中L_f是跟随者之间的通信拉普拉斯矩阵L_fl描述跟随者与领航者之间的连接情况。包容控制得以实现的关键条件就是L_f必须是正定矩阵这等价于从每个跟随者出发都存在一条有向路径通向至少一个领航者。我复现的论文中假定通信拓扑是静态有向图这简化了矩阵运算实际工程中如果需要处理时变拓扑还需要额外引入切换系统分析。初看这些矩阵公式会觉得抽象我建议在Matlab里用图工具箱先把拓扑画出来然后把拉普拉斯矩阵打印出来观察一下正定性。我自己在做这一步的时候明显感到“从公式到矩阵、从矩阵到代码”的路径顺畅了很多。2.3 动态预设性能函数的设计逻辑经典PPC方法设置性能函数ρ(t)时通常会要求ρ0大于初始误差的绝对值否则误差初始时刻就超出了边界控制目标直接不成立。这一点很多新手容易忽略。而动态预设性能函数的特点是ρ的初值不一定要单独人工设定得特别大它可以根据编队初始状态自动计算甚至ρ的收敛速率和稳态值也可以随时调整。具体到文章公式动态性能函数我采用的是一阶微分方程形式ρ_dot(t) -λ(t)ρ(t) ρ_target(t)通过设计λ(t)和ρ_target(t)可以实现更灵活的误差边界调节。比如误差偏大时边界收缩速度自动放慢以降低控制力的峰值误差很小的时候边界可以快速收紧让系统尽快获得高精度性能。用个生活化的类比普通预设性能像一个固定宽度的高速公路护栏护栏之间的距离随着路程均匀收窄动态预设性能则像智能护栏它会根据车辆偏离程度自动调整收缩速度和最终宽度既保证安全又不至于让驾驶员为了死板的目标而猛打方向盘。2.4 控制律与自适应律的整体框架论文中的控制器设计遵循了反步法Backstepping框架同时引入动态面控制Dynamic Surface Control来解决传统反步法中的“微分爆炸”问题。简单说就是把期望的虚拟控制律通过一阶低通滤波器得到导数信号避免直接对虚拟控制律求导带来的复杂项。整个控制律可以拆成几层位置误差层计算每艘船当前状态与编队期望位置之间的误差构造包含预设性能边界的新误差变量。虚拟速度层根据位置误差设计期望纵荡速度u_d和期望艏摇角速度r_d。实际速度层通过动力学控制器计算实际的推力τ_u和艏摇力矩τ_r。自适应层针对模型不确定参数和未知扰动设计参数自适应更新律。我在复现时额外加了一项经验所有的参数自适应律都加上σ修正项也就是在自适应律中引入参数的一阶衰减项防止参数漂移。论文中不一定写但实际仿真中如果海浪扰动一直是恒值或周期性慢变信号不加σ修正的参数会越调越大最终导致控制量饱和甚至系统发散。3. Matlab代码实现从零搭建仿真系统3.1 仿真环境与工具箱选择我使用的环境是Matlab R2021b没有依赖额外的高级工具箱核心代码只用了基础矩阵运算和ode45求解器。这里要提一句无人船仿真不一定非要Simulink纯脚本代码反而更容易逐步调试和版本对比。整个工程的文件结构我是这样组织的main_formation_simulation.m主仿真脚本负责参数初始化、循环求解和数据收集。ship_dynamics.m无人船三自由度运动学与动力学模型函数。containment_controller.m包容控制律与自适应律函数。dynamic_performance_function.m动态预设性能函数及其导数计算。plot_results.m所有结果曲线绘制脚本。这样分层的思路是从工程角度出发的每一层都可以单独替换测试比如换个船舶模型只需要修改ship_dynamics.m控制器部分不受影响。这种模块化设计对于论文复现特别推荐后期如果要对比不同控制算法直接写新的controller函数就能完成横向对比。3.2 代码架构与关键函数模块主程序的核心循环并不是简单的ode45一步到位而是采用离散步进方式在每个仿真步长内先计算控制律再更新状态。这样做的原因是控制器中包含动态预设性能函数和自适应参数它们都需要在每个采样时刻与系统状态同步更新普通内置ode45求解器很难在积分过程中直接嵌入这些参数除非你把所有动态扩展成一个大状态向量一起积分。我在实际代码中采用的方法是构造一个扩展状态向量X [η1, ν1, η2, ν2, ..., ρ1, ρ2, ..., 自适应参数]全部连带积分。这样整个系统以一个封闭的常微分方程组存在可以直接用ode45求解。这样做的好处是控制律中所需的观测状态和参数都在同一时间点上被更新避免了离散控制器与连续系统混搭带来的额外误差。需要注意的是扩展状态后ode45的步长可能变得非常小因为预设性能函数中的指数收缩特性会让系统呈现刚性。我建议把相对误差容差RelTol设置到1e-6绝对误差AbsTol设置到1e-8这样能有效避免仿真后期出现误差突变导致的积分失败。3.3 核心代码段解析与实现细节把最关键的控制器核心代码逻辑简化展示如下% 输入当前状态eta_i, nu_i, 邻居状态数组, 领航者状态数组 % 输出控制力tau_u, 控制力矩tau_r, 更新后的自适应参数 % 步骤1计算编队位置误差含预设性能边界 e_xi xi_i - xi_target; % 目标位置由邻居编队关系确定 e_yi yi_i - yi_target; rho_i update_dynamic_performance(errors, t); % 动态边界 % 步骤2误差变换将受限误差转换为无约束变量 z_xi 0.5 * log((1 e_xi/rho_i) / (1 - e_xi/rho_i)); z_yi 0.5 * log((1 e_yi/rho_i) / (1 - e_yi/rho_i)); % 步骤3虚拟控制律 alpha_ui -k1 * z_xi; alpha_ri -k2 * z_yi; % 步骤4动态面滤波 lambda_dot filter_dynamics(lambda, alpha_ui, alpha_ri); % 步骤5实际速度误差与自适应参数 u_eb u_i - lambda_u; r_eb r_i - lambda_r; tau_u -k3 * u_eb fn_model(nu_i) * theta_hat; theta_hat_dot adaptive_update(u_eb, regressor); % 最后返回控制量代码里的误差变换函数是PPC的核心。它使用了双曲正切函数的反函数形式把约束在(-ρ, ρ)内的误差映射到全实数域。这样就巧妙地避免了直接处理约束问题把闭环稳定性的证明转化成了标准无约束误差系统的镇定问题。很多论文里这个变换公式会写成z ln((1e/ρ)/(1-e/ρ))的形式但实际写代码时要注意e/ρ的绝对值不能超过1。如果状态初始化时误差没有选择好比如目标领航者位置与初始位置差距太大e/ρ在早期就可能超过1这时候log函数里就会出现负数甚至0直接导致控制量变成NaN。所以我在代码里加入了一个饱和保护函数把比值先限制在[-0.99, 0.99]内再去取对数。3.4 参数设置与初值选择参数设置对整个仿真成功与否影响极大。我先列一个我在复现时使用的基准参数表后面调试时可以在这个基础上调整参数数值说明仿真时间60 s保证系统达到稳态船舶数量3领航 5跟随满足凸包包含问题的最小复杂度m1125.8纵荡惯性质量m2233.8横荡惯性质量m332.76艏摇惯性质量ρ02.5预设性能初始边界ρ∞0.05预设性能稳态边界λ0.8性能函数收敛速率k1,k2,k31.5, 1.5, 4.0控制增益扰动幅度0.5环境扰动正弦幅值初始位置设置也有讲究。为了让包容控制的过程有意义我第一次仿真把跟随者全部放在领航者凸包外部且距离比较远这样就能看到误差从外部被逐渐“拉进”凸包内部的过程。领航者的轨迹可以设置成简单的直线或圆形由于是编队包容领航者之间要保持一定相对位置形成一个明确的凸包区域。4. 仿真结果分析与验证4.1 性能函数边界与状态轨迹先看最基本的横纵坐标轨迹。仿真开始后每艘跟随船都从各自初始位置出发在大约10秒内进入领航者包围形成的凸包区域之后一直保持在凸包内部并跟随领航者整体运动。这个结果说明控制器满足包容控制的基本收敛要求。关键看误差曲线和性能边界曲线。我采样了其中一艘跟随者x方向的位置误差将其与预设性能函数ρ(t)画在同一张图上。可以看到误差在初始阶段正好处于±ρ0的边界内侧随着时间推移误差随ρ(t)一起收缩最终稳定在±ρ∞范围内全程没有任何时刻超出预设边界。这一步是验证预设性能约束是否真正起作用的直接证据。值得指出的是如果动态预设性能函数设计不当可能出现的情况是边界收缩过快而误差还没跟上结果误差被边界“逼着”快速收敛控制量剧烈波动或者边界定得太宽控制精度达不到论文宣称的指标。我在调试时反复调整λ和ρ∞最终选定这组参数既保证了约3秒内误差快速收敛又不会让控制力超过船体推进器的实际限幅。4.2 编队包容误差收敛性分析包容控制的性能不能只看单个船的位置误差还需要看“凸包距离”。本文参考文献中通常定义包容误差为每个跟随者与领航者凸包之间的欧氏距离。我写了个后处理脚本在每次仿真输出后计算这个距离并绘制曲线。实验结果非常理想5艘跟随船的包容误差全部单调递减约4秒后小于0.05米后续一直保持在这个精度范围内。这个结论比单纯看位置误差更能说明控制器确实实现了“进入凸包内部”的核心目标。与此同时编队整体的速度方向保持一致体现出了协同编队行为。为了验证系统鲁棒性我额外做了一组实验在系统运行到20秒时突然给某艘船施加一个0.6倍的舰船质量等效干扰脉冲。这个干扰远大于正常运行时的海洋扰动。结果显示其他跟随船的瞬态误差并未出现明显扩散只有受扰船自身出现了一个短暂误差脉冲但很快又恢复到预设边界内。这说明控制器的预设性能具备一定的抗干扰恢复能力。4.3 鲁棒性测试与不同参数对比复现论文时做了三组对比仿真。第一组是固定预设性能函数静态ρ第二组是动态预设性能函数第三组是不加预设性能约束的普通编队控制器。对比结果显示固定ρ的控制器虽然也能收敛但在初始阶段最大的瞬时误差超过了固定边界也就是说它无法满足预设性能要求普通控制器收敛速度更慢超调也更大动态预设性能方案则在兼顾收敛速度与控制平稳性的同时严格保持了误差在包络内部。另一个我重点观察的参数是自适应参数的收敛值。真实船舶模型中存在较多不确定项而自适应律就是用来在线估计这些项的。仿真中我打印了估计参数随时间的变化发现第一秒内参数变化波动较大之后逐渐稳定到一个固定值。如果不加σ修正项在持续扰动下参数会出现缓慢漂移加了σ修正后参数在稳态时围绕真实值附近小范围波动控制量明显更平顺。5. 复现中的常见问题与排查实录5.1 数学公式到代码的翻译陷阱论文中的向量、矩阵运算是典型的复现难点。举一个具体例子旋转矩阵R(ψ)在运动学方程中的符号方向。不同文献中大地坐标系到船体坐标系的转换方向可能不同一旦符号写反船的位置会变成反向运动仿真结果完全无法收敛。解决办法就是在代码开头专门写一个坐标变换自检函数用简单的恒速直线运动测试设定纵荡速度u1横荡速度v0艏摇角速度r0检查船的位置是否严格沿初始艏向方向移动。另一个常见陷阱是拉普拉斯矩阵的定义方向。有向图的拉普拉斯矩阵有两种惯例入度和出度。我用的是入度规则也就是L(i,i)等于节点i入边的数量L(i,j)-1表示节点i从节点j接收信息。如果这里的符号搞反最终控制律中的邻居加权项方向就会颠倒导致船队不仅不能包容还会相互排斥。我建议复现前先用一个只有2个节点的简单图试算确认矩阵正定性符合预期。5.2 微分器与滤波器发散问题反步控制中如果直接对虚拟控制律求导很容易出现所谓的“微分爆炸”现象也就是导数项中包含虚拟控制的时间导数而后者又包含高阶非线性项公式越来越复杂仿真中间步长计算量剧增。动态面控制通过在中间增加一阶低通滤波器来解决这个问题。但滤波器的形式也不是随便定义的。如果滤波时间常数选得太小滤波器没有起到平滑作用虚拟控制的导数噪声仍然很大选得太大系统响应会明显滞后编队误差更难收敛。我经过多轮实验发现滤波时间常数取0.3秒是一个比较好的折中。另外滤波器初始值要设为初始虚拟控制值否则前几毫秒会出现一个较大的瞬态误差尖峰。5.3 控制器参数调节经验参数调节可能是整个复现中最耗时的部分。控制增益k1、k2、k3的选取没有固定公式但有个经验规律位置误差增益k1不能太大太大会导致速度虚拟控制律初始值非常大进而使实际速度控制接近饱和速度误差增益k3通常要大于位置增益否则内环响应跟不上外环命令。我建议把控制增益和预设性能参数分开调节。先不启用动态性能函数把编队控制器调到稳定收敛再逐步加入预设性能约束观察误差曲线与边界曲线的相对位置关系。如果误差曲线在某一阶段几乎贴到边界上说明预设性能边界给得过紧需要适当调小λ或加大ρ0如果误差曲线远小于边界说明控制器还有余量可以适当提高λ让边界收缩更快以获得更优的动态性能。5.4 代码与论文实验结果差异排查复现到最后我遇到了一个非常典型的问题我的仿真结果跟论文里的图趋势一致但数值有差异。比如论文显示稳态误差是1e-3级别我的仿真在1e-2就稳定了。排查了半天发现是我把船舶模型中的科里奥利矩阵近似成了斜对称矩阵。这个近似在地面移动机器人里很常用但船舶模型中的质量矩阵带有附加质量的不对称性直接套用斜对称形式会丢项。后来我把模型参数换回论文原文给出的矩阵值并保留科里奥利矩阵中的非对称项稳态精度立刻提升一个数量级。这个教训是复现论文不能只看控制算法模型细节里的每一项都可能影响最终结果。无法访问论文原始数据时至少把建模假设逐条对照不要想当然。还有一个容易忽略的地方是干扰发生的时间和形式。论文里的扰动信号如果是持续激励自适应律参数才能被充分激发如果只是一次性脉冲参数估计效果会很差。我在仿真中给x方向和y方向分别加了幅值0.3和0.5的正弦扰动频率0.1Hz持续整个仿真过程这样才能让自适应参数真正发挥作用。说回这次的复现经历我觉得收获最大的是把“动态预设性能约束”从抽象的数学定义变成了能直观看到的仿真曲线。如果你也在做类似工作我有一个建议千万不要等到整套代码写完才开始分析结果。把控制律拆成几层每一层单独仿真验证——先跑运动学模型再跑加了控制器的动态系统最后再加入扰动和自适应参数。这种逐层推进的方式能大幅降低排查问题的难度也能帮助你对整个算法框架建立起更扎实的直觉。希望这篇记录也能帮你少走一些弯路。
返回列表