工程实践与科技创新II-B M21

计算机控制小车走黑线


Path

简介

技术细节

图片及视频

组员介绍及心得

项目简介

计算机控制小车沿黑线向前走,以最快的速度到达终点(总长5M,转弯小于45度)。 计算机与小车之间采取无线通信的方式(使用蓝牙)。计算机用VC++和Opencv处理采集到的视频 ,分析路径并通过蓝牙向小车发出指令。小车内部的单片机程序分析指令,沿黑线前进。整体完成度较高 ,程序能够识别路径并控制小车沿黑线前进。


完成情况

我们的项目实现了,通过摄像头获取地图信息,进行变换处理后识别运行轨道,实时通过摄像头确定小车的位置及朝向,计算机依照设定好的算法决定小车的行动,并通过串口线发送指令,小车根据指令继续前行或进行姿态调整,从而沿黑线轨道行进到终点。 具体来说,我们主要实现了一下功能:

  1. 图像的采集和处理,路径点生成及排序;
  2. 实时确定小车的位置姿态,通过计算发出控制指令;
  3. 小车上的收到指令,控制电机转向和速度,实现小车的行进与转弯。

一些不足:

  1. 由于后期时间紧张,没有使用蓝牙进行通信,因而小车的行进一定程度上受串口线的限制;
  2. 小车的重量较轻,轮胎无弹性也无悬挂,因而在不很平坦的地图上行进时,轮子容易空转,行动较迟缓,有时还需人为协助。


成员分工


总体介绍

完成此次项目要求,首先需要使计算机获取轨道,也就是一组有序的二维点坐标。然后在确定小车位置的基础上,实时记录以达到过的点,找到下一个目标点,通过比较小车与目标的的相对位置及方向,计算得出小车是否应该转向。将转向或执行的命令通过串口发送到小车后,车载单片机接收指令,单片机程序根据指令,控制电机行止,以达到小车转向或前进的目的。


软件部分

PC端程序

  1. 路径获取:

    • 通过摄像头获取图像,进行透视变换:
      用鼠标依次(上左,上右,下左,下右)点击地图的四角后,将进行透视变换。

    • 二值化:
      对变换后的图像进行二值化,以便后续处理。
      若由于光线明暗及反光造成二值化效果不理想,可以拖动滑动条调整阈值,观察实时显示以决定最终效果。

    • 细化:
      由于黑线有一定宽度,为了进行最终的识别,还需对二值化后的图像进行细化。
      迭代细化10次后,路径变为单像素宽,如图:

    • 找出角点:
      焦点就是曲线发生弯曲的转折点,它们是决定路径的关键点,找到它们并排序就可得到最终路径。
      执行寻找焦点的语句后,得到一些角点坐标,将他们话在原图像上,得到下图:

    • 角点排序:
      对角点排序即可得到路径。
      开始时,我们打算使用种子填充法,依靠黑线区域的联通性以此寻找得到顺序。但实际操作后,由于效率太低,最终放弃,选用了效率更高但对一些极复杂地图可能判断错误的方法:选找下一个最近的点,作为该点的后继路径点,直到到达人为设置的终点。
      通过多次实验发现,这样的做法效率更高,稳定性也够强,在地图不太复杂的情况下,更为合适。
      一个改进措施:种子填充法效率过低,但可以处理更为复杂的情况。如果,事先将地图转换为较低像素,在进行种子填充,得到角点顺序,这样不失为一种平衡利弊的好办法。由于地图不至于过精细,分辨率降低为原来的几十分之一也不会影响结果,而处理速度却可以提高成百上千倍。

  2. 小车跟踪:
    • 定位车头车尾:
      本次项目中,我们采用meanshift算法进行目标跟踪。相比分颜色取重心的方法,这样做有着更高的适应性和可靠性,在实验室中基本不需修改参数就可正常跟踪,对车头车位的颜色也没有太大要求(只要纯度较高),甚至可以是同一颜色。唯一的缺点是,跟踪过程中若遇到有外界物体干扰(比如有人挡在小车和摄像头之间),则有在之后可能丢失目标,导致跟踪失败。一种解决方案是,自动判断是否丢失目标,若丢失则用找重心的方法确定跟踪窗口的位置,然后继续用meanshift算法进行跟踪。
      meanshift跟踪时,将图像转换为HSV色彩空间,以便提高识别率。
      按下鼠标左键向右下拖动,得到车头区域,重复操作得到车尾。计算生成颜色分布直方图:

      位置和颜色表示色向(HSV空间中的Hue维度),矩形高度表示该颜色范围在窗口中的分布多少,meanshift算法在确定下一个窗口位置时正是根据这个分布作出决定。

  3. 控制算法
  4. 已知小车头尾坐标及下一个目标点的坐标这样就得到两个向量:车尾到车头的小车方向向量和车尾到目标点的目标方向向量。
    首先通过坐标变换,将小车方向向量正规化,然后计算其夹角,判断是否在阈值之内。若在,则返回零,表示继续直行;若不在,则根据夹角正负返回-1或1,分别表示左转和右转。
    代码如下:

    const double a=3.14/3;  //a 为阈值
    int getdirection(double x1,double y1,double x2,double y2,double x3,double y3)
    {
    	double l1,l2,l3;
    	l1=(x2-x1)*(x2-x1)+(y2-y1)*(y2-y1);
    	l2=(x3-x1)*(x3-x1)+(y3-y1)*(y3-y1);
    	l3=(x3-x2)*(x3-x2)+(y3-y2)*(y3-y2);
    	double p;
    	double c,d;
    	c=sqrt(l1);
    	d=sqrt(l2);
    	p=(l2+l1-l3)/2/c/d;
    	double q,t;
    	q=atan((y2-y1)/(x2-x1));
    	t=(x3-x1)*sin(q)-(y3-y1)*cos(q);
    	if(cos(a)0)
    	{
    		if(t>0) return 1;
    		else return -1;
    	}
    	else
    	{
    		if(t>0) return -1;
    		else return 1;
    	}
    
    }
    
    				

单片机程序

  1. 单片机初始化:
    SCON= 0x50;//0101 0000 8位可变波特率,无奇偶校验位
    BRT = RELOAD_COUNT; //9600波特率
    AUXR= 0x15;
    	
    ES = 1;//允许串口中断
    EA = 1;//开总中断
            	
  2. 串口接受接受中断
    void uart_interrupt_receive(void) interrupt 4
          		

    由于篇幅所限,具体函数定义请见附件。
    中断响应函数,接收pc端通过串口发来的控制字,依照约定的方法解读控制字,作出相应控制。通过设定,IO口高低电平,完成对两个电机的行止及方向进行的控制。
    对于控制字的定义方法,我们小组原本直接借鉴往届学长的定义,但后来由于在实际调试过程中,可能是由于小车或单片机的问题,串口通信干扰较大,学长使用的定义方法冗余太小,无法正常运行,故重新自行定义了冗余度较大的编码方式,从而解决该问题,这方面内容将在,调试部分进行详细介绍。


硬件部分

  1. 单片机

    本次项目中使用STC11L02单片机芯片作为小车车载芯片

    上图为电路原理图,其中Power Part为电源部分,Motor Part为电机控制部分,MCU Part为单片机控制部分。单片机AT89S52芯片为微控制器,L298N为电机控制芯片。

  2. 小车及改造

    小车的组装,电路板的焊接,已基本有往届学长完成,我们在其基础上又进行了很多修理和改装工作

    小车的电路主要有三块电路板组成,分别是:供电部分,控制部分和电机驱动部分。
    小车又4节五号电池作为电源,总开关开启时,供电部分向控制部分和电机驱动部分供电。
    控制部分的核心为上述的STC11L02单片机芯片,还有串口接口,单片机开关和蓝牙串口跳线等部件,主要负责接收处理上位机发来的指令字,对电机驱动部分进行控制。
    电机驱动部分受单片机控制,驱动电机定向定速转动。
    由于转向是通过两后轮的行止实现,由于前轮对地面的摩擦力较大,转向迟缓。我们曾考虑改变行动方式,以后轮作前轮,即小车反向行进;又或是将前后轮间增加履带,减小转弯半径。但最终都由于材料不足或实现困难而放弃。采用前轮缠透明胶带减小摩擦系数,后轮缠双面胶带增大摩擦系数,并配重增大摩擦力的方式,这样起到了一定的效果。

  3. 摄像头

    项目中使用的摄像头为笔记本内置摄像头,减少了成本,清晰度也满足要求。
    唯一的缺点是需要将笔记本放在高处,屏幕近乎合上,不便于操作。

  4. 通信功能的实现

    小车通过一根USB转RS232线与计算机连接,通过驱动程序可以使USB端口作为一个虚拟串口,然后将USB的TXD与小车单片机的RXD相连,GND与小车的GND相连即可实现与小车的有线通信


测试与调试

  1. 对于单片机烧写不成功情况的处理办法:

    在进行本次项目会遇到的问题中,单片机程序烧写失败是最诡异最难以调试找出原因的故障。
    本小组前期在实验室进行调试的大部分时间都用于完成对单片机程序的烧写。
    以下是我们小组对于处理烧写单片机问题的一些经验:

    • 检查小车的两处开关都是否打开,否则电压达不到3.3V左右将会烧写失败;
    • 烧写开始后,在打开单片机板上的开关;
    • 若烧写失败,可以检查串口线路是否正常,方法是:短接电路板上串口线的接收和发送线(红,灰),用串口调试软件向串口发送任意字符,看是否有原值返回,若没有,则较可能是线路问题,可以重新接线;
    • 若线路无问题,则有可能是单片机故障,可以更换单片机;
    • 注意usb线与串口线相连时,并非同色相连,具体连接方法可参考硬件手册,连接错误会导致线路问题。

  2. 对于串口通信指令字发生变化的问题的解决方案:

    使用串口发送指令字时,原定的指令字编码方式是:01,02,04,08分别对应四种动作,这样的编码方式,只用到了指令字的后四位,过于密集。
    在实际运行时,有些动作不论发送怎样的指令也不会被执行。后来使用串口调试软件进行调试,发现由单片机回传来的指令字与实际发出的并不相同,由此判断可能是小车硬件有瑕疵,或是干扰所致。
    为了避开这样的问题,我们决定换用冗余更大的编码方式,将四种动作分配到16位,这样经过传输所导致的变化后也不至于重叠。
    经过试验,发现这个方法可以完美解决遇到的问题,故确定使用新的编码方案。
    新的指令字编码方案,极大的提高了控制的稳定性。


图片

以下是项目进行中拍摄的照片或屏幕截图

logic analyzer logic analyzer
work bench circuit board
circuit board circuit board
circuit board

成果展示

以下是运行时拍摄的视频,请下载播放:

视频


心得体会


下载

PC端程序pc.zip [10K]

单片机程序mcu.zip [376K]