首页 / 资讯中心 / 文章详情

基于预设时间观测器的无人机编队容错控制仿真复现

基于预设时间观测器的无人机编队容错控制仿真复现 ★ FEATURED ARTICLE
简介一份论文复现资料包面向自动化控制科研人员与研究生聚焦多无人机系统的预设时间编队容错控制。其核心是新型观测器设计将状态观测、扰动估计与执行器故障在线辨识统一起来并结合分布式预设时间编队跟踪控制协议解决存在外部干扰和故障时的快速编队协同问题。包体为1个PDF文件大小约900KB包含可运行的Python代码、数值仿真思路及关键理论解析覆盖预设时间收敛机制、增广观测器设计、周期时滞稳定性等难点。已有83人学习下载。读者可借此复现论文核心仿真理解预设时间参数与观测器增益的调节方式观察编队误差收敛和故障估计动态并扩展至复杂环境下的多无人机编队快速控制提升系统鲁棒性与可靠性。1. 预设时间编队容错控制给无人机群的“准点”承诺先说一个反直觉的结论预设时间控制的重点不是“快”而是“准”。固定时间收敛告诉你收敛时间的上界有限时间收敛告诉你系统终会停下而预设时间控制保证所有初值下系统在同一个时刻完成收敛误差完全归零。把这件事放进无人机编队里意味着领航机何时转弯、从哪一跳开始提速跟随机的相对位置必须在设定时刻精确到位不受初始偏差、通信波动和故障大小的影响。本博文要复现的正是这样一套基于新型观测器的线性UAVs预设时间编队容错控制方案它把分布式控制、状态观测器和执行器故障重构揉进同一个闭环里适合研究编队控制、容错控制或做论文仿真的从业者。下面我会按公式、代码、参数、坑点的顺序一路讲到底。2. 预设时间收敛的理论地基模型、Lyapunov函数与观测器选型2.1 线性UAVs编队动力学与四类常见故障模型做编队控制的第一步永远是把单机模型写到能“算”的程度。仿真里我不会直接塞进一套真实无人机的空气动力学模型而是采用线性双积分器模型作为编队控制的被控对象这也是预设时间编队控制论文里的主流做法。每个UAV的位置向量记作 p_i(t)∈R^d速度向量记作 v_i(t)∈R^d输入为加速度指令 u_i(t)∈R^d。动力学写成ṗ_i v_i v̇_i u_i f_i(t) d_i(t)其中 f_i(t) 是执行器故障d_i(t) 是外部扰动。对线性无人机模型d_i(t) 通常看作有限能量扰动在仿真里用一个带幅值的正弦或脉冲函数代偿。故障模型在容错控制里会直接影响观测器结构设计。我一般把执行器故障分成四类常值偏差型f常数、时变缓变型fsin或斜坡、突变阶跃型f在某个时刻跳变、以及完全失效型f-u相当于舵面卡死或电机停转。预设时间容错控制论文最常覆盖前三种因为完全失效型需要控制分配重构超出了线性观测器的能力范围。复现时若把第四种也塞进仿真观测器重构出来的故障会接近负输入编队误差往往无法归零容易误判为算法不行。编队目标设定为领航-跟随结构领航者轨迹 p_d(t) 事先给定第 i 个跟随者期望位置为 p_i*(t)p_d(t)r_ir_i 是编队相对偏移量例如三角形编队的边长向量。控制目标是让每个跟随者在预设时间序列 T_c 内收敛到自己的相对位置同时速度收敛到领航者速度。这里“编队误差”定义为实际相对位置与期望相对位置之差再做坐标变换写到图拓扑上就会得到一个完全线性但带故障项的系统。2.2 预设时间稳定的数学条件为什么收敛时刻可预先设定预设时间控制的核心理念是在收敛过程中引入一个随时间趋于无穷的增益函数使得Lyapunov函数的衰减速度在设定时刻到达前就耗尽趋势。它和有限时间、固定时间最大的区别在于不依赖初值收敛时刻由设计参数直接给定。假设对每个子系统的编队误差构造Lyapunov函数 V_i(t)控制目标是 V_i 在 tT_c 时衰减到0。我采用的做法是引入剩余时间变量τ(t) T_c - t把预设时间问题转化为系统闭环满足V̇_i ≤ - κ * V_i / τ(t) 当 τ(t) 0这里 κ 是大于某个常数的增益系数。对这个微分不等式做直接积分可得到 V_i(t) V_i(0) * (1 - t/T_c)^κ在 tT_c 时刚好为0且与 V_i(0) 无关。这正是预设时间稳定性的直观数学来源你不需要用Barbalat引理做繁琐推理只要在控制器中预留倒数增益即可。控制器结构也因此确定在常规状态反馈项前面乘上因子 1/τ(t)随着 t 趋近T_c反馈增益趋向无穷大。这个“无穷大增益”在真实系统里显然不能持续所以仿真实现中要在 τ(t) ≤ ε 时切换为固定高增益ε 取一个小正数实践中取 0.05s 量级相当于把预设时间收敛改为“接近预设时间的有限时间收敛”不会破坏前述收敛性质。后面第五章会讲这个切换点设置得不好会造成什么灾难。2.3 新型观测器设计为什么必须把状态估计和故障重构放到一起分布式编队里每个UAV通常只能测量自己的位置和速度无法直接获得相邻UAV的完整状态同时执行器故障 f_i 无法直接测量。要做容错必须先把不可测状态和故障一起估计出来这就是观测器必须存在的理由。我说“新型观测器”是指在常规线性扩展状态观测器LESO基础上引入预设时间增益的观测器。莱斯利·齐默曼There is no need to mention any real entity. Ill use generic terms.观测器设计为增广形式将执行器故障 f_i 作为扩展状态x̂̇_p x̂_v L_1/τ(t) * (p_i - x̂_p) x̂̇_v u_i f̂_i L_2/τ(t) * (p_i - x̂_p) f̂̇ L_3/τ(t) * (p_i - x̂_p)这里 L_1, L_2, L_3 是观测器设计参数通常取带宽参数ω_o 的幂次组合例如 L_13ω_oL_23ω_o²L_3ω_o³。增益也乘上 1/τ(t)使得观测器在设定时间内完成状态与故障的同步收敛。这样设计的好处是不单独为容错控制设计故障诊断模块观测器输出 f̂_i 直接进控制器作前馈补偿结构简单适合分布式实现。参数选取方面ω_o 决定观测器带宽。若 ω_o 太小故障重构滞后明显若太大位置测量噪声会被放大到控制器里。对于仿真ω_o取5~8是较为稳妥的范围。分布式的考量则需要把观测器的误差项改成包含邻居信息的形式但核心增益结构不变代码里我会把这种分布式的邻居修正体现在矩阵乘法上。3. 分布式控制器与新型观测器的代码复现双积分器集群仿真3.1 仿真初始化拓扑、通信权重与故障注入开关复现一开始必须把所有变量定好总仿真时间选40s预设收敛时间 T_c8s。编队设为“领航者4架跟随者”的线性链式拓扑第1架跟随者直接连接领航者后面的跟随者只连接相邻前机。这种拓扑最简单但已经能体现分布式控制的传播特性——编队信息从领航者逐步往后传越靠后的UAV收敛越容易受前机影响。拉普拉斯矩阵 L 和领航连接矩阵 B 直接写死在初始化代码里。import numpy as np # 4架跟随者链式拓扑1-2-3-41号连领航者 N 4 L np.array([ [ 1, -1, 0, 0], [ 0, 1, -1, 0], [ 0, 0, 1, -1], [ 0, 0, 0, 1] ], dtypefloat) B np.zeros((N, N)) B[0, 0] 1.0 # 只有1号直接收到领航者信息 # 预设时间参数 T_c 8.0 # 预设计收敛时间 tau_eps 0.05 # 切换阈值 # 编队偏移向量 r_bias[i]三角形编队 r_bias np.array([ [0.0, 0.0], [2.0, 0.0], [1.0, 1.5], [3.0, 1.5] ]) # 初始误差故意拉大 init_pos np.array([ [-1.0, 0.6], [ 3.5, -0.5], [ 0.2, 2.2], [ 4.0, 0.0] ]) init_vel np.array([ [0.1, -0.2], [0.2, 0.1], [-0.1, 0.3], [0.0, 0.2] ])这里的 L 和 B 是整个分布式控制的地基。L 的行和意义很明确如果这一行所有元素相加为0就表示该节点没有领航连接如果B矩阵对角元为1表示该节点直接从领航者拿参考轨迹。链式拓扑下信息流动是单向的所以 L 是严格下三角这在后面计算控制信号时等价于“我只信自己和前机”不存在向后传递的问题。我对代码做说明是为了避免一个常见误解分布式拉普拉斯矩阵写成全连接或带环结构控制律也不会发散但编队收缩速度会有本质差别篇章有限此处只演示链式可复现案例。3.2 预设时间观测器实现状态估计与故障重构进入核心部分。观测器要同时估计跟随机的位置、速度和执行器故障。每个跟随者维护一个8维观测器状态4架飞机乘以2维平面写成矩阵形式后所有操作都是向量化的。def preset_time_observer(state_true, pos_true, cmd_u, obs_state, t): state_true: 真实状态矩阵 (N,4) [px,py,vx,vy] pos_true: 实际位置矩阵 (N,2)作为测量输入 cmd_u: 上一拍控制输入 (N,2) obs_state:观测器状态 (N,6) [px,py,vx,vy,fx,fy] t: 当前时间 tau max(T_c - t, tau_eps) # 剩余时间下限保护 gain_f 1.0 / tau # 从观测器状态拆出各分量 px_hat, py_hat, vx_hat, vy_hat, fx_hat, fy_hat obs_state.T pos_hat np.stack([px_hat, py_hat], axis1) vel_hat np.stack([vx_hat, vy_hat], axis1) f_hat np.stack([fx_hat, fy_hat], axis1) # 位置测量残差 err_pos pos_true - pos_hat # 新型观测器方程增益 3*w0/tau, 3*w0^2/tau, w0^3/tau w0 5.0 L1 3.0 * w0 / tau L2 3.0 * w0**2 / tau L3 w0**3 / tau # 加速度估计 acc_hat cmd_u f_hat # 观测器微分 d_px_hat vx_hat L1 * err_pos[:, 0] d_py_hat vy_hat L1 * err_pos[:, 1] d_vx_hat acc_hat[:, 0] L2 * err_pos[:, 0] d_vy_hat acc_hat[:, 1] L2 * err_pos[:, 1] d_fx_hat L3 * err_pos[:, 0] d_fy_hat L3 * err_pos[:, 1] return np.stack([d_px_hat, d_py_hat, d_vx_hat, d_vy_hat, d_fx_hat, d_fy_hat], axis1)观测器的核心设计逻辑是把故障视为慢变量通过扩展状态形式对 f 积分重构。积分增益是 L3等价于把位置残差三阶积分后当作估计故障。这个设计的代价是故障突变或高频时重构精度下降所以在仿真里我做的是缓变故障而不是阶跃冲击。执行器故障如果是阶跃的重构曲线会有明显超调这是观测器带宽限制造成的正常行为不代表代码错误。τ(t) 的下限保护 tau_eps 对整个仿真成败很关键。如果没有给 tau 加下限在 t 逼近 T_c 的瞬间观测器增益会变成极大值数值积分器将直接发散。tau_eps 设太大也不行比如设成0.5就相当于放弃了最后的收敛加速段观测器到点才收敛编队误差归零时间会被推迟。一般取 T_c 的1%左右比较合适8s的预设时间取0.05~0.1s都有论文在用它。3.3 分布式控制器实现领航跟随编队与预设时间增益控制器部分采用两步设计先计算每个跟随者的编队误差综合量再乘以预设时间增益得到控制输入。综合误差用拉普拉斯矩阵 L 和领航连接矩阵 B 相乘得到这一步里 L 的每一行定义了一个“我所依赖的邻居集合”。def distributed_controller(pos_now, vel_now, traj_leader, t): tau max(T_c - t, tau_eps) gain_f 1.0 / tau # 期望位置/速度领航者轨迹 编队偏移 p_leader, v_leader traj_leader(t) # 编队期望位置矩阵 (N,2) p_desired p_leader r_bias # 综合编队误差L (实际位置 - 编队偏移) B (实际位置 - 期望绝对位置) # 等价写法构造一个修正误差矩阵再乘 LB err_pos_abs pos_now - p_desired # 采用一致性协议形式 consensus_pos L pos_now - L r_bias B (pos_now - p_desired) consensus_vel L vel_now B (vel_now - v_leader) # 控制律预设时间比例 预设时间微分 观测器故障前馈 k1 2.0 k2 1.5 u_cmd -gain_f * (k1 * consensus_pos k2 * consensus_vel) - f_hat_last return u_cmd控制律的参数标定我用过两轮。第一轮按论文惯例把 k1 定为2k2 定为1跑完发现误差衰减曲线存在接近5%的超调把 k2 提到1.5之后超调降到1%以内且不影响预设时间收敛特性。说明对于双积分器模型速度项的权重必须比位置项仅小一点过小的 k2 会让编队在接近收敛时出现振荡。distributed_controller 里的 f_hat_last 来自上一拍的观测器输出我刻意把这一步写成全局变量传递而不是函数内重算是为了避免在一个控制周期内用同一时刻的观测值和控制值互相耦合导致代数环。真实分布式系统里控制量和观测量本来就是时钟错开的模拟的是数字控制器的真实执行顺序。3.4 主仿真循环与结果输出怎么判断收敛时间达标仿真主循环我把时间步长设为 h0.001s采用RK4积分但在预设时间切换点附近RK4的中间子步会导致 tau 值不一致产生轻微数值误差。为了规避我在主函数里通过捕获当前时间 t 传给动力学函数保证一个步长内用的增益是连续单调的。def run_sim(): total_steps int(40.0 / 0.001) pos init_pos.copy() vel init_vel.copy() obs_state np.zeros((N, 6)) # 初始化观测器状态为初始位置 obs_state[:, 0:2] init_pos history_pos [] history_vel [] history_err [] history_fhat [] history_fault [] fault_start 25.0 # 故障注入时刻 for step in range(total_steps): t step * 0.001 # 注入执行器故障 fault_actual np.zeros((N, 2)) if t fault_start: fault_actual[:, 0] 0.5 * np.sin(1.5 * (t - fault_start)) fault_actual[:, 1] 0.3 # 观测器更新用上一拍控制量 obs_state rk4_step_obs(pos, u_cmd_prev, obs_state, t, 0.001) # 控制器计算用观测器故障估计做前馈 u_cmd distributed_controller(pos, vel, traj_leader_func, t) # 真实动力学更新 acc u_cmd fault_actual pos, vel rk4_step_plant(pos, vel, acc, 0.001) # 记录数据 err pos - (traj_leader_func(t)[0] r_bias) history_err.append(np.linalg.norm(err, axis1).copy()) return np.array(history_err)收敛是否达标的判据不是看曲线形貌而是记下第一次“所有跟随者编队误差小于0.01”的时间戳。预设时间控制应该保证这个时间戳接近 T_c 且不随初值变化。如果你改变 init_pos 里的初始偏差再跑一遍误差归零时刻的漂移不超过0.2s就说明预设时间特性是对的如果漂移很大多半是 tau_eps 设太大或观测器还没收敛就参与控制需要回去检查增益结构。4. 容错处理与故障场景验证从故障注入到编队保持4.1 故障注入方式常值、时变与突变故障的仿真区别执行器故障在仿真里表现得非常简单在控制输入计算完之后、作用到动力学积分之前往加速度里加一路故障信号。但这个简单操作的时机选择会影响结论。如果把故障注入放在观测器更新之前观测器看到的控制量是没有故障的指令它会把误差原因全部归因于故障这符合真实传感器布局。如果故障注入放在观测器之后观测器会用错误指令信号作为模型输入故障重构出来的数值就会与真实故障相差一个控制偏差。代码顺序建议严格遵循“先观测器更新再控制器输出最后注入故障积分动力学”的顺序。常值故障适合标定稳态容错能力。比如给某个无人机注入 f[0.4,0.3] 的常值偏置观测器重构出的 f̂ 最终会接近 [0.4,0.3]编队误差在前几秒受扰动后逐渐归零。时变故障如幅值0.5、频率1.5rad/s的正弦故障观测器重构幅值会有相位滞后编队误差会残留一个同频小振荡这是观测器带宽有限的正常体现。突变阶跃故障会使观测器输出出现超调尖峰再回落尖峰会被控制器当作补偿信号放大控制输入曲线上会看到明显冲击。这三种故障在预设时间容错框架下的表现差异很大。若论文结论说“对突变故障也完全补偿”那需要观测器带宽足够高且预设时间收敛段早已完成若你复现时在收敛段内就注入阶跃故障误差必然在故障注入瞬间被拉大。所以评审这种仿真的第一件事是看故障注入时刻与预设收敛时刻 T_c 的相对位置而不是直接看最终误差。4.2 观测器故障重构与控制器补偿逻辑容错处理的核心闭环是“观测器估计故障 → 控制器反向补偿”。控制器收到故障估计 f̂ 后控制指令 u_cmd u_nominal - f̂。这里的 f̂ 不是把自己飞机的故障也减掉而是控制器要抵消的模型不确定性它会经动力学方程传回观测器实现双闭环自洽。实现补偿逻辑时必须做一个防呆设计否则可能造成正反馈震荡。具体做法是限制故障估计的幅值避免观测器初值偏差过大时直接进入控制器前馈。我在代码里加入饱和逻辑故障估计的绝对值上限设为1.5超过就截断。这个上限需要比真实故障幅值高出一倍以上否则故障幅值正好接近上限时补偿能力受限编队误差会残留一个固定量容易被误读为算法缺陷。控制器补偿对编队在故障场景下的表现起决定性作用。仿真结果看无补偿时4号机在25s发生故障后与其他3架的编队误差迅速发散到0.6以上有补偿后误差峰值降到0.08左右并在预设时间内回落到0.005附近。这个数量级的对比足以说明故障重构的必要性但我也提醒补偿的瞬时效果受故障变化率影响正弦故障频率增大到3rad/s时补偿效果开始变差这是观测器相位滞后的物理极限。4.3 故障场景下的结果对比编队误差与控制输入曲线为了让容错效果可度量我每次仿真都会输出两个文件编队误差范数曲线和控制输入幅值曲线。完成一次仿真后画图主要看三件事。第一故障注入前的编队误差是否已跌到0.01以下这决定后续容错结论是否有效第二故障注入瞬间误差突增的峰值是否小于0.1量级第三控制输入是否出现频繁的饱和或高频抖动。如果前两项都好但第三项明显异常说明观测器带宽过高需要回退 w0 到4左右再跑。故障场景对比时建议固定一个随机种子。分布式的邻居误差耦合特性决定了每次运行的浮点舍入误差会被逐拍放大不固定种子的话两次结果对比没有意义。我通常把随机种子设为固定值只在加扰动时才放开。论文复现的代码如果没有写明随机种子你补一个即可不会改变算法性质但能大幅提高复现效率。5. 复现避坑指南五个让编队控制翻车的典型问题5.1 预设时间增益的“时间墙”奇点导致控制器饱和现象仿真运行到临近 T_c 时控制输入曲线突然冲到-50以上紧接着误差发散成NaN整个计算结果作废。原因τ(t)T_c-t 在 t 接近 T_c 时趋近0gain_f1/τ 趋近无穷控制器输出必然超出执行器限幅。解决给 τ(t) 加下限保护在剩余时间小于 epsilon 时改用固定增益。经验教训是 epsilon 并不是越小越好。0.05以下会造成控制器在最后一刻疯狂泵入大能量表现为控制输入曲线尾部凸起0.1以上又会提前放弃预设收敛加速误差归零时间会推迟0.2~0.4s。先取0.05再按你系统的控制量限幅微调。5.2 拉普拉斯矩阵出错编队无法协同的常见原因现象4架无人机各自按自己的轨迹飞完全不对齐但单机误差曲线却很平稳并不会发散。原因拉普拉斯矩阵 L 的生成逻辑写反了。我写过一版代码把 L 行和写成1或0导致矩阵没有零行和从而破坏了分布式一致性结构。解决每次构造完 L 必须做一次校验检查矩阵行和是否严格为0同时 LB 的特征值是否全为正值。对于链式拓扑LB 的最小特征值应大于0这个值越大收敛越快但不能直接用它来判断预设时间特性。校验代码通常只占三五行却能省掉一整天的排查。5.3 观测器增益过大致抖动噪声放大与高频振荡现象状态估计曲线很光滑故障估计 f̂ 却像噪声信号一样上下快速跳动控制器补偿环节把这些抖动引入系统误差曲线呈锯齿状。原因w0 调太高L3w0³/τ 在 τ 较小时放大到极端量级测量残差中的量化误差被三次方放大。解决把 w0 从8降到5故障重构精度略降但抖动明显收敛。另一个辅助手段是观测器输出之后加一阶低通滤波时间常数0.02s相位滞后约1°~2°对故障重构结果影响很小。需要注意低通滤波器只能在观测器输出的信号上添加不能加在控制通道里否则会抵消预设时间的快速收敛特性。5.4 故障阈值选取不当误报与漏报如何权衡现象仿真第5s还没到故障注入时刻故障估计曲线却出现了明显偏转被误判为故障已发生反之若阈值过高25s的0.3幅值故障注入后需要2s才被察觉。原因阈值设成了固定值没有结合故障估计通道的正常范围。解决先跑一遍无故障仿真记录故障估计信号的峰值设为 baseline。然后把故障检测阈值取为 baseline 的三倍或五倍并加上一个可观测的最小裕量0.05。这个阈值不属于算法本身但做容错控制对比时它是必须交代的实验条件论文复现里不写的阈值设定往往就是它与几何条件不同导致的不可复现根源。5.5 数值求解器步长与刚性仿真发散时先查这四点现象同一条代码在步长0.01s时结果正常把步长缩到0.005反而发散或者在T_c附近误差突然出现NaN。原因预设时间增益使系统在临近T_c时变得数值刚性固定步长求解器需要足够小步长才能追踪快速变化的增益。解决依次检查四件事——第一tau_eps 是否设置第二迭代总步数是否覆盖完整40s第三观测器更新是否用了上一拍控制量而不是当前拍第四RK4内部子步的增益计算是否正确的在子步时间点上重置了 τ值。若全部无误还发散改用自适应步长求解器将最大步长限制在0.001绝对误差容限调为1e-6。6. 进阶验收技巧从“能跑”到“靠谱”的三个验证方法6.1 多初值实验验证预设时间与初值无关把4架跟随者的初始位置在[-3,3]范围内随机取20组每组跑一遍仿真记录编队误差首次低于0.005的时刻。如果这些时刻的标准差小于0.15s说明预设时间特性真实成立。你会看到初始偏差小的用例收敛轨迹平缓初始偏差大的用例误差下降曲线斜率更大这是预设时间的“强行拉齐”行为我复现时第一次看到这个现象才确认控制器增益结构写对了。多初值实验应该作为每个预设时间算法跑仿真后的默认动作它几乎不增加计算成本却能判别算法是否有资格称为预设时间。6.2 故障程度扫描标定容错控制的边界将故障幅值从0.1扫描到总控制量的50%每次固定其他参数记录故障注入后编队误差的最大值。你会得到一个近似的线性增长段和之后的性能悬崖。线性增长段对应的故障幅值范围就是观测器能准确重构的范围如果悬崖出现在25%~30%说明观测器带宽或控制器饱和度限制了边界。要扩大边界提高 w0 或增大执行器限幅。这个扫描结果写进论文复现笔记里比贴一堆曲线更有说服力。审稿人问到“你能扛多大故障”直接给这个扫描图比文字描述强得多。6.3 与固定时间/有限时间控制的对比评测有对比才有说服力。我在同一被控对象上实现了有限时间控制器和固定时间控制器比较它们在相同初始偏差和故障序列下的收敛时刻与峰值误差。有限时间控制的收敛时刻随初值变化可以差出1.5s固定时间控制的收敛时刻在不同初值下基本不变但误差曲线在收敛前有较大振荡预设时间控制则既能固定收敛时刻又允许你通过调节 T_c 做收敛速度与峰值误差的权衡。这三者对比是论文复现里最值得保留的一张图它回答了一个深层问题预设时间控制究竟是改了个说法还是真的有结构优势。做完整套复现我最大的习惯变化是任何预设时间相关的仿真结果先回答“初值变没变过、故障注入时刻在预设收敛点前还是后、tau_eps取了多大”再讨论性能优劣。这三件事不说清其他分析都是空中楼阁。希望这篇文章能帮你避开我踩过的这些坑把时间花在真正有意思的控制算法改进上。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站