思岚雷达rplidar S1配置调试全纪录

耗时10天,终于从零开始用QT在Ubuntu系统下完成了一个雷达避障系统的设计,这文章的主要目的是将配置的流程和遇到的问题记录下来,以供自己以后遇到一样的问题时可以有个参考。

一.思岚雷达的配置

1.配置的基本条件
本次对思岚雷达的配置主要是Ubuntu18.04系统下完成,在Windows下的配置本质和Ubuntu上的大同小异(事实上有现成例程拿来改改就能用),主要是对SDK包的使用+内部函数的调用,别忘了把雷达的波特率调到256000,一头插电源,一头插在主机上,别插反了

特别提醒!新配置的Ubuntu电脑,不要忘记开启串口的权限!!没有权限自然无法打开雷达,你debug到明天也找不到问题!!

  1. SDK包的使用方法
    下载官方的SDK包后(https://download.slamtec.com/api/download/rplidar-sdk/1.11.0?lang=netural),将SDK包在解压到想要的目录下后,在该目录下调用 make 编译,编译后出的东西在SKD包的output 文件夹内,如果你急于测试雷达是否能用,可以把雷达插入USB口后,确认对应的USB口名字后(一般是ttyUSB0),进入 ./output/linux/Release/文件夹,进入终端,输入./ultra_simple ttyUSB0 或者别的(各个小例程都有自己的输入方式,这是其中一种,注意波特率),就能看见终端不断输出雷达发给你的坐标信息,这些小程序基本没有实际的用处,但是可以把里面代码用作参考,也可以用来测试雷达坏了没。
    如果想自己使用这些包,最简单的方法就是将SDK内头文件源文件都包含进去(目录在,SDK/SDK/include和SDK/SDK/src),然后将之前用make 编译出来 共享库 包含进去(目录在output,和可执行文件摆在一起),我使用的是QT,在pro文件内将以上都包含后,在雷达相关的类内添加#include“rplidar.h”即可,其余所有的雷达相关的都包含在里面了。

  2. 使雷达正常使用最起码需要调用的函数
    写在最前,别忘了在雷达有关的源文件中设置好namespace:using namespace rp::standalone::rplidar;

    ①:RPlidarDriver * drv = RPlidarDriver::CreateDriver(DRIVER_TYPE_SERIALPORT);
    该函数可以创造一个雷达对象,做雷达的操作都靠这个类
    ②:drv->connect(path, baud)
    该方法可以建立与雷达的连接,前者是USB口的名字,后是波特率(强烈建议直接写256000),比如默认下,drv->connect(“dev/ttyUSB0”, 2560000) 就行了,会返回一个参数,用IS_OK() 来验证是否连接成功。如果想断开连接就调用 disconnect()方法。
    ③:op_result = drv->getDeviceInfo(devinfo);
    在连接成功后,使用这个函数可以得到一个devinfo类(当然这个类需要事先声明),该类内有雷达的基本属性,可以用这些属性来辨识雷达,当同时使用多个雷达时,实现自动识别。
    devinfo.serialnum[pos]
    devinfo.firmware_version>>8
    devinfo.firmware_version & 0xFF
    (int)devinfo.hardware_version);
    ④:checkRPLIDARHealth(drv)
    在启动前,调用下看看雷达坏了没,正常的使用流程。
    ⑤:drv->startMotor();
    // start scan…
    drv->startScan(0,1);
    // fetech result and print it out…
    以上是标准的开启流程,调用后,雷达电机开始旋转,开始输出雷雷达点。
    另外,drv->stop(); drv->stopMotor();可以关闭雷达,停止扫描
    ⑥: rplidar_response_measurement_node_hq_t nodes[8192];
    size_t count = _countof(nodes);
    op_result = drv->grabScanDataHq(nodes, count,0);
    前两行创造俩个参数,前者是储存雷达点的数组,后者是记录雷达点数的数字(其实直接写8192不就得了?),最后调用方法得到扫描得到的扫描点,值得注意的是,方法的第三个参数是雷达的超时时间,不写就默认的超时时间,如果写个0就会执行非阻塞输出,你什么要什么时候给你,一般用0就满足需求了。

    二.QT程序架构

    1. 大体结构:主要功能分为三块,
      雷达类:专门用来提供与雷达控制相关的方法,虽然本来SDK就给了方便的方法,但是上位机不需要这么细的功能,再次封装下,只留几个需要的功能做成方法,同时由于雷达传输上来的数据是不能直接使用的,所以需要再创一个数组用来储存这些可以直接使用的数据。
      UI类:包含雷达类,设置按钮来调用雷达类的方法,同时获得雷达传上来的数据,在雷达图上画点,直观的表现雷达显示情况。
      多线程处理部分:这是雷达程序最核心的部分,用来实时处理雷达数据,由于处理8000+个点必然需要时间,而雷达图不能有卡顿,所以需要用多线程处理,起码分出俩个线程,一个线程专门获得雷达的数据点,然后进行处理变成可以直接使用的雷达点数据,另外一个不停的检索处理好的数据点,当发现某个特征时(比如某个距离内的点数过多),就发出信号。

    2. 雷达部分:雷达两大任务,一是封装方法,我只留下启、停、连接、断开连接、获得雷达数据等几个方法,内部再加上几个判断,防止出BUG。同时在头文件内声明一个结构,代替原有的雷达点结构,同时添加一个bool usbable属性,如果质量不高或者距离是0的废点,就标记为false,处理时直接略过。内部存有俩个大数组,一个是储存雷达发送的原始数据(note),一个是储存处理后的数据(dian),这俩个数组只有一个类拥有他们的写入权限,其余的只有读取权限,防止多线程下的混乱。

    3. 多线程处理部分:为了避免各个任务间排队导致卡顿,所以只能采用多线程解决问题,所有对雷达数据的处理都放在多线程处,方法采用的是对Qthread继承。一个多线程为leida_thread,不停的读取雷达的数据,然后转化成合适的格式写入dian数组中,另一个多线程为chuli_thread,不停的读取dian数组,通过设定好的逻辑作判定,如果判定出特殊情况,则 emit fasong(int),改变UI界面的部分设置,实现需要的效果。俩个多线程都自带bool isstop判定,如果从外部将isstop改为true,则线程结束。同时多线程与ui或者其他类的通讯采用QT自带的信号槽结构,需要发送信号时使用emit,从而实现对指定类的内部的指定方法的调用,实现类之间的信号传输。

    4. UI部分结构:UI结构是该软件的核心,包含了雷达类和多线程类,但是没有数据的改变权限,只是负责连通和显示。ui通过画图的形式实现对雷达图的绘制,自带定时器,定时器到时间后触发timeout信号,然后连接timertimeout,函数内调用update函数,实现对画面的更新。在初始化的函数中需要完成对雷达类,多线程类的配置,需要准备好和多线程类的对接。

    三.调试中得到的经验

    1.取雷达点认准
    u_result ans=drv->grabScanDataHq(dian,count,0);
    设置超时会导致收到一大堆0,用这个函数已经足够解决绝大多数的问题了。
    2.不需要真的采集8192个点,由于是非阻塞模式,一般也就2000+个点是有数字的,而且最坑爹的是,完成一圈也就是1012个点,之后的1000+个点是类似于记忆点的形式,它会自动判断哪些点是长期存在的,从而在一段时间后记忆下来,如果全部显示到屏幕上就会发生俩套图的现象,如果你只想要实时的图,建议只处理1013个点,之后的点随他去吧。
    3.多线程方面,由于UI类必然是主线程而且不能多线程,所以建议不要过多打断update函数的运转,具体操作比如在chuli_thread线程连接的方法内,不要直接动手修改ui,而是只改变某个参数(比如bool xianshi 这种)具体的ui变化全都放在update函数内执行,这样可以避免不必要的卡顿。
    4.对于这类动则几千个参数的数组,而且大小几乎不变的,个人建议用最简单的数组,而不是容器,在官方的SDK例程中用的是容器,但是在我的架构下频繁清除容器再填充很容易死机,而且还卡,直接用数组同时控制好写入权限,很流畅而且稳定性也高了很多

你可能感兴趣的:(思岚雷达rplidar S1配置调试全纪录)