markdown复制## 1. 项目概述
轨迹跟踪是自动驾驶和机器人控制领域的经典问题。最近我在研究如何用CasADi框架实现模型预测控制(MPC)来解决这个问题,发现这个组合在计算效率和实现便捷性上都有独特优势。本文将分享我用Matlab实现的完整方案,包含动力学建模、MPC设计、仿真验证的全过程代码。
质点车辆模型虽然简单,但能清晰展示MPC的核心思想。CasADi作为符号计算框架,可以自动求导并生成高效C代码,特别适合优化控制问题。实测在i5处理器上单次MPC求解仅需2ms,完全满足实时控制需求。
## 2. 核心原理与工具选型
### 2.1 为什么选择MPC?
模型预测控制的优势在于:
- 显式处理系统约束(如速度/加速度限制)
- 通过滚动优化实现反馈校正
- 天然处理多输入多输出系统
- 直观的调参方式(调整代价函数权重)
相比PID控制,MPC能提前"预见"未来状态,避免超调;相比LQR控制,MPC可以直接处理约束条件。
### 2.2 CasADi框架的特点
CasADi的核心价值在于:
1. 符号计算:自动推导Jacobian和Hessian矩阵
2. 高效代码生成:可将优化问题编译为C代码
3. 接口丰富:支持Matlab/Python/C++等多种语言
4. 求解器集成:无缝对接IPOPT、qpOASES等求解器
在Matlab中使用CasADi需要额外安装,推荐通过以下命令安装3.5.5版本:
```matlab
urlwrite('https://web.casadi.org/get/3.5.5/matlab/casadi-3.5.5-windows64-matlab2018b.zip','casadi.zip');
unzip('casadi.zip');
addpath('casadi')
采用自行车模型简化,状态量选为:
code复制x = [px, py, θ, v] % 位置x,y 航向角 速度
u = [a, δ] % 加速度 前轮转角
离散化后的状态方程:
matlab复制function x_next = dynamics(x, u, dt)
px_next = x(1) + x(4)*cos(x(3))*dt;
py_next = x(2) + x(4)*sin(x(3))*dt;
θ_next = x(3) + x(4)*tan(u(2))/L*dt; % L为轴距
v_next = x(4) + u(1)*dt;
x_next = [px_next; py_next; θ_next; v_next];
end
实际车辆存在的物理限制:
matlab复制v_min = 0; % 最小速度
v_max = 10; % 最大速度
a_min = -3; % 最大减速度
a_max = 2; % 最大加速度
δ_max = pi/4; % 最大转向角
预测时域N=10,控制时域M=5,代价函数包含:
Matlab实现核心代码:
matlab复制opti = casadi.Opti();
X = opti.variable(4, N+1); % 状态变量
U = opti.variable(2, M); % 控制变量
% 代价函数
J = 0;
for k=1:N
J = J + (X(1:2,k)-ref(:,k))'*Q*(X(1:2,k)-ref(:,k)); % 轨迹误差
if k<=M
J = J + U(:,k)'*R*U(:,k); % 控制量惩罚
end
end
J = J + (X(1:2,N+1)-ref(:,N+1))'*Qf*(X(1:2,N+1)-ref(:,N+1)); % 终端代价
opti.minimize(J);
% 动力学约束
for k=1:N
opti.subject_to(X(:,k+1) == dynamics(X(:,k), U(:,min(k,M)), dt));
end
% 物理约束
opti.subject_to(v_min <= X(4,:) <= v_max);
opti.subject_to(a_min <= U(1,:) <= a_max);
opti.subject_to(-δ_max <= U(2,:) <= δ_max);
设置IPOPT求解器参数:
matlab复制p_opts = struct('expand', true);
s_opts = struct('max_iter', 100, 'print_level', 0);
opti.solver('ipopt', p_opts, s_opts);
实测在Windows i5-10210U上:
设置参考轨迹为:
matlab复制t = 0:0.1:10;
ref_x = 5*sin(t/2);
ref_y = 5*sin(t/4);
跟踪效果指标:
预测时域N的影响:
权重矩阵调整经验:
matlab复制casadi.set_preferred_integrator('cvodes')
matlab复制mpc_solver = opti.to_function('f', {X0, ref_seq}, {U_opt});
mpc_solver.generate('mpc_solver.c',struct('with_header',true));
求解失败可能原因:
轨迹振荡解决方法:
项目包含以下文件:
code复制main.m % 主仿真脚本
mpc_design.m % MPC参数设计
vehicle_model.m % 车辆动力学模型
plot_results.m % 结果可视化
test_cases/ % 测试轨迹数据
核心函数调用流程:
matlab复制% 初始化
model = init_vehicle_model();
mpc = design_mpc_controller();
% 仿真循环
for k = 1:N_steps
x_curr = get_current_state();
ref_traj = get_reference();
u_opt = mpc_solver(x_curr, ref_traj);
apply_control(u_opt(:,1));
end
在实现中发现几个值得注意的细节:
code复制