概述
队伍名称:飞猪
参赛队员:于辰
国家宇
胡东哲
带队教师:邢关生
陈为
第一章 引言
随着时代的前进和科技的进步,电子科技的发展越发迅速,从工业生产到抢灾救险,从科学探索到航天军事,更多的电子智能设备从工业转入各行各业,嵌入式和人工智能的发展也为电子智能科技的发展提供助力,国内的智能领域发展迅猛,世界上也已经生产出无人驾驶的智能汽车,为响应智能科技发展趋势,国内组织开展全国大学生智能汽车竞赛。
本文介绍了青岛科技大学飞猪队队员们在参与第十六届全国大学生智能汽车竞赛中的工作成果。主要从系统设计、机械结构、软件设计等方面进行对本次比赛过程中所学所感的说明和总结。
第二章 方案设计
本章内容主要介绍智能车系统的设计思路和设计方案,主要由机械结构、控制模块,程序算法,识别及通讯算法四部分构成智能车系统。
2.1 系统的主要设计方案
此次比赛我们采用C型车模搭建小车,主控制器采用NXP公司推出的RT1064作为核心控制器,在IAR环境下进行软件设计。使用Altium Designer 13进行电路板的设计与绘制。主要通过车前的五路电感来采集赛道上的电磁线信号,以及基于MT9V032芯片的总钻风摄像头采集赛道图像信息,传入单片机内部进行算法来决策小车的舵机和电机处理不同的赛道元素。通过编码器测速模块来检测车速,电机转速控制采用 PID 控制,通过 PWM 控制驱动电路调整电机的转速,完成智能车速度的闭环控制,TFT作为显示器辅助调试,增加拨码开关实现档位选择。
2.2 系统总体方案设计
▲ 图2.2.1
本系统主要由RT1064主控电源模块,摄像头传感器模块,舵机电机驱动测速模块构成。
-
主控电源模块:负责给各个模块提供电能及主控制器给各个模块输出决策信息,控制驱动电机和伺服器。
-
摄像头传感器模块:负责作为智能车的“感官”,收集赛道信息。
-
舵机电机驱动测速模块:驱动直流电机和伺服电机完成智能车的加减速控制和转向控制,并对智能车速度进行采集,进行转向跟电机闭环控制。
第三章 智能车机械结构
智能车系统任何的控制都是在一定的机械结构基础上实现的,因此在设计整个软件架构和算法之前一定要对整个车模的机械结构有一个整体的想法和认识。从而再针对具体的设计方案来调整赛车的机械结构,并在实际的调试过程中不断的改进和提高。本章将主要介绍智能车车模的机械结构和调整方案。
3.1 智能车车体机械建模
此次比赛Ai视觉组选用的赛车车模采用 C型车模。赛车机械结构只使用竞赛提供车模的底盘部分及转向和驱动部分。控制采用前轮转向,后轮驱动方案。
我们对机械结构的要求是:在符合规则的前提下以及机械结构的合理性下,让结构简单高效,在不断地修改尝试下,最终确定了结构设计方案:
▲ 图3.1.1
▲ 图3.1.2
3.2 智能车前轮定位的调整
现代汽车在正常行驶过程中,为了使汽车直线行驶稳定,转向轻便,转向后能自动回正,减少轮胎和转向系零件的磨损等,在转向轮、转向节和前轴之间须形成一定的相对安装位置,叫车轮定位,其主要的参数有:主销后倾、主销内倾、车轮外倾和前束。智能车竞赛模型车的四项参数都可以调整,但是由于模型车加工和制造精度的问题,在通用的规律中还存在着一些偶然性。
3.2.1 主销后倾角
主销后倾角是指在纵向平面内主销轴线与地面垂直线之间的夹角。它在车辆转弯时会产生与车轮偏转方向相反的回正力矩,使车轮自动恢复到原来的中间位置上。所以,主销后倾角越大,车速越高,前轮自动回正的能力就越强,但是过大的回正力矩会使车辆转向沉重。通常主销后倾角值设定在 1°到 3°。
模型车通过增减黄色垫片的数量来改变主销后倾角的,由于竞赛所用的转向舵机力矩不大,过大的主销后倾角会使转向变得沉重,转弯反应迟滞,所以设置为 0°,以便增加其转向的灵活性。
3.2.2 主销内倾角
主销内倾角是指在横向平面内主销轴线与地面垂直线之间的夹角,它的作用也是使前轮自动回正。角度越大前轮自动回正的作用就越强,但转向时也就越费力,轮胎磨损增大;反之,角度越小前轮自动回正的作用就越弱。通常汽车的主销内倾角不大于 8°。
对于模型车,通过调整前桥的螺杆的长度可以改变主销内倾角的大小,由于过大的内倾角也会增大转向阻力,增加轮胎磨损,所以在调整时可以近似调整为0°—3°左右,不宜太大。
主销内倾和主销后倾都有使汽车转向自动回正,保持直线行驶的功能。不同之处是主销内倾的回正与车速无关,主销后倾的回正与车速有关,因此高速时主销后倾的回正作用大,低速时主销内倾的回正作用大。
▲ 图3.2.2.1
3.2.3车轮外倾角
前轮外倾角是指通过车轮中心的汽车横向平面与车轮平面的交线与地面垂线之间的夹角,对汽车的转向性能有直接影响,它的作用是提高前轮的转向安全性和转向操纵的轻便性。在汽车的横向平面内,轮胎呈“八”字型时称为“负外倾”,而呈现“V”字形张开时称为正外倾。如果车轮垂直地面一旦满载就易产生变形,可能引起车轮上部向内倾侧,导致车轮联接件损坏。所以事先将车轮校偏一个正外倾角度,一般这个角度约在 1°左右,以减少承载轴承负荷,增加零件使用寿命,提高汽车的安全性能。
模型车提供了专门的外倾角调整配件,近似调节其外倾角。由于竞赛中模型主要用于竞速,所以要求尽量减轻重量,其底盘和前桥上承受的载荷不大,所以外倾角调整为 0°即可,并且要与前轮前束匹配。
▲ 图3.2.3.1
3.2.4 前轮前束
所谓前束是指两轮之间的后距离数值与前距离数值之差,也指前轮中心线与纵向中心线的夹角。前轮前束的作用是保证汽车的行驶性能,减少轮胎的磨损。前轮在滚动时,其惯性力自然将轮胎向内偏斜,如果前束适当,轮胎滚动时的偏斜方向就会抵消,轮胎内外侧磨损的现象会减少。像内八字那样前端小后端大的称为“前束”,反之则称为“后束”或“负前束”。在实际的汽车中,一般前束为012mm。
在模型车中,前轮前束是通过调整伺服电机带动的左右横拉杆实现的。主销在垂直方向的位置确定后,改变左右横拉杆的长度即可以改变前轮前束的大小。在实际的调整过程中,我们发现较小的前束,约束 02mm 可以减小转向阻力,使模型车转向更为轻便,但实际效果不是十分明显。
虽然模型车的主销后倾角、主销内倾角、车轮外倾角和前束等均可以调整,但是由于车模加工和制造精度的问题,在通用的规律中还存在着不少的偶然性,一切是实际调整的效果为准。
3.3 编码器的安装
为了提高精度,本车没有选用编码盘,而采用龙邱mini1k线的编码器,使用与编码器配套的编码器安装支架与车模连接,调节编码器齿轮与差速器齿轮的咬合,保证两个齿轮的平顺性。
3.4智能车重心位置的调整
经过多次试验,智能车的重心前移或者后移都会影响智能车行驶时的稳定,因此,为了重心不外移,在设计主板和安装舵机以及电池的安装时都把重心问题慎重的考虑进去了,我们设计的中心靠后,防止车模在坡道及其其他急弯出现车模前倾问题。
第四章 电路设计说明
4.1电源管理模块
我们选用线性稳压芯片LM2940和RT9013将8.2V电压降至5V后,再降到3.3V。在其输入端和输出端均采用0.1微法贴片电容和100微法贴片铝电解电容达到滤波稳压
对于舵机我们使用的是AS1015高效率电源稳压芯片,留给舵机足够大的电流,使舵机打角更灵敏。
4.2 激光打靶模块
通过单片机PWM引脚输出125Hz的PWM波来控制激光头的亮灭。使用S8050 NPN型三极管,具有安全可靠性高,功率高等特点。
4.3摄像头模块
摄像头使用的是逐飞的总钻风灰度摄像头
4.4 电机驱动模块(H桥)
我们使用双H桥驱动,通过IR2104芯片控制MOS管的导通与关闭,控制输出电压的平均电压和正反,实现控制其功率元件由四只支 N 沟道功率 MOSFET 管和四只 P沟道功率 MOSFET管组成,额定工作电流可以轻易达到 100A 以上,大大提高了电动机的工作转矩和转速
4.5 系统主板设计
主控设计时,使用了很多的外设传感器,大部分通过其数据手册分析性能等,最后把模块化的分布在一起,形成了主控,主控原理图如下
第五章 智能车控制软件
5.1 软件设计总体框架
本智能车系统的软件基本实现流程为:(1)各个模块的初始化。(2)中断函数中,进行电感的采值进行分析和处理,主函数中,进行摄像头采集图像的处理分析。(3)中断函数中,进行转向和驱动的控制,输出处理过的PWM波值控制舵机和电机。流程图如图:
▲ 图5.1.1
5.2 采集传感器信息及处理
摄像头直接获取的灰度图像每个像素点的取值范围在[0,255]。
根据判断赛道类型,我们将进行直道加速,弯道减速的思想来控制电机转速,由此能使直道尽可能的加速通过,减少比赛用时,同时又能使小车于弯道减速得以顺利过弯。
5.2.1 摄像头采集赛道信息
考虑到当车体位于赛道内时图像相对单调,综合各算法的复杂程度与应用范围,我们决定采用简单的边缘追踪算法——八邻域边缘追踪算法。具体算法执行流程如下。
(1)获取图像的有效底和有效顶,两者之间的区域为有效图像;
(2)根据近处信息更可靠的原则,优先在有效底找起始边界,并从此边界开始运行八邻域算法获取左右轮廓;
(3)在找到轮廓的同时利用轮廓信息并行判断该行边界;
(4)轮廓搜到有效顶时即停止搜寻;
(5)利用灰度信息对边界坐标进行校正。
5.2.2 赛道边界的修正及中线的获取
摄像头对光线比较敏感,所以需要在不同的光线场景下调整不同的阈值,所以,计算出不同光线下的阈值来寻找满足条件的赛道元素特征。原始边界只是固定算法运行得到的信息,当赛道变得相对复杂(十字、环岛前)时,原始的边线没法满足使用要求,据此我们设计了赛道边界的修正方案。
- 单边插值补线:找单边下拐点,若有,找上拐点,若有,用正常边线和连接函数拟合拐点之间的边线。
- 单边延长线补线:找单边上拐点,若有,找下拐点,若无,直接利用所有边线数据和底边丢线连接函数拟合到图像底部。
在边界信息经过修正后,我们需要获取一条中线,具体的获取方法如下。
单边线从下往上只有三种情况:
- 1.有——无(弯道内侧)
- 2.有(直道)
- 3.全无
两条边线组合分析,从下往上,有几种情况:
- 1.单丢——未丢——单丢(弯道内侧,也可能从未丢开始)
- 2.单丢(弯道外侧或直道角度不正)
- 单丢——未丢(直道)
对于3,补中线用赛道宽度对于2,补中线用最底行到另一边的距离的一半作为定值,每一行都用边线做该定值偏移对于1,补中线用未丢单丢交接处到另一边距离的一半作为定值,单丢行用边线做该定值偏移。
5.2.3 十字处理
十字元素规则上是不能左右转,当经过十字时,在丢线部分根据已知图像趋势进行补线
5.2.4 环岛处理
环岛的特征比较明显,一侧为直道,一侧有圆形区域。但是由于在完全进入环岛弯之前图像始终包含直道、弯道双重信息,所以必须在识别为环岛后重新找有效底、有效顶、左右边线,同时对弯道的缺损区域进行补线以实现中线的合理运算,由于环岛补线与实际弯道外侧线有一定差异,所以环岛单独给定所有的控制参量。
5.2.5 三叉处理
三叉部分的特征也比较明显,两侧出现边线的反向扩张。但是由于在进入三叉之后图像始终包含直道、弯道双重信息,并且图像更为开阔干扰比较明显所以必须在识别为三叉后重新找有效底、有效顶、左右边线,进行左右道路规划,同时对丢线区域进行补线以实现中线的合理运算,由于三叉补线与实际弯道赛道宽度有一定差异,所以三叉单独给定所有的控制参量。
5.2.6 车库处理
出库前程序只进入初始化部分,舵机打死角处理。
5.3 舵机控制部分
舵机打角的控制是基于五路水平电感采集的值和左右水平电感差值的处理来实现对舵机的PWM输出。舵机的控制基本分为方向判断和打角控制。
- 方向判断:通过左右水平电感差值的正负来判断方向。
- 打角控制:打角控制通过左右水平电感偏差值,将偏差通过位置式PID控制算法中的P和D(舵机不使用I)对舵机进行控制。
通过调试发现通过PD控制算法能取得较好的舵机转向控制。在屏蔽I和D两个参数时,我们通过调整P参数在速度可观的情况下都能控制舵机很好的打角,让小车平稳运行,加速后加入D参数,能让小车在过弯时更好更快速的达到理想的打角角度,在出弯时,能更快的回到平稳状态,I参数加入后会出现一定的延迟效应,所以我们最终决定只用P和D参数来控制舵机,通过不断地调试,最终能够使得小车在赛道上实现较好的打角。
5.4 速度控制部分
速度控制我们通过两路水平电感的差值作为条件,当直道时,我们开环加速,当弯道时,轻微的开环减速,总体对速度的控制是一种开环控制,速度的设定是通过编码器来配置的,这种开环控制在车高速行驶后比纯开环控制小车过弯效果要好得多,直道上的加速也能减少时间。
5.5 PID算法介绍
PID算法中各个参数的作用如下:
- 比例调节(Kp):对偏差的快速调整,智能车测量得实际值与设定允许值产生偏比例控制立即对此时刻误差发生控制,根据偏差的大小直接按比例的输出相应的控制。朝着偏差减少方向变化。由此可见偏差调整的快慢取决于Kp比例值得大小,Kp值越大系统调整速度就越快,但是容易导致系统过调,使得系统震荡,稳定性下降。比例值过小,使得系统震荡减小,但是偏差调节变慢,不利于一些追求速度的系统。
- 积分调节(Ki):对系统的历史偏差积分计算,当系统一直存在偏差时,积分调节将对系统进行调整,调整直到没有误差才会停止。积分调节的强度取决于积分时间Ti,,Ti越小,积分调整强度越大,反之越小。
- 微分调节(Kd):微分是反映一个系统的偏差变化率,表明偏差的变化趋势,由此可见它是能超前比例和和积分调节,但是微分是反映变化率,当偏差没有发生变化时,微分作用也不存在,所以不可单独使用,必须结合使用。
数字PID控制算法通常分为位置式PID控制算法和增量式PID控制算法。
1、位置式PID
位置式PID中,由于计算机输出的u(k)直接去控制执行机构(如阀门)u(k)的值和执行机构的位置(如阀门开度)是一一对应的,所以通常称公式(5.5.2)为位置式PID控制算法。
位置式PID控制算法的缺点是:
由于全量输出,所以每次输出均与过去的状态有关,计算时要对过去e(k)进行累加,计算机工作量大;而且因为计算机输出的u(k)对应的是执行机构的实际位置,如计算机出现故障,u(k)的大幅度变化,会引起执行机构位置的大幅度变化,这种情况往往是生产实践中不允许的,在某些场合,还可能造成严重的生产事故。因而产生了增量式PID 控制的控制算法,所谓增量式PID 是指数字控制器的输出只是控制量的增量 。
2、增量式PID
第六章 AI视觉识别与串口通讯
关于视觉组的识别任务,我们采用了OPEN ART mini 来完成识别部分。而识别需要一个模型来量化数据集,我们通过ART MINI配套的量化软件:
来量化nncu_pc文件夹中的模型,生成.nncu文件,将它放到ART sd卡中,相应地将程序中的地址换成此文件就可以直接应用此模型进行识别了。
6.1 识别任务
总体思路:于图片像素的HSV空间的统计值,建立了一个简单的大类分类器。利用这个分类器可以非常精确的在第一时间吧图片分成Apriltag,数字以及彩色图片(动物和水果),然后在利用不同的识别模型进一步识别。
下面给出HSV的计算公式:
6.1.1数字识别
任务:如果是偶数,则往前行进大约30厘米,然后退回到原地;如果是奇数,往后退行大约30厘米,然后返回原地;
6.1.2水果识别
任务:识别到水果,车模激光管发送激光对水果图片下方的键盘进行照射打靶,激光光斑需打在图片垂直映射下来的键盘上即可(打在屏幕上会产生镜面反射,不容易判断是否进行了打靶),照射时间超过1秒钟。
6.1.3动物识别
任务:识别到动物,车模的摄像头左右摇摆两次,摇摆的角度大于90°。或者车模前轮转向左右摆动两次。
6.1.4 ApriTag识别
任务:如果是偶数,车模先往前行进大约10厘米,然后再返回原地。如果Apriltag是奇数,则车模先后退大约10厘米,然后返回原地。
处理方法:数字在HSV的S分布中基本处于0附近,而普通的彩色图片对应的S分量分布具有很多很大的数值。利用这一点,可以利用图片的灰度分布统计来,或者平均灰度来区分这两类。有效地区分是黑白照片的:Tag码跟数字 跟是彩色照片的:动物和水果。然后再利用黑白分布区分Tag码跟数字,对于图片内的形态识别特征,转换使用基于像素的统计规律,这样可以大大提高检测速度。
如果仅仅通过色保护度来区分黑白图片(Apriltag, 数字)与彩色照片(动物和水果)会存在比较大的误差。下面还可以通过图片的灰度分布差异来进一步区分黑白图与彩色图片。而对比黑色图片(Apriltag,数字)图片的亮度分布,可以看到它的分布主要集中在最高值与最低值,中间分布很少。因此,可以利用这个差异进一步区分黑白图片与彩色图片。
对于平均色饱和小于20(总共有41张图片),计算它的次级亮度平均值:
Vaverage=N11V(i,j)<230∑V(i,j)上面公式中的230是相对于亮度最高位255时所设定的阈值,把所有不是最高亮度,也就是背景像素之外的像素亮度(V值)相加,再除以这些像素个数N 1
为了提高分类器的适应性,我们合图片的S,V来区分黑白图与彩色图。计算图片的平均色饱和度值 Save以及次级平均亮度值 Vave,选择两个合适的阈值St和Vt
对于Save<St,Vave<Vt,则判断为黑白照片,
否则判断为彩色照片
当然具体阈值还需根据摄像头来自己调试
6.2 数据集扩充及加框及增强
当数据集库已经给出的时候我们就应用逐飞给的Ai视觉显示软件的训练模式,对每一张照片进行拍摄,然后为了节省时间,分别应用PyCharm写出自动对文件夹中的照片加框处理(数据集训只对红框中的特征进行提取训练),之后对于加框后的照片再用PyCharm对加框后的照片进行增强处理,其中包括对每张变亮,变暗,模糊,反转,缩放处理。当然这么做的目的为了防止模型过拟合导致准确率适得其反,下面给出加框及增强的部分代码:
增强处理:
加框处理:
6.3抓框处理,识别结果处理及通讯
6.3.1 抓框处理
我们在识别的时候发现,ART抓框识别时,如果环境杂乱,可能会导致阈值跳变,误抓框,同时我们发现它误抓的框大都成长方形,而对于需要识别的照片抓框往往是正方形,于是我们将框用r.rect()函数计算出框的长跟框,如果长比宽近似等于正方形是才将此识别数据进行传输,经试验证明,此处理也确实有很好的成效,极大地降低了误抓框导致传输错误的识别数据。
6.3.2识别结果处理及通讯:
我们对识别的结果进行了特殊处理,处理思路如下:
- 如果识别到的是数字,那我们将识别到的数字直接用uart.write()进行传输,当然要注意的是这个函数只能传送字符的形式。
- 如果识别到的是动物,我们发送字符”c”
- 如果识别到的是水果,那我们发送字符”d”
- 如果识别到Tag码,那我们先发送字符“a”代表下面的数字表征的是Tag码,再发送Tag码对应的数值,这么做是为了防止跟数字混淆。
对于每一个识别到的数据串口传输时我们都会应用三个uart.write()函数先后发送三个数据。如下:
发送的第一位代表起始位,第二位代表发送的数据代表什么类别(tag码,水果,动物,数字),第三位是代表所识别到的数据。
6.4识别结果接收,单片机进行相应的动作:
这里有四个步骤:
1、首先先对串口接受的数据进行处理,每三个为一组,组成5组,为了准确率,将5组进行对比,取众数,众数对应的即为最终处理的数据。
2、根据数据对对每个值进行动作的选择,并且将flag置1。
3、判断flag的属性。
4、中断选择舵机动作和电机动作。
(详细程序见附录。)
第七章 系统的开发环境与调试
在系统的设计制作和调试的过程中,不管是软件的开发还是硬件电路的仿真和电路板的制作都离不开PC 机。所以对于PC 机上的各种辅助设计软件必须要有一定的熟悉程度。这样可以提高开发的效率。
7.1 IAR的使用
c型车采用iar编译环境,注意文档提示使用8.2以上版本,否则会遇到程序无法下载的情况,iar自带jling驱动器,所以可以省略安装驱动部分,如果需要手动安装驱动器,注意安装过程中 要勾选将驱动器应用到 IAR 环境中
今年我们选定了恩智浦最新的32 位单片机,它的开发成了一个很难问题,我们选择了用IAR 来进行软件的开发。Embedded Workbench for ARM 是IAR Systems 公司为ARM 微处理器开发的一个集成开发环境(下面简称IAR EWARM)。比较其他的ARM 开发环境,IAR EWARM 具有入门容易、使用方便和代码紧凑等特点。
7.2 调试工具及调试方法
串口调试工具在车模过程中起着非常要的作用,传统无线串口模块调试工具在车模过程中起着非常要的作用,无线串口模块输串口调试工具在车模过程中起着非常要的作用。
第八章 主要技术参数说明
总结
8月23日,智能车比赛正式谢幕,感谢我们的指导老师,每一位队友,以及智能车组委会以及卓老师。
智能车竞赛是一个多学科、综合性的比赛,其中设计涉及了控制、传感技术、电子信息、模式识别、汽车电子、机械等多个学科,在整个准备的过程中,我们不仅仅把所学的理论知识应用于实际,还自学了大量的新知识。不仅开拓了视野,使我们的动手能力、运用知识的能力、分析解决问题的能力也有了很大的提高。
此次硬件电路还有很大的提升空间,例如将电路板全部规划在主控上,一块板子全部集成,方便硬件的搭建等,但是信号干扰就需要仔细的去考虑怎么抑制干扰。
8月23日,比赛结束,虽有最有略有遗憾,但是取得今天的成绩已然知足,天行健君子当自强不息,十二月份进入备战,经过这快半年的准备,中间过程有苦恼也有欢乐,五味杂陈,所填苦辣都有,正是这样才让我对智能车这个比赛充满了热爱,不惜牺牲课余时间调车,写程序。正是这样坚持不懈,才有了如今的成绩,在本次比赛中带给我的不仅是荣誉更是在课本中无法体会到的动手实践,让我对单片机有了更深入的了解,以及拓展了我的知识面,参加这个比赛对我的动手能力以及团队协作的锻炼都有很大提升。
虽然本次比赛中有太多遗憾和不甘,但大家绝不会沉浸于过去,每一次的历练都是为了更好地未来。正如竞赛的指导思想“追求卓越”那样,相信我们会继续坚持拼搏、踏实奋进,未来取得更好地成绩
参考文献
[1] 邵贝贝. 单片机嵌入式应用的在线开发方法. 北京, 清华大学出版社, 2001
[2] 刘慧银, 龚光华, 王云飞等. Motorola(Freescale)微控制器MC68HC08原理及其嵌入式应用(新版). 北京, 清华大学出版社,1993
[3] 卓晴, 黄开胜, 邵贝贝等. 学做智能车. 北京, 北京航空航天大学出版社, 2001
[4] 潘新民, 王燕芳. 微型计算机控制技术. 北京, 高等教育出版社, 2001
[5] 何立民. 单片机应用系统设计. 北京, 北京航天航空大学出版社, 1997
附录
部分程序代码
//================HD标志设立============//
int Sub45,Sub12;
int AD_HDflag1=0,AD_HDflag2=0,AD_HDflag3=0,AD_HDflag4=0,AD_HDflag5=0,AD_HDflag6=0,AD_HDflag7=0,AD_HDflag8;
int Flag12=0;
int R_HD=0,L_HD=0;
int32 Per_distance=0;
int32 Sec_distance=0;
int AD_distance=0;
int Out_distance=0;
int Smail_flag=0;
int AD_flag=0,Sub_flag=0,Sum_flag_fore=0,Sum_flag=0;
int Out1=0;
void AD_HD_deal()
{
Sub45=AD4-AD5;
Sub12=AD1-AD2;
if(Sub45<0)
{
Out1=0;
}
if(Sub45>0)
{
Out1=1;
}
if(AD_HDflag1==0)
{
AD_HDflag1=0, AD_HDflag2=0,AD_HDflag3=0;
AD_HDflag4=0,AD_HDflag5=0,AD_HDflag6=0;
AD_distance=0,Per_distance=0;
L_HD=0, R_HD=0;
if(Sub45>400&&G_Sum>4500)
{
AD_HDflag1=1;
L_HD=1;
gpio_init(PTD15, GPO,0);
}
if(Sub45<-400&&G_Sum>4500)
{
AD_HDflag1=1;
R_HD=1;
gpio_init(PTD15, GPO,0);
}
}
//=============********============//
if(AD_HDflag1==1&&AD_HDflag3==0&&R_HD==1)//右
{
if(Right_speed_int<1000)
{
Per_distance=Per_distance+Right_speed_int;
}
AD_distance=(int)(Per_distance/100);
if(Sub45>-50&&AD_HDflag2==0)
{
AD_HDflag2=1;
gpio_init (PTC0, GPO,0);
}
}
if(AD_HDflag2==1&&AD_HDflag3==0&&R_HD==1)
{
if(Sub45<-150)
{
AD_HDflag3=1;
gpio_init (PTA17, GPO,0);
}
}
if(AD_HDflag3==1&&AD_HDflag4==0&&R_HD==1)
{
if(G_Sum<2800&&(abs(AD1-AD2)>750))
AD_HDflag4=1;
}
if(AD_HDflag4==1&&AD_HDflag5==0&&R_HD==1)
{
if((G_Sum>4200&&AD_distance<37)||(G_Sum>6200&&AD_distance>=37))
AD_HDflag5=1;
}
if(AD_HDflag5==1&&AD_HDflag6==0&&R_HD==1)
{
if(G_Sum<3000)
AD_HDflag6=1;
}//右边结束
if(AD_HDflag1==1&&AD_HDflag3==0&&L_HD==1)//左
{
if(Right_speed_int<1000)
{
Per_distance=Per_distance+Right_speed_int;
}
AD_distance=(int)(Per_distance/100);
if(Sub45<50&&AD_HDflag2==0)
{
AD_HDflag2=1;
gpio_init (PTC0, GPO,0);
}
}
if(AD_HDflag2==1&&AD_HDflag3==0&&L_HD==1)
{
if(Sub45>150)
{
AD_HDflag3=1;
gpio_init (PTA17, GPO,0);
}
}
if(AD_HDflag3==1&&AD_HDflag4==0&&L_HD==1)
{
if(G_Sum<2800&&(abs(AD1-AD2)>750))
AD_HDflag4=1;
}
if(AD_HDflag4==1&&AD_HDflag5==0&&L_HD==1)
{
if((G_Sum>4200&&AD_distance<37)||(G_Sum>6200&&AD_distance>=37))
AD_HDflag5=1;
}
if(AD_HDflag5==1&&AD_HDflag6==0&&L_HD==1)
{
if(G_Sum<3500)
AD_HDflag6=1;
}//左边结束
if(AD_HDflag6==1)
{
AD_HDflag1=0, AD_HDflag2=0,AD_HDflag3=0;
AD_HDflag4=0,AD_HDflag5=0,AD_HDflag6=0;
AD_distance=0,Per_distance=0;
L_HD=0, R_HD=0;
gpio_init (PTD15, GPO,1);
gpio_init (PTC0, GPO,1);
gpio_init (PTA17, GPO,1);
}
}
void example_uart_callback(LPUART_Type *base, lpuart_handle_t *handle, status_t status, void *userData){
if(kStatus_LPUART_RxIdle == status){
if(Lock_flag == 0 && Plant_flag == 0 && Numodd_flag == 0 && Numeven_flag == 0 && Apriltagodd_flag == 0 &&Apriltageven_flag == 0 ){
Num_num[0] = 0;
Num_num[1] = 0;
for(uint8 i = 0;i<=4;i++){
Category[i] = 0;
Num[i] = 11;
Cat_num[i] = 0;
F_cnt = 0;
}
if(example_rx_buffer[0] == 102 || example_rx_buffer[1] == 102 || example_rx_buffer[2] == 102){
for(uint8 i = 0 ; i <= 8; i++){
if(example_rx_buffer[i] == 102){
F_cnt++;
if(F_cnt >= 6){
Lock_flag = 2;
}
}
}
}
if(Lock_flag == 0){
if(example_rx_buffer[0] == 101){
Category[0] = example_rx_buffer[1];
Category[1] = example_rx_buffer[4];
Category[2] = example_rx_buffer[7];
Category[3] = example_rx_buffer[10];
Category[4] = example_rx_buffer[13];
Num[0] = example_rx_buffer[2] - 48;
Num[1] = example_rx_buffer[5] - 48;
Num[2] = example_rx_buffer[8] - 48;
Num[3] = example_rx_buffer[11] - 48;
Num[4] = example_rx_buffer[14] - 48;
}
else if(example_rx_buffer[1] == 101){
Category[0] = example_rx_buffer[2];
Category[1] = example_rx_buffer[5];
Category[2] = example_rx_buffer[8];
Category[3] = example_rx_buffer[11];
Category[4] = example_rx_buffer[14];
Num[0] = example_rx_buffer[3] - 48;
Num[1] = example_rx_buffer[6] - 48;
Num[2] = example_rx_buffer[9] - 48;
Num[3] = example_rx_buffer[12] - 48;
Num[4] = example_rx_buffer[0] - 48;
}
else if(example_rx_buffer[2] == 101){
Category[0] = example_rx_buffer[3];
Category[1] = example_rx_buffer[6];
Category[2] = example_rx_buffer[9];
Category[3] = example_rx_buffer[12];
Category[4] = example_rx_buffer[0];
Num[0] = example_rx_buffer[1] - 48;
Num[1] = example_rx_buffer[4] - 48;
Num[2] = example_rx_buffer[7] - 48;
Num[3] = example_rx_buffer[10] - 48;
Num[4] = example_rx_buffer[13] - 48;
}
for(uint8 i = 0;i<=4;i++){
if(Category[i] == 97){
Cat_num[0]++; //0为TAG码
}
else if(Category[i] == 98){
Cat_num[1]++; //1为数字
}
else if(Category[i] == 99){
Cat_num[2]++; //2为动物
}
else if(Category[i] == 100){
Cat_num[3]++; //3为植物
}
}
/****************************************/
if(Cat_num[0] >= Cat_num[1] && Cat_num[0] >= Cat_num[2] && Cat_num[0] >= Cat_num[3] ){
for(uint8 i = 0;i<=4;i++){
if(Num[i] % 2 == 0 && Num[i] != 11 ){
Num_num[0]++;
}
else if(Num[i] % 2 != 0 && Num[i] != 1 )
Num_num[1]++;
}
if(Num_num[0] > Num_num[1] ){ //众数为偶数
if(Apriltagodd_flag == 0 && Animal_flag == 0 && Plant_flag == 0 && Numodd_flag == 0 && Numeven_flag == 0 && Apriltageven_flag == 0){
Apriltageven_flag = 1;
}
}
else{
if(Apriltageven_flag == 0 && Animal_flag == 0 && Plant_flag == 0 && Numodd_flag == 0 && Numeven_flag == 0 && Apriltagodd_flag == 0){
Apriltagodd_flag = 1;
}
}
}
/****************************************/
else if(Cat_num[1] >= Cat_num[0] && Cat_num[1] >= Cat_num[2] && Cat_num[1] >= Cat_num[3] ){
for(uint8 i = 0;i<=4;i++){
if(Num[i] % 2 == 0 && Num[i] != 11 ){
Num_num[0]++;
}
if(Num[i] % 2 != 0 && Num[i] != 11 )
Num_num[1]++;
}
if(Num_num[0] > Num_num[1]){ //众数为偶数
if(Apriltagodd_flag == 0 && Apriltageven_flag == 0 && Plant_flag == 0 && Numodd_flag == 0 && Animal_flag == 0 && Numeven_flag == 0){
Numeven_flag = 1;
}
}
else{
if(Apriltagodd_flag == 0 && Apriltageven_flag == 0 && Plant_flag == 0 && Numeven_flag == 0 && Animal_flag == 0 && Numodd_flag == 0){
Numodd_flag = 1;
}
}
}
/****************************************/
else if(Cat_num[2] >= Cat_num[0] && Cat_num[2] >= Cat_num[1] && Cat_num[2] >= Cat_num[3] ){
if(Apriltagodd_flag == 0 && Apriltageven_flag == 0 && Plant_flag == 0 && Numodd_flag == 0 && Numeven_flag == 0 && Animal_flag == 0){
Animal_flag = 1;
}
}
/****************************************/
else if(Cat_num[3] >= Cat_num[0] && Cat_num[3] >= Cat_num[1] && Cat_num[3] >= Cat_num[2]){
if(Apriltagodd_flag == 0 && Apriltageven_flag == 0 && Animal_flag == 0 && Numodd_flag == 0 && Numeven_flag == 0 && Plant_flag == 0){
Plant_flag = 1;
}
}
}
}
}
handle->rxDataSize = example_receivexfer.dataSize;
handle->rxData = example_receivexfer.data;
}
● 相关图表链接:
- 图2.2.1
- 图3.1.1
- 图3.1.2
- 图3.2.2.1
- 图3.2.3.1
- 图5.1.1
最后
以上就是追寻音响为你收集整理的智能车竞赛技术报告 | 智能车视觉 - 青岛科技大学 - 飞猪 第一章 引言 第二章 方案设计 第三章 智能车机械结构 第四章 电路设计说明 第五章 智能车控制软件 第六章 AI视觉识别与串口通讯 第七章 系统的开发环境与调试 第八章 主要技术参数说明 总结 参考文献 附录 的全部内容,希望文章能够帮你解决智能车竞赛技术报告 | 智能车视觉 - 青岛科技大学 - 飞猪 第一章 引言 第二章 方案设计 第三章 智能车机械结构 第四章 电路设计说明 第五章 智能车控制软件 第六章 AI视觉识别与串口通讯 第七章 系统的开发环境与调试 第八章 主要技术参数说明 总结 参考文献 附录 所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复