尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

MRAC模型参考自适应控制详解:MATLAB仿真与TM4C123移植实践

MRAC模型参考自适应控制详解:MATLAB仿真与TM4C123移植实践 简介这套MRAC算法控制MATLAB代码包专为自动化、计算机、电子信息工程及数学等专业学生打造可广泛应用于课程设计、期末大作业或本科毕业设计兼容MATLAB 2014/2019a/2021a三个版本。压缩包共212个文件大小仅3.93MB核心为60个.m脚本另有4个Simulink模型、5个图形文件、若干C代码及说明文档工程结构清晰方便按模块查阅。目前已有107人浏览学习。代码采用参数化编程参数集中于文件头部修改便捷注释明细、思路清晰并附赠可直接运行的案例数据。借助这些材料读者可深入理解MRAC算法的参考模型选取、自适应律推导与参数收敛过程还能快速修改被控对象或控制器参数进行二次扩展有效缩短算法验证与仿真的时间。1. MRAC 算法控制代码为什么值得手动推一遍跑 MRAC 的次数多了会得到一个反直觉的结论模型参数越准MRAC 的优势越不明显模型参数偏差越大自适应律才真正开始起作用。MRAC模型参考自适应控制不是 PID 的替代品它先定义一个可跟踪的参考模型再让实际被控对象去“贴近”参考模型控制增益按 Lyapunov 稳定性条件在线更新。这套方法适合被控对象存在恒值或慢变不确定性的场合比如电机负载突变、气动参数漂移、机械臂末端负载变化。这份资源的主体是 MATLAB 仿真代码同时附带了 TI Tiva TM4C123GH6PM 的 CCS 工程骨架正好覆盖“先用 MATLAB 验证算法再往 MCU 移植”的完整路径。适合课程设计、毕业设计也适合已经在写固定增益控制器、准备给系统加自适应能力的工程师。2. MRAC 参数自适应律推导Lyapunov 函数与一阶对象落点直接说结论MRAC 控制律可以写成u kx * x kr * r的形式难点不是控制律本身而是kx、kr怎么在线更新。网上大部分推导都从一阶对象展开这里也沿用这个路径因为后面的 MATLAB 和 C 代码都建立在这组公式上。2.1 直接 MRAC 与间接 MRAC 怎么选直接 MRAC 不建立对象内部参数的显式估计直接调整控制器增益结构简单控制周期和自适应周期可以用同一个任务驱动。间接 MRAC 会先在线辨识对象参数再把辨识值送到控制器里结构上多一个辨识回路收敛分析和稳定性分析都更繁琐。zip 里的FeedbackController.asv从命名看是直接 MRAC 的反馈控制器原型.asv是 MATLAB 自动保存文件不是正式的.m源文件打开之前最好先重命名避免误改。实际工程里直接 MRAC 更好落地因为控制器结构不随对象模型阶次变化太大参数辨识部分被隐式地塞进了自适应律。下面全部围绕直接 MRAC 写。2.2 一阶对象的 MRAC 完整推导假设被控对象是一阶线性定常系统参数a、b未知但符号已知取b 0dx/dt a * x b * u期望参考模型是稳定的dxm/dt am * xm bm * r其中 am 0控制器选为u kx * x kr * r定义跟踪误差e x - xm如果存在理想控制器增益kx*、kr*满足匹配条件a b * kx* am b * kr* bm那么误差动力学为de/dt am * e b * [(kx - kx*) * x (kr - kr*) * r]现在选 Lyapunov 函数V e^2 b / γx * (kx - kx*)^2 b / γr * (kr - kr*)^2因为b 0只要γx 0、γr 0V就是正定函数。对时间求导后把误差动力学代进去dV/dt 2 * am * e^2 2 * b * (kx - kx*) * (e * x dkx/dt / γx) 2 * b * (kr - kr*) * (e * r dkr/dt / γr)想让交叉项抵消自适应律必须取dkx/dt -γx * e * x dkr/dt -γr * e * r代入后得到dV/dt 2 * am * e^2 ≤ 0因为am 0所以能量函数不增。这里要提醒一句dV/dt ≤ 0只能说明误差有界不能直接说明误差收敛到零通常还要用 Barbalat 引理从误差函数的连续性推出e → 0。这也是 MRAC 和经典极点配置的本质区别MRAC 保证的是渐近收敛不是指数收敛。2.3 用 MATLAB 符号工具验证推导过程如果你要把上面的推导落到代码里建议先用 MATLAB 的符号计算快速验证一遍避免系数写错。这里给出一个可直接运行的符号脚本% mrac_symbolic_check.m syms a b am bm kx kr kxs krs gamx gamr e x r % 定义参数误差 deltax kx - kxs; deltar kr - krs; % 误差动力学 de am*e b*(deltax*x deltar*r); % 自适应律 dkx -gamx*e*x; dkr -gamr*e*r; % Lyapunov 函数 V e^2 (b/gamx)*deltax^2 (b/gamr)*deltar^2; % 对时间求导 dV 2*e*de 2*(b/gamx)*deltax*dkx 2*(b/gamr)*deltar*dkr; % 化简结果R2014/R2019a 用 simple 或 simplify 均可 simplify(dV)代码里deltax、deltar是控制器增益与理想增益的差gamx、gamr是自适应增益。simplify(dV)化简后只应该看到2*am*e^2如果看到多余项说明要么de写错要么dkx、dkr的符号反了。日常调 MRAC 时符号错误是最容易出问题的点尤其是从一阶推广到二阶系统时P B项会带入额外的符号信息不能照抄。2.4 从一阶到状态空间的参数映射实际对象很少真是一阶但很多状态反馈 MRAC 的最后落脚都是通过 Lyapunov 方程计算P矩阵自适应律里会把e^T * P * B当作广义误差乘子。参考模型通常写成dxm/dt Am * xm Bm * rAm必须是 Hurwitz 矩阵Bm的选择要满足参考模型的直流增益要求。用 MATLAB 求P矩阵的标准方法% 参考模型系数 wn 2.0; zeta 0.7; Am [0 1; -wn^2 -2*zeta*wn]; Bm [0; wn^2]; % 解 Lyapunov 方程 Q eye(2); P lyap(Am, Q);lyap(Am, Q)求解的是Am*P P*Am -Q注意这里用的是Am不是Am。求解P矩阵之后自适应律里所有e^T * P * B都需要在每次控制周期实时计算这会带来不小的乘法量但 TM4C123 这类 Cortex-M4F 运行单精度浮点足够。3. Matlab 代码里把 MRAC 跑起来M 脚本、激励信号与调参理论推导只是第一步真正能复现的还是 M 代码。这一章给一个可以直接运行的一阶 MRAC 脚本并说明参数怎么改、曲线怎么看。3.1 完整的一阶 MRAC M 脚本下面的脚本使用显式欧拉积分采样周期Ts足够小时精度满足工程需求这段代码针对的是dx/dt a*x b*u的对象% mrac_first_order.m % 用于验证源码包内 MRAC 算法主逻辑 clear; clc; % 被控对象参数实际调试时改这里 a 1.5; b 2.0; % 参考模型参数一阶惯性直流增益 1 am -1.2; bm 1.2; % 自适应增益 gamma_x 3.0; gamma_r 1.0; % 仿真时间与采样周期 Ts 0.001; T 6.0; N round(T / Ts); t (0:N-1) * Ts; % 激励信号前半段指令为 0后半段阶跃 r zeros(N, 1); r(N/21:end) 1.0; % 状态与增益序列 x zeros(N, 1); xm zeros(N, 1); kx zeros(N, 1); kr zeros(N, 1); u zeros(N, 1); for k 1:N-1 e x(k) - xm(k); u(k) kx(k) * x(k) kr(k) * r(k); % 对象模型实际使用时用传感器反馈替换 x(k1) x(k) (a * x(k) b * u(k)) * Ts; % 参考模型前推进 xm(k1) xm(k) (am * xm(k) bm * r(k)) * Ts; % 自适应律注意符号与 2.2 节一致 kx(k1) kx(k) - gamma_x * e * x(k) * Ts; kr(k1) kr(k) - gamma_r * e * r(k) * Ts; end % 绘图上图为跟踪下图为增益 figure subplot(2,1,1) plot(t, x, t, xm, --) legend(对象状态 x, 参考模型 xm) ylabel(x) subplot(2,1,2) plot(t, kx, t, kr) legend(kx, kr) xlabel(t/s)这里把自适应律放在对象更新之后实际上是拿上一拍的误差在更新增益工程上这样做没问题。重点看两个地方gamma_x和gamma_r决定参数调整的步长kx、kr初值设 0会让前 0.2 秒内u偏小系统响应会比参考模型慢半拍。3.2 不同激励信号下的自适应收敛MRAC 的参数收敛依赖参考输入的充分激励。r只给一次阶跃时参数在稳态附近会松弛但kr往往不容易收敛到理论值。想要验证参数辨识能力可以把指令改成方波或正弦% 方波指令 r 1.0 * (mod(t, 2) 1); % 带偏置的正弦指令 r 0.5 0.5 * sin(2 * pi * 0.5 * t);方波能同时激励多个频率正弦的跟踪误差曲线更直观。改完激励之后kx、kr的收敛轨迹会明显不同这是正常现象。如果最终系统输出能跟上参考模型而自适应律参数在持续小幅度震荡说明gamma偏大需要下调。3.3 调参顺序与关键参数表我习惯的调参顺序是先固定参考模型再调gamma_x和gamma_r最后改激励信号。参数关系如下表参数含义建议范围调大后的表现am参考模型极点小于对象开环极点收敛变快但控制量峰值增大bm参考模型增益bm/am取期望直流增益影响参考模型稳态输出gamma_x反馈增益自适应速率0.1 ~ 10收敛快但高频段噪声被放大gamma_r前馈增益自适应速率0.1 ~ 10影响阶跃指令跟随速度Ts采样周期比系统最短时间常数小 5~10 倍过大时欧拉积分误差明显如果gamma太大kx和kr会在稳态附近高频抖动抖动的频率接近奈奎斯特频率。这一点在纯 MATLAB 仿真里不容易暴露因为仿真测量没有噪声一旦接上真实 ADC 或者电流采样噪声会通过e * x进入自适应律参数漂移非常快。3.4 直接修改包内案例数据的方法如果你是从课程设计资源里拿到的代码案例数据通常以.mat文件存放。把外部数据接到 MRAC 脚本里的常见做法是% 载入案例数据只读取输入输出列 load(case_data.mat); r data(:, 1); % 指令列 y data(:, 2); % 测量输出列载入后把第 3.1 节循环里的x(k1) x(k) (a * x(k) b * u(k)) * Ts换成x(k) y(k);这样就能把仿真对象替换成真实采集到的数据。注意必须先把y和r对齐到同一个时间栅格否则相位差会被 MRAC 当成对象动态导致自适应律乱调。4. 把 MRAC 搬到 TM4C123 C 工程CCS 工程结构与控制循环源码包里包含了main.c、PLL.c、tm4c123gh6pm_startup_ccs.c、.ccsproject等文件这是一套标准 Code Composer Studio 工程。MRAC 算法在 MATLAB 里验证完成后要往 TM4C123 上移植不是把.m文件翻译成.c就能完事的还需要考虑任务调度、浮点类型和限幅。4.1 工程文件结构与各自作用先把文件作用说清楚文件作用移植时注意事项.ccsprojectCCS 工程描述文件双击打开工程不能直接烧录tm4c123gh6pm_startup_ccs.c中断向量表定义改中断优先级时不要动向量表顺序main.c主循环与控制任务入口重点修改对象PLL.c系统时钟配置决定定时器的定时周期FeedbackController.asvMATLAB 临时自动保存文件不是源码需另存为.m.asv文件是 MATLAB 编辑器在崩溃前自动保存的旧版本内容可能比正式.m还新但命名不规范。拿到资源后先把.asv改名再把里面和 2.2 节推导核对一遍。4.2 定时中断里的 MRAC 步进函数TM4C123GH6PM 没有内置硬件浮点加速指令集吗实际上它带 Cortex-M4F 的 FPU单精度 float 性能够用。控制任务建议放在定时器中断里周期固定为 1 kHz 或 2 kHz。参考模型和自适应律必须严格按同一个TS推进否则参考模型状态和对象状态之间会有相位误差。下面是一段可直接放进main.c的 MRAC 步进函数// mrac_control.c #define TS 0.001f #define GX 3.0f #define GR 1.0f #define AM (-1.2f) #define BM 1.2f // 外部提供当前对象状态的采样值比如编码器位置 extern float get_plant_state(void); static float x_meas; static float x_ref; static float kx 0.0f; static float kr 0.0f; static float u_out 0.0f; void MRAC_ControlTask(void) { float e; float ref_cmd; // 每个周期读一次反馈量 x_meas get_plant_state(); ref_cmd get_setpoint(); // 误差计算 e x_meas - x_ref; // 控制量反馈增益 前馈增益 u_out kx * x_meas kr * ref_cmd; // 限幅防止 MCU 的 PWM 模块出现异常占空比 if (u_out 0.95f) { u_out 0.95f; } if (u_out 0.05f) { u_out 0.05f; } // 参考模型前推进 x_ref x_ref (AM * x_ref BM * ref_cmd) * TS; // 自适应律注意和 MATLAB 代码保持一致 kx kx - GX * e * x_meas * TS; kr kr - GR * e * ref_cmd * TS; }这段 C 代码和 MATLAB 脚本的对应关系是x_meas对应x(k)x_ref对应xm(k)u_out对应u(k)。参考模型更新仍然在对象反馈之后执行顺序不能反。get_plant_state()如果是从 ADC 读取要先换算成物理量不能直接用原始寄存器值否则e的量纲和kx * x_meas不一致。4.3 手写 C 代码与 Simulink Embedded Coder 自动生成怎么选Matlab 版本从 2014 到 2021a 都能在 TM4C123 上做验证比较稳的路线有两种。第一种是直接在 CCS 里手写 C代码量小、逻辑透明适合毕业设计和课程设计缺点是参考模型改动后要同步改 C。第二种是在 Simulink 里搭出上面 3.1 节的框图用 Embedded Coder 生成 CCS 工程再和源码包里的.ccsproject合并优点是 MATLAB 和 MCU 行为一致缺点是生成代码体积大版本兼容性麻烦。如果你的目标是快速出结果我建议用 4.2 节的手写方式。MRAC 的核心状态只有kx、kr、x_ref三个远没有到必须上代码生成工具的程度。工程里真正要花时间的是把 ADC 采集、PWM 输出和定时器中断调通。5. 实际调试时最后要加的三个保护MRAC 算法在仿真里跑得通不代表电机台架或机械臂上也能直接跑。最后这一步主要讲验证方法建议把下面的保护加进代码里再测试。5.1 参考模型和真实状态不能有量纲差很多败局发生在量纲上。参考模型用的是角度单位编码器反馈的是 raw 计数值两者做差e会带着巨大的偏置自适应律会把kx、kr推离合理区间。加一个简单的线性校准编码器每圈 2000 线就换算成圈数或角度保证x_ref和x_meas的物理单位一致#define PULSE_PER_REV 2000.0f x_meas encoder_cnt / PULSE_PER_REV;如果没有这一行前 0.5 秒的kx增长量会大到让 PWM 直接饱和。5.2 自适应律加死区当跟踪误差小于量化噪声幅值时e * x不再是真实误差只是噪声。此时继续更新kx、kr只会引入参数漂移。在 MATLAB 和 C 里都要加死区float DEAD_BAND 0.001f; if (fabsf(e) DEAD_BAND) { kx kx - GX * e * x_meas * TS; kr kr - GR * e * ref_cmd * TS; }死区阈值一般取传感器分辨率的 2~3 倍。加了死区之后系统会从“持续自适应”变成“误差足够大时才自适应”稳态抖动明显减小。注意死区会破坏 Lyapunov 推导里的收敛性证明所以死区阈值不能太大否则小误差段会出现跟踪残差。5.3 用阶跃指令做边界测试验证 MRAC 到最后我习惯用三组数据小阶跃、大阶跃、方波连续扰动。小阶跃看稳态误差是否进入死区大阶跃看控制量是否饱和以及kx、kr是否发散方波扰动看自适应律能否在几次切换后快速修正参数。运行结束后画出u_out曲线如果出现高频毛刺优先调小GX和GR而不是换滤波器。把参考模型极点从am -1.2往左推到-3.0跟踪会变快但控制量的超调也会变大这是 MRAC 里最直接的调参手感。本文还有配套的精品资源点击获取
返回列表