1. PX4位置控制器概述
大家好,我是你们的飞控讲师。今天咱们聊聊PX4多旋翼位置控制器的整体架构。说实话,这个模块是整个飞控系统里最贴近用户感知的部分——你推摇杆,飞机怎么动,全看它。
1.1 位置控制器在飞控系统中的位置
先看一张整体结构图,我习惯把PX4飞控系统分成三层:
你看,位置控制器在最外层。它接收期望位置(比如你要飞到N30° E120°那个点),然后算出飞机应该朝哪个方向倾斜、给多大油门。说白了,它就是个翻译官——把「去哪」翻译成「怎么飞」。
1.2 位置控制器的核心数据流
数据怎么流的?我画个简化的框图你就明白了:
嗯,这里要注意:位置控制器内部其实还嵌套了一个速度控制器。位置环输出的是期望速度,速度环再算出期望加速度,最后映射到姿态角。我刚开始学的时候,老觉得位置环直接输出角度就行了,后来调试才发现——不加速度限幅,飞机起飞时能翻跟头!
1.3 位置控制器的输入输出
咱们把接口捋清楚:
| 信号类型 | 具体内容 | 数据来源 | 说明 |
|---|---|---|---|
| 输入 | 期望位置 (x, y, z) | 遥控器 / 任务规划 / 机载计算机 | 单位:米,NED坐标系 |
| 输入 | 期望偏航角 (yaw) | 遥控器 / 任务规划 | 单位:弧度 |
| 输入 | 当前位置/速度估计 | EKF2估计器 | 融合GPS、IMU、视觉等 |
| 输出 | 期望姿态角 (roll, pitch) | 传给姿态控制器 | 由加速度反算得到 |
| 输出 | 期望推力 (thrust) | 传给姿态控制器 | 归一化值 0~1 |
💡 个人经验:我在做物流无人机项目时,发现位置控制器的输入频率很关键。如果GPS更新率只有5Hz,位置环跑50Hz其实意义不大——你想想看,输入数据都跟不上,算得再快也是白算。后来我改成根据传感器更新率动态调整位置环频率,效果好了不少。
1.4 位置控制器的代码结构
源码在 src/modules/mc_pos_control/ 目录下。核心文件就这几个:
- PositionControl.cpp — 主逻辑,位置环+速度环计算
- PositionControl.hpp — 头文件,定义类接口
- takeoff.cpp — 起飞逻辑,单独抽出来了
- land.cpp — 降落逻辑,同样独立
我习惯先看头文件,了解有哪些成员变量:
// PositionControl.hpp 核心接口
class PositionControl
{
public:
// 设置期望值
void setPositionSetpoint(const PositionSetpoint& sp);
void setVehicleState(const VehicleState& state);
// 核心计算函数
void update(float dt);
// 获取输出
const VehicleAttitudeSetpoint& getAttitudeSetpoint() const;
private:
// 位置环P增益
matrix::Vector3f _pos_p;
// 速度环PID增益
matrix::Vector3f _vel_p, _vel_i, _vel_d;
// 限幅参数
float _vel_max;
float _acc_max;
};
你看,接口很清晰。setPositionSetpoint喂期望,setVehicleState喂当前状态,update算一步,getAttitudeSetpoint拿结果。说白了就是个标准的「设置-计算-读取」模式。
⚠️ 避坑指南:我曾经在修改代码时,忘了调用setVehicleState,结果位置控制器拿到的全是零值。飞机一解锁就猛往前窜,差点撞墙。记住:update之前,一定要把状态喂进去!
1.5 位置控制器的运行频率
默认情况下,位置控制器跑在50Hz。为什么是这个值?
- 传感器限制:GPS典型更新率就是5~10Hz,EKF2输出位置估计也就50Hz左右
- 执行器限制:姿态控制器跑250~400Hz,位置环没必要更快
- 计算资源:50Hz意味着20ms算一次,留给其他模块足够时间
当然,如果你用视觉定位(比如T265相机),位置更新率能到200Hz。这时候把位置环提到100Hz也是可以的。我有个项目就是这么干的,悬停精度从±30cm降到了±5cm。
1.6 小结
这一章咱们把位置控制器的位置、数据流、接口、代码结构都过了一遍。说白了,它就是飞控系统里承上启下的那个模块——上面接任务规划,下面接姿态控制。理解了这个框架,后面改代码你才知道动哪里、不动哪里。
嗯,内容就这些。下一章咱们会深入位置环的数学推导和参数整定,到时候拿实际飞行数据说话。
公众号:蓝海资料掘金营,微信deep3321