3、姿态PID控制器设计:内环与外环、角度环与角速度环

好,咱们今天聊点硬核的。姿态PID控制器,说白了就是让无人机“站稳”的核心。很多新手一上来就调PID,结果飞机乱抖甚至翻跟头。为什么?因为没搞明白内环和外环的关系。

我个人习惯把姿态控制拆成两层:角度环(外环)角速度环(内环)。这两层各有各的活,千万别混着调。

3.1 为什么需要内外环?

你想想看,无人机要控制姿态,最终靠的是电机转速变化。但电机转速变化直接产生的是角加速度,不是角度。所以我们需要一个“翻译”过程:

  • 外环(角度环):负责把期望角度和实际角度的偏差,转成期望角速度。
  • 内环(角速度环):负责把期望角速度和实际角速度的偏差,转成电机控制量。

我在项目中遇到过一个问题:有人只用一个角度环,结果飞机反应特别迟钝,稍微有点风就晃。为什么?因为角度环输出的是角速度期望,但实际角速度变化很快,单环根本跟不上。加上内环后,响应速度明显提升。

核心结论:内环负责“快”,外环负责“准”。内环频率通常是外环的5-10倍。

3.2 内环:角速度环设计

角速度环是姿态控制的“肌肉”。它直接面对陀螺仪数据,响应最快。

我一般这样设计角速度环的PID:

// 角速度环PID结构体
typedef struct {
    float Kp;   // 比例系数
    float Ki;   // 积分系数
    float Kd;   // 微分系数
    float integral;   // 积分累计
    float prev_error; // 上次误差
    float output_limit; // 输出限幅
} PID_Controller;

// 角速度环计算函数
float AngularRatePID_Update(PID_Controller *pid, float target, float actual) {
    float error = target - actual;
    
    // 比例项
    float p_out = pid->Kp * error;
    
    // 积分项(带限幅)
    pid->integral += error * dt;
    pid->integral = constrain(pid->integral, -pid->output_limit, pid->output_limit);
    float i_out = pid->Ki * pid->integral;
    
    // 微分项(注意:这里用角速度变化率,不是误差变化率)
    float d_out = pid->Kd * (error - pid->prev_error) / dt;
    pid->prev_error = error;
    
    // 输出限幅
    float output = p_out + i_out + d_out;
    output = constrain(output, -pid->output_limit, pid->output_limit);
    
    return output;
}

经验之谈:角速度环的Kd我一般设得很小,甚至为0。因为陀螺仪数据本身就有噪声,微分项容易放大噪声。我曾经在调试时把Kd设大了,结果飞机高频抖动,差点炸机。

3.3 外环:角度环设计

角度环是“大脑”,它告诉内环“该往哪个方向转多快”。

角度环通常只用P控制就够了。为什么?因为角度误差本身就有积分效果——你一直偏着,误差就一直存在,内环就会一直纠正。

// 角度环计算(输出给内环作为目标角速度)
float AnglePID_Update(float target_angle, float actual_angle) {
    float error = target_angle - actual_angle;
    
    // 角度环一般只用P
    float p_out = angle_Kp * error;
    
    // 限幅:最大角速度不能超过内环能处理的范围
    p_out = constrain(p_out, -max_angular_rate, max_angular_rate);
    
    return p_out;  // 这个值就是内环的目标角速度
}

嗯,这里要注意:角度环的输出限幅很关键。如果你设的max_angular_rate太大,内环可能跟不上,导致超调。我一般设成内环最大输出能力的60%-70%。

3.4 内外环的配合与调参顺序

调参顺序很重要。我见过有人上来就调角度环,结果怎么调都不对。正确的顺序是:

  1. 先调内环(角速度环):让飞机能快速响应角速度指令,不震荡。
  2. 再调外环(角度环):让飞机能准确跟踪角度指令。

具体步骤:

步骤 操作 现象
1 内环P从0慢慢增大 飞机开始有阻力感,推杆回中后能停住
2 内环I适当加入 消除稳态误差,悬停更稳
3 内环D(可选) 抑制超调,但注意噪声
4 外环P从0增大 飞机响应角度指令,回中迅速

避坑指南:我曾经在调内环时,发现飞机有低频振荡。检查了半天,发现是外环P太大,导致内环目标角速度频繁跳变。解决办法:降低外环P,或者给外环输出加一个低通滤波。

3.5 实际工程中的注意事项

说几个我在实际项目中踩过的坑:

  • 积分饱和:内环积分项一定要限幅。否则飞机长时间偏转后,积分累计太大,回中时会猛冲过去。
  • 控制频率:内环至少200Hz,外环50Hz以上。我习惯内环400Hz,外环100Hz。
  • 死区处理:陀螺仪在小角速度时有零偏,可以加一个死区,比如角速度小于0.5°/s时不做控制。

你想想看,如果内环频率太低,外环输出一个角速度指令,内环要等5ms才响应一次,那飞机肯定晃。所以频率匹配很重要。

最后总结一下:内环管快,外环管准;先调内环,再调外环;内环用PID,外环用P。 记住这个口诀,姿态控制就成功了一半。

个人习惯:我一般在调试时,先用一个简单的角度环P参数让飞机能勉强悬停,然后专心调内环。内环调好了,外环稍微调一下就能飞得很稳。别急着一步到位,慢慢来。