原文在这 finalobject.cn
这个项目是无人车里的一部分,完成激光雷达的驱动,数据采集然后后期的处理以及人型识别,并不涉及车辆硬件的控制。主要分三个大块讲吧,硬件驱动、数据聚类,以及模式识别,本来还想写一写UI部分的,但是感觉自己的UI写的其实蛮简陋的,所有还是不写了,对UI实现有兴趣的自己拔一下源代码吧。
github:https://github.com/finalObject/HumanDetectingOnLidar
这个项目是我大二时候写的,那时候还不会用github,版本记录都是直接备份实现的,所以在源代码里就会出现很多版本的项目,以最新的为准即可。然后里面files里还有一些项目中用到的硬件驱动库,型号资料。项目里有两个main类,带有radar的是连接雷达实时显示的,不带radar的,是把官方软件储存下来的数据文件作为数据来源。两者就是数据来源不一样。
这是程序的截图
使用的传感器是一只小型的激光雷达,型号UTM-30LX-EW,用到的库直接就是官网下载的java库urg_java_lib,另外files还提供了C++/VS版本的驱动库urg_library-1.2.0。驱动激光雷达的代码封装在RadarReader.java中。
这种小的激光雷达一般可以通过USB连接或者网口连接,当时可能是USB连接驱动装不上吧(忘记了),选择的是网口连接,所以在代码直接输入IP地址就可以进行连接。
device = new UrgDevice(new EthernetConnection());
device.connect("192.168.0.10");
RangeSensorInformation info = device.getInformation();
if(info != null){
System.out.println("Sensor model:" + info.product);
System.out.println("Sensor serial number:" + info.serial_number);
}else{
System.out.println("Sensor error:" + device.what());
}
device.setCaptureMode(CaptureSettings.CaptureMode.MD_Capture_mode);
//We set the capture type to a continuous mode so we have to start the capture
device.startCapture();
然后通过
capData= device.capture()
这个函数就可以获取一帧数据,因为返回的CaptureData类,我写了下面的函数把它解析成了一个数组,以方便后面对于数据的使用
public static int[] setDepthsFromRadar(CaptureData data)
这种激光雷达的基础工作模式其实类似于超声波测距,只不过把超声波换成了激光,然后这个传感器还会旋转。这个型号的激光雷达视场角为270度,所以它一帧的数据其实就是不同角度下,激光雷达和最近不透光障碍物之间的距离。data这里存了用官方软件记录下来的数据,txt格式,直接打开看其实也就是一帧一帧的数据,每一帧数据用一些时间之类的标签,主要还是就是一个数组,储存着测量结果。
我这个函数返回的结果就是把一帧里,所有距离储存成一个数据作为结果返回。至此就完成了硬件的驱动和数据采集。
因为要进行模式识别把,必须要有识别的对象,如果需要识别每一帧下,这些数据哪几块是人,哪几块是墙。因为一帧数据是整个数组,首先需要在这个数组中,找出哪几个数据点是一块,属于同一个物体,这之后才能进行模式识别。这个就是聚类。上面那张程序截图里,蓝色点就是数据结果,然后聚类之后认为是同一物体的,用红线连接起来了。
这里聚类我没有用那些传统的聚类算法,原因是这个场景比较简单,为了代码效率,放弃了需要大量迭代的k均值。
场景:这里所有数据都是有顺序的,每一个物体拥有的数据点都是连续的。这些数据都是一维的。
基本分类的原则就是,当连续两个点,距离激光雷达的距离相差大于某个阈值是判定不属于同一类。这个阈值如果手动输入的话就会很鸡肋,所有需要设计一个评价标准,让程序自动选择分类效果好的阈值。
每一个类的数据,应该都非常集中的分布在同一个距离范围内,所以可以用所有类数据的标准差之和,来判断集中程度,但是光是这样不够,因为这样一来,最好的分类结果就是所有点自成一类,标准差就全是0了。所以分类结果中,类的数量也必须足够多。因此我设计一个标准,就是【标准差之和】以及【分类类的数量】加权求和,值越小分类效果越小。这样一来遍历所有阈值,选择最好分类效果的就行,这样就实现的聚类。
用的是libsvm-3.21这个库,官网提供了各种语言的支持。这部分内容其实很简单了,就是从每一类数据中提取有用的特征,然后开始学习就好了。
用到的特征如下:
还有别的参数,但是我具体也说不上来了,自己扒扒代码吧。