☰
模糊强化学习下带输入延迟的多智能体指定性能共识控制
2026/9/26 9:02:53 网站建设 项目流程

如果你在控制方向待得够久,多半会碰到这样一个场景:课题要求里写着一长串名词——多智能体、强化学习、输入延迟、模糊控制、指定性能共识控制,最后还要在MATLAB里跑通并附上代码。第一次看到这套组合的时候,我的第一反应是“这怕不是把关键词全堆上来了”。但真正动手把一个带输入延迟的非线性多智能体系统,用模糊Actor-Critic强化学习实现带指定性能约束的最优共识控制之后,我才意识到这五个词并不是生拼硬凑,而是一条完整的问题链:共识是任务层目标,输入延迟是现实约束,指定性能是工程指标,模糊系统负责消化未知非线性,强化学习负责把“最优”两个字落到实处。本文按这条链拆解原理、梳理关键公式,并给出我在MATLAB里搭建仿真模型的完整代码结构与调参记录,适合正在做多智能体一致性、预设性能控制,以及想用强化学习做最优控制的研究生和工程师参考。

1. 五个关键词其实是一条问题链:共识、延迟、性能、模糊、强化学习各管哪一段

1.1 共识控制:任务层要解决什么

多智能体系统说白了就是一组带通信拓扑的智能体,各自只有局部信息,通过邻居之间交换状态,逐步让所有个体的状态同步到同一个值。如果系统里有一个领导者,其余是从者,问题就变成跟踪一致性问题:每个从者都希望自己的状态最终跟上领导者的轨迹。

更形式化一点,假设有N个从者和1个领导者,通信用图G描述,邻接矩阵A = [a_ij],智能体i能拿到智能体j的信息时a_ij = 1。领导者对从者的连接用b_i表示,b_i = 1说明从者i能直接收到领导者的状态。定义一个局部邻域误差:

e_i = Σ_{j=1}^{N} a_ij (x_i - x_j) + b_i (x_i - x_0)

这个误差把“我和所有邻居差多少,以及我和领导者差多少”揉到了一起。所有e_i同时收敛到0,就等价于所有x_i都收敛到x_0。写成向量形式是 E = (L + B)(x - 1 x_0),其中L是图的Laplacian矩阵。L + B这个矩阵的性质很关键:只要通信图连通,并且领导者至少能通过一条路径影响到每一个从者(即领导者根可达),L + B就是正定矩阵,一致性目标就有可能通过合适的控制律达到。

很多入门材料会告诉你,对一阶线性系统ẋ_i = u_i,直接取u_i = -c e_i就能收敛。但一旦把系统换成非线性动力学,再把执行器延迟和性能约束加进来,这个简单结论就完全不成立了。这也是为什么后面需要那一堆工具。

1.2 输入延迟与指定性能:现实层为什么难

输入延迟在真实系统里几乎必然存在:网络通信需要时间、执行器机械响应有滞后、采样保持也引入等效延迟。最要命的是延迟会破坏相位裕度,一个本来稳定的闭环,加上0.1s的延迟就可能发散。我第一个仿真实验直接把这个滞后扔进模型,结果控制量的符号在关键下降段严重滞后,跟踪误差直接冲出了预设边界。

比“不稳定”更隐蔽的问题是延迟对最优性的破坏。强化学习的目标是让某个代价泛函最小,代价里通常包含当前控制输入u_i(t),但实际作用于系统的却是u_i(t - τ)。如果在设计代价函数和更新律时忽略这个错位,你算出来的“最优策略”只是对虚假模型最优,放到真实模型上既不最优,甚至可能连稳定都保证不了。

指定性能控制要解决的是另一类问题:不光要收敛,还要收敛过程好看。很多工程场景对超调量、收敛速度、稳态误差都有硬性要求,比如机械臂关节角度不能突跳,编队成员间距不能越过安全边界。PPC的思路是用一个性能函数ρ(t)框出一个时变的误差漏斗,只要误差始终落在这个漏斗里,暂态和稳态性能就都有了保证。

1.3 模糊系统与强化学习:算法层怎么补位

现在问题清单已经有三项了——非线性不确定、延迟、性能约束。接下来是算法选型。多智能体系统里每个智能体的动力学f_i(x)、g_i(x)大概率是未知的,至少是建模不准确的,所以需要一种能在线的万能逼近器,模糊逻辑系统就是干这个的:用一组IF-THEN规则和隶属函数把未知函数在一个紧集内逼近到任意精度。

强化学习在这里的角色不是“从零探索环境”那种游戏玩法,而是求解最优控制的核心方程——HJB方程。对一个连续时间系统,设计最优反馈控制需要求解一个偏微分方程,解析解几乎不存在,传统数值方法在高维下完全不可行。Actor-Critic结构的好处是把求解转化为两个神经网络的在线迭代:Critic网络去逼近代价函数,Actor网络去逼近最优控制律,两个网络交替更新不断逼近HJB的解。在含延迟的系统里,这个框架还能通过状态增广或者李雅普诺夫-克拉索夫斯基泛函的方式把延迟信息嵌进去,后面会具体讲。

实际写代码时,模糊模块和Actor-Critic模块是分开的函数,合在一起就是一个典型的事件驱动循环:每个采样时刻,读状态、算误差、做性能变换、模糊逼近、计算控制量、更新网络权重。下面我就按这个顺序把每个模块的模型和数学过程过一遍。

2. 系统模型与控制框架:含延迟的非线性多智能体系统怎么建模

2.1 智能体动力学与通信拓扑

考虑N个从者和1个领导者。第i个从者的动力学:

ẋ_i = f_i(x_i) + g_i(x_i) u_i(t - τ_i)

这里x_i是状态,f_i和g_i是未知的光滑非线性函数,u_i是控制输入,τ_i是输入通道的延迟。领导者x_0(t)是一条已知参考轨迹,实际工程中也可能是时变目标,我后面仿真里直接取x_0(t) = sin(t)来做跟踪。

对动力学模型要做的假设都是教科书级别的,但写代码前还是要逐条确认:

  • g_i(x_i)需要有已知下界且符号固定,这样控制方向不会反转;
  • 延迟τ_i是有界常数或者时变但有上界,仿真里我取τ_i = 0.1s固定延迟;
  • 未知函数在某个紧集内有界,模糊逻辑系统的万能逼近性质才成立;
  • 通信拓扑连通,领导者根可达。

这些假设在论文里看一眼就过了,但仿真时每条都对应一次运行结果是否可信的校验,少一条都可能跑出发散或者“假收敛”。

2.2 局部邻域误差与同步目标

同步目标用局部邻域误差E = (L + B)(x - 1 x_0)来刻画。工程上更常用的是直接定义每个智能体的分布式误差e_i,因为它天然可执行——智能体i只能拿邻居状态,拿不到全局信息。前面已经给了公式,这里补充一个关键点:E收敛到0和智能体状态一致收敛到x_0,在“连通图+领导者根可达”条件下是等价的。这个等价关系是后面所有误差变换和稳定性分析的前提,别嫌它基础,很多仿真结果对不上理论,根源就是拓扑不满足条件。

仿真里我选了一个4从者的环形拓扑:每个智能体只跟左右邻居通信,领导者只连接1号和4号智能体。矩阵L + B的代码是这样:

A = [0 1 0 1; 1 0 1 0; 0 1 0 1; 1 0 1 0]; % 环形邻接矩阵 D = diag(sum(A, 2)); L = D - A; % Laplacian矩阵 B = diag([1 0 0 1]); % 领导者连接矩阵 M = L + B;

如果M的最小特征值明显大于0,说明拓扑条件满足。设计图拓扑时最容易犯的错是让某些从者完全收不到领导者信息链,此时M奇异,部分从者的误差根本压不进预设界内,性能约束形同虚设。

2.3 整体控制框架的工作流程

整套控制器的运行可以拆成五步,每步对应一个MATLAB函数:

  1. 读状态,计算局部邻域误差e_i;
  2. 用性能函数ρ_i(t)做误差变换,得到无约束的辅助误差ε_i;
  3. 模糊逻辑系统在线估计f_i和g_i,得到f̂_i、ĝ_i;
  4. Actor-Critic网络根据ε_i给出最优控制u_i;
  5. 控制量经过延迟缓冲后作用于系统,同时更新Critic和Actor权重。

这样做的好处是模块之间完全解耦:想改性能约束就只动第2步,想换网络结构就只动第4步。我做对比实验时,会把模糊模块关掉看纯RL效果,再把RL关掉看纯模糊自适应效果。这种分层结构帮了大忙,出问题能定位到到底是哪一环在拖后腿。

3. 指定性能控制:性能函数设计与误差变换是整套方案的地基

3.1 性能函数的数学形式与参数含义

预设性能的核心是选一个单调递减的正函数ρ(t),最常用的形式是:

ρ_i(t) = (ρ_0 - ρ_∞) e^{-α t} + ρ_∞

三个参数各管一件事:

  • ρ_0是初始漏斗宽度,必须大于初始误差|e_i(0)|,否则变换函数在t=0处直接无定义;
  • α控制了误差收敛的最慢速度,α越大收敛越快,但控制能量和抖振也越大;
  • ρ_∞是稳态误差允许上限,工程上就是“最终偏差不能超过多少”。

性能约束写为 -δ_min ρ_i(t) < e_i(t) < δ_max ρ_i(t),两个δ是为了同时刻画不对称暂态边界,比如允许正向超调大一点、负向不能越界。我仿真里对称情况直接取δ_min = δ_max = 1。

参数怎么选,实战中我总结的规则是:ρ_0取初始邻域误差最大值的1.2到2倍,ρ_∞按稳态跟踪精度的1.5到2倍留裕量,α先取1试跑。如果控制量饱和或者抖振明显,就把α降到0.5;如果误差在边界附近徘徊,就把α升到2。

3.2 误差变换的本质:把约束化为无约束

直接对含约束误差设计控制是麻烦的,因为既要保证稳定又要保证不越界,Lyapunov函数设计非常别扭。PPC的标准做法是用误差变换把有约束问题转成无约束问题。定义归一化误差z_i = e_i / ρ_i,然后做一个非线性映射:

ε_i = (1/2) ln((1 + z_i) / (1 - z_i))

这个映射把z在(-1, 1)区间内的变化映射到整个实数轴,反函数是z_i = tanh(ε_i)。变换厉害在逻辑上闭环:如果能设计控制律让ε_i有界(这是无约束系统的标准稳定性问题),那么z_i = tanh(ε_i) < 1,立刻推出 -ρ_i < e_i < ρ_i,性能约束自动满足。

这个技巧是整个框架里最值得反复体会的一步。它把“不能让误差越界”这样一个硬约束,转化成了“让辅助误差有界”这样一个软目标,而后者用Lyapunov方法处理起来非常顺手。

3.3 变换后的系统动力学与控制器任务

对ε_i求导,得到:

ε̇_i = q_i(e_i, ρ_i) (ė_i - e_i ρ̇_i / ρ_i)

把ė_i带入智能体动力学,整理成关于ε_i的等效模型:

ε̇_i = F_i(ε_i, ρ_i) + G_i(ε_i, ρ_i) u_i(t - τ_i)

其中F_i里包含未知非线性f_i、性能函数导数ρ̇_i以及拓扑耦合项,G_i是等效控制增益。到这里,整个控制任务变得清爽:设计u_i让ε_i系统稳定且最优。模糊系统直接作用在F_i的估计上,Actor-Critic输出针对变换后的系统,这正是标题里“最优指定性能共识控制”的落点——指定性能由ρ和变换保证,最优由强化学习在变换后系统上实现。

4. 模糊系统逼近与强化学习最优决策的分工细则

4.1 模糊逻辑系统怎么逼近未知动态

模糊逻辑系统的输出形式是:

f̂(x) = θ_f^T ψ(x)

其中θ_f是可调权重向量,ψ(x)是模糊基函数向量。一个模糊基函数ψ_k(x)的构造方式是:先给每个状态维度选隶属函数(常用高斯型),求出每条规则的前件隶属度乘积,再做中心平均反模糊化。MATLAB里这段非常省事,全是矩阵运算。

高斯隶属函数:

μ_{F_i^k}(x_i) = exp( -(x_i - c_{ik})² / σ_{ik}² )

基函数:

ψ_k(x) = (∏_i μ_{F_i^k}(x_i)) / (Σ_{j=1}^{M} ∏_i μ_{F_i^j}(x_i))

M是规则数。万能逼近定理保证,只要规则数够多、隶属函数覆盖合理,在紧集内逼近误差可以任意小。仿真里我用的是每维5条规则,对单状态系统就是5个基函数,计算量完全可忽略。

模糊系统和神经网络的一个本质区别在于:模糊规则的每条规则都有语义解释,哪条规则贡献大,可以打印出来看;神经网络则是一团黑。调试模糊系统遇到问题时,我习惯把规则激活强度打出来,看是不是某些规则从未被激活——那通常意味着隶属函数中心选得太偏,覆盖不到实际状态区域。

4.2 性能指标与HJB方程

现在考虑变换后系统的最优控制。对第i个智能体定义代价函数:

J_i = ∫_t^∞ [ ε_i(s)^T Q ε_i(s) + u_i(s)^T R u_i(s) ] ds

Q和R分别是半正定和正定加权矩阵。值函数V_i(ε_i)满足哈密顿-雅可比-贝尔曼方程:

0 = min_{u_i} [ ε_i^T Q ε_i + u_i^T R u_i + (∂V_i/∂ε_i) (F_i + G_i u_i(t - τ)) ]

如果延迟能被补偿,或者把延迟后的输入作为增广状态,最优解u_i*的形式是:

u_i* = - (1/2) R^{-1} G_i^T (∂V_i*/∂ε_i)

问题在于我们既不知道F_i、G_i,也不知道V_i*的解析形式。两个未知叠在一起,这正是模糊加强化学习一起上的理由:模糊负责第一层未知,RL负责第二层未知。

4.3 Actor-Critic更新律与延迟的嵌入方式

我用的是标准Actor-Critic在线结构。Critic网络逼近值函数:

V̂_i = w_ci^T σ_ci(ε_i)

Actor网络直接输出控制:

û_i = w_ai^T σ_ai(ε_i)

Critic的更新用的是HJB残差驱动的归一化梯度。定义残差:

e_h = σ_ci(ε_i)^T w_ci + ε_i^T Q ε_i + û_i^T R û_i

理想情况下,如果V̂_i是精确值函数,e_h应该为0。于是Critic权重沿e_h下降方向更新:

ẇ_ci = -β_c [ σ_ci / (1 + σ_ci^T σ_ci)² ] e_h

分母上的归一化项是实战里保命用的:不除的话,当ε状态变大时σ的范数快速变大,导致梯度爆炸,权重分分钟飞掉。Actor的更新则基于策略梯度近似:

ẇ_ai = -β_a σ_ai ( σ_ai^T w_ai - u_i* )

这里u_i*来自“当前最优猜测”,也就是由V̂_i推导出的贪心控制。边界上还需要加一个小的探测噪声n_i(t)来满足持续激励条件,没有激励的话Critic权重只能收敛到平凡解,这是在线强化学习绕不开的问题。

延迟的嵌入方式我采用了状态增广的变体:在每个采样时刻,把最近一段时间内的控制历史[u_i(t - τ), ..., u_i(t)]拼进Critic的输入向量。严格的学术做法是定义增广状态在泛函空间上做分析,但工程代码里就是开一个环形缓冲,把延迟后的控制输入读出来,跟ε_i拼接后送进网络。配合Lyapunov-Krasovskii泛函的稳定性条件,效果等价于在代价函数里隐式加入了延迟鲁棒项。

5. MATLAB仿真实现:模型搭建、代码结构和关键函数

5.1 仿真场景与图拓扑参数

下面是我跑通的仿真配置。智能体动力学故意取非线性甚至带状态相关增益的形式:

ẋ_i = sin(x_i) + (1 + 0.2 cos(x_i)) u_i(t - 0.1)

领导者轨迹x_0 = sin(t)。4个从者环形拓扑,矩阵M的设置见第2节。初始状态随机分布在[-0.6, 1.2],故意让部分初始误差略大,这样能看到性能函数约束真正起作用的过程。

仿真参数如下:

参数数值说明
N4从者数量
dt0.001 s仿真步长
τ0.1 s输入延迟
ρ_02.0性能函数初值
ρ_∞0.01稳态误差上界
α1.0性能函数衰减率
β_c / β_a0.05 / 0.01Critic/Actor学习率
Q1.0状态代价权重
R1.0控制代价权重

主循环骨架:

dt = 0.001; T = 20; t = 0:dt:T; N = 4; delayLen = round(0.1/dt); % 延迟对应的缓冲长度 uBuf = zeros(N, delayLen); x = [0.5; 0.8; -0.3; 1.0]; % 从者初始状态,一维状态示例 XL = sin(t); % 领导者轨迹

5.2 模糊模块与Actor-Critic模块的代码实现

模糊基函数用一个独立函数实现:

function psi = fbf(x, centers, widths) % x: 1 x nDim, centers: nRules x nDim, widths: 1 x nDim logPhi = -sum(((x - centers).^2) ./ widths, 2); phi = exp(logPhi); psi = phi / (sum(phi) + 1e-6); end

注意分母加了一个小常数,防止所有隶属度都为零时除零。这一步看着小,实际能省掉很多NaN报错。

Critic和Actor更新是每个智能体独立计算的:

% Critic更新 sigma_c = fbf(eps_i, centers_c, widths_c); hjb = sigma_c' * wc_i + Q * eps_i^2 + R * u_i^2; wc_i = wc_i - beta_c * sigma_c / (1 + sigma_c'*sigma_c)^2 * hjb * dt; % Actor更新 sigma_a = fbf(eps_i, centers_a, widths_a); u_star = -0.5 * Rinv * g_hat * (2 * wc_i' * sigma_c); % 由Critic推出的贪心控制 wa_i = wa_i - beta_a * sigma_a * (sigma_a'*wa_i - u_star) * dt;

Actor实际输出的控制量是û_i = wa_i^T σ_a(ε_i)。我还在前5秒叠加了一个衰减探测噪声n_i = 0.05 * e^{-0.3t} * sin(5t),用来激发Critic网络各模态,避免持续激励不足。

5.3 延迟仿真与求解器配置

延迟的仿真处理没有捷径,就是把控制量排队:

idx = mod(k - 1, delayLen) + 1; u_delayed = uBuf(:, idx); uBuf(:, idx) = u_apply; % 把当前计算出的控制量写入缓冲

这里有一个经常被忽略的细节:如果dt和延迟τ不成整数倍关系,就需要做插值或者找最近采样点,实际等效延迟会有dt/2的量化误差。20s仿真、dt = 0.001只引入0.0005s偏差,无所谓。但如果你用可变步长ODE求解器就要特别小心,因为步长会动态变化,缓冲索引会乱掉。

我为了省事全部用固定步长欧拉法,虽然精度低一点,但整套逻辑可控,出问题容易定位。真要高精度,可以改用dde23专门解延迟微分方程,代价是需要把Actor-Critic权重更新写成带历史依赖的函数,代码复杂度会高一个量级。

5.4 结果绘图与收敛性判断

结果按四张图来看。

第一张是每个从者的跟踪误差e_i和性能边界±ρ_i(t)画在一起,只要所有e_i都夹在两条曲线中间,指定性能就算达标。第二张是变换后误差ε_i随时间变化,理想情况下应该从初始值快速收敛到原点附近的小邻域。第三张是控制输入u_i,重点看有没有持续抖振或者瞬时尖峰。第四张是Critic权重w_ci的范数,它不要求一定收敛到某个具体值,但必须在十几秒内趋于平稳。如果一直大幅震荡,说明持续激励不足或者学习率不匹配。

判断“最优”是否真的达到,我用的办法比较粗暴:把最终学到的Actor策略固定下来,跑一个完全不更新的测试回合,看它的累计代价和训练回合末端Critic预测的值函数是否一致。两者偏差小,说明Critic学到的代价函数和系统实际付出的代价对上了,这就是“最优”的量化证据。

6. 调参经验与踩坑记录:从发散到收敛,我试出来的实用规则

6.1 学习率组合

我第一个版本把β_c和β_a都设为0.5,结果在5秒内权重爆炸,NaN直接灌满了整个数组。原因有两层:一是Critic残差没有归一化,二是Actor和Critic的更新速率必须拉开差距。仿照多时间尺度随机逼近的标准做法,我最后取β_c = 0.05、β_a = 0.01。经验法则是Critic要比Actor快一个量级,因为Actor需要一个相对准确的“老师”来指导方向,Critic还没站稳就去更新Actor,策略会原地打转。

6.2 模糊隶属函数数量与初始化

规则数方面,一维状态用5条高斯隶属函数,中心均匀分布在状态取值范围上,宽度取相邻中心距的1.2倍,工作得很好。规则数加到9条收益很小,但调参难度明显上升。状态维数一高就要小心指数爆炸,三维以上建议用稀疏规则或者改RBF网络结构。

模糊权重的初始值可以全部设零,但一定要保证f̂_i在初始状态附近不能偏差太大。我遇到过这样一个问题:f̂初始为零,导致等效模型F_i的估计动作过小,控制量一开始就饱和。后来我把模糊权重初始化成在初始状态处输出一个与真实单位量级一致的值——说白了就是用一个小偏置让控制器起步时不至于“睁眼瞎”。

6.3 性能函数参数与Q、R的影响

我把α从1调到2时,误差收敛速度确实快了,但控制输入的峰值几乎翻倍,在延迟存在的情况下甚至激出了高频振荡。原因是性能函数收缩太快,误差变换的增益在瞬间变大,相当于把高增益比例项强行塞进回路。没有延迟的系统也许能承受,有延迟的系统吃不下这种增益冲击。所以α和τ之间存在一个隐性约束:ατ的乘积不能太大,我试下来ατ大于0.4就明显劣化。这个坑教科书里很少明确写,但仿真里非常直观。

Q和R的比例决定“性能”和“控制成本”的性价比。Q / R取10时,误差收敛得很漂亮,但控制量在延迟作用下明显过冲;Q / R降到1,稳态误差略微变大,控制量平顺很多。我的建议是:先把RL关掉,用固定的高增益反馈保证系统稳定并通过性能约束,再以这个控制量的幅值为参照去选R,这样RL学出来的控制不会一上来就超出执行器合理范围。

6.4 一个典型发散案例的排查链路

最后给一次实际踩坑记录。现象:所有误差在初始阶段表现良好,第8秒左右第2个智能体的误差突然冲出性能边界,之后直接发散。

排查过程我按顺序走了四步。第一步,关掉RL,把控制固定成纯模糊自适应加PD,看是否还发散——发散消失,问题定位到Actor-Critic模块。第二步,把Critic残差e_h打印出来,发现其数值在第8秒前快速增大,说明是值函数估计先崩了。第三步,检查σ_ci的范数,发现ε_2因为某个瞬间扰动跑到了隶属函数覆盖范围之外,所有基函数输出几乎为零,归一化后梯度方向被噪声主导。第四步,解决方案是把基函数宽度调大30%,并对ε_i做软饱和处理,在进入网络前把超出边界的部分拉回边界附近。

这个案例给我的教训是:模糊系统加强化学习这类在线学习结构,最怕的不是参数不够准,而是“网络进入从未见过的输入区域”后梯度信息失真。处理办法就两个方向,要么扩大隶属函数覆盖范围,要么在输入端做限幅。两招都上之后,仿真从第5次开始再也没有出现过中途发散。

这套框架我在本地还扩展过两个方向:把固定拓扑换成时变切换拓扑,以及在执行器饱和约束下做测试。模糊规则数和网络结构都不用大改,主要调性能函数和Q、R就能得到可接受的结果。代码的每个模块我都拆成了独立函数,改动起来很快。你如果正在往这个方向做,我建议先把无延迟、无约束的版本跑通,再逐步往里加模块,每一步的仿真曲线都留底稿,出问题可以二分定位。控制算法这种东西,跑通一次不代表理解,跑崩一次才真正理解。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询