[BF学院_卷1] -- 第十讲:Angle Error(姿态角误差)如何变成 Desired Angular Rate(目标角速度)

第十讲:Angle Error(姿态角误差)如何变成 Desired Angular Rate(目标角速度)

  • 为什么 Angle Error(姿态角误差)不能直接控制飞机
  • Desired Angular Rate(目标角速度)到底是什么
  • Outer Loop(外环)为什么要把角度变成角速度
  • angleRate = errorAngle * angleGain + angleFeedforward 这一行代码在做什么
  • Angle Mode(自稳模式)的 Outer Loop(外环)正式开始工作

学习目标

阅读完本讲以后,你应该能够回答:

□ 为什么 Angle Error(姿态角误差)不能直接控制飞机?
□ 什么是 Desired Angular Rate(目标角速度)?
□ Outer Loop(外环)为什么要把角度变成角速度?
angleRate = errorAngle * angleGain + angleFeedforward 这一行代码在做什么?
□ Angle Mode(自稳模式)的 Outer Loop(外环)正式开始工作


本讲源码位置

src/main/flight/pid.c

Angle Mode(自稳模式)外环控制:

float angleRate =
    errorAngle * pidRuntime.angleGain
    + angleFeedforward;

本讲只讨论:

  • errorAngle
  • angleGain
  • angleRate

暂不讨论:

  • angleFeedforward

回顾上一讲

上一讲我们已经得到:

Target Angle(目标姿态角)

它表示飞手希望飞机最终达到的姿态。

例如:

Pitch = 30°

但飞控仍然无法控制飞机,因为它还不知道:

飞机现在在哪里?

Current Angle(当前姿态角)的来源

在 Betaflight 中:

const float currentAngle =
(attitude.raw[axis] - angleTrim->raw[axis]) / 10.0f;

attitude.raw[] 是什么?

表示飞机当前姿态估计值,由姿态解算系统(陀螺仪 + 加速度计)计算得到。

在本课程中可以理解为:

attitude.raw[] = 当前飞机姿态

angleTrim->raw[] 是什么?

用于补偿机架安装误差,例如:

  • 飞控安装倾斜
  • 机架轻微不水平

作用:

消除静态安装偏差

/10.0f 是什么?

attitude.raw 的单位是:

0.1°

因此需要转换为:

°

得到 Current Angle

最终:

Current Angle(当前姿态角)
= 去除安装误差 + 单位转换

Angle Error(姿态角误差)

计算公式:

Angle Error = Target Angle - Current Angle

示例

Target Angle = 30°
Current Angle = 18°

则:

Angle Error = 12°

表示:

飞机距离目标还差 12°

为什么 Angle Error 不能直接控制飞机?

因为电机无法执行:

角度(Angle)

电机只能执行:

角速度(Angular Rate)

本质区别

类型 飞控理解 电机能力
Angle 位置 ❌不能执行
Angular Rate 速度 ✅可以执行

Angle Mode 外环的作用

告诉飞机应该以多快速度旋转

核心代码解析

到这里,飞控已经完成了前面的全部工作,控制链已经推进到:

Target Angle(目标姿态角)

↓

Current Angle(当前姿态角)

↓

Angle Error(姿态角误差)

上一讲最后,我们已经计算出了:

const float errorAngle =
    angleTarget
    -
    currentAngle;

很多初学者看到这里,都会产生一个疑问:

Angle Error(姿态角误差)

已经计算出来了,

飞机是不是马上就可以开始旋转了?

答案仍然是否定的。

原因就在于:

Angle Error(姿态角误差)仍然只是一个"位置误差",它还不是电机能够执行的控制命令。

真正让飞机开始运动的,是下面这一行源码:

float angleRate =
    errorAngle * pidRuntime.angleGain
    + angleFeedforward;

这一行代码,就是 Betaflight Angle Mode(自稳模式)Outer Loop(外环)真正开始工作的地方。

如果把这一行源码翻译成一句中文,它实际上表达的是:

根据飞机距离目标姿态还有多少角度,

计算:

飞机现在应该以多快的速度开始旋转。

因此,这一行代码完成了一件非常重要的事情:

Angle(角度)

↓

Angular Rate(角速度)

Outer Loop(外环)的全部任务,就是完成这一次转换。


Angle Error 已经计算出来了,为什么还不能控制飞机?

上一节,飞控已经完成了这一行计算:

errorAngle = Target Angle - Current Angle;

也就是说,飞控已经知道:

飞机距离目标姿态,还差多少角度。

例如:

Target Angle = 30°

Current Angle = 18°

Angle Error = 12°

这里的:

12°

只是表示:

当前位置距离目标位置,还有 12° 没有完成。

注意,

它仍然只是:

位置误差(Angle Error)。

它还不是:

电机能够执行的控制命令。

真正的问题来了:

既然已经知道:

飞机还差 12°,为什么飞控还不能马上控制飞机开始旋转?

答案就在下一节。


为什么电机不能直接执行 Angle Error?

很多初学者第一次学习飞控时,都会下意识认为:

飞机还差 12°

↓

那就继续转 12° 不就可以了吗?

听起来似乎很合理,但实际上,对于电机来说,这样的命令根本无法执行。

原因是:电机能够控制的,从来不是角度(Angle),而是角速度(Angular Rate)。

例如,下面两个命令对于电机来说是完全不同的:

命令一:

转到 30°

(Angle)
命令二:

以 60°/s 持续旋转

(Angular Rate)

第一种命令描述的是最终停留的位置。

第二种命令描述的是:

每一秒,应该旋转多少度。

真正能够直接驱动电机工作的,是第二种。

因此,当飞控计算出:

Angle Error = 12°

它得到的信息只是:

飞机距离目标姿态,还差 12°。

但是,这里面仍然缺少一个最关键的信息:

应该以多快的速度,去完成这 12°?

所以,飞控还必须继续完成一次新的计算。


angleGain(角度增益)是什么?

继续来看源码中的第二个变量:

pidRuntime.angleGain

很多资料都会直接说:

angleGain,是一个 Gain(增益)。

但是,对于第一次学习 PID 的人来说,这种解释几乎没有帮助。

真正容易理解的方法是:

把它看成一种:

转换比例。

它规定了一件事情:

每差 1°,应该输出多少角速度。

例如,假设:

angleGain = 5

那么:

误差:

1°

↓

输出:

5°/s

如果误差变成:

那么输出就会变成:

10°/s

继续扩大:

误差:

10°

输出:

50°/s

如果:

误差:

20°

输出:

100°/s

可以发现:

误差扩大多少倍,

输出速度也扩大多少倍。

因此:

angleGain 的真正作用,就是把"角度误差"翻译成"目标角速度"。

第一项:errorAngle × angleGain 到底得到了什么?

现在,

Outer Loop(外环)已经拥有了两个条件:

当前还差多少角度

(Angle Error)

以及:

每差 1°,应该输出多少角速度(angleGain)

接下来,

飞控真正开始进行第一次控制计算:

errorAngle * angleGain

也就是说:

把:

姿态误差,转换成,目标角速度。

那么,把它们相乘以后:

errorAngle * angleGain

到底表示什么?

答案就是:

根据当前姿态误差,计算得到:

飞机此刻应该达到的目标角速度。

也就是说:

Angle Error(角度误差)

↓

Desired Angular Rate(目标角速度)

真正发生转换的位置,就是这里。


举一个完整例子

假设:

Target Angle = 30°

Current Angle = 18°

因此:

Angle Error = 12°

再假设:

angleGain = 5

那么:

angleRate

= 12 × 5

= 60°/s

飞控得到的新目标就变成了:

飞机现在应该以:

60°/s,继续旋转。

注意,

这里已经不是:

还差多少角度。

而是:

应该以什么速度旋转。

这就是 Outer Loop(外环)最重要的一次翻译。


为什么 Outer Loop 一定要把 Angle(角度)变成 Angular Rate(角速度)?

上一节,我们已经知道:

电机不能直接执行:

Angle(角度)。

因此,

Outer Loop(外环)必须先把:

Angle Error

↓

Desired Angular Rate

完成转换。

那么问题来了:

为什么电机不能直接控制角度,

却能够控制角速度?

答案来自飞机本身的物理运动过程。

飞机真正能够控制的对象,是:

四个电机的转速。

电机转速发生变化以后,

首先产生的是:

力矩(Torque)

然后:

力矩

↓

角加速度

角加速度继续作用以后,

才会产生:

角速度(Angular Rate)

最后,

角速度不断积累,飞机的位置(姿态角)才会发生变化。

因此,

整个物理过程实际上是:

电机

↓

力矩

↓

角加速度

↓

角速度

↓

姿态角

可以发现:

电机距离:

姿态角(Angle)

中间隔着很多层。

但是距离:

角速度(Angular Rate)

却只有一步。

所以,

飞控不会直接控制:

Angle(角度)。

而是先控制:

Angular Rate(角速度)。

这样,整个控制链才符合飞机真实的物理运动过程。


P 控制为什么会产生"误差越大,转得越快"?

很多资料都会写一句话:

P 控制:

误差越大,输出越大。

第一次看到的人,往往会觉得:

这只是一个结论。

其实,

它完全可以从刚才的公式直接看出来。

回到源码:

angleRate = errorAngle * angleGain

如果:

Angle Error = 2°

输出就是:

10°/s

如果:

Angle Error = 10°

输出就是:

50°/s

如果:

Angle Error = 20°

输出就是:

100°/s

可以发现:

误差越大,目标角速度也越大。

这就是:

P(Proportional),比例控制

名字的真正来源。

因为:

输出始终保持:

输出

∝

误差

它们始终保持固定比例。

因此,

飞控会自然表现出一种直觉:

离目标越远,转得越快;

离目标越近,转得越慢。

飞机最终就会越来越平滑地停在目标姿态附近。


angleFeedforward 是什么?

继续看源码:

float angleRate =
    errorAngle * pidRuntime.angleGain
    + angleFeedforward;

除了:

errorAngle × angleGain

后面还有:

angleFeedforward

本讲暂时不会展开它的具体算法。

但是,

至少需要知道:

它并不是:

PID 的一部分。

它的作用更接近:

提前补偿。

也就是说,除了根据:

当前误差

计算目标角速度以外,

飞控还会根据飞手打杆的动作,

提前增加一部分角速度,

让飞机感觉:

响应更直接,更跟手。

因此,

这一行代码实际上由两部分组成:

第一部分:

errorAngle × angleGain

↓

根据姿态误差,计算应该旋转多快。

以及:

第二部分:

angleFeedforward

↓

提前增加一点目标角速度,提高操纵响应速度。

后面课程,我们会单独进入:

Feedforward(前馈控制)

专题,

详细讨论它为什么能够让飞机感觉"更丝滑"。

因此,

现在只需要知道:

它负责:

提前补偿,而不是修正误差。

整行代码最终完成了什么?

现在,

再回来看整行源码:

float angleRate =
    errorAngle * pidRuntime.angleGain
    + angleFeedforward;

终于可以把它完整翻译成一句中文:

根据飞机距离目标姿态还有多少角度,

计算:

飞机现在应该以多快速度开始旋转,

同时加入前馈补偿,提高操纵响应。

经过这一行代码,

Outer Loop(外环)的工作已经结束。

它最终输出给下一层的是:

Desired Angular Rate(目标角速度)

也就是说,

飞控已经完成了:

Angle(角度)

↓

Angular Rate(角速度)

这一整次翻译。

接下来,

这个目标角速度将交给下一层:

Rate PID(角速度内环)

继续处理。

因此,

控制链继续推进:

Target Angle

↓

Current Angle

↓

Angle Error

↓

Desired Angular Rate

但是,

飞控仍然不知道:

飞机现在,真正的角速度,是多少?

只有知道:

Current Angular Rate(当前角速度)

才能计算:

Rate Error(角速度误差)

真正进入:

Rate PID(角速度内环)

Angle Mode 外环总结

经过本讲,

Outer Loop(外环)已经全部完成。

控制链现在变成:

RC Stick(遥控器摇杆)

↓

Target Angle(目标姿态角)

↓

Current Angle(当前姿态角)

↓

Angle Error(姿态角误差)

↓

Desired Angular Rate(目标角速度)

可以发现,

Outer Loop(外环)始终没有控制电机。

它只完成了一件事情:

把:

飞手希望飞机停在哪个姿态,

翻译成:

飞机现在应该以什么角速度开始旋转。

真正负责驱动飞机的,其实还在下一层。


下一讲预告

现在,

飞控已经得到:

Desired Angular Rate(目标角速度)

但是,

它仍然不知道:

飞机现在,真正的角速度,是多少?

下一讲,

我们正式进入:

Current Angular Rate(当前角速度)

并开始进入 Betaflight 真正的核心控制器:

errorRate = desiredRate - gyroRate;

从这里开始,

Rate PID(角速度内环)将正式接管飞机的控制。

posted on 2026-08-03 14:35  longyue  阅读(25)  评论(0)    收藏  举报

导航