代码链接在文中,邮箱[email protected]
本人一直以来对无人机以及机器人、自动驾驶感兴趣。作为一个创客爱好者趁着寒假闲来无事,利用手头积攒的一些开源硬件想制作一个无人驾驶小车。经历了两个礼拜的工作后,初步实现了车辆控制、避障、目标检测与识别、跟踪等功能。本文将从总体方案、小车控制、目标检测与识别、避障方法五个方面来介绍我的工作。
一个完整的自动驾驶智能小车至少应当包括传感器、动力机构、车载处理器以及车身结构。
车载处理器:一般涉及到图像处理方面智能机器人都会采样高性能的处理器来做高层算法计算,如深度学习、路径规划等,称之为上位机。经典的上位机有英伟达的TX2、Intel NUC等。此外,还需要一个单片机去处理运动控制的计算问题,驱动电机、舵机,称之为下位机。为了节约成本(穷 ==),我们选用了另外一套方案:树莓派3B+movidius NCS。树莓派3B不需要多介绍,我们稍微介绍一下movidius NCS。movidius NCS是movidius公司(现属英特尔)生产的一种神经计算棒(Neural Compute Stick,NCS),专门用来加速计算神经网络。movidius NCS只有一个打火机大小,使用USB接口。具体SDK以及使用方法可参考其官方网站。我们使用树莓派进行路径规划、传感器数据读取以及控制指令输出。使用movidius NCS计算神经网络,进行图像处理。
图1:树莓派3B与movidius NCS
传感器:我们使用的传感器包括一个USB摄像头,一个磁罗盘以及一个IMU模块,一个超声模块。
动力结构:我们使用简单的TT马达带动车轮,由于我们设计的是四轮车,为了保证动力,我们采用四驱模式。使用树莓派控制TT马达需要配直流电机驱动模块。在这里我们选用的是L298N。一个L298N模块可以驱动两个电机。在电力供应上,采用动力系统和计算处理器分开供电的方式。动力系统使用3节18650锂电池串联供电,树莓派、NCS以及各种传感器使用充电宝供电。
图2:L298N、TT马达加轮胎
车身结构:我们选用的是铝合金加工底盘。底盘一共有两层,下层用于固定电机、轮胎以及L298N模块。此外,下层还输出了固定了一个面包板。控制机构与动力机构通过面包板插线进行连接,可以有效防止接线的错误。通过铜柱撑起上层底板,上层底板用于固定电池盒、树莓派和movidius NCS以及充电宝。传感器也被安装在上层底盘上。
图3:小车下层底盘
为了方便以后对系统进行拓展,我们选用机器人操作系统(ROS)作为我们的系统框架。ROS的特点是各模块(进程)之间可以很方便地进行广播通信,共享数据。目前我们的小车自主驾驶系统有五个进程:电机控制、目标检测、障碍物探测、路径规划以及运动状态解算。如果读者不了解ROS,那也没关系,可以将这五个功能整合成一个大程序,唯一的缺点就是不方便添加新的功能模块。
图4:系统框架
在介绍本章之前,先需要介绍一下树莓派的GPIO。GPIO(GeneralPurposeI/OPorts)意思为通用输入/输出端口,通俗地说,就是一些引脚,可以通过它们输出高低电平或者通过它们读入引脚的状态-是高电平或是低电平。用户可以通过GPIO口和硬件进行通信。国内常见的树莓派大多为40pin,其针脚定义如下:
图4:树莓派针脚定义(引自树莓派实验室)
使用树莓派GPIO以及L298N模块驱动电机的原理可参考https://www.jianshu.com/p/775b4fb2c98d,此外,作者自己编写的控制代码也会共享给大家,代码地址为博主的GitHub(改地址目前只有部分源码,全部源码将会在本文阅读量达到100时上传)。
在实现了对电机的控制后,我们可以利用车轮转速差实现转向控制;利用转速实现速度控制。为了保证控制效果,我们需要利用IMU+磁罗盘模块实现闭环控制。在这里我们使用GY85模块作为传感器,该模块包含了加速度计、陀螺仪和磁罗盘的功能。树莓派读取该模块的方法可参考:https://www.cnblogs.com/hangxin1940/archive/2013/04/05/3000395.html。利用卡尔曼滤波处理数据可得到更加精确的状态信息。在获取状态信息后,我们便可以使用PID控制器实现更加精确的控制。卡尔曼滤波姿态解算以及PID控制器设计都是求助我的同学完成的,技术细节等他发布在新博客里。
随着深度学习的发展,基于深度学习的目标检测算法日渐成熟。基于深度学习的目标检测算法可以实现多目标检测,并且在性能上远超传统目标检测算法。基于深度学习的目标检测算法按照框架结构可以分为非端到端检测算法以及端到端的目标检测算法。非端到端的目标检测算法大多使用卷积神经网络提取图像的特征,然后通过处理特征图来得到检测框以及物体类别。典型非端到端的算法有Fast-RCNN、Faster-RCNN、SSD等。端到端的目标检测算法大多使用卷积神经网络直接回归检测框的大小、位置以及物体类别等参数。典型的端到端的检测算法有YOLO、YOLOv2等。端到端的目标检测算法由于框架简单,一般速度比非端到端的算法更快。
由于受到预算以及载重的限制,博主选取的树莓派+movidius NCS硬件平台的算力是有限的。端到端的目标检测算法目前在GPU平台上可以实现实时检测。但是在博主的的硬件平台上,由于深度神经网络计算量太大,实时性较差。为了解决基于深度学习的目标检测算法在无人机平台上运行速度较慢的问题,博主提出了两种解决方法。
shufflenetV2是旷视提出的一种轻量级神经网络(ShuffleNet V2: Practical Guidelines for Ecient CNN Architecture Design ),其具体原理可以通过搜索论文来学习,本文不再阐述。shufflenetV2从计算量和内存两个角度优化神经网络的计算过程,经过作者测试,shufflenetV2 0.5x在Intel i5-4250CPU上帧率可达140FPS。YOLOV2是一种目标检测框架,其实时性好,检测准确率高。更重要的是,利用YOLOV2框架可以实现同一模型检测不同尺寸的输入照片,在应用时更加的灵活。
博主基于shufflenetV2的计算优化思想,使用YOLOV2框架训练了自己的目标检测模型。具体细节以及代码见博主的GitHub:https://github.com/ZHURENTAI/faster-yolo。该算法检测效果如下图所示,其运算平台为一台处理器为i5-8250U的笔记本电脑,输入图片大小为544x544,帧率约为31(CSDN不支持5M以上的GIF,请读者们原谅渣画质)。
虽然该算法性能很优越,但是博主最后却没能将其应用在小车上,原因是因为博主的第一代movidius NCS不支持该神经网络中的一个特殊层。movidius NCS2以及其他平台应该支持博主的网络,因此博主将其写上了给大家作为参考。
为了适应硬件,我们选取了另外一种方法:mobilenet网络结合SSD检测框架的方法。mobilenet源自Google的论文:MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications。在该论文中提出了一种特殊的卷积形式:深度可分离卷积,利用深度可分离卷积可以大大减少计算量,具体技术细节本文不做阐述,感兴趣的读者可以去搜索资源自学。SSD是一种检测速度仅次于YOLO的目标检测算法框架,性能也很优越。博主参考chuanqi305的工作,训练了自己的模型。博主将两种方法计算速度进行了对比,测试平台均为CPU为Intel i5-8250U的笔记本电脑:
方法 | 输入图片分辨率 | 帧率 |
shufflenetV2-YOLOV2 | 544x544 | 31 |
mobilenet-SSD | 300x300 | 12 |
检测效果上来看,作者直观上观察mobilenet-SSD算法略优于shufflenetV2-YOLOV2(没有用标准数据集进行对比,因为在实际应用时效果往往和标准集有偏差)。
mobilenet-SSD算法其实是一个神经网络,该神经网络输入是图片,输出是检测结果,包括检测框形状、尺寸、位置以及目标的类别、置信度等。之前已经提到,movidius NCS是一种专门用于计算神经网络的硬件,在本文中movidius NCS是以树莓派为载体的。因此我们只需要将mobilenet-SSD网络转化为movidius NCS可以计算的形式,通过树莓派读取摄像头获取图片,然后传递给movidius NCS,在movidius NCS中运行mobilenet-SSD并返回结果给树莓派即可。
movidius NCS不能直接利用现有的几种深度学习框架(caffe、tensorfloiw等)的训练结果,但是利用movidius NCS的SDK可以将caffe和tensorfloiw文件转化为特有的graph文件,graph文件就是movidius NCS可以识别的神经网络文件。SDK的安装以及使用方法在官方网站中有很详细的说明。为方便广大读者,博主的GitHub中已经上传好了graph文件以及调用graph文件实现检测的python源码。
待续 由于树莓派目前不在身边,目前博主的GitHub中只有目标检测部分的源码,全部源码将会在本文阅读量达到100时上传。博客预计在2019-2-27之前完成更新。