CarSim仿真程序中的MPC自动驾驶轨迹跟踪控制:从原理到实践

1次阅读
没有评论

共计 2103 个字符,预计需要花费 6 分钟才能阅读完成。

image.webp

1. 为什么选择 MPC?传统 PID 的局限性

刚开始做轨迹跟踪时,我也像大多数人一样首选 PID 控制器。但实际在 CarSim 里跑 S 弯道和 8 字轨迹时,发现了几个头疼的问题:

CarSim 仿真程序中的 MPC 自动驾驶轨迹跟踪控制:从原理到实践

  • 车速超过 60km/ h 后,前轮转角会出现明显振荡
  • 遇到曲率突变的路段,横向误差经常超过 0.3 米
  • 调参时顾得上前半段轨迹就顾不上后半段

后来读到 MPC 的预测机制才恍然大悟——PID 就像「闭着眼睛开车」,只根据当前误差调整;而 MPC 则是「老司机」,能提前预判未来 3 - 5 秒的路况。举个例子:当车辆接近急弯时,MPC 会在入弯前就开始平滑地打方向,而不是等到偏离轨迹才急打方向盘。

2. MPC 控制器的核心设计

2.1 车辆模型搭建

在 CarSim 中我们采用简化自行车模型(动力学模型可导出为 DLL 供后续调用):

\begin{cases}
\dot{x} = v \cdot \cos(\psi + \beta) \\
\dot{y} = v \cdot \sin(\psi + \beta) \\
\dot{\psi} = \frac{v}{l_r} \sin(\beta) \\
\beta = \arctan(\frac{l_r}{l_f + l_r} \tan(\delta_f))
\end{cases}

注意 :CarSim 的车辆参数(如质量、轮胎刚度)需要与模型匹配,否则会出现「仿真漂移」现象。我建议先在静态工况下验证模型一致性。

2.2 CarSim 联合仿真配置

推荐使用 S -Function 接口(比 DLL 更方便调试):

  1. 在 VS 中配置 CarSim S-Function 模板工程
  2. 修改 vehicle_inputs.c 获取方向盘转角、油门等信号
  3. 通过 simfile.par 设置仿真步长(建议 0.05s)

关键代码片段(C++):

// 获取 CarSim 输出状态
void get_carsim_states(double* states) {states[0] = vs->u;       // 纵向速度
    states[1] = vs->v;       // 横向速度
    states[2] = vs->wz;      // 横摆角速度
    states[3] = vs->Phi;     // 全局航向角
}

3. Python/C++ 实现示例

Python 版(使用 Casadi)

import casadi as cs

def build_mpc_controller():
    # 定义状态变量(x,y,ψ,v)x = cs.MX.sym('x',4)
    u = cs.MX.sym('u',2)  # [前轮转角, 加速度]

    # 离散化模型(欧拉法)x_next = x + dt * vehicle_model(x,u)

    # 构造 QP 问题
    Q = np.diag([10, 10, 5, 1])  # 状态权重
    R = np.diag([0.1, 0.1])      # 控制权重
    cost = (x-ref).T @ Q @ (x-ref) + u.T @ R @ u

    # 添加约束(前轮转角±30 度)constraints = [-0.523 <= u[0] <= 0.523 ]

    # 创建求解器
    nlp = {'x':cs.vertcat(x,u), 'f':cost, 'g':cs.vertcat(*constraints)}
    solver = cs.nlpsol('solver', 'ipopt', nlp)

C++ 版(OSQP 求解器)

// 构造 QP 矩阵
Eigen::SparseMatrix<double> P(2*N, 2*N); 
P.setIdentity();
P *= 0.1; // 控制量权重

// 设置 OSQP 求解器
OSQPSettings settings;
osqp_set_default_settings(&settings);
settings.eps_abs = 1e-4; // 收敛阈值

OSQPData data = {n, m, P.data(), ...};
osqp_setup(&work, &data, &settings);

4. 调参避坑经验

4.1 预测时域选择

  • 城市道路:3 秒(N=20 @ dt=0.15s)
  • 高速场景:5 秒(N=25 @ dt=0.2s)

血泪教训 :预测时域过长会导致:
1. 求解时间超过实时要求
2. 远处轨迹点权重过低反而降低精度

4.2 权重矩阵调参

推荐分层调参法:

  1. 先调横向误差权重(Qy=10~50)
  2. 再调航向角误差(Qψ=5~20)
  3. 最后微调控制量权重(R=0.1~1)

我常用的「8 字轨迹」测试参数:

Q = \begin{bmatrix}
50 & 0 & 0 \\
0 & 20 & 0 \\
0 & 0 & 10
\end{bmatrix}, \quad
R = \begin{bmatrix}
0.5 & 0 \\
0 & 0.3
\end{bmatrix}

5. 性能验证对比

测试场景 最大横向误差 (m) 方向盘抖动 (deg/s)
PID 控制 0.42 15.6
MPC 控制 0.18 7.3

从数据可以看出,MPC 在保持轨迹精度的同时,控制平滑性提升 50% 以上。特别是在曲率变化大的路段(如 8 字交叉处),MPC 的优势更加明显。

6. 进阶扩展思路

如果想进一步提升性能,可以尝试:

  1. LSTM+MPC 混合架构 :用 LSTM 预测未来轨迹点,替换固定参考轨迹
  2. 自适应权重调整 :根据曲率动态调整 Q 矩阵权重
  3. 多速率控制 :路径规划层 (10Hz) + 跟踪层 (50Hz)

我在 GitHub 上开源了一个基础示例项目(链接见文末),包含 CarSim 2022 的仿真文件和一键对比脚本,欢迎 Star 交流!

正文完
 0
评论(没有评论)