做车辆动力学仿真,最头疼的往往不是车辆模型本身,而是让车"听话"地跑起来。很多同学在CarSim和Simulink联合仿真时,辛辛苦苦搭好了Simulink控制模型,一跑却发现车辆完全不受控,要么方向盘转角乱跳,要么直接冲出道路边界。碰到这种问题,先别急着怀疑自己的控制算法,大概率是Driver Model(驾驶员模型)这一层没有配置对。
这篇学习笔记接上一篇的环境准备,记录我用C-class车模做Driver Model仿真的完整过程,重点拆解5个Driver Sensors(驾驶员传感器)从哪里来、怎么配、怎么用。这个Driver Sensors不是简单的传感器选型,它本质上是CarSim内部驾驶员模型的"感知输入集合",理解了这5个信号,CarSim驾驶员模型的底层逻辑也就通了。
这篇笔记适合两类人:一是正在做横向/纵向控制算法验证的工程师,二是刚接触CarSim联合仿真、被各种变量名和配置页面搞得头晕的学生。我会把配置步骤、信号含义、踩坑记录都写清楚,保证你跟着操作能跑通一个基本的驾驶员模型仿真。
1. 整体设计思路与Driver Sensors选型逻辑
1.1 为什么选C-class车模
CarSim自带的车型库里有C-Class、E-Class、SUV、Pickup等好几类整车模型,我这次选C-class,主要是看中三个点。
第一,C-class的整车参数相对公开,轴距大约2.6到2.7米,整车质量1.3吨上下,属于典型紧凑型轿车,动力性和操稳性表现都比较中性。相比大尺寸SUV,C-class在弯道工况下侧倾更小,转向响应更直接,用来做控制算法验证不容易被车辆本身的强非线性干扰。第二,C-class模型的子系统配置(悬架、轮胎、转向)在当前版本里属于经过充分验证的默认模板,不需要额外调整太多参数,适合把注意力集中在驾驶员模型上。第三,模型复杂度适中,联合仿真时的计算量比E-class和SUV小不少,调试迭代会明显更快。
如果你后续要做的是重型车或者特殊车型,选型逻辑可以照搬:优先选轴距、质量、轮胎特性与你最终应用场景相近的模板,这样控制参数迁移时有参考价值。
1.2 驾驶员模型在联合仿真中的角色
先说清楚一个概念:CarSim里的"驾驶员"不是一个人,而是一套完整的感知-决策-执行机制。它做三件事:感知外部道路和交通信息、根据感知信息计算转向和加减速指令、执行这些指令(驱动转向盘、油门、制动踏板模型)。
CarSim内置驾驶员模型分为几个子模块:路径跟随驾驶员(Path Follower)、速度控制器、制动和挡位控制逻辑。其中路径跟随驾驶员负责横向控制,速度控制器负责纵向速度跟踪。默认情况下,你只要在CarSim里设置好目标路径和速度,它就能自己把车开走,不需要外接任何控制算法。
但是做联合仿真时,通常有两种诉求。一种是你想验证自己的横向控制算法(比如MPC、LQR、预瞄控制),那就要绕开CarSim内置的路径跟随驾驶员的方向盘控制,把车辆状态和道路感知信息读出来,用自己的算法算方向盘转角,再回传给CarSim。另一种是你只想用CarSim做整车环境,控制算法占用Simulink主模型,CarSim干脆作为被控对象。不管哪种诉求,你都需要知道CarSim到底能输出哪些"感知信息"——这就是Driver Sensors的来源。
1.3 5个Driver Sensors分别传递什么信息
CarSim的Driver Sensors在我的理解里,本质上是"驾驶员感知信息的输出接口"。它模拟的是真实驾驶员在开车时通过眼睛和前庭系统获得的道路和交通信息,然后把这些信息以信号的形式暴露给外部控制器。
做横向和纵向控制,最关键的感知信息就是这5个:
- 目标车道曲率(Curvature):单位是1/m,描述车辆前方目标车道的弯曲程度,是横向前馈控制的核心输入。弯道越急,曲率值越大。
- 目标车道横向偏移(Lateral Offset):单位是m,描述车辆当前位置相对目标车道中心线的横向偏差。这个值反映了"车偏了多远",是横向反馈控制的主信号。
- 航向误差(Heading Error):单位是deg(部分版本输出rad,后面细说),描述车辆当前航向角与目标车道方向之间的夹角。这个值配合横向偏移一起用,能提升横向控制的收敛速度和稳定性。
- 前车距离(Range):单位是m,描述自车与前车之间的实际距离,纵向跟车控制(ACC类功能)的输入。
- 前车相对速度(Range Rate):单位是m/s,描述前车速度与自车速度的差值,用于判断自车是接近前车还是远离前车。
这5个信号分为两组:前3个服务于横向控制,后2个服务于纵向控制。为什么是这5个而不是更多?因为对于基本的驾驶员模型仿真,这5个信号已经覆盖了横向和纵向两个控制环路的全部感知需求。横向控制需要道路几何信息(曲率)和车辆位置/姿态偏差(横向偏移、航向误差),纵向控制需要目标车辆的运动状态(前车距离、相对速度)。自车速度可以通过CarSim状态输出单独读取,不归入Driver Sensors。
2. CarSim端配置:C-class车模与驾驶员传感器设置
2.1 新建C-class模型并设置仿真工况
CarSim主界面的操作路径是:File → New Database,然后在Vehicle Configuration里选择C-Class模板。选好之后会进入整车模型配置界面,比如车体、悬架、转向、动力总成等。对初学者来说,这些子系统保持默认即可,不用一上来就改悬架刚度或轮胎侧偏刚度。
接下来在Procedures里设置仿真工况。这个步骤很多人忽略,但特别重要。要设置三项:初始速度、初始位置、道路几何。我实际操作时,先把初始速度设为80km/h(大约22.2m/s),初始位置放在直道起点,道路用一段带弯道的组合路段(比如直道接半径200m弯道再接直道),这样既能验证纵向速度保持,又能验证横向过弯控制。
注意一个细节:初始速度不要设成0。因为内置驾驶员模型在零速起步阶段需要同时做离合器结合、油门踏板控制、挡位切换,控制逻辑比较复杂,如果这一步没配好,容易出现车辆一直不动或者动力突兀的问题。先把初始速度给上去,让车辆在运动状态下跑,验证核心的横向/纵向控制逻辑,之后再回头研究静态起步问题。
2.2 Driver Sensors的配置入口在哪里
Driver Sensors的配置在Driver Model(驾驶员模型)面板里,不是车辆配置面板。这个面板通常在Procedures或Run Control附近,不同CarSim版本入口不太一样,我用的版本里是在Parser菜单下的Driver Model选项。
进入Driver Model页面后,首先选择驾驶员模型类型。如果要做路径跟随,选Path Follower;如果要模拟跟车场景,选Traffic模式或者启用Traffic Scenario设置。在这个页面里,你会看到一个Sensors或Driver Sensors的配置区域,这里就是5个传感器信号的控制开关。
我建议的配置方法是:先勾选Lane Curvature、Lateral Offset、Heading Error这三个横向感知信号,再把Target Lane(目标车道)和Leading Vehicle(前车)配置好,最后勾选Range和Range Rate。有的版本里,前车距离和相对速度不是通过勾选开启的,而是需要先在Traffic Scenario里定义一辆前车(比如设定前车初始位置在自车前方50m,以80km/h匀速行驶),信号才会有效输出。
有一个特别容易踩的坑:如果你只勾了传感器但没定义目标车道,Lateral Offset和Heading Error的输出会一直是0或者NaN。具体表现就是车辆在直道上还好,一进弯道横向控制就失效。所以配置顺序很重要——先定义道路和目标车道,再配置传感器。
2.3 前车运动参数与路面附着设置
如果做跟车仿真,前车参数需要单独定义。在Traffic Scenario里,可以设置前车的初始位置、速度曲线、行驶车道。我常用的设置是:前车初始位置在自车前方60m,速度按时间变化——先以80km/h匀速行驶10秒,然后以2m/s²的减速度减速到60km/h,保持到仿真结束。这样设计工况,既能测试定速巡航功能,又能测试跟车减速逻辑。
路面附着系数也要看一下,默认的干燥沥青路面附着系数大约0.85,做常规工况不用改。如果你后面要验证雨雪路面下的控制算法,再降到0.3到0.5。
仿真时长和输出步长:我习惯设仿真时间60秒,步长0.001秒。CarSim的求解器是变步长的,但导出到Simulink联合仿真后,Simulink侧一般用固定步长运行,所以 在CarSim里也尽量把输出步长设置成和Simulink的固定步长一致或成整数倍数关系,避免多速率混叠带来的信号突变。
3. Simulink联合仿真模型搭建与信号处理
3.1 导出CarSim S-Function并接入Simulink
CarSim配置完成后,在主界面点击"Send to Simulink"或者通过联合仿真接口生成S-Function模块。这一步会自动把CarSim模型编译成Simulink可调用的S-Function,并生成对应的例程模型(通常是sm_car_simulink.mdl或类似名字)。
注意:生成S-Function的过程中,CarSim会把当前模型的传输接口(Input/Output)打包进S-Function。所以你在CarSim里配置的输入输出通道,决定了Simulink侧能看到哪些信号。如果后面发现Simulink里读不到你要的信号,先回CarSim的Output配置里检查有没有把这个变量加进去。
在Simulink模型里,CarSim S-Function的输入是控制量(比如方向盘转角、节气门开度、制动主缸压力),输出是车辆状态量(纵向速度、横向加速度、横摆角速度、车辆位置坐标等)。打开S-Function的封装参数,你会看到一个变量列表,其中就包含我们配置的Driver Sensors信号。
3.2 定位5个传感器输出信号并做量纲换算
这是最容易搞混的一步。CarSim S-Function输出端口的信号顺序,取决于你之前在CarSim Output列表里添加变量的顺序。所以我在CarSim里配置输出变量时,会特意按照控制模型的端口顺序来排列,比如:
- Vx(纵向速度)
- SteerL1(方向盘转角)
- Curvature(目标车道曲率)
- LateralOffset(横向偏移)
- HeadingError(航向误差)
- Range(前车距离)
- RangeRate(相对速度)
这样在Simulink里,S-Function输出端口的对应关系就一目了然。如果你没有提前排好顺序,建议在Simulink里对输出信号做Demux或者Selector,然后给每条信号线加上标签,方便排查问题。
量纲换算这块要特别小心。CarSim内部统一使用国际单位制:速度为m/s,角度为deg或rad要看具体变量定义。我遇到过的情况是:横向偏移输出单位是m没问题,但航向误差返回的可能是rad,曲率返回的可能是1/km而不是1/m。如果直接用,PID参数会变得非常难调。
一个保险做法:在Simulink里对每个传感器信号加一个Gain模块做单位转换。比如Curvature如果单位是1/km,乘0.001就变成1/m;HeadingError如果单位是rad,乘57.3就变成deg。做完转换之后,再用Display模块或者Scope看一下信号幅值是否符合预期,再进入控制算法。
3.3 搭建自己的驾驶员控制环路
S-Function接入后,控制环路分两部分:横向控制环和纵向控制环。
横向控制环的输入是Curvature、LateralOffset、HeadingError,输出是方向盘转角。我的基本结构是:曲率做前馈(方向盘转角前馈值 = 轴距 × 曲率 × 传动比),横向偏移和航向误差做反馈(PD控制)修正。具体参数估算方法见下一节。
纵向控制环的输入是目标车速(或基于Range和RangeRate算出的期望加速度),输出是节气门和制动请求。在联合仿真中,节气门和制动通常以百分比或者主缸压力的形式给到CarSim输入端口。CarSim里有两个标准输入(Throttle、Brake Master Cylinder),Simulink侧控制量要做限幅,节气门0到1,制动主缸压力0到对应最大压力(通常几MPa)。
我实际搭建的时候,会把这两个控制环分成两个子系统模块,中间用GoTo/From或者Bus信号连接,不要把所有逻辑堆在一个Level-2 MATLAB Function里。这样做的原因是:联合仿真调试时,你经常需要单独看横向环或者纵向环的问题,分模块可以快速定位是哪个环节出了故障。
4. 驾驶员控制模型实现要点与参数估算
4.1 横向前馈控制与前馈量计算
横向控制最基础的逻辑是"看路走",也就是根据目标车道的曲率决定方向盘转角。理想情况下,车辆稳态过弯时,前轮转角与路径曲率满足阿克曼转向关系:
δ_front ≈ L / R = L × κ
其中L是轴距,R是弯道半径,κ是曲率。把前轮转角换算成方向盘转角,还需要乘以转向传动比i:
δ_steer = δ_front × i
以C-class为例,轴距L≈2.7m,转向传动比i≈17。目标车道曲率κ=0.005 1/m(对应半径200m的弯道),那么:
δ_front ≈ 2.7 × 0.005 = 0.0135 rad ≈ 0.77° δ_steer ≈ 0.77° × 17 ≈ 13.1°
也就是说,在半径200m的弯道上,方向盘大概要打13度左右。这个计算值可以作为前馈控制的初始量,在Simulink里直接用Gain模块实现两个环节的乘积:曲率信号 → Gain(2.7) → Gain(17)。
这里有一个非常重要的工程细节:前馈控制只解决了"稳态"问题,弯道入口和出口处的动态误差必须靠反馈控制来修正。不做反馈只做前馈的结果是,车辆在弯道中始终存在横向偏移误差,尤其在曲率突变的路段,误差会很明显。
4.2 横向偏差反馈控制参数调试
反馈控制我用的是PD结构,输入是横向偏移误差和航向误差,输出是方向盘转角修正量:
δ_feedback = Kp_lat × e_offset + Kd_lat × d(e_offset)/dt + Kp_heading × e_heading
刚开始调试时,先把所有增益设小,比如Kp_lat=0.5,Kd_lat=0.1,Kp_heading=0.3,在直线道路上跑,观察LateralOffset的响应曲线。如果没有明显发散,再逐步增加。
实际调试的经验是:横向P增益过大会引起方向盘高频抖动,过小则车辆会明显偏离车道中心线。一个判断标准是:在80km/h直线行驶时,横向偏移误差应能控制在±0.2m以内,且方向盘转角不出现明显的高频颤动。如果方向盘转角信号出现类似"毛刺"的抖动,优先检查是增益太大还是信号单位换算错误。
再一个容易忽略的是符号问题。不同CarSim版本里,LateralOffset的正负定义可能不同(左偏为正还是右偏为正)。如果控制方向反了,车辆会迅速向反方向偏出去。我建议调试时,故意先给一个大的初始横向偏移,看控制量的反应方向是否正确,确认无误后再恢复正常工况。
4.3 纵向速度控制与跟车策略
纵向控制我用的是分层思路:上层根据目标车速和跟车需求计算期望加速度,下层通过PID输出节气门开度和制动主缸压力。
巡航阶段的逻辑比较简单,期望加速度 = Kp_v × (v_target - v_current),一般Kp_v取0.3到0.5,配合积分项消除稳态误差。跟车阶段则要考虑前车距离和相对速度,一个简化策略是:
v_target = v_lead + K_gap × (Range - Range_desired)
其中Range_desired是期望跟车距离,可以取一个固定值(比如50m),也可以用车速的时距形式计算。跟车策略调试时要特别注意RangeRate的正负:正值表示前车比自己快,自车不用减速;负值表示在靠近前车,需要提前减速。
纵向控制里,节气门和制动的切换逻辑要处理好,不然会出现一个常见问题——车辆在跟车减速过程中,节气门和制动踏板频繁切换,表现为车速波动。我通常设置一个滞回区间:当期望加速度大于0.3m/s²时只给节气门,小于-0.3m/s²时只给制动,中间区间保持上一个控制量,防止频繁切换。
4.4 参数初始化与调试顺序
联合仿真控制参数的调试顺序也很有讲究,我的习惯是"先横后纵、先慢后快、先直后弯"。
先横后纵:先把横向控制调好,让车能沿着目标路径走,再调纵向速度控制。因为纵向控制对横向控制有耦合影响(加速时车辆转向特性会变化),两个一起调很难定位问题。
先慢后快:先用60km/h低速工况调通控制逻辑和信号连接,确认无误后逐步提高速度到80、100、120km/h。高速工况下车辆动力学非线性增强,控制参数可能需要重新标定。
先直后弯:先用纯直道工况验证纵向控制和直线保持,然后加小曲率弯道(曲率0.002 1/m,对应半径500m),验证前馈控制方向是否正确,最后再上急弯(曲率0.01 1/m,对应半径100m)。
这一步是整个联合仿真里最耗时间的环节,不要想着一次把所有参数调到位,边看Scope曲线边微调才是正常节奏。
5. 常见问题排查与实操避坑指南
5.1 联合仿真模型跑不起来的常见原因
联合仿真最让人抓狂的问题就是S-Function初始化失败或者模型根本跑不起来。我把这类问题整理成一个速查表:
| 现象 | 常见原因 | 处理办法 |
|---|---|---|
| S-Function初始化失败 | CarSim版本与Simulink版本不兼容 | 确认CarSim支持当前MATLAB版本,必要时切换MATLAB版本 |
| 模型运行速度极慢 | 求解器步长太短 | 联合仿真用固定步长,建议0.001s到0.005s之间,步长过小计算量爆炸 |
| 模型直接报错找不到文件 | CarSim模型路径包含中文或空格 | 把整个工程目录放到纯英文路径下,避免任何中文字符 |
| Simulink里S-Function显示红色 | CarSim的DLL/动态库未正确加载 | 重新编译S-Function,确认编译输出无错误 |
| 车辆一直原地不动 | 初始速度设成了0且纵向控制未参与 | 给一个非零初始速度,或检查Throttle输入是否为0 |
第4条里"动态库未正确加载"出现频率很高,特别是在别人电脑上拷来的模型。解决办法是把整个CarSim工程目录重新导出一遍S-Function,不要直接复制DLL文件。
5.2 传感器输出恒为零或异常值的排查思路
Driver Sensors输出恒为零,这个问题很隐蔽,我排查过整整半天,最后发现是CarSim里传感器开关没勾上。在Driver Model面板里,传感器需要逐个确认启用状态。如果只配置了目标车道但没启用Lateral Offset传感器,信号虽然存在,但值恒为0。
排查顺序建议是:先在CarSim的动画界面里看车辆是不是真的在有弯道的路上跑,确认道路和目标车道存在;然后看Driver Sensors面板里传感器是否全部勾选;最后在Simulink里用Display模块直接观察信号原始值,排除封装层信号丢失的可能。
如果传感器输出出现NaN或者极大值,优先检查是不是出现了除零问题。比如目标车道曲率在某些版本里输出的是"曲率半径的倒数",当道路曲率接近0(直道)时,如果信号定义的是"半径"而不是"曲率",直道上就会出现分母接近0的异常。这个问题在不同版本之间的变量定义差异比较大,需要看具体的变量帮助文档确认。
5.3 信号单位与量纲对照速查表
联合仿真里单位错误是最隐蔽的系统性误差,很多时候控制参数调不出来,根源就是某个信号单位差了一个数量级。我把CarSim常见输出信号和单位整理成对照表:
| 信号名 | 含义 | 常用单位 | 联合仿真推荐单位 |
|---|---|---|---|
| Vx | 纵向速度 | km/h或m/s | m/s |
| SteerL1 | 方向盘转角 | deg | deg |
| Curvature | 目标车道曲率 | 1/km或1/m | 1/m |
| LateralOffset | 横向偏移 | m | m |
| HeadingError | 航向误差 | deg或rad | deg |
| Range | 前车距离 | m | m |
| RangeRate | 前车相对速度 | km/h或m/s | m/s |
特别注意Vx和RangeRate,CarSim内部很多变量习惯用km/h,而Simulink控制模型里用m/s比较顺手。如果发现车速相关信号数值比预期大3.6倍,基本就是单位没换算。
5.4 我踩过的几个坑
第一个坑是传动比。最初做前馈控制时,我算出了前轮转角0.77度,直接把这个值作为方向盘转角输给了CarSim,结果发现过弯严重不足。后来才意识到,CarSim输入端口SteerL1要求的是方向盘转角,而阿克曼公式算出的是前轮转角,中间差了传动比这个关键因子。类似的坑在制动控制里也有——CarSim输入的是主缸压力,不是制动踏板位移。
第二个坑是信号时序。联合仿真模型用固定步长运行时,如果CarSim侧的输出步长设置成0.001秒而Simulink侧是0.01秒,你会看到传感器信号呈阶梯状变化,特别是Range和RangeRate这种由前车运动学生成的信号。解决办法是让Simulink的步长不小于CarSim的输出步长,推荐两者一致。
第三个坑是符号方向。我的控制模型里把LateralOffset正方向定义成"偏左为正",但CarSim默认输出可能就是"偏右为正"。这个问题在直线道路上完全看不出来,一进弯道车辆就往外侧跑。最后我在Simulink里加了一个Gain(-1),问题立刻消失。所以拿到新模型时,第一步不是写控制算法,而是用阶跃输入把每一个信号的极性确认一遍。
6. 后续扩展建议与个人体会
这次C-class驾驶员模型仿真跑通之后,后面能扩展的方向挺多的。最直接的是把内置PID换成预瞄控制或者MPC,CarSim输出信号不变,只需要改Simulink控制算法模块。然后是传感器融合,可以在CarSim里配置多个传感器组合(比如加上侧向加速度、横摆角速度输出),模拟真实车辆上多种传感器信息融合的场景。
我个人的体会是:CarSim和Simulink联合仿真真正难的往往不是算法本身,而是信号全链路打通之前的排查过程。从CarSim配置到Simulink接线,再到量纲换算和方向定义,任何一环出问题,最终表现都是车辆控制效果异常。所以每次新起一个联合仿真项目,我都会先做一个最简的"信号回环"测试——给一个固定方向盘转角,看车辆状态响应曲线是否合理,确认通路无误后再上复杂控制算法。
另一个建议是保存好每一版仿真配置。我调试的时候,每调一版参数就保存一次工况文件,并在文件名里注明日期和参数特征,比如"Cclass_driver_v3_offset_PI_0620"。这在联合仿真配置项特别多的时候尤其有用,回退到某个可用版本只需要几分钟,而从头排查可能要几个小时。
这套流程跑通之后,你会发现后面做ACC、AEB、车道保持都只是换控制算法和传感器配置的事,框架完全不用动。希望这篇笔记能帮你少走一些弯路。