ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

无模型自适应控制CFDL-MFAC原理与Matlab/Simulink仿真实践

无模型自适应控制CFDL-MFAC原理与Matlab/Simulink仿真实践 无模型自适应控制MFAC这两年在控制类毕设和课题设计里出现得越来越频繁尤其是基于紧格式动态线性化的CFDL-MFAC几乎成了无模型控制入门的必做题目。这个题目有个很尴尬的地方原理看起来只有两三页PPT真到需要写Matlab代码、搭Simulink仿真的时候新手往往一头雾水——伪偏导数到底是什么重置条件怎么写用MATLAB Function还是S-Function仿真发散又该怎么排查我打算把这条链路完整走一遍从算法推导到Matlab代码到Simulink搭建到参数调节全程用实际操作经验说话。这篇内容适合第一次接触无模型自适应控制的本科生和研究生也适合想做PID或MPC对比实验、需要快速搭起MFAC仿真平台的工程师。1. 项目认知无模型自适应控制到底在研究什么1.1 为什么无模型会成为刚需传统控制设计的起点几乎都是被控对象的数学模型FOC需要知道电机方程MPC需要相对精确的预测模型自适应控制也要知道对象的结构只是参数未知。真实工业现场往往是另一回事——化工反应釜温度、纸机烘缸表面温度、污水处理的pH中和过程装置本身就有大滞后、非线性和参数时变精确建模成本很高建出来也很快失效。PID虽然不需要模型但面对强非线性对象时参数整定很依赖经验而且缺乏稳定性保障。MFAC走的是一条完全不同的路线不建立对象的数学模型只利用被控系统在线的输入输出数据设计一个“数据驱动”的控制器。只要能实时测到输入输出MFAC就能工作对象参数变了、结构漂移了它也能源源不断地从数据中自动修正。更有说服力的是MFAC不是拍脑袋的启发式算法它有完整的稳定性与收敛性理论支撑这正是它区别于一堆“智能PID”或“经验调参”方法的关键。对于很多实际装置来说MFAC意味着可以把控制器部署成本从“花三个月建模型”压缩到“花三天做数据接入”。1.2 紧格式动态线性化把未知系统“局部拉直”假设被控对象是一个离散时间非线性系统输出y(k1)与历史输入输出都有关系。严格分析这样一个未知非线性系统非常困难但MFAC有一个核心洞察在每一个工作时刻k只要输入变化Δu(k)不是零那么在k这个局部邻域内系统输出增量与输入增量之间存在一个等价的关系Δy(k1) φ(k)·Δu(k)这里的φ(k)被称作伪偏导数Pseudo Partial DerivativePPD。它不是一个固定的偏微分而是随着工作点和时间实时变化的一个参数把所有非线性、耦合、时变信息都“挤”进了这一个变量里。在满足广义Lipschitz条件输入变化引起的输出变化有界的前提下这个动态线性化关系在数学上是严格成立的这就是紧格式动态线性化Compact Form Dynamic LinearizationCFDL。“紧格式”指的是它只用当前时刻输入增量这一个变量来刻画局部动态是最紧凑的表达形式。如果还考虑往前若干步的输入增量那是偏格式PFDL如果同时把输入输出历史增量都纳入线性化那是全格式FFDL。CFDL是MFAC家族里的基础款结构最简单也最适合入门很多高阶无模型控制方法都是在它基础上扩展出来的。1.3 CFDL-MFAC的完整数学形态与参数含义整个CFDL-MFAC算法由三部分组成伪偏导数在线估计、控制律和重置机制。对应公式如下PPD在线估计 φ̂(k) φ̂(k-1) η·Δu(k-1)·[Δy(k) - φ̂(k-1)·Δu(k-1)] / (μ Δu(k-1)²)控制律 u(k) u(k-1) ρ·φ̂(k)·[y*(k1) - y(k)] / (λ φ̂(k)²)PPD重置机制当|φ̂(k)| ≤ ε、|Δu(k-1)| ≤ ε或sign(φ̂(k)) ≠ sign(φ̂(0))时令φ̂(k) φ̂(0)。参数所在位置典型作用常见取值范围ηPPD估计步长因子影响PPD收敛速度0~2常见0.5~1μPPD估计权重因子限制PPD突变同时防止分母为零0常见0.01~1ρ控制律步长因子影响控制强度0~1常见0.5~1λ控制律权重因子限制控制量增量防止分母为零0常见0.1~10ε重置机制判定PPD是否失效的阈值1e-5量级φ(0)初值PPD初始估计按对象开环增益粗估与对象尺度有关多在1~3这段公式看起来不复杂但真正实现的时候每一步都有坑。下面我把自己踩过的坑和调试经验拆开讲特别是伪偏导数这个核心参数值得单独开一个章节。2. 伪偏导数整个算法的灵魂2.1 伪偏导数到底是什么——一个“动态增益”的生活化理解伪偏导数有点像你开一辆完全不熟悉的车你并不知道发动机内部的精确特性但你能感知“油门踩深一点车速变化多少”这个“点油门对车速的局部增益”就是PPD。它随当前车速、档位、坡度实时变化不是一个固定值。MFAC每步都在用数据估计这个局部增益然后基于它决定下一步油门怎么调。它与解析偏导数的关键区别在于解析偏导数要求知道被控对象的数学表达式而PPD完全不依赖对象模型它只是输入增量到输出增量之间的一个等价映射关系。PPD的数值甚至可以不等于真实梯度只要它保持有界且符号正确控制律依然可以稳定工作。这个“不精确但可用”的特性恰好是MFAC能在模型未知场景中立足的重要原因。在仿真里我会建议你把PPD曲线打出来看。第一次看到PPD在不同工作点之间来回漂移时你对“动态线性化”的理解会比任何教材都深刻。2.2 PPD在线估计的代价函数推导PPD估计并不是凭空给出的递推式它来自一个带正则项的极小化问题。估计准则函数是J(φ̂(k)) [Δy(k) - φ̂(k)·Δu(k-1)]² μ·[φ̂(k) - φ̂(k-1)]²第一项衡量的是“用当前PPD估计乘以上一步输入变化能否复现刚才实测到的输出变化”这是估计误差项第二项惩罚PPD不要变化太剧烈μ越大PPD估计越平滑。对φ̂(k)求导并令为零∂J/∂φ̂(k) -2·Δu(k-1)·[Δy(k) - φ̂(k)·Δu(k-1)] 2μ·[φ̂(k) - φ̂(k-1)] 0整理之后就是标准估计算法。实际使用中还会在整理结果前面乘上步长因子η目的不是让PPD严格落在极值点而是在PPD的跟踪速度和抗噪声能力之间留出调节余地。如果完全按极小值点取值一旦数据本身有噪声扰动PPD会剧烈跳动。这里面μ的取值特别值得注意μ越小PPD对输入输出变化的响应越灵敏但抗噪声能力越差μ越大PPD曲线越平滑跟踪系统真实增益变化的速度也越慢。建议刚开始不要在这上面花太多时间先用μ0.5这样的中间值跑通再根据PPD曲线调整。2.3 控制律的另一半从代价函数到增量式控制控制律同样不是拍脑袋的公式它来自另一个极小化问题。控制准则函数是J(u(k)) [y*(k1) - y(k) - φ̂(k)·Δu(k)]² λ·Δu(k)²第一项是“如果我用当前PPD乘以输入增量输出能离目标多近”的预测误差第二项是限制控制增量不要过大。对Δu(k)求导并令为零∂J/∂Δu(k) -2·φ̂(k)·[y*(k1) - y(k) - φ̂(k)·Δu(k)] 2λ·Δu(k) 0整理后就是控制律的标准形式。ρ可以理解成对严格极小解的一个松弛因子用于调节控制作用的保守或激进程度。由于MFAC控制律本质上是增量式控制它天然带有积分作用对常值扰动和模型失配天然有鲁棒性这一点在实际仿真中体现得很明显即使对象参数突然漂移控制器也能自行把输出拉回参考值。2.4 重置机制三种触发条件与保命逻辑重置机制是我认为整个MFAC算法中最容易被忽略、但又最“保命”的设计。很多初版代码在仿真时突然发散十有八九就是因为没有写或者写错了重置条件。第一种触发情况是PPD估计值过小。被控对象存在死区或执行器饱和时会出现“输入变了但输出不变”的情况PPD会被不断拖向零。一旦PPD趋近零控制律分母λφ̂(k)²也会趋近零控制量会出现巨大尖峰甚至直接发散。重置为初值相当于告诉控制器“我暂时失去了局部增益估计恢复到初始假设重新来”。第二种触发情况是输入增量过小。Δu(k-1)接近零时PPD更新项的分母虽然还有μ撑着不会除零但此时估计结果已经不可信强行更新只会让PPD漂移索性重置更稳妥。第三种触发情况是PPD符号反了。绝大多数工业对象的控制方向是固定的阀门开大流量变大控制方向不应该突变PPD突然反号说明估计被噪声或异常数据严重带偏此时如果继续按反号增益控制控制器就变成了“往反方向使劲”系统很快就会失控。从工程角度理解重置机制就是给在线估计算法装了一个“安全护栏”这个思想在递推辨识、自适应控制里都有类似设计。仿真过程中看到PPD曲线出现锯齿状跳跃不要慌说明控制器正在用重置自保。3. Matlab代码实现与验证3.1 仿真对象设计与实验场景仿真对象我选了一个非常经典的非线性离散系统y(k1) 2.5·y(k)/(1y(k)²) 1.2·u(k)这个对象有几个特点非线性项在y1附近有峰值说明对象增益会随状态变化输入项是线性的所以PPD的理想值在1.2附近但实际估计会随工作点有一定的漂移波动非常适合观察伪偏导数的在线估计行为。如果你想加大难度可以把1.2·u(k)改成1.2·u(k)³这样u靠近零时系统局部增益接近零重置机制会频繁触发对理解重置条件非常有帮助。参考信号设计成多段阶跃0.5 → 1.0 → 0.4 → 0.8跨越不同幅值区间。这样设计的目的是检验控制器对大范围工作点变化的适应能力而不是只在一个平缓参考点上来回磨。仿真步数500步采样时间0.01秒。3.2 完整Matlab主程序代码以下代码在Matlab上直接保存运行即可%% CFDL-MFAC 主程序 clc; clear; close all; %% 参数设置 % 被控对象: y(k1) 2.5*y(k)/(1y(k)^2) 1.2*u(k) alpha 2.5; beta 1.0; gamma 1.2; % MFAC控制器参数 eta 0.5; % PPD估计步长 mu 0.5; % PPD估计权重 rho 0.5; % 控制律步长 lambda 0.5; % 控制律权重 epsilon 1e-5; % PPD重置阈值 phi0 2; % PPD初值 %% 仿真参数与参考轨迹 T 500; % 仿真步数 dt 0.01; % 采样时间 t (0:T-1)*dt; % 时间向量 y_ref zeros(T,1); y_ref(1:100) 0.5; y_ref(101:200) 1.0; y_ref(201:300) 0.4; y_ref(301:500) 0.8; %% 初始化存储变量 y zeros(T,1); u zeros(T,1); phi_hat ones(T,1)*phi0; %% 主循环 for k 2:T-1 % 步骤1伪偏导数在线估计 if k 2 dy_current y(k) - y(k-1); du_prev u(k-1) - u(k-2); if abs(du_prev) 1e-8 phi_hat(k) phi_hat(k-1) eta*du_prev*(dy_current - phi_hat(k-1)*du_prev)/(mu du_prev^2); % 重置机制三种触发条件 if abs(phi_hat(k)) epsilon || abs(du_prev) epsilon || sign(phi_hat(k)) ~ sign(phi0) phi_hat(k) phi0; end else phi_hat(k) phi_hat(k-1); end else phi_hat(k) phi_hat(k-1); end % 步骤2计算控制量 u(k) u(k-1) rho*phi_hat(k)*(y_ref(k1) - y(k))/(lambda phi_hat(k)^2); % 步骤3被控对象输出递推 y(k1) alpha*y(k)/(1 beta*y(k)^2) gamma*u(k); end %% 绘图 figure(Color,white,Position,[100 100 600 700]); subplot(3,1,1); plot(t, y_ref, k--, LineWidth, 1.5); hold on; plot(t, y, b-, LineWidth, 1.2); ylabel(输出 y(k)); legend(参考轨迹,实际输出,Location,best); title(CFDL-MFAC 输出跟踪效果); grid on; subplot(3,1,2); stairs(t, u, r-, LineWidth, 1.2); ylabel(控制量 u(k)); title(控制输入); grid on; subplot(3,1,3); plot(t, phi_hat, g-, LineWidth, 1.2); ylabel(伪偏导数 \phi(k)); title(PPD 在线估计过程); grid on; xlabel(时间/s);3.3 代码走读与PPD估计行为分析这段代码的主循环逻辑非常重要我建议你按三步去理解第一步在k时刻先更新PPD使用的数据是上一时刻的控制增量u(k-1)-u(k-2)和当前时刻的输出增量y(k)-y(k-1)第二步用更新后的PPD和当前跟踪误差y_ref(k1)-y(k)计算控制量这里用的是未来一步参考值第三步才把被控对象递推一步得到y(k1)。先后顺序一旦搞反整个控制回路的因果性就乱了。我在做这个仿真时第一版代码就犯了时序错误先算控制量再用旧PPD更新结果跟踪曲线总是差一个采样周期相位滞后非常明显。这个细节书本上很少强调但实现层面极其重要。跑完代码后你会看到几个典型的实验现象PPD初值设为2而对象真实增益接近1.2所以前几步PPD会快速下降并稳定在1~1.5区间附近。参考信号阶跃跳变时PPD会发生短暂波动然后恢复这说明估计算法正在重新适应新的工作点。控制量在每一个阶跃处先有一个较大调整之后逐步收敛这是增量式控制器的典型行为。如果把被控对象改成带输入三次方的版本y(k1) 2.5y(k)/(1y(k)²) 1.2u(k)³你会观察到PPD曲线出现很多锯齿状跳动那是重置机制在u靠近零时反复触发的结果。这属于正常现象本质上说明系统在增益为零的区间里很难用线性模型去近似重置机制正在保命。4. Simulink仿真搭建从脚本到模块化4.1 方案选型MATLAB Function还是S-FunctionMatlab脚本仿真的好用之处在于调参快、容易加断点调试但很多课程设计和论文复现要求用Simulink展示模块化架构。在Simulink里实现MFAC控制器主要有两种方案我分别说一下适用场景。第一种是基于MATLAB Function模块控制器代码直接以M语言函数形式写在模块里用persistent变量保存历史状态。优点是简单直观特别适合课程设计和第一次接触MFAC的人几乎不需要学习S-Function的规范模板缺点是函数内部逻辑对不了解算法的人不透明而且如果用连续求解器容易出现代数环问题。第二种是基于Level-2 MATLAB S-Function需要写完整的S函数模板状态用Dwork向量保存在Output和Update回调函数中分别实现控制律计算和状态更新。优点是非常专业适合作为可复用的控制器模块也方便将来做代码生成或硬件在环仿真缺点是模板较复杂新手容易把Output和Update的职责搞混。我的建议是如果目标只是完成课设或复现论文用MATLAB Function就够了如果你想做一套自己的控制算法工具库或者要在论文里强调“控制器模块可复用”那就花半天时间把S-Function框架吃透。4.2 基于MATLAB Function的控制器搭建步骤在Simulink中搭建的完整步骤如下。第一步新建一个Simulink空模型拖入两个MATLAB Function模块分别命名为MFAC_Controller和Plant。再拖入Repeating Sequence Staircase作为参考信号发生器一个Scope作为输出显示。第二步双击MFAC_Controller写入以下代码function u mfac_controller(y_ref, y) % CFDL-MFAC控制器MATLAB Function实现 persistent u_prev u_prev2 phi_hat y_prev phi0 eta mu rho lambda epsilon if isempty(phi_hat) u_prev 0; u_prev2 0; phi_hat 2; y_prev 0; phi0 2; eta 0.5; mu 0.5; rho 0.5; lambda 0.5; epsilon 1e-5; end % 1. PPD在线估计 dy y - y_prev; du_prev u_prev - u_prev2; if abs(du_prev) 1e-8 phi_hat phi_hat eta*du_prev*(dy - phi_hat*du_prev)/(mu du_prev^2); if abs(phi_hat) epsilon || sign(phi_hat) ~ sign(phi0) phi_hat phi0; end end % 2. 控制律 u u_prev rho*phi_hat*(y_ref - y)/(lambda phi_hat^2); % 3. 历史状态更新 u_prev2 u_prev; u_prev u; y_prev y; end第三步双击Plant模块写入被控对象代码function y_next plant(u) persistent y_prev alpha beta gamma if isempty(y_prev) y_prev 0; alpha 2.5; beta 1.0; gamma 1.2; end y_next alpha*y_prev/(1 beta*y_prev^2) gamma*u; y_prev y_next; end第四步连接信号参考信号和Plant输出进控制器控制器输出u进Plant输入Plant输出分别连接到Scope和控制器反馈输入。第五步模型设置里把求解器选为discrete离散固定步长固定步长设为0.01仿真时长设为5秒对应500步。这里特别提醒MATLAB Function模块里的persistent变量不会在仿真暂停后自动清除。如果你改完参数再运行老的状态可能还在结果看起来就像“控制器没更新”。解决办法是在仿真前运行clear all或者在MATLAB Function里加一个外部reset输入这是团队协作时经常被忽略的坑。4.3 基于Level-2 S-Function的进阶实现框架S-Function的好处是可以通过标准接口封装控制器在模型里看起来就是一个普通S函数块便于项目归档和版本管理。Level-2 S-Function的核心结构如下function mfac_sfun(block) setup(block); end function setup(block) % 两个输入y_ref和y block.NumInputPorts 2; block.NumOutputPorts 1; block.SetPreCompInpPortInfoToDynamic; block.SetPreCompOutPortInfoToDynamic; block.InputPort(1).Dimensions 1; block.InputPort(2).Dimensions 1; block.OutputPort(1).Dimensions 1; % 五个Dworku_prev, u_prev2, phi_hat, y_prev, init_flag block.NumDworks 5; for i 1:5 block.Dwork(i).Dimensions 1; block.Dwork(i).DatatypeID 0; block.Dwork(i).Complexity Real; end block.Dwork(1).Name u_prev; block.Dwork(2).Name u_prev2; block.Dwork(3).Name phi_hat; block.Dwork(4).Name y_prev; block.Dwork(5).Name init_flag; block.SampleTimes [0.01 0]; block.RegBlockMethod(Start, Start); block.RegBlockMethod(Outputs, Outputs); block.RegBlockMethod(Update, Update); end function Start(block) % 初始状态赋值 block.Dwork(5).Data 0; end function Outputs(block) if block.Dwork(5).Data 0 block.Dwork(1).Data 0; block.Dwork(2).Data 0; block.Dwork(3).Data 2; block.Dwork(4).Data 0; block.Dwork(5).Data 1; end u_prev block.Dwork(1).Data; u_prev2 block.Dwork(2).Data; phi_hat block.Dwork(3).Data; y_prev block.Dwork(4).Data; y_ref block.InputPort(1).Data; y block.InputPort(2).Data; % 这里执行PPD更新和控制律具体代码同MATLAB Function内部逻辑 % 控制量写入OutputPort(1).Data end function Update(block) % 在Update回调中保存历史状态避免在Output中直接修改数据 end这里最关键的是Dwork向量它相当于S-Function的“持久内存”。PPD的更新要放在Outputs里执行但历史状态的写回必须放在Update里否则会出现同一仿真步内状态被修改的问题。很多初学者把状态的修改写在Outputs里结果仿真结果完全乱套。如果你只做课程设计S-Function这部分可以先跳过但如果想认真搭一套可以反复用于多场景仿真的MFAC模块我推荐花时间搞定它。4.4 仿真配置与代数环避坑指南搭建Simulink模型时最常遇到的错误是代数环。代数环出现在信号路径上存在“同一时刻直通回路”的情况Simulink求解器不得不在每一步迭代求解多个模块之间的静态关系不仅计算慢严重时直接报错或结果异常。MFAC控制器包含输出到对象的直通关系而对象下一时刻输出又依赖于控制量如果求解器配置不当反馈支路很容易形成代数环。解决办法有三个第一把求解器设为离散固定步长第二在反馈支路上加一个Unit Delay或Memory模块人为地把反馈信号延迟一个采样周期这与MFAC的离散控制时序天然吻合第三如果用MATLAB Function在Plant模块内部使用persistent状态而不是直接形成即时代数关系。采样时间的设置也值得注意。控制器和被控对象的采样时间必须统一如果控制器是0.01秒采样被控对象却是连续求解两者之间就会引入额外的零阶保持器延迟影响PPD估计的准确性。我测试过的经验是对所有离散模块统一使用0.01秒的采样周期仿真结果和纯脚本仿真几乎完全一致。5. 参数调节、常见问题与故障排查5.1 参数调节的先后顺序与实验洞察MFAC一共有五个主要参数要调η、μ、ρ、λ和PPD初值φ(0)。很多人一上来就同时改三四个参数结果完全不知道哪个起了作用。我调试这类算法的固定习惯是先用一组中间值把系统跑稳再逐项微调。推荐的初始参数组合是η0.5、μ0.5、ρ0.5、λ0.5、φ(0)2。先用这组默认参数跑一遍确认基本跟踪是成立的。然后看控制量和输出曲线的形态再做针对性调整。如果控制量高频抖动优先增大λ。λ是控制增量的惩罚权重增大会让控制动作变平滑代价是响应变慢。如果输出噪声大优先增大μ。μ会让PPD估计更平滑但PPD跟踪真实增益变化的速度会变慢。如果跟踪太慢可以先减小λ再增大ρ但ρ最好不要超过1超过1容易出现超调和振荡。PPD初值如果完全没概念就用对象开环增益的一个粗略估计值控制器启动后重置机制会帮助修正偏差。我实测过一组对比λ从0.5调到0.05响应确实快了但控制量抖动从可接受变成非常猛烈最后把λ调回0.2并给输出测量加了一阶低通滤波才算稳定。这个案例说明控制量抖动不一定要靠继续压λ解决滤波同样有效而且不牺牲响应速度。5.2 常见故障速查表与排查实录故障现象最可能原因处理办法输出发散、控制量爆表PPD重置条件没写或初值过大检查重置代码把φ(0)调小再试响应太慢、跟踪不上λ偏大或ρ偏小先减小λ再增大ρ控制量高频抖动λ太小或采样间隔太大增大λ同时缩短采样周期稳态误差明显被控对象存在死区或增益过零区间在参考信号前加积分修正或增大ρPPD频繁跳到初值系统工作在增益为零的区域确认对象局部可逆或换输入线性对象Simulink报代数环错误反馈支路存在直通回路反馈支路加Unit Delay或改用离散固定步长求解器排查时我有一个习惯先把PPD曲线和控制量曲线放一起看。如果PPD曲线在某一步突然跳回初值同时控制量剧烈变化多半是重置条件在起作用这时候去看该时刻的Δu是不是接近零就能确认原因。如果PPD曲线一直在缓慢漂移但控制量没异常多半是η和μ的搭配有问题而不是控制律的问题。还有一个值得注意的小陷阱Matlab脚本里如果被控对象带输入三次方项起始阶段u0附近PPD会频繁触发重置控制器会表现出“先抖两下再稳定”的特点。如果你为了写论文需要更平滑的曲线可以先把参考信号起始幅值设大一点让系统快速离开低增益区间。5.3 一个容易被忽略的细节采样周期与延迟MFAC是离散控制算法采样周期对控制性能的影响往往比PID更大。采样太快时相邻两个采样点的输出增量Δy太小数值上PPD估计的信噪比很差很容易拖进重置区采样太慢时控制延迟大动态响应明显变差。对于大多数模拟对象我建议采样周期取在系统主导时间常数的1/20到1/10之间。如果是0.01秒采样500步就是5秒这个时长足够观察多段阶跃的跟踪效果。如果对象本身惯性很大比如化工温度对象时间常数几十秒那采样周期就要相应放大到1秒到5秒否则PPD估计会一直处于“看不清变化”的状态。对带纯延迟的对象MFAC的表现会明显弱于无延迟场景此时可以尝试改用偏格式PFDL或者全格式FFDL它们在结构上能利用更多历史信息来补偿延迟影响。在工程实现层面还有一个容易被忽略的细节控制量u(k)的饱和和变化率限制。MFAC控制律是增量式的但如果执行器有输出范围和变化率限制必须在仿真模型里加入Saturation和Rate Limiter模块。不要觉得这是多余的“美化”因为工业执行器不可能无限快速变化加了限幅后你才真正看到算法在真实约束下的表现。做这个仿真研究时我最大的体会是MFAC的原理和代码写起来都不难但真要把参数调到“既跟得快又不抖”依然要靠系统性的实验和对比。尤其是重置机制很多初版代码里没有它仿真结果会在某个阶跃附近突然失控加上重置后一切就顺了——这让我对理论中那些不起眼的辅助机制有了真实的敬畏。建议你把伪偏导数曲线单独打印出来盯着看它能直观展示控制器内部的判断过程比单纯看输出跟踪曲线有用得多。如果你手头还有其他需要对比的控制算法也可以在这套代码框架里直接替换被控对象MFAC模块不需要改动一行这就是数据驱动方法最舒服的地方。
返回列表