














主要函数:
mixTable(timeUs_t currentTimeUs)
核心代码:
const float scaledAxisPidRoll =
constrainf(pidData[FD_ROLL].Sum,
-currentPidProfile->pidSumLimit,
currentPidProfile->pidSumLimit)
/ PID_MIXER_SCALING;
const float scaledAxisPidPitch =
constrainf(pidData[FD_PITCH].Sum,
-currentPidProfile->pidSumLimit,
currentPidProfile->pidSumLimit)
/ PID_MIXER_SCALING;
float scaledAxisPidYaw =
constrainf(pidData[FD_YAW].Sum,
-yawPidSumLimit,
yawPidSumLimit)
/ PID_MIXER_SCALING;
以及:
float mix =
scaledAxisPidRoll * activeMixer[i].roll +
scaledAxisPidPitch * activeMixer[i].pitch +
scaledAxisPidYaw * activeMixer[i].yaw;
理解 Mixer 接收到的不是"某个电机应该转多少",
而是"飞机需要多少 Roll、Pitch、Yaw 控制力"。
Mixer 的职责是:将飞机级控制需求,通过每个电机不同的权重,转换为每个电机需要增加或者减少多少输出。
上一讲分析了 calculateThrottleAndCurrentMotorEndpoints(), 它负责建立 Mixer 使用的油门输出空间。
也就是说, Mixer 在计算电机输出之前,需要先知道当前油门应该映射到哪个电机输出范围。
PID Controller 输出的是:飞机需要的控制量。
例如:飞机发生向右倾斜,PID Controller 计算以后得到:
Roll PID Output = +50
这个 50 表示:飞机需要一个 Roll 修正力。
但是它没有说明:
控制链:
姿态误差
↓
PID Controller
↓
Roll / Pitch / Yaw 控制需求
↓
Mixer
↓
Motor Output
所以,PID Output 是: "飞机需要什么",
而 Mixer 输出的是:"每个电机应该做什么"
在 mixTable() 中:
pidData[FD_ROLL].Sum
pidData[FD_PITCH].Sum
pidData[FD_YAW].Sum
分别代表:
Roll PID 总输出
Pitch PID 总输出
Yaw PID 总输出
这里的 "Sum" 表示 PID Controller 最终合成后的输出。
它已经包含 P项 + I项 + D项 的计算结果。
观察源码:
constrainf(pidData[FD_ROLL].Sum, -currentPidProfile->pidSumLimit, currentPidProfile->pidSumLimit)
这里进行了限制。
原因是:PID 输出理论上可以无限增大, 比如:飞机受到强烈扰动。
PID Controller 可能认为:需要非常大的修正力量。
但是电机存在物理限制:最大输出有限。
如果 PID 输出过大,进入 Mixer 后,可能导致:
因此,Mixer 输入之前,需要限制 PID 输出范围。
控制思想:
无限控制需求 -> 限制到飞控允许范围 -> 进入 Mixer
限制以后,源码继续:
/ PID_MIXER_SCALING
例如:
scaledAxisPidRoll = pidData[FD_ROLL].Sum / PID_MIXER_SCALING;
作用是:将 PID Controller 输出单位,转换为 Mixer 使用的控制空间。
因为PID Controller 内部使用的是PID 计算尺度,而 Mixer 使用的是电机输出混合尺度,二者不是同一个范围。
因此需要:
PID Output -> 缩放 -> Mixer 输入
最终得到:
scaledAxisPidRoll
scaledAxisPidPitch
scaledAxisPidYaw
经过限制和缩放以后,Mixer 得到三个核心输入:
表示:飞机需要多少 Roll 修正,
例如,正值:需要向正方向 Roll;负值:需要向反方向 Roll
表示:飞机需要多少 Pitch 修正
表示:飞机需要多少 Yaw 修正
注意:这里仍然不是电机输出,而是飞机级控制需求。
现在进入 Mixer 核心:
float mix =
scaledAxisPidRoll * activeMixer[i].roll +
scaledAxisPidPitch * activeMixer[i].pitch +
scaledAxisPidYaw * activeMixer[i].yaw;
这就是 Mixer 数学模型。
对于第 i 个电机:
Motor Mix = Roll需求 × Roll权重
+ Pitch需求 × Pitch权重
+ Yaw需求 × Yaw权重
例如:某个电机,
roll = 0.5
pitch = -0.5
yaw = 1.0
那么:
motorMix = Roll × 0.5 + Pitch × (-0.5) + Yaw × 1.0
这个结果表示:该电机需要因为姿态控制,增加多少,或者减少多少输出。
因为电机的位置不同。
例如,
Roll 控制:左侧电机增加,右侧电机减少 -> 产生滚转力矩;
Pitch 控制:前后电机产生推力差 -> 产生俯仰力矩;
Yaw 控制:不同旋向电机改变输出 -> 改变反作用力矩。
所以,每个电机对应一个:
Roll 权重
Pitch 权重
Yaw 权重
Mixer 并不是创造控制需求。
它只是按照飞机结构,重新分配控制需求。
到这里,Mixer 已经完成:
PID Output -> motorMix
转换。
此时, motorMix[]里面保存的是:每个电机由于姿态控制产生的 "修正量"。
但是,它还没有加入 "Throttle", 也没有转换成最终 ESC 输出值。
下一步的问题, 如何把:
Throttle + motorMix
合成为真正的:
Motor Output
本讲完成了 Mixer 输入控制量的建立。
源码中的 pidData[].Sum 是 PID Controller 输出的三轴控制需求,它描述飞机需要多少 Roll、Pitch、Yaw 修正,而不是直接描述电机输出。
Mixer 首先对 PID 输出进行限制和缩放,形成 scaledAxisPidRoll、scaledAxisPidPitch、scaledAxisPidYaw,然后通过 motorMixer_t 中保存的权重,将三轴控制需求转换为每个电机对应的 motorMix 修正量。
至此,控制链完成了:
PID Controller
↓
Roll / Pitch / Yaw 控制需求
↓
Mixer 分配
↓
motorMix
下一讲继续分析 mixTable()。
重点:
motorMix + Throttle -> Motor Output
也就是:Mixer 如何把姿态修正量和油门基础输出合成为最终电机输出。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。