🛡️ ADRC 自抗扰控制与嵌入式实现

TD / ESO / LADRC 完整推导 + STM32 落地细节 —— 从韩京清「估计 + 补偿」哲学,到高志强带宽法三个参数搞定整定,再到一阶/二阶 LADRC 的可移植 C 代码、抗扰验证与失效排查。本页是 ADRC 的体系页,与 00-01 的 ESO 代码演示、04-09 的工程升级路线、06-11 的面试题库互为补充。
ADRC 自抗扰 TD / ESO / LADRC 带宽参数化 STM32 C 实现 抗扰整定
🎯 本页学习目标
1. 能画出 ADRC 的完整结构框图,说清 TD、ESO、LSEF/NLSEF、扰动补偿四部分各自解决什么问题
2. 能推导三阶 ESO 方程组,并用高志强带宽法写出 β₁ β₂ β₃ 与 kp kd 的全部增益表达式
3. 能解释 b₀ 的物理意义,并用空载阶跃实验估计 b₀,说出 b₀ 过大/过小的两种相反症状
4. 能按「先内环后外环、ωₒ 从低到高扫」的流程把一个 PI 环替换成一阶 LADRC,并知道 ωₒ ≤ fs/10 的由来
5. 能在 STM32 上部署 ~80 行的一阶/二阶 LADRC C 代码,并根据症状表排查 ωₒ 过高、b₀ 失配等失效模式
建议用时:约 45 分钟(推导部分可配合 00-01 页的交互仿真对照阅读)

1 ADRC 动机与思想:把「不知道」当成扰动来估计

1.1 是什么:PID 的「误差导向」范式到底卡在哪

是什么:PID 的控制量完全由「设定值 − 输出值」这个误差驱动:u = Kp·e + Ki·∫e + Kd·de/dt。它不看对象内部发生了什么,只看「结果差多少」再事后补救。这套范式统治工业八十年,靠的是两条:不依赖模型、结构简单。但放在人形机器人关节上,它的三个短板被放大:

为什么:问题的根源是「扰动不可见」。韩京清(中科院系统科学研究所,ADRC 创始人)的切入点是:与其给每种扰动单独建模,不如把所有「模型对不上 + 外部作用」统一打包成一个量,在线估计它,然后从控制量里减掉。这个打包后的量就叫总扰动:

\ddot{y}(t) = f\big(\,y,\ \dot{y},\ w(t),\ t\,\big) + b_0\,u(t) \qquad\text{(二阶对象标准型,如关节位置环)}

怎么做:把对象强制写成上式 —— 唯一要求知道的模型信息只有两个:阶次 n(关节位置/速度环通常是二阶)和输入增益 b₀ 的估计值。剩下所有复杂东西都塞进 f。这就是 ADRC「不依赖精确模型」的准确含义:不是不用模型,而是只用的部分少而粗(阶次 + b₀,误差 3 倍以内都能工作)。

面试怎么问:「ADRC 为什么说是不基于模型的?它到底需要知道什么?」——标准答案:需要对象的相对阶次输入增益估计 b₀,其余(参数摄动、非线性、外扰)全部归入总扰动由 ESO 在线估计;这是它与自抗扰之前所有「先建模再设计」方法的本质区别。

⚠️ 易错点:①把「总扰动」理解成只有外部负载 —— 它还包括参数漂移和未建模动态,这正是比「扰动观测器 DOB」覆盖面更广的地方;②以为总扰动是标量常值 —— 它是 y、ẏ、外输入 w 和时间 t 的函数,只是被当成「扩张状态」在线跟踪。

1.2 核心思想:估计 + 补偿,ADRC 四件套各司其职

是什么:ADRC(Active Disturbance Rejection Control)= TD + ESO + 状态误差反馈 + 扰动补偿四件套。逻辑链只有三步:

  1. 安排过渡过程(TD):目标指令先经跟踪微分器「柔化」,不再拿阶跃直接砸闭环 —— 消超调、防激励机械谐振,顺带得到无噪声放大的微分信号;
  2. 估计总扰动(ESO):把 f 扩张成第 n+1 个状态,用输入 u 和测量 y 实时观测出 z₁…zₙ₊₁,其中 z₃(二阶对象)就是总扰动的估计;
  3. 对消 + 反馈(补偿):控制量里减去 z₃/b₀,把对象实时「改造成」纯积分器链,再用 PD(或 NLSEF)控制这个被简化后的对象 —— 问题从「控制复杂不确定对象」降维成「控制教科书级积分器」。
\text{补偿后:}\quad \ddot{y} = \underbrace{f - z_3}_{\approx\,0} + b_0\cdot\frac{u_0 - (f-z_3)}{b_0} \;\approx\; u_0 \qquad\text{(对象被实时改造成双积分器)}
v 参考输入 TD 跟踪微分器 安排过渡过程·提取微分 v₁ v₂ Σ + e₁ e₂ NLSEF / 线性PD (LSEF) u₀ = kp·e₁ + kd·e₂ u₀ Σ + u 被控对象 ÿ=f+b₀u u(控制量) y(测量) ESO 扩张状态观测器 e = z₁−y · ż₁=z₂−β₁e · ż₂=z₃−β₂e+b₀u · ż₃=−β₃e 吃进 u 与 y,吐出 z₁ z₂(状态) + z₃(总扰动) z₁ z₂ 扰动补偿 −z₃/b₀ 绿:指令/控制通道 · 蓝:测量通道 · 橙:观测器状态反馈 · 红:求和与扰动补偿
图① ADRC 完整结构:ESO 是「心脏」—— 同时吃控制量 u 和测量 y,把总扰动 z₃ 估出来;控制律只做两件事:PD 出力 u₀ + 减去 z₃/b₀ 对消扰动

面试怎么问:「画出 ADRC 的结构框图,并指出总扰动从哪进、从哪出。」—— 总扰动「进」在对象方程的加速度端(与 b₀u 同一通道),「出」在 ESO 的扩张状态 z₃,最终以 −z₃/b₀ 的形式汇入控制量。画不出 ESO 双输入(u、y)是常见扣分点。

💡 与站内已有内容的关系:00-01 3D 解剖页的「ADRC 推导与代码」小节给了二阶 LADRC 的交互仿真与单文件宏定义版代码;04-23 升级路线页给了「三环 PID → 三环 ADRC」的工程变体表。本页负责把推导、整定方法论与嵌入式细节一次讲全 —— 三页配合使用。

2 TD 跟踪微分器与 ESO 扩张状态观测器:ADRC 的两大「信号器官」

2.1 TD 安排过渡过程:一次性解决超调与微分噪声放大

是什么:TD(Tracking Differentiator,跟踪微分器)是一个二阶动态环节,输入原始指令 v(k),输出两个信号:v₁ —— 平滑跟踪 v 的「过渡过程」,v₂ —— v₁ 的微分。为什么需要它:阶跃指令直接进闭环,误差瞬间达到最大值,积分项迅速饱和 → 超调;而想给 PID 加微分项,直接对测量差分,信噪比崩塌。TD 用「最速跟踪 + 微分在环内产生」同时解决这两个老问题 —— 这是韩京清对 PID「微分噪声放大」死结的正面回答。

怎么做(fhan 最速离散跟踪微分器):

v_1(k+1)=v_1(k)+h\,v_2(k),\qquad v_2(k+1)=v_2(k)+h\,\cdot\mathrm{fhan}\big(v_1(k)-v(k),\ v_2(k),\ r,\ h_0\big)
\text{其中}\ \ d=r\,h_0,\ \ d_0=h_0\,d,\ \ y=x_1+h_0\,x_2,\ \ a_0=\sqrt{d^2+8r\,|y|},\ \ a=\begin{cases} x_2+\dfrac{a_0-d}{2}\,\mathrm{sign}(y), & |y|>d_0\\[4pt] x_2+\dfrac{y}{h_0}, & |y|\le d_0 \end{cases}
\mathrm{fhan}(x_1,x_2,r,h_0)=\begin{cases} -r\,\mathrm{sign}(x_2), & |a|>d\\[3pt] -\dfrac{r\,a}{d}, & |a|\le d \end{cases}

直观理解:fhan 是「最速控制综合函数」—— 它回答「以加速度上限 r,最快多少步能把 x₁ 拉到 0」。把它接进上面两行迭代,得到的 v₁ 就是「在加速度受限下最快又最平滑地跟上 v 的轨迹」,v₂ 就是这条轨迹的速度,天然可用作前馈。

参数物理意义调大调小工程经验
r 速度因子「虚拟加速度上限」,决定过渡过程快慢跟踪快,但 r→∞ 时 v₁ 退化为阶跃,失去安排过渡过程的意义过渡平缓、无超调,但响应滞后按「希望几个周期到达」反推;常从阶跃响应时间 T 估 r ≈ 10·v₀/T 量级起试
h₀ 滤波因子等效滤波时间常数,抑制输入噪声v₁/v₂ 更平滑,但相位滞后增大,v₂ 滞后于真实微分跟随快,噪声残留多h₀ ≥ 采样周期 h,典型 (3~10)·h;输入噪声大时加大

工程简化(重要):人形机器人整机控制器通常以 1kHz 下发「位置 + 速度 + 力矩前馈」三元组(q_des, dq_des, τ_ff),指令本身就是平滑轨迹、速度前馈现成 —— 此时关节侧 TD 可省略,直接令 v₁=q_des、v₂=dq_des(00-01 页同样结论)。TD 真正的用武之地是:指令来自阶跃型上位机、或需要从「又脏又跳」的指令里提取干净微分信号的场合。

面试怎么问:「TD 解决什么问题?r 和 h₀ 分别管什么?」——答「安排过渡过程消超调 + 无噪声放大的微分提取」;r 管快慢(等效加速度限幅),h₀ 管滤波(等效噪声采样窗),二者独立可调是 TD 优于「一阶惯性 + 差分」的地方。

⚠️ 易错点:①把 h₀ 直接填成采样周期 h —— 滤波几乎为零,v₂ 满屏毛刺;②把 r 调到天文数字然后抱怨「TD 没用」—— r 过大就等于没安排过渡过程;③以为 TD 有闭环稳态精度概念 —— 它是开环信号预处理,不参与抗扰。

2.2 ESO:把总扰动扩张为第 n+1 个状态

是什么:ESO(Extended State Observer,扩张状态观测器)是 ADRC 的心脏。普通状态观测器(见 04-17 状态观测器全解)只估计模型里已有的状态;ESO 的绝招是把「模型之外的一切」—— 总扰动 f —— 也当作一个状态 x₃ = f 扩张进来,让观测器把它连同 x₁ x₂ 一起估出来。对二阶对象(以关节位置环为例,x₁=y、x₂=ẏ、x₃=f):

\dot{x}_1=x_2,\qquad \dot{x}_2=x_3+b_0 u,\qquad \dot{x}_3=\dot{f}\approx 0\ \ (\text{扰动缓变假设})

为什么能收敛:第三行的 ḟ≈0 不是说扰动真的不变,而是「在观测器带宽对应的时标内近似不变」。对扩张系统构造观测器,用输出误差 e = z₁ − y 驱动三个状态的校正,就得到非线性三阶 ESO:

\begin{aligned} \dot{z}_1&=z_2-\beta_1\,\mathrm{fal}(e,\alpha_1,\delta)\\ \dot{z}_2&=z_3-\beta_2\,\mathrm{fal}(e,\alpha_2,\delta)+b_0\,u\\ \dot{z}_3&=-\beta_3\,\mathrm{fal}(e,\alpha_3,\delta) \end{aligned}\qquad e=z_1-y
\mathrm{fal}(e,\alpha,\delta)=\begin{cases} \dfrac{e}{\delta^{\,1-\alpha}}, & |e|\le\delta\ \ (\text{线性段防抖})\\[5pt] |e|^{\alpha}\,\mathrm{sign}(e), & |e|>\delta \end{cases}\qquad 0 < \alpha < 1

fal 函数与收敛性直觉:当 0 < α < 1 时,|e| 很小则 |e|^α 反而比 |e| 大(例如 e=0.01、α=0.5 时 |e|^α=0.1)——「小误差大增益、大误差小增益」:误差小时强拉快收敛,误差大时增益自动回落防超调,δ 线性段保证过零处增益有限不抖振。这套「幂次增益」与滑模观测器的 sigmoid 边界层、电机控制里的变结构思想一脉相承。收敛性的严格证明较难(韩京清用有限时间稳定性与时间尺度概念给直觉论证),但线性化后看:β 配置使特征多项式全负实部 + 扰动变化率有界 ⇒ 估计误差最终有界收敛;工程上更重要的是下一节的带宽法 —— 它把「β 怎么选」变成一个频率参数。

怎么做(读 ESO 的三个输出):z₁ = 位置估计(可直接替代测量做反馈,滤了噪声)、z₂ = 速度估计(比编码器差分干净,可省掉独立测速滤波)、z₃ = 总扰动估计(重力 + 摩擦 + 负载冲击的「合力」,既送去补偿,也可顺手做碰撞检测:|z₃| 突增即触碰)。观察 z₃ 波形是调 ESO 的第一手诊断量 —— 它应当平滑地跟随重力/摩擦的慢变化。

t (s) |x−z| 估计误差 误差 = 0 ωₒ 过高:振荡发散 (显式欧拉 + 噪声) ωₒ=50:收敛慢,扰动「追不上」 ωₒ=200:快速干净收敛 ✓ ωₒ 小 · 慢 ωₒ 适中 · 快且稳 ωₒ 过高 · 发散
图② ESO 收敛性随观测器带宽 ωₒ 的变化:ωₒ 越大对扰动的「追赶」越快,但受噪声与离散化限制 —— ωₒ 超过采样率允许的上限后,显式欧拉下直接振荡发散(第 6 节给出定量关系)

面试怎么问:「ESO 为什么能估计不知道的扰动?它对扰动做了什么假设?」——标准答案三层:①扩张状态——把 f 当第 n+1 个状态纳入观测器;②唯一假设是扰动「缓变」(ḟ≈0 或变化率有界),观测器带宽决定能跟踪多快的扰动;③收敛靠 β 增益配置使误差动态稳定, fal 的「小误差大增益」进一步加快小误差段收敛。

⚠️ 易错点:①把 ESO 与 04-17 的扰动观测器(DOB)混为一谈 —— DOB 需要对象逆模型 Q(s),ESO 只要 b₀ 和阶次,模型依赖更低;②忽略「扰动能被观测」的前提:扰动频率接近或超过观测器带宽时 z₃ 显著滞后,补偿能力随之下降 —— 这是 ωₒ 要尽量做高的根本原因;③fal 的 δ 取 0,导致过零抖振(数值上等价于去掉线性段)。

3 LADRC 线性化与带宽参数化:工程落地的关键一步

3.1 高志强带宽法:全部增益由 ωₒ 一个参数决定

是什么:非线性 ADRC 的 fal、fhan 里有一堆参数(α₁ α₂ α₃ δ β₁ β₂ β₃…),整定困难、理论分析也难。高志强(克利夫兰州立大学)在 ACC 2003 论文(资源卡 R2)里给出尺度变换 + 带宽参数化:把 ESO 全部增益用单一参数 —— 观测器带宽 ωₒ 表示,办法是把观测器特征多项式的所有极点统一配置在 −ωₒ:

(s+\omega_o)^3 = s^3+3\omega_o\,s^2+3\omega_o^2\,s+\omega_o^3 \;\Longrightarrow\; \beta_1=3\omega_o,\quad \beta_2=3\omega_o^2,\quad \beta_3=\omega_o^3

为什么这么配:观测器误差动态的特征多项式就是 s³+β₁s²+β₂s+β₃(对三阶 ESO),把它对比 (s+ωₒ)³ 的展开,β 就全定了 —— 三重极点统一在 −ωₒ,单调无超调的收敛形态,物理意义就是「误差以 ωₒ 为时间尺度的指数速度被拉回」。同理控制器侧把 PD 的两个极点统一配在 −ω_c:k_p=ω_c²、k_d=2ω_c。于是整个二阶 LADRC 只剩三个待定参数:ωₒ、ω_c、b₀,且前两个都是频率量纲、可以直接对着「闭环带宽需求」和「采样率上限」拍板。

为什么工程都用 LADRC:

面试怎么问:「LADRC 的带宽参数化是怎么把多参数问题变成单参数的?」——答:把 ESO(和 PD)特征多项式按 (s+ωₒ)ⁿ/(s+ω_c)ⁿ 展开对比系数,β₁=3ωₒ、β₂=3ωₒ²、β₃=ωₒ³、k_p=ω_c²、k_d=2ω_c;ωₒ 定「估计多快」,ω_c 定「闭环多快」,经验 ωₒ≈(3~5)ω_c。

⚠️ 易错点:①β 的表达式只对「三阶 ESO / 二阶对象」成立 —— 一阶对象用二阶 ESO,是 β₁=2ωₒ、β₂=ωₒ²(第 5.2 节);别背错阶次。②ωₒ、ω_c 是弧度/秒,和 Hz 差 2π —— 「fs=1kHz 所以 ωₒ≤100」是把单位搞混的典型事故(应为 ωₒ≤628 rad/s)。

数值算例:给定电机参数算 ESO 增益与控制律(手推)

对象:某关节电机二阶模型 J·θ̈ = u − d(含负载/摩擦总扰动 d),折算到电机端的惯量 J = 0.002 kg·m²,则 b₀ = 1/J = 500(单位 1/(kg·m²),配转矩指令 u 时恰是 rad/s²/N·m 的换算)。取观测器带宽 ωₒ = 150 rad/s、控制器带宽 ωc = 100 rad/s(经验 ωₒ ≈ (3~5)ωc 的中段)。

三阶 ESO 增益(带宽法一步算完):

\beta_1 = 3\omega_o = 3\times150 = \mathbf{450},\qquad \beta_2 = 3\omega_o^2 = 3\times150^2 = 3\times22500 = \mathbf{67500},\qquad \beta_3 = \omega_o^3 = 150^3 = \mathbf{3.375\times10^6}

控制器 PD 增益:kp = ωc² = 100² = 10000,kd = 2ωc = 200代一组数感受量纲:设位置误差 v₁−z₁ = 0.05 rad、估计速度 z₂ = 2 rad/s、负载扰动 d = 3 N·m(z₃ ≈ −d/J = −1500 rad/s²),则 u₀ = 10000×0.05 − 200×2 = 500 − 400 = 100 rad/s²(加速度指令),控制量 u = (u₀ − z₃)/b₀ = (100 − (−1500))/500 = 1600/500 = 3.2 N·m。拆开看:0.2 N·m 用于加速(u₀/b₀ = 100×0.002),3.0 N·m 用于顶住负载——扰动补偿项占了 94%,这就是 z₃/b₀ 在干活

采样率校核:由 ωₒ ≤ fs/10 得 fs ≥ 10×150 = 1.5 kHz。对照 §12 分层表:速度/位置环通常跑 1~2 kHz——取 2 kHz 时高于最低要求 1.5 kHz,但余量仅 33%(fs/ωₒ ≈ 13.3 倍,刚过 10 倍准则),环频一旦掉到 1.5 kHz 以下就得降 ωₒ;电流环 20 kHz 相比之下宽裕一个数量级,进一步说明 ESO 放在位置/速度层、电流层仍交给 PI 的分层是自洽的。若现场只剩 1 kHz,反解 ωₒ ≤ 628 rad/s,需把 ωₒ 降到 ~120 rad/s 并同步下调 ωc

📌 自检:把数字换成你的电机参数重算一遍(提示:先重算 b₀ = 1/J,再按 β₁=3ωₒ、β₂=3ωₒ²、β₃=ωₒ³、kpc²、kd=2ωc 逐个代,最后用 ωₒ≤fs/10 校核你控制器的环频)。

3.2 线性控制律与扰动补偿:u = (u₀ − z₃)/b₀

是什么:LADRC 的控制律分两步 —— 先用估计状态做线性 PD(称作 LSEF,Linear State Error Feedback),再做扰动补偿:

u_0 = k_p\,(v_1-z_1) + k_d\,(v_2-z_2),\qquad k_p=\omega_c^2,\ \ k_d=2\omega_c
u = \frac{u_0 - z_3}{b_0} \qquad\Longrightarrow\qquad \ddot{y} \approx u_0\ \ (\text{总扰动被对消,对象变成双积分器})

怎么理解补偿这一步:对象真实满足 ÿ = f + b·u(真实增益 b)。代入 u=(u₀−z₃)/b₀ 得 ÿ = u₀ + (b/b₀)(f−z₃)·b₀/b₀… 把量纲捋直:ÿ = (b/b₀)·u₀ + [f − (b/b₀)·z₃]。当 b₀≈b 且 z₃≈f 时,ÿ≈u₀ —— 控制器面对的等效对象变成了干净的双积分器,PD 控制双积分器是教科书问题,这就是「ADRC 把复杂对象改造为积分器串联型」的含义。注意两点:①即使 b₀≠b,z₃ 也会把 (b/b₀−1)·u₀ 的部分一起「吸收」掉,这正是 ADRC 对 b₀ 失配鲁棒的来源;②u 的量纲跟随 b₀ 的定义(电压、电流指令或力矩),写代码前先统一。

面试怎么问:「z₃/b₀ 里的 b₀ 是干嘛的?去掉行不行?」——不行:z₃ 是加速度量纲的总扰动,要换算成「控制量」量纲才能在输入端对消,除以 b₀ 就是这个换算;b₀ 是 b 的估计,失配只会降低对消质量,不会破坏结构。

3.3 NLSEF:什么时候才真的需要「非线性」

是什么:NLSEF(非线性状态误差反馈)把线性 PD 换成 fal 组合:

u_0 = \beta\,\mathrm{fal}(e_1,\alpha_1,\delta) + \beta\,\mathrm{fal}(e_2,\alpha_2,\delta)\qquad(\text{非线性版,常用 } \alpha_1<1<\alpha_2)

与线性 PD 的差别:线性 PD 的增益恒定 —— 误差大时出力「不够狠」,误差小时又「推不动残差」;NLSEF 用幂次函数做变增益:小误差段(α<1)增益趋于无穷大级地放大,消除稳态残差又快又干净;大误差段增益相对收敛,防止猛出力导致超调。再加上「大误差段 α>1 加速合围」的组合策略,理论上比线性更接近时间最优。

对比项线性 LSEF(PD)非线性 NLSEF
增益特性恒定,频域工具齐全随误差幅值变化,「小误差大增益」
稳态残差依赖 ω_c 与扰动补偿质量幂次增益对小残差「穷追不舍」,更干净
整定与分析ω_c 单参数,可自动化多参数(α、δ、β),无成熟频域方法
适用场合绝大多数伺服/关节场景(工程默认)大范围高精度快速定位、强非线性对象、对极限性能有要求的研究课题

怎么做(决策建议):先用线性版把系统跑通、拿到基线性能;只有当「小误差段爬行」「大误差段超调」两类问题同时出现、且线性版调不动时,才考虑把 LSEF 换成 NLSEF —— 并接受整定时间翻倍的代价。韩京清原著(资源卡 R1)对非线性机理讲得最透,可作为进阶阅读。

面试怎么问:「LADRC 已经线性了,韩京清的原始 ADRC 为什么坚持非线性?你选哪个?」——答出取舍即可:非线性版理论性能上限更高(最速性),线性版工程可控性更好;选型看「性能缺口是否存在 + 整定资源是否充裕」,工业界默认线性。

⚠️ 易错点:把 NLSEF 和「给 PID 加个非线性增益」划等号 —— NLSEF 作用的对象是补偿后的积分器链,误差用的是估计状态误差 (v−z),不是测量误差 (r−y);脱离 ESO 单独用 fal 组合,既丢了抗扰又引入抖振。

4 b₀ 的物理意义与整定:三个参数里最容易翻车的那个

4.1 b₀ 是什么:控制增益估计,失配的两种相反症状

是什么:b₀ 是对象方程 ÿ = f + b·u 中真实输入增益 b 的估计值 —— 「1 单位控制量能产生多少加速度」。位置/速度环里 b ≈ 1/J(J 为折算到该环输出端的转动惯量);电流环一阶模型里 b ≈ 1/L。它出现在两处:ESO 用它把「u 产生的那部分」从总变化里剥离(模型项),控制律用它把 z₃ 换算回控制量量纲(补偿项)。

为什么它决定性能:b₀ 不准时,ESO 与补偿同时「错」,但错的方式部分抵消 —— 所以 ADRC 对 b₀ 误差有 3~5 倍的容忍度(远好于增益调度),但超出后症状对称地出现:

b₀ 取值补偿效果等效对象典型症状处理方向
b₀ 过小(b₀ < 真实 b)过度补偿:同样的 z₃ 被换算出更大的控制量等效增益虚高响应变快但超调、振荡、啸叫,严重时发散增大 b₀
b₀ 过大(b₀ > 真实 b)补偿不足:对消不干净等效增益偏低 + 残留扰动响应迟钝、爬行,抗扰恢复慢,像「欠阻尼的软系统」减小 b₀
b₀ 准确(±3 倍内均可工作)对消干净≈ 双积分器阶跃快而稳,z₃ 平滑贴合负载变化固化参数

面试怎么问:「b₀ 失配会失稳吗?怎么判断往哪个方向调?」——答:多数情况不直接失稳(z₃ 会吸收一部分失配),但性能退化;「振荡 → b₀ 偏小,迟钝 → b₀ 偏大」这组对称口诀必须答出来。判断技巧:比较 |u₀| 与 |z₃/b₀| 的量级 —— 若补偿项远大于反馈项,说明 b₀ 或扰动通道有问题。

4.2 b₀ 怎么估:从一次空载阶跃到在线自整定

怎么做(三条路,由易到难):

  1. 惯量折算法(桌面估计):查电机转子惯量 J_r、减速比 i、负载折算 J_L,得 b₀ ≈ 1/(J_r + J_L/i²)(输出端系)。5 分钟出初值,误差可到 ±50%,但足够当扫参起点;
  2. 空载阶跃拟合法(推荐,10 分钟):断开位置环,对速度环(或直接电压)施加已知小阶跃 u₀(额定值的 10~20%,避免饱和),由编码器测角加速度 ä:b₀ ≈ ä/u₀。多取几个幅值求平均,注意剔除摩擦主导的低速段数据;
  3. 在线辨识/递推最小二乘(进阶):把 b 作为参数随运行数据递推更新,负载大范围变化(机械臂抓放)时值得做,代价是引入参数激励条件问题。
b_0 \approx \frac{\Delta\ddot{y}}{\Delta u}\Big|_{\text{空载小信号阶跃}}\qquad\text{(多次取幅值平均;电流环则 } b_0\approx 1/L\text{,用 datasheet 的相电感)}

面试怎么问:「现场没有惯量数据,如何 10 分钟拿到可用的 b₀?」——答空载小信号阶跃 + 差分求加速度 + 线性回归,并补一句「量测端先做低通再差分,否则噪声把 ä 淹没」。

⚠️ 易错点:①在饱和区测 b₀ —— 输出饱和后 ä 不再随 u 线性增长,估出来系统性偏小;②忘了单位折算 —— 减速比平方出现在惯量折算里(1/i²)、编码器单位 rad 还是 count,错一个量级 b₀ 就错两个量级;③认为 b₀ 越准越好而过度打磨 —— b₀ 偏大 30% 只损失少量响应速度,优先把时间花在 ωₒ 扫描上。

5 LADRC 完整整定流程:从 b₀ 到固化参数的六步

5.1 整定 step-flow:先内环后外环,ωₒ 从低到高扫

怎么做:多环系统(电流→速度→位置)遵循「先内环后外环」—— 内环整定完成后,对外环近似为理想力矩源,外环才好整。单环之内按下面流程走:

① 辨识 b₀(空载小信号阶跃) b₀≈Δÿ/Δu;或 1/J 惯量折算,误差 3 倍内可用 ② 定控制器带宽 ωc 按闭环需求从需求值的一半起(位置环 30~150 rad/s) ③ 定观测器带宽 ωₒ:从 (3~5)·ωc 起扫 只往上扫,上限 fs/10;盯 z₃ 平滑度与电流啸叫 ④ 小幅阶跃验证:超调?振荡?稳态残差? 振荡 → ωc 回退 30%;迟钝 → 查 b₀ 方向(第 4.1 节口诀) 啸叫/抖动 → 降 ωₒ(或改滤波) ⑤ 突加负载扰动验证(对照 PI 基线) 看跌落深度与恢复时间(第 8 节读曲线四步) ⑥ 固化参数 · 写入固件 · 记录版本
图③ LADRC 整定流程:唯一允许「来回」的只有 ③→④ 的回退环 —— ωₒ 只增不减地扫,遇到啸叫先降 ωₒ 或加滤波,不要回头去动 ω_c
参数起点扫描方向停止判据
b₀阶跃拟合值 / 1/J按症状微调(振荡↑b₀、迟钝↓b₀)阶跃无超调、无爬行
ω_c需求带宽的一半从小到大轻微振荡后回退 30%
ωₒ(3~5)·ω_c从低到高,典型扫到 fs/5~fs/10 为止z₃ 平滑、阶跃恢复达标、无啸叫
限幅 u_max执行器能力(电流/力矩)涵盖补偿项与反馈项之和

ωₒ 上限为什么是「典型 1/5~1/10 采样率」:ωₒ 越高,ESO 对突扰动的跟踪越快,但显式欧拉离散的稳定域有限(第 6 节推导),且 β₂=3ωₒ²、β₃=ωₒ³ 会把编码器量化噪声放大进 z₂ z₃。工程折中:先扫到 z₃ 开始「起毛」,再退一档 —— 这比任何公式都可靠。

面试怎么问:「给你一个新关节,LADRC 三参数你怎么下手?顺序能乱吗?」——答 b₀ 先行(没它补偿方向都不知道)、ω_c 按需求、ωₒ 最后且必须 ≥3ω_c;顺序乱调会互相掩盖症状。

5.2 与 PID 对照:一个 PI 电流环改造成一阶 LADRC 的完整替换

为什么用电流环举例:电流环对象是一阶(R-L 电路),对应一阶 LADRC(二阶 ESO),代码最短、收益直观(反电动势 Ke·ω 就是现成的「总扰动」—— ESO 会把它估出来并补偿,等效于免费的自适应反电动势前馈)。对象方程:

L\frac{di_q}{dt} = -R\,i_q + u - K_e\,\omega \;\;\Longrightarrow\;\; \dot{i}_q = \underbrace{\tfrac{1}{L}\big(-R\,i_q - K_e\omega\big)}_{\text{总扰动 }f} + \underbrace{\tfrac{1}{L}}_{b_0}\,u

一阶 LADRC 完整方程(二阶 ESO,β₁=2ωₒ、β₂=ωₒ²):

\dot{z}_1=z_2-\beta_1(z_1-i_q)+b_0\,u,\qquad \dot{z}_2=-\beta_2\,(z_1-i_q),\qquad u=\frac{k_p\,(i_q^{ref}-z_1)-z_2}{b_0},\quad k_p=\omega_c
1留基线
记录原 PI 参数(Kp,Ki)与 3 组阶跃/突扰波形,给改造后的对比留下「对照组」
2算 b₀
b₀=1/L(L 取 datasheet 相电感);ω_c 取原 PI 穿越频率;ωₒ=4ω_c 起步
3换函数
把 PI 函数替换为第 7 节 ladrc1_calc();调用位置、周期、限幅都不变
4扫 ωₒ
从 fs/20 扫到 fs/10,盯电流波形毛刺与啸叫;再校 ω_c 对齐原带宽
5对比验证
反电动势工况(高速段)与突加负载下对比基线:跌落深度、恢复时间
留退路
参数表里保留 PI/LADRC 双方案与切换开关 —— 量产路径允许回滚
💡 预期收益与代价:电流环换一阶 LADRC 后,高速段因反电动势被 z₂ 实时补偿,电流跟踪滞后明显减小;代价是每周期多 ~30 次浮点运算(第 6.2 节),以及多了 ωₒ 一个需要保护的参数(改错会啸叫)。速度环换二阶 LADRC 的流程完全相同,对象换成 J·dω/dt,b₀≈1/J,ESO 多一个状态。

面试怎么问:「把 PI 环换成 LADRC,最小改动是什么?哪些必须保持不变?」——答:只替换「误差→控制量」的映射函数,执行周期、输出限幅、保护逻辑、通信接口全部保持;必须保留原方案基线与回滚开关。

6 离散实现与采样率:ωₒ 上限、浮点/定点与耗时量级

6.1 欧拉离散与 ωₒ ≤ fs/10 的由来

是什么:MCU 上跑的是差分方程。对连续 ESO 用前向欧拉(显式)离散最简单 —— 每周期把导数乘以 Ts 直接累加:

z_1^{k+1}=z_1^{k}+T_s\big[z_2^{k}-\beta_1 e^{k}+b_0 u^{k}\big],\qquad z_2^{k+1}=z_2^{k}+T_s\big[z_3^{k}-\beta_2 e^{k}\big],\qquad z_3^{k+1}=z_3^{k}-T_s\,\beta_3 e^{k}

为什么 ωₒ 有上限:显式欧拉把连续极点 −ωₒ 映射到 z 平面的 1−ωₒTs,落在单位圆内才稳定,粗略要求 ωₒ·Ts ≲ 1;再考虑三重极点的稳定裕度收紧 5~10 倍,就得到工程经验式:

\omega_o \;\le\; \frac{f_s}{10}\qquad\Big(f_s=\tfrac{1}{T_s}\ \text{为采样频率,如 } f_s=1\,\text{kHz}\Rightarrow\omega_o\le 628\ \text{rad/s}\approx 100\,\text{Hz}\Big)

怎么做(想突破上限怎么办):①改离散方法 —— 后向欧拉/Tustin(双线性)把稳定域扩大,Tustin 下 ωₒ 上限可放宽到 fs/3 左右,代价是每周期多做几次乘加;②精确离散 —— 观测器矩阵是 3×3,可用查表或上电时算一次矩阵指数;③降采样需求 —— 高速环(20kHz)本来就给了 ωₒ 巨大空间,「ωₒ 不够用」通常只发生在拿 1kHz 位置环硬扛大冲击的场合,此时应把 ADRC 下沉到速度环(2kHz+)。

控制环典型 fsωₒ 上限(fs/10)对应 ω_c(取 ωₒ/4)ESO 阶次建议
电流环10~20 kHz6280~12570 rad/s≈2000~3000 rad/s(充裕)一阶 LADRC(2 阶 ESO)
速度环1~5 kHz628~3140 rad/s150~800 rad/s二阶 LADRC(3 阶 ESO)
位置环0.5~2 kHz314~1257 rad/s80~300 rad/s二阶 LADRC / PD+前馈

面试怎么问:「ωₒ 能配到任意高吗?上限由什么决定?」——三层:①采样与离散(ωₒ≤fs/10,显式欧拉);②噪声(β₃=ωₒ³ 放大编码器量化噪声);③执行器(把噪声顶到电流里成啸叫)。答出任意两层即合格。

⚠️ 易错点:①单位混用 —— fs 是 Hz、ωₒ 是 rad/s,差 2π(前面易错点再次出现,因为这是真事故高发区);②用「预测-校正」顺序错误地展开欧拉 —— 更新 z₂ 时必须用本拍之前的 z₃、u 值,代码里顺手用了刚更新的 z₁ 会让离散化与设计不符,高 ωₒ 时直接发散;③中断里 ESO 和控制律不同频调用 —— 两者必须同频,或严格按多速率重推离散式。

6.2 浮点、定点与 STM32 上的耗时量级

是什么:一次 LADRC 计算的代价 ≈ ESO 的乘加次数 + 补偿除法。二阶 LADRC(三阶 ESO)约 30~40 次 FMA + 1 次除法;一阶约一半。

面试怎么问:「STM32G431 跑 20kHz 电流环,能不能塞进一阶 LADRC?算一笔账。」——答:G431 带 FPU,一阶 LADRC 约 0.5~1μs,加 FOC 本体约 10~15μs,20kHz 周期 50μs,占比 <30%,可以;若换 M0 就要定点化或降环频。

⚠️ 易错点:①除法用 b₀ 而不是 b₀ 的倒数 —— 初始化时算好 inv_b0 = 1/b0,运行期只做乘法(除法在 M4 上 ~14 周期,且定点化后根本没法除);②中断优先级里让 ESO 被高优先级任务打断 —— ESO 状态跨周期不一致等于隐式变步长;③调试时 printf 浮点拖垮实时性 —— 高频环里用 DMA 上传,别在环内做格式化输出。

7 完整 C 实现:一阶/二阶 LADRC 教学精简版(~80 行)

7.1 结构体 + init + calc 完整代码与站内版本对照

是什么:下面这份代码包含一阶(LADRC1)与二阶(LADRC2)两套结构体和计算函数,前向欧拉离散、参数运行时可改。与 00-01 3D 解剖页ADRC_Init/ADRC_Calc 单文件宏定义版相比:那边是「二阶专用、宏参数、零依赖」,适合直接抄进工程演示;本版是「一阶+二阶通用、结构体参数、含输出限幅与上一拍 u 缓存」,适合做在线整定上位机或多关节复用 —— 两版算法内核完全一致,可互移植。

/* ===================================================================
 * ladrc.c —— 一阶/二阶 LADRC 教学精简版(前向欧拉离散, float)
 * 依赖: 无(纯 float 运算) | 移植: 复制即用, 无动态内存
 * 带宽约束: w_o <= fs/10;  经验: w_o ≈ (3~5)*w_c
 * ================================================================ */
typedef struct {                 /* ---- 一阶: 对象 dy = f + b0*u ---- */
    float Ts, w_o, w_c, b0;      /* 周期 / 观测器带宽 / 控制带宽 / 增益 */
    float kp, inv_b0;            /* kp = w_c;  预先取倒数避免运行期除法 */
    float z1, z2;                /* z1: 输出估计   z2: 总扰动估计        */
    float u;                     /* 上一拍输出(ESO 更新要用)             */
    float u_max;                 /* 输出限幅                            */
} ladrc1_t;

typedef struct {                 /* ---- 二阶: 对象 ddy = f + b0*u ---- */
    float Ts, w_o, w_c, b0;
    float kp, kd, inv_b0;        /* kp = w_c^2;  kd = 2*w_c             */
    float z1, z2, z3;            /* z1: 位置  z2: 速度  z3: 总扰动估计   */
    float u;
    float u_max;
} ladrc2_t;

void ladrc1_init(ladrc1_t *a, float Ts, float w_o, float w_c,
                 float b0, float u_max)
{
    a->Ts = Ts;  a->w_o = w_o;  a->w_c = w_c;  a->b0 = b0;
    a->u_max = u_max;
    a->kp     = w_c;             /* 一阶: 极点统一配在 -w_c            */
    a->inv_b0 = 1.0f / b0;
    a->z1 = 0.0f;  a->z2 = 0.0f;  a->u = 0.0f;
}

void ladrc2_init(ladrc2_t *a, float Ts, float w_o, float w_c,
                 float b0, float u_max)
{
    a->Ts = Ts;  a->w_o = w_o;  a->w_c = w_c;  a->b0 = b0;
    a->u_max = u_max;
    a->kp     = w_c * w_c;       /* 二阶: (s+w_c)^2 = s^2 + 2w_c s + w_c^2 */
    a->kd     = 2.0f * w_c;
    a->inv_b0 = 1.0f / b0;
    a->z1 = 0.0f;  a->z2 = 0.0f;  a->z3 = 0.0f;  a->u = 0.0f;
}

/* -------- 一阶 LADRC: 每周期调用一次, v=目标, y=测量(已滤波) -------- */
float ladrc1_calc(ladrc1_t *a, float v, float y)
{
    float b1 = 2.0f * a->w_o;            /* 极点统一在 -w_o:            */
    float b2 = a->w_o * a->w_o;          /* (s+w_o)^2 = s^2+2w_o s+w_o^2 */
    float e, u0;

    e = a->z1 - y;                       /* 输出误差                    */
    a->z1 += a->Ts * (a->z2 - b1 * e + a->b0 * a->u);   /* ESO 欧拉更新  */
    a->z2 += a->Ts * (-b2 * e);
    u0 = a->kp * (v - a->z1);            /* 状态误差反馈(kp=w_c)        */
    a->u = (u0 - a->z2) * a->inv_b0;     /* 扰动补偿 u=(u0-z2)/b0       */
    if (a->u >  a->u_max) a->u =  a->u_max;   /* 限幅防饱和              */
    if (a->u < -a->u_max) a->u = -a->u_max;
    return a->u;
}

/* -------- 二阶 LADRC: v1=目标, v2=目标微分(前馈, 可为0) ------------ */
float ladrc2_calc(ladrc2_t *a, float v1, float v2, float y)
{
    float c1 = 3.0f * a->w_o;            /* 极点统一在 -w_o:            */
    float c2 = 3.0f * a->w_o * a->w_o;   /* (s+w_o)^3 展开系数          */
    float c3 = a->w_o * a->w_o * a->w_o;
    float e, u0;

    e = a->z1 - y;
    a->z1 += a->Ts * (a->z2 - c1 * e);
    a->z2 += a->Ts * (a->z3 - c2 * e + a->b0 * a->u);
    a->z3 += a->Ts * (-c3 * e);
    u0 = a->kp * (v1 - a->z1) + a->kd * (v2 - a->z2);
    a->u = (u0 - a->z3) * a->inv_b0;
    if (a->u >  a->u_max) a->u =  a->u_max;
    if (a->u < -a->u_max) a->u = -a->u_max;
    return a->u;
}

/* -------- 用法示例: 1kHz 位置环(整机下发 q_des/dq_des/tau_ff) ------ */
/* static ladrc2_t g_pos;                                            */
/* void pos_init(void){ ladrc2_init(&g_pos, 0.001f, 240.0f,          */
/*                               60.0f, 8.0f, 20.0f); }              */
/* void pos_1kHz(float q_des,float dq_des,float q)                   */
/* {  float iq = ladrc2_calc(&g_pos, q_des, dq_des, q);              */
/*    motor_set_iq(iq);      输出送电流环力矩指令  }                 */

代码四个细节,面试常被追问:

面试怎么问:「你的 LADRC 代码怎么处理输出饱和?」——答限幅三件套:控制量限幅、限幅后的 u 回写进 ESO(而不是裸 u₀−z₃)、必要时对 z₃ 补偿项也做权重衰减;只答「clamp 输出」是不完整的。

⚠️ 易错点:①z₁ 初始化成 0 而 y 非 0 —— 上电瞬间 e 很大,ωₒ 高时 z₃ 冲一记「虚拟扰动」,电机抽动一下;正确做法是首拍把 z₁=y、z₂=0(或用速度 0)、z₃=0 同步;②Ts 用宏写死但调用频率改了 —— 任何环频变更都要同步改 Ts;③float 直接和 0 比较做收敛判断 —— 浮点残余误差永远存在,给死区。

7.2 float 与 Q15 定点的选择建议

场景建议理由
STM32F4/G4/H7 等带 FPU 内核float 直用硬件浮点 1 周期乘加,1~2μs 算完,LADRC 不是算力瓶颈;可读性、可移植性最好
M0/M3 无 FPU、环频 ≤1kHzfloat 可接受软件浮点单次几十~百周期,1kHz 周期 1000μs 仍放得下,先跑通再优化
M0/M3、环频 ≥10kHz(电流环 ADRC)Q15/Q31 定点软浮点撑不住高频;定点乘加用 DSP 扩展指令单周期;但要做归一化与饱和检查(第 6.2 节)
调试/上位机侧永远 float整定、仿真、日志全用 float,只在下位机最后一公里定点化

开源实现可对照阅读:GitHub 上的 JcZou/ADRC_Lib(float 版 C 库)与 simorxb/ADRC-Pendulum-C(二阶 ADRC 摆杆示例,含 Python 绘图),见资源卡 R11/R12。

8 抗扰性能验证:突加负载曲线怎么读,PI vs ADRC 怎么选

8.1 突加负载扰动仿真/实测曲线的四步读法

怎么做:抗扰实验的标准做法:系统稳定跟踪某一中等幅值指令(速度环或位置环),在 t₀ 时刻突加/突卸负载(对关节即撞块、挂重物、或电流环里注入反向阶跃),记录输出响应。读曲线四步:

  1. 量跌落深度 Δ:扰动瞬间输出偏离稳态的最大幅度 —— 反映 ESO 估出扰动并补偿之前「扛」了多久,主要由 ωₒ 决定(ωₒ 高则浅);
  2. 量恢复时间 tr:从 t₀ 到回到 ±2% 稳态带的时间 —— 反映补偿之后 PD 拉回的速度,主要由 ω_c 决定;
  3. 看恢复过程形态:单调爬回 = 健康;来回振荡 = ω_c 过高或 b₀ 偏小;爬一半停住(残差)= 补偿不足,查 b₀ 或 z₃ 是否被限幅压住;
  4. 对照基线:同一工况跑原 PI,两条曲线叠一起 —— 没有基线的「ADRC 变好了」不可信。
t 输出(速度/位置) 稳态指令 t₀ 突加负载 PI: 跌落深 Δ₁ · 恢复慢 ADRC: 跌落浅 Δ₂ · 恢复快 PI(整定至临界良好) LADRC(同对象同限幅) 跌落深度 Δ 主要由 ωₒ 决定 · 恢复时间 tr 主要由 ω_c 决定 · 恢复形态诊断 b₀ 方向
图④ PI vs ADRC 突加负载对比(示意):两者阶跃跟踪差距不大,差距在扰动瞬间 —— ESO 在扰动「造成大错之前」就开始补偿,跌落更浅、恢复更快;交互版仿真见 00-01 页 ADRC 小节

面试怎么问:「ADRC 抗扰好,好在这条曲线的哪一段?为什么?」——答:好在扰动后的跌落与恢复段。PI 要等误差积分起来才反击,ADRC 的 ESO 从 u、y 的不一致里「抢先」估出扰动并前馈对消,所以跌落浅、恢复快;阶跃跟踪段两者可以调到接近。

8.2 PI vs ADRC 全面对比表:什么时候 ADRC 不值得上

对比项三环 PIDLADRC结论
阶跃响应调好后同样快调好后同样快打平
超调(有 TD/过渡过程时)PID 本体难消大误差超调TD 安排过渡,天然小超调ADRC 优
抗突发扰动误差驱动,滞后反击扰动前馈对消,跌落浅恢复快ADRC 明显优
参数鲁棒(负载/温度漂移)工况变了要重调总扰动兜底,一组参数管宽工况ADRC 优
调试成本(首次)3 参数,人人会调3 参数(ωₒ/ω_c/b₀),需理解机理PI 略优
计算量~5 次乘加一阶 ~15、二阶 ~35 次乘加PI 优(差距已不重要)
对测量噪声的敏感不用 D 则不敏感z₂/z₃ 微分本质,噪声大会起毛PI 略优

什么时候 ADRC 不值得(诚实清单):

面试怎么问:「ADRC 是不是全面优于 PID?什么时候你会拒绝用 ADRC?」——这是压力题,考察对适用边界的诚实:答出噪声、大时滞、算力三条拒绝理由,比背十条优点加分得多。

9 失效模式与排查:从症状反推参数

怎么做:ADRC 调试 90% 的问题落在「ωₒ、b₀、噪声」三处。把症状 → 原因 → 处理做成查表,现场照单抓药:

症状机理确认方法处理
观测器振荡/发散ωₒ 过高 × 显式欧拉:1−ωₒTs 跑出稳定域;或 Δωₒ 步进太猛z₁ z₂ 锯齿状自激,与输入无关;降 ωₒ 立刻消失降 ωₒ 至 ≤fs/10;或改 Tustin/后向欧拉;步进按 1.5× 逐档扫
z₃ 微分噪声(毛刺)β₃=ωₒ³ 放大编码器量化/采样噪声,以微分形式灌入 z₃静止时 z₃ 不为零且高频抖;z₃ 频谱集中在编码器量化频率提高编码器有效分辨率;y 先过 α-β/二阶低通;降 ωₒ;加大 fal 的 δ(非线性版)
b₀ 偏小:振荡/啸叫补偿过度,等效增益虚高(第 4.1 节)阶跃超调大、恢复来回摆;增大 b₀ 症状减轻增大 b₀(每次 ×1.5);确认未在饱和区辨识
b₀ 偏大:迟钝/残差补偿不足,扰动残留响应变「软」;稳态有固定残差;减小 b₀ 症状减轻减小 b₀;重做空载阶跃辨识;检查单位折算(rad/count、减速比)
上电瞬间抽动z₁ 初始化为 0,y 非 0,首拍误差巨大冲出假 z₃只在使能瞬间出现一次使能首拍同步 z₁=y、z₂=0、z₃=0;或使能前先「预跑」ESO 若干拍不输出
低速爬行/死区感静摩擦进入总扰动但变化太快,z₃ 跟不上;或输出限幅过紧换向瞬间速度凹陷;|u| 常贴 u_max提 ωₒ(留噪声裕量);放宽 u_max;速度环加摩擦前馈双管齐下

测量噪声预处理三原则(上 ADRC 之前先做):源头 —— 编码器线数/细分、采样同步(在 PWM 中央对齐点采电流),比任何滤波都值钱;②前置滤波 —— 给 y 过一个截止频率 ≈ 5ωₒ 的低通,滤波器本身相位滞后要计入预算;③留诊断口 —— z₁ z₂ z₃ 与 u 全部走 DMA 上位机画曲线,盲调 LADRC 等于蒙眼开环。

面试怎么问:「现场 LADRC 电机啸叫,你按什么顺序查?」——标准顺序:①确认啸叫频率(开关频率=电气问题;几十~几百 Hz=控制环)②降 ωₒ 观察(消失→观测器噪声/稳定域问题)③看 z₃ 毛刺(毛刺大→编码器/滤波问题)④查 b₀ 方向(振荡→偏小)⑤都无效→回滚 PI 基线,逐项排除。

⚠️ 易错点:把「啸叫」一律归因 ωₒ 过高 —— 电流采样相序错、PWM 死区补偿缺失同样啸叫,先排除硬件层,再动控制参数;否则会把好参数越调越坏。

10 业界应用与高频考问:关节电机里的 ADRC 现状

10.1 宇树 / 优必选 / 智元的关节控制里,ADRC 处在什么位置

是什么:主流整机厂目前普遍采用「三环 PID 底座 + 选择性 ADRC 增强 + 上层 MPC/WBC」的混合架构(即 04-09 页定义的变体 C),而非「全环 ADRC」:

完整的「三环 PID → 三环 ADRC」工程变体表与五阶段升级路线,直接见 04-23 通信与控制算法升级路线页(不在此重复);未来 3~5 年的判断是「底层 ADRC 化 + 上层 MPC/RL 化」的混合架构,关节 MCU 只需做好「接指令 + 本地 ADRC 执行」。

面试怎么问:「宇树的关节用的是 ADRC 吗?为什么大厂不全部上 ADRC?」——答混合架构现状 + 三条工程理由:①PID 三环已满足大部分指标,只补短板性价比高;②全 ADRC 调试与维护成本高,量产要为「产线工人能调」负责;③上层 MPC/RL 前馈已消化大部分可建模扰动,底层只需处理残余。

10.2 面试高频四连问:标准答题框架

Q1:ADRC 和 PID 的本质区别是什么?
三层作答:①信息来源 —— PID 只用「输出误差」这一个标量;ADRC 用 u 与 y 重构出全部状态 + 总扰动,信息量大一个量级。②处理不确定性的方式 —— PID 靠参数鲁棒性「扛」,ADRC 靠 ESO 估计 + 前馈「对消」。③结构 —— LADRC 线性化后可视为「PD + 扰动前馈 + 状态滤波」的组合,与 2DOF-PID 有深刻联系,但整定变量是物理意义明确的带宽,不是抽象增益。
Q2:ESO 为什么能估计「未知」扰动?它偷偷用了什么假设?
核心机制:把总扰动扩张为第 n+1 个状态并入观测器,用「模型预测与测量的不一致」(e=z₁−y)通过 β 增益把它反解出来。两个前提必须主动说出:①扰动缓变(ḟ≈0 或变化率有界)—— 这决定了「能跟踪多快的扰动」由 ωₒ 决定;②b₀ 已知(至少量级正确)—— 否则 ESO 分不清「u 的功劳」和「扰动的捣乱」。
Q3:ωₒ 和 ω_c 到底怎么定?给一个可复现的流程。
ω_c 按需求正向定:闭环带宽需求(位置环 30~150 rad/s 量级)→ 起点取一半,从小往大扫到轻微振荡回退 30%。ωₒ 按约束反向定:上限 min{(3~5)·ω_c 的跟踪需求, fs/10 的离散/噪声上限},从 3ω_c 起只增不减地扫,以 z₃ 平滑度 + 无啸叫为停止判据。最后 b₀ 微调按「振荡增大、迟钝减小」口诀。
Q4:ADRC 和状态观测器(04-17)、MPC(04-16)是什么关系?
与龙伯格/KF:ESO 就是「把扰动增广成状态」的龙伯格观测器;线性 ESO 与 KF 稳态等价(KF 的 Q/R 折算出等效增益)。04-17 讲的是「估状态」,ADRC 多走一步「估了就拿去补偿」。②与 MPC:MPC 靠精确模型向前滚动优化,模型错了全错 —— 工程上常用「ADRC 底层抗扰 + MPC 上层规划」分层互补:ADRC 消化快扰动,MPC 管轨迹与约束;也有研究把 ESO 嵌进 MPC 用估计状态替代真实状态(输出反馈 MPC)。③与 04-17 的 SMO/HFI 无感:同为观测器家族,但目标不同 —— 无感观测器估「反电动势/转子位置」,ESO 估「总扰动」。

更多真题与逐题解析见 06-11 保研复试面试题库的 adrc 学科 8 题(含「b₀ 偏小会怎样」等变形题)。

11 本节自测

1. ESO 里被「扩张」进来的第 n+1 个状态是什么?
💡 ESO 的「扩张」就是把总扰动 f 当成第 n+1 个状态(二阶对象里是 x₃=f),由 u、y 驱动观测器估出 z₃ 并补偿;b₀ 是已知量(估计值),不是被扩张的状态。
2. 二阶对象的 LADRC,观测器增益 β₁ β₂ β₃ 按带宽法应取?
💡 三阶 ESO 极点统一配在 −ωₒ:(s+ωₒ)³=s³+3ωₒs²+3ωₒ²s+ωₒ³,对比系数得 β₁=3ωₒ、β₂=3ωₒ²、β₃=ωₒ³。注意 2ωₒ/ωₒ² 是一阶对象(二阶 ESO)的取法,别混。
3. 控制周期 1kHz 的位置环,观测器带宽 ωₒ 的工程上限大约是?
💡 fs=1000Hz,ωₒ≤fs/10=100Hz,换成弧度制 2π×100≈628 rad/s。B 选项是把 Hz 当 rad/s 的典型单位事故;ωₒ 过高时显式欧拉离散发散 + 噪声放大。
4. LADRC 阶跃响应出现超调振荡、电机啸叫,按「b₀ 方向口诀」应如何调整?
💡 口诀:振荡/啸叫 → b₀ 偏小(补偿过度、等效增益虚高)→ 增大 b₀;迟钝/爬行 → b₀ 偏大(补偿不足)→ 减小 b₀。同时检查 ωₒ 是否超出噪声/离散裕量。
5. 以下哪种场景最不推荐上 ADRC?
💡 ESO 的 z₂/z₃ 是微分本质,噪声大时先于扰动毁掉性能;纯时滞对象超出「缓变扰动」假设,估计总是慢半拍 —— 这两类是 ADRC 的适用边界。A/B/D 恰是 ADRC 的优势场景。
📌 本节小结:ADRC 用「估计 + 补偿」替代 PID 的「误差事后补救」:TD 安排过渡过程并产出无噪声放大的微分;ESO 把总扰动扩张为第 n+1 个状态实时估出 z₃;控制律 u=(u₀−z₃)/b₀ 把对象实时改造成积分器链再用 PD 控制。高志强带宽法把全部增益压缩到 ωₒ、ω_c、b₀ 三个参数:ω_c 按需求正向定,ωₒ≥3ω_c 且 ≤fs/10 反向定,b₀ 按空载阶跃辨识、按「振荡增大、迟钝减小」微调。嵌入式落地三件事:前向欧拉 + 限幅回写 ESO、inv_b0 预倒数、带 FPU 直接 float(1~2μs/次)。它买的是「不确定性保险」—— 噪声大、大时滞、算力弱时别买。
🤔 思考题: 1. 你的关节位置环若把 ADRC 放在位置环、速度/电流环仍是 PI,总扰动里「速度环带宽不足」造成的滞后会被 ESO 当成扰动补偿 —— 这会不会掩盖速度环本身的整定问题?边界在哪?
2. ωₒ 提高一倍,抗扰跌落深度大约怎么变?编码器量化噪声在 z₃ 上又怎么变?试着用 β₃=3ωₒ³ 定量解释。
3. 若整机 MPC 已下发 τ_ff 重力/动力学前馈,关节内的 ESO 还需要估「重力」吗?前馈与 ESO 补偿同时存在会不会「双重补偿」?z₃ 稳态值会告诉你什么?

12 参考来源与延伸资源

以下资源均经联网核实可达(2026-09)。⭐ 标注为强烈推荐:R1 是理论原著,R2 是带宽法原始论文,R9 是高志强本人 12 集入门讲座。

📖
⭐ R1 · 韩京清《自抗扰控制技术:估计补偿不确定因素的控制技术》
ADRC 理论原著(国防工业出版社 2008,豆瓣 9.9 分)。TD/ESO/NLSEF 的原始推导、fhan/fal 函数出处、非线性机理的完整论述 —— 想回答「韩京清为什么坚持非线性」,只此一本。
豆瓣图书页⭐ 理论原著进阶
📄
⭐ R2 · Gao, "Scaling and Bandwidth-Parameterization Based Controller Tuning" (ACC 2003)
高志强带宽参数化的原始论文(美国控制会议 ACC,DOI 10.1109/ACC.2003.1242516,被引 4000+)。LADRC 三参数整定、ωₒ≈(3~10)ω_c 准则均出自此文;克利夫兰州立大学机构库页面。
ACC 2003 论文机构库正版⭐ 带宽法源头
📄
R3 · 同上论文 IEEE Xplore 正式版
IEEE Xplore 收录版(需机构订阅)。引用此论文时的规范出处页,与 R2 内容相同。
IEEE Xplore正式出版版
🎬
⭐ R4 · B站《ADRC 入门讲座(高志强,2015 年 12 月)》12 集
高志强本人主讲的 ADRC 入门系列(「自抗扰控制-ADRC」账号发布,12 集连续讲座)。从 PID 剖析到 ESO 带宽法,中文 ADRC 视频第一站,与本书页 1~3 节一一对应。
B站视频⭐ 作者亲授入门必看
🎬
R5 · B站《快速认识 LADRC 与 LADRC 参数整定方法》(比 PID 好用系列)
面向工程的 LADRC 快速上手与整定演示,配合本书页第 5 节整定流程食用;同系列还有 ESO 应用解析续集。
B站视频整定演示
🎬
R6 · B站《二阶自抗扰控制的原理及其带宽法 ADRC Matlab/Simulink》(此梦千寻 A5)
二阶 LADRC 的 Simulink 建模与带宽法整定实操,公众号提供仿真文件;同 UP 主 A1 集讲 ADRC 基本原理、A2 集讲一阶 ADRC 仿真,适合跟着搭一遍仿真再写 C。
B站视频Simulink 实操
📝
R7 · 知乎专栏《自抗扰控制 - 入门》
从 PID 局限讲到 TD/ESO/非线性反馈,并引入观测器带宽、控制器带宽的 LADRC 设计思路,中文社区口碑较好的入门长文。
知乎专栏入门长文
📝
R8 · 知乎专栏《控制算法手记 —— 自抗扰控制的几点思考》
偏工程视角的冷静分析:ESO 观测什么、补偿边界在哪、与 PID/前馈的关系,适合读完本书页后对照「哪些宣传夸大了、哪些是真的」。
知乎专栏工程思辨
💻
⭐ R9 · CSDN《自抗扰控制(ADRC)原理与 STM32 硬核部署指南》
面向 STM32 的 ADRC 部署实战:角速度环 LADRC、嵌入式工程细节(非阻塞解析、寄存器输出等),与本书页第 6~7 节的嵌入式落地互补。
CSDN 博客⭐ STM32 实战嵌入式部署
💻
R10 · CSDN《从 PID 到 ADRC:原理、公式推导、C 语言实现与电机调参指南》
一条龙长文:PID → ADRC 的公式推导、C 实现、电机调参,TD 信号特性讲得细,可作为本书页的「另一份推导视角」对照阅读。
CSDN 博客推导+C实现
💻
R11 · CSDN《ADRC 算法及参数整定(调参)心得体会》
一线调参经验帖:参数扫描顺序、常见症状与对应处理,与本书页第 9 节排查表互相印证。
CSDN 博客调参经验
🧩
R12 · GitHub: JcZou/ADRC_Lib(C 语言 ADRC 库,MIT)
纯 C 的 ADRC 库(adrc.c/adrc.h,float 版),36★/23 fork;适合与本书页 ladrc.c 对照学习「别人的结构体怎么组织」。
GitHub 开源C 库
🧩
R13 · GitHub: simorxb/ADRC-Pendulum-C(二阶 ADRC 摆杆 C 示例,MIT)
用 C 实现二阶 ADRC 控制摆杆模型(10ms 采样),Python 绘图验证 —— 想在 PC 上复现「完整闭环再移植 MCU」的完整流程,这是最小可跑样例。
GitHub 开源可跑样例
📘
⭐ R14 · MathWorks《Active Disturbance Rejection Control》官方文档(Simulink Control Design)
MATLAB/Simulink 官方 ADRC 概念页与 ADRC 模块说明(内置 ESO 带宽法整定,支持代码生成部署);附 SEPIC/Boost/水箱等官方示例,中文版在 ww2.mathworks.cn 同路径。
官方文档⭐ 仿真到代码生成
📄
R15 · 《一种新型控制方法 —— 自抗扰控制技术及其工程应用综述》
中文核心期刊综述:ADRC 发展脉络、工程应用全景与 LADRC 带宽法地位,写论文/做调研时的引言素材库。
学术综述期刊全文
📅 资源核实说明:以上 15 条链接于 2026-09 通过搜索引擎与网页抓取逐一核实可达;其中原 MathWorks /help/control/ug/ 路径已迁移至 /help/slcontrol/ug/(本书页采用新地址)。站内配套:00-01 页(ESO 推导 + STM32 代码 + PI/ADRC 交互仿真)、04-09 页(三环 PID → ADRC 变体表)、06-11 页(ADRC 面试 8 题)。