一. 前言

大家好,我们是来自东北大学秦皇岛分校的东秦人工智能一队。智能车竞赛的初心就是“以车会友,突破创新”,于是我们决定公开我们团队的技术方案,欢迎大家一起来交流学习。

首先我先说说我们团队的成绩吧,在区域赛线下赛中,我们的智能车以两轮总和4m53s的成绩拿下了满分1000分,此成绩在东西部所有队伍当中都排名第一位。目前经过赛后复盘和调试,我们的小车已经能稳定在1m40s左右完赛并满分,而且这还是没有更换过车道线模型或优化巡航程序后的成绩。我们也是购买的官方车模,所以对大部分队伍应该有比较大的参考价值。

下面我将从每个任务入手,介绍我们团队的设计思路。

在这里插入图片描述

二. 方案介绍

1. 巡线

巡线这里官方已经给了非常多了,无论是训练的代码还是预测的代码都一应俱全,但为什么这么多团队还是在比赛的时候巡线失败呢?对,就是模型的问题。对于我们团队而言,我们团队中没有计算机专业的同学,我们对于深度学习也没有非常深的了解,所以对于训练的代码和预测的代码我们都没有做什么太大的修改,我相信很多团队跟我们也是一样的情况,所以我们就要从数据集入手,来最大化的优化我们的模型。

1.1 遥控

数据集的好坏与操作手的遥控技术有直接的关系,尤其是在转弯的时候,一定要保证智能车完全丝滑。也就是说,当智能车进入弯道后,操作手切忌大幅度的调整转向角,可以在当前转向角的基础上做微调以保证智能车不出边线,绝对不可以转一下回到零位再转一下再回到零位的方式。

很多参赛队伍肯定也遇到了遥控智能车的过程中智能车不听使唤的情况,群里老师的建议是插一个容量大一点的U盘,我们比较懒没有用这种方法。我们在遥控器上加了一个暂停按键,当小车不听使唤的时候按下暂停按键,虽然小车并不会因此停下来,但是图片和数据不会再继续保存。并且我们后来扩大了sd卡的容量,不听使唤的现象也很少再出现了。

1.2 光线

我相信大家的智能车在自己的实验室跑的时候肯定是6的很的,那为什么到了比赛现场就失灵了呢?那就是环境变了,光线不同了。所以我们在采集的数据集就要加入不同光线下的数据,以增强模型的鲁棒性。并且我们自己写了更改文件夹中图片名和.json文件中键名的程序,这样不同时间时采集的数据集经过处理之后就可以融合到一个数据集里面,能够让我们的数据集越来越强大。

#批量修改文件夹中.jpg的文件名
import os
path = 'C:/Users/Administrator/Desktop/train1'
filelist = os.listdir(path)
i= 8300 #输入你想转换目标图片的启始数字,这个数字必须大于当前图片数量
#比如你采集的图片是0-3999,这里输入4000图片名就会变成4000-7999
for item in filelist:
        if item.endswith('.jpg'):
                name = str(int(item.split(".",3)[0]) + i)
                src = os.path.join(os.path.abspath(path),item)
                dst = os.path.join(os.path.abspath(path),name + '.jpg')
        try:
                os.rename(src,dst)
                print('rename from %s to %s'%(src,dst))

        except:
                continue
#批量修改.json文件中的键名
import json

new_json={}
new_start=8300 #输入你想转换的启始键名
#比如你的键名是从0-3999,输入4000键名就会变成4000-7999

with open("C:/Users/Administrator/Desktop/train1/result.json","r") as load_f:
    load_dict = json.load(load_f)
    

for i in range(len(load_dict)):
   new_json[str(new_start)]=load_dict[str(i)]
   print("new_json{}=".format(str(new_start)),new_json[str(new_start)])
   new_start+=1

with open("C:/Users/Administrator/Desktop/train1/1.json","w") as dump_f:
    json.dump(new_json,dump_f)

1.3 分段

分段是我们巡线方案中最重要的一个部分,为了提高模型的专一性,我们将整个赛道分成了三个部分,分别采集三段的数据集训练出三个模型,在做完某个任务后就更换车道线巡线模型,并且在每两个任务中间的巡线我们都设置了不同的Kx值,可以随时根据智能车的行驶情况来做出调整。

在这里插入图片描述


这样一来,当某一段车道线跑不好的时候,我们就单独采集这一段的数据集即可,而不必再把全图再跑一遍,大大节约了时间,并且还提高了巡线的质量。比如我们的车在180°弯道那里经常容易出去,于是我们单独采集了两万张那一段的数据集,当小车做完倒球任务后切换到这个模型,在做完最后一个举旗任务后再切换为第三段的模型,所以究竟把赛道分成几段大家可以根据情况自己调整。并且我们测试过切换车道线模型的时间花费仅为0.1-0.2秒之间,大家完全不用担心因为切换模型而耗费太多的时间。

2. 举旗

举旗我们在区域赛中也是采用的官方按顺序举旗并且现场换旗的方式,我们知道这个方法争议很大,但由于当时时间紧迫并且打印机出现问题从而无法修改那部分的机械结构。但是我们现在已经做了完善,我们已经能够通过摄像头的识别来举旗。为了能够最快速地举旗节省时间,我们采用了两个180°PWM舵机来实现。

这里提示一下大家,到最后一个举旗的时候,由于已经举过前面两个旗,所以最后一个旗不需要识别直接跑到位置举起来即可。

在这里插入图片描述

3. 打靶

这个任务也许是大家最关心的任务,可以说这个任务两极分化比较严重,做的好的一次也不会失误,做的差的也基本很难戳中靶心。讲道理规则中确定了靶心的高度确实降低了不少的难度,但对于能够准确识别并且戳中靶心的队伍来说无论靶心如何移动基本都能精准命中,无非是需要稍微修改一下机械结构。

3.1 调整车头方向

很多人可能发现当小车跑到打靶任务时,车头总是很难正对前方,也就是说笔和靶子并不是完全垂直的关系,这样就会导致笔戳到靶子上由于靶子向后倾斜从而划出一道线。

我们的解决方案是采用前向摄像头来调整车头角度。我们修改采集车道线模型的程序,令车头偏左时图片对应的值为-1,正对时对应值为0,偏右时对应值为1,组合成一个数据集后放到AI Studio上进行训练。在做打靶任务时切换前向摄像头的模型,设置一个上下限值。当模型预测返回的值小于下限时,车子向右转;当返回值大于上限值时,车子向左转。这样就实现了车头角度的调整。

3.2 靶心定位

大家可能发现当识别整个靶子的时候,矩形框并不能总是完美地框住整个靶子,这就会导致矩形框的中心并不总是在靶子的中心,这样做识别必然会导致不准确。

于是我们采用了二分类模型,即只有靶子圆心的红圈和背景两个类,这样做矩形框的中心点基本就在圆心附近,用这个中心点在摄像头视野中的位置,即可判断出圆心的位置。我们将摄像头置于笔的正上方,令摄像头视野中水平坐标范围为0-1,则当圆心的坐标处于0.5±0.01时,即可击靶;当圆心坐标小于0.49时,小车慢速前进;当圆心坐标大于0.51时,小车慢速后退。为了避免小车前进或者后退过量,每退一点就停一下,这样就出现了比赛的时候很多小车抖啊抖的现象(有一些大佬将圆心坐标和目标值之间的误差运算后作为小车前进和后退的时间也是不错的办法)。

3.3 距离控制

大家还有可能遇到智能车行驶到打靶任务时,车子离靶子距离非常远,导致即使将笔全部伸出去也没有办法击中靶子。受限于小车尺寸等各种各样的因素又没有办法把笔做的更长,这时控制小车和靶子之间得距离就非常重要了。

于是我们采用了超声测距传感器。有人可能会问,测量到哪里的距离呢?我这里给出两种方案,第一种是将超声测距传感器放置在笔的正上方,直接测量到靶子圆形面的距离;

第二种就是我们采用的这种,也是我偶然间发现,就是当我们在做倒球任务时,我们需要精准地把控小车到兵营的距离,但是兵营上全是孔,超声波很容易就从孔洞中穿过导致没有办法测量。突然我发现兵营的底座是实心,虽然有一些小孔,但是并不是特别深,于是我想能不能测量到底座的距离。我把超声波紧贴地面,发现无论超声波对着底座的哪个位置都能准确地返回距离值。

在这里插入图片描述

我突然想到靶子也有底座,不出所料,靶子的底座也是实心的,这就意味着我只需要用一个超声传感器就可以满足两个任务的测距。这样,我们通过3D打印,让超声传感器贴紧地面,即可测量小车到靶子的距离,然后通过距离控制小车的左右平移(这个只有使用麦克纳姆轮才能够实现)。至此,我们就可以实现精准打靶了。

在这里插入图片描述

4. 宿营

为了保证准确性,这里我们依然使用到了深度学习,也就是把地面上的帐篷也分为了一个类,当前向摄像头识别到地标同时侧面摄像头识别到帐篷后,使用麦轮平移进出即可。

5. 抓物块

这个我们跟大家一样,也是控制两个舵机进行抓取。只不过之前官方规则里说物块的位置和角度不定,于是我们设计了能够适应任何位置、任何角度的爪子,结果到了比赛前两天说物块就是平行放置,所以设计的爪子并没有能发挥出它的特长,有点小难受。

6. 倒球

这个任务是我们最头疼的一个任务,也就是唯一一个不敢保证满分的任务。我们采用的也是倒球的方式,但偶尔会有其中一个小球把另外一个小球挤出来,虽然概率比较低。我们本打算在国赛中采用扣球或者像北京科技大学的大佬一样让球垂直下落的方式,现在看来是没机会了。

具体的控制方案与打靶任务完全相同,也是分为调整车头方向、兵营定位、距离控制三部分,只不过兵营定位时的二分类选取的是营地边上的黄条,这里就不再赘述了。

在这里插入图片描述

三. 其他问题

1. 每次控制舵机之后无法读取到磁敏传感器或超声传感器的返回值怎么办?

答:这个问题我们也遇到了,通过打印串口返回值的时候发现,在控制舵机后读取串口值完全是紊乱的,等待一段时间才能恢复正常。于是我猜测是不是串口通信的通道堵塞了,经过实验后发现,在给串口发送数据前清空一下串口缓冲区即可解决问题。

在这里插入图片描述

2. 亮灯的时候,就算设置时间间隔为0,它也会按照1s的频率闪烁怎么办?

答:这个问题我们同样遇到了,在设置time.sleep(0)后,我发现小灯闪烁的频率正好是1.00秒,我感觉这个1.00肯定是人为设定的一个值,于是我顺藤摸瓜,在串口初始化那里发现有一个timeout=1,通过查阅资料后发现这个是读超时设置,把这个值设为0.1即可。

在这里插入图片描述

3. 控制另外一个PWM舵机时,前面的PWM舵机就送了怎么回事?

答:群里老师发的新的下位机固件应该能解决这个问题,但我们从来没刷新过下位机固件,我们通过更换舵机即可解决这个问题,达盛的舵机具备自锁的功能。
在这里插入图片描述

4. 运行完抓取任务后下位机发出“滴”的一声就退出程序了怎么回事?

答:这个问题发生在我们比赛的现场,甚至就在比赛前最后一次试车都一直存在这个问题。我们回来复盘后猜测可能是之前抓取物块时舵机堵转时间太长导致舵机损坏,从而造成回流,WOBOT为了保护自己从而退出程序执行。更换一个新的舵机即可解决。

四. 写在最后

这次比赛可以说是我一生中都难以忘怀的一次经历。在这次比赛之前,我参加数学建模竞赛推国一,最终掉为国二;参加ROBOCON差两名获得国一。我绩点不算突出,所以只能走创新特长生保研,而我们学校的推免政策是只有获得全国一等奖才能有机会参加最终评审,所以似乎运气总是与我差那么一点点。很幸运在去年12月份我加入了智能车百度组,但在得知比赛是在八月份举行的时候,我犹豫了。是的,这意味着这将是我最后一次机会,如果我未能获得全国一等奖,那么我只有四个月的时间准备考研,这显然是不切实际的。刚开始我母亲也不太支持我参加这个比赛,她认为这样做风险太大。我咨询了很多老师和学长的意见,他们都鼓励我把握住这一次机会,于是我成功说服了我爸妈,决定最后背水一战。

我们是五月份买车模之后正式开始备赛,因为我结课时间比较早,所以我几乎一个人完成了程序编写的所有工作,我知道我必须拼尽全力。比赛前的艰辛这里就不再多说了,我相信各参赛队伍肯定都不容易,这里我想说说我们在上海的那两天。

第一天比赛说实话并没有遇到特别大的困难,虽然有一个模型在现场并不能很好的适应,但并没有造成特别大的影响。于是第一天稳稳的拿下500分,想着第二天再拿这套代码跑一遍即可满载而归。到了第二天,我们早上七点钟就到达了比赛现场开始调试。可怕的事情发生了,我们的小车一直发生各种意外,不是姿态调整失败,就是小球没倒进去,一直没有办法顺利满分跑下来。然而这还不是最可怕的,最可怕的是到了八点多的样子,我们小车每次在做完抓取任务后都会自动退出程序然后停在原地,也就是出现上面的第四个问题。那时候谁也没想到会是舵机的问题,我们一遍又一遍地检查代码,一遍又一遍地跑,但每次到那里还是一样的结果,直到最后都没能成功跑下来。那两个小时是我人生中最恐惧的两个小时,我那时候就觉得我这三个月的努力可能就要付之一炬了。但那时候我的队友一直在鼓励我,在我想要放弃的时候。于是我们决定最后复盘一遍代码,降低了那一段车道线的速度,还修改了180°弯道的模型,把车上USB接口新贴的电工胶摘了下来,说实话我们也不知道到底有没有用。那时候要封车了,我们也没有机会试一次这个改动后的代码,那时候只能把一切交给天意。

结果大家肯定也知道了,我们成功了,当车完赛的那一刻,我喜极而泣,我根本无法用言语形容我当时的心情。我只能感谢上天,感谢幸运终于眷顾了我一次。在赛后我们在现场又跑了几次,之前的问题又再次出现,也就是说,在比赛当天的三个小时过程中,我们就成功了比赛的那一次。运气这种东西,真的不服都不行。在这里特别感谢一下我的队友,在我几近崩溃的时候给予我支持和信任。

五. 题外话

在前几天卓晴老师发的公众号上,看到了有自制车模的队伍对购买车模的队伍提出了质疑和不满,在这里我想说说我的看法。

首先我想对自制车模的队伍表达我的尊敬,在大多数队伍购买车模的前提下,你们还能沉下心来制作车模,这一点确实值得我们尊敬。但是你要是说我们购买车模的队伍唯奖是图,拿奖是理所当然的,这个我实在不敢苟同。我们购买车模拿到手的并不是一个完整的车模,而是一堆积木零部件,甚至官方车模用到的某些零部件套件里都没有,所以究竟如何搭建自己的小车,每个队伍都有不同的方案。于我们队伍而言,我们的小车除了底盘和打靶机构,其他机械结构都做了非常大的改动,相信看了我文章的同学都会感受得到。而对于官方提供的代码程序,微信群里都有开源的核心代码,每个同学都可以自由下载。究竟如何使用这些资源,这就需要每个队伍自己钻研和探索。