
别看一个纵向控制听着比横向简单好像只管速度、不管方向盘可真要把车稳定控制在目标车速上让乘客不晕车、让跟车不点头光靠一个PID是远远不够的。我在做Carsim与Simulink联合仿真的纵向控制项目时最大的感触是真正决定控制效果上限的往往不是控制器本身而是被大多数人当成“预处理杂活”的油门刹车标定表。这张表要是不准上层控制律再好下发到执行端也是白搭。这篇我结合自己调Carsim纵向控制的完整过程聊透油门刹车标定表从设计、采集、拟合到写入控制器的每个细节包括中间踩过的坑。适合正在做自动驾驶控制算法入门、搞车辆纵向运动控制或者被Carsim标定数据折磨到怀疑人生的同学参考。1. 纵向控制在自动驾驶控制算法里的位置1.1 横向与纵向两套完全不同的控制逻辑做自动驾驶控制算法首先得把横向控制和纵向控制分开来看。横向控制管方向盘转角目标是让车沿着期望路径走关注的是车道保持、换道、避障时的轨迹跟踪纵向控制管油门和刹车目标是让车按照期望速度、期望加速度行驶关注的是定速巡航、自适应跟车、前向碰撞缓解这类工况。横向控制的对像是前轮转角到车辆横摆角速度、横向偏差的映射模型复杂魔术公式、自行车模型、运动学模型全往那堆很多人一上来就死磕LQR、MPC把横向控制研究得明明白白。纵向控制看似简单以为一个PID闭环就能搞定但实际上它有个隐藏难点控制算法算出来的是期望加速度可车辆执行机构根本不听加速度指令它只认油门踏板开度和刹车踏板压力。从期望加速度到油门刹车执行量之间隔着一条非线性严重、且随车速和负载变化的映射关系。这条映射关系就是标定表存在的意义。没有它你写的控制器等于“开环”在跑控制律再漂亮也发不出正确的执行指令。1.2 标定表为什么是纵向控制落地的核心瓶颈很多初学者在Simulink里搭纵向控制第一版都是直接拿期望加速度乘个比例系数当成油门开度给到Carsim模型。跑仿真一看低速下油门给大了车窜出去高速下油门给小了车没反应定速巡航“定不住”跟车起步慢半拍。问题出在哪油门开度与车辆加速度之间的增益不是常数。同一脚油门车速30km/h和120km/h下的加速度完全不一样同一期望加速度平路和坡道上的油门开度需求也完全不同。乘一个固定比例系数本质上是把这条极度非线性的曲线强行当成了线性关系后果就是控制器参数不得不迁就“误差最大的那个工况”——最后各工况都照顾不好。这就是为什么工程上要用标定表预先通过大量稳态工况的数据采集把“车速—油门开度—加速度”的真实映射关系测出来做成二维查表放进控制器里。上层算法算出一个期望加速度查表直接找到对应的油门或刹车执行量这样才是在“知道车到底什么脾气”的前提下做闭环控制。我做完这张表之后控制器参数几乎没怎么调纵向控制的跟踪误差就断崖式下降这是标定表价值最直观的体验。2. 标定前必须想清楚的三件事2.1 Carsim里先搞清楚虚拟传感器到底怎么配很多人一上来就急着搭Simulink模型结果连Carsim的输出通道都没设置对。Carsim本身没有“IMU传感器”这种一键添加的物理实体它的做法是提供一个庞大的变量库你需要的所有信号都在这个库里选相当于内置了一堆虚拟传感器你想“安”哪个信号就选哪个信号。纵向控制标定至少要选这五个信号车速Vx单位km/h和m/s都有注意统一建议用m/s纵向加速度Ax用于计算实际加速度油门开度Throttle反馈实际执行量制动压力Brake Master Cylinder Pressure反馈刹车执行量发动机转速或挡位选装用于排查动力中断和挡位切换问题。在Carsim主界面的“Output”里把这几个变量拖进输出列表保持变量名和Simulink模型接口一一对应。这一步做不对后面仿真的数据全是错的别问我怎么知道的我第一次做标定车速信号用了单位km/h的版本没换算拟合出来的多项式严重失真整个表作废重来。2.2 联合仿真的接口配置S-Function是最省事的路径Carsim与Simulink联合仿真有两种主流方式一种是Carsim S-Function另一种是FMUFunctional Mock-up Unit。做标定表这种需要频繁改输入输出、反复跑批次的活S-Function最省事。建议在Simulink模型里放一个“Carsim S-Function”模块输入口接你控制的油门开度、制动压力、挡位信号输出口接车速、纵向加速度、行驶里程等状态量。这里有个关键点Carsim的输入通道顺序、输出通道顺序必须和S-Function模块的端口顺序完全一致多一个少一个都不行顺序错位了数据全乱。我在这个模块上栽过一次输入口我接了两个信号油门、刹车Carsim里却只配置了一个输入通道剩下的刹车信号被默认成0导致标定刹车表时车辆完全不减速排查了大半天。检查接口顺序时一定要把Carsim的I/O通道列表和Simulink端口列表放在一起逐项核对。联合仿真的仿真步长也建议固定为定步长Carsim模型本身是变步长ODE求解器但Simulink里用定步长比如1ms或5ms跑联合仿真更稳标定数据的时间对齐也好处理。用变步长跑标定数据导出后时间戳参差不齐处理拟合还得做插值白白增加工作量。2.3 标定工况设计先想清楚“标什么”标定之前必须先想清楚一个核心问题你标定出来的表是给哪个控制策略用的我做的纵向控制分两层上层决策输出期望加速度下层是执行层。所以我的标定表目的是建立“车速v 期望加速度a_des → 油门开度α / 刹车压力p_b”的映射本质上是一个逆向模型。为了把逆向模型标得干净工况必须可控路面选高附着平整路面附着系数0.85以上排除打滑干扰坡度平路标定坡度设为0坡度的影响后面另做坡度补偿不混进这张表挡位固定挡位或自动挡D挡正常升挡优先标定中高速段低速段的挡位切换问题后期单独处理风阻Carsim默认有空气阻力模型车速越高影响越大不必刻意关闭因为实际车辆也有风阻标定表里包含风阻的影响是好事。工况设计的原则是一次只标一个变量其他变量全部锁死。如果你的标定表又要覆盖油门又要覆盖刹车那就要分两张表来做不要试图一张表解决所有问题。3. 油门刹车标定表的制作全过程3.1 第一步稳态工况数据采集标定表的核心数据来源是稳态试验。所谓稳态就是让车辆在一个固定油门开度下跑足够长时间等车速和加速度不再变化或者变化极小时记录下此时的车速和实际纵向加速度。我做了一个简单的Simulink数据采集模型输入给Carsim的是阶跃油门信号。具体做法是从油门开度10%开始给一个阶跃等车速稳定后保持3秒记录这一段的车速Vx和纵向加速度Ax然后切换到20%重复同样操作。油门开度依次遍历10%、20%、30%、40%、50%、60%、70%、80%、90%、100%。这里有个很重要的操作细节加速度信号不能直接用Carsim输出的Ax原始值。因为车辆在达到稳态之前会有瞬态振荡直接取均值会混入动态误差。我处理的办法是截取每个油门开度下最后1秒的稳定段数据然后对这1秒的Vx和Ax分别取平均得到一个数据对Vx_avg, Ax_avg, Throttle。刹车侧类似制动力用Carsim的总缸压百分比或者MPa控制从10%到100%同样遍历一圈记录每个制动压力下车辆稳定减速时的Ax。注意刹车标定不需要等车速稳定因为刹车工况天然是减速的取的是“这个压力下车辆能达到的最大减速度”当减速度不再变化时记录。所有数据采集完成后整理成一张原始数据表大致长这样油门开度 (%)稳态车速 (m/s)稳态纵向加速度 (m/s²)1012.30.352018.60.723023.40.95.........3.2 第二步数据拟合把离散点变成连续曲线拿到离散数据后不能直接查表。油门开度只有10个离散点上层控制算法可能在某一个车速下算出0.5 m/s²的期望加速度但这个加速度对应多少油门开度10%和20%之间怎么取值必须把离散点拟合成连续的函数。拟合对象有两个维度车速和期望加速度拟合结果是油门开度。这是一个二元拟合问题最常用的方法是分段多项式拟合。我用的方案是按照车速分成若干个区间每个区间内用最小二乘法把“期望加速度—油门开度”关系拟合成二次多项式。二次多项式是最均衡的选择。一次多项式太粗拟合残差大三次以上出现过拟合在数据点之间会抖出奇怪的波浪形反而不符合油门—加速度的真实物理关系。拟合时有个容易忽略的问题多项式要保证单调性。油门开度增大加速度必须增大这是物理底线。如果拟合出的多项式在某个区间出现“油门开度增大、加速度反而减小”的倒挂说明原始数据有噪声或者分段边界没处理好宁可手动调掉这个数据点重新拟合也不能让这张表在生产环境里出现倒挂。拟合完成以后把多项式在车速—加速度网格上离散化成二维表。我用的网格是车速从0到50 m/s步长1 m/s加速度从-3 m/s²到3 m/s²覆盖最大制动到最大加速步长0.1 m/s²。交叉点上填入对应的油门标定值形成一张51×61的二维标定表。3.3 第三步标定表的写入与边界处理标定表最终以二维查表的形式写进Simulink控制器。Simulink里直接用2-D Lookup Tablen-D Lookup Table模块X轴设为车速、Y轴设为期望加速度、表值为油门开度。刹车侧同理单独一张表。查表结构设计里有几个关键细节全部是实操中踩出来的第一表值的边界处理。查表模块默认在查表范围外做线性外推这对标定表来说很危险。比如车速到了30 m/s、期望加速度超过3 m/s²时外推出来可能给出150%的油门开度这种指令Carsim收到后非线性系数直接爆表。解决办法是在查表模块外层套一个Saturation模块把输出限制在0%到100%之间。第二油门和刹车的切换逻辑。期望加速度为正时查油门表为负时查刹车表但绝不意味着加速度接近0时能来回切换。如果期望加速度在0附近抖动油门刹车会高频切换车辆会产生非常严重的闯动。我在控制器里加了一个滞回区间期望加速度大于0.2 m/s²才切油门小于-0.2 m/s²才切刹车中间区域保持上一状态同时给油门和刹车各做了一个斜坡变化限制避免执行量突变。第三查表输入要做平滑滤波。上层算法输出的期望加速度如果是阶跃的直接查表会输出一个阶跃油门车辆就会有顿挫感。我在查表前给期望加速度加了一阶低通滤波时间常数约0.3到0.5秒标定表的真实性保留同时把执行端的冲击抹平了。我做完这张表后整个纵向控制的执行链路就变成了这个结构期望加速度 → 低通滤波 → 判断油门/刹车 → 车速加速度二维查表 → 限幅/限斜率 → 油门开度/刹车压力 → Carsim车辆模型实测效果车辆在定速巡航工况下车速波动控制在正负0.3m/s以内跟车的加速度跟踪误差控制在正负0.1m/s²以内跟标定前比是质的变化。4. 标定结果验证与各类问题排查4.1 查表偏差为什么这么大先检查这五个细节标定表做完第一次放进闭环里跑大概率会发现实际加速度和期望值对不上。别慌按顺序排查这五件事第一时间对齐问题。Carsim输出的Ax点到查表结果的对应关系是实时闭环的但你在分析数据时如果发现“表查出来给了50%油门实际Ax却很低”很可能是数据记录延迟。建议所有仿真信号进一个Buffer再导出统一时间戳。第二单位问题。Carsim车速变量有好几个版本Vx的单位可能是km/h也可能是m/s同时Carsim模型内部用的可能是m/s但你表格里存的是km/h查表时直接把车速送进去就会导致查表点落在完全错误的区域。这个错误不显眼但极容易犯检查时先把所有变量的单位列一张清单。第三稳态数据有没有真稳态。如果每个油门开度只跑了几秒就开始记录数据车辆还在加速过程中取到的Ax是瞬态值拟合出来的表普遍偏大或偏小。我重新做了实验每个工况点让车至少跑10秒确认加速度变化率小于0.05m/s²才记录。第四忽略了挡位切换。Carsim自动挡模型在低速加速过程中会升挡升挡瞬间发动机转速跌落、牵引力中断导致这个区间内的加速度和拟合曲线偏差极大。我的处理方案是标定表分两段制作第一段覆盖20km/h以下的起步区间这个区间挡位固定在一挡第二段覆盖20km/h以上的行驶区间挡位固定在D挡巡航两段表在中间有重叠区切换时用加权过度。第五动、静态标定的混用。如果你把瞬态加减速工况的数据也混进了标定表那这张表就没有意义了。标定表必须基于稳态数据动态响应特性应该靠控制器的闭环PID去补偿而不是靠标定表去“扛”。4.2 油门刹车切换工况下的闯动问题纵向控制最怕的不是大油门大刹车而是油门刹车在0附近频繁来回切。我做过一个实验期望加速度设为一个零均值的高频正弦波控制器在这种输入下以每秒好几次的频率在油门和刹车之间切换。Carsim的车辆模型在这种输入下车身纵向加速度输出满是毛刺车体像筛糠一样剧烈闯动。解决办法就是我前面提到的滞回区间加斜率限制结合起来效果非常显著。滞回区间的宽度需要根据车型调整不能照搬。我用的轿车模型设定0.2m/s²主观感受上车的加减速切换已经非常平顺如果你做的是重型商用车模型执行机构响应慢滞回区间甚至要加到0.4m/s²以上。斜率限制的参数也要注意。油门斜坡变化率我限制在每秒不超过30%开度刹车限制在每秒不超过20%压力。限制太紧会让响应变慢限制太松又起不到平滑作用这个值要结合你的上层控制周期来调。一般控制周期5ms到20ms限制值取这个量级比较合理。4.3 联合仿真里最容易踩的几个时序坑Carsim和Simulink联合仿真的标定实验整体流程不难但时序坑一个接一个这里列几个我遇到的高频问题仿真时长不够导致数据未收敛有些人为了快每个工况点跑2秒就切下一个油门阶跃后车辆还在加速期就被切走采集的数据全是动态数据。我后来把所有标定工况的仿真时长统一改为30秒前15秒预跑后15秒记录稳定段。油门输入是百分比但Carsim内部可能带死区Carsim默认油门输入低于3%到5%时发动机不响应如果标定表最小区间刚好落在死区里查表输出一个很小的油门值车可能完全不走。这种情况要么给油门输入加偏置补偿要么强制把表最小油门值拉到死区以上。Carsim重编译被忽略联合仿真时每次修改Carsim模型参数Simulink端的S-Function模块不会自动重编译导致你总觉得改了参数但仿真结果没变实际上Carsim模型还是旧版。解决办法是每次改完Carsim参数后在Simulink里CtrlD更新模型或者直接清空Carsim生成的临时文件再重新仿真。多组数据导出格式错乱标定过程数据量大我建议直接把Carsim数据导出到MATLAB工作区用脚本统一处理别靠手工复制粘贴。处理完后马上保存.mat文件R方、拟合曲线图、残差图都归档好方便后面复盘。4.4 低速起步区间的特殊处理低速起步区间的标定是个小坑因为车辆从静止到起步要克服的静摩擦力和滚动阻力远大于中高速段而且这个区间加速度信号信噪比低随便有点噪声采集到的Ax波动就能达到0.2m/s²以上。我的做法是低速单独处理。在Carsim里把起始车速设为0油门给一个很小的固定值比如8%观察车辆从静止到蠕行的全过程记录“刚好能让车动起来”的最小油门开度这个值作为起步死区补偿存在表中最底层低于这个值的油门不参与控速。另外一个细节低速时转速低发动机扭矩波动对加速度影响大如果标定表中其他车速段的油门精度是1%低速段必须有更细的油门分辨所以我在0到5m/s这个区间内额外补了11.5%、12%、12.5%这种更细的油门标定点拟合精度明显提升。现实中很难靠仿真做到完美但标定表把基础打牢后面实车有数据再迭代会省很多事。5. 标定表做完之后还能做哪些扩展标定表做完那一刻纵向控制器基本就有了“手感”。但如果你以为标定表是一次性工作那就想简单了。真实工程中标定表至少要支持两种扩展工况外推和在线修正。工况外推最典型的场景就是坡度。我做标定表时光顾着平路等把车放到一个有坡度的场景跑发现同样的油门开度上坡时加速度明显偏低。解决思路是在标定表之外加一个坡度前馈补偿项坡度信息从Carsim输出的道路坡度信号获取换算成等效的加速度扰动反向补偿到期望加速度里。注意这个补偿不要写进标定表否则会污染平路数据。我踩过这个坑把坡道补偿直接加进标定表导致平路上同一期望加速度对应的油门开度跳来跳去平路工况全乱套。在线修正是更进阶的做法。采集实车数据通过自适应算法对标定表做局部修正或者用深度学习拟合车速、加速度、油门刹车映射关系效果可能比查表更平滑但离线查表方案的好处是稳定、可解释、安全可控在没有大量实车数据的开发阶段标定表永远是工程上的主力方案。另外如果你做的是Carsim和Simulink联合仿真建议把标定表做成独立的MATLAB文件或者Simulink库和控制器主体解耦。这样换车型、换场景时直接换张表就行控制器代码不用改一行。我当时就是图省事把表直接写在控制器内部后来换了个重型车模型改表改得头皮发麻所有仿真案例全部重新跑了一遍。写在最后的体会关于油门刹车标定表老实说它不是什么高深算法但它是检验控制算法团队是否“落地”的一块试金石。我在实际做项目中的体会是标定表的详细程度和车辆模型的准确度直接决定了上层控制算法好不好调。调PID调MPC调半天调不好先别怀疑算法回过去看看标定表是不是做得够扎实。还有个小技巧放在最后分享每次标定数据采集完别急着拟合先把原始数据画成散点图看一眼。车速、加速度、开度三者的对数坐标或归一化坐标中如果散点分布有明显的分层或断层说明你的采集中间有工况异常当场重采别依赖拟合去掩盖问题。如果你正在做Carsim纵向控制我建议你把标定表这件事当成一个独立的里程碑任务来做——标定表做完并且闭环验证通过比控制器参数调好更有成就感。控制器参数换三个场景就变标定表的底子在换什么场景都不慌。祝你标定顺利少踩几个我踩过的坑。