ARTICLE DETAIL

资讯详情

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

超音速导弹飞行动态仿真中的控制分配:从伪逆到约束QP的工程实现

超音速导弹飞行动态仿真中的控制分配:从伪逆到约束QP的工程实现 前段时间要做一套超音速导弹的飞行动态仿真核心任务是把“自主控制系统分配”这条链路完整跑通上层鲁棒控制律实时给出三轴力矩指令下层要在一堆气动舵面里把这个指令按效率、按约束、按优先级“分配”成每个舵面的实际偏角。这活儿听着像教科书里的一个章节真动手去做才发现从气动数据表怎么组织到分配算法怎么选再到Simulink里怎么避免代数环处处都是坑。这篇文章不打算复述理论就讲讲我这次从建模到闭环验证的完整过程遇到的坑以及最后跑出来的结果。正在做飞行器仿真、控制分配或者被“舵面饱和”“参数摄动”折磨的同学可以直接照着这篇操作。1. 控制分配模块在超音速导弹飞控中的定位与难点1.1 为什么不能简单地把指令除以舵面数量飞控系统通常被拆成两层来设计。制导与控制律层负责决策比如“我需要多少俯仰力矩变化才能保持攻角指令”输出的是一个三元素的力矩指令向量分别对应俯仰、偏航和滚转通道。执行机构层则是多个气动舵面真实地改变导弹受到的力和力矩。控制分配要做的就是连接这两层的那座桥。很多人一开始会想既然有四个舵面一个通道的指令除以四不就行了事实远没这么简单。超音速导弹的舵面布局里每一片舵面偏转时不是只影响一个通道的。差动舵扰动滚转的同时可能带着偏航升降舵在俯仰力矩之外也会有微小的滚转效应这是气动耦合。把这种耦合关系写成数学形式就是效率矩阵B三个力矩通道的控制指令M_cmd等于B乘以舵面偏角向量delta。B的每一列表示某一片舵面偏转一个单位角度时产生的三轴力矩。由于舵面数量通常大于力矩通道数量M_cmd B * delta是一个欠定方程同一个力矩指令可以对应无穷多种舵面偏角组合。这才是“分配”二字的真正含义你要在所有可能的组合里选出一个最合理的出来。什么叫最合理通常就是在舵面偏转角限制、偏转速率限制之内让实际产生的力矩尽量接近指令同时照顾某些舵面的使用优先级。1.2 “自主”在这里到底指什么如果B矩阵是常数控制分配用一张固定增益表就够了。但超音速导弹的飞行包线很宽从跨声速到高超声速区间马赫数一变气动焦点位置就变舵效也跟着剧烈变。同一片舵面在海平面大动压条件下偏一度可能产生很大的力矩到了20公里高空动压掉下来偏同样的角度力矩可能只剩个零头。所以“自主控制系统分配”在我这个项目里的理解是分配模块不能拿一套固定参数用到底它需要根据当前飞行状态自动更新效率矩阵、自动调整各舵面的权重、自动把执行器约束纳入优化。控制系统自主决定每片舵面的贡献度而不是靠工程师在地面调死一组合适的静态增益。这套思路虽然今天听起来不算新鲜真正在Simulink里把所有环节接成闭环的时候还是花了不少力气。这还没算上模型不确定性。气动系数表通常来自风洞或者气动计算本身就有误差跨声速段误差更大舵机动态也存在漂移。因此控制分配不能只对标称模型有效。这也就是为什么“鲁棒控制”这个词必然出现在这类项目里既要让上层控制律对干扰不敏感也要让下层分配在效率矩阵不准时不会把指令分得面目全非。2. 超音速飞行动力学建模气动表、舵效与Simulink模型的衔接2.1 六自由度模型用自建方程还是Aerospace Blockset一开始我图省事想直接用Aerospace Blockset里的六自由度模块。这个模块封装了坐标变换、重力模型、惯性张量处理看起来很完整。但实际用起来发现问题想从模型里抽出中间变量去做控制分配比如当前攻角、侧滑角、动压、效率矩阵模块内部不一定暴露得很顺手修改起来也很别扭。后来我改成了自建六自由度刚体运动学方程在Simulink里按照标准的力方程、力矩方程、四元数运动学方程搭建。多花了一天时间但好处非常明显所有状态量的物理意义、单位、中间计算过程都在眼皮底下后面对接控制分配模块、注入参数摄动都方便得多。如果你也想这么干记得几个关键量的单位处理好。角速度用弧度每秒力矩用牛米转动惯量用千克平方米。任何一组单位不一致反馈回路里跑不出正常结果。2.2 气动系数表的组织与插值细节气动数据是飞行动态仿真的灵魂。我手里的数据表包含升力系数、侧力系数、阻力系数以及俯仰、偏航、滚转三个力矩系数。每个系数都是马赫数、攻角、侧滑角的三维表个别系数还会受舵偏角影响那就得再加一个维度。在Simulink里实现查表最自然的工具是n-D Lookup Table。但要注意一点这几张表的数据范围是有限的。仿真中间如果状态量短暂超出表的边界默认的线性外推可能给出极其离谱的值甚至直接返回NaN。闭环回路里出现一个NaN几毫秒内就会污染整个状态向量模型瞬间发散。我在代码里用的是interpn函数最后一个参数填0.0表示边界外的数据不做线性外推直接取边界值。这样即使某个瞬间攻角跑到表外也不会让整个仿真直接崩溃。这个细节很小但救了我很多次。2.3 舵机动态与速率限制的处理舵机模型我用了二阶环节带宽大概30弧度每秒再加上偏转速率限制比如每秒钟最多转2弧度。Simulink里直接搭一个二阶传递函数输出接一个Rate Limiter再接Saturation限位就行了。这里有个容易被忽略的问题Rate Limiter和Saturation都是非线性环节放在连续时间模型里如果后面接的是离散控制器仿真步长必须足够小否则限制作用会发生在一个步长内跳变产生不真实的抖振。我最后用固定步长1毫秒ode4求解器跑下来效果正常。如果你的仿真里舵机带宽更高或者需要捕捉更快的动力学模态建议把步长压到0.5毫秒再对比一次。3. 分配算法从伪逆到约束优化的递进我的选型过程3.1 从最直接的伪逆开始分配算法我是一步步试过来的。首先最简单也最经典的是伪逆法。既然M_cmd B * delta而B不是方阵那就用伪逆直接求一个最小范数解delta B * (B * B)^(-1) * M_cmd在MATLAB里写起来就是一行function delta allocPseudoInverse(M_cmd, Mach, alpha, beta) B getEffectivenessMatrix(Mach, alpha, beta); delta B * (B * B) \ M_cmd; end伪逆法的优势是计算量极小适合实时性要求高的场景。但它有一个致命短板完全不考虑舵面的偏转范围和速率限制。如果某一片舵面算出来的指令是40度而实际限位只有25度模型里只能硬截断。这一截断实际产生的力矩就跟指令对不上了。在低动压、高空飞行段舵效率低同样大小的力矩指令需要更大的舵偏角伪逆法几乎必然触发限位。我在仿真里很快遇到了这个问题。3.2 加权伪逆给舵面加优先级为了缓解伪逆的盲目性我给效率矩阵加了加权矩阵W让某些舵面优先级更高比如高速段更愿意用滚转效率高的副翼而不是用舵效差的升降舵联动。加权伪逆的公式变成delta W^(-1) * B * (B * W^(-1) * B)^(-1) * M_cmd计算量仍然很小也能在一定程度上避免“所有舵面平均分担”的不合理现象。但问题依然存在它不会主动预测饱和。加权可以降低某片舵面被分到超大指令的概率但无法保证所有舵面都在限位之内。也就是说加权伪逆本质上是“尽可能不超限”而不是“保证不超过限位”。对于需要在整个飞行包线内都稳定工作的超音速导弹这不够可靠。3.3 带约束的QP分配把限位写进优化问题最后我换成了带约束的二次规划QP分配。把分配问题写成标准形式minimize (B * delta - M_cmd) * Q * (B * delta - M_cmd) delta * R * deltasubject to delta_min delta delta_max这个式子的含义很直白第一项让分配后的实际力矩尽量接近指令第二项是正则项避免舵面动作过于激进约束则是每个舵面的偏转角上下限。Q矩阵可以按通道加权比如俯仰通道要求高精度就把对应的Q元素调大。在Simulink里用一个MATLAB Function块实现function delta allocQP(M_cmd, Mach, alpha, beta) B getEffectivenessMatrix(Mach, alpha, beta); n size(B, 2); dmin -30 * pi / 180 * ones(n, 1); dmax 30 * pi / 180 * ones(n, 1); Q diag([2.0, 1.0, 1.0]); R 0.01 * eye(n); H B * Q * B R; f -B * Q * M_cmd; opts optimoptions(quadprog, Display, off); delta quadprog(H, f, [], [], [], [], dmin, dmax, [], opts); end有人会担心quadprog在仿真里跑得太慢。我实测下来舵面数量在四五个的时候一次QP求解大约几十微秒到几百微秒对控制周期5毫秒的回路来说完全够用。当然如果之后要做代码生成部署到飞控计算机直接把quadprog搬过去是不现实的那时候需要换成主动集法或者内点法的嵌入式实现但那是另一个话题了。三种算法放在一起对比特征非常清楚分配算法计算量是否处理饱和是否考虑优先级鲁棒性普通伪逆极低否否差加权伪逆极低否是中带约束QP中是是较强4. 联合仿真架构与接口设计滑模鲁棒控制环加上分配器的工程实现4.1 总体模块划分整个Simulink模型我按信号流分成了六大块飞行状态与指令输入、六自由度运动学与动力学、气动系数与效率矩阵计算、鲁棒控制律、控制分配器、舵机执行机构。传感器环节我先用了理想反馈没有加噪声这样更容易定位控制律和分配器本身的问题。模型的顶层结构大致是这样走通的制导指令生成期望攻角和侧滑角控制律比较当前状态和期望状态输出三轴力矩指令M_cmd分配器读取当前马赫数、攻角、侧滑角查表得到效率矩阵B结合舵面限位做QP优化输出舵偏指令舵机动态按二阶环节响应最后把舵偏角反馈给气动系数计算模块参与下一时刻的力和力矩计算。4.2 鲁棒控制律的选择与实现鲁棒控制这一层很多人首选H∞回路成形或者基于LMI的状态反馈设计。这两者理论漂亮但在工程仿真里调权重函数本身就能耗掉大量时间。我这次为了保证整体方案能快速跑通选择了滑模控制配合边界层饱和函数。滑模控制对匹配不确定性和外部扰动天然不敏感这一点非常适合超音速导弹这类参数跨度大、气动数据有一定置信度误差的对象。设计思路也不复杂对每个通道定义滑模面比如俯仰通道的s (alpha_dot - alpha_dot_ref) lambda * (alpha - alpha_ref)然后让控制力矩包含等效项加切换项。切换项用sat(s / phi)代替严格sign(s)避免抖振。我选的边界层厚度phi约0.05等效项里的气动参数用标称值不确定项交给切换项吸收。这样分配器拿到的力矩指令绝对是“有节制的”指令不会因为控制律本身对执行器极限无动于衷而让分配器疲于应付。4.3 调配器与效率矩阵查表的接口设计这一步是整个Simulink架构里最容易翻车的环节。效率矩阵B依赖当前攻角当前攻角又依赖舵偏角产生的力和力矩舵偏角来自分配器分配器又需要B来算舵偏角。如果不加处理Simulink会告诉你检测到代数环。我的处理办法是在分配器里使用上一控制周期的状态量来计算B和分配结果。具体做法是把历次仿真的状态量包括马赫数、攻角、侧滑角存到Unit Delay模块里分配器只读取Unit Delay输出的值。这个一拍延迟对控制回路的相位裕度有一点影响但我的控制频率是200赫兹周期5毫秒相对于舵机带宽和弹体刚体模态来说相位损失在可接受范围内。仿真结果也验证了这一点没有因为这一拍延迟出现稳定性退化。5. 参数摄动下的鲁棒性验证一组有说服力的仿真对比5.1 不确定性怎么注入才合理仿真模型本身只是真实系统的近似气动系数的误差、重心位置的偏移、舵机增益漂移这些在模型里都应该有体现。我的做法是选取几个最容易出问题的源向它们注入摄动所有气动力矩系数取标称值的±20%范围内随机摄动重心位置沿纵轴偏移±5%参考长度舵机带宽在20%范围内漂移。摄动只加在被控对象侧控制律和分配器用的仍然是标称气动数据。这样才是真实的场景飞控不知道气动参数已经变了它只能依靠自己的鲁棒性硬扛。每个工况我跑了20组蒙特卡洛覆盖参数摄动的不同组合。5.2 两组关键工况的结果我把验证集中在两个极端工况。第一组是高空气行高度20公里马赫数2.0动压很小舵效低分配器最容易饱和第二组是低空大动压高度5公里马赫数3.0舵效高但气动加热和跨声速区效应让气动数据不确定性更大。仿真的典型结果整理如下指标高空低动压工况低空高动压工况伪逆法分配误差峰值8.6%4.2%伪逆法舵面饱和时间占比46%18%QP分配误差峰值1.7%1.1%QP舵面饱和时间占比1%1%参数摄动±20%下伪逆法俯仰通道发散振荡明显参数摄动±20%下QP法跟踪误差4%跟踪误差2%伪逆法在高空低动压工况下的发散过程很典型伺服面饱和后实际力矩小于指令滑模控制为了保证跟踪继续加大力矩指令伪逆解出的舵偏角继续超限并被限幅截断形成一个正反馈最终俯仰通道的攻角跟踪曲线完全失控。而QP分配从一开始就把舵偏限制写进了优化目标它给不出“不存在”的指令所以分配误差小闭环稳定。这组对比让我确信在超音速导弹这种大包线对象上带约束的分配不只是一个“锦上添花”的优化选项而是保证整个飞行包线内闭环鲁棒性的必需品。6. 调试与排查我在这个仿真里踩过最深的几个坑6.1 气动表外推导致的NaN发散前面提过interpn边界外推的问题但值得单独拿出来再说一次。我第一版模型用的是默认线性外推结果仿真跑到大攻角机动的时候状态量超出气动表范围查表直接返回NaN。Simulink里一个NaN顺着信号流扩散出去三个通道的力矩全部变成NaN整个状态向量几分钟内崩溃。排查这个问题的过程也很折磨人因为NaN出现的位置反直觉一开始我一直怀疑是求解器数值发散。最后逐步拆分模块发现是二维查表在边界处出的问题。解决办法就是把边界外推改成0填充或者提前对状态量做饱和限幅从根上避免进入表外区域。6.2 代数环与一拍延迟代数环的问题在第4章讲过这里补充一个细节。我第一次用Memory模块打破代数环但Memory模块在离散系统中会引入额外延迟分布不当会破坏控制时序。后来我统一改成Unit Delay把效率矩阵计算和分配器都挂在同一个离散采样时间上控制时序才变得干净。反馈到调参上代数环存在的时候同一个控制器参数可能跑出完全不同的波形。我建议在搭建模型的初期就决定好所有离散模块的采样时间并且给状态量留一个统一的“当前值/以前值”接口不要让Simulink自动去解代数环。6.3 效率矩阵里的单位不一致这个问题最隐蔽也最能让调参的人怀疑人生。气动系数表里力矩系数通常是无量纲的需要乘以动压、参考面积、参考长度之后才是真力矩。我曾在效率矩阵里漏乘了参考长度导致俯仰通道的效率比真实值整整大了一个数量级。而模型在配平点附近小扰动情况下闭环依然稳定因为控制律设计时正好把参数凑回来了。但一旦做大机动误差暴露出来跟踪曲线出现莫名其妙的漂移。排查到最后办法很笨但很有效把效率矩阵B的每个元素单独做开环验证给某个舵面一个单位阶跃看力矩输出是否和矩阵里的数值一致。这一步做完单位问题无所遁形。6.4 伪逆加饱和的正反馈第5章提到的伪逆法发散第一次遇到时我完全没想到是分配器的锅一直以为是滑模控制律参数没调好。后来把分配结果一路打点到Scope里看到舵偏指令在限位上来回反弹、实际力矩跟指令越差越大才定位到问题。复盘这件事我的经验是选定分配算法之前先把执行机构的约束条件列清楚这是“分配器设计的前置约束”。伪逆法作为快速验证可以但最终方案必须把约束纳入优化。不然的话控制律设计得再好到了执行器层面也会被截断和偏置毁掉。跑完这套仿真之后我个人最大的感受是控制分配不是一个可以在项目最后阶段随手接个模块就能应付的东西。它和飞行动力学建模、执行器动态、鲁棒控制律是高度耦合的。你选择伪逆还是QP不是计算量的比较而是对整个飞行包线内系统行为方式的判断。如果重新做一次我会从第一天就把舵面速率限制纳入分配优化而不是中途再补。另外一个Simulink使用层面的小建议效率矩阵B的计算尽量提前算好并做成独立的查表子系统不要在每个MATLAB Function里重复读取气动表否则模型跑一次大包线仿真光查表就要占掉不少时间。把这些基础功做好后面无论往分配器里加多少种优化策略仿真迭代的速度都能跟上你调试的节奏。
返回列表