惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

爱范儿
爱范儿
Y
Y Combinator Blog
博客园 - Franky
D
Docker
B
Blog RSS Feed
M
MIT News - Artificial intelligence
雷峰网
雷峰网
博客园 - 司徒正美
人人都是产品经理
人人都是产品经理
宝玉的分享
宝玉的分享
S
SegmentFault 最新的问题
GbyAI
GbyAI
Recent Announcements
Recent Announcements
Martin Fowler
Martin Fowler
H
Hackread – Cybersecurity News, Data Breaches, AI and More
MyScale Blog
MyScale Blog
B
Blog
H
Help Net Security
Microsoft Security Blog
Microsoft Security Blog
WordPress大学
WordPress大学
Vercel News
Vercel News
The Cloudflare Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Google DeepMind News
Google DeepMind News

博客园 - longyue

[BF学院_卷1] -- 第30讲:mixTable() 总结 —— Mixer 完整控制模型 [BF学院_卷1] -- 第29讲:applyMixToMotors() —— 最终 Motor Output 生成 [BF学院_卷1] -- 第28讲:applyMixerAdjustment() —— 为什么 Mixer 需要重新分配控制权限 [BF学院_卷1] -- 第27讲:PID Output 如何进入 Mixer —— 从控制需求到 motorMix [BF学院_卷1] -- 第26讲:calculateThrottleAndCurrentMotorEndpoints() —— Mixer 如何确定油门基础范围 [BF学院_卷1] -- 第25讲:mixTable() 总览 —— Mixer 在控制循环中的位置 [BF学院_卷1] -- 第24讲:mixer_init.c —— 飞控启动时如何准备 Mixer [BF学院_卷1] -- 第23讲:Mixer 数学模型 —— motorMixer_t 如何形成 Motor Output [BF学院_卷1] -- 第22讲:Betaflight 如何描述 Mixer —— mixer.h 数据结构 [BF学院_卷1] -- 第21讲:四旋翼为什么可以通过电机控制姿态 —— Mixer 背后的物理基础 [BF学院_卷1] -- 第20讲:从 PID Output 到 Motor Command(电机指令)——为什么飞控需要 Mixer [BF学院_卷1] -- 第19讲:PID Controller(PID控制器)——飞控到底如何理解误差并控制飞机? [BF学院_卷1] -- 第18讲:PID Controller 的最后一环——为什么飞控还需要 Feedforward(前馈控制)? [BF学院_卷1] -- 第16讲:I Term(积分控制项)——飞机为什么总是差一点? [BF学院_卷1] -- 第14讲:Rate Error(角速度误差)——PID 真正控制的到底是什么? [BF学院_卷1] -- 第15讲:P Term(比例控制项)——飞控是如何利用误差开始控制飞机的? [BF学院_卷1] -- 第13讲:Outer Loop 的终点——为什么还要读取 Current Angular Rate(当前角速度)? [BF学院_卷1] -- 第十二讲:Yaw Compensation(偏航补偿) [BF学院_卷1] -- 第12讲脚本 [BF学院_卷1] -- 第十一讲:Current Angular Rate(当前角速度)——飞控怎样知道飞机现在转得有多快? [BF学院_卷1] -- 第十讲:Angle Error(姿态角误差)如何变成 Desired Angular Rate(目标角速度) [BF学院_卷1] -- 第九讲:Current Angle(当前姿态角)遇见 Target Angle(目标姿态角) [BF学院_卷1] -- 第八讲:飞手打杆以后,飞控首先得到什么? [BF学院_卷1] -- 第七讲:为什么 Pitch Flip 只在 180° 看起来正确 [BF学院_卷1] -- 第7讲脚本 [BF学院_卷1] -- 第6讲:为什么 Pitch Flip 会骗人 [BF学院_卷1] -- 第6讲脚本 [BF学院_卷1] -- 第五讲:第一次修正——Pitch Flip 为什么看起来有效 [BF学院_卷1] -- 第5讲脚本 - longyue [BF学院_卷1] -- 第4讲:为什么"绕飞机自己转"不等于"朝世界转" - longyue
[BF学院_卷1] -- 第17讲:D Term(微分控制项)——飞控如何提...
longyue · 2026-08-03 · via 博客园 - longyue

第17讲:D Term(微分控制项)——飞控如何提前感知运动变化?


本讲知识点

  • PID Controller(PID控制器)中的 D Term(微分控制项)解决什么问题?
  • 为什么 P Term 和 I Term 仍然无法提前抑制飞机变化?
  • D Term 为什么关注角速度变化趋势?
  • Betaflight 如何通过陀螺仪数据计算 D Term?
  • gyroRateDterm(D项使用的角速度数据)与 Current Angular Rate(当前角速度)的区别
  • D Term 与 Feedforward(前馈控制)的关系
  • D Term 在 PID 控制链中的最终职责

本讲对应 Betaflight 源码

文件:

src/main/flight/pid.c

函数:

pidController()

本讲涉及源码:

const float delta = - (gyroRateDterm[axis] - previousGyroRateDterm[axis]) * pidRuntime.pidFrequency;

float preTpaD = pidRuntime.pidCoefficient[axis].Kd * delta;

pidData[axis].D = preTpaD * pidRuntime.tpaFactor;

本讲重点分析:

gyroRateDterm[axis] - previousGyroRateDterm[axis]

这一部分如何体现:

当前运动变化

↓

未来趋势预测

↓

提前抑制运动变化

回顾上一讲

上一讲中,我们建立了:

I Term(积分控制项)

它通过累计长期存在的Rate Error(角速度误差), 解决飞机总是差一点的问题。

控制链继续推进:

Rate Error

↓

P Term

↓

I Term

↓

D Term

本讲学习目标

即使加入 P Term 和 I Term,飞机仍可能因为运动惯性出现:已经接近目标,但是仍然继续增加旋转速度。

因此,PID Controller(PID控制器)还需要判断:变化正在发生得多快。

这正是 D Term(微分控制项)负责解决的问题。

本讲进入 D Term(微分控制项), 理解飞控如何通过观察角速度变化趋势,提前抑制飞机过冲和快速变化。


飞机不仅需要知道误差,还需要知道变化趋势

P Term 关注:现在差多少。

例如:

目标角速度:300°/s

当前角速度:200°/s

误差:100°/s

P Term 会增加控制输出。

但是,如果飞机正在快速加速:

200°/s -> 250°/s -> 290°/s

虽然当前误差仍然存在,但是飞机已经正在快速接近目标。

如果继续按照误差增加输出,飞机可能因为惯性,超过目标。

因此,控制器还需要知道:

误差正在扩大?还是正在快速减少?

这就是 D Term 引入的原因。


D Term 的核心思想:关注变化速度

D Term 的本质不是观察:现在是多少。

而是观察:变化有多快。

数学上:D Term = 变化量 ÷ 时间

也就是:对当前状态变化趋势进行预测。

在飞控中,D Term 主要观察:

Angular Rate(角速度)随时间的变化。

也就是:

角速度增加很快 -> 提前降低控制输出

角速度变化稳定 -> 减少额外影响

回到 Betaflight 源码

首先观察:

const float delta = - (gyroRateDterm[axis] - previousGyroRateDterm[axis]) * pidRuntime.pidFrequency;

这一行可以拆开理解。

首先, gyroRateDterm[axis] 表示:当前用于 D Term 计算的角速度。

然后, previousGyroRateDterm[axis]表示:上一次 PID 循环时的角速度。

两者相减:gyroRateDterm[axis] - previousGyroRateDterm[axis] 得到:这一瞬间角速度变化了多少。

例如:

上一周期:200°/s

当前周期:220°/s

变化:+20°/s

说明:飞机正在加速旋转。


为什么需要乘以 pidFrequency?

根据 PID 控制理论, D Term(微分控制项)关注的不是当前误差是多少, 而是误差正在变化得多快。

在连续控制系统中,微分项表示:

误差变化量 ÷ 时间变化量

也就是:

D Term ≈ Kd × (Δerror / Δt)

其中:

Δerror 表示误差发生了多少变化;

Δt 表示变化发生所经过的时间。

但是,Betaflight运行在数字控制系统中, 飞控不会连续观察飞机状态,而是在固定频率下:

读取传感器数据;

↓

执行PID计算;

↓

输出控制量。

因此,源码中需要使用离散方式近似连续微分。

也就是:

变化量 ÷ 采样时间 --> 变化速度

而 PID 运行频率:

pidFrequency 表示 1秒钟内PID计算执行多少次。

因此:

pidFrequency = 1 / Δt

所以:

Δerror / Δt 等价于 Δerror × pidFrequency

这也是源码中:

const float delta = - (gyroRateDterm[axis] - previousGyroRateDterm[axis]) * pidRuntime.pidFrequency;

的数学来源。

其中, gyroRateDterm[axis] 表示 当前采样周期内,陀螺仪角速度数据。

而 previousGyroRateDterm[axis] 表示 上一次PID计算周期中的角速度数据。

两者相减:

当前角速度 - 上一次角速度 -> 角速度变化量

也就是 Δerror

再乘以 pidRuntime.pidFrequency 以后,就与刚才的公式对上了。

也就是,飞控知道:

飞机旋转速度正在增加还是减少;

以及增加或减少得有多快。

这正是 D Term(微分控制项)能够预测飞机运动趋势的基础。

同时,源码采用:

Δerror × pidFrequency

而不是:

Δerror / Δt

还有一个工程原因:

嵌入式控制系统需要高频实时运行。

乘法运算通常比除法运算更加高效,因此提前计算:

pidFrequency = 1 / Δt

然后在PID循环中直接使用:

变化量 × pidFrequency

可以减少实时计算负担。

因此:

pidRuntime.pidFrequency

并不是额外增加的控制参数。

它的作用是:

把离散采样得到的角速度变化量,转换成为实际的变化速率。

这就是 Betaflight 中 D Term 计算中乘以 pidFrequency 的真正原因。


为什么 delta 前面有负号?

源码:

const float delta = -(...)

原因是:D Term 的作用是抵抗变化趋势。

如果飞机角速度正在快速增加,那么 D Term 希望产生:

反方向控制力

降低继续增加的趋势。

因此:

变化趋势 -> 反向修正

这就是负号存在的原因。


Kd 如何参与 D Term?

源码:

float preTpaD = pidRuntime.pidCoefficient[axis].Kd * delta;

其中, Kd 表示 D Term 增益。

它决定:

对于变化趋势,控制器反应多强。

如果 Kd 较大, 更敏感地抑制快速变化。

如果 Kd 较小, D Term 作用较弱。

因此:

D输出 = 变化趋势 × Kd

D Term 与陀螺仪数据

需要注意, D Term 使用:

gyroRateDterm[axis]

而不是简单直接使用:

gyroRate

原因是:D Term 对高频变化非常敏感。

陀螺仪中的噪声:

小幅快速变化

经过微分以后会被放大。

因此 Betaflight 会对 D Term 使用的数据进行专门处理。

例如:

  • D Term 专用滤波;
  • D Term Lowpass Filter;
  • D Term Notch Filter。

目的:

保留真实运动变化,减少噪声变化。

D Term 与 Feedforward 的区别

两者都具有:

提前响应

的特点。

但是解决的问题不同。

Feedforward(前馈控制):

飞手刚打杆

↓

提前知道期望变化

↓

提前输出控制

关注目标变化。


D Term:

飞机已经开始运动

↓

检测变化趋势

↓

提前抑制变化

关注:

实际运动变化。

简单理解:

Feedforward:提前推动。

D Term:提前刹车。

两者共同作用:

更快响应 + 更稳定停止。

本讲小结

本讲完成了 PID Controller(PID控制器)中 D Term(微分控制项)的建立。

D Term 与 P Term、I Term 不同,它并不关注当前误差大小,而关注飞机旋转速度变化趋势。。

Betaflight 通过比较:

当前 gyroRateDterm 与 上一周期 gyroRateDterm

得到角速度变化量,再结合:Kd

生成 D Term 输出。

至此,PID 三个基础控制项已经全部建立:

P Term:解决现在差多少。

I Term:解决过去累计差多少。

D Term:解决变化趋势有多快。

下一讲预告

下一讲,我们将进入:

Feedforward(前馈控制)

理解飞控如何直接利用飞手输入变化,提前产生控制响应。