ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

智能车竞赛单车拉力组实战:图像处理与PID控制从入门到调试排障

智能车竞赛单车拉力组实战:图像处理与PID控制从入门到调试排障 每次翻看去年单车拉力组的代码和调试记录总有一种说不出的复杂情绪。从最初对着赛题规则一头雾水到后来能在一张灰度图像里快速找到赛道边界、在高速下稳稳过环岛这中间踩过的坑比我在实验室待的时间还长。大连海事大学同舟拾队的这套技术报告最初是交到组委会的文档后来很多学弟问我要我干脆把核心内容整理出来按照“规则理解—硬件搭建—图像处理—控制策略—调试排障”这条线来写希望能帮到正在准备智能车竞赛尤其是想碰单车拉力和摄像头赛题的队伍。这篇内容既讲“怎么跑通”也讲“为什么这么做”大白话为主但该较真的地方一点都不会含糊。1. 赛题拆解与整体设计思路1.1 单车拉力组到底考什么单车拉力组在智能车竞赛里属于“看着简单、跑起来要命”的类型。规则层面它通常要求小车从车库出发沿着赛道跑完规定的圈数期间要识别并处理十字、环岛、坡道、起跑线等元素最终准确停回车库。听起来和四轮组差不多但车辆本身是单车结构平衡、转弯、加速特性和四轮车完全两回事。四轮车即使转向不足也能用速度硬扛单车模型一旦速度快了弯道里稍微给错一个输出车就直接侧滑甩出去所以控制策略必须比四轮组更细腻。我们从赛题看到的第一层需求是“循迹”第二层是“稳定地高速循迹”第三层是“在各种赛道元素下不犯错地高速循迹”。这三层需求的优先级不能搞反。很多队伍刚开始只盯着速度结果十字路口直接冲出去环岛进不去速度再快也没意义。我们组的思路是先把元素识别做到位再回头压榨速度这样每一步的调试目标都很明确。1.2 系统架构的三层拆分整车系统我习惯分三层看。底层是机械和硬件包括车架、轮胎、电机、传感器、电源这一层决定了车辆的基本物理特性中间层是处理器的软件逻辑负责图像采集、数据处理、控制输出最上层是策略与状态管理负责在不同赛道元素之间切换运行模式比如环岛模式、十字模式、坡道模式。这样拆的好处是某个环节出问题能快速定位。比如车跑偏到底是轮胎磨损导致机械中心偏移还是图像中线算偏了又或者是 PID 参数不合适如果脑子里没有分层概念就会把所有问题都归到“调参”越调越乱。我们每次改完硬件都会强制自己在图像调试助手上看一眼中线偏移量确认硬件问题没有混进软件调试里。1.3 摄像头方案为什么是我们的选择单车拉力组允许的传感器方案一般有摄像头和电磁两种我们选了摄像头。原因很直接图像信息能看全赛道结构环岛、十字、坡道都能提前发现方便做策略电磁方案更像“沿着轨道走”前瞻距离短对速度提升的上限制约明显。摄像头方案的代价是处理复杂、调试变量多尤其是曝光、视角、二值化阈值每一项都够你折腾一个礼拜。如果队伍里有人以前写过图像处理代码我建议直接上摄像头如果全是新手电磁方案入门会平滑很多但后续想拿好成绩迟早要补图像。我们当时选摄像头还有一个私心同组的调试经验可以共享给后面报四轮组的队伍代码框架复用率很高。2. 硬件平台搭建与关键模块选型2.1 主控芯片和处理资源我们用的是 TC264 双核单片机这是当时参赛队伍里非常常见的配置。选它不是因为性能碾压而是社区资料多、坑都被前人踩平了。摄像头图像数据量大TC264 的 DCMI 接口可以直接接数字摄像头DMA 搬运数据不占 CPU处理完一帧再切下一帧这一个特性直接决定了图像处理能做到多少行、多少列。主控选型上有一条重要经验不要追新。每年比赛前市面上都会冒出新主控、新传感器看起来参数很漂亮但调试资料少遇到问题连问都没地方问。竞赛时间有限稳定的老方案比纸面性能重要得多。我们身边就有队伍换了新主控结果 SDK 里一个现成外设驱动都没有前两周全在扣底层寄存器进度彻底落后。2.2 摄像头、编码器与惯性传感器摄像头我们用了总钻风灰度摄像头输出灰度图像而不是 RGB减少了很多颜色处理的开销。灰度图的每个像素用一个字节表示亮度处理速度快适合单片机跑。安装高度和俯仰角非常关键装高了看得远但近处盲区大装低了近处清晰但前瞻太短。我们最终把摄像头架在大约 30 厘米高度、俯仰角 15 度左右既能看清车前 60 厘米的近处赛道也能看到四米外的弯道趋势。编码器装在后轮用来测车速。这里提醒一句编码器安装的同轴度一定要检查我们曾经因为编码器支架稍微歪了一点测出来的速度在高速时波动很大PID 怎么调都抖。惯性传感器选的是六轴 IMU主要用来辅助判断坡道和车姿不过单车模型本身倾斜角度变化剧烈IMU 数据一定要做低通滤波否则噪声比信号还大。2.3 电机驱动与电源稳定性电机驱动板用的是常见的大电流驱动方案控制方式就是 PWM 占空比。单车结构比四轮车对电机响应更敏感因为重心高猛踩油门车头会抬猛收油门车身会顿这都会干扰图像采集。所以我们给电机加了加速度斜坡把每一次速度切换拉长到几十毫秒让车身姿态变化平滑下来。电源是整个系统里最容易被忽略的环节。电池电量从 8.2V 掉到 7.4V 的过程中摄像头曝光和电机驱动都会受影响。我们给摄像头、主控和电机驱动做了单独稳压避免电机大电流拉低逻辑电压导致单片机重启。实测中我见过同行队伍因为电源纹波太大摄像头图像在高速时出现横纹查了半天才发现是电源问题。3. 摄像头图像处理与赛道元素识别3.1 灰度图像的二值化处理摄像头原始输出是灰度图赛道是浅色背景、深色赛道边线或者反过来具体看场地配色。我们要做的是把赛道从背景里分离出来最简单也最实用的方法是二值化设定一个阈值像素亮度大于阈值的设为白小于阈值的设为黑。阈值的选取直接决定图像质量。固定阈值最不靠谱因为场地光照明暗不均同一个车库场景里靠近灯下和远离灯下的亮度能差出一大截。我们用自适应阈值对每一帧图像计算一个全局灰度平均值再乘一个系数作为阈值。这个方案实现简单鲁棒性比固定阈值好很多。如果还想更稳可以用大津算法自动寻找让类间方差最大的阈值效果更好但计算量稍大。实际处理时我不会整个图像都做二值化而是只截取赛道区域附近的感兴趣区域也就是 ROI。这样可以大幅减少计算量也能过滤掉背景里的干扰物比如观众、围栏、远处的人影。ROI 的上下边界跟随车速和前瞻动态调整这是后面要讲的动态前瞻的基础。3.2 提取边缘和中线二值化之后图像变成黑白两大块下一步是提取赛道边缘。我的做法是从图像底部向上逐行扫描对每一行找到左边第一次出现黑到白跳变的点作为左边界右边第一次白到黑跳变的点作为右边界。正常直线赛道下左边界和右边界都稳定存在取中点即可得到赛道中线。问题出在边界缺失的情况。比如大弯道外侧边线太远跑出摄像头视野或者环岛区域边线断开这一行的边界就找不到了。如果强行用上一行的值填充中线会在丢失位置突然跳变车就会左右甩头。我们用的是宽度约束和斜率约束如果某行左右边界宽度明显异常就判定该行不可信用附近可信行的线性插值来补。对于连续缺失的段落则用赛道宽度先验值外推把边界“脑补”出来。3.3 环岛、十字和坡道的识别策略元素识别是单车拉力组拿分的关键。十字路口在图像里的表现是左右边界突然向两侧“炸开”前方出现横向的白色通道边缘连续性被打断。我们处理十字的方法是补线把左右边界在炸开点直接连起来人为生成一条虚拟的直道中线让小车保持直行通过。补线不是随便连要参考十字前一段的赛道方向如果入口是斜的补线也要跟着斜否则过十字后会冲进错误赛道。环岛比十字复杂太多因为环岛有一个“入环—绕环—出环”的完整过程。如果只靠简单的补线车会从环岛外侧直接冲过去。我们的策略用状态机管理先识别入环特征通常是右侧或者左侧出现圆环边界边界断开模式很特殊确认入环后设置环岛状态此时不再用普通中线而是跟踪环岛内边线引导车绕圈在环岛出口附近会出现赛道和主路汇合的特征这时候恢复到正常循迹状态。整个过程用状态变量串起来状态转移必须加连续多帧确认避免误触发。坡道识别我们依赖边缘斜率突变和 IMU 俯仰角辅助。图像上坡道会出现前方大面积阴影边界高度突然抬升同时 IMU 检测到车体俯仰角变化。识别到坡道后提速冲坡上到坡顶前收油门防止飞坡。这里比较考验速度规划和状态的配合我们在后面细说。3.4 逆透视变换和动态前瞻摄像头图像是透视视角前方的赛道宽度看起来比近处窄很多直接算出来的中线偏差在远处会被压缩导致转向响应不准。比较进阶的做法是做逆透视变换把图像映射成鸟瞰图让赛道的几何关系和实际场地一致。逆透视变换相当于把相机画面“摊平”来看远近的宽度比例就正常了环岛形状、十字结构也更直观。不过逆透视变换计算量大标定也繁琐我们最后是在近处直接处理原始图像在远处用一条虚拟的“前瞻线”读取透视位置。所谓动态前瞻就是根据当前车速动态决定要看多远速度慢时看近处速度快时看远处。我的理解是前瞻距离本质上决定了控制的“预判量”太近了车会在弯道里收紧太晚太远了近处弯道又被忽略。我们用的经验公式是“前瞻距离约等于车速乘以一个响应时间系数”具体系数要靠实车感觉。4. 运动控制与速度规划4.1 方向控制和角速度输出控制系统的核心是方向环和速度环。方向环的输入是图像里算出来的赛道中线偏差也就是车身当前位置和赛道中线的横向距离差。我们最终让方向环输出的是角速度而不是直接给舵机 PWM 占空比。这中间差了一层换算角速度乘以车速再考虑车辆轴距才能得到对应的转向半径进而换算成舵机角度或两侧轮子差速。为什么要把输出量定为角速度因为单车模型的转向响应和车速耦合很强同一个方向盘角度在低速和高速下产生的横向偏移完全不同。如果方向环直接输出转角你调好的参数只在一个速度区间有效速度一变就要重调。输出角速度后控制逻辑变成“需要的角速度是多少”执行层再根据当前车速换算成转角这样方向和速度两个环就解耦了参数也更通用。PID 的 P 项负责核心跟随D 项负责抑制振荡I 项用得很少。方向环的 D 项对单车特别重要因为单车高速时惯性大纯 P 控制会在中线附近来回振荡加一点 D 能让转向提前克制。我调 D 项的经验是先把 P 调到车能过弯但开始振荡然后慢慢加 D 直到振荡消失再稍微回调一点留出裕量。4.2 速度规划和元素状态机联动速度规划不是简单地在直道加速、弯道减速。我们给每个赛道元素分配了独立的速度档位直道全速大弯道降速环岛内限制到安全速度十字路口因为要直线通过速度可以保持但方向必须稳坡道则是提前加速再收油。状态机在这里的作用是打破“速度完全依赖图像偏差”的单调关系。普通循迹模式下速度根据前方弯道曲率动态调整进入环岛状态后速度不再只看曲率而是用一个更保守的预设值检测到出环后又切换回动态模式。这样做的原因是环岛内的曲率变化很复杂如果速度环一直跟着图像误差走车会在绕环过程中忽快忽慢姿态很难稳定。我见过不少队伍在速度规划上过度依赖模糊控制或者查表搞得代码非常复杂。实际上速度规划只需要保证“该快的地方敢快该稳的地方稳得住”用简单规则加状态覆盖就足够了。我们最后的速度规划代码不到一百行但每一行都是在赛道上验证过的。4.3 舵机响应和机械限位单车模型的转向执行机构有自己的响应延迟从控制信号变化到前轮真正转到目标角度需要十几毫秒。这个延迟在低速时不明显高速时就会被放大成“推头”或者“甩尾”。所以控制周期不能太长我们主循环控制在 10 毫秒以内图像处理完马上算控制量不挤占控制周期。舵机机械限位也要检查。我们第一次装车时舵机连杆长度没调好导致转角范围不居中直道方向环输出 0轮胎却是微微偏左的。这个机械小误差在图像上表现为赛道中线和车身实际运动方向不重合你以为车在走直线其实一直在轻微画弧。后来我们把车架空观察轮速相等时轮胎是否正对前方才把这个隐性误差干掉。4.4 速度环的反馈和标定速度环用编码器反馈PID 整定方向环类似先调比例再调积分。单车模型对速度环响应速度要求高因为弯道里需要快速把速度降下来如果速度环响应太慢车进入弯道时已经在超速方向环再努力也救不回来。编码器的标定很关键。我们要知道“PWM 占空比和实际转速的关系”可以在赛道上让车空跑记录不同占空比下的编码器读数拟合出一条近似线性曲线。实测中我发现电池电压变化会让同样占空比下的转速有变化所以速度环的输出本质上是补偿模型误差不能完全依赖标定表。5. 调试过程实录与问题排查5.1 调试工具链上位机、波形和日志没有趁手的调试工具智能车竞赛就成了盲调效率低得可怕。我们组花了一个礼拜搭调试环境现在看来非常值。图像调试用上位机连上摄像头后可以实时看二值图、边缘提取结果和中线拟合结果所有算法问题在电脑屏幕上无所遁形。控制参数的调试用串口波形把 PID 输出、速度、偏差实时画成曲线调参就像“看着心电图做手术”比凭感觉试快太多。SD 卡日志是最后兜底的手段。实车跑的时候不能连串口线因为线会拖累车身于是我们把关键状态量存到 SD 卡里跑完再把日志导出来离线分析。有一次小车连续在同一位置飞出赛道从日志里才看到那个位置的图像偏差在十帧内跳变了 80 个像素顺着这个线索定位到是曝光没处理好。5.2 常见问题速查表现象可能原因排查方向直道走着走着突然偏头中线拟合出现跳变检查二值化阈值和边界缺失处理十字路口冲出去十字补线逻辑没触发检查十字状态判定条件环岛入口直接冲过入环特征误判拉长确认帧数加入向心方向判断高速时车身左右振荡方向环 D 项不足或 P 项过大加重 D 项降低 P 项油门加速时车头翘起速度规划切换太猛加速度斜坡拉长摄像头图像有横纹电源纹波大检查稳压电机驱动隔离电池满电和亏电表现不一致速度环标定模型不准增加电压补偿过坡道后方向丢失坡道识别到但状态退出晚了调整坡道退出条件这类问题排查要遵循“先硬件后软件、先开环后闭环”的顺序。硬件上没锁紧的螺丝、没插牢的排线都会伪装成软件 bug我见过最离谱的一次是摄像头排线松动图像偶发雪花算法怎么改都压不下去。5.3 备赛中的版本管理和实车迭代智能车竞赛的调试周期长代码改着改着就会变成“新代码不如旧代码跑得好”这时候没有版本管理很容易心态崩溃。我们用 Git 管理代码每次实车有效调优后立刻打一个 tag这样下次调崩了能马上回退。硬件上我们也有记录表换了摄像头高度、轮胎胎压、机械结构后都要记录因为这些参数直接影响软件标定。实车迭代要追求“单变量原则”。一次只改一个参数改完上赛道跑三圈看效果效果不好就回退。很多队伍喜欢一次改五个参数然后车跑得好了都不知道是哪个改动起效跑得差了也不知道该怪谁。我们的经验是参数记录表比代码更重要它能让你在赛前一周还能稳定复现两周前的配置。5.4 赛前最后一周做什么最后一周不要研究新算法了重点是稳定复现和跑满时长。我们提前三天把所有赛道元素都布置好每天按比赛节奏跑完整的模拟流程包括发车、跑圈、停车。这个阶段暴露出来的问题往往都是“慢性病”比如某个元素的识别成功率只有七成平时觉得是偶然失误模拟赛里就会直接让你少跑一圈。停车入库是单车拉力组容易被忽略的环节。入库识别要用起跑线加距离双重判断因为起跑线每次经过都在图像里出现但只有跑完规定圈数后才该停。我们代码里用一个圈数计数器每次检测到起跑线就加一达到目标圈数后进入停车流程低速滑行到车库位置再刹车。踩过这么多坑之后我最大的体会是智能车竞赛比的不是谁的算法理论更漂亮而是谁能在连续一个月的调试中保持清醒把每一个小问题都按逻辑拆干净。同舟拾队的名字就是取“同舟共济”的意思有些坑确实要靠队友一起踩才能快速爬出来。如果你正在被 PID、环岛识别或者图像透视折磨别急着怀疑自己不行按我们文档里的排查顺序一步一步来车总能跑起来。最后再分享一个小技巧每次调车结束把当天的图像留存一份日后再调参数时翻出来对比很多你以为忘了的细节图像会帮你记得清清楚楚。
返回列表