1. 项目背景与核心挑战在智能车竞赛的全向组别里圆环赛道元素一直是个让人又爱又恨的存在。爱的是它作为标志性的复杂赛道是拉开技术差距、体现算法实力的关键点恨的是它的处理逻辑如果不够精细很容易让赛车在高速下“翻车”——要么是识别晚了导致冲出赛道要么是识别错了导致路径规划混乱。我这次开源的全向组算法在圆环处理上下了不少功夫核心目标就一个让车在高速状态下能像老司机一样平滑、稳定、精准地通过圆环而不是像个新手一样“一脚刹车、一顿操作猛如虎”。这个“圆环处理”模块绝不仅仅是图像里找到一个圆那么简单。它涉及到从原始图像到最终控制指令的完整链路摄像头看到的画面是什么样的怎么从一堆噪点里把圆环的轮廓准确地抠出来识别到了之后怎么判断车当前处于圆环的哪个阶段即将进入、正在通过、即将离开知道了阶段又该怎么生成一条既符合赛道物理约束又能让车跑得又快又稳的路径最后这条路径怎么转换成电机的控制量每一步都环环相扣任何一个环节的粗糙都会在最终的成绩上体现出来。我这次分享的就是我们在实际调车、比赛过程中从无数次“撞环”和“跑飞”的教训里总结出来的一套相对鲁棒的处理方案。2. 圆环的视觉特征提取与误判防御摄像头拍回来的图像在圆环区域往往不是教科书上那种完美的圆形。光照变化、车身震动导致的图像模糊、赛道边缘磨损、甚至是其他队伍的赛车留下的轮胎印都会对识别造成干扰。所以第一步不是急着找圆而是做好预处理把干扰降到最低。2.1 图像预处理为特征提取铺平道路我们的图像源是全局快门摄像头输出的是灰度图。第一步是进行高斯滤波一个5x5或者7x7的核就足够了目的是平滑图像抑制高频噪声特别是CMOS传感器本身的噪点和电机带来的高频振动干扰。滤波之后我们会进行一次自适应二值化。这里坚决不推荐使用全局固定阈值因为赛场上光线不均匀太常见了观众席的阴影、场馆顶灯的直射都会让赛道一部分过曝一部分过暗。我们用的是基于局部像素块均值的自适应二值化方法比如OpenCV的cv2.adaptiveThreshold配合ADAPTIVE_THRESH_GAUSSIAN_C它能根据图像不同区域的亮度动态调整阈值确保无论在明暗区域赛道的白色边缘都能被清晰地提取出来。注意自适应二值化的块大小blockSize是个关键参数。太小了会对噪声敏感太大了会模糊边缘。我们的经验是这个值大概取图像宽度的1/20到1/15比较合适。例如图像宽160像素块大小取11或13。二值化后我们得到的是黑白图像。接下来用Canny算子或者简单的Sobel算子进行边缘检测。实际上对于智能车这种对比度很高的场景有时直接对二值化图像进行轮廓查找cv2.findContours也是可行的但边缘检测能提供一个梯度信息对后续的筛选有帮助。我们通常选择Canny因为它的双阈值机制可以较好地平衡边缘的连续性和抗噪性。2.2 圆环特征筛选从轮廓中找出“真命天子”通过边缘检测或轮廓查找我们会得到一大堆轮廓。现在的问题是如何从中找出那个代表圆环的轮廓。这里不能只用cv2.minEnclosingCircle然后看圆度因为干扰太多了。我们采用了一套组合筛选策略面积筛选首先过滤掉面积过大或过小的轮廓。圆环在图像中的投影面积可以根据摄像头的俯仰角、高度和圆环的实际物理尺寸比赛规则会规定大致估算出一个范围。只保留在这个范围内的轮廓。凸性检测真正的圆环轮廓应该是凸的或近似凸的。使用cv2.isContourConvex可以快速排除那些奇形怪状的干扰块比如一片连在一起的噪点。圆形度筛选这是关键一步。我们计算轮廓的圆形度Circularity公式是4 * π * 面积 / (周长^2)。一个完美圆的圆形度是1。我们设定一个阈值比如0.7或0.75只有圆形度高于这个值的轮廓才进入下一轮。这一步可以过滤掉长条形的障碍物或者不规则的斑块。外接矩形纵横比计算轮廓的最小外接矩形并计算其宽高比。一个正圆的投影其外接矩形应该接近正方形宽高比接近1。我们允许一定的偏差比如设定比例在0.8到1.2之间。位置先验在全向组中圆环通常出现在赛道中央或特定组合元素如十字、三岔接圆环之后。我们可以结合上一帧的赛道中线信息预估圆环可能出现的图像区域ROI优先在这个区域内搜索。这不仅能加快处理速度也能避免远处看台上类似圆形的物体造成误识别。经过这五层筛选剩下的轮廓就极有可能是真正的圆环了。我们会对这些“候选者”进行最小外接圆拟合得到圆心坐标和半径。2.3 误判防御与状态保持即使经过严格筛选误判依然可能发生比如某一帧图像因为突然的强光反射彻底丢失了圆环信息。因此必须引入状态机和时间滤波。我们维护一个“圆环置信度”状态并设计了一个简单的状态机未识别状态连续N帧比如5帧没有找到符合条件的圆环置信度归零。初步识别状态当某一帧识别到一个符合条件的圆置信度加1。如果连续M帧比如3帧都能识别到且圆心位置在像素坐标上的跳动不超过一定阈值例如10个像素则进入确认状态。确认状态在此状态下我们相信圆环是真实存在的。即使某一帧识别失败我们也会使用上一帧的圆环参数圆心、半径进行“预测补全”同时置信度缓慢衰减。只有当置信度衰减到0才退回“未识别状态”。离开状态当车辆驶离圆环识别到的圆环半径持续快速增大在图像中越来越小或圆心移出图像下方一定范围则触发离开逻辑清空状态。这种机制保证了控制的连续性避免了因单帧图像误识别导致的控制指令突变这是高速稳定通过的关键。3. 基于圆环识别的车辆状态估计与阶段划分识别到圆环的几何参数后我们需要解读这些参数回答一个核心问题我的车现在相对于这个圆环处于什么位置下一步该干什么这需要将图像坐标转换到车身坐标系并进行阶段划分。3.1 坐标转换与相对位置计算摄像头标定后我们可以建立一个从图像像素坐标(u, v)到车身坐标系(x, y)通常车体中心为原点车头方向为x轴正方向的映射关系。这里假设我们已经有了标定参数内参和相对于车体的外参。对于识别到的圆环我们得到图像中的圆心(u_c, v_c)和半径r_pixel。通过坐标转换可以估算出圆环中心在车身坐标系下的水平位置(x_ring, y_ring)。这里的y_ring可以粗略理解为车头距离圆环中心的纵向距离前提是摄像头朝前且俯仰角不大。更关键的是计算车辆预期进入点。圆环不是一个实心障碍我们需要让车从环中穿过。通常我们会设定圆环的“入口”和“出口”。一个简单有效的策略是将圆环看作一个“门”车辆需要从环心穿过。那么我们需要规划一条路径让车的中心线对准环心。我们定义两个关键状态量横向偏差车体中心线与圆环中心在横向y轴上的距离d_lateral y_ring。纵向距离车头到圆环中心的纵向距离d_longitudinal x_ring这里假设x轴正向为车头方向。3.2 通行阶段状态机划分根据d_longitudinal和d_lateral以及圆环的半径我们将通过圆环的过程划分为四个阶段每个阶段对应不同的控制策略阶段触发条件示例核心任务控制重点1. 预瞄准阶段d_longitudinal R_ring L_lookaheadR_ring为圆环物理半径估计值L_lookahead为前瞻距离提前调整车头方向使车辆大致对准圆环中心。以横向偏差d_lateral为主要控制目标使用PD控制器生成一个较小的前轮转角或差速让车慢慢向环心靠拢。此时速度可以保持较高。2. 进入与穿越阶段-R_ring d_longitudinal R_ring L_lookahead控制车身平稳穿过圆环中心区域。这是最关键的阶段。控制目标从“对准环心”平滑过渡到“保持当前朝向”。需要引入圆环的切向速度参考。同时要防止过度转向导致在环内振荡。速度可能需要适度降低。3. 出环稳定阶段d_longitudinal -R_ring且 圆环仍被识别车辆已穿过环心需要稳定车身准备衔接后续赛道。控制目标切换回常规的赛道中线跟踪。但由于刚经过圆环车身姿态可能有一定偏差需要给控制器一个短暂的“恢复期”允许它柔和地纠正方向而不是急打方向。4. 后圆环恢复圆环丢失识别置信度归零完全回归普通赛道跟踪。使用常规的PID控制但可以适当提高一点积分项的抗饱和能力以应对可能存在的残留误差。这个状态机是控制逻辑的骨架。L_lookahead这个前瞻距离参数非常重要它决定了车辆提前多久开始为圆环做准备。设得太短车到环前才急转弯设得太长可能会对远处的其他弯道产生误干预。这个参数需要和车速联动车速越快前瞻距离应该相应增加。4. 圆环区域的路径规划与控制策略知道了自己在哪、处于哪个阶段接下来就要解决“怎么走”的问题。对于全向组我们的车是麦克纳姆轮或全向轮具备平面内三个自由度的运动能力前后、左右、旋转这给路径规划带来了更大的灵活性但也增加了复杂性。4.1 参考路径生成我们并不需要为圆环规划一条复杂的曲线。对于从环心穿过这种策略一个非常有效且简单的参考路径就是一条直线——从车辆当前位姿指向圆环中心再指向圆环出口方向即圆环中心对称的另一侧的直线。具体生成步骤如下在预瞄准阶段参考路径点就是圆环中心点(x_ring, y_ring)。当进入进入与穿越阶段参考路径点可以设置为圆环中心点。但更平滑的做法是在环心附近让参考路径点沿着一条虚拟的“穿过环心的直线”运动。例如我们可以定义一个路径点(x_ref, y_ref)其中x_ref根据车辆运动估计或时间递增y_ref始终为0假设环心在车身坐标系y0上。在出环稳定阶段参考路径点迅速切换回由常规赛道识别算法提供的中线点。4.2 全向底盘的运动解算与控制这是全向组区别于其他组别的核心。对于差速轮或阿克曼转向的车控制输出通常是转向舵机角度和电机速度。而对于全向底盘我们需要解算出四个轮子或三个全向轮各自的速度指令。我们采用分层控制结构上层控制器根据路径跟踪误差横向偏差、角度偏差计算出一个期望的车体运动指令。这个指令是一个二维向量[v_x_desired, v_y_desired, omega_desired]分别代表车体坐标系下前进速度、横向平移速度和旋转角速度。横向偏差控制使用一个P或PD控制器根据横向偏差d_lateral计算出所需的横向速度v_y_desired Kp_lat * d_lateral Kd_lat * d(d_lateral)/dt。目的是产生一个横向移动来消除偏差。角度偏差控制同样使用PD控制器根据车头方向与参考路径切线方向的夹角角度偏差计算出所需的旋转角速度omega_desired。前进速度v_x_desired通常由一个独立的速度规划模块给出在圆环区域可能会适当减速。下层解算器将上层得到的[v_x, v_y, omega]指令通过运动学逆解转换成每个轮子的转速。对于麦克纳姆轮这是一个固定的线性变换矩阵取决于轮子安装角度和位置。将车体速度指令乘以这个逆运动学矩阵就得到了四个轮子的目标转速。4.3 圆环区域的特殊参数整定在圆环区域控制器的参数需要与直道、普通弯道有所区别横向控制增益在预瞄准阶段Kp_lat可以设置得稍大一些让车快速对准。但在进入与穿越阶段这个增益要降低甚至可以将v_y_desired直接设为零或一个很小的值目的是让车“滑”过圆环中心而不是剧烈地左右修正。剧烈的横向修正容易导致车身在环内摇摆失速甚至撞环。前馈补偿在穿越阶段由于我们希望车体基本保持进入时的角度穿过可以引入一个基于圆环半径和车速的前馈旋转角速度omega_feedforward。例如如果希望车沿切线方向这个前馈量可以粗略估算为v_x_desired / R_ring。将其加到omega_desired上可以让控制更顺滑。速度规划圆环区域必须减速。我们的策略是在预瞄准阶段后期开始线性减速在进入圆环中心时达到最低速这个最低速需要测试保证车有足够的操控性穿过中心后开始线性加速。减速和加速的斜率要平缓避免冲击。5. 调试心得、常见问题与实战技巧理论说完来点实在的。下面这些坑我们几乎一个不落地都踩过希望你能绕开。5.1 图像识别部分的“坑”“幽灵圆环”最头疼的问题就是在没有圆环的地方识别出了圆环。除了前面提到的多层筛选一定要结合赛道元素逻辑。比如圆环不会出现在坡道上也不会紧贴着另一个圆环除非是特殊元素。可以维护一个简单的赛道地图记忆对识别结果进行合理性校验。圆环大小跳动拟合出的半径帧间变化大。这通常是轮廓提取不稳定造成的。解决方法是对二值化阈值进行滤波避免帧间突变。对识别到的半径进行低通滤波如一阶滞后滤波R_filtered α * R_current (1-α) * R_filtered_prev。α取值在0.2到0.5之间平滑效果明显。在状态机的“确认状态”下直接使用预测值不更新半径。光照剧变下的失效从阴影区突然进入强光区图像可能全白或全黑。除了自适应二值化可以增加一个图像整体亮度检测模块。当检测到亮度突变超过阈值时暂时冻结控制输出或切换到基于惯性导航如果有的短时预测同时快速调整摄像头曝光参数或软件增益。5.2 控制策略部分的“坑”在环内“画龙”车穿过圆环时左右摇摆。根本原因是横向控制过强。在穿越阶段一定要大幅降低横向控制的PID增益或者切换到一个更“柔和”的控制模式。我们的经验是在穿越阶段将横向速度指令v_y_desired的上限设得非常低或者直接使用一个很小的固定值来微调主要依靠前期的预瞄准和车体的惯性来通过。出环后“甩尾”车冲出圆环后猛地向一侧偏转。这是因为出环瞬间从“圆环跟踪模式”切换回“普通赛道跟踪模式”时参考路径点发生了跳跃导致误差突变控制器输出一个很大的纠正指令。解决方法是在状态切换时做一个参考路径的平滑过渡。例如在出环稳定阶段不是立刻切换到远处的赛道中线点而是生成几个虚拟的过渡点让参考路径从环心平滑地连接到识别到的赛道上。速度与路径不匹配车速太快但规划的路径曲率太大比如为了对准环心拐了个急弯导致离心力过大车轮打滑。必须要有速度-曲率约束。根据轮胎摩擦力和车重估算一个最大安全向心加速度a_max。那么在路径曲率半径ρ的地方车速v必须满足v^2 / ρ ≤ a_max。在圆环预瞄准阶段如果计算出的所需横向加速度超过阈值就要提前、平顺地减速。5.3 参数调试的实用流程不要所有参数一起调按顺序来静态调试把车放在圆环前用手推着慢慢走通过无线串口打印出识别到的圆环坐标、半径、计算出的横向偏差、纵向距离以及状态机状态。确保视觉识别模块输出稳定、正确状态机切换符合预期。低速闭环调试让车以很低的速度如0.3m/s自动通过圆环。重点观察状态机切换是否及时、平滑在穿越阶段车的横向摆动大不大如果大降低该阶段的横向控制增益。出环后车能否顺利接回赛道如果不能检查参考路径过渡逻辑。中高速调试逐步提高速度。此时重点关注预瞄准阶段是否足够提前如果不提前增加前瞻距离L_lookahead。进入圆环前减速是否平缓调整速度规划曲线的斜率。高速下识别是否还能稳定检查图像处理耗时确保在控制周期内完成。压力测试在不同光照条件下、从不同角度接近圆环、甚至故意制造一些干扰如用纸片部分遮挡圆环测试整套算法的鲁棒性。记录下失效的场景回头优化视觉筛选逻辑或状态机的容错机制。圆环处理是智能车算法里一个非常经典的模块它很好地串联了视觉感知、状态估计、决策规划和控制执行。把这套逻辑吃透、调稳不仅能让你的全向车在圆环上如鱼得水其中蕴含的“识别-滤波-状态机-分层控制”的思想对于处理其他复杂赛道元素如车库、坡道也同样具有很高的参考价值。最终所有的算法都要服务于一个目标让车跑得又快又稳。在调参时不妨时不时问自己一句“如果我是车上的那枚单片机我收到的指令让我感觉舒服吗” 找到那个让车感觉“舒服”的参数点往往就是最优解。