1. 项目概述:当ADRC遇上四旋翼
第一次接触四旋翼ADRC(自抗扰控制)时,看着前辈们对着屏幕上一堆参数反复微调,嘴里念叨着"这个观测器带宽再调大点"、"TD环节的跟踪速度不够",确实有种看风水先生摆弄罗盘的错觉。直到自己亲手推导出滚转通道的角加速度方程,才发现这套看似玄学的控制方法背后,藏着精妙的数学模型和工程智慧。
ADRC的核心魅力在于它不依赖精确的数学模型——这对受复杂气动干扰的四旋翼简直是天作之合。想象一下:当你的无人机遭遇突风扰动时,传统PID需要精确知道风力矩大小才能有效补偿,而ADRC的扩张状态观测器(ESO)却能实时"看到"这些扰动并自动抵消。这种"遇强则强"的特性,正是我们在复杂环境下依然能保持稳定姿态的关键。
2. 核心原理拆解:从微分方程到抗扰策略
2.1 滚转通道动力学建模
四旋翼的滚转运动本质上是由电机力矩差驱动的刚体旋转。设滚转角为φ,根据欧拉方程可得:
math复制J_x\ddot{\phi} = l(F_2 - F_4) - K_f\dot{\phi} + d(t)
其中:
- J_x:绕x轴的转动惯量
- l:电机到质心的力臂长度
- F_2,F_4:对角电机的拉力
- K_f:空气阻尼系数
- d(t):集总扰动(包含模型误差、气流干扰等)
这个看似简单的方程已经揭示了控制难点:d(t)作为时变扰动无法精确建模,而传统PID恰恰需要依赖精确模型才能设计补偿项。
2.2 ADRC的三重防御体系
ADRC的解决方案是构建三层防御:
- 跟踪微分器(TD):为指令信号安排合理的过渡过程,避免超调
python复制# 离散TD实现示例 def TD(v, v_last, h): fh = fhan(v - v_last, v_last, r, h) return v_last + h*fh - 扩张状态观测器(ESO):将模型不确定性和外部扰动统一视为"总扰动"进行实时估计
math复制其中z₃就是被估计出的总扰动\begin{cases} \dot{z}_1 = z_2 - \beta_{01}e \\ \dot{z}_2 = z_3 - \beta_{02}fal(e,\alpha_1,\delta) + bu \\ \dot{z}_3 = -\beta_{03}fal(e,\alpha_2,\delta) \end{cases} - 非线性状态误差反馈(NLSEF):用非线性组合取代PID的线性加权
math复制u_0 = k_p fal(e_1,\alpha,\delta) + k_d fal(e_2,\alpha,\delta)
关键洞见:ESO的β参数选择遵循"带宽参数化"原则——观测器带宽ω₀越大,扰动估计越及时但噪声敏感度越高。经验公式β₁=3ω₀, β₂=3ω₀², β₃=ω₀³
3. 参数整定实战:从玄学到科学
3.1 调参路线图
按照"先内后外"的原则分阶段调试:
-
ESO参数整定
- 初始带宽ω₀取系统带宽的3~5倍
- 通过阶跃响应观察扰动估计速度
- 典型问题:观测值振荡→降低ω₀;响应滞后→提高ω₀
-
NLSEF参数整定
- 先设α=0.5, δ=0.1作为起点
- 调整kp时关注动态响应速度
- 调整kd时关注超调量
-
TD参数整定
- 速度因子r决定跟踪快慢
- 滤波因子h影响平滑程度
3.2 调参辅助工具
python复制# 参数扫描自动化脚本框架
def param_scan(drone, param_range):
results = []
for value in param_range:
drone.adrc.set_params(omega=value)
response = drone.step_test()
results.append(calculate_metrics(response))
return find_optimal(results)
避坑指南:地面测试时给ω₀设上限(如30rad/s),避免电机高频振荡烧毁电调。实测中遇到过因ESO带宽过高导致电机发出刺耳鸣叫的案例!
4. 代码实现细节:从公式到飞控
4.1 离散化实现要点
飞控通常在1kHz频率下运行,需特别注意:
c复制// ESO离散化示例(stm32 hal库)
void ESO_Update(ADRC_TypeDef *adrc, float y, float u) {
float e = adrc->z1 - y;
adrc->z1 += adrc->h * (adrc->z2 - adrc->beta01 * e);
adrc->z2 += adrc->h * (adrc->z3 - adrc->beta02 * fal(e,0.5,0.1) + adrc->b * u);
adrc->z3 += adrc->h * (-adrc->beta03 * fal(e,0.25,0.1));
}
4.2 抗饱和处理
执行器饱和是实际工程中的高频问题:
math复制u = \begin{cases}
u_{max} & \text{if } u_0 - \frac{z_3}{b} > u_{max} \\
u_{min} & \text{if } u_0 - \frac{z_3}{b} < u_{min} \\
u_0 - \frac{z_3}{b} & \text{otherwise}
\end{cases}
5. 实测效果对比:ADRC vs PID
在自建测试平台上的对比数据:
| 指标 | PID控制 | ADRC控制 |
|---|---|---|
| 阶跃响应超调量 | 15% | <5% |
| 抗突风扰动恢复时间 | 0.8s | 0.3s |
| 参数敏感性 | 高 | 低 |
| 建模依赖性 | 强 | 弱 |
特别在室内飞行测试中,当人为用风扇制造扰动时,ADRC控制的无人机表现出明显的"韧性"——姿态误差幅度减小40%以上,且不会出现PID典型的持续振荡现象。
6. 进阶优化方向
6.1 自适应带宽策略
根据飞行状态动态调整ω₀:
math复制\omega_0 = \begin{cases}
30 & \text{高速机动} \\
15 & \text{悬停} \\
20 & \text{常规飞行}
\end{cases}
6.2 基于Q学习的参数优化
构建强化学习框架自动调参:
python复制class ADRC_Agent:
def __init__(self):
self.memory = deque(maxlen=1000)
def remember(self, state, action, reward):
self.memory.append((state, action, reward))
def act(self, state):
# 输出参数调整建议
return np.clip(self.model.predict(state), -1, 1) * scale_factor
调参过程中发现一个有趣现象:当故意将初始参数设得很差时,ADRC往往还能保持基本稳定,而PID可能直接失控。这种鲁棒性正是工程应用中最珍贵的特性。后来在飞控代码里加入了参数异常检测机制——当ESO估计的扰动值持续超过阈值时自动触发保护逻辑,这个改进让我们在野外测试中成功避免了好几次炸机。