首页 / 资讯中心 / 文章详情

智能车竞赛电路组开源方案:视觉惯导电磁三层感知架构与调试实战

智能车竞赛电路组开源方案:视觉惯导电磁三层感知架构与调试实战 ★ FEATURED ARTICLE
1. 项目缘起与整体设计思路1.1 为什么会有这份开源目录21届智能车竞赛的赛道上疯狂电路组一直是个特殊的存在。它不像四轮组那样有成熟的循迹方案可以照搬也不像电磁组那样有相对固定的信号处理范式电路组的核心难点在于——你得自己搭一套能稳定识别赛道元素的硬件系统再用软件把那些模拟信号翻译成车能听懂的控制指令。Soberup战队在那一届比赛结束后把整个项目的代码、原理图、调试笔记整理成了一份开源目录这件事在当时的参赛圈子里引起了不少关注。我做智能车相关的技术分享有好几年了见过太多队伍比赛完就把代码锁进硬盘里下一届学弟学妹想参考只能对着空荡荡的GitHub仓库发呆。Soberup这份开源目录的价值不在于代码写得多优雅而在于它完整记录了一个队伍从零到完赛的全过程——包括那些走弯路的记录、参数调崩的截图、以及最后为什么选择某个方案的决策逻辑。这些东西比一份漂亮的最终代码有用得多。这份目录适合谁看如果你是第一次参加智能车竞赛想了解电路组到底在做什么它能帮你建立完整的认知框架如果你已经有一定基础正在为某个具体问题发愁比如视觉识别在强光下不稳定、惯导积分漂移怎么处理里面的调试记录能给你提供直接的参考哪怕你只是对嵌入式视觉和传感器融合感兴趣这份目录里的技术选型思路也有借鉴意义。1.2 整体架构是怎么搭起来的Soberup战队最终采用的方案是“视觉为主、惯导为辅、电磁兜底”的三层感知架构。这个选择不是一开始就定下来的而是经过了好几轮迭代。最初他们尝试过纯视觉方案用摄像头识别赛道边线和元素但在调试中发现两个致命问题一是光照变化对识别效果影响太大室内赛道不同区域的亮度差异能到30%以上二是当车高速通过十字路口或环岛时单帧图像的处理延迟会导致控制指令滞后。后来加入惯导模块用陀螺仪和加速度计做姿态解算提供短时间内的位置和角度变化估计。惯导的好处是响应快、不受光照影响但缺点是积分漂移——你永远不知道它什么时候会突然告诉你车转了90度实际上车还在直行。所以最终的架构是视觉负责绝对位置和元素识别惯导负责短时高频的姿态补偿电磁信号作为最后的兜底判断当视觉和惯导都不可信时至少还能沿着电磁线走。这个三层架构在代码层面体现为三个独立的处理线程通过一个共享的环形缓冲区交换数据。视觉线程以30帧每秒的频率输出赛道元素列表和边线方程惯导线程以200赫兹的频率输出姿态角速度电磁线程以1千赫兹的频率输出偏差值。主控线程根据当前车速和赛道状态动态调整三个数据源的权重低速时视觉权重高高速时惯导权重高检测到异常时电磁权重拉满。1.3 硬件选型的取舍逻辑主控芯片选的是STM32H743当时市面上也有用RT1064的性能更强但价格贵不少。Soberup的选择理由是H743的480兆赫兹主频足够跑视觉算法双精度浮点单元对惯导积分运算友好而且他们队伍之前有H7系列的使用经验能省去不少底层驱动的调试时间。这个决策很务实——比赛准备时间有限用熟悉的平台比用理论性能更强的平台更稳妥。摄像头用的是总钻风MT9V034全局快门灰度输出分辨率可配置。全局快门在高速运动场景下不会产生果冻效应这对智能车来说很关键。灰度图虽然丢失了颜色信息但数据量小、处理速度快而且赛道识别本质上就是找黑白边界颜色反而是干扰。他们试过彩色摄像头光是白平衡调整就花了一周时间最后果断换回灰度。惯导模块用的是MPU6050六轴I2C接口。这个选择比较常规价格便宜、资料多、社区支持好。但MPU6050的零偏稳定性一般需要定期校准他们在代码里加了一个自动零偏补偿的逻辑每次发车前静止两秒采集一千个样本取平均作为零偏值运行过程中如果检测到车静止超过一秒就重新校准一次。电磁采集用的是工字电感加运放调理电路四个电感分别朝向车头左前、右前、左后、右后。电感信号经过全波整流和低通滤波后送入ADC采样率设的是10千赫兹实际有效带宽大概在2千赫兹左右足够捕捉20千赫兹的电磁信号变化。2. 视觉识别模块的核心细节与实操要点2.1 图像预处理为什么不能省很多新手拿到摄像头数据后直接就开始找边线结果发现阈值稍微变一点识别结果就天差地别。问题出在图像预处理这一步被跳过了。Soberup的代码里从原始灰度图到边线提取之间有整整四步预处理去噪、畸变校正、动态阈值、边缘增强。去噪用的是3乘3的高斯核这个没什么好说的标准操作。畸变校正是重点MT9V034配的镜头有比较明显的桶形畸变图像边缘的直线在画面里是弯的。他们用棋盘格标定法测出了畸变系数然后在代码里做反向映射校正。这一步的计算量不小但H743的硬件浮点单元能扛住实测下来单帧校正耗时约2.3毫秒。动态阈值是视觉识别稳定的关键。固定阈值在光照均匀时能用但赛道上有阴影、有反光、有不同颜色的背景布固定阈值必然翻车。他们的做法是把图像分成16乘16的网格每个网格独立计算大津阈值然后用双线性插值生成每个像素的阈值。这样既能适应局部光照变化又不会因为网格边界产生突变。实测在光照差异30%的场景下动态阈值的识别准确率比固定阈值高40%以上。边缘增强用的是Sobel算子但只对水平方向做卷积因为赛道边线主要是垂直方向的。这个细节很关键——如果水平和垂直都做十字路口的横线会被增强反而干扰边线提取。只做水平方向垂直边线被强化水平横线被抑制后续的边线拟合会干净很多。2.2 边线提取的三种方案对比边线提取是视觉模块的核心Soberup在调试过程中试过三种方案每种都有各自的适用场景和坑。第一种是扫描线法。从图像底部往上每隔几行扫一次找每行里灰度跳变最剧烈的两个点作为左右边线。这个方案计算量最小实时性最好但在弯道处容易丢线——因为弯道时边线在图像里是斜的扫描线可能扫不到。他们的解决办法是动态调整扫描行的间距直道时稀疏弯道时密集但这样又引入了新的问题弯道时计算量激增帧率会掉。第二种是连通域法。先对图像做二值化然后找最大的白色连通域作为赛道区域连通域的左右边界就是边线。这个方案在直道和缓弯时很稳但在十字路口会出问题——十字路口的白色区域是连通的连通域法会把整个十字都当成赛道边线提取完全失效。他们后来加了一个十字判断逻辑如果连通域的宽度突然增大超过阈值就判定为十字暂停边线提取改用惯导维持方向。第三种是边缘检测加霍夫变换。先Canny边缘检测再用霍夫变换找直线。这个方案对弯道的适应性最好因为霍夫变换能拟合任意角度的直线。但计算量是三种里最大的单帧耗时约8毫秒在H743上跑30帧每秒已经很吃力了。他们最终只在弯道时启用霍夫变换直道时切回扫描线法用状态机来管理模式切换。最终上车的方案是扫描线法和连通域法的融合直道用扫描线弯道用连通域十字用惯导。这个融合逻辑写在了一个叫vision_fsm.c的文件里状态转移条件包括边线丢失计数、连通域宽度变化率、惯导角速度阈值等。2.3 元素识别的状态机设计智能车赛道上的元素就那么几种直道、弯道、十字、环岛、坡道、断路。但要在高速运动中准确识别并做出正确反应状态机的设计就很重要了。Soberup的状态机有七个状态直道巡航、入弯、弯中、出弯、十字通过、环岛绕行、异常恢复。每个状态都有明确的进入条件和退出条件条件参数包括边线曲率、边线丢失计数、惯导角速度、电磁偏差等。以环岛为例进入条件是连续三帧检测到右侧边线消失同时左侧边线曲率增大惯导角速度为正。进入环岛状态后视觉模块切换为只识别左侧边线右侧边线用惯导积分推算。绕行过程中如果检测到左侧边线也消失说明车已经过了环岛中心切换到出环状态此时视觉重新寻找右侧边线找到后回到直道巡航。这个状态机在调试时遇到的最大问题是误触发。有一次在直道上因为阳光从侧面照过来右侧边线在图像里突然变淡连续三帧低于阈值状态机误判为环岛车直接往左打方向冲出了赛道。后来他们加了一个电磁验证条件进入环岛状态前必须同时检测到电磁信号有对应的变化模式。这个双重验证把误触发率降到了几乎为零。3. 惯导与电磁模块的融合实现3.1 惯导姿态解算的实操细节MPU6050输出的是三轴加速度和三轴角速度要得到姿态角需要做传感器融合。Soberup用的是互补滤波而不是卡尔曼滤波。原因很实际互补滤波的参数少、调试直观、计算量小卡尔曼滤波虽然理论上更优但调参过程太耗时比赛准备期耗不起。互补滤波的核心公式是角度等于陀螺仪积分乘以高频权重加上加速度计解算角度乘以低频权重。权重系数选的是0.98和0.02这个比例意味着陀螺仪积分占主导加速度计只做缓慢修正。为什么这么选因为车在运动时加速度计会受到运动加速度的干扰解算出的角度噪声很大只能用来修正陀螺仪的长期漂移不能参与快速姿态估计。陀螺仪积分漂移的处理是另一个重点。MPU6050的零偏温漂大概在正负0.1度每秒每摄氏度从发车到完赛芯片温度可能升高10度累积漂移就是1度每秒跑十秒就是10度足够让车跑偏。他们的解决办法是每次发车前做一次零偏校准运行过程中如果检测到车静止超过0.5秒自动重新校准。这个逻辑写在了一个定时器中断里每毫秒检查一次。姿态角的输出频率是200赫兹通过DMA送到主控的共享内存。这里有个细节DMA传输完成中断的优先级要设得比控制中断低否则会出现姿态数据还没更新完控制中断就读取了半新半旧的数据导致控制抖动。3.2 电磁信号的调理与采样电磁模块的硬件部分包括四个工字电感、一个四通道运放、一个模拟开关和一个ADC。电感感应到的20千赫兹信号非常微弱直接送ADC根本采不到必须先放大。运放用的是OPA2350增益带宽积38兆赫兹在20千赫兹时增益可以做到100倍而不失真。放大后的信号是交流有正有负但ADC只能采正电压所以需要加一个直流偏置把信号抬到电源电压的一半。偏置电压的稳定性直接影响采样精度他们用的是TL431基准源温漂比电阻分压小一个数量级。采样策略上他们没有用峰值检测而是用了同步解调。具体做法是用单片机产生一个20千赫兹的方波和电磁信号做乘法然后低通滤波。这样得到的直流分量正比于电磁信号的幅度而且能抑制其他频率的干扰。同步解调的计算量比峰值检测大但抗干扰能力强很多实测在电机干扰下同步解调的噪声比峰值检测低20分贝。四个电感的采样是分时复用的模拟开关每250微秒切换一次通道ADC以10千赫兹的速率采样。这样每个电感每毫秒能采到2.5个点经过100毫秒的滑动平均后等效采样率虽然还是10千赫兹但噪声被压得很低。3.3 三源融合的权重分配策略视觉、惯导、电磁三个数据源各有优劣融合策略的核心是根据当前场景动态分配权重。Soberup的做法是维护一个置信度向量每个数据源有一个0到1的置信度值融合输出是三个数据源的加权平均。视觉置信度的计算依据包括边线丢失计数、图像平均梯度、动态阈值的方差。边线丢失越多置信度越低图像梯度越小说明画面越模糊置信度越低阈值方差越大说明光照越不均匀置信度越低。这三个指标加权求和后映射到0到1之间。惯导置信度的计算依据是陀螺仪零偏校准的时间间隔、加速度计的噪声方差、积分时间。校准间隔越长置信度越低噪声方差越大置信度越低积分时间越长漂移越大置信度越低。电磁置信度的计算依据是信号强度、信噪比、历史稳定性。信号太弱或太强都降低置信度信噪比低于阈值降低置信度历史波动大降低置信度。权重分配的逻辑是直道时视觉权重0.7、惯导0.2、电磁0.1弯道时视觉0.5、惯导0.4、电磁0.1十字时视觉0.2、惯导0.6、电磁0.2环岛时视觉0.4、惯导0.5、电磁0.1。这些权重值不是拍脑袋定的而是通过大量实车测试拟合出来的测试方法是在不同场景下分别记录三个数据源的输出和车的实际轨迹然后用最小二乘法拟合权重。4. 调试过程中踩过的坑与排查技巧4.1 视觉模块的典型问题速查视觉模块出问题的时候现象往往很直观——车突然往一边偏、在某个特定位置反复摆动、或者直接冲出赛道。但要从现象定位到根因需要一套系统的排查方法。下面这张表是Soberup在调试过程中整理的常见问题速查表我根据他们的记录和自己的经验做了一些补充现象可能原因排查方法解决方案直道行驶时车轻微摆动边线提取的噪声大打印边线方程的系数看是否高频抖动增大扫描线的行间距或对边线方程做低通滤波弯道入弯时反应迟钝状态机切换阈值太保守记录入弯时的边线曲率和切换延迟降低曲率阈值或提前预判入弯十字路口误判为弯道连通域宽度变化率阈值太低打印十字前后的连通域宽度提高宽度变化率阈值或加入电磁验证环岛绕行时压内圈惯导积分漂移导致角度估计偏大对比惯导角度和实际轨迹缩短零偏校准间隔或降低惯导权重强光下边线丢失动态阈值的网格太大可视化每个网格的阈值缩小网格尺寸或改用自适应窗口图像处理帧率不稳定霍夫变换计算量波动统计每帧的处理耗时限制霍夫变换的启用条件或降低分辨率这张表里最值得说的是“环岛绕行时压内圈”这个问题。他们当时调了整整三天一开始以为是视觉识别的问题反复优化边线提取算法效果都不明显。后来把惯导的角度输出和实际轨迹画在一起才发现是惯导积分漂移导致的——车在环岛里绕了五秒惯导角度累积漂移了将近15度车以为自己在走直线实际上已经偏了。解决办法很简单把零偏校准的静止检测阈值从1秒降到0.5秒同时在环岛状态下把惯导权重从0.5降到0.3问题就解决了。4.2 惯导模块的校准与维护惯导模块的坑主要集中在零偏校准上。MPU6050的零偏不是固定的每次上电都不一样而且随温度变化。Soberup的校准流程是这样的第一步上电后等待500毫秒让芯片内部稳压器稳定。第二步采集1000个样本采样间隔1毫秒计算均值和标准差。第三步如果标准差大于阈值他们设的是0.05度每秒说明车在晃动重新采集。第四步把均值写入零偏寄存器同时保存到Flash下次上电可以直接加载省去等待时间。运行过程中的动态校准也很重要。他们的做法是每100毫秒检查一次加速度计的模长如果接近重力加速度误差小于0.1g说明车处于静止或匀速状态可以重新校准零偏。这个逻辑在直道巡航时特别有用因为直道时车基本是匀速的可以频繁校准把漂移压到最低。还有一个容易被忽略的细节MPU6050的I2C通信速率。默认是100千赫兹读一次六轴数据需要大概1毫秒。如果主控的I2C中断优先级设得不对可能会被其他中断打断导致数据读取不完整。他们把I2C中断优先级设成了最高同时把DMA也配上让I2C传输不占用CPU时间。4.3 电磁模块的抗干扰实战电磁模块最大的敌人是电机干扰。智能车的电机是PWM驱动的PWM频率一般在10到20千赫兹和电磁信号的20千赫兹很接近很容易串扰。Soberup试过三种抗干扰方案第一种是硬件滤波在运放输出端加一个带通滤波器中心频率20千赫兹带宽2千赫兹。这个方案能把带外干扰压下去但对同频干扰无效。第二种是同步解调前面已经说过了用同频方波做乘法能抑制非同频干扰但对同频干扰还是没办法。第三种是软件滤波在ADC采样后做滑动平均窗口长度100个点等效带宽100赫兹。这个方案对随机噪声有效但对周期性干扰效果有限。最终他们用的是三种方案的组合硬件带通滤波加同步解调加软件滑动平均。实测在电机全速运行时电磁信号的噪声从原来的正负200毫伏降到了正负20毫伏信噪比提升了20分贝。还有一个细节电感的安装位置。他们最初把电感装在车头正前方结果发现电机电流产生的磁场在车头位置最强干扰最大。后来把电感移到了车头两侧离电机远了5厘米干扰就小了很多。这个5厘米的位移让电磁信号的基线噪声降低了将近一半。5. 开源目录的组织方式与复现指南5.1 目录结构是怎么设计的Soberup的开源目录不是简单地把所有文件扔进一个文件夹而是按照功能模块做了清晰的划分。根目录下有六个子目录hardware、firmware、vision、imu、electromagnetic、docs。hardware目录里是原理图和PCB文件用的是立创EDA格式因为这是国内队伍最常用的工具不需要额外安装软件就能打开。原理图按功能分成了四页电源、主控、视觉、电磁。每页都有详细的网络标签和注释关键参数比如电容容值、电阻精度都标在了旁边。firmware目录是主控的固件代码基于STM32CubeMX生成的HAL库工程。代码按模块分成了bsp、app、algorithm三层。bsp是板级支持包包括GPIO、UART、I2C、ADC、DMA的初始化app是应用层包括状态机、控制律、任务调度algorithm是算法层包括滤波、拟合、融合。这种分层的好处是如果你想移植到其他主控只需要改bsp层app和algorithm基本不用动。vision目录是视觉处理的独立工程可以单独编译运行方便在PC上调试。里面包含了图像预处理的每一步每个函数都有详细的注释和参数说明。他们还附了几张测试图片你可以直接用这些图片验证算法是否正确。imu和electromagnetic目录类似都是独立的算法工程配有测试数据和验证脚本。docs目录是文档包括调试笔记、参数记录、问题排查日志。这些文档不是事后补的而是调试过程中实时记录的所以里面有很多“当时以为是这样后来发现是那样”的原始记录读起来很有现场感。5.2 如何快速复现核心功能如果你想基于这份开源目录快速复现核心功能我建议按这个顺序来第一步先跑通视觉模块的离线测试。把vision目录里的工程编译一下用附带的测试图片跑一遍看看边线提取的结果是否和文档里描述的一致。这一步不需要任何硬件在PC上就能完成能帮你快速理解视觉算法的输入输出。第二步搭建最小硬件系统。只需要主控、摄像头、一个串口转USB模块。把firmware目录里的工程烧进去通过串口打印图像处理的中间结果。这一步的目的是验证硬件连接和基础驱动是否正常。第三步加入惯导模块。把MPU6050接到I2C总线上运行imu目录里的校准程序确认姿态角输出正常。然后修改主控代码把惯导数据接入融合模块。第四步加入电磁模块。这一步需要自己焊调理电路建议先用信号发生器模拟电磁信号验证ADC采样和同步解调是否正确再接实际电感。第五步整车联调。把三个模块的数据都接入融合模块在直道上低速跑一遍观察融合输出的轨迹是否平滑。然后逐步提高车速记录每个速度下的表现找到稳定运行的边界。这个顺序的核心逻辑是先离线后在线先单模块后多模块先低速后高速。每一步都有明确的验证标准通过了再进入下一步避免多个问题同时出现导致排查困难。5.3 参数整定的经验法则智能车调试最耗时的部分就是参数整定。Soberup在文档里记录了一些经验法则我觉得很有参考价值视觉阈值的整定不要追求单帧的最优要看连续多帧的稳定性。他们的做法是在赛道上选十个典型位置每个位置采集100帧图像统计边线提取的成功率。成功率低于95%的位置调整该区域的动态阈值参数直到所有位置的成功率都达标。惯导权重的整定从低到高逐步增加。初始权重设0.1跑一圈看轨迹是否平滑如果平滑增加到0.2再跑一圈直到出现明显的振荡或漂移然后回退到上一个稳定值。这个过程大概需要跑20到30圈。电磁阈值的整定要在电机全速运行时进行。因为电机静止和全速时的电磁噪声完全不同静止时调好的阈值全速时可能完全不能用。他们的做法是把车架在支架上电机全速空转然后调整电磁阈值直到信号稳定。控制参数的整定先调内环再调外环。内环是速度环外环是方向环。速度环的积分时间常数从大到小调方向环的比例系数从小到大调。每调一个参数跑三圈取平均避免单次运行的偶然性。这些经验法则看起来简单但都是实打实跑出来的。我在自己的调试中也验证过按这个流程走确实比盲目试参数效率高很多。6. 从21届到22届的技术演进思考6.1 哪些方案值得延续21届Soberup的三层感知架构在22届的比赛中被不少队伍借鉴。视觉加惯导加电磁的组合本质上是用不同物理原理的传感器互相补位这个思路在任何一届比赛中都适用。视觉提供绝对位置惯导提供高频姿态电磁提供兜底信号三者缺一不可。动态阈值的网格化处理也值得延续。光照变化是视觉方案永远的敌人固定阈值在实验室能用到了比赛现场必然翻车。网格化动态阈值虽然计算量大一点但换来的稳定性提升是值得的。状态机的设计思路同样值得延续。智能车的赛道元素是有限的用状态机来管理不同元素的处理逻辑比用一堆if-else堆在一起清晰得多。状态机的关键是状态转移条件的设定这个需要根据实车测试来调没有捷径。6.2 哪些地方可以改进21届的方案也有明显的不足。最大的问题是计算资源分配不均——视觉模块占了主控70%的算力惯导和电磁加起来才30%。这导致视觉模块的帧率上不去高速时控制指令的更新频率不够。22届可以考虑把视觉处理卸载到独立的协处理器上比如用K210或者OpenMV做图像预处理和边线提取主控只负责融合和控制。这样主控的算力可以全部用在控制律的计算上控制频率能从现在的200赫兹提到500赫兹甚至更高。另一个改进方向是惯导模块的升级。MPU6050的零偏稳定性一般如果换成BMI088或者ICM42688零偏温漂能小一个数量级积分漂移的问题会缓解很多。当然成本也会上去需要权衡。电磁模块的改进空间在于电感的布局。21届用的是四个电感只能测出电磁场的梯度方向测不出电磁场的高阶分布。如果增加到八个电感可以拟合出电磁场的二阶分布对赛道边界的判断会更准确。但八个电感的调理电路复杂度翻倍调试时间也会增加。6.3 给下一届队伍的建议如果你正在准备下一届智能车竞赛我有几个建议第一尽早开始调试。智能车的调试周期比想象中长得多视觉模块的阈值整定、惯导的零偏校准、电磁的抗干扰每一项都需要大量重复测试。提前两个月开始比提前两周开始从容得多。第二重视数据记录。Soberup的开源目录之所以有价值很大程度上是因为他们记录了完整的调试数据。每次跑车都记录关键参数和轨迹出了问题可以回溯调好了也知道为什么好。没有数据记录调试就是碰运气。第三不要迷信单一方案。视觉、惯导、电磁各有优劣融合才是出路。但融合的前提是每个单模块都足够可靠如果视觉本身就不稳定融合只会把问题放大。先把单模块调稳再考虑融合。第四留出冗余。比赛现场什么都有可能发生光照突变、电磁干扰、传感器故障。代码里要有异常检测和降级策略视觉丢了用惯导惯导漂了用电磁电磁也挂了至少还能低速完赛。完赛比拿名次重要这是很多老队伍的血泪教训。我在实际使用这份开源目录的过程中最大的体会是开源的价值不在于代码本身而在于它记录了一个团队解决问题的完整思路。你可以直接抄代码但更重要的是理解他们为什么这么写。每一行代码背后都有一次调试、一个坑、一个决策。把这些决策逻辑搞懂了你面对新问题时才能自己找到答案而不是到处找现成的代码。
阅读完成 · 觉得有帮助?
咨询建站