简介:面向无人机控制与模型预测控制学习者的避障实践素材,聚焦四阶无人机在三维空间中的前后、左右、升降与偏航运动建模,并借助MATLAB实现滚动预测与优化求解,帮助理解如何根据未来位置姿态规划安全飞行路径。压缩包为rar格式,内含1个m脚本文件,整体约1KB,体量轻便,适合直接阅读算法框架并在此基础上修改优化目标与约束条件。已有1631人学习下载,说明该主题在控制算法入门与课程实践中具有一定关注度。内容围绕MPC的核心环节展开,包括预测模型、优化函数设计以及避障策略中的约束处理,读者可从中体会最小化飞行时间、保持安全距离或恒定高度等目标如何转化为优化问题,并了解传感器数据参与实时路径更新的思路。对于需要完成无人机避障仿真、课程设计或算法二次开发的读者,这份脚本可作为起点,便于对照调整参数、复现实验并扩展至更复杂的非线性场景。
1. 一个反直觉的结论:MPC 避障的难点从来不是“最优”,而是“有解”
很多人第一次用 matlab 为无人机搭建模型预测控制(MPC)避障时,都会很兴奋:状态方程写出来,代价函数里加入位置误差和加速度惩罚,再把障碍物定义成“距离必须大于 r”的硬约束,用quadprog一调用,就会觉得已经做成了。仿真里路径贴着障碍物边缘绕过去,看起来很专业。
实际运行结果往往相反:要么无人机在障碍物前三四米处来回摆动或原地画圈,要么求解器直接返回exitflag = -2,程序没有处理这个错误,把上一拍的控制量继续下发,无人机就直直撞了上去。
问题的原因不在避障那一项约束写错了,而在于“滚动时域”这个结构本身。MPC 每一拍都要求解一条长度为 N 的预测轨迹,却只执行其中第一步;因此约束必须对整条预测轨迹成立。轨迹尾段的可行性,反过来决定了当前这一拍能否解出一个控制量。这层因果关系是模型预测控制避障最容易被忽略的底层逻辑,也是它和“一次规划一条路径”的传统避障算法(如 A*、RRT)最大的分歧所在。
2. 滚动时域:MPC 为什么“算一整条、只走一小步”还能稳定
2.1 从一次最优到反复最优:优化循环里的时序拆解
传统轨迹规划的思路是“算完再走”:用当前环境生成一条从起点到终点的完整路径,把它交给控制器,控制器按时间戳依次跟随。这种做法假设环境静态、模型准确、没有扰动;而无人机避障恰好三条都不满足:障碍物可能移动,模型只有近似,风扰始终存在。一旦实际位置偏离了规划轨迹,整条轨迹就作废了。
模型预测控制更换了计算方式:它不再追求“全局最优的一条线”,而是每一拍都重新求解一次有限时域的最优控制问题。具体时序是这样的:在时刻 k,读取当前状态 x(k),用预测模型推演未来 N 步在不同控制序列下的演化,在满足约束的前提下最小化代价函数,得到一串控制量 u(k), u(k+1), …, u(k+N-1),然后只取 u(k) 真正下发,剩下的 N-1 个全部丢弃。下一拍 k+1 时,用新的实测状态重新来一遍。
这个“丢弃”动作是整个机制的支撑点。它把开环的最优解变成了闭环的反馈律:每一拍都拿真实状态当作初值,等于把反馈信号注入优化过程本身,而不是靠外层的 PID 事后修正。从控制论的角度看,MPC 本质上是一个用在线优化实现的非线性状态反馈控制器,只是这个反馈律没有解析表达式,必须通过数值求解。
还有一个常被忽略的细节:预测时域 N 和控制时域 Nc 可以不一样。当 Nc < N 时,认为第 Nc 步之后控制量保持不变,未知变量减少,QP 规模降下来,代价是对尾段的控制自由度做了简化。在算力有限的机载平台上,这通常是第一个被采用的近似。
2.2 预测模型:双积分无人机怎么离散成 Ad 和 Bd
预测模型是 MPC 的基础。模型错了,后面所有优化都是在错误的基础上求精确。无人机的外环位置控制普遍用双积分模型,这不是偷懒,而是由微分平坦性质决定的:四旋翼的位置输出与推力矢量之间存在平坦映射,位置的四阶导数与姿态角速率直接相关。大多数飞控的底层接口接受位置、速度、加速度三层的 setpoint,外环用双积分建模,和下层接口是自洽的。
状态量取 x = [p, v](三维位置加三维速度,共 6 维),控制量取 u = a(三轴加速度指令,3 维)。连续方程是:p_dot = v,v_dot = u。写成矩阵形式,A 是 6×6 的分块矩阵,B 是 6×3 的分块矩阵。离散化用零阶保持(ZOH),双积分有解析解,不需要调用c2d:
p(k+1) = p(k) + T*v(k) + 0.5*T^2*u(k)v(k+1) = v(k) + T*u(k)
所以Ad = [I, T*I; 0, I],Bd = [0.5*T^2*I; T*I]。这里 T 是控制周期,这个参数的选择在后面第 6 章会详细讨论,因为它直接决定了整个闭环的稳定裕度和计算压力。
值得停下来想一下:为什么不用更精确的六自由度模型(含姿态动力学)?因为那会引入强非线性和四元数归一化约束,QP 立刻退化成非线性规划,求解时间从毫秒级涨到几十毫秒,机载算力承受不了。常见的工程做法是外环位置用双积分做 MPC,内环姿态用 PID 或几何控制器高速跟随,把姿态环的时延近似成一阶惯性环节串进位置模型。这是一种“故意用低阶模型换取可解性”的取舍,代价是模型失配,而模型失配靠滚动时域的反馈特性去吸收。
2.3 只执行第一步的代价与回报
只执行第一步听上去很浪费:算了 N 步只用了 1 步,剩下 N-1 步的计算全部作废,下一拍还要从头再算一遍。这个“浪费”换来了三样东西。
第一是抗扰。假设飞行中遇到一个常值侧风,模型里没有这一项,开环轨迹会整体漂移。但每一拍都用实测位置做初值,漂移立刻体现在 x(k) 里,优化器会自动在下一拍把偏差补回去。这在效果上等价于一个积分环节,但补偿方向是从约束和代价里推导出来的,而不是靠人工调积分增益。
第二是模型失配的容忍。双积分模型忽略了姿态环的动态,实际加速度指令到真实加速度之间有几十毫秒的滞后。这个滞后在单次开环规划里会累积成可见的位置误差,但在滚动优化里,每一拍的实测状态都会把误差拉回正轨,误差不会长期累积。
第三是约束的动态可行。因为预测窗口一直在向前滑动,障碍物信息可以每拍更新。如果前方突然出现一个新障碍物,只要它在当前预测窗口内,约束立刻生效,无人机就开始减速绕行,不需要重规划整条全局路径。
代价也很清楚:计算量是持续的开销,每拍都要解一次 QP;而且 MPC 是“短视”的,它只对预测窗口内的约束负责。窗口外的障碍物,模型预测控制看不见,也不会提前做出任何反应。这就是为什么实际系统里,MPC 一般不单独使用,前面还会有一层全局规划给出粗糙的参考走廊,模型预测控制负责在走廊内做局部避障和跟踪。
3. 代价函数与约束:避障如何转化为可求解的二次型
3.1 Q 与 R 的物理含义:两个权重在互相拉扯什么
MPC 的标准代价函数长这样:
J = Σ (x_k - x_ref)' Q (x_k - x_ref) + Σ u_k' R u_k + (x_N - x_ref)' Qf (x_N - x_ref)
Q 惩罚状态偏差,R 惩罚控制量,Qf 是终端代价。这三个矩阵不是玄学调参,它们每一个都在回答一个具体的工程问题。
Q 决定“多想去目标点”。Q 里的位置项调大,无人机就表现得激进,更快收敛到参考轨迹,但也更容易贴着障碍物边缘走,因为绕远路意味着更大的位置误差。Q 里的速度项通常比位置项小一个数量级,比如位置权重取 10、速度权重取 1,含义是“到达位置比速度匹配更重要”,允许在接近目标时速度自然衰减。
R 决定“多舍不得用力”。R 调大,控制量被压小,轨迹平滑、省电、对执行器友好,但响应变慢,遇到突发障碍物时可能刹不住。R 调小,机动性强,但容易出现控制量高频抖动,实际飞行时电机发热、姿态环震荡。
真正需要警惕的是 Q 和 ρ(软约束惩罚系数)之间的比例关系,这个在第 3.2 节展开,它是避障失效最常见的原因。
终端代价 Qf 值得单独说一句。它的作用是近似“N 步之后还剩多少代价”,通常取离散代数 Riccati 方程的解 P,这样能在有限时域下近似出无限时域的最优性,改善闭环稳定性。工程上如果懒得解 Riccati,直接把 Qf 设成 5 到 10 倍的 Q,也能起到“终端要收敛”的引导作用,代价是保守性变强。
3.2 距离约束为什么必须软化:硬约束的可行域会被需求限制为空
这是整篇里最关键的一节。
障碍物约束的原始写法是:对预测轨迹上的每一步 k,||p_k - p_obs|| >= r。它表示一条圆形禁区。硬约束意味着这条永远不能被违反,一旦违反,QP 就无解。
现在想象一个具体场景:无人机以 8 m/s 的速度朝障碍物飞,控制周期 0.1 s,预测时域 20 步也就是 2 秒。障碍物在正前方 10 米处,膨胀后的安全半径 1.5 米。优化器一看,2 秒后按当前速度会飞到障碍物里面,于是要求轨迹在窗口内绕开。但物理上,8 m/s 的速度在 0.1 秒内只能改变 0.8 m/s 的速度(受加速度上限约束),第 1 步到第 3 步的轨迹几乎完全由初速度决定,压根来不及拐弯。约束要求第 5 步就必须在障碍物侧面,但前 4 步无法到达,于是整条轨迹不存在,QP 直接报告不可行。
这就是硬约束的风险:约束是对整条轨迹同时施加的,前段的动力学不可达会直接导致整个问题无解,而不是“尽力而为”。
软约束的写法是引入松弛变量 s_k >= 0:||p_k - p_obs|| >= r - s_k,同时在代价里加一项ρ * Σ s_k。它的物理解释非常直观:给“撞进禁区”标一个价格。ρ 足够大时,优化器只有在别无选择时才愿意付出这个代价;ρ 不够大时,优化器会发现“直接穿过去”比“绕一大圈”更划算,于是主动撞上去,这在调试时表现为无人机无视障碍物,是最常见也最让人抓狂的 bug。
经验上 ρ 要比 Q 里最大的权重高两到三个数量级。位置权重如果是 10,ρ 取 1000 到 10000。这个数量级不是随便定的:它要保证即使绕行带来很大的位置误差累积,绕行的总代价仍然低于直接穿越。
提示:软约束的松弛变量必须加下界 s >= 0,否则优化器会取负值来“提前预支”未来步的松弛,导致约束在数值上被抵消掉。
3.3 非凸避障约束的三种凸化路线:半空间、膨胀圆与整数规划
||p - p_obs|| >= r是非凸约束:可行域是圆外面,中间有个洞。二次规划只接受凸约束(线性不等式),所以必须先凸化。业界有三条主流路线,各自的保守性和计算代价差别很大。
第一条是半空间线性化,也是最常用的。在上一拍的解 p*_k 处取一个法向量n_k = (p*_k - p_obs) / ||p*_k - p_obs||,把圆形约束替换成半空间n_k' * (p_k - p_obs) >= r。这相当于在障碍物表面切一刀,要求轨迹待在这一侧。因为 n_k 是从上一拍解算出来的,它带来的是“序列凸化”的结构:每一拍解一次,用新解更新法向,下一拍再解。在滚动时域里这几乎是免费的,因为本来就要每拍重算。缺点是当轨迹需要绕着障碍物转动方向时,法向更新有滞后,可能多绕一点路。常见的补救是用上一拍解的若干步做平滑,而不是只取一个点。
第二条是保守膨胀。把障碍物半径从真实的 r_obs 放大到r_obs + r_uav + margin,其中 r_uav 是机体半径,margin 是跟踪误差余量,通常取 0.3 到 0.5 米。这个做法不改约束形式,只是把半径调大,相当于用保守性换取安全性。它不是凸化手段,但能和半空间线性化叠加使用,效果是把“理论上可能擦边”的概率压到很低。工程上这条几乎是必选项:模型里的位置是理想质点,真实机体有尺寸,姿态倾斜时旋翼外缘的投影半径还会变大。
第三条是混合整数规划。用大 M 法引入二进制变量,表示“无人机在障碍物的左侧还是右侧”,从而在凸优化框架里精确表达非凸的择一逻辑。这种写法数学上很漂亮,能保证全局最优而不只是局部可行。问题是求解时间:每多一个障碍物、每多一步预测,二进制变量就翻倍,求解时间从毫秒级跳到几十甚至上百毫秒,机载实时控制承受不了。它一般用在离线规划,或者起降、低速精细作业这类允许长计算周期的场景。
还有一条介于两者之间的思路:把势场函数当作软惩罚项塞进代价,形如k / (||p - p_obs||^2 + eps),障碍物附近代价急剧上升,优化器自然会避开。它是光滑可微的,可以交给fmincon这类非线性求解器。缺点同样明显:势场在障碍物附近梯度极大,容易导致数值病态;而且它只是“劝说”而不是“约束”,在极端情况下仍然可能穿过去。所以更常见的组合是:势场做初值或引导项,QP 半空间约束做精修与兜底。
4. MATLAB 实现骨架:从状态方程到 quadprog 的完整链路
4.1 预测矩阵拼装:Phi 和 Gamma 的构成
整个 MPC 在代码层面只有一件事:把“未来 N 步状态”表示成“当前状态 + 未来 N 步输入”的线性组合。因为模型是线性的,这个关系可以显式写出来:
X = Phi * x0 + Gamma * U
其中 X 是把 N 步状态竖着摞起来的 6N 维向量,U 是把 N 步控制量摞起来的 3N 维向量。Phi 是 6N×6 的自由响应矩阵,Gamma 是 6N×3N 的强迫响应矩阵,且是下三角分块结构(第 k 步只受前 k 步输入影响)。
% 双积分无人机模型离散化 + 预测矩阵拼装 T = 0.1; % 控制周期 (s),和飞控主循环对齐 N = 20; % 预测时域步数,对应 2s 的前瞻 nx = 6; nu = 3; % 状态维数(位置3+速度3) / 控制维数(三轴加速度) % 连续系统: p_dot = v, v_dot = a Ac = [zeros(3) eye(3); zeros(3) zeros(3)]; Bc = [zeros(3); eye(3)]; % 双积分有解析离散解,不需要 c2d,避免符号运算开销 Ad = [eye(3) T*eye(3); zeros(3) eye(3)]; Bd = [0.5*T^2*eye(3); T*eye(3)]; % 堆叠: X = Phi*x0 + Gamma*U Phi = zeros(nx*N, nx); Gamma = zeros(nx*N, nu*N); Ak = eye(nx); for k = 1:N Ak = Ad * Ak; % A^k Phi((k-1)*nx+1:k*nx, :) = Ak; for j = 1:k Gamma((k-1)*nx+1:k*nx, (j-1)*nu+1:j*nu) = (Ad^(k-j)) * Bd; % A^(k-j)*B end end这段代码的核心是两层循环里的Ad^(k-j) * Bd:它表达“第 j 步施加的加速度,经过 k-j 步的积分累积,对第 k 步状态产生的影响”。位置通道累积的是0.5*T^2再叠加后续速度积分,所以 Gamma 的上半部分(位置行)块不是常数,而是随 k-j 增长。这个结构说明了一个物理事实:越早施加的控制,对轨迹尾段的影响越大,这也是预测时域越长、前期控制越保守的原因。
Phi和Gamma都是常值矩阵,只要 T 和 N 不变,它们在整个飞行过程中只算一次,必须放在循环外面。把它放进主循环是新手最常见的性能问题,后面第 5 章会详细说明。
4.2 QP 标准型拼装与滚动主循环
有了 Phi 和 Gamma,代价函数J = (X - Xref)'Qbar(X - Xref) + U'Rbar U展开后就是 U 的二次型。标准 QP 形式是min 0.5*U'*H*U + f'*U,对应关系是 H = 2*(Gamma'QbarGamma + Rbar),f = 2Gamma'Qbar(Phi*x0 - Xref)。注意 f 里含 x0,所以 f 每拍都要重算,而 H 是常值。
Q = diag([10 10 10 1 1 1]); % 位置权重远大于速度权重: 到点优先 R = 1e-1 * eye(3); % 加速度惩罚: 抑制抖振、保护电机 Qbar = kron(eye(N), Q); % 块对角展开到整个时域 Rbar = kron(eye(N), R); H = 2*(Gamma'*Qbar*Gamma + Rbar); H = (H + H')/2; % 强制对称, 消掉浮点误差导致的求解器报警 umax = 5; % 单轴加速度上限 (m/s^2) Ain = [eye(nu*N); -eye(nu*N)]; % |u| <= umax 拆成两条 bin = [repmat(umax, nu*N, 1); repmat(umax, nu*N, 1)]; opts = optimoptions('quadprog','Display','off', ... 'Algorithm','interior-point-convex', ... 'MaxIterations',200); U0 = zeros(nu*N,1); % 热启动初值 for t = 1:length(tspan) % 1) 拼一次项: 只和当前实测状态有关 f = 2 * Gamma' * Qbar * (Phi*x(:,t) - Xref); % 2) 求解, 传入上一拍解做 warm start [U, ~, flag] = quadprog(H, f, Ain, bin, [], [], [], [], U0, opts); % 3) 无解兜底: 沿用上一拍解, 绝不把失控量下发 if flag ~= 1 U = U0; end u = U(1:nu); % 只执行第一步 x(:,t+1) = Ad*x(:,t) + Bd*u; % 推进真实系统(仿真中即模型) % 4) 热启动: 解整体前移一拍, 末尾补一拍保持维数 U0 = [U(nu+1:end); U(end-nu+1:end)]; end几个关键点。H = (H+H')/2这行看着多余,实际上quadprog对非对称 H 只取上三角,浮点误差会让结果和你预期的不一致,强制对称是标准做法。flag ~= 1的兜底分支是整个代码里最重要的容错设计,真实系统绝不能让一次求解失败变成一次撞击。热启动把上一拍解前移作为初值,对内点法效果有限(内点法对初值不敏感),但对有效集法和一阶方法能显著减少迭代次数。
4.3 障碍物约束如何加入 A 矩阵
把 3.3 节的半空间线性化落地成代码。对每个障碍物、每一步 k,约束是n_k' * (p_k - p_obs) >= r。把p_k = C * (Phi_k*x0 + Gamma_k*U)代进去,整理成A_row * U <= b_row的形式:
C = [eye(3) zeros(3)]; % 从 6 维状态里取出位置分量 A_obs = []; b_obs = []; for k = 1:N rows = (k-1)*nx+1 : k*nx; for i = 1:numel(obs) % 法向取当前实测位置指向障碍物, 或用上一拍预测解, 后者更平滑 nk = ( p_now - obs(i).c ) / norm(p_now - obs(i).c); Grow = C * Gamma(rows, :); % 3 x (nu*N) pfree = C * Phi(rows, :) * x(:,t); % 自由响应下的位置 A_obs = [A_obs; -nk' * Grow]; % 注意负号: 转成 <= b_obs = [b_obs; nk'*(pfree - obs(i).c) - obs(i).r]; end end Ain = [Ain; A_obs]; bin = [bin; b_obs]; % 与输入幅值约束拼在一起pfree是“不施加任何控制时,靠惯性飞到第 k 步的位置”,用它来构造不等式右端,含义是“在当前惯性趋势下,到第 k 步时相对障碍物还差多少距离才安全”。负号那行最容易写错:quadprog的约定是A*x <= b,而避障约束天然是>=,符号搞反会让约束变成“必须撞上去”,症状是无人机主动朝障碍物飞,非常迷惑。
参数上,obs(i).r是膨胀后的半径,等于真实半径加上机体半径和余量,这一步千万别省。nk用实测位置算还是用上一拍预测解算,效果差别很大:实测位置算出来的法向变化剧烈,轨迹容易抖;用预测解算出来的法向连续,但需要先有一个可行解。常见的折中是第一拍用实测位置,之后用求解结果,并对法向做一阶低通。
5. 避障翻车现场:五类高频问题的排查路径
5.1 求解器返回不可行:可行域是如何被需求限制为空的
现象:quadprog返回flag = -2,日志里一堆“no feasible point found”。如果代码里没有兜底分支,无人机直接执行上一拍的老控制量冲出去。
原因:三种典型诱因。一是预测时域过长而加速度上限太小,物理上根本刹不住,前几步轨迹被初速度完全支配,约束要求后几步远离障碍,两者矛盾。二是多个障碍物的半空间同时生效,把可行域限制成空集,尤其是两个障碍物距离较近时,两侧的半空间互相冲突。三是硬约束下所有松弛变量被设成 0,没有任何回旋余地。
解决:优先把所有障碍物约束改成软约束,松弛变量留正,ρ 取大值。其次缩短预测时域 N,从 20 降到 10 到 12,让窗口内的轨迹是可机动调整的。再者在靠近障碍物前主动降速,把速度上限做成随距离衰减的函数,这是最有效也最容易被忽略的一招:刹不住的本质是速度太快,而不是优化器不够聪明。
5.2 轨迹抖动与边界横跳:法向跳变和硬约束的组合效应
现象:无人机在障碍物前方左右摆动,或者绕着障碍物画小圈。遥测曲线上看,控制量每拍符号翻转,角速度指令高频震荡。
原因:法向量nk每一拍根据当前位置重算,位置微小的变化会让 nk 大幅转动,半空间的方向随之跳变。上一拍要求“从左边过”,这一拍可能变成“从右边过”,优化器在两解之间来回横跳。如果约束是硬的,边界上不存在缓冲,抖动被放大器放大。
解决:对 nk 做时间上的一阶低通,nk = alpha*nk_prev + (1-alpha)*nk_new,alpha 取 0.7 到 0.9。把避障约束软化之后,抖动自然会消失一大半,因为松弛变量吸收了边界附近的震荡。另外检查 R 是否太小,控制量惩罚不足时,优化器会用剧烈的高频机动来换取微小的位置收益,这种解在数学上最优,在物理上不能用。
5.3 仿真好看、实飞撞墙:模型误差与实时性两条线
现象:Simulink 里轨迹完美,实飞时贴着障碍物擦过去甚至撞上。日志回放发现实际位置比预测位置滞后了半米左右。
原因:一是模型太简,双积分忽略姿态环时延和推力饱和,实际加速度达不到指令值,尤其在急停急转时差距最大。二是求解耗时超过控制周期,控制量基于过期的状态算出来,等于人为引入了延迟。
解决:模型里串一个一阶惯性环节近似姿态响应,a_actual(k+1) = a_actual(k) + (T/tau)*(u(k) - a_actual(k)),tau 取实测的阶跃响应时间常数。把状态量扩一维进去,QP 结构不变。实时性方面,先用tic/toc量一下单次求解耗时,如果超过周期的 50%,就得动手:预计算 H、开启热启动、把 N 降下来、或者把quadprog换成能生成 C 代码的方案。
5.4 障碍物明明很远却已经开始绕:膨胀半径设得过大
现象:无人机在距离障碍物三四米的地方就开始大幅度偏航绕行,路径非常保守,甚至绕不回来。
原因:obs(i).r把真实半径、机体半径、跟踪误差余量、还有预测时域内可能的漂移全部叠加在一起,导致安全圆膨胀得比实际需要大很多。时域越长,为了覆盖尾段的不确定性,余量往往被加倍预留。
解决:把余量做成和速度相关的函数,低速时用小余量,高速时用大余量,而不是全局一个常数。另外检查膨胀半径是不是被错误地乘了 N 步。一个实用的自检方法是把求解出来的预测轨迹画出来,看每一步到障碍物中心的距离,如果最小距离远大于 r,说明膨胀过度,可以收紧。
5.5 权重调完之后一切正常,换个场景又不行
现象:在空旷场景调好的 Q、R、ρ,换到狭窄走廊里立刻失效,要么穿墙要么卡死。
原因:固定权重本质上是在“跟踪精度”“控制平滑”“避障优先级”三者之间定了一个静态的兑换比例。场景变化时,这个比例的最优值会变。狭窄环境需要避障优先级极高,开阔环境需要跟踪精度优先。
解决:把 ρ 做成随距离动态调整的:距离越近 ρ 越大,形成“越靠近越不敢碰”的软墙效应。或者引入场景自适应,检测到障碍物密度上升时整体放大 ρ 并缩小速度上限。这类改动的血泪经验是:任何动态调整都要加限幅和平滑,否则参数突变本身就会引起抖动,比原来的问题更难排查。
6. 预测时域、控制周期与保守性的三角取舍
把前面几章的内容汇总,会发现三个参数之间存在牵制:预测时域 N、控制周期 T、以及为了安全留出的保守余量。它们之间的关系不是独立的。
N*T 是前瞻的物理时长。前瞻太短,无人机“看不见”远处的障碍,等它进入窗口时已经来不及机动,只能靠软约束兜底,表现为临门一脚的急刹。前瞻太长,窗口尾段的轨迹被初速度主导,约束很难满足,可行域容易被限制为空,同时 QP 规模按 N 的三次方增长(H 是 3N×3N 的稠密矩阵),求解时间会迅速上升。
T 的选择同样有两面性。T 太小,控制频率高、响应快,但每拍能改变的动量少,同样的物理时长需要更多步,N 变大,计算量上升。T 太大,单步内的模型误差被放大,双积分模型的近似精度下降,姿态环的滞后没法忽略。
下面这组数据来自一个 2 米见方的室内场景调参记录,仅供参考趋势:
| 时域 N | 周期 T | 前瞻时长 | 单次求解耗时 | 表现 |
|---|---|---|---|---|
| 10 | 0.1 s | 1.0 s | 约 3 ms | 窗口偏短,高速时来不及绕,靠软约束急刹 |
| 20 | 0.1 s | 2.0 s | 约 12 ms | 综合表现最佳,能提前 1 秒开始减速绕行 |
| 40 | 0.1 s | 4.0 s | 约 70 ms | 尾段不可达约束多,频繁不可行,且耗时超过周期 |
| 20 | 0.05 s | 1.0 s | 约 12 ms | 响应更细腻,但前瞻不足,需配合降速 |
一个实用的判断方法是:让前瞻时长覆盖“以最大速度从当前状态刹停所需时间”的 1.5 到 2 倍。刹停时间约等于当前速度除以最大加速度,8 m/s 除以 5 m/s² 是 1.6 秒,前瞻就该在 2.4 到 3.2 秒之间。这个公式不精确,但它把“时域长度”从玄学调参变成了一个有物理依据的估算,比盲目试 N 快得多。
另一个值得认真对待的设计取舍是:要不要加终端约束。理论上,加上终端不变集和终端代价能保证闭环稳定性与递归可行性,也就是“只要这一拍有解,下一拍必有解”。但终端不变集的计算本身不便宜,而且它会大幅收紧可行域,在狭窄场景下反而更容易无解。所以工程实现的常见做法是放弃严格的终端不变集,改用终端代价 Qf 做软引导,再用无解兜底 + 降速策略作为工程层面的“后悔药”。这是一个用理论严格性换实际鲁棒性的典型取舍,值不值得取决于场景:空旷环境可以严格,狭窄环境必须先保证有解。
从那以后,我每次为新机型配 MPC 避障参数,都会强制走一遍同一个流程:先算刹停时间定前瞻,再把所有障碍约束改成软约束并检查 ρ 的量级,最后用日志回放确认每一拍的最小障碍距离是否远大于膨胀半径。跳过任何一步,后面都要用实飞事故来补。希望帮到你。
本文还有配套的精品资源,点击获取