ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

从零开发大学生电动方程式赛车算法:架构与状态估算实战指南

从零开发大学生电动方程式赛车算法:架构与状态估算实战指南 从零开始开发一套大学生电动方程式赛车算法这个选题我其实盯了很久。每年那批参加大学生电动方程式大赛FSAE的车队里真正能把“算法”这件事讲清楚的帖子少得可怜大多数人的认知还停留在“写个PID控制电机”或者“搭个Simulink模型仿真一下”。但实际你下场跑动态赛的时候会发现算法是个系统工程从传感器数据采集、整车状态估计、扭矩分配策略到故障诊断与冗余安全是一条完整的链路任何一个环节出问题车都可能在八字绕环或者耐久赛里直接趴窝。这篇作为“算法”系列的第一篇我不打算一上来就甩代码或者公式而是先帮大家把整车的电子电气架构和算法地图梳理清楚。因为我在帮几支车队做技术顾问的时候发现很多队伍不是不努力而是死在了“方向错误”上——上来就研究各种高级控制策略结果连最基本的车速估算都没做准IMU安装误差大得离谱CAN总线上数据乱成一片最后算法写得再漂亮也没法落地。1. 大学生电动方程式赛车的算法到底包含哪些东西先给大家一个整体的认知框架。电动方程式赛车和传统燃油方程式在算法层面的最大区别在于电动车的动力响应几乎没有延迟但是能量管理和热管理成了新的约束。算法不只是“控制”而是围绕“怎么把电池里的每一度电转化成圈速”这一核心目标展开的系统工程。具体来说一套完整的电车算法体系通常包含以下五大块整车控制算法VCU这是大脑中枢。负责解析驾驶员意图油门踏板、制动踏板、挡位信号综合当前车速、电池SOC剩余电量、电机温度等状态计算并输出目标扭矩。这里涉及到踏板标定、扭矩滤波、蠕行控制、倒挡限速等基础逻辑。车辆状态估算算法这是底盘控制的地基。核心是估算纵向车速、横向车速、质心侧偏角、路面附着系数。很多车队直接拿轮速传感器算车速但电车在急加速和强回收时车轮滑移率很大轮速和真实车速之间的偏差能达到15%到20%所以必须用融合算法一般是扩展卡尔曼滤波把轮速、IMU惯性测量单元加速度、GPS速度融合起来。扭矩矢量控制与驱动防滑TCS这是电车相比油车最有优势也最复杂的部分。由于电机响应速度是毫秒级的我们可以精细控制每个驱动轮的扭矩。在低附着路面或者弯道中通过左右后轮的扭矩差产生横摆力矩帮助赛车更快入弯。这和传统机械LSD限滑差速器的思路完全不同。能量管理与制动能量回收策略在耐久赛里这个算法决定了你是在第18圈还是第22圈被掏空。核心问题包括什么时候允许强回收、回收扭矩和液压制动如何协调coast-down制动解耦、SOC和电机温度如何参与扭矩限制降额。故障诊断与功能安全BSPD/AMS电车的核心安全逻辑。不是简单的“报错就断高压”而是分等级处理某些故障触发降额某些故障触发断开继电器BSPD制动系统过速保护甚至要通过硬件电路在驾驶员误踩油门且无制动信号时直接切断电机扭矩。这一篇作为开篇我重点讲前两块——整车控制架构的搭建和车辆状态估算的基础框架。这两块是后续所有高级策略TCS、扭矩矢量、能量管理的地基地基不牢后面全是空中楼阁。2. 整车控制架构怎么搭从CAN总线拓扑到传感器选型很多车队第一步就栽在“架构”上。以为算法就是写代码忽略了代码跑在什么硬件上、数据从哪里来、指令怎么发出去。这里我直接给一套经过多支车队验证过的参考架构大家可以根据自己车队的情况调整。2.1 核心硬件拓扑分域控制比中央控制更适合初学者我不推荐第一年做算法的车队直接上一块中央控制器搞定所有事。调试效率太低了。按功能分域各域之间通过CAN总线控制器局域网络通信是最稳妥的方案。动力域主VCU整车控制器、两个电机控制器MCU、电池管理系统BMS、高压配电单元PDU。底盘域ABS/ESP阀体如果装了、转向角传感器、四个轮速传感器、制动压力传感器。感知域IMU、GPS/INS组合导航模块、激光雷达如果做无人驾驶版本但一般不建议第一年上。数据记录域独立的数采板卡常见的有Vector、NI CompactRIO低成本方案可以用Teensy加CAN shield加SD卡。这些域控制器之间通过一条500kbps一般电车队标准的CAN总线连接。2.2 信号源质量决定算法上限传感器安装与标定的血泪教训传感器选型和安装这部分直接决定后面算法的效果。我见过太多车队用非常好的算法模型但输入信号上一堆毛刺导致控制器输出疯狂抖动车在赛道上画龙。三个最关键的传感器安装时要注意第一个是油门踏板位置传感器。原则是要用双电位计冗余且两路信号的电压比要始终在某个固定比例比如2:1。算法必须在每个控制周期里校验这个比例关系一旦发现两路信号不一致超过阈值立即进入降级模式。踏板的机械结构必须消除空行程否则会造成扭矩输出死区开车的人会觉得车“不跟脚”。第二个是转向角传感器。这个是TCS和扭矩矢量算法的命根子。安装时要确保转向柱的轴向窜动不会影响传感器读数。如果传感器是CAN输出一定要确认它输出的角度是经过多圈累积的绝对值而不是相对值。我见过有车队拿增量编码器当绝对角度用结果车手打了两圈方向后算法里的方向盘角度已经完全错乱车身稳定系统直接反向工作。第三个是IMU的安装位置与方向定义。IMU必须安装在整车质心附近而且要保证X轴指向车头正前方Y轴指向车身左侧SAE坐标系Z轴垂直向上。安装误差哪怕只有2到3度横向车速估算中重力加速度的分力就会产生很大的常值偏置。装完以后要做一次静态六面校准记录Z轴加速度应该在1g重力加速度左右X和Y轴应该接近0。这个校准数据要写死在控制器的非易失存储里每次上电做一次验证。2.3 通信协议统一CAN消息矩阵是车队最容易忽略的文档做算法之前最先要做的是把CAN消息矩阵CAN Matrix定义清楚。这不是文档工作这直接决定DEBUG效率。每个关键信号在CAN协议里必须明确以下内容消息ID信号名起始位长度因子/偏移单位最大值/最小值0x181VCU_TorqueCmd0160.1 Nm/bitNm0~30000x182MCU_ActualTorque0160.1 Nm/bitNm-3000~30000x183BMS_SOC080.4 %/bit%0~1000x184BMS_MaxDischargePower8161 kW/bitkW0~500这里的因子factor选择很讲究。比如扭矩信号如果用1 Nm/bit那16位只能表示0到65535看似够用。但如果电机峰值扭矩是3000Nm你希望做到0.1Nm的分辨率扭矩闭环的精度要求就必须用0.1的因子。同理电流信号如果用0.1A/bit16位的最大表示范围只有655.35A对于峰值800A的电机控制器来说根本不够需要改成0.25或0.5。制定CAN矩阵时要统一字节序是小端还是大端、统一单位制全部使用国际单位制和信号命名规范。这不是强迫症而是当你调试问题查到凌晨三点的时候一份清晰的CAN矩阵文档比任何代码注释都管用。3. 车辆状态估算为什么轮速不能直接用怎么做一个简单的融合估计器这部分是算法入门的“分水岭”。很多车队在仿真里跑得好好的一上路就完蛋核心问题就是车速估算不准。3.1 轮速信号为什么失真滑移率在作怪先看一个动态方程。以驱动轮为例驱动力矩T驱动车轮滚动地面给轮胎一个向前的纵向力Fx。车轮的旋转动力学方程是J * dw/dt T - Fx * r其中J是车轮转动惯量w是车轮角速度r是滚动半径。当扭矩T很大的时候Fx * r地面反作用产生的阻力矩跟不上T的变化车轮角加速度dw/dt就会变得很大也就是车轮转动速度远高于车速对应的等效角速度。这就是滑移。滑移率的定义是λ (w * r - v) / (w * r)在驱动工况下λ在0到1之间。当λ达到0.15到0.2时轮胎纵向力达到峰值这是Pacejka魔术公式的核心结论超过这个滑移率后纵向力反而下降车轮开始明显打滑。你可以用轮速w乘以r直接当车速v用吗在λ0.15的情况下真实车速只有轮速的85%。如果直接用轮速除以滚动半径作为车速你算出来的车速比实际车速高15%。这个误差对于续航里程估算来说还能接受但对于TCS、差速策略和能量回收策略来说完全是灾难性的。TCS在低附着路面需要精确判断滑移率如果基准车速本身就有15%的误差那控制器就永远无法收敛。3.2 车道级融合扩展卡尔曼滤波EKF入门不直接使用轮速那怎么办最基础的做法是做一个加权融合把轮速修正滑移后的轮速、IMU纵向加速度积分、GPS速度三者融合。这里我用最常用的扩展卡尔曼滤波EKF做一个示意。EKF的核心思想是分两步走预测与更新。预测步根据运动模型从上一时刻的状态推算当前时刻的预测值假设状态向量是 x [v, a_bias]其中v是纵向车速a_bias是IMU加速度计的纵向偏置。系统的状态方程可以写成v(k1) v(k) (a_imu(k) - a_bias(k)) * dt a_bias(k1) a_bias(k)用矩阵形式 [ v(k1) ] [ 1 -dt ] [ v(k) ] [ dt ][ a_bias(k1) ] [ 0 1 ] * [ a_bias(k) ] [ 0 ] * a_imu(k) w(k)这里的w(k)是过程噪声用来描述模型不确定度。它的大小决定了你对模型的信任程度。如果模型白噪声大滤波器就更偏向于靠测量值如果小就更偏向于靠模型推算。更新步用测量值修正预测值轮速经过滑移修正后的等效车速v_wheel w * r / (1 - λ_est)这里的λ_est可以是固定值比如起步大扭矩时用0.1正常行驶用0.03GPS测速v_gps精度一般在0.1m/s左右但更新频率低一般5到10Hz同时有延迟。观测方程 z(k) H * x(k) n(k)其中z [v_wheel, v_gps]H [1, 0; 1, 0]n(k)是测量噪声。那个a_bias是干什么用的IMU加速度计有零偏温度变化、振动都会让它漂移。EKF里面把它当状态量估计出来车辆静止时可以通过轮速为零判断但要注意轮速在低速时可能因为齿轮噪声而跳动所以加滞回比较稳妥a_bias的最优估计值就是IMU当前的零偏。这样在赛道上跑一圈就能自动在线估计并修正IMU偏置不用每次上车都手动校准。卡尔曼滤波的工程实现里有几个坑值得提前说过程噪声协方差矩阵Q设小了滤波会越来越不信测量数据输出越来越平滑但动态响应变差设大了滤波会跟随测量噪声抖动。我建议Q中对角元初始化为车速的0.01倍左右加速度偏置的0.001倍左右然后通过实车数据分析调整。测量噪声协方差矩阵R轮速和GPS的噪声特性差很多。轮速在低速时本身是跳变的ABS齿圈精度有限GPS在高速时噪声谱密度更大。R矩阵必须按实际测试数据统计千万不要拍脑袋写。时间同步问题GPS和轮速不是同一时刻采集到的CAN总有延迟。如果不对齐时间戳融合出来的车速会有一个恒定滞后。低成本方案是在接收GPS数据时记录本地控制周期的计数值然后做一次线性插值对齐。这个细节在做耐久赛能量管理时尤为重要因为SOC估算需要精确的累积里程。3.3 轮速修正的更优解多传感器融合的闭环思路如果你不想用固定滑移率希望在实际运行中自动修正这个滑移率偏差有一个进阶的做法把滑移率本身也放进状态向量里去估计。观测方程不直接用轮速当作车速而是用v_wheel w * r / (1 - λ_state)其中λ_state也被当成状态量。此时状态向量变成x [v, a_bias, λ]状态方程中λ可以建模为随机游走即λ(k1) λ(k) 噪声。这样在路面附着变化时滤波器能够自动感知“轮速和GPS还有IMU积分三者不一致”的程度把轮速与大地的“滑移”分离出来。这个方案的难点在于可观测性当车辆匀速直线行驶时轮速和GPS都正常λ的估计是高度不确定的因为轮速和真实车速几乎一致但急加速时轮速由于滑移明显高于真实车速而GPS和IMU积分仍然反映真实车速二者差距就能用来估计λ。所以你会发现自然激励不足的场景下滤波器估计会退化这也是一整块可以深入研究的课题。4. VCU状态机与基础扭矩策略让车先“能跑、敢跑、听话”状态估算有了接下来是整车控制主逻辑。我的建议是VCU先实现一个“最小可用版本”保证车在赛道上能跑再一步步往上叠加。以下是我推荐的首版状态机设计。4.1 整车状态机设计上电、待机、驱动、故障锁定一个清晰的状态机是整车安全的第一道防线。参照ISO 26262中的ASIL分解思路一般电车VCU的状态机建议包含以下几个状态INIT初始化上电后执行自检检查传感器信号是否在合理范围油门踏板双路是否一致、IMU是否有效、CAN节点心跳是否正常、BMS是否允许放电必须在高压上电且绝缘检测通过。这段时间建议控制在1到2秒内。STANDBY待机自检通过后进入待机等待启动信号。电车的启动逻辑和油车不同不是“点着火”就行而是必须检测到制动踏板被踩下同时挡位在空挡或驻车位置才会允许进入READY状态。READY就绪READY状态下踩油门才会输出扭矩。这里有一个重要的逻辑是“驱动方向管理”D挡前进和R挡倒车都要限制最大扭矩R挡一般限制在20%到30%的峰值扭矩D挡在起步阶段也建议做一阶或二阶扭矩斜率限制。DRIVE驱动在READY状态下油门被踩下超过一定阈值比如1%到2%不同的电位计输出特性不同这个阈值要在标定时确定且未触发安全条件进入DRIVE状态按扭矩映射表输出扭矩。FAULT故障任何关键安全条件触发BMS严重故障、VCCU内部看门狗复位、电机控制器反馈超时、制动和油门同时被踩下且持续超过一定时间等立即进入FAULT状态部分情况下允许经过降级状态过渡。FAULT是不可自动恢复的必须驾驶员手动断电重新上电或者通过维修口断开高压。这样做是为了避免“自愈”带来的意外风险。这中间有个容易被新手队伍忽略的细节看门狗超时。控制器硬件看门狗只能保证MCU不死机但算法层面也要做逻辑“看门狗”——每个CAN节点MCU、BMS都应该按约定周期发送心跳信号比如100Hz。 VCU如果连续100ms也就是丢失10个心跳没收到某个关键节点的心跳就要根据该节点的关键程度触发降额或故障。这个逻辑在代码里写起来很简单但很多队伍从来不做结果就是在动态赛时偶尔出现“车突然没动力但是仪表盘没有任何故障灯”这种最让人抓狂的问题。4.2 基础扭矩映射不只是一张查表油门踏板位置APPS百分比到目标扭矩之间的映射是最基础但也是最影响驾驶感受的部分。有些车队直接线性映射50%油门等于50%峰值扭矩。这对一台电机瞬态响应极快的赛车来说是不合理的驾驶员会觉得车太“冲”弯道开起来信心不足。推荐的映射逻辑是T_target T_max(v, SOC, Temp) * f(APPS)这里的f(APPS)曲线起步阶段APPS低于10%要用比较平缓的斜率初始扭矩增加慢一些让驾驶员有线性感中段10%到60%可以激进一些保证动力响应末段60%到100%要稍微收收敛避免达到峰值扭矩附近后因为扭矩波动造成车辆后轴瞬时滑移。T_max(v, SOC, Temp)是降额函数这是电车算法和油车最大的不同。它要计算三个限制因素电池最大允许放电功率电池包在低SOC比如低于15%时电芯压降大如果请求功率超过电池允许功率会触发BMS的过放保护。VCU必须根据BMS当前允许的最大放电功率反算出当前车速和挡位下的最大允许扭矩。电机控制器最大输出电流电机在低速时可以输出峰值扭矩但高速时因为反电动势的升高输出能力下降。所以T_max要按电机的外特性曲线恒扭矩区到恒功率区的转折点转速查表得出。热降额电机、控制器和电池都有温度限制。当油温超过90度时电机的持续扭矩能力下降当电池温度超过45度时最大允许放电功率也要降。热降额不是简单一刀切而是用一个一阶滞后滤波让降额值缓慢变化避免扭矩突变造成车身冲击。这里补充一个经验值扭矩斜率限制Torque Rate Limit在赛车的驾驶感受中极其重要。很多车手抱怨车“太贼”或者“顿挫”其中一个原因就是扭矩斜率限制参数没有标好。起步或出弯踩油门时扭矩上升速率如果达到1000Nm/s以上后轴容易瞬间突破附着极限但如果限制到300Nm/s以下直线加速出弯会很肉圈速损失严重。这个参数最终是用车手反馈加遥测数据分析来标定的没有公式可以一步到位。4.3 踏板冲突逻辑与安全冗余最后必须强调踏板冲突Pedal Interlock逻辑。电车和油车最大的区别在于油车如果油门和刹车同时踩发动机扭矩还会正常输出但刹车系统能通过机械摩擦把车停住虽然会加速磨损刹车片电车如果油门和刹车同时踩电机会全力输出扭矩如果BSPD电路没有正确生效车会顶着刹车往前冲这是动态赛中最危险的事故之一。VCU端必须实现的逻辑包括如果油门踏板信号有效且超过3%到5%且制动主缸压力信号超过某个阈值比如2bar到3bar且该状态持续超过300ms防止颠簸路面信号瞬时抖动造成的误判VCU必须立即将目标扭矩清零并进入FAULT状态或受限状态。这个逻辑在两次控制循环之间必须保持且不能因为驾驶员松开油门而清除。必须等到两个踏板都回到零位后经过确认才能退出受限状态。更可靠的做法是用硬件电路平行实现BSPD一个独立的比较器电路或TS19任务里要求的专用芯片或继电器同时接收油门信号、制动信号和车速信号一旦判断“车速超过设定阈值比如5m/s且油门开度大于25%且制动压力大于15bar”就直接断开电机控制器的使能信号或切断主接触器的15V供电。VCU软件里的踏板冲突检测只是第二道防线BSPD电路是第一道防线。我见过低年级车队把BSPD简单理解成“在代码里做个判断”这是极其危险的。BSPD要求的是在VCU主MCU失效的情况下还能独立工作必须是一个独立的硬件路径。哪怕是一条最简单的硬件比较器方案都比代码逻辑可靠得多因为代码可能“跑飞”或者“卡死”而硬件比较器只要供电正常就一直工作。5. 从Simulink到实车之间原型开发流程和验证闭环控制器代码怎么落地也是绕不开的问题。这里给一套适合车队节奏的开发流程。5.1 模型在环MIL、软件在环SIL、硬件在环HIL到底做到什么程度很多车队纠结“我们要不要做HIL是不是太高端了”我的经验和建议是按车队资源和时间预算有梯度地做。MIL模型在环必做。Simulink里把车辆模型哪怕是最简单的自行车模型或整车纵向动力学模型需要包含滑移率模型和电机外特性模型、VCU策略模型和传感器模型全部搭起来验证策略逻辑在理想测量环境下是否正确。这里最重要的是不要在C语言里写了VCU控制逻辑后又去写一份C语言的车辆模型来验证逻辑验证和车辆仿真用同一套Simulink拓扑能省掉大量时间。SIL软件在环策略验证通过后把VCU模型的C代码生成出来Embedded Coder或者手写C代码封装再用同一份测试用例跑一遍。SIL的价值在于检查代码生成过程是否引入数值误差尤其是除法、类型转换、整数溢出这些地方。HIL硬件在环预算有限的车队我做简化的HIL把VCU真实硬件用一个真实CAN卡接上CAN网络上挂一个负载模拟器模拟BMS、MCU的收发再跑一遍关键的故障注入测试用例。HIL主要是验证底层驱动和通信协议栈不需要追求高保真。等有赞助或者经费了再上Speedgoat/Concurrent这类实时目标机没条件就用普通工控机加CAN卡做慢速HIL也行。5.2 基于模型设计的工具链配置实例我给一套2025年依然主流且对学生车队最友好的工具链MATLAB/Simulink Vehicle Dynamics Blockset Simscape做整车纵向/横向动力学模型、轮胎模型和控制策略原型。Embedded Coder从Simulink模型生成嵌入式C代码要设置成定步长离散求解器步长一般取1ms或2ms。电机控制器内部扭矩环的周期是62.5μs到125μsVCU的外环不需要那么快。NXP S32K系列或者TI TMS570系列MCUS32K在FSAE圈子用得比较多原因是NXP的汽车MCU工具链成熟有S32 Design Studio免费版CAN外设驱动可以直接生成。CANdb编辑DBC文件CAN报文数据库文件这是整个项目各个域控制器的“共同语言”。INCA或者CANape做标定和数据采集。如果预算有限用开源的SavvyCAN加自己写的数据解析Python脚本也完全可以跑通。这里给一个关键提醒用Embedded Coder生成代码时必须打开浮点数编译优化和代码生成优化选项并关闭所有不必要的运行时检查。否则生成的代码体积会膨胀近一倍而且运行效率打折。比如在Simulink模型里要把信号的数据类型显式指定清楚能定标成定点就用定点在嵌入式MCU上定点运算比浮点快得多但这需要提前根据物理量的取值范围和分辨率要求确定定标方案。5.3 实车验证闭环台架标定到赛道联调模拟仿真和实车之间建议至少经过三个阶段电机台架标定电机控制器通过CAN控制电机用测功机记录电机外特性曲线扭矩-转速效率-扭矩-转速、温度特性和电流控制环的动态响应。这些数据回填给VCU算法是扭矩映射和热降额的基础。静态台架闭环测试把VCU通过CAN连上真实的MCU和BMS模拟器或者真实BMS但驱动电机空转不带负载甚至可以用一个简易的滚轮台架模拟负载验证上下电时序、状态机流转和故障响应。这个阶段能发现大量通信时序问题。场地联调低速场地测直线加速和刹车采集遥测数据导出Excel对比实际纵向加速度与IMU信号再微调车速估算器的协方差矩阵参数。实车调试中有个小技巧和大家分享用惯导系统比如VectorNav VN-100或Xsens MTi-630做“黄金参考”对比VCU估算的车速。这些模块自带RTK级别的速度精度速度误差可以做到0.03m/s跑几圈后把二者的速度曲线叠加对比你会发现VCU估算的车速在中低速弯道里会周期性偏大原因往往是IMU的安装偏移或轮胎滚动半径在过弯时因为侧偏而轻微变化。这个黄金参考对比法比只靠肉眼看CAN日志里的数据流要高效得多。6. 给算法组新人的三个实战建议最后作为第一篇的收尾闲聊几句团队管理层面的东西。第一算法组不要等硬件全部装车才开始写代码。整车还没落地前把车辆模型在Simulink里建起来把状态机逻辑仿真跑通把CAN报文和DBC定义好这些都是能提前三个月完成的。等到车架和电池包到了再上车写底层驱动就太晚了。第二数据记录和标定工具链要提前准备。我见过太多车队在耐赛现场出了问题连一个能看实时CAN数据的软件都没有全靠VCU上的OLED屏显示几个数字。强烈建议从项目一开始就做好“遥测记录”这回事哪怕只是一个树莓派加一个CAN转USB模块把完整跑动过程中的CAN报文全部存下来后期所有算法的调参和问题分析都依赖这些真实数据。没有完整数据算法优化就是盲人摸象。第三每个算法模块要设计“手动断开开关”和“退出策略”。这句话在团队技术路线讨论中常常被忽略。TCS模块在标定初期大概率是不稳定的如果无法一键关闭TCS、回到基础扭矩策略那么一次调试失败可能就要拖回到库房半修半天。高可靠性的团队会在VCU状态机里为每一个高级算法模块设计独立的“使能/禁止”位并用物理开关或至少一个可靠的车手指令控制。这看起来是小事但能帮车队在动态赛时快速止损。这一篇聊的是框架和地基。下一期我打算把纵向车速估算的EKF具体代码逐行拆开讲包括状态方程怎么离散化、量测矩阵怎么定、协方差矩阵的物理含义和调参经验再配一段完整的Simulink模型实现。等那篇写完大家就会发现“从零开始”最难的根本不是公式推导而是把所有看似孤立的模块串成一个能稳定跑完22圈耐久赛的闭环系统。
返回列表