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

推荐订阅源

IT之家
IT之家
博客园_首页
S
SegmentFault 最新的问题
罗磊的独立博客
博客园 - 【当耐特】
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
阮一峰的网络日志
阮一峰的网络日志
D
Docker
雷峰网
雷峰网
Google DeepMind News
Google DeepMind News
博客园 - 司徒正美
V
V2EX
大猫的无限游戏
大猫的无限游戏
V
Visual Studio Blog
腾讯CDC
宝玉的分享
宝玉的分享
酷 壳 – CoolShell
酷 壳 – CoolShell
人人都是产品经理
人人都是产品经理
T
Tailwind CSS Blog
Vercel News
Vercel News
H
Help Net Security
博客园 - Franky
D
DataBreaches.Net
aimingoo的专栏
aimingoo的专栏

博客园 - 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] -- 第19讲:PID Controller(PID控制器)——飞控到底如何理解误差并控制飞机? [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] -- 第20讲:从 PID Output 到 Motor Command(...
longyue · 2026-08-03 · via 博客园 - longyue

第20讲:从 PID Output 到 Motor Command(电机指令)——为什么飞控需要 Mixer


本讲知识点

  • PID Controller(PID控制器)输出的到底是什么?
  • 为什么 PID Output(PID输出)不能直接控制 Motor(电机)?
  • 为什么四旋翼需要 Mixer(混控器)?
  • 飞机运动需求与电机执行命令之间有什么区别?
  • Mixer(混控器)在整个控制链中的作用是什么?
  • Motor Command(电机指令)如何成为电机真正执行的数据?

本讲对应 Betaflight 控制链位置

本讲位于:

PID Controller(PID控制器)

↓

PID Output(PID输出)

↓

Mixer(混控器)

↓

Motor Command(电机指令)

↓

ESC

↓

Motor

上一讲,我们已经完成了 PID Controller(PID控制器)的学习。

飞控已经能够根据:

目标状态

↓

当前状态

↓

两者之间的误差

计算出:

为了消除误差,飞机需要产生怎样的控制作用。

这个结果,就是:

PID Output(PID输出)

但是,现在出现了一个新的问题:

PID Output(PID输出)如何变成每一个电机真正执行的动作?

因为,PID 到这里,只解决了飞机应该怎样运动。

但是,电机需要知道的是:每一个电机应该输出多少动力。

这两个问题,并不是同一个问题,而连接这两个阶段的模块,就是:

Mixer(混控器)

PID 已经完成了什么?

在进入 Mixer 之前,我们先明确 PID 的职责。

假设飞手向右推动 Roll 摇杆。

经过前面的控制链:

RC Stick(遥控输入)

↓

Target Angle(目标姿态角)

↓

Angle Error(姿态角误差)

↓

Desired Angular Rate(目标角速度)

↓

Rate Error(角速度误差)

↓

PID Controller(PID控制器)

最终,PID 计算得到:Roll PID Output(滚转PID输出)

这个输出表示:飞机需要产生一个向右滚转的控制作用。

注意,这里描述的是 “飞机整体运动需求”。

而不是 “某一个电机增加多少转速”。

因为 PID Controller(PID控制器)并不知道:

  • 哪个电机应该增加;
  • 哪个电机应该减少;
  • 每个电机需要变化多少。

这些问题并不属于 PID 的职责范围。


一个简单问题:如果只有一个电机,还需要 Mixer 吗?

为了理解 Mixer,我们先考虑一个极端情况。

假设一架飞行器只有一个电机,控制过程可能非常简单:

需要更多动力

↓

增加电机输出

↓

飞机产生运动

因为,只有一个执行机构。

所以:

控制需求 -> 执行动作

之间不存在复杂转换。

但是, 四旋翼完全不同, 四旋翼拥有:

Motor 1

Motor 2

Motor 3

Motor 4

四个执行机构。

此时,飞控提出:“飞机需要向右滚转”。

对于电机来说,这个信息仍然不完整,因为电机不知道:

哪个电机应该增加?

哪个电机应该减少?

增加多少?

减少多少?

因此,随着执行机构数量增加,控制系统出现了一个新的问题:

飞机希望产生什么运动,多个执行机构应该如何配合?

这个问题,就是 Mixer 需要解决的问题。


生活案例:四个人搬箱子

为了建立直观理解,我们先离开飞控。

假设,一个很重的箱子,需要四个人搬动。

四个人分别站在:左前,右前,左后,右后。

现在,一个控制者告诉他们:“箱子需要向右移动”。

这个命令是否足够?

答案:不够。

因为四个人还不知道:“每个人应该用多大力量”?

例如:

如果四个人同时向右推动,箱子可能整体向右移动。

但是,如果希望箱子:“向右移动,同时改变方向”

那么四个人的力量就必须不同。

可能需要:

左侧增加力量,右侧减少力量

这样箱子才会产生旋转。

这里出现了两个不同的问题:

第一个问题:箱子需要产生什么运动?例如,向右移动。

第二个问题:四个人分别应该如何用力?例如,谁增加力量,谁减少力量。

第一个问题属于控制目标,第二个问题属于执行分配。

负责执行分配的角色:就是 Mixer。


回到四旋翼

四旋翼的问题完全一样。

飞控首先关心:飞机需要产生什么运动。

例如:

Roll(横滚)

Pitch(俯仰)

Yaw(偏航)

Throttle(油门)

这些都是飞机整体运动需求。

但是,飞机真正执行动作的是:

Motor 1

Motor 2

Motor 3

Motor 4

电机并不知道什么叫:Roll,Pitch, Yaw。

电机只知道:

提高转速 -> 产生更大动力

或者:

降低转速 -> 减少动力

因此,飞控需要一个中间翻译层:

飞机运动需求 -> 每个电机具体执行量

这个过程, 就是 Mixer(混控)。


Mixer 的核心职责

现在可以正式定义 Mixer。

Mixer(混控器)的职责:

将飞控产生的运动控制需求,转换为多个电机对应的执行指令。

简单来说:

PID Output(PID输出)告诉飞机:我要产生什么运动。

Mixer(混控器)告诉电机:你们每一个应该如何配合。

所以:

PID Output ≠ Motor Command

中间必须经过 “ Mixer ” 才能得到:

Motor Command(电机指令)

四旋翼为什么需要同时处理多个控制需求?

现在,我们已经知道 PID Output(PID输出)表示飞机希望产生什么运动。

但是,真实飞行过程中,飞机通常不会只执行一种运动。

例如:

飞手推动油门,飞机需要上升;

同时,飞手推动 Roll,飞机需要向右倾斜;

同时,飞手推动 Pitch,飞机需要向前倾斜;

同时,飞手推动 Yaw,飞机需要改变朝向。

也就是说,飞机的运动需求,通常是多个目标同时存在。

四旋翼需要同时处理:

Throttle(油门) : 控制整体升力

Roll(横滚):控制左右倾斜

Pitch(俯仰):控制前后倾斜

Yaw(偏航):控制旋转方向

但是,飞机最终只有 Motor 1 ~ Motor 4 四个执行机构。

因此,飞控必须解决一个问题:

多个飞机运动需求,如何组合成四个电机的输出?

这就是 Mixer 存在的根本原因。


为什么 Mixer 叫 "混控器"?

现在,我们可以理解 Mixer 名字中的 "Mix"。

Mixer 并不是创造新的控制目标,它也不是重新计算飞机应该如何运动。

这些工作已经由前面的控制链完成。

Mixer 做的是:

多个已有控制需求组合,形成多个电机执行量

例如,飞机当前需要:

Throttle = 50

Roll = +20

Pitch = -10

Yaw = +5

这些信息分别代表:

需要多少升力;

需要多少滚转;

需要多少俯仰;

需要多少偏航。

但是,电机无法直接理解这些信息。

Mixer 需要把它们转换为:

Motor 1 = ?

Motor 2 = ?

Motor 3 = ?

Motor 4 = ?

因此,Mixer 的 "混合",指的是:

Throttle + Roll + Pitch + Yaw -> 组合成为多个 Motor Command

一个简单 Roll 混控案例

现在,我们只观察一个最简单的情况。

假设, 飞机当前:Throttle = 50,表示四个电机共同提供基础升力。

此时,飞控希望:Roll = +20,表示飞机需要向右滚转。

为了产生滚转力矩:飞机左右两侧的升力必须不同。

例如:

左侧电机增加动力,左侧升力增加

右侧电机减少动力,右侧升力减少

于是,Mixer 可能产生类似:

左前电机:Throttle + Roll

右前电机:Throttle - Roll

左后电机:Throttle + Roll

右后电机:Throttle - Roll

最终,四个电机得到不同的输出。

例如:

Motor 1 = 70

Motor 2 = 30

Motor 3 = 70

Motor 4 = 30

注意,这里的数字只是为了理解 Mixer 的思想。

真实 Betaflight 中,还会考虑:

  • 电机布局;
  • 电机编号;
  • 旋转方向;
  • Yaw 力矩;
  • 输出限制;
  • 电机协议等。

但是核心思想不变:

飞机运动需求 -> Mixer 分配 -> 电机执行量

Mixer 并不是控制飞机

这里需要建立一个非常重要的边界, 很多初学者容易认为Mixer 控制飞机。

这个理解是不准确的, 因为Mixer 不知道:

飞机当前姿态是多少;

误差是多少;

应该向哪里飞。

这些属于前面的控制系统。

Mixer 只接收已经计算好的控制需求。

它负责:

怎么让多个电机合作完成这个需求。

因此, 控制链中:

PID Controller(PID控制器)负责计算控制需求。

Mixer(混控器)负责分配执行方式。

两者承担完全不同的职责。


回到完整控制链

现在,我们重新观察 PID Output 之后发生了什么:

Target Angle(目标姿态角)

↓

Angle Error(姿态角误差)

↓

Desired Angular Rate(目标角速度)

↓

Current Angular Rate(当前角速度)

↓

Rate Error(角速度误差)

↓

PID Controller(PID控制器)

↓

PID Output(PID输出)

↓

Mixer(混控器)

↓

Motor Command(电机指令)

↓

ESC

↓

Motor

↓

Aircraft Motion(飞机运动)

到这里, 控制链出现了一个非常重要的变化。

在 PID 之前, 飞控关注的是:飞机应该怎样运动。

经过 Mixer 以后, 飞控开始关注:每一个执行机构应该怎样动作。

也就是说, 控制链完成了一次转换:

飞机级控制需求

↓

执行机构级控制命令

本讲核心认识

现在,可以总结第20讲最重要的三个概念。

第一:

PID Output(PID输出)不是电机控制信号。

它表达的是:飞机需要产生什么运动。


第二:

Motor Command(电机指令)不是控制需求。

它表达的是:每一个电机应该输出多少。


第三:

Mixer(混控器)连接两者。

它完成:

飞机运动需求 -> 多个电机执行量

的转换。


下一讲预告

现在,飞控已经完成了从 PID Output 到 Motor Command(电机指令)之间概念上的转换。

但是,还有一个问题:Betaflight 中的 Mixer 到底是如何实现这个转换的?

它如何知道:

Roll,Pitch,Yaw,Throttle

应该分别影响哪些电机?

下一讲,我们将正式进入:

Mixer(混控器)的源码实现。

观察 Betaflight 如何根据四旋翼结构,将控制需求转换成:

Motor 1

Motor 2

Motor 3

Motor 4

最终输出真正的:

Motor Command(电机指令)。