恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
四旋翼容灾控制仿真与半物理验证:从故障注入到控制重构
首页
资讯中心
/
四旋翼容灾控制仿真与半物理验证:从故障注入到控制重构
四旋翼容灾控制仿真与半物理验证:从故障注入到控制重构
发布时间:2026/10/14 22:29:43
简介面向北航可靠飞行控制研究组四旋翼容灾控制教学的Simulink源码包也作为相关论文的部分代码适合开展容错控制仿真与半物理仿真实验的研究生和工程师。资源按模型、控制、软件仿真、硬件在环仿真、自编函数库五类目录组织模型目录包含四旋翼模型参数脚本与三维显示接口控制器目录提供控制器参数脚本及QGC地面站参数定义软件仿真与半物理仿真流程清晰便于逐步学习。全部文件共142个压缩包约683KB以xml工程配置、slx模型文件、m脚本为主另有prj工程、dll动态库及mat数据文件。已有941人学习下载。借助该源码可快速搭建四旋翼容灾控制仿真环境理解从模型搭建到Pixhawk硬件在环的完整链路并基于函数库开展二次开发适合课程作业或论文复现。1. 四旋翼容灾控制仿真DegradedControl 源码到底要解决什么问题把 DegradedControl 这个标题拆开读degraded 是性能退化control 是控制合在一起说的是四旋翼在电机堵转、桨叶缺损、传感器卡死这类故障下靠剩下的资源继续把姿态和轨迹控制在可用范围内。四旋翼和固定翼不一样单个动力失效后没有滑翔机会姿态会在几百毫秒内失去平衡所以容灾控制要做的是“带伤稳住”不是“避免故障”。这套源码方向把 Simulink 仿真和半物理验证串起来先用故障注入与重构控制跑通逻辑再把真实飞控板接入回路验证时序和接口。适合刚进入飞控方向、需要一套能改能扩展的仿真底座的学生也适合交付前要向用户证明“极端场景依然可控”的工程师。我做过不少同类测试最大的感受是容灾控制的难点不在控制器本身而在故障注入的真实性、切换过程的平滑性以及半物理接口的可靠性这些恰恰是标题里最容易被忽略的工作量。2. 为什么容灾控制要放在 Simulink 里验证从模型在环到半物理的选型逻辑2.1 容灾控制的核心逻辑状态感知 模式切换 重构分配容灾控制不是一个新的 PID 或 LQR而是一套控制结构。完整的容灾回路至少包含三层第一层是故障检测与诊断持续比较传感器估计值与模型预测值的差值输出一个“健康度”向量第二层是模式切换当健康度低于阈值时把控制器从正常模式切到保稳模式或应急降落模式第三层是控制重构根据剩余执行器的能力重新分配控制量让系统在带伤条件下重新找到稳定工作点。这三层在 Simulink 里比较容易组织和观测。很多人一开始只写了第三层也就是控制分配部分然后发现第一层和第二层不接起来重构就无从谈起。做飞控容灾的常见做法是先做一个“故障报告”信号把它像机内测试一样接到模式选择逻辑里再让模式选择逻辑去改控制器参数最后才轮到控制分配去处理具体输出。信号流向清晰了后面的半物理验证才敢放心接。所谓“退化控制”里的退化也不是指控制器性能平平而是指故障后的控制目标可以主动放宽。比如正常模式下要同时跟踪期望位置和偏航角退到故障模式后先保证不摔角速度和倾角允许超出常规限制但必须稳定。这个目标放宽过程必须用一个明确的模式字和一组阈值写出来不能靠控制器自己“自然反应”凑合。用 Simulink 的好处是模式和阈值都能作为工作区参数改起来不动模型结构这对后续批量跑故障场景非常关键。2.2 从 MIL 到 HIL为什么这类项目一定要做到半物理在写控制律之前建议先选好验证层次。常见做法是把验证分成模型在环、软件在环、处理器在环、硬件在环四档它们的适应场景完全不同。一个故障重构算法在纯数学仿真里可能跑得很漂亮但一旦进了真实飞控板就要面对采样抖动、接口阻塞、运算周期被其他任务抢占这些问题这是纯仿真永远覆盖不到的。四档验证方式的差别用一张表来总结比较直接验证方式控制器运行位置模型运行位置主要验证目标典型成本MIL 模型在环与动力学模型同在 Simulink同一台 PC控制逻辑、参数、故障策略最低适合算法迭代SIL 软件在环相同的 C 代码生成后跑在 PC与 MIL 相同代码生成、数值一致性较低适合查翻译问题PIL 处理器在环目标芯片但无外设仿真机喂信号指令集行为、任务时序中等HIL 硬件在环真实飞控板仿真机实时运行动力学接口、延迟、真实传感器特性最高适合交付验证拿标题里的容灾控制来说MIL 能验证“切换逻辑对不对”HIL 才能验证“切换逻辑在目标板上来不来得及”。故障从发生到被检测出来通常只有几十毫秒窗口如果检测算法在主控板上因为任务抢占而延迟仿真里所有理想假设都会失效。这就是这类源码方向会带“半物理”的原因它不是离线跑完画几张曲线就结束而是要接真实飞控闭环验证容灾表现。我一般会先在 MIL 阶段把故障场景铺开把控制重构参数调到一个相对优的位置再进 HIL。到了 HIL 阶段只改与硬件相关的参数比如采样率、滤波系数、通信超时不碰控制重构的核心矩阵。这样两部分问题分开排错会快很多。如果在 HIL 阶段去调控制分配你会分不清问题到底出在算法还是接口。2.3 先建好四旋翼动力学模型最小刚体模型与参数初始化不管源码自带模型还是需要自己搭四旋翼动力学模型都会采用“刚体 动力单元”的简化结构。刚体部分处理重力、惯性以及电机推力和反扭力矩的合成结果动力单元则把电机转速映射成力和力矩并用一阶惯性近似电机响应。对容灾控制来说执行器健康度必须能直接作用在这个映射关系上这样才能模拟推力系数衰减和完全堵转。% 四旋翼最小参数初始化 % 单位制kg, m, s, rad, N quad.m 1.2; % 整机质量 quad.g 9.8; quad.L 0.25; % 机架力臂长度 quad.I diag([0.012, 0.012, 0.023]); % 惯性张量 quad.kF 1.2e-5; % 推力系数N/(rad/s)^2 quad.kM 2.4e-7; % 反扭力矩系数 quad.tau 0.015; % 电机一阶响应时间常数s这组参数对应的是一架 1.2 kg 左右的小型四旋翼。质量越大、力臂越长、电机转速越高kF 和 kM 的比值都会变化不要直接照抄别人的值仿真里出现高频抖动或响应太钝先回来检查这两个系数。把它们放在一个初始化脚本里Simulink 模型通过quad这个结构体引用参数后续做半物理时只需要改脚本不用改模型。在 Simulink 里建模时四个电机的输入统一处理成 4 维向量会方便很多。故障注入只需要对这个向量做乘法或替换就能模拟推力系数衰减和堵转。姿态方程建议先用欧拉角表达虽然内环控制用四元数更稳但在故障注入和结果解释阶段欧拉角更直观等进入半物理前再改成四元数也不迟改动范围集中在姿态解算模块里。2.4 模型复杂度怎么取舍容灾控制最怕的不是气动力不准搭建模型时最容易犯的错误是一上来就追求高保真。对于四旋翼容灾控制真正要仿真的是“故障发生后系统状态变化的速率”而不是某一个翼面上的涡流细节。因此我会刻意先关掉气动阻力、地面效应、桨叶柔性这些项把它们留到后面统一加到扰动输入里而不是写进动力学方程内部。原因很简单控制重构算法的关键是找到新的稳定工作点。如果把几十个气动参数叠进去参数辨识本身就会占据大量时间反而掩盖了故障切换的核心现象。尤其对新手模型里模块一多步长一乱跑出“玄学”发散时根本不知道是控制器问题还是模型问题。保持一个小而完整的模型出现异常时才能靠人工检查模型结构快速定位。同时模型复杂度直接决定半物理实时性。到 HIL 阶段仿真机必须在一个固定步长内完成解算和 IO 收发每一步多余计算都会以 CPU 占用率形式体现出来。正确做法是结构保留完整参数尽量简化。动力学保留 12 个状态执行器用一阶惯性传感器用“理想值 噪声”模块。故障注入独立出来放在最外层不跟动力学混在一起后面替换真实 IO 时也更容易摘干净。3. 把容灾控制闭环搭起来故障注入、模式切换与控制重构实现3.1 拿到这类源码包先看目录模型、故障、控制、半物理四层分开一个能长期维护的容灾控制 Simulink 项目目录结构通常按层拆开。拿到源码先不急着打开模型先看目录里有没有这五类东西模型层、控制器层、故障注入层、脚本层、半物理接口层。它们的职责应该各管一段不应该混在同一个模型里。目录/命名职责关键内容models四旋翼动力学与传感器模型刚体方程、电机模型、噪声源controllers正常模式与容灾模式控制律PID/LQR、重构分配、限幅faults故障注入与检测故障报告、健康度估计、模式选择scripts初始化与批处理参数初始化、仿真后处理hil半物理接口UDP 编解码、时间戳、实时配置这套结构不是唯一标准但很实用。拿到标题里这种源码包先找 fault 相关的模块因为容灾控制的辨识度就在故障注入和切换逻辑里。模型层和控制层以后再细看半物理接口放到最后看否则很容易被一堆封装子系统淹没。3.2 故障注入模块一个可配置的 MATLAB Function 写法故障注入模块应该做到“不改模型结构就能改故障类型”。常见的做法是在模型里放一个 MATLAB Function 模块输入是仿真时钟t输出是故障标志向量和故障报告值。故障标志进控制分配模块故障报告进模式选择模块。下面是一个可以直接放到子系统里的写法function [fault, fault_report] fault_inject(t, params) % 在设定时刻注入可配置的故障 % params.fault_time : 故障发生时刻s % params.fault_type : 1 传感器冻结 2 执行器部分失效 3 执行器堵转 % params.fault_channel : 目标执行器编号或传感器通道 % params.fault_ratio : 执行器健康度0~11 表示完全健康 % params.fault_duration: 故障持续时长Inf 表示永久故障 fault zeros(1, 4); % 默认全部健康 fault_report 0; % 0 表示无故障 if t params.fault_time t params.fault_time params.fault_duration switch params.fault_type case 1 fault(1) 1; % 高度传感器冻结 fault_report 101; case 2 fault(2) 1 - params.fault_ratio; % 推力损失比例 fault_report 102 params.fault_channel; case 3 fault(3) params.fault_channel; % 堵转电机编号 fault_report 103 params.fault_channel; end end这里fault(1)给传感器层用fault(2)给控制分配层用fault(3)给模式选择逻辑用。三个通道分开的好处是检测与重构各取所需不会因为故障类型增加而改动接口。fault_report的数字规则是一开始就定好的比如 1 开头是传感器类故障2 开头是执行器部分失效3 开头是堵转后两位是通道号。把这个规则写进注释里能省掉很多沟通成本。参数通过基础工作区传进来批处理脚本只需要修改params.fault_time、params.fault_type和params.fault_channel然后重新运行模型。注意设置fault_duration如果是永久故障把它设成Inf并不会在仿真里产生问题如果要在一次仿真里先后注入两个故障建议把fault_inject改成支持时间序列的结构否则代码会变得很难读。3.3 模式切换逻辑写成状态机还是纯逻辑故障检测完成后控制器要切换到对应模式。常见做法有两种用 Stateflow 画状态机或者用普通逻辑块配合 MATLAB Function。我的习惯是模式不超过三个时用纯逻辑超过三个才考虑 Stateflow。原因是容灾控制过程中高频切换是主要风险状态图一旦复杂切换条件的优先级很难一眼看出来。function ctrl_mode mode_select(fault_report, yaw_rate, threshold) % 根据故障报告和当前状态选择控制模式 % 0 正常模式 % 1 姿态保稳模式放弃轨迹跟踪 % 2 应急降落模式下降率受限 % 3 着陆保护模式 if fault_report 100 ctrl_mode 0; elseif fault_report 200 % 单通道部分失效先看偏航速率是否异常 if abs(yaw_rate) threshold ctrl_mode 2; else ctrl_mode 1; end else % 堵转或传感器冻结进入应急降落 ctrl_mode 2; end % 进入着陆保护的条件由外部模块单独判断 end模式切换不能只靠当前时刻的故障报告否则轻微的性能波动会让模式在两个状态之间来回跳。实际做法是给模式增加一个切换锁定时间例如进入应急降落模式后至少锁 1 秒防止震颤。这个锁定逻辑可以放在模式选择函数外部用 Simulink 的 unit delay 加比较器实现也可以直接在这个函数里维护一个持久变量但持久变量在代数环里容易造成时间混合我一般会在模型外用状态更新模块处理。3.4 控制重构实现动态伪逆分配与限幅控制重构是容灾控制里最核心的部分。四旋翼正常时四个电机的分配矩阵是固定的但当某个电机推力下降到只剩一半时固定分配矩阵对应的滚转、俯仰力矩无法全部产生强行用原来的分配矩阵只会让健康的电机饱和。常见做法是使用动态伪逆控制分配根据健康度实时计算分配矩阵伪逆。function u reallocate_ctrl(vcmd, B, health, u_min, u_max) % 根据执行器健康度重构控制分配 % vcmd : 期望虚拟控制量[总推力; 滚转力矩; 俯仰力矩; 偏航力矩] % B : 4xN 控制效率矩阵N 为执行器数量 % health: 1xN 执行器健康度1 表示完全健康0 表示完全失效 % u_min/u_max : 执行器输出限幅 n size(B, 2); W diag(health); % 加权伪逆加小量避免矩阵奇异 B_pinv (B * W * B 1e-6 * eye(4)) \ B * W; u B_pinv * vcmd; % 输出限幅避免重构瞬间控制量过大 u max(min(u, u_max), u_min); end这里的B是 4 行 N 列的效率矩阵N 可以大于 4比如带倾斜电机的构型。health是故障检测层输出的估计值在仿真里可以直接从故障注入模块拿在实际系统里需要由在线估计器提供。由于健康度会突变分配矩阵也会跳变如果不加限幅切换瞬间可能出现很大的油门差异导致姿态突变所以u_min和u_max必须按真实电机出力和执行机构速率限制来设置。这个函数不需要每个控制周期都改成新的文件只需要把health作为信号接入就能在线计算分配矩阵。注意伪逆求解不稳定时优先检查B * W * B的条件数如果某个执行器完全失效且整体控制效率矩阵不可逆伪逆会给出一个看起来无害但实际不可实现的输出这时限幅是最后一道防线。3.5 Simulink 连线阶段的几个硬性检查把故障注入、模式选择、控制重构三个模块接进原模型之后有一组很容易翻车的设置检查。第一求解器必须改成固定步长且步长不超过控制周期的一半如果你用变步长姿态控制器仿真里能跑但到半物理实时执行时一定会卡死。第二检查模型是否存在代数环尤其是重构函数输出到限幅再反馈到分配矩阵的路径上代数环会让固定步长仿真出现时间穿越。第三初始化脚本要在模型打开前执行否则参数结构体在模型初始化阶段是空的仿真一启动就报错。另外一个容易忽略的是初始状态一致性。故障注入在零时刻如果已经有故障标志控制器启动时直接进入容灾模式这不是错误但会让结果分析很难办。常见做法是仿真开始后先保持 0.5 秒无故障让系统稳定再注入故障。这个“稳定时间”也是半物理测试里的标准动作因为真实飞控板上电后也需要一个初始化窗口。4. 半物理验证从 Simulink 模型到飞控硬件之间要补哪些胶水4.1 半物理验证到底验证什么仿真里看不见的问题半物理验证里的“半”字很关键不是所有东西都上真实硬件而是把最有价值的一部分换成真实件。常见分工是动力学模型保留在仿真机里因为真实四旋翼在实验室里飞有风险故障场景也不容易安全复现而飞控算法要放到真实飞控板上跑因为故障切换对指令周期、中断优先级和通信阻塞都极其敏感。半物理主要覆盖四类问题。第一是时序问题控制循环是否能在规定周期内跑完第二是接口问题传感器数据从仿真机到飞控板再到执行器指令回传整个链路的时间延迟是否稳定第三是初始化问题飞控板上电后各个模块的启动顺序是否匹配仿真机的等待逻辑第四是数值问题仿真机里浮点计算与目标芯片的浮点处理差异会不会导致积分漂移。这些在纯仿真里全都看不见所以容灾控制的方向要做到半物理否则故障切换的实效性没法证明。4.2 最小半物理回环仿真机 飞控板 UDP 的接线方案搭建最小半物理回环不需要买昂贵的机架和传感器。仿真机运行四旋翼动力学和故障注入飞控板运行控制器。两者之间通过串口或网口通信。我一般选 UDP因为它的传输时序比串口更稳数据包边界清晰而且可以在同一台电脑上先用回环测试验证通信逻辑再搬到硬件上。接线方案是仿真模型在每个步长结束时把当前仿真 IMU 数据、执行器反馈、故障标志打成数据包发送给飞控板飞控板运行控制律后把电机控制指令通过回传包发给仿真模型。仿真模型收到指令后更新动力学状态如此循环。重点是把发送和接收放到 Simulink 的定时执行子系统里不要用非连续触发否则数据包到达时间会抖动。set_param(quad_hil, SolverType, Fixed-step); set_param(quad_hil, FixedStep, 0.001); set_param(quad_hil, StopTime, 30);这三行配置告诉模型用固定 1 毫秒步长跑 30 秒。1 ms 对于四旋翼容灾控制来说是底线故障切换要求检测至少 50 Hz重构至少 200 Hz1 ms 仿真步长可以覆盖。如果你用的飞控板控制频率只有 250 Hz仿真步长可以放大到 0.002但不要再大了不然电机动态会在两个步长之间丢失。4.3 UDP 定长包与时间同步一份可运行的编码示例半物理接口最容易出现的问题是粘包和解析错位。常见规避手段是使用定长包每包固定 64 或 128 字节发送端在整包开始处加一个固定帧头接收端根据帧头切包。下面是一个把 IMU 状态和控制指令编码成 64 字节定长包的例子function pkt encode_hil(ts, imu, ctrl, fault) % 将仿真数据打包成 64 字节定长 UDP 包 % ts : 仿真时间戳单精度 % imu : 6 维 IMU 数据角速度3 加速度3 % ctrl : 4 电机指令 % fault : 故障标志1 维 data single([ts, imu, ctrl, fault]); pkt uint8(zeros(1, 64)); bytes typecast(data, uint8); pkt(1:length(bytes)) bytes; end这里用typecast把单精度数组转成无符号整数字节流接收端再用相反的typecast恢复数据。数据长度远小于 64 字节多出来的留空这就是定长包的好处无论发送节奏怎么抖动接收端始终按固定长度切包不会累积误差。注意大小端问题MATLAB 默认小端如果飞控端是大端芯片需要在打包前做字节序转换。时间戳必须放在包的首个字段。半物理系统里仿真机和解算板各有一个时钟不能要求两个时钟完全对齐只能统一以仿真机时钟为主。飞控板的时间戳只作为记录通道不要用来触发动作。这样即使两边时间有偏差回放数据时也能通过仿真时间戳对齐事件。4.4 半物理调参表采样率、超时、切换锁定时间参数推荐值说明仿真步长0.001 ~ 0.002 s容灾控制最小可用步长控制周期0.004 s与飞控板主循环频率匹配UDP 包长度64 字节定长包便于解析通信超时2 ~ 5 ms超时后进入安全失效模式模式切换锁定0.5 ~ 1 s防止故障模式来回切换故障检测阈值3~5 倍噪声均方根避免误报切换锁定时间不要设得太长。四旋翼在单电机故障下能在 1 秒内维持姿态已经算很强如果锁 2 秒意味着在锁定期内如果另一个电机也坏了控制器无法进应急降落风险反而增大。常见做法是把锁定时间做成可调参数批处理时专门扫描这个参数对容灾边界的影响。4.5 半物理调试顺序回环、对值、闭环三个台阶半物理调试切忌直接闭环。第一步先做数据回环仿真机发任意正弦波飞控板收到后原样返回确认 UDP 通道的丢包率和延迟第二步做开环对值仿真机发送一组已知 IMU 数据飞控板解算后回传估计姿态对比两者的差值第三步才切换到闭环控制。每一步都要在 Simulink 里加一个唯一的故障标志或数据包序号这样抓到错误数据时能快速定位是接口问题还是计算问题。5. 容灾控制从仿真到半物理的常见问题现象、原因与排查方法5.1 仿真阶段容易翻车的四个问题第一个问题是仿真发散但控制器数学上稳定。现象是零时刻一切正常忽然某个状态飞出去步长缩小也不能解决。常见原因是控制循环和动力学之间存在代数环重构模块的输出被同一个步长内的反馈再次使用导致隐式方程被显式求解。解决方法是打开 Simulink 诊断里的代数环检测把反馈路径用 memory 模块打断或者在重构输出端加一阶滤波。第二个问题是故障注入后系统没有任何反应。现象是设置了电机堵转但姿态曲线完全不变。常见原因是故障标志没有真正接到控制分配模块或者接在了错误的电机通道上。解决方法是先在故障注入模块输出端加一个 display观察fault_report是否在设定时刻变化再往链路下游逐级查看直到找到断点。这个排查逻辑很基础但很多快速排错都靠它。第三个问题是模式切换过于频繁。现象是故障报告在阈值附近波动模式在保稳和应急之间来回跳姿态在切换点附近震荡。原因是阈值没有滞环也没有切换锁定。解决方法是把模式切换逻辑改成带滞环的阈值比较同时加锁定时间。注意故障检测阈值不要设得太低否则半物理上的真实噪声会让你一上电就误报。第四个问题是固定随机种子被忽略。现象是同一组参数跑十次其中有三次不收敛但又找不到规律。原因是噪声模块每次仿真都重新初始化随机序列。解决方法是在初始化脚本里使用rng(42)固定随机种子并在仿真开始前记录初始状态向量。这样每次跑的结果可复现做容灾边界扫描才有意义。5.2 半物理阶段另加的五个坑半物理阶段第一个典型问题是飞控板上电就进容灾模式。现象是仿真机还没注入故障飞控板已经切到应急降落。原因是真实 IMU 数据噪声水平远高于仿真里设置的白噪声故障检测模块把噪声尖峰当成了传感器故障。解决方法是先采集一段真实 IMU 静态数据计算噪声均方根再把故障检测阈值设置为该值的 3 到 5 倍。第二个问题是切换瞬间电机指令直接顶到限幅。现象是故障注入后前几十毫秒内某个电机输出从 30% 跳到 100%随后剧烈抖动。原因是控制重构输出没有做增量限制模式切换时控制器积分器里还存着故障前的累加值。解决方法是切换模式时重置姿态控制器积分器并对重构输出增加一阶惯性环节或速率限制器。第三个问题是半物理模型实时性能不够。现象是固定步长 1 ms 下 CPU 占用率超过 90%断断续续出现超时错误。原因可能是模型中还保留着示波器模块、高精度惯性解算或多余的连续积分器。解决方法是把所有可视化模块去掉改用logsout记录数据动力学解算模块里用离散积分器代替连续积分器把不需要的高频信号降采样。第四个问题是 UDP 丢包导致控制量偶发跳变。现象是飞控板回传的指令偶发损坏仿真机上执行器输出出现毛刺。原因是 UDP 不是可靠传输网络驱动缓存满时会丢包。解决方法是把通信超时检测加进模型超时后不采用当前包而是保持上一刻指令并记录丢包计数。同时把仿真机和飞控板用网线直连避免交换机和公共网络中其他流量干扰。第五个问题是半物理数据时间戳对不上。现象是飞控板记录的控制指令和仿真机记录的姿态曲线在画图时总是错开几十毫秒而且每次仿真偏移量不同。原因是两边各自维护独立时间基准又没有统一同步。解决方法是所有数据以仿真时间戳为主飞控板回传包里的时间戳只做辅助在仿真和飞控两侧同时记录一个硬同步信号用这个信号的上升沿对齐整段数据。5.3 一条通用的排查路线先冻结随机源再做接口回环出现任何“这次跑不过、下次又能跑”的容灾仿真问题不要先怀疑控制器先做两步。第一步把所有随机模块的种子固定检查初始状态是否一致第二步把故障注入时间设成一个极大值让系统跑成纯正常模式确认基线稳定再逐步缩短故障时间看从哪个时间点开始出问题。这样能把“故障本身有问题”和“故障发生后控制器有问题”拆开。对于半物理接口最简单的排查方法是断开控制闭环让飞控板只回传遥测数据仿真机只接收不利用。运行 60 秒统计丢包率、延迟抖动、数据长度是否恒定。如果这一步不稳定后面所有容灾结果都不可信。等通信问题清零再把故障注入和重构逻辑逐一打开每打开一层就重跑一次直到某层引入失败就能锁定问题根源。6. 进阶技巧用批处理脚本扫描故障参数量化容灾边界仿真单次跑通只是开始真正说服别人的是“在哪些故障组合下系统可控在哪些组合下不可控”。把故障时刻、故障通道、故障程度做成参数网格批量跑一遍用脚本记录每个场景的位置误差和姿态最大值就能得到一张容灾边界表比单独看十几张曲线有用得多。% 批处理故障场景脚本 rng(42); % 固定随机种子保证可复现 faultTimeList [1, 3, 5]; faultChannelList [1, 2, 3, 4]; healthList [0.2, 0.5, 0.8]; res []; for ft faultTimeList for fc faultChannelList for h healthList % 写入故障注入参数 params.fault_time ft; params.fault_channel fc; params.fault_ratio h; assignin(base, params, params); % 运行模型 simOut sim(quad_hil, StopTime, 12); % 提取位置误差最大值 posErr simOut.logsout.getElement(posErr).Values.Data; maxErr max(abs(posErr), [], all); % 记录结果 res(end1,:) [ft, fc, h, maxErr]; %#okSAGROW end end end这段脚本把故障时间、故障通道、健康度三个维度穷举了一遍最后输出一个表格。用assignin把参数写进基础工作区模型在初始化时自动读取不需要改模型内部变量。注意每次sim调用之间需要确保模型输出logsout里包含posErr信号否则脚本会在取数据时中断。跑完批处理之后我会把结果按故障通道分组画热力图横轴是健康度纵轴是故障时间颜色是最大位置误差。哪一块颜色深哪一块就是容灾边界上的高危区域。这样汇报时不用贴几十条曲线一张图就能说明问题。现在我的习惯是任何容灾仿真改动后先跑这个批处理脚本半小时出边界再决定要不要继续做半物理验证能省掉很多无效的实物测试时间。希望帮到你。本文还有配套的精品资源点击获取