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

推荐订阅源

有赞技术团队
有赞技术团队
Martin Fowler
Martin Fowler
N
Netflix TechBlog - Medium
WordPress大学
WordPress大学
罗磊的独立博客
H
Help Net Security
MongoDB | Blog
MongoDB | Blog
A
About on SuperTechFans
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
D
Docker
云风的 BLOG
云风的 BLOG
Microsoft Security Blog
Microsoft Security Blog
Blog — PlanetScale
Blog — PlanetScale
P
Proofpoint News Feed
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
I
InfoQ
J
Java Code Geeks
博客园 - 聂微东
大猫的无限游戏
大猫的无限游戏
Engineering at Meta
Engineering at Meta
美团技术团队
小众软件
小众软件
Stack Overflow Blog
Stack Overflow Blog
C
Check Point Blog

博客园 - 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] -- 第18讲:PID Controller 的最后一环——为什么飞控还需要 Feedforward(前馈控制)? [BF学院_卷1] -- 第17讲:D Term(微分控制项)——飞控如何提前感知运动变化? [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] -- 第19讲:PID Controller(PID控制器)——飞控...
longyue · 2026-08-03 · via 博客园 - longyue

第19讲:PID Controller(PID控制器)——飞控到底如何理解误差并控制飞机?


本讲知识点

  • 为什么 PID Controller(PID控制器)是飞控最核心的控制算法之一?
  • PID 为什么不是“让飞机达到目标”,而是“不断修正误差”?
  • P Term(比例控制项)、I Term(积分控制项)、D Term(微分控制项)分别解决什么问题?
  • 为什么单独使用 P、I、D 中任何一项都无法完成稳定控制?
  • Betaflight 中 PID 四个控制项:
    • P Term
    • I Term
    • D Term
    • Feedforward(前馈控制)
      分别承担什么控制职责?
  • 从日常直觉到飞控源码,建立完整 PID 控制思维。

本讲对应 Betaflight 控制链位置

前面的课程中,我们已经完成了 PID Controller(PID控制器)内部各控制项的建立:

Rate Error(角速度误差)

↓

P Term(比例控制项)

↓

I Term(积分控制项)

↓

D Term(微分控制项)

↓

Feedforward(前馈控制)

其中:

P Term:解决现在差多少。

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

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

Feedforward:提前响应未来输入变化。

但是,到目前为止,我们更多是在分别理解每一个控制项。

本讲我们暂时离开源码细节,站在整个PID控制器的角度,重新回答一个最核心的问题:

PID 到底是什么?

回顾之前的学习

之前的课程中,我们已经逐步建立了:

飞手输入

↓

目标姿态

↓

目标角速度

↓

当前角速度

↓

Rate Error(角速度误差)

↓

PID Controller(PID控制器)

↓

电机控制量

同时,我们也已经知道,PID Controller(PID控制器)真正接收的,

不是目标值,也不是当前值,

而是目标值与当前值之间的差距,也就是Error(误差)。

本讲将在这个基础上,把 P、I、D 和 Feedforward 重新组合起来,形成完整的 PID 控制思想。


一个生活中的问题:如何控制汽车速度?

为了理解 PID,我们先暂时离开飞机。

假设,我们正在驾驶汽车。

道路限速:

目标速度:100 km/h

但是现在汽车速度:

当前速度:70 km/h

两者之间存在:

速度误差:30 km/h

也就是说汽车还差 30 km/h。

现在问题来了,如果让你控制油门,你应该怎么做?


最简单的方法:看到差多少,就踩多少油门

直觉上,差得越多,踩油门越大。

例如:

速度:70 km/h

目标:100 km/h

差距:30 km/h

于是,大力踩油门。

如果:

速度:95 km/h

目标:100 km/h

差距:5 km/h

那么,轻踩油门。

这个思想就是:

P Term(比例控制项)。

P Term(比例控制项):现在差多少,就修正多少

P Term 的核心思想非常简单:当前误差越大,控制输出越大。

数学关系:

P Output = Kp × Error

其中:

Error:当前误差。

Kp:比例强度。

放回汽车,如果,误差:30 km/h,那么,输出:较大的油门。

如果,误差:5 km/h,那么,输出:较小的油门。

因此,P Term 解决的是:现在差多少。


但是,P Term 有一个问题

继续驾驶,目标:100 km/h

汽车:98 km/h

误差:2 km/h

此时 P Term 认为:误差很小,所以油门很小。

但是现实中,汽车存在:

  • 风阻;
  • 路面阻力;
  • 发动机负载。

于是,虽然一直给一点油,汽车可能只能保持:98 km/h

永远达不到:100 km/h

这就是:稳态误差。


I Term(积分控制项):过去一直差一点,需要累计补偿

那么怎么办?

既然现在误差很小,但是过去一直存在误差。

那么控制器应该记住过去发生了什么。

例如,过去一分钟:速度一直比目标低2 km/h

虽然当前只差:2 km/h,但是,过去累计起来,说明发动机输出不足。

于是,控制器逐渐增加补偿。

这就是:

I Term(积分控制项)。

它关注:误差累计了多久,累计了多少。

因此,I Term 解决:

过去累计差多少。

但是,加入 I Term 后又出现新问题

现在,汽车终于达到:100 km/h

但是,由于 I Term 已经积累了一部分补偿。

此时,车辆可能继续加速:

100 -> 105 -> 110

出现过冲。

也就是:已经接近目标,但是仍然继续增加。

为什么?

因为,系统存在惯性,飞机也是一样。


D Term(微分控制项):观察变化趋势,提前刹车

如果控制器不仅知道“现在差多少”,还知道“速度正在变化多快”,

那么,它就能提前判断:是否马上超过目标。

例如,当前:98 km/h, 目标:100 km/h

表面看,只差 2 km/h。

但是,如果速度变化趋势是:每秒增加 10 km/h

那么控制器知道:马上会超过目标。

因此,提前减少输出。

这就是:

D Term(微分控制项)。

它关注:变化趋势。

因此,D Term 解决:变化正在发生多快。


到这里,PID 三项已经形成完整逻辑

现在重新看汽车控制:目标 100 km/h


P Term

观察现在差多少?负责:快速靠近目标。


I Term

观察过去是否长期存在误差?负责:消除长期偏差。


D Term

观察:变化趋势是否会导致过冲?负责:提前抑制变化。


三者组合:

P:拉近目标。

I:消除剩余误差。

D:避免过冲。

这就是:PID Controller(PID控制器)。


但是飞控中的 PID 和汽车有什么不同?

汽车控制的是:速度。

而飞控控制的是:角速度。

例如:

飞手打杆后,飞控得到:

Desired Angular Rate(目标角速度)= 300°/s

陀螺仪测量:

Current Angular Rate(当前角速度)= 250°/s

于是:

Rate Error = 300 - 250 = 50°/s

PID Controller(PID控制器)看到:飞机还少旋转 50°/s。

然后:P、I、D 分别开始工作。


Betaflight 中的 PID 输出是什么?

在 Betaflight 中:

PID Controller(PID控制器)最终不是直接控制电机转速。

它计算:

P + I + D + Feedforward

得到 PID Sum。

也就是控制输出。

对应源码逻辑:

const float pidSum = pidData[axis].P
                   + pidData[axis].I
                   + pidData[axis].D
                   + pidData[axis].F;

这一步表示:四个控制思想最终合成为一个控制结果。


一个完整数字案例

假设:飞机需要:

目标角速度:300°/s

当前:

250°/s

因此:

Rate Error:50°/s

P Term,

假设 Kp = 0.8,那么:

P = 0.8 × 50 = 40

表示:当前误差需要立即产生 40 的控制力度。


I Term:

假设过去飞机长期少转:5°/s

经过累计,得到:I = 10。

表示:过去误差需要补偿。


D Term:

如果当前角速度快速增加,控制器发现马上接近目标。

于是:D = -8。

提前减少输出。


Feedforward:

如果飞手刚刚快速打杆,控制器知道:

这是人为希望快速变化。

提前增加:F = 15。


最终:

PID Output = 40 + 10 - 8 + 15 = 57

这个就是飞控接下来用于控制飞机的输出。


回到控制链

现在完整控制链已经建立:

RC Stick

↓

Target Angle

↓

Current Angle

↓

Angle Error

↓

Desired Angular Rate

↓

Current Angular Rate

↓

Rate Error

↓

PID Controller

↓

P + I + D + Feedforward

↓

PID Output

↓

Mixer

↓

Motor Output

到这里,PID Controller(PID控制器)在整个飞控中的职责已经完整建立。

它并不是一个神秘公式。

而是一套:

不断观察误差,根据误差状态,决定控制力度的反馈系统。

本讲小结

本讲对 PID Controller(PID控制器)进行了系统总结。

我们通过汽车速度控制的例子,重新理解了 PID 的核心思想:

P Term(比例控制项)解决当前差多少。

I Term(积分控制项)解决过去累计差多少。

D Term(微分控制项)解决变化趋势有多快。

同时,结合 Betaflight 的控制链,我们明确了:

飞控中的 PID 并不是直接控制飞机姿态,而是控制:

Rate Error(角速度误差)

并通过:

P + I + D + Feedforward

生成最终控制输出。

至此,PID Controller(PID控制器)作为 Inner Loop(内环)的核心控制模块,已经完成系统性建立。


下一讲预告

现在,PID Controller(PID控制器)已经完成:

误差 -> 控制输出

的转换。

但是, PID Output(PID输出)仍然不能直接驱动电机。

因为, 飞机还需要解决:

一个控制输出,如何转换成四个电机不同的推力?

下一讲,我们将进入:

Mixer(混控器)

理解飞控如何把:

Roll / Pitch / Yaw 控制量

↓

转换为:四个电机的输出差异。