[BF学院_卷1] -- 第八讲:飞手打杆以后,飞控首先得到什么?
第八讲:飞手打杆以后,飞控首先得到什么?
- Angle Mode(自稳模式)的控制链路总览
- 飞手真正控制的是什么
- 为什么遥控器不是直接控制电机
- angleTarget(目标姿态角)的来源
- angleTarget(目标姿态角)为什么这样计算
- 控制链路正式开始
本讲对应 Betaflight 源码
源码文件
src/main/flight/pid.c核心函数
pidLevel()核心变量
currentPidSetpoint
angleTarget本讲对应控制流程
RC(遥控器) │ ▼ currentPidSetpoint │ ▼ angleTarget(目标姿态角)
本讲学习目标
阅读完本讲以后,你应该能够回答:
□ 飞手真正控制的是什么?
□ currentPidSetpoint 从哪里来?
□ angleTarget(目标姿态角)是什么?
□ angleTarget 为什么这样计算?
□ 飞控为什么要先得到 angleTarget,而不是直接控制电机?
从这一讲开始,我们正式进入 Betaflight
前面的几讲,
我们一直讨论:
飞机应该怎样运动。
例如:
Yaw 应该绕 Earth Frame(地球坐标系)旋转。
Pitch Flip 为什么只能用于 180°。
这些内容,
都是为了建立:
空间直觉。
但是,
从这一讲开始,
我们正式进入:
Betaflight 源码。
我们的目标,
也发生了变化。
以后,
每一讲都会围绕一个核心问题:
飞控是怎样把飞手的控制意图,
一步一步翻译成电机控制命令的?
整个过程,
我们都会对应:
Betaflight 源码,
逐行理解。
飞手真正控制的是什么?
很多初学者,
都会认为:
飞手控制的是:
电机。
或者:
飞手控制的是:
飞机姿态。
其实,
这两种说法,
都不准确。
飞手真正控制的是:
遥控器摇杆。
例如:
Pitch(俯仰)
向前推一点。
飞控收到的,
只是:
一个摇杆输入。
此时,
飞控仍然不知道:
飞机应该转到多少度。
因此,
第一步,
必须把:
摇杆输入
翻译成:
飞机希望到达的姿态。
这个姿态,
就是:
angleTarget(目标姿态角)。
angleTarget(目标姿态角)到底来自哪里?
对应源码:
float angleTarget =
angleLimit
*
currentPidSetpoint
*
pidRuntime.maxRcRateInv[axis];
以后,
阅读源码,
我们遵循统一的方法。
首先,
回答第一个问题。
angleTarget(目标姿态角)是什么?
一句话来说:
angleTarget
=
飞手希望飞机最终停留的位置。
例如:
飞手希望:
Pitch = 30°
那么:
angleTarget
=
30°
注意:
这里仍然只是:
目标。
飞机,
此时,
还没有开始运动。
飞控,
只是知道:
飞手希望飞机,
最终停留在这里。
currentPidSetpoint 到底来自哪里?
继续看源码:
float angleTarget =
angleLimit
*
currentPidSetpoint
*
pidRuntime.maxRcRateInv[axis];
阅读源码时,
按照我们的新规范,
第二步要回答:
currentPidSetpoint
来自哪里?
答案是:
RC(遥控器)
更准确地说,
对应源码:
float currentPidSetpoint =
getSetpointRate(axis);
因此:
整个来源可以理解成:
RC(遥控器)
↓
getSetpointRate()
↓
currentPidSetpoint
这里,
我们暂时不用深入:
Rates(摇杆曲线)
因为:
它属于:
RC 输入模块。
后面会单独介绍。
目前,
只需要知道:
currentPidSetpoint
=
RC 当前摇杆输入。
angleLimit 是什么?
继续看:
angleLimit
它表示:
ANGLE 模式允许的最大姿态角。
例如:
如果:
angleLimit
=
55°
那么:
飞机最大只能飞到:
Pitch = ±55°
Roll = ±55°
即使:
飞手把摇杆推到底,
飞机也不会继续倾斜。
因此:
angleLimit
决定了:
ANGLE 模式的最大姿态角。
maxRcRateInv 又是什么?
最后还有:
pidRuntime.maxRcRateInv[axis]
名字看起来很复杂。
其实,
它只是:
maxRcRate
的倒数。
作用只有一个:
把 RC 输入,
转换成:
0~1 的比例。
例如:
假设:
最大 RC 输入
=
500°/s
那么:
摇杆当前:
250°/s
经过:
maxRcRateInv
以后:
得到:
0.5
也就是说:
当前摇杆,
推到了:
50%。
因此:
这一项,
真正表示的是:
RC 当前打杆比例。
为什么三者相乘?
现在,
三个变量,
已经全部认识了。
currentPidSetpoint
↓
当前 RC 输入
maxRcRateInv
↓
转换成打杆比例
angleLimit
↓
最大允许姿态角
于是:
整个公式:
angleTarget =
angleLimit
*
currentPidSetpoint
*
pidRuntime.maxRcRateInv[axis];
其实就是:
RC 当前比例
×
最大姿态角
得到:
Target Angle(目标姿态角)
例如:
ANGLE 最大姿态角
=
60°
飞手:
摇杆推到:
50%
那么:
angleTarget
=
30°
飞控立即知道:
飞手希望:
飞机最终停留在:
30°。
到这里,飞控真正完成了第一次翻译
飞手,
一直认为:
自己只是:
推了一下摇杆。
但是,
飞控已经完成了一次非常重要的翻译。
它把:
RC 输入
翻译成:
Target Angle(目标姿态角)
整个过程可以表示成:
RC(遥控器)
↓
currentPidSetpoint
↓
RC 当前比例
↓
angleTarget(目标姿态角)
这也是:
Angle Mode(自稳模式)
真正开始工作的第一步。
但是,还有一个问题
现在,
飞控已经知道:
Target Angle
=
30°
可是,
它仍然不能控制飞机。
原因非常简单。
飞控只知道:
希望飞机去哪里。
但是,
它还不知道:
飞机现在在哪里。
因此,
控制系统还缺少另一半信息:
Current Angle(当前姿态角)
只有:
Target Angle
+
Current Angle
同时存在,
飞控才能计算:
Angle Error(姿态角误差)
真正开始控制飞机。
本讲小结
这一讲,
飞控完成了控制链中的第一次翻译:
RC(遥控器)
↓
currentPidSetpoint
↓
angleTarget(目标姿态角)
其中:
currentPidSetpoint
=
RC 当前摇杆输入。
angleLimit
=
ANGLE 模式允许的最大姿态角。
maxRcRateInv
=
把 RC 输入转换成打杆比例。
最终:
飞控得到:
Target Angle(目标姿态角)
它表示:
飞手希望飞机最终停留的位置。
但是,
飞控仍然不知道:
飞机现在到底在哪里。
因此,
下一讲,
我们将继续寻找:
Current Angle(当前姿态角)
并计算:
Angle Error(姿态角误差)。
下一讲预告
下一讲,
我们将正式进入:
const float currentAngle =
(attitude.raw[axis]
-angleTrim->raw[axis])
/10.0f;
这一行源码。
重点理解:
Current Angle(当前姿态角)
到底来自哪里?
以及:
为什么:
Target Angle
-
Current Angle
就能够得到:
Angle Error(姿态角误差)。
浙公网安备 33010602011771号