智能车轮腿方案:室外视觉识别与开源实践 全国大学生智能车竞赛做了二十多届常见方案已经很成熟想在国赛里拿一等奖要么把成熟路线做到极致要么拿出点别人没怎么见过的结构。这里要拆的21届智能车轮腿方案拿的是室外视觉方向国一属于后者。车体不是普通四轮而是带腿部结构的轮腿构型视觉不是在室内固定灯光下做灰度巡线而是在室外强光、阴影、反光、路面材质变化都存在的环境里识别赛道。整份工程代码已经开源适合正在备赛、准备换新构型、或者想从传统摄像头方案往视觉方案转的队伍参考。我会按这个顺序讲轮腿和室外视觉各自难在哪车体和视觉怎么搭、怎么调从仿真到实车怎么跑通最后是开源项目整理和问题排查思路。整套内容不是照搬某支队伍的完赛报告而是把这类方案公认的坑、参数和判断标准整理出来方便你拿着开源代码对照验证。1. 先搞清楚轮腿、室外视觉和猎奇方案到底难在哪1.1 轮腿不是简单地把轮子装在腿上轮腿结构最常见的理解是“能跑的腿”或“能跨的轮”。实际做起来会发现它比纯轮式多了一整套运动学问题。轮式车只要考虑转向半径、速度、侧滑轮腿车还要考虑腿部关节角度、重心位置、落地瞬间的冲击、姿态变化对传感器的影响。比赛里常见的轮腿构型大致有三类。第一类是两轮自平衡加腿部结构靠车体倾角和腿长变化实现越障灵活但最不稳调平衡会花大量时间。第二类是四轮独立驱动加主动腿部关节每个轮子都能单独抬升越障能力最强但电机数量多、机械结构复杂、整车重量高对驱动板和控制频率的要求也更高。第三类是前后轮加被动悬挂式腿部结构最简单腿不主动发力只靠形变吸收冲击稳定性好但越障高度有限。三类构型的调试难度差别很大。两轮自平衡构型最考验控制频率姿态稍不稳就可能摔四轮主动腿最灵活但复杂度最高被动悬挂式最容易上手但上限也低。这个开源方案具体选的是哪一种要看仓库里的机械图纸和控制代码。无论哪一种你拿到代码后都应该先搞清楚一件事它的腿部到底是主动控制还是被动跟随。这决定了你改参数时动的是平衡环、位置环还是姿态环方向错了参数越调越乱。1.2 室外视觉的干扰源比室内多得多室内灯光条件下的赛道识别主要处理的是反光和固定阴影环境相对可控。室外完全不是一回事。室外识别至少要多面对四类干扰太阳直射导致的过曝区域白色赛道边界可能直接变成一片白边界信息直接丢失树木、围栏、建筑投射的长阴影阴影边缘和赛道边界在灰度上非常接近路面材质变化比如柏油、水泥、砖地混在一起同样一个阈值在不同路段表现完全不同风引起的树叶晃动、飞虫、云层遮光造成的亮度突变单帧图像里会出现随机噪声。所以室外视觉方案不能照搬室内那套“固定阈值二值化加找边界”的流程。要么把曝光控制做好要么在算法里加自适应处理要么把摄像头视角和安装角度设计得能避开大部分干扰。这个开源方案能在室外环境里跑稳说明它在曝光或预处理环节一定做了针对性处理而不是靠算法硬扛。1.3 猎奇方案的真正价值不在结构本身猎奇意味着规则里没有明确对应的技术路线评审时反而不容易找到参照系。它的价值在于第一避开成熟方案的激烈内卷第二赛道适应性确实有物理上的优势轮腿能过一些纯轮式过不去的坎第三如果测试数据完整、开源整理到位对后来者有很强的参考意义。但猎奇也有代价。没有现成方案可以抄所有坑都要自己踩一遍机械加工、控制调试、视觉识别三块都要自己打通任何一块拖后腿整体成绩都上不去。这也是为什么这类方案能拿国一通常不是某一项特别突出而是机械、控制、视觉三者没有明显短板。如果你准备借鉴这个方案先别急着看它的猎奇部分先看机械结构图、电机选型和控制频率。这三项决定你能不能稳定复现。2. 车体和运动控制轮腿构型怎么选、怎么调2.1 先确认你手里的硬件条件准备复现这套轮腿方案之前先清点自己队伍的条件。第一是电机步进电机还是无刷直流电机带不带编码器编码器分辨率多少直接决定你能获得多精确的转速和位置反馈。第二是驱动板输出电流够不够、PWM 频率上限是多少、有没有过流保护轮腿在越障瞬间电流会突然增大保护不够很容易烧。第三是主控处理器算力能不能同时跑视觉和控制回路外设接口够不够接所有传感器。第四是结构件3D 打印、碳板、铝件刚性不同腿部响应差异明显软结构的延迟会被控制环放大。这些条件不一定要和原项目完全一致。原项目用的是哪款主控、哪类电机以开源仓库的物料清单为准。你只需要保证自己的组合能把控制频率跑到足够高关节间隙足够小。如果机械结构精度不够再好的控制算法也补不回来。2.2 控制频率和姿态解算是核心轮腿控制最忌讳的是“控制频率不够但参数先调满”。常见经验值是姿态解算频率至少到千赫兹量级才能保证小角度波动时来得及修正速度环、位置环不需要这么高但也要在 200Hz 以上IMU 的加速度计和陀螺仪必须做融合处理不能直接拿原始值当角度用。融合方式可以是互补滤波也可以是卡尔曼滤波关键是要稳定、少延迟。如果你拿到代码后发现它把姿态解算放在和图像处理同一个循环里要注意 CPU 占用。视觉处理一旦耗时波动姿态环就会被拖慢车就会出现周期性抖动。更稳的做法是控制中断单独跑视觉处理在主循环里跑两者通过共享数据交互并做好数据锁或队列。这样即使视觉偶尔卡一下车也不至于立刻失去平衡。2.3 平衡和越障的调参顺序如果你复现的是两轮自平衡轮腿调参顺序一般是这样先把车架固定单调整传感器零偏和角度融合确认 IMU 数据没有明显漂移再解锁轮子先把原地平衡调稳再考虑前进后退然后调到能直线慢速走十米不摔倒再开始加入腿部动作最后才做越障越障高度要从低到高慢慢加不能一步到位。调参时最容易犯的错是“哪个参数不稳就拉哪个”。实际上轮腿抖动经常是机械间隙大、控制频率不够、或者 IMU 安装松动导致的参数只是最后的表现形式。我自己比较推荐的做法是每次只改一个参数记录改动前后二十秒的传感器波形或曲线而不是凭感觉微调。至少这样能知道到底是哪个环节在恶化后面复盘也有依据。3. 室外视觉从采图到识别的完整管线3.1 摄像头选型和安装决定了后处理难度室外视觉第一个决策是摄像头。优先考虑这几点全局快门优于卷帘快门车速快时卷帘快门会产生果冻效应图像里的赛道边界会歪动态范围尽量大能同时保留亮部和暗部细节这对室外逆光路段特别重要帧率至少要 60fps否则高速过弯时容易丢帧最好能手动调节曝光时间和增益不能只有自动曝光因为自动曝光在场景突变时会有一段调整期。安装位置同样重要。摄像头装得越高视野越远但近处盲区越大装得越低近处看得清但远处信息不足。轮腿车还有个额外问题腿部动作会让车体姿态周期性变化摄像头视角会跟着晃。如果能加一层机械减震或者把视觉安装支架固定在车体的主要质量中心附近画面稳定性会好很多。室外风大的时候安装支架的刚性不足会导致高频抖动这个问题经常被误判成算法不稳定。3.2 光照变化时先动曝光再动算法室外视觉最容易翻车的点就是光照突变。车从阴影区跑到太阳直射区自动曝光需要时间调整这个时间内图像可能过曝或欠曝识别就会断。处理思路有三种固定曝光参数配合 ND 滤镜或偏振镜压光保证大部分情况下图像亮度稳定自动曝光但限制调整范围避免单帧突变在算法里做曝光补偿映射把不同亮度下的图像统一到相近的灰度分布。我个人更推荐先用固定曝光把整体跑通。等系统稳定了再考虑自动曝光和动态调整。如果一上来就同时开自动曝光和自适应算法一旦识别出问题你很难判断是曝光调整滞后还是算法参数不对多层因素混在一起非常不好排查。很多队伍在室外路段反复丢线最后发现不是算法问题就是强光下过曝导致边界信息彻底消失。3.3 一条实用的识别管线室外赛道的识别管线常见流程是取图裁剪出有效 ROI 区域减少计算量做色彩空间转换或直方图均衡降低光照影响用边缘检测或自适应阈值提取赛道边界候选点按行扫描或按列扫描拟合出左右边界和中线最后把中线信息换算成横向偏差和航向偏差交给底层控制。这套流程每一步都有替代方案。边缘检测可以用固定阈值也可以用 Canny边界拟合可以用直线也可以用多项式或样条。关键是先跑通再比较效果不要一上来就上看起来很高级的模型。如果输入图像本身过曝或者太暗后面的算法再先进也救不回来这一点在室外方案里尤其明显。4. 三步跑通离线数据、低速实车、整圈闭环4.1 第一步先拿离线数据验证视觉算法拿到开源代码后不要直接烧进车就跑。原始仓库如果提供了测试视频或数据集先用这些数据验证视觉模块的输出。环境准备时如果依赖包下载慢也可以换成国内常用的开源镜像源能省不少时间。这个阶段要确认三件事静态单帧上赛道边界和中线输出是否合理连续帧之间输出是否平滑有没有跳变不同光照片段下识别结果是否一致。如果原始代码不带数据你自己也要录一段室外车道的视频用脚本回放测试。离线测试环境干净、能反复跑是定位算法问题的最高效方式。4.2 第二步低速半开环实测离线视觉没问题之后再上车。第一次上车建议这样做不要开视觉闭环转向先手动遥控或固定直行速度降到 0.5m/s 以内人跟在车旁边随时准备扶车把视觉输出实时显示到屏幕上同时保存原始图像和控制量日志跑一圈回来看记录里视觉输出有没有异常跳变。这一步的目的是把“视觉对没对”和“控制灵不灵”两个问题拆开。如果视觉输出在低速时就已经乱跳说明算法或安装有问题跟控制无关不要去调 PID。如果视觉输出稳定但车还是跑偏那才是控制参数的事。很多人一上车就往 PID 上调结果调了半天问题根本在摄像头固定不牢。4.3 第三步整圈闭环逐步提速半开环稳定之后开始把视觉输出接入转向和速度控制。提速要遵循“一次只提百分之十到二十”的原则每提一档都要跑完整圈看稳定性。整圈闭环测试时要记录这些数据单圈用时、出赛道次数和位置、视觉跳变次数、控制量是否饱和、电机温度和电池电压变化。如果提速后出现规律性失误比如总在同一个弯道冲出去大概率不是视觉整体不行而是那个弯道的曲率或光照条件触发了某个阈值。把对应时段的图像日志翻出来看比盲目调参数快得多。还要注意电池电压的影响室外跑圈时间长了电压下降电机响应变慢同一个参数在不同电量下的表现可能差很多。闭环测试至少要连续跑五圈不能以单圈成功作为验收标准。轮腿车的姿态和视觉受环境影响波动大偶尔一圈成功说明不了问题。5. 核心参数和验收标准怎么判断方案真的稳5.1 先定义一组可量化的指标很多队伍判断“稳不稳”靠感觉这是最要命的。建议至少维护下面这张表每次测试都更新指标说明常见参考范围姿态解算频率IMU 融合输出频率500Hz 以上越高越好控制回路频率输出 PWM 的频率1kHz 量级或更高视觉帧率摄像头实际处理帧数60fps 以上为佳视觉处理延迟从取图到输出控制量的时间最好控制在 20ms 内单圈最大速度整圈中能稳定跑到的峰值以赛道和规则为准越障高度轮腿能稳定通过的障碍高度以实际机械限位为准连续成功率连续十圈不失误的比例至少八成以上再谈提速注意参考范围只是经验值不代表原项目就是这些数值。原始仓库里如果给出了配置参数以仓库文档为准。关键是你要有自己的量化记录而不是每次都用“还行”来描述结果。5.2 稳定性比速度重要室外轮腿国一方案的难点不在于某一圈跑出多快而在于能不能把快和稳同时保持。判断稳定的方式不是看最好成绩而是看最差成绩。最好的三圈平均成绩意义有限最差的三圈是否出现失误、是否接近冲线才是真实水平。失误位置如果集中说明是特定路段问题如果分散说明是系统随机性问题处理方式完全不同。如果最差成绩总是掉链子先别提速回头排查对应路段的图像日志和传感器数据。室外环境里哪怕同一条赛道上午和下午的光照都不一样不能因为上午跑得好就认定下午一定没问题。5.3 参数调整的优先级参数太多时容易陷入“改一个坏一个”的循环。我一般按这个顺序排查第一是机械结构关节间隙大不大、轮子有无松动第二是底层控制频率够不够、姿态稳不稳第三是视觉安装摄像头固定牢不牢、曝光是否稳定第四才是算法参数阈值、ROI、拟合点数这些最后才动。这个顺序的核心逻辑是上一层的问题不解决下一层调参只是在掩盖问题。比如曝光不稳导致边界丢失你把拟合点数从 10 改成 20效果只是短暂变好换个光照又会出问题。真正该做的是把曝光稳定性解决掉。6. 常见问题排查链路6.1 视觉识别不准、跳变现象是边界线时断时续、中线左右跳、某段赛道完全丢失。排查顺序先看原图确认是不是过曝、欠曝、阴影强干扰再看 ROI 区域是不是把非赛道区域也算进来了接着看预处理参数阈值、二值化方式是否适合当前光照最后看拟合算法点数太少或多项式阶数太高都容易跳变。注意不要在没看原图的情况下直接改二值化阈值。很多“算法不行”最后都变成“摄像头曝光不合适”。建议在日志里同时保存原始图像和处理结果图像这样问题出现时能直接对照不用凭记忆回放。6.2 车体抖动、跑偏、姿态不稳现象是直行时左右摆头、越障后姿态回不来、弯道里侧倾过大。排查顺序先确认 IMU 固定牢固线缆有没有在运动中拉扯传感器再检查机械关节间隙间隙大的地方通常伴随可听见的撞击声然后看姿态数据曲线是持续振荡还是偶发跳变两者调法完全不同最后才查控制参数重点是速度环和位置环的超调量。如果姿态数据本身干净但车体还是抖那就是控制频率或阻尼不够。如果姿态数据本身就乱那就先解决传感器安装和滤波参数怎么调都白搭。轮腿车的线缆管理也是常见坑腿部运动时线缆如果搭在 IMU 或摄像头上传感器读数会被机械扰动污染。6.3 越障失败或者摔车现象是过障时轮子卡住、车身前翻、落地后跑偏。排查顺序先确认障碍高度是否在机械行程范围内再检查接近时速度是否过快腿部有没有足够时间完成动作然后确认腿部动作与视觉输出的时序有没有冲突最后看落地瞬间的姿态修正是不是单独逻辑而不是复用平地平衡参数。轮腿越障其实是三个阶段的控制问题接近时的速度规划、越障时的关节动作、落地后的姿态恢复。三个阶段用同一套参数很难同时做好。很多队伍卡在越障就是因为只调了中间那个阶段的参数忽略了接近速度和落地恢复。7. 开源项目怎么整理别让代码躺在仓库里7.1 一个能被人复现的仓库至少要有这些拿到别人的开源代码第一件事不是看 README 有多漂亮而是看能不能按文档从零跑起来。反过来你自己开源时也要按这个标准要求自己。一个值得参考的目录结构大概是这样smartcar-wheel-leg/ ├── README.md ├── docs/ │ ├── 硬件清单.md │ ├── 机械装配说明.md │ └── 调试记录.md ├── firmware/ │ ├── control/ # 姿态和运动控制 │ └── vision/ # 图像处理和识别 ├── config/ │ ├── control_params.yaml │ └── vision_params.yaml ├── dataset/ │ └── test_videos/ # 至少录几段实测视频 └── tools/ └── replay.py # 离线回放和可视化工具README 里最关键的几项硬件清单、依赖版本、烧录或编译步骤、第一次上电检查事项、已知问题列表。缺少任何一项新手复现都会卡住。尤其是依赖版本很多项目过了半年自己都跑不起来往往就是某个库升级了导致不兼容。7.2 配置参数要和代码分开室外视觉和控制参数会因为赛道、光照、车重不同而差别很大。把参数写成配置文件比硬编码在代码里方便太多。视觉配置里至少应该有摄像头分辨率、帧率、曝光时间、增益范围ROI 区域坐标二值化阈值或自适应参数边界拟合的采样行数和多项式阶数。控制配置里至少有IMU 安装方向和坐标系定义姿态环、速度环、位置环的 PID 参数越障阶段的速度阈值和关节角度序列。参数文件要注释清楚每个参数的作用和调整范围。光给数值不给含义别人拿到手还是不知道怎么改。你自己过两周回来看大概率也会忘。7.3 许可证和文档语言开源不一定非要选最宽松的许可证。如果只是想让同赛道的同学交流选一个常见许可证并在 README 里写清楚“可自由学习、商用需联系作者”之类的说明即可。关键是把使用边界写明白避免有人拿着代码去比赛出了问题反过来怪作者。文档语言建议用中文为主标题或关键术语配上英文这样国内队伍看起来快国外开发者也有引用路径。测试数据如果单独存放链接要放到稳定位置别经常变动。开源的意义不是把代码放上去就结束而是让下一个队伍能在你的基础上少踩一个坑。哪怕只写清楚“这个位置我摔了三次”也很有价值。8. 给下一届选手的几条实在建议8.1 先求稳再求猎奇猎奇结构确实能带来差异化但前提是你已经把传统路径的基本功练好。轮腿方案里同时涉及平衡控制、腿部运动学和视觉识别任何一块能力不够整台车都会成为“会动的 demo”而不是“能完赛的作品”。如果你们队伍是第一次参加智能车竞赛我建议先用成熟四轮方案把比赛流程、调参方法、时间管理跑通再考虑轮腿或其它新构型。如果已经有国赛经验再动手做猎奇方案成功率会高很多。8.2 不在训练现场解决所有问题很多队伍的常规操作是到现场发现问题现场改参数反复试。这个方式非常低效。更合理的做法是把问题带回去用离线数据或仿真环境复现再在训练场验证。我见过不少队伍把百分之九十的时间花在最后两周改参数上结果真正的问题在机械设计或姿态解算逻辑里参数根本改不出来。现场调试只适合做微调不适合做大改。室外视觉尤其如此光照、风力、场地材质都在变现场看到的问题可能隔二十分钟又消失了靠现场反复试错很难积累有效数据。8.3 把失败记录当成最重要的资产备赛过程中最有价值的不是顺利跑完的那几圈而是每一个失败瞬间背后的数据摔倒前的 IMU 曲线、丢线前的图像帧、冲弯前的控制量。把这些数据保存下来命名清楚隔几天回顾一次很多规律会自己浮现出来。等到了写开源文档或赛后复盘时这些失败记录比任何“成功经验”都有参考价值因为成功的路每个人都不一样失败的原因却常常高度相似。我自己看过不少智能车开源项目发现真正能被后人复现并继续往前走的往往不是代码最漂亮或算法最亮的而是测试数据完整、文档诚实、参数可改的项目。这套轮腿室外视觉方案能在21届拿到国一本身就是对这三个点的最好验证。如果你决定在这个方向投入请先把机械、控制、视觉三类问题各拆成一个小目标逐个解决最后再把所有模块拼起来。这条路不短但走通之后你带走的绝不只是那张奖状。