四旋翼无人机的控制一直是机器人领域的热点研究方向。传统控制方法如PID在面对复杂非线性系统时往往捉襟见肘,而基于精确模型的非线性模型预测控制(NMPC)又面临计算复杂度高、实时性差等问题。本文介绍的Koopman-MPC框架提供了一种创新性的解决方案——通过数据驱动的方式将非线性系统"抬升"到高维线性空间,再利用成熟的线性MPC技术实现高效控制。
这个方法的独特之处在于它巧妙结合了两个关键思想:一是Koopman算子理论,可以将非线性动力学系统转化为无限维线性系统;二是扩展动态模态分解(EDMD)算法,能够从实际飞行数据中学习出有效的有限维近似。特别值得一提的是,我们采用了基于旋转矩阵的物理信息驱动可观测量,避免了传统欧拉角表示中的奇异性问题,使得模型在SE(3)流形上具有更好的全局性质。
Koopman算子的核心思想是将非线性系统的状态空间映射到一个函数空间,在这个新的空间中,系统的演化表现为线性动力学。具体来说:
在实际应用中,我们通常采用数据驱动的方式学习Koopman算子。EDMD算法通过收集系统轨迹的"快照"数据,构建如下优化问题:
min‖G₊ - AK G‖₂² + λ‖A‖₂²
其中G是观测数据矩阵,A是待求的Koopman矩阵,λ是正则化参数。这个最小二乘问题的解给出了Koopman算子的有限维近似。
传统四旋翼建模通常采用欧拉角或四元数表示姿态,但这些方法存在固有缺陷:
我们的创新点在于直接使用旋转矩阵R∈SO(3)表示姿态,结合角速度ω∈ℝ³,构建如下状态向量:
x = [R₁₁, R₁₂, ..., R₃₃, ω₁, ω₂, ω₃]ᵀ
这种表示方式具有几个关键优势:
在实际实现EDMD算法时,有几个技术细节需要特别注意:
数据预处理:
可观测函数选择:
正则化处理:
基于学习得到的Koopman线性模型,我们可以构建如下MPC优化问题:
min_{u} ∑(x̂ₖᵀQx̂ₖ + uₖᵀRuₖ) + x̂_NᵀPx̂_N
s.t. x̂ₖ₊₁ = Âx̂ₖ + B̂uₖ
u_min ≤ uₖ ≤ u_max
Δu_min ≤ uₖ - uₖ₋₁ ≤ Δu_max
其中:
为了实现100Hz的实时控制,我们采用了以下优化技巧:
针对风扰等外部干扰,我们在基础框架上增加了两项增强:
matlab复制% 数据收集参数设置
dataParams = struct(...
'samplingTime', 0.01, ... % 10ms采样周期
'duration', 60, ... % 60秒记录时长
'inputRange', [0.7, 1.3], ... % 输入激励范围
'frequency', [0.1, 5]); % 激励信号频率范围
% 生成扫频激励信号
t = 0:dataParams.samplingTime:dataParams.duration;
u = chirp(t, dataParams.frequency(1), dataParams.duration, ...
dataParams.frequency(2)) * diff(dataParams.inputRange)/2 + ...
mean(dataParams.inputRange);
% 数据预处理函数
function [cleanData] = preprocessData(rawData)
% 低通滤波
[b,a] = butter(4, 10/(100/2));
cleanData = filtfilt(b, a, rawData);
% 异常值处理
medianData = movmedian(cleanData, 5);
diffData = abs(cleanData - medianData);
cleanData(diffData > 3*std(diffData)) = medianData(diffData > 3*std(diffData));
end
matlab复制function [A, B, C, obsFunc] = edmd(X, Y, U, obsFuncType)
% 构建可观测函数矩阵
switch obsFuncType
case 'poly2'
Psi_X = [X; kron(X, X)];
Psi_Y = [Y; kron(Y, Y)];
case 'so3'
% SO(3)特定的可观测函数
R = reshape(X(1:9,:), [3,3,size(X,2)]);
omega = X(10:12,:);
Psi_X = [X;
reshape(pagemtimes(R, reshape(omega,[3,1,size(X,2)])), [3,size(X,2)])];
Psi_Y = [Y;
reshape(pagemtimes(reshape(Y(1:9,:),[3,3,size(Y,2)]), ...
reshape(Y(10:12,:),[3,1,size(Y,2)])), [3,size(Y,2)])];
end
% 添加常值项
Psi_X = [ones(1,size(Psi_X,2)); Psi_X];
Psi_Y = [ones(1,size(Psi_Y,2)); Psi_Y];
% 构建增广矩阵
Z = [Psi_X; U];
% 最小二乘求解
AB = Psi_Y * pinv(Z);
A = AB(:,1:size(Psi_X,1));
B = AB(:,size(Psi_X,1)+1:end);
% 输出矩阵C (选择原始状态)
C = [zeros(size(X,1),1), eye(size(X,1)), zeros(size(X,1),size(Psi_X,1)-size(X,1)-1)];
% 返回可观测函数句柄
obsFunc = @(x) evalObsFunc(x, obsFuncType);
end
function psi = evalObsFunc(x, type)
% 可观测函数求值
switch type
case 'poly2'
psi = [1; x; kron(x,x)];
case 'so3'
R = reshape(x(1:9),3,3);
omega = x(10:12);
psi = [1; x; R*omega];
end
end
matlab复制classdef KoopmanMPC < handle
properties
A, B, C % Koopman模型矩阵
Q, R, P % 代价权重
N % 预测时域
umin, umax % 输入约束
dumin, dumax % 输入变化率约束
solver % QP求解器
prev_u % 上一时刻输入
end
methods
function obj = KoopmanMPC(A, B, C, Q, R, P, N, umin, umax, dumin, dumax)
% 初始化控制器参数
obj.A = A; obj.B = B; obj.C = C;
obj.Q = Q; obj.R = R; obj.P = P;
obj.N = N;
obj.umin = umin; obj.umax = umax;
obj.dumin = dumin; obj.dumax = dumax;
obj.prev_u = zeros(size(B,2),1);
% 初始化QP求解器
obj.initQP();
end
function initQP(obj)
% 构建QP问题的矩阵形式
nx = size(obj.A,1); nu = size(obj.B,2);
% 构建预测矩阵
Sx = zeros(nx*obj.N, nx);
Su = zeros(nx*obj.N, nu*obj.N);
for k = 1:obj.N
Sx((k-1)*nx+1:k*nx,:) = obj.A^k;
for j = 1:k
Su((k-1)*nx+1:k*nx,(j-1)*nu+1:j*nu) = obj.A^(k-j)*obj.B;
end
end
% 构建QP矩阵
Qbar = blkdiag(kron(eye(obj.N-1),obj.Q), obj.P);
Rbar = kron(eye(obj.N),obj.R);
H = Su'*Qbar*Su + Rbar;
f = @(x,r) Sx'*Qbar*Su*(x - repmat(r,obj.N,1));
% 构建约束矩阵
Aineq = [eye(nu*obj.N); -eye(nu*obj.N);
tril(ones(nu*obj.N)); -tril(ones(nu*obj.N))];
bineq = [repmat(obj.umax,obj.N,1); -repmat(obj.umin,obj.N,1);
repmat(obj.dumax,obj.N,1) + [obj.prev_u; zeros((obj.N-1)*nu,1)];
-repmat(obj.dumin,obj.N,1) - [obj.prev_u; zeros((obj.N-1)*nu,1)]];
% 保存QP参数
obj.solver = struct('H',H, 'f',f, 'Aineq',Aineq, 'bineq',bineq);
end
function [u, x_pred] = solve(obj, x, r)
% 求解MPC问题
H = obj.solver.H;
f = obj.solver.f(x,r);
Aineq = obj.solver.Aineq;
bineq = obj.solver.bineq;
% 调用QP求解
options = optimoptions('quadprog', 'Display', 'off');
U = quadprog(H, f, Aineq, bineq, [], [], [], [], [], options);
% 提取控制输入
nu = size(obj.B,2);
u = U(1:nu);
obj.prev_u = u;
% 预测状态轨迹
x_pred = zeros(size(obj.A,1), obj.N);
x_pred(:,1) = obj.A*x + obj.B*u;
for k = 2:obj.N
x_pred(:,k) = obj.A*x_pred(:,k-1) + obj.B*U((k-1)*nu+1:k*nu);
end
end
end
end
我们搭建了完整的仿真测试平台,主要配置如下:
硬件环境:
软件环境:
无人机参数:
我们设计了多种测试轨迹来评估Koopman模型的预测能力:
正弦扫频测试:
8字形轨迹测试:
阶跃响应测试:
我们将Koopman-MPC与两种基准方法进行了对比:
传统PID控制器:
非线性MPC:
控制器在三种不同硬件平台上的表现:
高性能桌面:
嵌入式平台(NVIDIA Jetson Xavier):
低功耗处理器(Raspberry Pi 4):
激励信号设计:
数据质量检查:
交叉验证策略:
量化指标:
权重调整技巧:
约束处理:
实时性优化:
Koopman-MPC框架可扩展至多无人机系统:
集中式架构:
分布式架构:
增强系统的自适应能力:
递归EDMD:
集成学习:
提升计算效率的硬件方案:
FPGA加速:
GPU并行:
专用AI芯片: