锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

智能车竞赛技术报告 | 智能车视觉 - 温州大学- 春华秋实

时间:2022-08-30 06:00:00 600v2000uf折机电容传感器线色白色系列拉线传感器v2000传感器

简 介: 近年来,华为、特斯拉、谷歌、百度等大型互联网公司都在研究自动驾驶的话题。本文设计了基于恩智浦 RT1064芯片智能汽车 keil以开发环境为基础,利用环境 MT9V03X总钻风数字摄像头用作道路识别的传感器 S依靠3010转向舵控制汽车转向,依靠 RS380大电机和编码器构成闭环电路,控制小车速度。汽车模型使用摄像头收集轨道数据,根据差异和图像灰度跳点是轨道边缘,计算轨道中线,然后控制舵转向前进,同时使用 OpenArt mini摄像用于识别靶标图像,并使用它 RT-Thread创新使用操作系统,充分发挥芯片性能,提高车模完成任务的成功率。该操作系统功能强大,操作方便,学习方便,在提高车模性能和开发车模软件方面发挥了突出作用。

关键词 汽车图像识别电磁PIDRT-Thread

学校:温州大学温州大学
队伍名称:春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实春秋实
参赛队员:陈俊达 程先春 倪世杰
带队教师:王峰???

第一章


1.1智能汽车生产情况

??本文由全国大学生智能汽车竞赛官方指定 C车型模型为主体,采用两个直流电机驱动后轮,舵机驱动梯形转向机构完成前轮转向。在硬件电路周围 RT以1064微处理器为主控制单元, OpenARTmini主控制单元用于识别动物、水果和数字,其次包括 MT9V032摄像头采集,全桥驱动电路驱动直流电机,512线编码器作为速度反馈, LCD由屏幕和按钮组成的人机交互平台。其次,利用差异和像素阈值算法检测轨道边界线,然后通过图像处理获得中心边界线,路径识别和决策规划。

??最后,利用自动控制理论,建立相应的模型,设计跟踪控制器,包括 PID速度控制器和 PD方向控制器 PID控制,对 kp、kd动态变化值等。

1.2 RT-Thread技术概述

??RT-Thread,全称是 Real Time-Thread,顾名思义,它是一个嵌入式实时多线程操作系统,其基本属性之一是支持多任务,允许多任务同时运行并不意味着处理器同时执行多任务。事实上,处理器的核心只能在某个时刻运行一个任务,因为每个任务的执行时间很短,任务和任务通过任务调度器快速切换(调度器根据优先级决定此时执行的任务),造成多个任务同时运行的错觉。在 RT-Thread系统中,任务通过线程实现的, RT-Thread线程调度器是上述任务调度器。

??RT-Thread主要采用 C语言编写简单易懂,移植方便。它将面向对象的设计方法应用到实时系统设计中,使代码风格优雅,架构清晰,系统模块化,割性好。针对资源有限的微控制器( MCU)通过方便易用的工具,用的工具切割 3KB Flash、1.2KB RAM内存资源的 NANO版本(NANO是 RT-Thread官方于 2017年 7月份发布的极简版核心);对于资源丰富的物联网设备, RT-Thread还可使用在线软件包管理工具,配合系统配置工具实现直观快速的模块化裁剪,无缝地导入丰富的软件功能包,实现类似 Android图形界面、触摸滑动效果、智能语音交互效果等复杂功能。

??相较于 Linux操作系统, RT-Thread除此之外,体积小,成本低,功耗低,启动快 RT-Thread它还具有实时性高、占用资源少的特点,非常适合各种资源受限(如成本、功耗等)。虽然 32位 MCU它是它的主要运营平台,其实很多都有 MMU、基于 ARM9、ARM11甚至 Cortex-A系列级别 CPU也适用于特定应用场合的应用处理器 RT-Thread。

??近年来,物联网( InternetOfThings,IoT)物联网市场发展迅速,嵌入式设备的联网已成为大势所趋。终端网络大大提高了软件的复杂性,传统 RTOS内核已经越来越难满足市场的需求,在这种情况下,物联网操作系统( IoTOS)概念应运而生。物联网操作系统是指操作系统的核心(可以) RTOS、Linux等文件系统、图形库等相对完整的中间件组件为基础,具有低功耗、安全、通信协议支持和云连接能力的软件平台, RT-Thread就是一个 IoTOS。

??RT-Thread与其他很多 RTOS如 FreeRTOS、uC/OS主要区别之一是,它不仅是一个实时核心,而且具有丰富的中间层组件,如下图所示。

▲ 图 1.1 RT-Thread中间层组件

??我们采用 RT-Thread开发和运行代码大大提高了开发效率。任务调度的功能可以大大提高我们的利用率 CPU效率提高了摄像头的帧率,提高了车辆前进的上限,可以在各个方面轻松切换任务,真正减少了不必要的代码计算能力浪费和代码开发速度。

1.本文的概况和结构安排

  • 第一章描述了本设计的研究背景,阐述了智能汽车技术的发展,得出了本设计的主要研究工作和论文结构安排。第二章,智能汽车系统的整体设计首先介绍了设计理念,进一步简要介绍了本设计的系统结构,最后展示了智能汽车的整车布局。
  • 第三章设计和优化机械结构,包括基于阿克曼转向原理的转向结构优化,获得合理的转向梯形结构,优化其他结构部分。
  • 第四章重点介绍了硬件电路的设计和优化 RT最小系统部分,电源部分,视频信号处理部分,驱动电路部分,速度检测部分。
  • 第五章,路径识别是视觉导航的关键技术,运用差比和算法检测出赛道两条黑色边界线,经过特殊处理得到赛道中心边界线,进而完成路径识别和决策规划。还介绍了如何运用 OpenArtmini实现功能和任务。
  • 第六章主要介绍速度和方向的控制 PID控制方法。
  • 第七章重点介绍了如何完成动物、水果和动物 Apriltag码的识别。
  • 第八章重点介绍了如何对待 RT-Thread移植和应用。第九章,重点介绍 RT-Thread创新使用操作系统
  • 第十章,总结。

第二章 统总体设计


2.1系统概述

??智能车的核心单元和 OpenARTmini恩智浦公司推出了核心单位 32位微控制器 RT1064。其采用 ARM-Cortex-M7芯片内核,芯片频率为 600Mhz,是 STM32F103系列的 8倍多,有 1M片内 SRAM和 4M片内 FLASH和丰富 IO口

??智能车系统的工作原理:

??智能车系统的硬件分为摄像头自动跟踪识别 6个模块:主控制器模块、电源模块、轨道信息采集模块、智能视觉识别模块、方向控制模块、速度控制电路模块、摄像头自动跟踪智能汽车系统硬件整体设计框图 2.1所示。恩智浦公司推出的主控制器模块 RT1064系列的 32位微控制器 NXPRT作为智能车嵌入式系统的核心控制单元,1064是整个摄像头智能车的大脑电源模块负责提供各子模块所需的电压。通过摄像头采用轨道信息采集模块 MT9V03X通过路径识别算法提取偏差,将获得的数据存储在二维数组中。采用智能视觉识别模块 OpenARTmini上部署神经网络模型识别数字水果和动物,然后将识别信息传回车辆主控模块,然后由主控模块判断下一步行为。

  方向控制模块使用的是 S3010转向舵机,该舵机转向灵活、反应速度快且力矩较大,通过赛道中心线部位与小车位置的偏差,由相应控制算法控制舵机灵活转弯。通过 PID算法以及灵活调整 PID参数,通过编码器读到的数值进行一定运算得到现场速度。停车由摄像头采集图像内是否遇到斑马线然后判断黑白跳变条数来决定。

▲ 图 2.1系统结构框图

2.2整车布局

  小车的布局本着轻量化的设计原则,尽可能降低重心以提高稳定性,具体包括具有以下特点
  1) 舵机位置在前,立式安装,既保证响应速度又大多数符合阿克曼转角原理;
  2) 电池用扎带固定在后方,平衡重心;
  3) 摄像头通过碳杆、金属支架和 AB胶固定在舵机与主板中间,有效的采集赛道信息;
  4) 云台在前,控制激光发射器在 15cm高度,将 OpenArt mini倒置安装减少打

  靶的误差,同时后方的总钻风采用 33cm高度可以完美避开前方云台的视野遮挡。下图为详细的整车布局:

▲ 图 2.2整车布局

 

第三章 械安装


3.1智能车整体参数调校

  智能车的整体参数,都对整个智能车系统的稳定运行起着至关重要的作用,通过对小车的布局,尽量保证小车左右平衡,以及寻找一个合适的重心,保证小车既能够可靠地抓牢地面,又能够对前轮舵机,后轮电机有较快的响应。机械的变化可以提升小车的速度上限,另外,机械的稳定性非常重要,因此要尽量保证小车既能够可靠地抓牢地面,又能够对前轮舵机,后轮电机有较快的响应。

3.2前轮倾角调节

3.2.1主销内倾

  主销在转向轴线上向内倾斜,主销轴线与地面垂直线在赛车横向断面内的夹角称为主销内倾角。主销内倾角也有使轮胎自动回正的作用,当汽车转向轮在外力作用下发生偏转时,由于主销内倾,则车轮将整辆车抬起,在外力消失后,车轮就会在重力作用下力图恢复到原来的中间位置,主要在低速时可利用内倾回复转向。

3.2.2主销后倾

  主销后倾角的作用是当汽车直线行驶时,若转向轮受到外力作用而发生偏转,汽车会转向。这时,后倾角会使路面对车轮产生一个侧向反作用力,使车轮回正,从而保证在中高速行驶中汽车直线行驶的稳定性,适当的加大主销后倾角可以帮助转向轮自动回正,可有效扼制转向器的摆振。

3.2.3前轮前束调节

  通过车轮中心的汽车横向平面与车轮平面的交线与地面垂线之间的夹角,称为前轮外倾角,前轮外倾可以抵消由于车的重力使车轮向内倾斜的趋势,减少赛车机件的磨损与负重,保证车辆行驶性能,前轮在滚动时,其惯性力自然将轮胎向内偏斜,抵消轮胎偏斜的力,从而减小磨损

3.2.4车轮外倾角

  轮外倾角是指通过车轮中心的汽车横向平面与车轮平面的交线与地面垂线之间的夹角,对汽车的转向性能有直接影响,它的作用是提高前轮的转向安全性和转向操纵的轻便性。在汽车的横向平面内,轮胎呈 “八”字型时称为 “负外倾 ”,而呈现 “V”字形张开时称为正外倾。如果车轮垂直地面一旦满载就易产生变形,可能引起车轮上部向内倾侧,导致车轮联接件损坏。所以事先将车轮校偏一个正外倾角度,一般这个角度约在 1°左右,以减少承载轴承负荷,增加零件使用寿命,提高汽车的安全性能。

  模型车提供了专门的外倾角调整配件,近似调节其外倾角。由于竞赛中模型主要用于竞速,所以要求尽量减轻重量,其底盘和前桥上承受的载荷不大,所以外倾角调整为 0°即可,并且要与前轮前束匹配。

3.3车模重心

  在完成车模的搭建后,通过测量小车轮胎位置的质量测量出整个车模的质心分布。从而保证整个小车的稳定性,车体重心的位置对赛车加减速性能、转向性能和稳定性都有较大的影响,同时还应该尽量降低车模重心高度,防止车模行驶时发生侧翻

3.4舵机安装

  舵机的安装方式有立式和卧式两种,经过分析,我们沿用经典的立式装法。舵机是具有较大延迟特性的器件,其延迟与其转角大小成正比,但如果能使舵机转过一个较小的角度而使车轮转过一个越大的角度,则会大大提高舵机过弯的响应速度。这不仅与舵机的安装方式有关,而且也与舵机输出臂的长度有关。

▲ 图 3.1舵机安装图

  安装时将舵机竖起,使得两条舵机拉杆几乎成一字型直线,某种程度上增长了拉杆的有效长度,可提高智能车转向控制的速度。

3.5摄像头安装

  摄像头我们采用前后分配的安装模式,前方碳棒架起 15cm高的 OpenArt mini,尽可能的低的将摄像头高度降低,降低整车重心,便在后方使用碳棒架起到一个更高的高度安装总钻风摄像头,并且调整俯视角度,尽量减少对于视野盲区的影响,同时保证了前方视野的前瞻来减少舵机的滞后性影响。

 

第四章 路设计


4.1.总体结构图

▲ 图 4.1电路设计思路

  硬件系统是整个智能车系统可靠运行的基础,更是软件程序得以稳定运行的基础,所以硬件系统的设计是非常重要的,我们的硬件系统主要包括电源管理模块,电机驱动模块,舵机驱动模块,电磁循迹模块,主要使用三块板子分别为母版,电机驱动以及电磁。

4.2.电源管理模块

▲ 图 4.2 5v降压电路

  首先是电源管理模块,我们采用的 7.2V2000mAh的供电电池。电机驱动需要的就是 7.2v的电压,所以我们采用开关稳压芯片进行稳压输出,舵机工作电压范围为 4V到 6V,我们需要通过调节电位器使他的电压维持在 5v即可正常工作,单片机系统,电磁,以及下面的 oled等均使用的是 3.3V的电源。通过以上电路将 7.2v的 vccbat输入降到 5v进行输出。

▲ 图 4.3 3.3v降压电路

  再通过如上电路将 5v降为 3.3v,其中 u6使用的是 rt9013-33gb

4.3单片机

▲ 图 4.4单片机电路

  我们使用的是恩智浦公司推出的 RT1064系列的 32位微控制器 NXP.RT1064,更大的 RAM可以放更多的数组或者变量, RT1064通过快速 GPI0可以实现 150M的 I0翻转速度,由于 RT1064片内自带了 flash,因此 IDE (IAR、 MDK等)都会自带相应的下载算法,不需要自己手动添加,使用更加的方便, RT1064自带 ROMAPI可以非常方便的操作片内的 flash。

4.4电机驱动

  将直接输入的电压先转化成 5v稳定电压,再通过单片机输入的 pwm波信号达到电机驱动目的。

▲ 图 4.5电机驱动原理图

▲ 图 4.6pwm接收与发出

▲ 图 4.7整体 pcb图

4.5电磁模块

  因为在路上有时仅凭摄像头会出现小误差导致偏移出赛道的情况,可能会冲撞导致损坏摄像头,所以我们使用电磁模块,来有效防止这一情况的出现,电路图如下:

▲ 图 4.8电磁模块原理图

▲ 图 4.9电磁整体 pcb图

 

第五章 像信息获取及处理


5.1赛道信息采集

  赛道信息获取是智能车稳定快速运行的根本保障。赛道信息通过 MT9V03X总钻风摄像头进行采集, MT9V03X总钻风摄像头采集速率最高可达每秒 498帧,它具有 FPS可调,全局快门、高动态范围( High dynamic range)、可进行自动曝光等优点。同时 MT9V03X总钻风摄像头采集的是灰度图,具有更多的赛道信息。

▲ 图 5.1差比和寻线 (图片来自逐飞科技公众号,侵删 )

  往最长白列的左右开始扫描边界黑点,边界黑点的确认方式也采用差比和的方式,公式等于 abs(a-b)/(a+b)*100,与上面一样。例如我们现在需要找最近一行的左边界,我们取最近一行与最长白色列交点处的灰度值为 a,然后取该点左侧点的灰度值为 b,然后根据公式计算得出结果,如果差比和的值大于我们设置的阈值则认为 b点是边界黑点。如果不是我们将 b点的值赋值给 a,然后 b点左侧点的灰度值赋值给 b,再次计算并判断。

▲ 图 5.2差比和举例 (图片来自逐飞科技公众号,侵删 )

  上表列出了 4种情况

  • 情况 1:黑点为 30,白点为 100,我们通过差比和公式计算并放大100倍,得到的结果为 53。
  • 情况 2:白点 1为 90,白点 2为 100,我们通过差比和公式计算并放大 100倍,得到的结果为 5。
  • 情况 3:黑点 1为 30,黑点 2为 35,我们通过差比和公式计算并放大 100倍,得到的结果为 7。

  通过对这三种情况进行分析,我们可以看到当选取的两个点,像素值差距较大时计算出来的值比较大,像素值差距较小的时候计算出来的值比较小,那么我们就可以设置一个阈值,当差比和计算出来的值超过这个阈值的时候(这个阈值就需要自己上赛道观察白点与黑点的值,然后再自己计算一下这个黑点与白点的差比和值是多少,然后计算出来的值乘以 0.7来作为阈值,也可以根据自己的测试对这个阈值再稍加调试),我们认为找到了一个黑点与一个白点。

  • 情况 4:可以看得出来白点与黑点都比较暗,但是通过差比和计算出来的值却还是和正常图像计算出来的值差距不大,

  这样我们就可以通过使用差比和提高我们的稳定性,不像二值化那样光线稍有变化二值化图像就会跟随着变化。所以,使用这样的方法也相当于提高了对光线的适应能力。

5.2消除寻线误判

  对于利用差和比寻找赛道边界来说,判断出何处为赛道边界其实是容易误判的,举例说明,当寻找右边界时,假如处于弯道,或者车身不正进入直道时候,图片就会如下图 1所示,可以发现,左边界和有边界在远处一定距离已经被扫线到一处去了,因为差比和算法,每次都是从中间开始往两边扫线的,当赛道已经完全处于中心点外便会导致赛道误判。于是进行优化的方式是通过每次找到边界之后,对下一次起始的点做偏移修正,并且对差和比中加入方向的概念,通过判断像素值的大小一定是从大到小来进行做限制条件,这样同时可以减少运算工作量,同时完美解决了这种现象的发生,提高了寻找中线的稳定性。

▲ 图 5.3弯道错误寻找边界

▲ 图 5.4扫线效果图

5.3算法优化

  简单使用差比和对每一行像素点扫线寻找赛道边界后会发现在弯道曲率较大的时候,会出现单边寻找赛道边线丢线的情况,如下图所示,左边边线已经丢失了,蓝色为计算出的赛道中线,导致中线,明显畸变,会导致计算出来的偏差位置过小,导致舵机打角过小,从而向外侧冲出赛道。解决办法有两个,一种为修改摄像头角度,另一种是通过算法修正。

▲ 图 5.5弯道扫线情况

  我们采用半宽补线法对赛道中线进行修复,通过计算赛道一行的像素点长度,取一半对赛道中线开始丢线的地方进行修复,首先可以确定的是,这种情况下,只有单边丢线,那么计算中线的方式就是由右边边界减去半宽的赛道像素点长度。并且只要确定底部的第一行中线起点即可,后续行的中线可以根据右边界的变化来进行对应变化,以下是修复过中线的丢边界线的效果图。

  对比可以发现,效果显著,并且配合赛道上边界的判断,可以很好的区分出赛道,不会受到其他外界赛道的干扰,扛干扰能力强,且降低了对外界地板颜色的依赖程度,一定程度上提高了容错率,适应性更强。

5.4修复结果

▲ 图 5.6修复后结果

  可以发现,即使现在图像发生了严重的丢线情况,赛道中线也能被精准的定位。效果良好,极大的提高了弯道过弯时,舵机打角的准确性。

5.5灰度图中的八领域寻线应用

  传统的八领域寻线都是将图像二值化之后再进行寻线,其基本思想是:遍历图像找到第一个非零像素点,那么这个点一定是边界点。设这个点为起始点 x,顺时针查找该点八邻域内遇到的第一个非零像素点 x’(点 x’也为边界点)。令x=x’,再进行邻域内的顺时针查找,查找的起点为刚刚 x到 x’过程中 x’前一个零点。

  对图( a),在 X点时,按照 0->1->2->3->4…….的顺序进行查找。 6处为查找到的第一个非零像素点,则 6处为边界点, X’查找的起始位置是( a)中的 5,即 X’对应的 4,则 X’的查找顺序是 4->5->6->7->0->1->2->3。

  由于我们并没有对图像进行二值化操作,所以我们在传统八领域寻线的基础上进行改进,使之适用于灰度图。

  主要改进的点就是在二值化图中八领域寻线的赛道边界判断是判断该点在数组中存的值是 0还是 255,而在灰度图中的赛道边界判断就是采用上面所讲的差比和算法,如果该点和辅助点差比和的结果大于阈值,那该点就是赛道边界
  而在顺时针(或逆时针)遍历八个邻近像素的时候,用于辅助判断该点是否为赛道边界的辅助点不能向上面讲解的一样选取右边(或左边)第五个点作为辅助点,而是也要随着当前点顺时针(或逆时针)旋转。
  下面是我的方向数组和辅助点方向数组

▲ 图 5.7代码

▲ 图 5.8代码

  第一个为当前点方向数组,第二个为顺时针八领域寻线当前点的辅助点方向数组,第三个为逆时针八领域寻线当前点的辅助点方向数组。

  在顺时针八领域和逆时针八领域的时候,顺时针时,方向数组加加,逆时针时方向数组减减即可。而赛道边界和赛道的相对位置是相反的,所以对应的辅助点方向数组是刚好是对称的。

5.6车库图像

  1. 在出库方面,由于是可以由参赛人员自由放置,因此我们采用了开环控制。对编码器进行积分就可以得到其运行距离,在多次测试之后设置一个固定打角、固定出库速度和固定行驶距离,行驶到固定距离时再恢复扫线,正常行驶。以上方法只要保证每次放小车的时候都大概在那个区域,就能完美出库。
  2. 在入库方面,我们参考了杭电双车组三轮图像处理总结。因为我们的摄像头前瞻比较远,可以在很远判别到斑马线,但不稳定,有时候很远就能判别到,有时候较近才能判别到。,于是我将判别区域限制在图像 30行到 100行,当斑马线起始行或者总止行大于 35行时,开始采用灰度图八领域寻线找到车库入口的两个拐点,然后再进行拉线处理,具体拉线方式如下图


  (图片来自卓大大公众号,侵删)而当左上大于一定行数时直接打死并且后轮加差速即可入库。

5.7总钻风检测赛道上 Apriltag码

  赛道上加 Apriltag码是今年新增加的元素,这对于各个学校来说都是一个全新的挑战,而我们采用的方案是用识别斑马线的方法来识别赛道上的黑块。这样能在较远的地方准确且快速识别到。 Apriltag码一行有 2-6个黑块,一般都是 2-5个,当扫到某一行黑块大于 2小于 6并且间隔小于该行赛道的 2/3,并且这样的行有大于四个就判定为 Apriltag码,同时为了防止在斑马线哪里误判,当识别到斑马时不识别 Apriltag码。当一行黑块数大于 7个重新识别。

  当识别到 Apriltag码后再用沿着赛道中线找 Apriltag码边界,找到起始点后用灰度图八领域将 Apriltag边框找到,然后边框上的点的 y坐标最大和 y坐标最小分别为 Apriltag码的上下边界,即使当 Apriltag码较远,图像上的点跳变,灰度图八领域无法将 Apriltag码边框完全找全,用这个方法也能大概确定找 Apriltag码的上下边界,从而帮助小车调整到一个合适位置,便于 OpenART在合适的距离识别 Apriltag码到底是奇数还是偶数,然后再控制云台将 OpenART拉直,向左(或向右),然后再由 OpenART识别靶标的蓝色边框,然后判断与小车的相对位置,通过串口中断发送回来控制小车前后移动,然后 OpenART继续识别动物还是水果。

 

第六章 动控制


6.1方向控制

  摄像头智能车能够围绕着赛道中心线稳定运行依靠舵机转向功能。方向控制模块采用的是 S3010转向舵机,该舵机具体高扭矩、响应速度快的优点。舵机有三根接线,红色线接 5.5V电源、黑色线接 GND、白色线为舵机信号控制线,接 PWM输出端,通过单片机的控制信号来调节舵机的脉冲占空比来实现舵机的转向功能。系统框图如下图 6.1所示。

  舵机采用位置式 PID进行控制,同时为了适应各种赛道元素,增加舵机响应速度,我们采用了模糊 pid进行改良,同时为了防止把舵机的齿轮打坏,我们对舵机的打角进行限幅处理。根据中线误差通过模糊 pid算法得到打角输出,有效而且快速的完成了对赛道正确的打角,能保证在 2.8m/s速度以下正确的进行转向,再快因为舵机滞后性的原因,采取了速度控制策略来使车辆略微减速,使舵机的滞后能够不至于小车冲出赛道。

6.2电磁控制

  电磁传感器放置位置受限于摄像头视野范围,无法距离车头很远,不然会影响摄像头寻线,实际上我们直接安装在车头上。我们电磁传感器主要用于检测小车是否冲出赛道和是否遇到环岛。

  当小车冲出赛道时,电磁信号归一化之后的值几乎在 10以下,因此用电磁来判断小车是否冲出赛道,快速又准确。

  当小车运行到环岛区域,由于电磁线数量变成四根,电磁感应出来的数值会是普通赛道的两倍,实际测量中因为一些干扰,达不到两倍,但相对于普通赛道而言,电磁在一开始入环的区域感应出来的数值还是明显变大,因此可以通过这个特点来辅助摄像头进行对环岛的判断。

6.3速度控制

  速度控制模块主要由电机、电机驱动电路、编码器等组成,与主控器一起构成闭环控制系统。如果单片机输出的 PWM信号直接给到电机,会造成电机转动产生过大的电流可能将单片机烧毁,故需要通过电机驱动电路来控制电机。因为电机采用的 RS380直流大电机,电流较大,驱动电路主要芯片采用 DRV8701E和 TOH1R403NL。

  后轮的速度,采取增量式的 PI,通过匿名科创的上位机进行调参,通过跑赛道采集数据,最终确立了合适的后轮 PI,后轮有着较好的响应速度,且不至于超调严重。

▲ 图 6.1方向控制流程图

 

第七章 像识别


7.1 OpenART mini整体代码思路

  OpenARTmini兼容了几乎所有的 Openmv的库文件,对图像的处理只要调用相应的 api即可,十分的简介方便。智能视觉组赛题的识别要求包括三项,数字识别, Apriltag码识别以及水果动物的分类,这三个任务我们都基于官方建议的 OpenARTmini进行实现,早期也使用了龙邱的 openmv来实现,但由于仅支持 nncu神经网络模型并不支持 tf模型,并不如 OpenARTmini方便,于是后期更换了摄像头。

  部署神经网络模型有两种方式,一种是官方介绍的,通过 nncu工具将 h5模型量化转换进行部署,还有一种就是通过 tensorflow将 h5模型转换为 tflite模型,再部署到 OpenARTmini上。

  最后我们采用第二种方案,首先我们通过学习谷歌发布的 moblienetv3.0轻量型模型,改进了自己的 tensorflow模型,显著提高了模型的识别效率和准确率,之后通过爬虫从互联网上爬取了足够的动物水果的图片,通过大量的训练和参数调试,最终得到了良好的识别动物水果的模型,最后通过 tensorflow官方学习了模型量化的方法,转换为 tflite模型之后部署到了摄像头上,做到了即使是识别逐飞官方数据集之外的动物水果图片,在复杂背景之下也能做到对靶标类型正确识别。

  相同的对数字靶标也做了相似的模型训练,训练了一个十一分类 tflite神经网络模型,同样取得成效。

7.2数字识别

  首先会打开摄像头的打光灯来保证光线恒定,再通过 openmv的色块二值化函数 find_blobs,通过颜色的设置将紫色矩形边框二值化显示出来,同时运行 find_rects来寻找矩形框,因为二值化图形的处理非常迅速,整个寻找边框的过程效率大大提升达到了每秒近 40fps,再次通过对矩形边框的限制条件,如正方形和大小显著,来准确定位矩形位置,获得矩形边框位置后,再通过二值化之前的图像,定位矩形图片位置并且进行神经网络模型识别,通过识别之后向小车发送数字的信息。整个过程只需要大概 200ms,可以迅速的识别并通过三叉路口,唯一遗憾的是,真实赛场上因为光线的变化,在远离靶标的时候,摄像头的打光灯不能很好的照射到靶标上,于是识别三叉路口会存在找不到色块的问题,最终采用了停车策略,来保证稳定通过三叉路口,但在光线良好的赛场,通过三叉路口的速度将会很快。

  同样的动物和水果的识别也和数字识别一样,但会是在识别边框到中心位置之前一直返回矩形边框的中心位置,直到到达图片的中心,发送指令让小车停下并识别靶标,识别完成后再通过,打靶或者直接通过。

▲ 图 7.1动物水果识别结果

7.4模型训练

  因为模型训练的比较早,保存了两个版本,一种是爬虫爬下来互联网上的图片进行训练的模型,识别能力强,但为了保证没有意外,又针对官方发布的训练集训练了所需要的模型,图片分类模型的训练最重要的就是图片的训练集质量,于是我们为了提高模型的泛化能力,对数据集进行了增强,通过预处理图片,产生更多的图像来补充训练集,从而增强模型的鲁棒性,我们利用了翻转,旋转,缩放,移位,高斯模糊,噪声,运动模糊,以及各种亮度和对比度的数据增强方法。

7.5 Apriltag码识别

  Apriltag的识别必须是全摄像头下的识别,暂时没能想到较好的改进办法,采用我们采用总钻风摄像头识别黑块,然后停下检测 Apriltag码内容,并返回给小车指令,小车收到指令后对云台进行控制转向,同时摄像头进入识别图片功能。

7.6总决赛图像识别策略

  决赛制度采用积分制度,识别一次图片便进行一次动作,而且每四张图片之间便有一个空白页,于是我们采取了淘汰制度的算法,来提高识别速度。

  因为紫色边框的图片有很明显的特点,与 tag码有鲜明的区别,于是我们采用先识别紫色边框,当我们没发现紫色边框时,一定是 tag码,便启动 openart识别 tag程序,之后发送信息给小车。

  反之,若识别到紫色边框,便提取紫色边框内的图片数据,计算平均饱和度值,我们发现,平均饱和度值高于 30的图片都是水果或者动物,数字远远低于这个数值,但有部分图片,动物平均饱和度小于 30,于是采用第二轮筛选,我们去掉边框内的最大亮度计算平均灰度值,可以发现这些图片的平均灰度值都大于 30,而数字都小于 30,依据这便可以大大提高成功率。
  通过这种分类算法之后,我们便通过调用对应的神经网络模型进行识别,但在进行过程中发现,这种分类过程依然要花费大量时间。于是依据我们良好的识别正确率,我们使用了淘汰算法。

  一轮只有四种类别,当一轮中 apriltag码已经出现过了,那下一次分类识别时就不会对 apriltag码进行二次识别,同理,数字如果已经出现过了,便不会再次识别,动物和水果如果出现过了,也不会在被识别,大大提高了每一轮识别的速度。

  在做到这个程度后我们的成绩达到了平均 370分,但还不能达到期望分值,于是我们检查了识别的过程,我们是每一次识别完成给小车发送信息,做出动作,但其实可以在小车快做完动作时直接开始识别,在小车做完动作之后马上就会收到新的指令,提高了流畅程度,同时我们调整了每一次分类模型的运算量,仅仅计算边框中一部分像素点的值,计算速度被大大提升,这时我们的分数到达了 410分,后面我们又给识别摄像头安装了散热片,稳定了识别速度,在熟练软件操作后,我们就达到了 450分左右的成绩,效果良好。

  同时我们发现在识别中,车辆前后移动可能会出现车辆偏移,这因为外倾角的存在导致。我们就在保证小车识别赛道的情况下前后移动来保证不偏移。我们的车轮在马上停车时会有打滑现象,我们采用 openart每次识别方框的位置,并且传回小车,小车就可以每次进行不同距离的前后移动来保证小车原点位于中心。

 

第八章 RT-Tread移植和运用


  部分移植演示是基于逐飞 RT1064的裸机开源库和 RT-Tread源码 rt-thread-v4.0.2文件进行的。逐飞 RT1064的裸机开源库可从 gitee上下载,如下图 8-1所示

▲ 图 8-1

  图 8-2RT-Tread源码可从 RT-Tread官网->资源->下载处免费下载,如图 9-2所示

8.1移植

  1)首先将 rt-tread源码放到逐飞工程目录的 Libraries里,如图 8-3所示

▲ 图 8-3

  2)打开逐飞工程,打开 keil,在工程目录下建立 rttread_src、rttread _components、 rttread_inc、rttread_lib四个分组。如图 8-4所示

▲ 图 8-4

  3)将 Libraries->rt-tread-> src中的 C文件全部添加进 rttread_src分组中,如图 8-5所示

▲ 图 8-5

  4)将 Libraries->rt-tread-> include中的 .h头文件全部添加进 rttread_inc分组中,如图 8-6所示

  图 8-6将 Libraries->rt-tread->include->libc中的 .h头文件全部添加进 rttread_inc分组中,如图 8-7所示

▲ 图 8-7

  5)将内核部分汇编支持的文件 Libraries->rt-tread->libcpu->arm->cortex-m7中的 c文件和 context_rvds.S(如果是用的 IAR则应该添加 context_iar.S)添加进 rttread_lib分组中,如图 8-8所示

▲ 图 8-8

  6)加载组件文件 Libraries->rt-tread-> components-> finsh,将里面的 c文件全部添加到 rttread_componets分组中如图 9-8所示

▲ 图 8-9

  7)将 Libraries->rt-tread-> bsp-> imxrt->imxrt1064-nxp-evk中的 rtconfig.h加入
  user.h分组中,如图 8-9所示

▲ 图 8-10

  8)将刚刚添加文件的头文件路径包含进来,如下图 8-10所示 …\Libraries\rt-thread\bsp\imxrt\imxrt1064-nxp-evk …\Libraries\rttherad_libraries\include\libc
…\Libraries\rttherad_libraries\components\finsh
…\Libraries\rttherad_libraries\include

  图 8-10把汇编的头文件路径也包含进来如下图 8-11所示
…\Libraries\rt-thread\libcpu\arm\cortex-m7

▲ 图 8-11

  9)将 RT-Tread头文件包含进来,如下图 9-12所示

▲ 图 8-12

  10)打开 seekfree_libraries分组下的 zf_systick.c文件,将 RT-Tread头文件 "rtthread.h"包含进来 ,再将 void systick_delay_ms(uint32 ms)函数里的内容替换为下图 8-13

▲ 图 8-13

  11)修改 board分组下的 board.c文件将 头文件和 头文件包含进来,在 board.c文件中添加如图 8-14所示内容

▲ 图 8-14

  再修改 board_init(void)函数,将里面的内容修改为如下图 8-15所示

▲ 图 9-15

  继续在 board.c文件中添加三个函数,如下图 8-16和 8-17所示

▲ 图 8-16

  图 8-17在 board.h头文件中添加宏定义以及一些声明如下图 8-18所示

▲ 图 8-18

  12)打开 sdmmc分组下的" fsl_sdmmc_event.c"文件将 SysTick_Handler函数注释掉再打开 seekfree_libraries分组下的" common.c"和" common.h"将里面 HardFault_Handler( void)函数和 MemManage_Handler( void)函数以及 PendSV_Handler(void)函数的声明和定义都注释掉即可

  打开 sdmmc分组下的 "fsl_sdmmc_event.c"文件,添加 void sdmmc_tick_handler(void)函数,在"fsl_sdmmc_event.h"头文件里面声明该函数, c文件里的实现方式如下图 8-19所示

▲ 图 8-19

  13)再次编译之后发现还是会出现两个错误,这是分散加载文件错误导致的

▲ 图 8-20

  只需点开这个 Edit,如图 9-21所示

▲ 图 8-21

  进入编辑界面在图示位置加入下面两段代码即可,如图 8-22所示 #define RTT_HEAP_SIZE(m_data_size-ImageLength(RW_m_data)-ImageLength(ARM_LI B_HEAP)-ImageLength(ARM_LIB_STACK))
;ARM_LIB_STACK m_data_start+m_data_size EMPTY -Stack_Size { ; Stack regiongrowing down ;} ARM_LIB_STACK+0 EMPTYStack_Size{};Stackregion growingdown RTT_HEAP+0EMPTYRTT_HEAP_SIZE{}

▲ 图 8-22

  14)点击编译, 0错误 0警告,大功告成,连接开发板即可运行 main任务,然后就可以尽情使用 RT-Tread了。如图 8-23所示

8.2 RT-Tread的使用

  使用 RT-Tread我们有如下任务 //main优先级为 10 //recognitionTag优先级为 18 //recognition斑马线优先级为 17 //buzzer优先级为 20 //send优先级为 21 //display优先级为 30 //out优先级为 13 //view优先级 16 //两个软件 pit定时器
//多个信号量和多个邮箱

▲ 图 8-24

▲ 图 8-25

  RT-Tread作为一个嵌入式实时多线程操作系统,基本属性之一是支持多任务,然后它还有定时器、信号量、邮箱、队列等可以使用。我们主要使用了它的多任务、信号量、邮箱和定时器。

1)main任务

  我们将赛道寻线任务放在了 main()任务,这是我们最核心的任务,所以它的优先级最高为 10。在它里面对其它所有任务和软件定时器进行初始化,而在初始化的时候会执行 rt_sem_take(OUT_sem, RT_WAITING_FOREVER),语句来获取来自出库任务发来的信号量,当没有来自出库任务发来的有效信号量, main任务一直等待,等待出库任务完成。我们出库是开环出库,固定打角和速度,不需要对赛道识别。当出库完成,出库任务发送信号量给 main任务, main任务接收信号量,才继续往下执行。

  在 main任务的 while(1)循环体里面还需要执行 rt_sem_take(camera_sem, RT_WAITING_FOREVER);语句,等待获取来自摄像头中断发来的信号量,每次摄像头拍完一次照,发送一个信号量给 main任务,任务一接收到该信号量就开始分别发送信号量给 ApriTag识别任务和斑马线识别任务,因为这两个任务优先级较低,所以这两个任务还是处于等待状态。然后 main任务就进行赛道识别。否则就等待,保证能及时分析赛道,且不会重复分析同一张图片。

2)out任务

  出库任务,它的优先级是 13,我们出库是开环控制,当小车未完全出库 main任务因为未接收到信号量就一直等待。
  而同时因为初始化了 display任务以及用于按键的软件 pit等其它功能,使得我们可以在屏幕上可视觉化的按按键调整参数,调整完毕,打开电机电源,当 ”out”出库任务判定出库成功即发送信号量给 main任务, main任务接收到信号量继续执行下一条 rt_thread_delete(tid_OUT),删除“ out”任务,因为它已经完成了它的使命。

3)smotor2舵机调整任务

  当识别靶标时需要微调云台,让 openARTmini对准靶标,以提高识别准确率,当其它任务发送相应信号量,该任务接收到其它任务发来的信号量后,就可以根据 openARTmini发来的数字调整云台。因为只有当识别靶标的时候才需要运行该任务,所以这里加入信号量来控制它。

4)Apriltag码任务和识别车库斑马线任务

  这两个任务里面都各有一个获取信号量

  rt_sem_take(camera_semMain2, RT_WAITING_FOREVER);
  rt_sem_take(camera_semMain, RT_WAITING_FOREVER);

  main任务里面以及提到,每次拍照完,获取拍照中断里发送的信号量之后,main任务会发送 camera_semMain2和 camera_semMain两个信号量,告诉这两个任务拍照完成,这里使用信号量是因为每一张图片只需识别一次,多次识别是没有意义的。

  识别赛道上的 Apriltag码任务和识别车库斑马线任务,他们的任务优先级为 17、 18,相对靠后,这是因为识别赛道上的黑块要花费比较多的时间,优先级低一点就不会影响其它任务的执行。

5)view任务

  该任务为处理 openARTmini发送过来的数据任务,优先级为 16,并且里面有一个获取信号量 rt_sem_take(view_sem, RT_WAITING_FOREVER)。该信号量由 rt1064负责和 OpenARTmini通信的串口接收中断发送, OpenARTmini每发送一个字节在串口接收中断中都会对其分析是否为结束符号,当串口接收中断判断 OpenARTmini发送过来一个结束字符,就发送信号量给 view任务, view任务开始执行下面的代码,根据 OpenARTmini发来的内容进行判断,进行模式选择。切换一些标志位,影响其它任务。使用信号量是因为该任务只有 OpenART mini向 rt1064发送一段完整信息时才需要执行,别的时候不需要执行在,这样就能方便其它低优先级任务处理信息。

6)buzzer任务

  该任务是蜂鸣器任务,优先级为 20,并且里面有一个从消息邮箱获取消息的语句 rt_mb_recv(buzzer_mailbox,(rt_uint32_t*)&mb_data,RT_WAITING_FOREVER);否则就无限等待。别的任务需要使用该任务时,只需发送相应的消息到该消息邮箱,该任务接收到消息,根据消息内容,叫一段时间。使用邮箱而不是信号量是因为使用邮箱不仅可以控制蜂鸣器叫,还能控制蜂鸣器每一次叫多久。

7)send任务

  该任务是无线串口发送任务,优先级为 21,当小车跑起来的时候,我们可以通过让无线串口发送一些信息给上位机的串口助手,从而更好的分析小车运行情况。该任务是一直执行的,但因为优先级不高,无需担心影响主要任务。

9)display任务

  该任务是屏幕显示任务,优先级为 30.该任务优先级最低,因为屏幕显示要消耗大量时间,将其设置为最低优先级,可使其不会对其它任务造成影响,即使后期小车需要处理的东西越来越多,但也无需担心刷新屏幕的占用问题。 10)用判读按键是否按下的“ button” rt-tread软件定时器

  该定时器 20ms进入一次,用于判断按键是否按下,不同按键按下发送不同的信号量,在 display任务里接收,从而实现设置一些参数和切换屏幕显示内容 11)“timer1” rt-tread软件定时器

  该定时器 1ms进入一次,在任务里可以进行其它时间的定时。
  每 10ms采集编码器信息并根据期望速度对电机控制
  每 5ms采集电磁信息并处理以及根据所有任务处理的结果对小车前轮舵机进行判断。

  使用定时器是因为控制电机、控制舵机、获取电磁信号都需要周期执行,产生 pwm波和读取编码器数值等都需要占用一个 RT1064的硬件定时器。而硬件定时器的数量是固定的, RT-tread的软件定时器拓展了定时器的个数,可以很好的解决我们定时器不够用的苦恼。

 

第九章 用 RT-Thread的创新点


9.1利用 RT-Thread提高图像处理程序的稳定性

  一开始裸机进行小车软件的开发时,发现实时性差,编写程序代码冗长,在赛道要素逐渐增多,最后编写完成时,甚至 RT1064600Mhz主频都会有一些延迟,这里的延迟体现在摄像头拍

相关文章