愿多年后想起智能车时,铺面而来的就是我的青春!
我们使用了双核主控的方案,在主核执行传感器信息融合、车模位姿推算、电机控制等任务,在从核单独执行运算量较大的图像处理任务。
用MT9V034摄像头可以获取比赛开始时A4 纸上任务点的坐标信息,并在车模运行时识别目标卡片相对于车身的位置,对车的坐标位置信息进行修正。使用ICM20948模块获取车模运行时yaw 轴的角速度,并与电机磁编码器所得四个车轮的转速进行融合,可以解算出车模在场地上的位姿信息。基于当前时刻的车模位姿信息和目标点的位置,可以求出对4个电机所应发布的速度指令,并 使用pwm经由电机驱动对电机转速进行控制。
使用OpenArt mini识别到卡片的种类后,控制机械臂将卡片抓取并搬运到指定位置,同时使用无线串口将识别结果发送至裁判系统。
此次比赛选用的赛车车模采用M型车模。赛车机械结构只使用竞赛提供车模的底盘部分及转向和驱动部分。整车由4个麦克纳姆轮进行驱动。
整车机械机构从前到后以此由电磁铁、机械臂﹑前置双电机驱动、弹射装置、后置双电机驱动、主控板、电池以及摄像头支架构成。
电磁铁采用的是逐飞科技直径2.5cm的电磁铁。机械臂由2个 RDS3218舵机和连接件组成,连接件以及前置舵机支架采用SLA光固化3D打印制作。前置部分的任务是拾取地面的卡片并将其精准投放到指定的收集框中。在此部分上有安装摄像头框架的孔位。
前置电机驱动由亚克力板打孔安装在车模侧边,亚克力支架板下,利用车模自有孔位安装电机以及编码器。
车模中间部分是弹射装置,使用3个四面盒和配套的转动轴以及弹簧,实现由电磁铁控制的释放操作。
车模尾部亚克力板搭载有后置电机驱动以及主控板。主控板和电机驱动板交错安装。主控板通过铜柱加高并且使用立方体螺母直立安装。电池固定在尾部的摄像头支架杆上,并于主板相连。
摄像头支架采用十字架形式。三个刚性约束使得摄像头尽可能不受震动的影响。
车模使用2块11.1v锂电池并联供电,并且直接连接在主板上,为满足使用需要,本车模中存在如下几种电压:
电池电压11.1v~12v。在电路系统的标识为+12。用来给控制模块和驱动板供电。+12电压连接到驱动板、开关及稳压电路,当开关按下时由稳压二极管驱动MOS管导通GND与电池负极,实现电路通电。此处MOS管采用2块LR7843。
主板阶段电压6v,通过TPS54531将12v降压到6v,给电磁铁以及其他控制电路供电。共有3路6v电压,另外两路分别给两个舵机供电。
直流5v电压,从第1路TPS54531产生的6v,经过TPS76850低压差稳压器降压到5v,给单片机等供电。
直流3.3v,从第1路tps54531产生的6v,经过TPS76833低压差稳压器降压到3.3v,给摄像头等供电。
信号部分,分配合适的端口之后采用端到端连接,详细的原理图和实物图如
我们使用M法测速,在周期为1ms的软件定时器中使用磁编码器这次的读数减去上次的读数,除以时间间隔再乘以与车模有关的比例系数,就可以获得车轮的实际转速。
我们使用一阶线性自抗扰控制(LADRC),通过调整输出到驱动板的pwm值来控制车轮的转速,使其能够快速达到并稳定在期望的转速。
同时,我们将四个车轮的实际转速按麦克纳姆轮逆运动学解算求得车模的xy方向速度和自转角速度,作为里程计数据存入本地FIFO 中,供后续使用。
我们结合RT-Thread 系统提供的信号量和邮箱机制,在IMU所产生的GPIO中断和串口接收中断中释放信号量或将数据发送到邮箱,在对应的接收线程里获取数据并进行处理,这样即使在对应的线程里需要用到较为耗时的运算或复杂的控制逻辑,也不会占用系统的中断资源导致卡死。
我们选用的IMU即 ICM20948可以设定采样周期,按周期采集数据并产生数
据有效的中断信号。线程在获取到接收信号量后可以使用SPI将角速度数据从IMU的FIFO取回,存入本地FIFO中,供后续使用。
我们开了多个串口接收线程,分别用于处理RT1064从核所传回的A4纸数据和基于目标卡片的位置修正数据,OpenArt 的图像分类数据,以及无线串口上位机的数据。
main 函数和Finsh控制台式RT-Thread 系统默认自带的线程。
在main函数中初始化了所有外设和线程后,直接使用一个死循环来周期性开关核心板上的LED灯,用于指示系统在正常运行。
我们没有对Finsh控制台进行修改,一般在调试时用它来打印线程运行时的信息。
主运算任务在一个死循环中采用RT-Thread 提供的线程延时接口来实现周期性执行。
每一轮运算时将里程计数据和 IMU数据从FIFO中取出,使用扩展卡尔曼滤波进行融合,可以得到车模的3轴绝对位置和速度,即位姿数据。
通过当前时刻的位姿数据和目标点的信息,以及事先设定参数,如3轴最大速度、最大加速度、向前演算时间,可以计算出当前时刻车模的期望3轴速度。利用麦克纳姆轮正运动学解算就可以求出4个轮子的期望转速。
我们使用优先级最低的线程来执行按键轮循、显示屏等用户交互相关的任务。在触发发车后,线程将阻塞地执行每个比赛任务,如路径规划、发布目标点等。具体的比赛任务逻辑将放在第六章进行说明。
find_rects函数是openmv库中的一个函数,可以在图片中寻找与背景有较大颜色差异的四边形。所用的算法实现为apriltag 算法中初步筛选四边形的算法,可以简单描述为:
将图像转化为灰度图,并对灰度图应用局部自适应二值化。
使用并查集求解二值化图中的连通域,并使用哈希表维护相邻连通域之间连续的边界点。
对于每一簇连续的边界上的点,先对它们的坐标绕重心进行极角排序,并去掉极角值相近且坐标重合的点。
尝试使用最小二乘法拟合四边形的边界。每次用连续的一些点拟合一条直线,得到这些点中间位置的拟合误差。找到拟合误差的一些极大值点,用4重循环尝试以这些极大值点为四边形的四个角点拟合四条直线,选择其中拟合误差最小的一组四个顶点作为这个四边形的拟合结果,并根据拟合误差的阈值、相邻边夹教大小等指标粗略筛选掉形状完全不符合要求的四边形。(Apriltag算法到此为止,下面的两步为Openmv中 find_rects 函数的实现)
对于有重合部分的四边形,随机选取其中一个删掉,即去重。
对于每一个结果中的四边形,计算它四条边上像素点位置的图像梯度之和,作为评价四边形拟合结果的标准,并删掉评价值小于设定阈值的四边形。
我们将find_rects 的算法移植到了RT1064从核上,并针对所需对函数进行了一定的修改。
在Apriltag原算法中,是先尝试对四边形内二维码数据进行解码拟合,过滤掉大量不合适的四边形后才进行的去重,而find_rects 的过滤步骤放在了去重步骤的后面,导致经常有由噪声产生的错误四边形没有被过滤掉,并由于去重的步骤是随机选取删除,导致本来正确的四边形结果被删掉,反而是错误的四边形被保留了下来。
我们去掉了函数的去重和计算梯度和的部分,保留所有的结果四边形,之后将所有得到的四边形逆透视变换到车身坐标系下,依据目标卡片的实际边长和4个直角筛选出唯一的正确结果。
在OpenArt mini上识别到四边形后,我们结合双三次插值法将所得到的四边形内的部分逆透视变换到原图的左上角,可以得到形式与所公布数据集完全相同的图片形式,因此可以直接对原数据集进行训练,而不需要进行实地拍摄或全角度随机旋转,只需要旋转90度的倍数即可,这样做识别的效果也十分精确。
RT1064 从核的任务是利用识别到的目标卡片的四边形推算出目标卡片相对于车身坐标系的位置,因此最终只需要获取卡片像素中心逆透视变换后的坐标即可。将这个结果发送到RT1064主核后,主核可以结合当前时刻车身位姿中的偏航角推算车身的准确坐标,从而对车身在地图坐标系下的坐标进行修正。
比赛任务逻辑放在了优先级最低的线程内,流程为:发车手按下初始化按键,将A4纸放在MT9V034摄像头前。
RT1064 从核识别完A4纸将结果传回RT1064主核,发车手按下确认按键,触发发车。
将目标点位间的距离存入邻接矩阵,求解搬运卡片的全局近似最短路径。按所求路径依次前往目标卡片的位置,并基于从核识别到的卡片坐标实时修正车身坐标。
每到一张卡片前停车后,通知OpenArt进行拍照,拍照完成后OpenArt通知主核使用机械臂将卡片拾取,在拾取的同时前往下一个目标点的位置。
OpenArt将所拍照片运行神经网络进行图像分类完成后,再将结果传回主核,主核在独立的线程将识别结果发送到裁判系统,并控制机械臂将卡片放入对应的卡槽。
当场地上所有卡片都拾取完成后,分别前往三条边上进行卡片放置,之后返回车库前的位置。
基于OpenArt 的find_blobs 函数识别场地边线,并进行入库。
下面将介绍求解搬运卡片的全局近似最短路径的算法和入库的方法。
比赛任务中,车模从车库触发,将所有卡片捡起并搬运到三条边线外后再返回车库的过程,可以建模为度量空间上的旅行商问题。唯一需要特殊处理的步骤是将卡片搬到三条边线外并返回车库的步骤。
设场地长宽分别为W ,H,我们将车库的位置(1,0)分别沿x =W和y =H两条边线对称到右上角的(2W ,2H +1),并将求出场地中所有卡片到这个点的连线。将连线对称回场地内后即是从某一个卡片出发,分别到三条边放置卡片再回到车库的最短路径。
为了保证旅行商问题求解算法所得到的路径是以这个构造出的车库对称点为终点的,我们又额外引入了一个辅助点,将这个点与起点车库和构造车库的距离设置为0,与所有卡片的距离设置成无穷大,这样所求出的路径必然是以这个点为终点的。
我们选择使用Christofides算法与3-opt算法结合求解旅行商问题。
Christofides 算法是一种复杂度较小且近似比优秀的旅行商问题近似求解算法,所求路径长度不会超过最优解的1.5倍。算法的流程大致可以描述为:
使用Prim算法求解输入图的最小生成树。
选取最小生成树中的奇点,为奇点的子图构造最小权匹配。
将最小权匹配的结果与最小生成树合并,使用Hierholzer 算法求出合并后的多重图中的一条欧拉回路。
去除欧拉回路中重复遍历的节点,得到的就是算法的输出。
其中计算一般图最小权匹配的步骤一般使用Blossom算法进行求解,但由于其复杂度较大,实现较为复杂,且我们后续使用了3-opt算法进行了进一步优化,因此我们改用了贪心算法仅求解了近似最小权匹配。
3-opt算法是一种简单的局部搜索算法,来一条初始的回路中使用三重循环遍历回路的边,并尝试通过重新连接三条边的六个端点的方式来让回路变得更短。我们以Christofides算法的输出作为初始回路,使用3-opt算法进行优化,取得了不错的效果。并且由于算法的复杂度较低,在具有23个路径点的情况下,计算的耗时不到1毫秒。
一个队伍中的三个人各自分工不同,但不代表我们不需要关注了解其他人的工作,软件和硬件是一个相互依存的关系,硬件是软件赖以工作的物质基础,软件的正常工作是硬件发挥作用的唯一途径,所以程序员了解硬件则能更好的发现程序上问题和对硬件的需求有哪些,帮助硬件负责人更好的工作。
我们将两年的青春都放在智能车上面,智能车不仅仅是我们的回忆,更承载着我们的梦想驶向远方。不管最后比赛成绩如何,我们做智能车的初心不会改变,我们对智能车的热爱不会改变,希望智能车越办越好,希望我们变得更强!
花费了我们很多精力,所以设置了付费,望谅解!