1. 项目概述:运动学模型与MPC轨迹跟踪的Matlab实践
在自动驾驶和机器人控制领域,轨迹跟踪是核心问题之一。最近我用Matlab完整实现了一套基于运动学模型的MPC(模型预测控制)轨迹跟踪方案,整个过程从建模到实现全部采用纯Matlab代码完成,没有依赖Simulink或其他工具箱。这种方案特别适合学术研究和小型无人系统开发,因为Matlab的矩阵运算和优化工具包能极大简化MPC的实现难度。
传统PID控制在处理非线性系统和约束条件时表现不佳,而MPC通过在线优化未来时间窗口内的控制序列,能够显式处理各种约束(如速度限制、转向角限制等)。我选择自行车模型作为运动学基础,因为它在低速场景下(<5m/s)能很好平衡精度和计算复杂度。实测下来,这套方案在1kHz的控制频率下,单步优化耗时仅2-3ms(使用Matlab的quadprog求解器),完全能满足实时性要求。
2. 运动学模型构建与离散化
2.1 自行车模型推导
自行车模型是车辆运动学控制的黄金标准,它假设前后轮可以合并为单个轮子。模型状态包括:
- (x,y):车辆后轴中心坐标
- φ:航向角
- v:车速
- δ:前轮转向角
连续时间模型可以表示为:
ẋ = v*cos(φ) ẏ = v*sin(φ) φ̇ = (v/L)*tan(δ)其中L是轴距。这个模型有两个输入:加速度a和转向角速度ω。
注意:该模型假设无侧滑,当车速较高或地面摩擦系数低时,需改用动力学模型
2.2 离散化处理
MPC需要在离散时间域工作,我采用前向欧拉法进行离散化(时间步长dt=0.01s):
x(k+1) = x(k) + v(k)*cos(φ(k))*dt y(k+1) = y(k) + v(k)*sin(φ(k))*dt φ(k+1) = φ(k) + (v(k)/L)*tan(δ(k))*dt v(k+1) = v(k) + a(k)*dt δ(k+1) = δ(k) + ω(k)*dt离散化后的状态空间方程可表示为:
function x_next = bicycle_model(x, u, L, dt) % x = [px, py, phi, v, delta] % u = [a, omega] x_next = x + [ x(4)*cos(x(3))*dt; x(4)*sin(x(3))*dt; (x(4)/L)*tan(x(5))*dt; u(1)*dt; u(2)*dt; ]; end3. MPC控制器设计
3.1 预测模型与优化问题
MPC的核心是在每个控制周期求解如下优化问题:
min J = Σ(跟踪误差) + Σ(控制量惩罚) + Σ(控制变化率惩罚) s.t. 运动学约束 控制量约束 状态约束我设计的代价函数包含三项:
- 状态误差惩罚:(x-x_ref)'Q(x-x_ref)
- 控制量惩罚:u'Ru
- 控制变化率惩罚:Δu'RΔΔu
对应的Matlab实现:
Q = diag([10, 10, 5, 2, 1]); % 状态权重 R = diag([0.1, 1]); % 控制量权重 Rdelta = diag([0.01, 0.1]); % 控制变化率权重 H = blkdiag(kron(eye(N),Q), kron(eye(Nc),R), kron(eye(Nc),Rdelta)); f = zeros(size(H,1),1);3.2 约束处理技巧
实际车辆存在物理限制,必须处理以下约束:
- 速度范围:0 ≤ v ≤ 10 m/s
- 转向角范围:-30° ≤ δ ≤ 30°
- 加速度范围:-3 ≤ a ≤ 3 m/s²
- 转向速度范围:-30°/s ≤ ω ≤ 30°/s
在Matlab中通过quadprog的A、b矩阵设置这些约束:
Aineq = [...]; % 构建不等式约束矩阵 bineq = [...]; % 构建不等式约束边界 options = optimoptions('quadprog','Display','off'); [u_opt,~,exitflag] = quadprog(H,f,Aineq,bineq,[],[],[],[],[],options);实操心得:初始调试时可先去掉约束,确认基本功能正常后再逐步添加约束,便于问题定位
4. 轨迹生成与跟踪实现
4.1 参考轨迹生成
我采用三次样条曲线生成平滑参考轨迹。首先生成路径点,然后用spline插值:
waypoints = [0 0; 5 2; 10 -1; 15 3]; t = cumsum([0; sqrt(sum(diff(waypoints).^2,2))]); ref_path = spline(t, waypoints', linspace(0,t(end),1000))';对于每个参考点,还需要计算参考速度和航向角:
dx = gradient(ref_path(:,1)); dy = gradient(ref_path(:,2)); phi_ref = atan2(dy, dx); v_ref = 2*ones(size(phi_ref)); % 恒定速度2m/s4.2 闭环控制流程
完整的MPC跟踪算法流程如下:
- 获取当前状态x(k)
- 从参考轨迹提取N个点的参考序列
- 构建QP问题矩阵H,f,A,b
- 调用quadprog求解最优控制序列
- 应用第一个控制量u(k)
- 等待下一个控制周期
核心循环代码结构:
while k < length(ref_time) % 获取当前参考轨迹窗口 ref_window = get_reference_window(k, N, ref_path); % 构建QP问题 [H, f, A, b] = build_mpc_problem(x_current, ref_window, Q, R, Rdelta); % 求解MPC u_opt = solve_mpc(H, f, A, b); % 应用控制量 x_current = bicycle_model(x_current, u_opt(1:2), L, dt); % 记录数据 X_history(:,k+1) = x_current; U_history(:,k) = u_opt(1:2); k = k + 1; end5. 性能优化与调试技巧
5.1 计算效率提升
纯Matlab实现容易遇到性能瓶颈,我采用了以下优化措施:
- 预分配所有数组内存
- 将H矩阵构建改为增量更新(90%元素不变)
- 使用persistent变量保持求解器状态
- 将频繁调用的函数转为pcode
优化前后对比:
| 操作 | 原始耗时(ms) | 优化后(ms) |
|---|---|---|
| H矩阵构建 | 1.8 | 0.3 |
| QP求解 | 2.1 | 1.9 |
| 状态更新 | 0.05 | 0.02 |
5.2 调试常见问题
- 求解器失败:检查H矩阵是否正定(添加小量单位矩阵)
- 跟踪振荡:增大控制变化率惩罚Rdelta
- 滞后严重:减小预测时域或提高速度权重
- 约束冲突:检查约束条件是否自相矛盾
典型调试命令:
% 检查H矩阵条件数 cond(H) % 可视化预测序列 plot_prediction(x_current, u_opt) % 验证梯度计算 check_gradient(@cost_function, x0)6. 扩展应用与进阶方向
这套基础框架可以扩展为:
- 考虑道路边界约束(增加状态不等式约束)
- 加入障碍物避碰(在QP中添加距离约束)
- 多车协同控制(分布式MPC)
- 参数自适应(在线调整Q,R权重)
对于更复杂的场景,我建议:
- 改用C++实现提升速度(使用ACADO或HPIPM求解器)
- 加入动力学模型(魔术公式轮胎模型)
- 结合SLAM实现完全自主导航
我在实际测试中发现,当引入路面坡度估计时,需要在状态方程中添加θ(俯仰角)状态,这会增加模型复杂度但能显著提升爬坡性能。另一个实用技巧是在弯道处根据曲率动态调整参考速度,这能减少侧向误差。