智能车竞赛的单车定向组,这几年在圈里热度一直不低。尤其是全国大学生智能车竞赛把单车组的任务从单一的直线竞速扩展为"直线+八字慢速"组合后,乍看是增加了难度,实际上更考验一套系统在两个极端工况下的平衡能力。我见过不少队伍把直线调得飞快,一到八字场地就开始画龙,也见过八字绕得很稳但直线被对手甩开一两秒的车。说白了,这个组别比的不是某一项能力,而是你对自己那台车的理解程度。
如果你正准备参加第二十一届智能车竞赛的单车定向组,或者已经在备赛路上被直立平衡和转向控制折磨得头疼,这篇文章应该能给你一些真正可落地的经验。我下面要讲的内容,不是从规则文档里复制出来的条条框框,而是基于实际调车过程中的整套方法论:从硬件选型、机械调校,到直立环、速度环、方向环的配合逻辑,再到直线竞速和八字慢速两套控制策略怎么在一辆车上切换共存。篇幅会比较长,但每一段基本都是从实践中磨出来的。
1. 先搞清楚比赛在比什么:单车组的物理本质与赛道逻辑
1.1 单车不是"骑单车",是控制一个不稳定的倒立摆
很多人第一次接触单车组会有个误解,以为"单车定向"就是让车像人骑车一样,有两个轮子但能保持平衡往前走。实际上竞赛里的单车组,车轮接地点形成的支撑面非常窄,车体在横向上(roll方向)天然不稳定,跑起来就像一个人体倒立摆在往前移动。这个物理本质决定了:你所有算法的起点,都不是先追求速度,而是先让这辆车"立得住、不往两边倒"。
从控制角度看,这是一个典型的欠驱动系统。执行器就是后轮电机,转向靠前轮的舵机或者步进电机,但车体横向平衡的控制力来自于后轮的滚动加减速——加速时车体有向后倒的趋势补偿,减速时车体有向前倒的趋势补偿。这个耦合关系非常有意思:你越想把车控稳,越不能只盯着平衡环,得让速度环、方向环和直立环形成统一的整体。
直线竞速和八字慢速这两个任务,恰恰是对同一套物理系统的两种极端考验:
- 直线竞速要求车体在高速下维持平衡,此时车体的陀螺仪角速度变化剧烈,车轮打滑、机械共振、传感器延迟都会被速度放大。
- 八字慢速要求车体在小半径连续转向中稳定绕行,不是简单跑慢就行,因为低速下直立环的修正力矩也相应变小,反而更容易侧倒。
所以备赛的第一原则不是"分别练两套代码",而是先深刻理解你的车在高速和低速下分别是什么状态,再决定控制策略怎么调整。
1.2 规则里没写透的几个关键限制
每个赛季规则细节会有调整,但有几条是单车组一直以来的共性约束,备赛时必须提前注意:
- 传感器数量限制:单车定向组通常不允许使用太多传感器,一般以摄像头为主要的赛道感知手段,配合编码器、陀螺仪/加速度计完成状态估计。这意味着你没法像完全体无人车那样依赖激光雷达,必须把有限的传感器信息用到位。
- 车模机械结构限制:车模需要自制或基于指定车模改造,但轮径、轴距、转向结构有限制范围。很多队伍在机械上压榨极限,但过度改装往往会带来新的不稳定因素。
- 场地环境不确定:比赛现场的光线、地面摩擦系数、地毯纹理甚至观众席的反光都会影响摄像头的识别效果。这个我在后面单独讲,是新手最容易翻车的地方。
把这些限制记在脑子里之后,你再看网上那些开源方案,就不会盲目照抄了。开源代码可以给你起点,但到了赛场上,决定上限的一定是你对自己车体特性的掌握深度。
2. 硬件选型与机械调校:直线冲得住、八字绕得稳的全在前期准备
2.1 摄像头、陀螺仪和编码器怎么搭配
单车组的核心传感器就三个:摄像头负责"看路",陀螺仪/加速度计负责"感知姿态",编码器负责"知道速度"。
摄像头的选择一直是争论焦点。近几年规则允许使用带一定处理能力的摄像头模块(比如总钻风、沁恒等方案),也有队伍直接用OpenMV或者带MCU的摄像头模组做初步处理。我的建议是别盲目追求分辨率,帧率比分辨率重要得多。单车高速直线时,车体状态变化极快,如果摄像头只有30帧,那在高速下每帧之间车已经跑出去十几厘米,留给控制系统的反应时间完全不够。备赛时优先选能稳定跑60帧以上、且曝光可调的摄像头方案。分辨率一般80x60到160x120就够用,关键是图像处理的实时性。
陀螺仪/加速度计建议用MPU6050或更新一点的六轴模块,这个是主流选择。注意两个点:一是安装位置要尽量靠近车体中心,二是务必做零偏校准。很多车的平衡问题不是算法不行,而是陀螺仪数据在开机后直接拿来用,零偏没校准导致直立环有一个恒定的偏置误差——车会莫名其妙地往一个方向倾斜。这个坑我在现场帮别人调车时见过太多次了。
编码器装在电机尾部,用来测后轮转速。低速八字绕圈时,速度反馈的精度直接决定了你能否稳定维持某一个低速目标。推荐用带有减速比编码器的电机,分辨率高一些,低速下的速度环控制会更细腻。
2.2 电机、驱动与电池的搭配逻辑
电机方案基本就是带霍尔编码器的直流减速电机(比如常见的GA25、MG513等),或者无刷电机方案。直流减速电机便宜、好驱动、控制简单,适合绝大多数队伍;无刷电机功率密度高,但驱动逻辑复杂,如果车队没有很有经验的成员,不建议备赛初期就上无刷。
驱动这块要注意电流余量。直线竞速时电机瞬时电流可能很大,驱动模块选太小的容易过热保护,比赛时车突然失去动力,那真是欲哭无泪。建议驱动芯片至少留出2倍额定电流的余量,并加散热片。
电池一般是7.4V两节锂电池或11.1V三节锂电池。这里有个人实践中的建议:直线竞速和八字慢速尽量用两个不同电压/电量状态的电池做测试。因为电池放电曲线的不同会导致同样的PWM输出实际车速不一样,直立环和速度环参数也会随之漂移。赛前要做的不是只测满电状态,而是测70%电量、50%电量下的车体表现,提前知道系统什么时候会开始力不从心。
2.3 机械调校:重心、轴距、轮胎才是容易被忽略的大头
很多队伍把精力全放在代码上,机械结构差不多能跑就开始调参,这是大忌。单车组的机械调校基本决定了你的控制算法上限能到多少。以下几项是我反复调整后的心得:
重心高度:直线竞速时重心低一些,车体抗侧倾能力强,但重心太低会让八字绕圈时的转向响应变钝;重心太高则直线容易"发飘"。实际调整手段是电池的安装位置——电池是车上最重的大件,把它压低、居中安装,是性价比最高的稳定方案。
轴距和轮距:轴距越长,直线稳定性越好,但转弯半径变大,八字慢速时的操控性变差。所以这里是直线和八字的第一处直接矛盾。不要总想找一个"通吃"的轴距,而是先找到规则允许范围内的中间值,然后靠控制策略去适应这个机械设定。
轮胎与地面:八字场地通常是短毛地毯,直线冲刺可能区域摩擦条件略有不同。轮胎选硬一点还是软一点,直接影响抓地力。软胎抓地好但磨损快、高速时发热后特性变化明显;硬胎高速表现稳定但八字低速时容易打滑。我的个人选择是用中等硬度的橡胶胎,并且在赛前用酒精清洁胎面,去除脱模剂残留和灰尘,这一点很不起眼但对成绩影响很大。
3. 底层控制逻辑:直立环、速度环、方向环如何协同工作
3.1 直立环:让车先学会站住
直立环是单车组所有控制的基础,它本质上是一个PD控制环。输入是车体横向倾角(由陀螺仪积分加加速度计融合得到)和倾角角速度(陀螺仪直接测量),输出是电机PWM的修正量。让车保持平衡的核心逻辑是:车往哪边倒,就让车轮往哪个方向加速,利用惯性把车体"扶"回来。
调直立环的顺序有讲究。先把P项从小到大慢慢加,你会看到车体开始有"抗拒倾倒"的反应,从一个方向歪倒变成左右来回小幅震荡。接着加D项,震荡会逐渐收敛。注意D项过大的典型现象是车体高频抖动、电机发出尖锐的嗡嗡声,这时候要把D项往回退。
一个关键经验:纯PD直立环只能在车体倾角较小的时候维持平衡,一旦倾斜超过某个范围就救不回来了。所以实际赛道上,车需要的是"动态平衡",即车体始终在一个小角度范围附近微调,而不是等大倾角出现再修正。这就要求后续的速度环和方向环不能让直立环"措手不及"——比如速度突变或方向猛打时,必须限制变化率,给直立环留出调整空间。
3.2 速度环:直线要稳、八字要精
速度环的作用是让车按期望速度行驶,同时在这个过程中协助维持平衡。它的实现方式一般是级联在直立环外层的PI控制环:把编码器测得的实际速度与目标速度做差,通过PI计算出一个角度修正量,叠加到直立环的目标倾角上。
这里有一个很多新手理解不透的点:速度环不是独立地"控制速度",它是通过改变车体的目标倾斜角度来间接调速的。比如想让车加速,就让车体前倾一点,直立环为了让车不倒必然会加速向前;想让车减速,就让车体后仰一点。所以速度环的PI参数本质上是在决定"车体倾斜程度和速度误差之间建立什么样的映射关系"。
直线竞速时,速度环只需要一个简单的目标速度,重点是上限速度下不发生过大超调。八字慢速时,速度环不仅要有更小的目标速度值,还要对速度波动的容忍度更低——因为速度不稳,车体倾角就会抖动,进而导致转向轨迹变形。
我实践中习惯在速度环输出端加一个低通滤波,避免直线上速度的微小抖动用太大的力度去修正,反而引起车体振荡。滤波时间常数大概选5~20ms,具体看编码器采样频率。
3.3 方向环:从"看到线"到"走在想要的路径上"
方向控制的输入是摄像头识别到的赛道信息,输出是舵机或前轮转向角。基础做法是计算赛道中线的偏差,然后用PD控制让车头对准目标方向。
但单车组的方向控制有个特殊性:转向不仅改变行驶方向,还会产生侧向力,而这个侧向力会干扰车体的侧向平衡。所以在八字慢速中,你会发现方向环P值稍微大一点,车就开始在弯道中摇摆;而直线高速时,方向环如果响应太慢,车又会直直冲出赛道。
我的建议是方向环参数不要一次性定死,而是做成按车速和场景动态调整的形式。低速八字时,方向环P可以大一些,让车头快速跟随中线;高速直线时,方向环P适当降低,避免过激转向破坏平衡。这个"变参数"思路会在后面第5节详细展开。
4. 图像处理与赛道识别:直线和八字场景下的预处理差异
4.1 摄像头视角与ROI设计
摄像头的安装角度决定了图像处理的上限。装得太平,近处看得清但远处信息少,高速直线时来不及反应;装得太俯视,远处赛道丢失,八字连续弯道时容易冲出弯心。我的经验是把摄像头略微上仰,让画面下边缘刚好看到车头前方10~20cm的赛道,上边缘看到车前方80~120cm的信息。这样近处信息用于精确居中,远处信息用于预判弯道。
ROI(感兴趣区域)设计上,尽量不要整幅图像处理,太耗时。把图像的下半部分作为主处理区域,进行二值化后提取赛道边界。ROI的高度在不同场景下应该有调整:直线时ROI可以拉高一些,利用远场信息提前发现赛道走向;八字时ROI压低一些,只关注近距离的赛道,避免弯道中远场信息太乱干扰判断。
4.2 直线场景:远场前瞻与丢线处理
直线竞速时,车通常处在赛道中段,前方就是一条笔直的通道。此时图像处理的重点不是精确找线,而是快速确认"前方没有障碍、没有大弯",然后放心让速度环全速冲。我习惯在这种状态判断中做一个简单分类:如果前方80cm范围内左右边界都是笔直且基本平行的,就判定为直线场景,方向环保持当前输出,控制核心放心交给速度与直立环。
直线场景最怕的是"丢线"——摄像头视野内只看到一侧边界,甚至两侧都看不到。这可能是车体倾斜太大导致视角偏移,也可能是前方出现了急弯。丢线处理的核心是别慌,不要用上一次的偏差值强行加到极致。我的做法是设置一个丢线计数,持续丢线超过N帧(比如5帧)才认为前方确实是急弯,否则维持上一次的有效方向值并降低速度。
4.3 八字场景:连续弯道的边界拟合与目标路径
八字绕圈的本质是连续地走两个方向相反的圆弧。在这个场景下,图像里的赛道边界往往是斜线和曲线,简单的"中线偏差+PD"很容易导致转向滞后,表现为车总是走外圈,或者进弯时切弯太狠开始画龙。
更好的办法是做边界拟合:把图像中左右边界的点集用直线或二次曲线拟合,然后根据拟合结果计算目标行驶线。对于八字这种连续弯道,可以算一个虚拟的"目标弧线",让方向环跟踪这条弧线而不是单纯跟踪中线。
提取左右边界之后,计算中线的平均位置,但不要直接用这个平均值作为目标。我通常的处理是:识别弯道方向(左弯还是右弯),在进入弯道时把目标线预设得更靠近弯心一点,出弯时再逐渐回到赛道中心。这样转向动作更平滑,车的横向平衡受到的扰动也更小。这就是很多队伍说的"切弯"策略。
4.4 曝光与光照:早上调好的参数,下午就废了
这是比赛现场最典型的问题。室内场地的灯光在上午和下午、晴天和阴天都有明显差异,如果图像二值化阈值是写死的,那大概率会翻车。我的解决方法分三层:
第一层是自动曝光/自动白平衡。如果摄像头模组支持,把曝光模式设置为自动,并且限制最大曝光时间,避免运动模糊。
第二层是动态二值化。在采集到图像后,先统计整幅图像的灰度直方图,根据灰度分布自适应计算分割阈值,而不是用固定值。这个计算量不大,但对环境光线变化的抗性提升非常明显。
第三层是颜色空间选择。如果场地是蓝色赛道配白色边界,可以考虑在HSL空间里用色相H来分割,这样对亮度变化更鲁棒。我在备赛时用的是灰度图+动态阈值,到比赛现场临时改为HSL空间下的色相分割,效果立竿见影。
5. 控制策略切换:一套代码同时吃下直线和八字
5.1 任务状态机与模式切换逻辑
一辆车要同时完成直线竞速和八字慢速,最简单粗暴的做法是准备两套代码,跑之前手动切换。但这在实际比赛中有风险——万一裁判临时调整发车顺序,或者你有两台车分别需要跑不同任务,手动切换很容易出错。
更好的设计是在代码里做一个轻量的任务状态机。根据摄像头识别到的赛道特征自动判断当前处于直线段还是八字弯道区,然后切换对应的控制参数组。我实际使用的状态划分如下:
- 状态A(直线冲刺):前方赛道边界近似平行且连续,无急弯特征,目标速度设为高速值(比如3~4m/s,具体看车体能力)。
- 状态B(八字慢速):前方左右边界弯曲程度大或开始出现交叉特征,目标停车速降到低速值(1~1.5m/s),方向环参数切换到高响应模式。
- 状态C(恢复过渡):刚从八字弯道出来进入直线段,速度从低速逐渐爬升到高速,避免急加速导致平衡失效。
状态切换之间还要设置滞回区间,防止在直线和弯道交界处频繁切换导致速度剧烈波动。打个比方,不要在前方边界弯曲程度刚好到达阈值时就立刻切换,而是让"进入弯道"的判定阈值比"离开弯道"更灵敏一些,这样状态切换才有缓冲。
5.2 速度规划:怎么从直线高速平滑落到八字低速
直线冲完紧接着就要进入八字,速度从几十km/h瞬间降到几km/h,如果直接阶跃式降速,车体惯性会让车猛地前倾,直立环根本反应不过来。所以必须做一个速度斜坡规划。
我的实现是在判定即将进入八字区域时,就开始按一个预设的减速度递减目标速度。减速度的选择要让车体在减速过程中仍能维持较小倾角变化,通常通过实验反复标定。我调试时发现比较合适的减速度大约在1.5~2.5m/s²之间,具体值取决于车体重量和机械结构。
同样,八字绕完进入直线阶段,加速也要平滑。不过加速过程相对容易一些,因为直立环本身对加速度有天然补偿——车体前倾就自动加速,只要限制目标速度的爬升速率即可。
5.3 PID参数分时切换的平滑处理
如果你在模式切换时直接把PID参数从一组换成另一组,控制器输出会有一个跳变,这个跳变轻则让车抖一下,重则直接失衡。解决方法是参数插值:在切换过程中,按控制周期逐步把参数从旧值插值到新值,插值时间一般在100~300ms。
具体的做法是维护一个"当前生效参数"结构体,在状态切换时记录旧参数和目标参数,然后在多个控制周期内按线性或S形曲线逼近目标值。这样整个切换过程是平滑的,车的动作不会出现突兀的转折。
另一个容易被忽视的点是积分项的处理。速度环和直立环的积分项在参数切换时如果不做处理,累计值会延续到新模式里,可能造成瞬时的过冲。我的习惯是在状态切换瞬间把速度环的积分项清零,或者乘以一个衰减系数,让新状态从零开始累积。
6. 调参实战与典型问题排查:从原地转圈到高速过弯
6.1 先调直立,再调速度,最后调方向
调参顺序千万别乱。我见过太多队伍上来就希望车能绕着八字跑,实际连直立都还没完全站稳。正确的顺序是三步走:
第一步调直立环:把车拿在手里,启动控制,感受车体是否有回正力矩。逐步加大P,直到车能短时间直立(2~3秒),然后加D消除震荡,最终目标是车能原地站立5秒以上不借助外力不倒下。
第二步调速度环:设定一个较低的期望速度(比如0.5m/s),让车轻轻往前推着走。观察速度响应是否平缓、是否有来回震荡。慢慢提高期望速度,直到直线上能稳定巡航。
第三步调方向环:先让车走直线,观察是否跑偏;再放到大半径弯道试试;最后才上八字连续弯道。每换一个场景,方向环参数单独调。
这个顺序背后是依赖关系:速度环依赖直立环提供的稳定基准,方向环依赖速度环带来的可预测运动。跳过任何一步都会让问题变得难以定位。
6.2 八字绕圈时的"外抛"和"切内"现象
八字跑不好的典型表现有两种:一是车总是往外侧甩,过弯半径明显比赛道大;二是车进弯时猛切向内,出弯时又猛打向外,轨迹像锯齿一样。
外抛的根源一般是方向环的P太小或摄像头前瞻太短。车看到弯道时已经离弯心很近了,转向来不及。解决方法是增大方向环P值,并适当增大远场ROI的权重,让车提前看到弯道。如果这两种操作都做了还是外抛,检查一下速度是不是太快——八字慢速场景中速度一旦超过机械抓地力极限,再调控制参数也没用。
切内则是方向环P太大或者D太小,导致车头过度转向,进弯时前轮转向角度过大,车体被侧向力推出去。解决方法是适当降低方向环P、增大方向环D,或者在前轮转向输出上加一个限幅,限制舵机转角的最大变化率。
我之前在调八字时遇到一个很诡异的问题:左弯很顺,右弯总是外抛。检查大半天,最后发现是摄像头安装位置在车体稍微偏右了一点点,导致视野中心与车体中心不对齐,左右弯看到的赛道偏差不对称。所以调方向环之前,务必先校准摄像头的物理对中性——把车放在赛道正中,软件读取的中线偏差应该接近零。
6.3 直线冲线时的抖动与侧滑
直线高速常见的问题是车体高频颤抖或者明显的侧向滑动。高频颤抖十有八九是直立环D项过大,或者是陀螺仪数据噪声大且没有滤波。可以在代码里对陀螺仪角速度做一阶低通滤波,截止频率大概50~100Hz,能有效减少高频噪声,但要注意延迟也会略微增加,所以时间常数要折中。
侧滑的征兆是车虽然保持直立但行驶方向开始偏移,轮胎发出轻微的"吱吱"声。这说明速度已经接近轮胎抓地极限,或者前轮转向角有一些微小的偏置——很多车的舵机中位并没有精准校准,导致车实际有一个很小的恒定转向。直线高速时这个微小转向会被放大成明显的侧滑。所以每次赛前都要重新校准舵机中位,跑直线时如果车往一侧偏,先别急着调PID,先确认舵机中位是否真的准。
6.4 比赛现场的突发情况处理
现场翻车最典型的几个场景:
电池电压不足导致车速明显变慢。如果测试时用的是满电电池,比赛时换了块旧电池,同样的PWM输出车速完全不一样。所以赛前一定要用比赛当天的电池多跑几轮,记录不同电压下的表现。如果车在比赛后半段明显变慢,可以考虑在速度环里加入"电压补偿"——根据当前电池电压动态调整油门上限。
场地灯光在摄像头里产生反光或阴影。如果你用的是灰度图+固定阈值,几乎一定会出问题。稳妥起见,提前到比赛场地测试光线,并且用前面说的动态二值化方案。
地毯拼接缝导致赛道图像断裂。很多比赛场地是用拼接地毯铺的,两条地毯之间的缝隙在图像里会被识别成一条黑色边界,干扰找线。可以在图像处理里加一个简单的宽度滤波:如果某个方向的连续黑线宽度明显小于赛道边界,就把它忽略掉。
7. 备赛节奏与团队协作:一份可复用的时间线
7.1 五个月备赛周期怎么分配
如果你是从零开始准备,建议至少给自己留五个月。我习惯按下面这个节奏来:
- 第1~2月:机械组装、硬件调试、基础代码框架搭建。此阶段目标是让车能跑起来,哪怕只是歪歪扭扭直行。同时把开发环境、代码版本管理、日志系统搭好——这些前期工作越牢固,后面调参效率越高。
- 第3月:完成直立环、速度环、方向环三代控制的基本调通,能在简单赛道上完整跑一圈。开始引入摄像头图像处理,完成基本的找线和中线提取。
- 第4月:优化直线速度上限,开始调八字慢速。可以搭建一个简易的八字场地每天反复跑。此时要建立系统的调参日志,记录每次改动和对应的效果。
- 第5月:模拟比赛流程,进行完整的两轮任务测试。重点测试状态切换的可靠性、电池续航下的稳定性、现场光线的适应性。最后两周不要再大改代码,只做参数微调。
7.2 开源方案怎么用:抄框架,别抄参数
现在网上能找到不少开源的单车组方案,包括缩微光电开源的工程文件、各学校车队的技术报告。这些开源内容价值很高,尤其是对新手来说,能省去大量从零摸索的时间。但要注意几点:
开源代码的PID参数、图像阈值、滤波系数,几乎都和你自己的车体机械特性绑定,直接抄过来大概率是不能直接用的。所以正确的用法是:把开源方案当成框架参考,理解它的程序结构、控制流程和思路,然后基于自己的硬件平台重新标定每一个参数。这个过程没有捷径,但恰恰是提升最快的时候。
另外,看开源代码时重点看它的状态切换逻辑、异常处理、调试输出这些工程化细节,而不是只看"用了什么算法"。算法大家都会说,差的是把算法在真实系统上跑稳的工程能力。
7.3 调参日志:让每一次改动都有据可查
这个习惯我强烈建议所有队伍养成。调车时的每改动一个参数,都应该记录:改动前的表现、改动后参数值、改动后的表现、当时的电池电量、场地状态、光照情况。不要觉得这很麻烦,等你调了一周发现车变慢了,回头翻日志才发现是一周前某个参数的微小改动造成的连锁反应,你会庆幸自己有日志。
日志不复杂,一个Excel表格或者Markdown文档就行,关键是坚持记。另外建议在代码里加一个"调试模式",可以在运行时通过按键或蓝牙切换显示当前的PID输出、车体倾角、目标速度、状态机状态等信息。这在现场排错时简直救命——很多问题你只看车跑根本想不到原因,但把状态数值打印出来一眼就能锁定。
写在最后的一些个人体会
回看这一路备赛,单车定向组最难的地方真心不是某一个算法,而是所有环节互相纠缠:机械上一个毫米的偏差,到高速直线上会被放大成一次侧滑;图像处理一个小失误,到八字弯道里就是整圈出界;代码里一个参数切换没做平滑,赛场上就是车突然失控。备赛的过程,很大程度上就是反复地"发现问题、定位原因、修复验证"的循环,而支撑这个循环高效运转的,是你对系统整体的理解深度和那些不起眼的工程习惯。
如果你正准备参加新一届的竞赛,我给的最实际的建议只有两条:一是尽早开始,每个赛季都有队伍因为时间不够而在最后关头被迫放弃大的改进计划;二是重视每一次失败,车跑崩了不可怕,真正可怕的是不去追究为什么崩、下次照样崩。祝你们调车顺利,赛场上见分晓。