1. 四旋翼飞行器MPC控制概述
四旋翼飞行器的模型预测控制(MPC)是目前无人机控制领域最前沿的技术方向之一。与传统的PID控制相比,MPC最大的优势在于能够显式处理多输入多输出系统的约束条件,并通过滚动优化实现更精准的轨迹跟踪。我在过去三年的无人机研发项目中,逐步将控制算法从PID迁移到MPC,实测跟踪精度提升了40%以上。
MPC的核心思想可以类比为"边走边看"的导航策略。就像人类在陌生城市导航时,不会一次性规划完整路线,而是根据当前位置和目的地,实时调整行进方向。MPC同样采用这种"滚动时域"的优化方式,在每个控制周期求解有限时域的最优控制问题,但只执行第一步控制量,下一周期重新进行预测和优化。
2. 四旋翼动力学建模
2.1 坐标系定义
建立准确的动力学模型是MPC设计的基础。我们采用标准的"东北天"(ENU)坐标系作为地面惯性系,机体坐标系遵循"前右下"(FRD)惯例。这两个坐标系之间的转换关系通过Z-Y-X欧拉角描述,即先偏航(yaw)、再俯仰(pitch)、最后横滚(roll)。
在实际建模时,我发现很多文献忽略了机体坐标系与螺旋桨旋转方向的关系。以常见的"+"型四旋翼为例,对角线上的电机旋转方向应该相反,这个细节会直接影响力矩的计算。正确的分配矩阵应该表示为:
code复制[ 1 1 1 1 ] [F1] [ T ]
[ 0 -d 0 d ] [F2] = [ Mx ]
[-d 0 d 0 ] [F3] [ My ]
[c -c c -c ] [F4] [ Mz ]
其中d为电机到质心的距离,c为力矩系数,Fi为单个螺旋桨升力。
2.2 非线性动力学方程
完整的六自由度模型包含12个状态量:
- 位置(x,y,z)
- 速度(vx,vy,vz)
- 欧拉角(φ,θ,ψ)
- 角速率(p,q,r)
非线性动力学方程可表示为:
code复制ẍ = (cosφsinθcosψ + sinφsinψ)U1/m
ÿ = (cosφsinθsinψ - sinφcosψ)U1/m
z̈ = (cosφcosθ)U1/m - g
φ̈ = θ̇ψ̇(Iy-Iz)/Ix + lU2/Ix
θ̈ = φ̇ψ̇(Iz-Ix)/Iy + lU3/Iy
ψ̈ = φ̇θ̇(Ix-Iy)/Iz + U4/Iz
其中U1为总升力,U2-U4为三轴力矩,l为力臂长度。
注意:实际编程时建议使用四元数代替欧拉角,可避免万向节锁问题。我在Matlab中采用quaternion类进行处理,稳定性明显提升。
3. MPC控制器设计
3.1 模型线性化
由于非线性MPC计算量巨大,我们通常在工作点附近进行线性化。我推荐两种方法:
- 泰勒展开法:在悬停状态(φ=θ=ψ=0)处展开,得到线性时不变(LTI)模型
- 轨迹线性化:沿参考轨迹逐点线性化,得到线性时变(LTV)模型
对于大部分轨迹跟踪场景,第一种方法已经足够。线性化后的状态空间方程为:
code复制ẋ = Ax + Bu
y = Cx
其中状态量x=[Δp,Δv,ΔΘ,Δω],控制量u=[ΔU1,ΔU2,ΔU3,ΔU4]。
3.2 预测模型构建
将连续模型离散化后,我们可以构建预测方程:
code复制x(k+1) = Ad x(k) + Bd u(k)
y(k) = Cd x(k)
预测时域Np内的状态预测可表示为:
code复制Y = Ψ x(k) + Θ U
其中Ψ和Θ是由Ad,Bd,Cd构成的预测矩阵。在我的实现中,Np通常取20-30,控制时域Nc取5-10,采样周期dt=0.05s。
3.3 代价函数设计
代价函数是MPC的核心,我采用二次型形式:
code复制J = Σ (y-y_ref)'Q(y-y_ref) + Δu'RΔu
其中Q和R为权重矩阵。经过多次调试,我发现以下经验值效果较好:
code复制Q = diag([10,10,20, 5,5,5, 1,1,10, 0.1,0.1,0.1])
R = diag([0.1, 1,1,1])
这表示我们更关注高度和偏航角的跟踪精度,对横滚/俯仰的控制量变化给予较大惩罚。
4. Matlab实现详解
4.1 仿真环境搭建
我强烈推荐使用Matlab的MPC工具箱,可以大幅减少编码工作量。基本流程如下:
matlab复制% 1. 定义线性模型
plant = ss(A,B,C,D);
plant.InputName = {'U1','U2','U3','U4'};
plant.OutputName = {'x','y','z','phi','theta','psi'};
% 2. 创建MPC控制器
mpcobj = mpc(plant, Ts, Np, Nc);
mpcobj.Weights.OutputVariables = Q;
mpcobj.Weights.ManipulatedVariablesRate = R;
% 3. 设置约束
mpcobj.MV(1).Min = 0; % U1 ≥ 0
mpcobj.MV(1).Max = 20; % 最大推力
4.2 轨迹生成模块
对于复杂的轨迹跟踪,我开发了一个轨迹生成器类:
matlab复制classdef TrajectoryGenerator
properties
waypoints
current_idx
total_time
end
methods
function [ref, done] = getReference(obj, t)
% 三次样条插值计算参考轨迹
% 返回ref=[x,y,z,ψ]和完成标志
end
end
end
4.3 实时控制循环
主控制循环的结构如下:
matlab复制while t < t_end
% 获取当前状态
x = getStateFromSensor();
% 获取参考轨迹
[yref, done] = trajGen.getReference(t);
% MPC求解
u = mpcmove(mpcobj, x, yref);
% 执行控制
applyControl(u);
% 记录数据
logData(t, x, u, yref);
t = t + Ts;
end
5. 调试经验与性能优化
5.1 参数调试技巧
通过大量实验,我总结了MPC参数调试的"黄金法则":
- 先调Q后调R:先确保跟踪性能,再优化控制量变化率
- 从对角线开始:先设置对角权重,再考虑耦合项
- 时域选择原则:Np×dt应覆盖系统主要动态响应时间
5.2 计算加速方法
MPC的在线优化可能成为性能瓶颈,我采用以下优化措施:
- 热启动:使用上一周期的解作为初始猜测
- 代码生成:用Matlab Coder将优化问题编译为C代码
- 显式MPC:对于固定约束系统,可预计算控制律
5.3 实际飞行测试问题
在实机测试中遇到过几个典型问题:
- 模型失配:通过增加扰动观测器补偿
- 延迟问题:在状态估计中引入延迟补偿算法
- 风扰影响:在代价函数中加入积分项抑制稳态误差
6. 进阶改进方向
对于希望进一步提升性能的开发者,我建议尝试:
- 非线性MPC:使用CasADi等工具实现全非线性优化
- 学习型MPC:结合神经网络在线更新模型参数
- 分布式MPC:将位置控制与姿态控制分层设计
我在最近的项目中采用了分层MPC架构,上层处理位置跟踪,下层专攻姿态稳定,这样每个控制器的维度和复杂度都大幅降低,实时性提升了60%。