ARTICLE DETAIL

资讯详情

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

Matlab实现ADRC平衡车仿真:从ESO设计到参数整定全解析

Matlab实现ADRC平衡车仿真:从ESO设计到参数整定全解析 简介面向自动化控制与机器人学方向的MATLAB平衡车控制资源聚焦自抗扰控制ADRC算法在两轮自平衡车上的实现涵盖倒立摆建模、状态估计与扰动补偿等关键环节适合深入研究自抗扰控制理论并希望进行嵌入式移植的开发者。包体内含22个文件以11个头文件和9个C源文件为主覆盖ADRC控制器、ESO扩张状态观测器、PID算法以及陀螺仪/编码器底层驱动配套构建脚本与说明文档整体仅35KB目录结构清晰便于快速阅读和二次开发。已有483人学习下载可用作从MATLAB仿真到硬件落地的过渡参考。通过研读代码可理解ADRC对系统不确定性和外部扰动的估计与补偿流程掌握两轮车姿态解算与控制闭环的实际实现思路尤其适合需要将控制理论转化为可运行工程的读者也可作为课程设计或毕业设计的起点。1. 为什么ADRC平衡车比PID更耐调先把问题立住做两轮自平衡小车的人都有过这种经历角度环PID调了一个通宵空载能站稳加上负载立刻开始低频抖动换一块地面摩擦系数一变原来的参数又不行了。PID不是不能调而是它默认系统模型是确定的——一个固定的极点、固定的增益、固定的延迟可平衡车恰好是这一切的反面重心高度会变、电池电压会掉、轮胎磨损会让摩擦非线性变大。你真正需要的是一个不太依赖精确模型、却能把未知扰动实时“看见”并补偿掉的控制方案。ADRCActive Disturbance Rejection Control自抗扰控制正是朝这个方向设计的。韩京清先生把系统的未建模动态、参数摄动和外部干扰统一视为“总扰动”用一个扩张状态观测器实时估计它再在控制量里反向抵消。放到平衡车场景里你的重力力矩、摩擦、地面斜度、电机死区都可以被塞进这个“总扰动”里不需要单独建模。Matlab的价值则体现在两端一是用Simulink快速验证ADRC的三个核心组件二是用脚本做批量扫参和频域分析避免了在实车上反复试错。这篇文章就用Matlab把一个ADRC平衡车的完整仿真链路讲清楚从数学模型到ESO的离散化代码到带宽法整定参数再到和LQR的对比实验。适合正在调平衡车但受够PID的工程师也适合把ADRC当课题方向但还没找到落地样例的学生。2. 从平衡车动力学到ADRC核心结构TD、ESO、NLSEF分别解决什么2.1 平衡车角度环的简化模型为什么不稳定极点是个麻烦两轮平衡车的完整动力学包含车体倾角、左右轮速、车身位移等多个状态量但角度环才是决定“能不能站稳”的核心。把车体近似成倒立摆取倾角θ为输出电机驱动力矩为输入u忽略车轮转动的耦合细节可以得到一个二阶微分方程Jθ̈ m g l·sinθ - u d(t)其中J是车体绕轮轴的转动惯量m是车体质量l是质心到轮轴距离d(t)是所有未建模干扰的总和。在平衡点附近把sinθ近似为θ系统开环传函为 1/(s² - a)a mgl/J。这个系统有一个正实部极点意味着只要倾角有微小偏差车体就会加速倒下去——PID里的比例项就是为了顶住这个正极点微分项负责增加阻尼。问题在于a随负载变化质心l一变a立刻变PID的相位裕度就跟着缩水。2.1.1 摩擦和死区为什么让PID参数很难迁移真实平衡车上还有两个PID模型里几乎不会写的环节。一个是摩擦力库仑摩擦在速度过零时方向跳变等效成高频非线性扰动另一个是电机死区PWM占空比低于某个阈值时电机不转形成纯滞后。这两者叠加后角度环在路上出现持续数秒的低频振荡其实不是PID没调好而是控制器带宽太高把摩擦跳边当成信号在追。ADRC对这类问题的处置方式完全不同它不区分扰动来自摩擦、斜坡地面还是重心漂移统一交给扩张状态观测器去估计再用控制律补偿。下面拆开看ADRC的三个组成部分。2.2 ADRC三件套的数学含义各自的输入输出和在平衡车里的角色ADRC的经典结构是三个组件串联跟踪微分器TD、扩张状态观测器ESO、非线性状态误差反馈控制律NLSEF。它们的职责可以一句话概括TD安排过渡过程ESO估计总扰动NLSEF把误差变成控制量。2.2.1 跟踪微分器TD为什么要“柔软”地跟踪目标平衡车的目标值永远是θ_ref 0看起来似乎不需要处理目标跟踪但TD在平衡车上的作用不是跟目标而是提取角速度信号。角度值来自MPU6050的融合输出角速度在静止时会带有毛刺直接微分会放大噪声。TD对输入信号安排一个过渡过程同时给出微分信号的平滑估计等效于一个非线性低通滤波器加微分器。离散化表达式为v1 v1 h * v2 v2 v2 h * fhan(v1 - θ_ref, v2, r, h0)fhan是韩京清提出的最速控制综合函数r决定跟踪速度h0起滤波作用。对平衡车场景角速度信号噪声大时适当加大h0但会引入相位延迟和后面ESO的带宽要权衡。2.2.2 扩张状态观测器ESO把“总扰动”作为第三个状态ESO是ADRC的核心也是理解整篇文章的关键。把一个二阶被控对象改写成状态方程形式ẍ f(x, ẋ, d, t) b0·u其中f包含内部动态和外部扰动b0是控制增益的估计值。把f扩成第三个状态x3ESO写成e z1 - θ z1 z1 h * (z2 - β1 * e) z2 z2 h * (z3 - β2 * e b0 * u) z3 z3 h * (-β3 * e)z1和z2分别估计倾角和角速度z3估计总扰动f。观测器带宽ωo决定了z3收敛的速度实际调试中β1 3ωo、β2 3ωo²、β3 ωo³是常用的参数化方式。平衡车调ESO时常见错误是只调ωo不调b0——b0如果偏离真实控制增益太多ESO会把一部分控制量误判成扰动控制效果会变得非常“钝”。2.2.3 非线性状态误差反馈NLSEF最后一段控制律NLSEF把TD给出的平滑目标v1、v2和ESO估计的z1、z2做差再用非线性组合生成初始控制量最后减去扰动补偿u0 kp * fal(e1, α1, δ) kd * fal(e2, α2, δ) u (u0 - z3) / b0fal函数在误差小时采用线性段误差大时采用幂函数段兼顾小误差下的平顺和大误差下的快速收敛。实际工程中很多团队用线性PD简化替代NLSEF所得控制器称为LADRC线性自抗扰控制参数只有ωc和ωo两组在平衡车调试里更实用下文主要围绕LADRC展开。2.3 线性ADRC为什么是平衡车工程化的更优解非线性ADRC参数多且每个fal的幂次、线性区间都要单独调在实车上很难一次性找到稳定域。LADRC把控制律简化为u (kp·(v1 - z1) kd·(v2 - z2) - z3) / b0配合ESO的带宽参数化一共只需要整定ωc、ωo、b0三个参数。这在平衡车上的意义是调PID需要同时照顾角度环和速度环的耦合而调LADRC可以先固定b0的粗略值按ωc 2ωo的经验快速得到一组能站稳的参数。Simulink里可以用一个封装子系统模拟LADRC切换控制律时不需要改模型结构。3. Matlab里搭ADRC平衡车仿真微分方程、S-Function与Simulink接线3.1 用m脚本先写被控对象微分方程验证模型本身能跑进入Simulink之前先在MATLAB脚本里把被控对象的微分方程定义清楚。这样做的好处是可以单独验证被控对象的开环稳定性也能为后面S-Function和fcn模块的转换做准备。取平衡车典型参数m 1.2kgl 0.25mJ 0.04kg·m²g 9.81代入mgl/J算得a ≈ 73.6可以看出这个开环极点离原点非常远控制难度大。% balance_model.m - 平衡车被控对象微分方程 function dx balance_model(t, x, u) % x(1): 倾角 theta, x(2): 角速度 omega % u 为电机输出力矩(N*m) J 0.04; % 车体绕轮轴转动惯量 m 1.2; % 车体质量, kg g 9.81; % 重力加速度 l 0.25; % 质心到轮轴距离, m d 0; % 外部扰动, 可在仿真中临时修改 f (m * g * l / J) * sin(x(1)) - u / J d; % 总动力学 dx [x(2); f]; end这段代码里的d在初始阶段设为0目的是验证无扰动情况下模型能不能稳定在验证ADRC抗扰时再把d改成阶跃或正弦信号。注意f表达式中u/J和重力项的单位一致性力矩除以转动惯量后的量纲是rad/s²u直接取电机输出力矩而非PWM占空比是在仿真阶段的一个简化。3.2 把ESO写成S-Function或MATLAB Function三种实现方式怎么选在Matlab里实现ESO有三种常见做法Simulink原生模块搭、MATLAB Function模块写、S-Function写。三种方式各有取舍。原生模块搭的好处是可视化强缺点是离散状态较多时连线混乱ESO三个状态变量的更新顺序容易出错MATLAB Function模块适合在模型内部快速改参数调试效率高S-Function适合需要复用、批量跑参数扫描的场景。对平衡车仿真来说建议先用MATLAB Function跑通后再封装成S-Function做批处理。3.2.1 用MATLAB Function写ESO离散递推平衡车实车控制器的采样周期一般在2到5毫秒仿真步长固定为h 0.001或0.002用欧拉法做离散递推即可。ESO需要三个状态变量z1、z2、z3但在MATLAB Function中它们要作为持久变量保存每次调用更新。function [z1_hat, z2_hat, z3_hat, u_out] eso_predict(theta, u_in) % 离散ESO核心递推逻辑, 采用带宽参数化 % 观测器带宽 persistent z1 z2 z3 if isempty(z1) z1 0; z2 0; z3 0; % 初值全置零, 让ESO自己收敛 end h 0.001; % 采样周期, 必须与仿真步长一致 b0 100; % 控制增益估计值 w0 50; % 观测器带宽, rad/s beta1 3 * w0; beta2 3 * w0^2; beta3 w0^3; e z1 - theta; z1 z1 h * (z2 - beta1 * e); z2 z2 h * (z3 - beta2 * e b0 * u_in); z3 z3 h * (-beta3 * e); z1_hat z1; z2_hat z2; z3_hat z3; u_out z1_hat; % 为保持接口统一输出占位 end代码中z3的更新没有直接使用b0和u_in这是物理含义使然的总扰动中不被控制量补偿的部分只能靠误差驱动估计。如果b0估计不准z3会吸收掉模型偏差。调试时如果发现z3波形持续缓慢漂移说明b0偏小实际控制器需要更大的力矩来达到同样的加速度。3.2.2 控制律模块和Simulink信号连接顺序控制器部分把TD、ESO、控制律用信号线连起来。Simulink模型里的信号流是被控对象的theta输出同时连到ESO和控制器控制器的u输出回到被控对象形成一个闭环。TD的信号从theta_ref输入这里固定为0但保留TD结构是为了验证有目标值的斜坡变化时控制器的过渡过程。接线顺序需要特别注意ESO的输入u必须与控制律输出的u一致不能直接从被控对象取力矩信号否则ESO会“假设”对象收到的力矩和它认为的一致从而丢失对执行器饱和的估计能力。3.3 Simulink里用积分模块搭被控对象最小可运行模型很多人习惯直接写m脚本仿真但Simulink模型的优势是能方便地注入非线性环节比如饱和、死区、摩擦这是验证ADRC抗扰的必要条件。最小模型结构为一个求和模块接收–u和mgl·sinθ乘以1/J后进入积分器1得到角速度进入积分器2得到角度再通过三角函数反馈回来。在Simulink里搭这个模型时把被控对象封装成子系统暴露的输入是电机力矩u输出是角度theta和角速度omega。摩擦非线性方面可以用饱和模块做限幅电机力矩限幅通常设置在2到3N·m超过这个值就认为电机输出到达饱和边界。ADRC的ESO如果在这种情况下不收发散说明观测器增益太小需要按比例提升ωo。4. ADRC平衡车参数怎么调带宽法、阶跃响应与LQR对比4.1 带宽法整定流程三个参数先定哪个后定哪个LADRC参数整定采用带宽法时核心思路是“带宽分离”。先确定控制带宽ωc控制器的响应速度再确定观测器带宽ωoESO的收敛速度最后校准b0。常规经验是ωc取4到10 rad/s再令ωo 5ωc或更大。平衡车开环不稳定极点a的平方根约为8.6 rad/s如果ωc明显低于这个值控制器响应较慢车体倾向较大如果ωc过高角度信号中的噪声被放大车体高频抖动。步骤可以归纳为固定b0的初值平衡车场景下先设b0 100对应单位力矩产生的角加速度估计按ωo 5ωc设置观测器带宽ωc从5开始扫观察阶跃响应倾角超调大就降低ωc收敛慢就提高ωo最后重新校准b0观察z3的波形若存在周期性隆起则b0与实际值偏差大。4.2 用阶跃响应和扫参脚本评估一组参数的稳定裕度单纯看时域波形很难判断参数的稳健性建议写一个扫参脚本把ωc和ωo组合成一个二维网格对每个组合跑一次阶跃响应记录超调量、调节时间和是否发散。以下脚本的热词关联点是“matlab 阶跃响应”——用stepinfo函数批量评估对参数选型会有更直观的量化依据。% sweep_ladrc.m - 批量扫参评估LADRC参数稳定性 wc_list [4 6 8 10]; % 控制带宽 wo_list [20 30 50 80]; % 观测器带宽 results []; for wc wc_list for wo wo_list if wo 3 * wc continue; % 观测器太慢会导致ESO估计滞后 end simOut sim(balance_ladrc.slx, StopTime, 5); y simOut.yout{1}.Values.Data; t simOut.yout{1}.Values.Time; stepInfo stepinfo(y, t, 0); if isempty(stepInfo.SettlingTime) || any(isnan(y)) continue; end results(end1, :) [wc, wo, stepInfo.Overshoot, stepInfo.SettlingTime]; end end % 筛选稳定且快速收敛的参数 valid results(results(:, 3) 20 results(:, 4) 2.5, :); disp(valid);stepinfo函数里传入的目标值0表示期望稳态是0度。使用stepinfo时有个细节如果平衡车模型在参数组合下发散y中会出现NaN需要先用any(isnan(y))过滤否则stepinfo会报错。筛选条件里超调小于20%、调节时间小于2.5秒是经验值实际工况可以根据载重和期望动态调整。批量扫参的好处是可以直观看到ωo追得太紧会引入噪声ωc追得太紧会激发摩擦振荡——这两个趋势靠手调很难察觉。4.3 ADRC与LQR在平衡车上的定位差异不是替代关系Matlab相关热搜词里有大量的“lqr平衡车”说明LQR在平衡车圈子的普及度很高。LQR返回最优状态反馈矩阵K的过程非常简单给定状态空间矩阵A、B和权重Q、R调用K lqr(A, B, Q, R)即可。它对模型准确性的依赖非常高——如果模型里没有摩擦、死区项LQR在仿真里性能很好但上实车后状态估计质量下降控制效果立刻打折扣。ADRC的ESO把这些问题的大部分归结于总扰动模型里不需要精确包含摩擦项也能处理。下表从工程设计维度做一个对比对比维度LQRADRC(LADRC)依赖精确模型程度高要求A、B矩阵准确低只需b0的大致范围待整定参数Q、R矩阵通常需要试凑ωc、ωo、b0三个标量对抗动的估计能力无靠反馈硬扛ESO实时估计并补偿实车调试上手难度状态估计部分较复杂参数物理含义明确典型适用阶段模型准确、状态可测的场景模型不确定性大的场景实车上更稳妥的做法是把两者做内环外环组合内环角度环用ADRC抵抗摩擦和地面变化外环速度环用LQR保证位置收敛。这需要两套控制器之间用不同采样率运行内环1kHz、外环100Hz是常见的划分方式。5. 实战技巧在模型失配和噪声下验证ADRC鲁棒性5.1 在Simulink里注入模型失配改变m和l看ESO是否真的能扛不少人在Simulink仿真里把被控对象模型的m、l控制在固定值得到漂亮的响应曲线上了实车才露馅。正确做法是把被控对象的参数改得跟控制器里假设的值不同步比如控制器里b0对应m1.2kg的情况被控对象模型里把m改成1.8kgl改成0.3m。如果ADRC的调节时间变化在三倍以内说明ESO把重心偏移导致的动力学变化当作扰动“吞”掉了。具体操作用一个参数开关模块在仿真进行到2秒时让l从0.25跳到0.3% sim_time 2秒后切换质心高度 l_val 0.25 (t 2) * 0.05;观察角度响应如果2秒后出现明显的振荡且持续超过两个周期说明观测器带宽ωo不足以跟踪突变型扰动需要提升ωo并检查是否引入噪声。5.2 传感器噪声和量化误差的模拟技巧实车角度环的输入来自陀螺仪和加速度计融合融合算法本身有延迟角速度信号有噪声。仿真时在角度测量通道上叠加高斯白噪声标准差取0.005rad角速度通道取0.05rad/s。Simulink里的Band-Limited White Noise模块即可实现。加了噪声后一个值得关注的现象是和ESO带宽相关的抖动ωo太高时角度上的噪声被ESO当作高频扰动估计进z3控制量上会出现持续的毛刺。此时推荐在角度入口前加一个一阶低通滤波器截止频率控制在20Hz。过滤波器的代价是增益裕度变小所以保存两组参数应对噪声适配也是工程常态。5.3 用控制量限幅检验ESO的抗饱和能力ADRC的一个隐藏优势是它在控制量饱和时依然能观察对象响应饱和状态下执行器并没有按控制律输出ESO通过z3估计到“应该有的力比实际有的力大”从而自动调整后续控制量这个性质被称作“抗饱和”。在Simulink中对u加饱和模块限幅设为±2N·m跑一个大幅扰动的仿真看theta是否能恢复。如果ESO在这种情况下偏差持续增大需要检查ESO的z3初值是否置零并确认b0的比值是否过小。抗饱和能力是ADRC在平衡车实车调试中最实用的特性很多PID方案在电机堵转时积分器快速饱和退绕逻辑复杂度远超参数本身。本文还有配套的精品资源点击获取
返回列表