
2026年夏天我结束了最后一届智能车。如果把大学几年里的项目排一个优先级智能车一定是我花时间最多、情绪波动最大、也最晚真正想明白的一件事。跑完最后一圈整理完最后一版代码我突然意识到在这件事里真正值得带走的不是奖状不是好不容易调好的参数而是一套关于“如何让一个复杂系统稳定工作”的方法论。见过太多队伍把大量时间耗在玄学调参上——车冲出去了就改参数改了再冲最后只是把不稳定从一个弯道搬到了另一个弯道。所以我一直想写一篇不像教程的智能车文章讲讲最终能稳定完赛的队员到底做对了什么。1. 先想清楚智能车比拼的从来不只是“能跑”1.1 从“车会动”到“车能完赛”中间隔着三层能力新队员最容易产生的错觉是看到车动起来就觉得自己已经完成了一大半。电机能转舵机能打遥控器和串口都有反应于是整个实验室都松了一口气。但只要你把车放到赛道上跑一圈就会发现问题远比自己想象的多入弯太晚、出弯甩尾、直道跑偏、电感或图像信号偶尔抖动甚至电池电量下降后整辆车的行为都会变。能跑只是一个起点。真正的问题不是“车会不会动”而是“车能不能稳定地完成整个流程”。从工程经验看这个过程大概分成三个层次阶段核心问题常见误区判断标准最小系统传感器是否可靠读数执行器是否正确响应“能动就是成功”固定输入时输出可预期稳定复现相同条件下的多圈结果是否一致“今天跑得好就没问题”连续多圈不失控异常点可复现速度竞争极限速度在哪里如何逼近但不崩溃“只调速度环就能变快”单圈时间下降且控制仍处于可控范围很多队伍一直停在第一层不是因为他们不会写PID而是因为他们没有意识到“稳定”需要被当作一个专门的指标来设计。车能跑完一圈可能只是运气车能在不同光照、不同电压、不同轮胎状态下都能保持类似表现才是工程能力。1.2 为什么很多人卡在“能跑”这一层一个很常见的现象是今天下午车在实验室跑得好好的换到比赛场地就不行了。于是大家开始疯狂调参数但无论怎么调都找不到一个“万能值”。原因在于他们一直在理想条件下测试没有主动制造扰动。稳定复现的能力来自你有意识地改变环境变量并观察系统的响应。比如拉上窗帘和打开强光观察图像处理结果是否稳定。把电池充到不同电量观察电机输出和传感器阈值的变化。在赛道表面制造轻微灰尘或水痕观察轮胎抓地力的变化。连续跑十圈记录每一圈的异常点而不是只记录最快一圈。这不是为了制造焦虑而是为了尽早暴露问题。如果等到比赛现场才发现光线变化导致赛道识别丢了你的调试时间通常不够用。更建议的做法是从中期开始每周至少做一次“环境变化测试”把测试条件写进记录里。2. 我建议把所有工作拆成五层而不是先调算法很多新队员的第一反应是问“你们用的什么算法用的什么单片机”。这其实是个很低效的起点。智能车是一个完整的系统算法只是其中一层。真正决定上限的是每一层之间能不能可靠衔接。我后来习惯把一个智能车项目拆成五层机械层、硬件层、控制层、感知层、调试层。每层解决的问题不同验证方式也不同。2.1 机械层决定物理极限机械是最容易被忽略却又最容易产生隐性问题的层。重心位置、轮距、轮胎磨损、螺丝紧固程度都会直接影响车在高速下的表现。很多“算法问题”最后追查下来其实是底盘变形或者螺丝松动。机械层的验证方式很直接手动推车看它在直线轨道上能不能自然走直检查轮胎磨损是否均匀每次试车前用标记笔给关键螺丝做记号。不要等到车跑偏了才去检查机械那时候你已经在错误的路线上浪费了很多时间。2.2 硬件层决定电气可靠性硬件层的问题往往是“偶发”的。传感器数据偶尔跳变、电机偶尔没响应、单片机上电后偶尔死机这些现象最容易让人误以为是代码问题。但真正的原因经常是供电不稳、接插件接触不良、信号线过长或者地线处理不当。我建议先做一次完整的硬件检查确认所有模块的供电电压和电流余量。确认上下电顺序避免传感器和驱动模块同时上电造成电压跌落。确认信号线尽量短并且远离电机线和电感线等大电流线路。用扎带、热缩管和标签把线束固定好避免车辆震动导致接触不良。注意通电状态下不要插拔接插件尤其是驱动模块和传感器。不要因为问题“偶尔出现”就跳过这一层偶发性往往意味着接触问题。2.3 控制层决定稳定性控制层最常见的实现是PID但很多人一开始就跳到调参忽略了先做开环验证。正确顺序应该是先小油门固定输出确认电机转速和舵机角度基本正确再手动给一个转向输入观察车的响应最后才进入闭环控制。控制层最容易踩坑的点是输出饱和。转向角输出限制设得太宽舵机可能一直打到极限速度环输出限制设得太高电机可能突然加速。参数不是越大越好控制目标是“有限范围内稳定”不是“无限制响应”。2.4 感知层决定信息质量感知层直接决定控制层能获得什么样的输入。摄像头组的曝光、对比度、分辨率电磁组的增益、滤波编码器的采样频率和接口稳定性都会直接影响后续判断。一个很值得养成的习惯先看原始数据再做处理。很多人一上来就跑复杂的图像处理流程但如果原始图像本身是过曝的任何算法都救不回来。先通过串口或上位机把原始图像、电感数组或编码器数据导出来确认数据稳定再开始写上层逻辑。2.5 调试层决定效率调试层不是“出了问题再调试”而是从第一天就建立记录和复盘机制。很多人觉得记录浪费时间但真正浪费时间的往往是“盲调”改参数、跑一圈、冲出去、再改参数、再跑一圈循环两小时仍然没有结论。我建议把调试能力当成一个功能来开发。最早可以很简单就是串口打印关键变量中期加入SD卡日志后期加入录像和参数回放。有了这些你才会知道车在赛道上那一刻到底发生了什么而不是靠肉眼猜测。层核心问题常见坑第一验证方式机械重心、轮胎、底盘是否稳定螺丝松动被误认为算法问题手动推车、检查磨损硬件供电和接线是否可靠偶发接触不良难复现上电观察串口日志控制输出是否稳定、有限幅盲目调PID导致震荡开环验证固定输入感知原始数据是否可用脏数据进入处理流程上位机查看原始数据调试现象是否可沉淀、可复现靠体感调参日志、录像、参数表这个验证顺序是固定的先机械再硬件再感知再控制最后是算法和参数。不要跳过前面四层直接调算法否则问题永远无法收敛。3. 真正消耗时间的不是写代码而是“盲调”3.1 为什么“昨天还能跑今天就不行”这是智能车实验室里最经典的一句话。通常不是因为代码变了而是因为某个输入变量变了。可能是电池电压低了可能是光线不一样可能是轮胎沾了灰也可能是赛道表面摩擦系数变了。没有采集数据的情况下你根本无法区分这些因素。盲调的本质是变量不可控。你在调整一个参数的同时环境也在变化于是结果无法归因。今天跑得好你不知道是哪几个条件叠加出来的明天跑不好你也不知道是哪个条件变了。3.2 我后来坚持的调试顺序如果你已经陷入盲调先停下来然后按这个顺序做先复现。把车身固定或者把驱动轮架起来给一个固定输入观察输出是否一致。如果固定输入下输出都不稳定那大概率是机械或硬件问题不是赛道适应问题。先隔离。分别验证传感器、控制器、执行器。比如给舵机一个固定PWM看它是否准确转到预期角度给电机一个固定油门看车速是否稳定。先记录。在改任何参数之前把当前参数、当前现象、当前环境全部记录下来。没有记录就改参数等于没有实验设计。只改一个变量。不要同时调PID和图像阈值不要同时换轮胎和改速度规划。一次只改一个变量才能知道成果来自哪里。这个过程看起来慢实际快。因为它避免了你反复在同一个问题上打转。3.3 日志、录像、参数表把体感变成数据盲调的另一面是“体感调试”。你感觉车入弯快了一点感觉图像识别有点不稳但这些感觉不能验证也不能传承。更建议的做法是建立三样东西运行日志每次试车时记录关键变量包括速度、电池电压、转向输出、控制周期、异常标志。赛道录像从车头或俯视角拍摄记录车在赛道上的表现。参数表记录每次实验的参数变更和结果。日志字段可以很简单比如[100] speed1.82m/s battery7.86V curveR90 target_angle27 actual_angle24 error3 statusOK关键是让日志和录像在时间上对齐。这样当车在第三个弯冲出赛道时你能同时看到图像、数据和视频明确到底哪一层出了问题。参数表的形式也不必复杂一栏一栏写清楚即可日期参数旧值新值赛道场景现象结论06-01舵机PD的P0.80.9连续右弯入弯响应更快保留06-02速度环P0.50.6直线末端出弯加速更猛暂时回滚这套方法在真实工程里很常见本质是实验管理。把它带到智能车里你会发现很多“玄学问题”其实是可以被定位的。注意调参前先把当前参数和现象写下来。这个动作只需要一分钟但能避免你改完三个参数后完全不知道哪个参数有效。4. 从弯道识别到速度规划几个可以复用的实现思路4.1 先做信息简化再做决策不同组别的信息源不同但思路是一致的先简化信息再决定控制量。不要一上来就上复杂模型先要一个可解释、可调试、参数少的基线方案。以图像处理为例很多强队的第一版算法都非常朴素。第一步不是识别整个赛道而是把图像压缩成若干行在每行上寻找赛道边界求出中心线。伪代码思路大致是# 示意逻辑不依赖具体硬件接口 for row in selected_rows: left_edge find_edge(row, directionleft) right_edge find_edge(row, directionright) center[row] (left_edge right_edge) / 2这个方案的价值在于可解释。如果直道中点正常、弯道中点跳变你可以直接在图像上画出每一行的左右边缘判断是左边线丢失、右边线丢失还是整行噪声。等基线稳定了再去做补线、预测、平滑而不是一开始就写一个看似智能但无法调试的复杂流程。对于电磁组道理类似先看原始电感值和归一化后的曲线确认信号在赛道各个元素上的变化规律再决定用差比和还是更复杂的融合方法。4.2 把控制分成转向环和速度环控制层最常见的误区是把所有逻辑写在一起。更清晰的方式是拆成两个环转向环负责方向速度环负责速度。两个环都独立调好之后再考虑联动。转向环通常可以先用PDangle kp * error kd * (error - last_error);调这个参数的顺序建议是先给一个小一点的P让直道方向基本稳定再逐步增加P观察弯道入口是否响应及时最后才加D用来抑制超调和震荡。不要一开始就追求大P大P很容易让舵机在直道上高频抖动。速度环再单独调。速度环的目的是让车速尽量贴近目标速度同时避免电机死区带来的非线性。要注意对PID输出做限幅不管目标是多快输出都不能无限增大。积分项也要有上限否则长时间偏差累积会导致过冲。控制环节最容易出问题的地方不是公式而是“环之间互相影响”。速度突然变化转向角度就会有变化转向突然变化轮胎侧偏也会影响速度。所以调参时不要同时改两个环。先固定一个再优化另一个。4.3 边界不要照搬别人的参数很多队伍在网上找到某个开源方案烧进去之后发现“确实能跑”于是开始在自己的车上微调。这种做法不是完全不行但风险很大。参数不是从一套环境迁移到另一套环境就能直接复用的机械结构、重心、轮胎、赛道表面、电池特性、传感器安装位置哪个不同都会让参数失效。更建议的做法是把别人的方案当参考但一定要搞懂每个参数的意义。比如图像采样行为什么选择这些行中线跳变时算法有没有兜底逻辑PID的P为什么是这个量级输出限幅为什么是这个值目标速度是根据什么条件切换的如果你回答不了这些问题那这套方案仍然是别人的不是你的。比赛中最怕的不是慢而是“不知道为什么快也不知道为什么慢”。处理方式优点风险简单中线提取可解释、易调试、参数少复杂赛道元素需要补逻辑每帧全图处理信息完整计算负载高噪声影响大直接照搬开源参数启动快环境差异导致不通用先理解再迁移能定位问题、能迭代需要耐心5. 最后一届最该留下的不是代码而是文档和流程5.1 为什么代码不是最重要的传承物比赛结束后最容易出现的场景是学弟学妹拿到前几届的工程文件却不知道怎么开始。文件夹里可能有 final_v1、final_v2、final_v8、最终版以及一个“真正最终版”。代码能编译但没有人知道为什么这些参数是这个值也没有人知道硬件接线和电源要求。代码只是最终产物。真正能帮助下一支队伍的是“为什么这样做”和“遇到这个现象怎么排查”。如果只留下代码下一届大概率还要重新踩一遍所有坑。也许他们能在一个月后跑起来但浪费的时间本来可以避免。5.2 我建议最后整理三份文档最后一届最值得做的工作不是继续压榨零点几秒的单圈时间而是把经验归档成下面三份文档硬件清单与供电说明所有模块的型号、接口、引脚、电压范围、地线连接、信号线走向以及哪些地方最容易接触不良。调试手册每个传感器如何处理、每个控制参数的合理范围、常见异常现象和对应的排查路径。迭代记录每周的目标、实测结论、遗留问题、下一步要做的实验。这一步相当于把整个赛季的决策过程留下来。这三份文档的价值不在于格式多漂亮而在于后面的人遇到问题时能快速定位。比如“图像中线抖”应该先查曝光还是先查算法调试手册里直接写清楚先看原始图像是否稳定再看边缘提取是否连续最后才看是否需要对中心线做滤波。5.3 版本管理不是可选项代码版本管理在实验室里经常被忽略但在工程里其实是基础要求。不需要多复杂的流程基本要求是每次实验后提交一次代码commit message 写清楚“改了什么、为什么改、现象是什么”。关键实验的记录和代码版本对应最好能在代码里保留一个参数版本号。不要只保留最终版本要保留能回退到“上一版还能跑”的中间版本。我见过最可惜的情况是学长毕业时只留下一个编译好的固件没有源码也没有接线图。下一届只能靠拆硬件反向推断模块接法花了大量时间在重新做基础工作。这个坑只要提前做好归档完全可以避免。一个更现实的建议写文档时想象自己是三个月后重新打开这个工程的新人。如果你觉得光看代码无法理解那说明文档还不够。6. 如果重来一次我会从第一天就按这样的节奏走6.1 三阶段计划如果时间倒流我会把整个赛季分成三个阶段而不是“先写代码再调参数最后冲速度”。前期是“最小系统期”。目标是让车在固定输入下能可靠响应传感器数据稳定控制逻辑能从开环过渡到闭环。这个阶段不要追复杂算法重点是确认每一层都能正常工作。中期是“稳定单圈期”。目标是连续五圈以上不失控。这个阶段要建立日志、参数表和录像回放机制。任何一次异常都要尽量找到可复现的原因。后期才是“速度优化期”。在这个阶段每改一个变量都要做类似A/B测试只改一个参数跑多圈比较结果。如果成绩变差立刻回滚到上一版参数。这个三阶段节奏能在最大程度上避免最后一刻还在做“大改”。6.2 一个通用的异常排查顺序如果你不知道问题出在哪里可以按下面这个顺序排查看现象是入弯冲出、出弯甩尾、直道跑偏还是偶发性丢失信息看输入图像/传感器/编码器数据是否稳定电压是否在合理范围看环境光线、赛道表面、轮胎状态、场地温度有没有明显变化看机械螺丝是否松动轮胎是否磨损底盘是否变形看硬件信号线是否接触不良供电是否正常看算法感知结果是否进入控制逻辑控制输出是否被异常分支破坏看参数最近一次改了什么参数改之前是否有记录举个例子。如果车在出弯后甩尾严重正确的排查顺序不是直接调速度环而是先确认速度计算有没有跳变。如果编码器读数因为接触问题偶尔丢脉冲那速度环拿到的输入本身就是错的调参只会越调越乱。6.3 容易被忽视的细节最后一届之后回头看有些细节看起来很小但实际影响很大电池电压不要无差别使用。电机输出和传感器阈值都会随电压波动。测试时尽量固定在同一电量区间否则数据不可比。轮胎状态比很多人想象的重要。轮胎脏了、磨损了高速下的抓地力变化非常明显。调参前先检查轮胎比先改PID更高效。摄像头固定要抗振动。安装高度、俯仰角会影响视野范围但更重要的是不能松动。一个会晃动的摄像头会让所有图像处理结果都不可信。串口调试线偶尔也会成为问题来源。接触不良会导致数据中断干扰判断。先检查连接再怀疑代码。比赛现场环境一定和实验室不同。提前做“环境切换测试”在更亮、更暗、更滑的场地各跑几圈观察系统有没有收敛。这些细节不会出现在任何一份能力清单里但它们才是决定稳定性的关键。2026年夏天之后我可能不会再像现在这样蹲在赛道边看一辆小车过弯但我会一直记得那个下午车完赛静下来从日志里看懂了它为什么在第三个弯犹豫。那一刻我意识到所谓最后一届并不是结束而是我终于学会了怎么面对一个复杂系统。智能车给我的不是“我能参加比赛”而是“我知道怎么把一个复杂问题拆开、定位、解决”。如果你也在准备你的最后一届希望你能早一点开始记录早一点相信稳定比速度更重要。等到夏天结束你会发现真正留下来的不是那辆车而是你学会的这套做事方式。