
做这个项目的起因其实挺直白我在验证紧急避障工况下的MPC跟踪效果时急需一套能“真·跑起来”的仿真环境。纯用Simulink自己搭车辆模型轮胎和悬架的非线性很难整得靠谱纯靠在CarSim里调内置控制算法又没法灵活改代价函数和约束。最后把方案定成了MATLAB 2016 CarSim 2018联合仿真控制端用模型预测控制MPC工况选的就是典型的紧急换道避障——前方障碍物突然出现车辆在高速状态下快速变道绕开。整套系统在Simulink里闭环跑通CarSim提供高保真车辆动力学响应MATLAB负责生成参考轨迹、求解MPC并输出前轮转角。如果你现在也在做智能车规划控制相关的算法验证或者课题需要搭一套可信度足够高的控制仿真平台这篇东西应该能帮你少踩几个坑。我把版本选择、车辆建模参数、场景配置、参考轨迹生成、MPC参数整定、信号接线这些环节全部展开顺便把那些只有真跑过才会遇到的问题也列了出来——尤其是版本兼容和单位不统一这两个坑文档里基本不会写清楚。1. 方案设计的思路为什么这样搭1.1 分工思路CarSim管车MATLAB管脑联合仿真这件事首先要搞清楚谁干什么。CarSim的价值在于车辆动力学模型足够真实——轮胎的侧偏特性、载荷转移、悬架几何、转向系统的响应这些都是它的强项。你自己在Simulink里用二自由度自行车模型搭一套“车”转向输出和实际车辆动态的差异非常大尤其在高速紧急变道这种极限工况下轮胎力很容易进入非线性区简单线性模型根本Hold不住。所以CarSim负责当那台“真实”的车MATLAB负责当大脑。MATLAB侧的控制器在每个控制周期计算前轮转角把这个值通过Simulink送给CarSim模型CarSim积分求解当前车辆状态再把横向位置、横摆角、横摆角速度这些状态反馈回MPC模块。整个闭环就在这个“你算一步、我跑一步”的循环里完成。实际在Simulink里CarSim被封装成一个S-Function模块不需要你去理解它内部怎么列方程只需要知道输入是什么、输出是什么。也就是说你在MATLAB里开发的算法和将来部署到实车控制器里的算法几乎可以是同一套代码仿真结果的可迁移性比纯数学仿真高很多。1.2 版本搭配的考虑2016 MATLAB与2018 CarSim为什么能配合很多人一上来就问为什么不用同一年代的版本我实测下来的结论是CarSim 2018的Simulink接口对MATLAB 2016支持得很好官方兼容列表里明确包含R2016a和R2016b。而且MATLAB 2016这个版本对quadprog等优化求解器的调用已经非常成熟完全够用。更重要的一点是联合仿真接口的本质是一个动态链接库它通过S-Function与Simulink交换double数组不依赖什么额外插件。只要两边位数一致都是64位或者都是32位编译环境能用接口就能正常加载。没必要为了追求新版本而升级高版本MATLAB反而可能因为换掉了默认C编译器导致CarSim生成的MEX文件加载时报错我身边就有朋友被这个问题折腾过很久。还有一点安装路径别带中文和空格这算是一个通用老规矩尤其是CarSim生成仿真文件时路径里有中文可能导致S-Function根本加载不进来。2. CarSim车辆模型与场景配置2.1 车辆参数设置让CarSim与MPC预测模型“对齐”虽然CarSim里有现成的车辆模型但我还是建议把关键参数改成和MPC预测模型里使用的一致。原因很简单MPC内部使用的是简化线性模型如果预测模型里的整车质量、轴距、侧偏刚度与CarSim里的真实车辆参数偏差过大控制效果会在仿真中直接暴露出来——最典型的表现就是横向误差不收敛或者轨迹振荡。我这次采用的是某中型轿车的参数配置整车质量1550kg轴距2.8m质心到前轴距离1.1m到后轴距离1.7m。前轮侧偏刚度约-80000 N/rad后轮侧偏刚度约-90000 N/rad质心高度0.55m。这些参数看起来枯燥但它们是MPC预测模型的核心输入。实际操作时我在CarSim的车辆参数页面里逐一核对并修改确保两边对应上。注意CarSim里的侧偏刚度单位是N/deg而MPC推导时一般用N/rad。换算关系是1 deg约等于0.01745 rad数值上大约要除以57.3。我第一次就没注意这个导致MPC预测模型的“转向灵敏度”和实际车辆差了几十倍仿真结果直接飞了。2.2 工况场景设置障碍物、车道与附着系数场景布置方面我设置的是双向四车道的直线高速公路单车道宽度3.75m。自车初始位置在中间车道车速设定为72km/h也就是20m/s。前方30m处放置一个静止障碍物目标车道是相邻的左侧车道或者右侧车道具体看你想测试哪一侧。为了模拟真实紧急工况障碍物触发时机放在2s——给车辆留出前1.5s稳定直线行驶的时间然后突然出现障碍物MPC规划层立刻生成换道轨迹。路面附着系数设为0.85对应干燥柏油路面。如果你想测试低附着极限工况可以后面把附着系数调到0.3左右做对比但要注意这时单靠前轮转向可能不够最好加直接横摆力矩控制DYC这一点我在文章最后会展开说。另外CarSim默认带了驾驶员模型练习模式下它会自己控制油门、刹车和转向。做联合仿真时这个内环驾驶员模型必须关闭把控制权完全交给外部的MPC控制器否则会出现“两个人在抢方向盘”的冲突车速和路径都会被CarSim自带的逻辑带走。2.3 输入输出通道配置与单位陷阱CarSim与Simulink交互的信号通过通道Channel来配置。输入通道我用了前轮转角单位是deg输出通道则选了车辆坐标系下的纵向位置X、横向位置Y、横摆角Yaw、横摆角速度Yaw Rate、纵向速度Vx和横向速度Vy。这里有个我踩过的坑CarSim每个通道的输出单位是可以在配置面板里改的。默认有些通道是km/h有些是deg如果你的MPC控制器按国际单位制m、rad、rad/s来算就必须在输出通道里把单位统一改成m/s、rad。我第一版跑的时候纵向速度从CarSim输出来是km/hMPC里做参考轨迹的纵向位置积分时全错了横向偏差曲线看起来就像“醉酒驾驶”后来排查了半小时才发现是单位问题。所以建立好通道后务必打开输出通道设置页面逐项确认单位。3. 紧急换道避障轨迹与MPC控制器设计3.1 参考轨迹生成五次多项式换道曲线换道轨迹的规划方法很多正弦函数、贝塞尔曲线、多项式曲线都可以用。我最后选了五次多项式核心原因是它的边界条件可以全部显式满足而且加加速度连续不会在起点和终点产生剧烈冲击。五次多项式的一般形式是[ y(t)a_0a_1ta_2t^2a_3t^3a_4t^4a_5t^5 ]对换道工况而言横向初始位置为0初始速度和初始加速度都为0终点位置为目标车道中心线即一个车道宽度L3.75m终点速度和加速度同样为0。六个边界条件对应六个系数可以直接解出来[ a_00,\quad a_10,\quad a_20,\quad a_3\frac{10L}{T^3},\quad a_4-\frac{15L}{T^4},\quad a_5\frac{6L}{T^5} ]其中T是期望换道持续时间我取的是4s20m/s车速下意味着换道过程纵向行驶约80m横向加速度峰值大约在0.35g左右体感上接近紧急但不至于失控。生成轨迹时x方向按恒速推进每个采样时刻把对应的t代入公式就能得到参考横向位置和参考横摆角。下面这段MATLAB代码可以直接生成参考轨迹点function [y_ref, psi_ref] generate_lanechange_ref(t, T, L, vx) % 五次多项式换道轨迹 y_ref 0; psi_ref 0; if t 0 t T tau t / T; a3 10 * L / T^3; a4 -15 * L / T^4; a5 6 * L / T^5; y_ref a3 * t^3 a4 * t^4 a5 * t^5; dy_ref 3*a3*t^2 4*a4*t^3 5*a5*t^4; psi_ref atan(dy_ref / vx); elseif t T y_ref L; psi_ref 0; end end换道结束后轨迹保持在目标车道中心线横摆角回归为0方便MPC在稳态阶段把横向误差收敛到零。3.2 预测模型与MPC问题建模MPC的预测模型采用的是经典的二自由度自行车模型。状态变量取横向速度Vy、横摆角速度γ再加上横向误差e_y和横摆角误差e_psi控制输入是前轮转角δ。先列出二自由度车辆动力学方程[ m(\dot{v}_yv_x\gamma)C_f\alpha_fC_r\alpha_r ][ I_z\dot{\gamma}l_fC_f\alpha_f-l_rC_r\alpha_r ]其中前轮侧偏角α_f和α_r在低速小角度假设下可以近似为[ \alpha_f\delta-\frac{v_yl_f\gamma}{v_x},\quad \alpha_r-\frac{v_y-l_r\gamma}{v_x} ]把状态方程写成标准的状态空间形式 ( \dot{x}AxBu )然后用采样时间Ts0.05s做零阶保持离散化得到每个控制周期都能用的离散模型。MPC在每个时刻基于当前状态预测未来Np步的系统响应并求解如下优化问题[ J\sum_{j0}^{N_p-1}\big(Q_1 e_y(kj|k)^2Q_2 e_\psi(kj|k)^2\big)\sum_{j0}^{N_c-1}R,\Delta\delta(kj|k)^2\rho\varepsilon^2 ]约束条件包括前轮转角限幅、转角增量限幅以及质心侧偏角软约束[ \delta\in[-10^\circ,10^\circ],\quad \Delta\delta\in[-0.85^\circ,0.85^\circ],\quad \beta\in[-6^\circ,6^\circ]\varepsilon ]这里把侧偏角约束做成了软约束加上松弛变量ε是为了避免极端工况下优化问题直接无解。每个控制周期只需要把这个二次规划问题丢给quadprog求解取第一步最优控制量作为实际输出。3.3 控制参数整定的实操经验参数怎么定这是MPC项目里最考验人的部分。我最终的参数组合是预测时域Np20步相当于1s的预测长度控制时域Nc5步权重Q180Q25R0.3松弛变量权重ρ1000。整定逻辑是有顺序的。先把横向误差的权重Q1调大一些让控制器对横向偏差足够敏感但如果Q1过大、R过小前轮转角会非常激进仿真里能看到转向角快速震荡。再当Q1和R的平衡基本能保证稳定后加横摆角误差权重Q2用来抑制车辆在换道过程中的“甩头”现象。我的经验是横向范围在50到120之间比较合适R一般设在0.2到0.6之间。R太小控制增量变化太快转向执行机构受不了R太大轨迹跟踪变得懒散紧急工况下横向偏差会比较大。4. 实操过程从零搭一套可跑的联合仿真4.1 CarSim端导出Simulink联合仿真模型在CarSim里完成车辆参数、道路场景、输入输出通道配置后点击主界面中的“Send to Simulink”或“Create Simulink Model”按钮CarSim会生成一个后缀为.sim的仿真数据文件同时自动打开一个带S-Function接口的Simulink模板模型。这个模板里已经预置了CarSim车辆模块模块的输入端口对应前轮转角等控制信号输出端口对应你配置好的车辆状态信号。这里有一个很重要的细节CarSim生成的模型文件名和保存路径不要包含中文或空格否则S-Function在加载时很容易报错。同时在CarSim的Options设置里指定MATLAB 2016的安装路径让CarSim能够正确调用MATLAB引擎。我用的路径就是纯英文目录例如D:\CarSimData\LaneChange。4.2 Simulink控制系统搭建与信号接线在MATLAB侧新建一个Simulink模型把CarSim生成的模块复制进来然后在它的前面接MPC控制器后面接状态反馈。完整的数据流是这样的CarSim车辆模块输出Y、Psi、Vx、Vy等状态量状态量经过一个零阶保持器Zero-Order Hold按0.05s的控制周期采样参考轨迹生成模块在同一时刻输出参考横向位置Y_ref和参考横摆角Psi_ref误差计算模块把实际状态与参考值做差送入MPC控制器MPC控制器输出前轮转角δ再经过一个零阶保持器返回到CarSim车辆模块的输入端口。MPC控制器我建议用MATLAB Function模块实现方便在每个控制周期里调用quadprog。关键代码结构如下function delta mpc_controller(y_state, psi_state, y_ref, psi_ref, p) % 构建误差向量和预测矩阵 x0 [y_state - y_ref; psi_state - psi_ref; vx; gamma]; % 根据当前状态更新状态空间矩阵A,B [A_d, B_d] discrete_vehicle_model(vx, p); % 构建QP矩阵 H, f, Aeq, beq, lb, ub % ... options optimoptions(quadprog, Display, off); u_opt quadprog(H, f, Aineq, bineq, [], [], lb, ub, x0, options); delta u_opt(1); endSimulink求解器设置为固定步长步长取0.001s与CarSim内部积分步长保持一致。MPC模块是0.05s的触发采样相当于每50个仿真微步执行一次控制计算这样整体仿真速度不会太慢也能保证车辆动力学积分的精度。4.3 仿真运行与结果判读配置好所有参数后我把仿真停止时间设为8s点击运行。整个过程大概几秒钟就能跑完。观察结果时我主要看三件事第一条是横向位置曲线是不是平滑地从0过渡到3.75m有没有明显超调第二条是实际轨迹与参考轨迹的横向偏差峰值能不能控制在0.2m以内第三条是前轮转角曲线是否平滑有没有高频抖动。我这次跑出来的典型结果是2s触发换道后车辆在1.5s内完成换道横向偏差峰值约0.15m横摆角速度峰值约15度每秒前轮转角最大5.2度整个过程转向动作干脆但不过激换道结束后横向偏差经过一次小幅振荡收敛到0.02m以内。这个结果对于仿真验证来说已经足够说明MPC控制器有效。5. 高频问题与排查笔记5.1 版本兼容与接口启动问题CarSim生成的模型在Simulink中提示找不到S-Function文件是我见过最多的问题。排查思路很简单检查.sim文件是否和Simulink模型在同一目录检查路径是否含中文或空格再确认Simulink的工作目录有没有切换到模型所在目录。另一个常见报错是“Invalid MEX-file”这通常是MATLAB没配置好C编译器或者MATLAB位数与CarSim不匹配。解决办法是在MATLAB命令窗口执行mex -setup选择一个可用的C编译器然后重新加载模型。CarSim无法识别MATLAB的情况通常是因为CarSim安装时没有正确找到MATLAB安装路径需要在CarSim的选项菜单里手动指定。建议把MATLAB 2016安装目录写成纯英文路径降低出问题的概率。5.2 MPC发散、振荡与约束不可行如果MPC控制器在仿真刚开始就发散先别急着调权重。两个最常见的原因是预测模型参数和CarSim偏差太大或者状态反馈的符号接反了。我的做法是先在Simulink里把CarSim输出的状态量和MPC内部的状态量打印出来对比确认正负方向和单位完全一致。比如在CarSim输出横摆角速度时正方向是逆时针为正如果你的预测模型里也按这个约定就必须保证仿真里坐标系定义一致。约束不可行这个问题在紧急避障工况里很容易出现。解决办法有三个一是给稳定性约束加松弛变量这就是我前面提到的软约束二是适当放宽前轮转角限幅从±8度放宽到±10度三是缩短预测时域从30步减到20步因为更长的预测时域意味着更多约束要同时满足可行域会变小。我的经验是软约束方案最实用它不会让优化问题无解只是会在万不得已时牺牲一两个约束来换取控制指令。还有一个很典型的现象换道过程跟踪得很漂亮但换道结束后横向偏差迟迟不回调。这通常是因为参考轨迹在T时刻的位置导数虽然都是0但MPC的目标函数里没有对“终端位置”做足够强的约束。解决方法是在目标函数里把最后几步的横向误差权重提高或者在换道结束逻辑里直接把参考位置锁死在目标车道中心线。5.3 参数异常排查速查表现象可能原因处理办法仿真开始即发散状态符号反了或单位错误打印CarSim输出与MPC内部状态对比横向偏差一直不收敛Q1太小或R太大提高Q1到80~120降低R到0.2~0.4前轮转角高频抖动R太小或采样时间不匹配增大R到0.5以上检查零阶保持器换道完成后回摆终端误差惩罚不足增加终端Q1权重或锁死参考位置仿真速度极慢Np过大或每一步调用非线性求解换quadprog减小Np到20必要时离线查表车速莫名变化CarSim驾驶员模型未关闭在CarSim里把驾驶员模型设为外部控制写在最后这套MPC CarSim方案跑通之后我最大的体会是MPC在联合仿真里真正难的不是推导公式和写求解代码而是让简化预测模型与高保真车辆模型“和谐相处”。CarSim里的轮胎只要进入非线性区你在二自由度模型里算得再准的侧偏刚度都会失效。所以实际项目中一定要把工况边界框住别让算法在超出设计范围的场景里硬跑。我目前的方案里MPC还只输出前轮转角这一个执行量如果想进一步挑战低附着路面或者更高车速可以考虑在优化问题里增加一个直接横摆力矩控制输入DYC——利用左右轮驱动扭矩差产生附加横摆力矩帮助转向系统更稳定地完成紧急换道。那样的话预测模型里只是多一个输入维度目标函数和约束的框架不用动QP求解依然成立。如果后续有精力我会把DYC扩展也补上来。