sick激光器LMS4000软件使用方法以及通信协议数据解析

sick激光器LMS4000软件使用方法以及通信协议数据解析


前言

最近在使用sick激光传感器LMS4000配合机器人获取点云数据,在网上查了几天都没查到这个类型激光器相关的资料,其他类型我看有博文提及过。自己看英文的说明书学习很折磨,因此在初步研究明白部分使用方法后,做一个记录和总结,也希望能帮助一下有和我有相同困扰的工程师,本人第一次写博文,有错误或者表述不清晰的地方希望大家指出,互相交流,一起进步。

我们工作站使用的sick激光器型号是LMS4000,具体的一些安装方法我个人不太了解,如果有想了解这方面的朋友,留言给我,我可以咨询下同事。我们实验站只使用了一台激光器,对多台激光器联合工作的模式也不太了解。因此,以下的内容只针对单台LMS4000在windows操作系统下的软件部分。


一、sick激光传感器软件下载

产品说明地址

在这里插入图片描述
需要下载的说明书和软件都在这里。

在这里插入图片描述
说明书,只有英、德、法三种语言(本人英文水平一般,因此看的我很折磨)。
在这里插入图片描述
软件下载界面。

C++和C的程序库是在github上的,二者是一个文件,应该是SDK,我看了下感觉是需要ROS的,这个我完全不了解,因此我就没使用,大家可以酌情下载,如果有会使用的,可以教教我。

如果想直接使用,下载SOPAS Engineering Tool就可以了,下载完成后直接解压即可;SDD文件也需要下载,下载完成后放在软件同一目录下,软件内需要时配置即可。
在这里插入图片描述
也可以在Sopas软件内部下载SDD文件,那种方式好像更容易些,但是我当时配置的时候忘记截图了。
以上就是软件的部分准备工作,下面讲一下软件的使用方法。

二、软件使用方法

如果使用场景比较简单,可以直接参考此章,如果使用场景较复杂,建议还是查看说明书的第3章和第7章。

1.设置网段以及登录设备

首先将激光器通过网线与自身电脑相连,为了能顺利连接上设备,要修改电脑的IP地址与设备在同一个网段,我是按照同事的指导配置的,这里就不细说了,放一张截图供大家参考吧。
在这里插入图片描述
通过网线正确连接上设备之后就可以登陆了,右键点击想要使用的设备,如图所示。
请添加图片描述
登录的时候选择相应的用户级别,我这里选的是“授权的用户”,密码在说明书的第7章7.1节,登录成功后点击设备右上角的三个点。
在这里插入图片描述
主界面上左侧显示一些设备信息,右侧就是当前角度范围内激光器采集到的点,红色框的地方是对显示模式进行修改,可以根据需要自行查看。
在这里插入图片描述

2.基础设置以及应用

在这里插入图片描述
基础设置里会有一些频率、角度分辨率、测量角度之类的量,它们中部分可以在后面应用界面修改。激光控制有自由采集、软触发、硬触发等,我只用过自由采集和软触发。自由采集情况下,激光会常亮,上面开始测量停止测量的选项也会消失,相当于一直处于开始测量状态;软触发情况下,开始测量的时候激光器亮,停止测量和待机情况下激光器不亮。
我在测试过程中发现了一个事情:
1、从开始测量状态切换到待机状态再切换回开始测量状态,激光器会由亮到关闭再到亮;
2、从开始测量状态切换到停止测量状态再切换回开始测量状态,激光器由亮到关闭,切换回来的时候也不会亮,要想让激光器有光,需要停止测量后切换两次待机状态再切换回开始测量状态,即停止—待机—开始—待机—开始,激光器才会亮。
在这里插入图片描述
这个应该是时间戳,我没用到,所以没做设置,就不细说了。
下面说应用界面。
在这里插入图片描述
这个是一些激光器的扫描设置和预处理,我使用此激光器只是为了取点云,点云处理会后续处理,因此我对中间那些滤波器的选择比较随意,需要设置这些的朋友还得阅读下说明书。这个界面我主要就是设置开始终止角度以及最下面的角度分辨率。
请添加图片描述
下面是数据输出格式。我只需要距离、角度、码值(Encoder),设置好让它们以数字格式输出即可。
最下面是扫描的一些设置,设置好扫描时间和码值,相机的支架带着相机运动并点击开始,就可以得到一幅点云了,点云内的数据单位是m,我比较喜欢用mm,因此我在处理过程中会将其×1000。
这里需要注意的是,
1、软件里的扫描时间最长只有10s,如果需要更长时间的数据,就需要调用SDK的接口或者自己写程序与激光器通信(3.2节会讲)
2、保存后的pcd文件,无法直接用点云显示软件打开,以CloudCompare为例,打开pcd文件的时候会报错,需要人为修改一下pcd文件,将这四个多余的部分删除即可。
在这里插入图片描述
3、保存的pcd文件的坐标轴不是右手系的,无法用于后续标定等步骤,因此我在处理的时候,重新构建了相机坐标系,以激光线的方向为x轴,高度方向为z轴,垂直于此二轴且码值变化的方向为y轴。pcd文件中是按照x、z、y的坐标进行存储的。
4、按照3中的方法转换点云后,x、z方向上坐标值与真实空间中的值基本一样了,但是y方向的值仍然与真实空间中距离有偏差,这是因为码值分辨率导致的,这个的调整方法在2.4节中说。

3.外部接口设置以及配置

请添加图片描述
左侧应该是激光硬触发的接口,我暂时未使用到,不在此细说了。右侧上方是IP地址,下面是TCP通信的端口。
请添加图片描述
上图中,我只设置过编码器的值,别的都没改过,编码器的增加方式选择如图所示,将相机的支架移动到一个初始的位置,将码值置0(保证移动后码值增加),相当于此位置即为相机坐标系y轴的零点,后续采集的时候,可以记录起始点的码值,获取点云后通过码值的比例和起始点码值得到当次采集的点在相机坐标系下的位置。如果10s的扫描时间可以满足你实验的需求,码值设置不设置都不会有影响。
请添加图片描述
前面的参数都设置好后,就可以点击“save permanently”保存了,后面再打开软件,默认使用上次保存的参数。

4.码值与距离的比例以及码值分辨率

首先采集两组点云,分别记录它们的起始点码值和空间中的距离,两个起点的距离尽量远一些,这样求出来的比例尺比较准确,用码值除以距离可以得到一个比例尺。举个例子,第一次扫描的起始点码值为977,第二次扫描的起始码值为5932,它们的空间距离为1800mm,比例尺即为

1800 / (5932 - 977) = 0.36326942

码值分辨率就是单次扫描的点云内部的比例。点云内某一点与扫描起点的距离:当前坐标值 × 0.36326942×10×1000,单位是mm。

第二章部分章节拖了一个月才补上,一些细节确实记忆不够深刻,如有错误,欢迎指正

三、通信协议解析

通信协议的下载地址和说明书一样,它就在说明书的下面。
PS:这个通信协议的文档是针对所有产品的,“×”的代表对应产品有此项功能。

1.通过socketTool通信

由于我自己不会写TCP通信,但是我还想先解析通信协议,所以先用通信助手获取应答数据。

我们是作为客户端,也就是TCP client,设置好IP和端口,按照上述截图,我这边输入“192.168.3.201”和“2112”,点击连接后,即可完成连接。

接下来发送一些简单的指令,看看应答数据如何(只看十六进制部分)。
以Authorized client登录:

发送数据:{02 73 4D 4E 20 53 65 74 41 63 63 65 73 73 4D 6F 64 65 20 30 33 20 46 34 37 32 34 37 34 34 03 }sMN SetAccessMode 03 F4724744[1]
收到数据:{02 73 41 4E 20 53 65 74 41 63 63 65 73 73 4D 6F 64 65 20 31 03 }sAN SetAccessMode 1

与通信协议对照后发现一样,Start measurement、Stop measurement、Stand by状态的应答也是固定的,不在此赘述了。

读取频率和角分辨率:

发送数据:{02 73 52 4E 20 4C 4D 50 73 63 61 6E 63 66 67 03 }sRN LMPscancfg[1]
收到数据:{02 73 52 41 20 4C 4D 50 73 63 61 6E 63 66 67 20 45 41 36 30 20 31 20 33 34 31 20 38 36 34 37 30 20 31 33 31 32 44 30 03 }sRA LMPscancfg EA60 1 341 86470 1312D0

EA60 就代表600HZ,即频率;341代表1/12°,即角度分辨率;86470 是LMS4000的起始角度(这个是产品本身的参数,不是人为设置的,而且通信协议上应该是写错了),即55°;1312D0是LMS4000的终止角度,即125°。

读取实际输出范围(当前设置65°-108°):

发送数据:{02 73 52 4E 20 4C 4D 50 6F 75 74 70 75 74 52 61 6E 67 65 03 }sRN LMPoutputRange[1]
收到数据:{02 73 52 41 20 4C 4D 50 6F 75 74 70 75 74 52 61 6E 67 65 20 31 20 33 34 31 20 39 45 42 31 30 20 31 30 37 41 43 30 03 }sRA LMPoutputRange 1 341 9EB10 107AC0

341代表1/12°,即角度分辨率;9EB10是自己设置的起始角度,即65°;107AC0是自己设置的终止角度,即108°。

上面的测试让我对通信协议有了基础的了解,接下来就是解析单帧数据。
使用通信协议说明4.3.6的poll one telegram获取单帧数据:

发送数据:{02 73 52 4E 20 4C 4D 44 73 63 61 6E 64 61 74 61 03 }sRN LMDscandata[1]
收到数据:{02 73 52 41 20 4C 4D 44 73 63 61 6E 64 61 74 61 20 31 20 31 20 31 33 36 41 43 37 44 20 31 20 30 20 35 41 39 38 20 42 35 32 38 20 41 34 37 44 42 43 36 30 20 41 34 37 44 43 30 35 35 20 30 20 30 20 38 20 30 20 30 20 45 41 36 30 20 32 31 43 30 20 31 20 42 34 39 20 30 20 32 20 44 49 53 54 31 20 33 44 43 43 43 43 43 44 20 30 30 30 30 30 30 30 30 20 39 45 42 31 30 20 33 34 31 20 32 30 35 20 30 20 36 45 37 36 20 35 34 35 37 20 35 34 35 37 20 35 34 36 33 20 35 34 41 43 20 35 35 32 34 20 35 35 32 30 20 35 35 42 30 20 35 35 45 30 20 35 36 31 38 20 35 36 39 31 20 35 36 42 32 20 35 37 35 34 20 35 37 38 36 20 35 37 42 41 20 35 37 45 36 20 35 37 45 32 20 35 37 44 37 20 35 37 43 46 20 35 37 42 45 20 35 37 42 31 20 35 37 41 34 20 35 37 39 36 20 35 37 37 46 20 35 37 37 37 20 35 37 36 44 20 35 37 36 30 20 35 37 35 34 20 35 37 34 43 20 35 37 33 38 20 35 37 32 44 20 35 37 31 46 20 35 37 31 36 20 35 37 30 32 20 35 36 46 39 20 35 36 45 46 20 35 36 45 33 20 35 36 44 39 20 35 36 43 41 20 35 36 42 44 20 35 36 42 31 20 35 36 41 31 20 35 36 39 35 20 35 36 38 41 20 35 36 38 30 20 35 36 37 35 20 35 36 36 37 20 35 36 36 30 20 35 36 35 32 20 35 36 34 41 20 35 36 34 30 20 35 36 32 44 20 35 36 32 35 20 35 36 31 32 20 35 36 30 43 20 35 36 30 34 20 35 35 46 34 20 35 35 45 36 20 35 35 44 45 20 35 35 44 32 20 35 35 43 33 20 35 35 42 46 20 35 35 42 36 20 35 35 41 37 20 35 35 39 41 20 35 35 39 30 20 35 35 37 45 20 35 35 37 38 20 35 35 37 31 20 35 35 36 31 20 35 35 35 38 20 35 35 35 31 20 35 34 35 34 20 35 31 31 30 20 35 31 31 32 20 35 31 30 39 20 35 31 30 38 20 35 31 30 41 20 35 31 35 38 20 35 32 36 33 20 35 32 41 37 20 35 33 31 46 20 35 33 33 33 20 35 33 37 41 20 35 33 45 35 20 35 34 33 46 20 35 34 36 37 20 35 34 38 36 20 35 34 39 35 20 35 34 39 43 20 35 34 39 39 20 35 34 38 45 20 35 34 38 32 20 35 34 37 32 20 35 34 36 39 20 35 34 36 31 20 35 34 35 45 20 35 34 35 33 20 35 34 34 42 20 35 34 34 34 20 35 34 33 39 20 35 34 33 31 20 35 34 32 37 20 35 34 31 46 20 35 34 31 42 20 35 34 31 30 20 35 34 30 39 20 35 33 46 46 20 35 33 46 38 20 35 33 45 44 20 35 33 45 38 20 35 33 45 31 20 35 33 44 31 20 35 33 43 38 20 35 33 43 34 20 35 33 42 44 20 35 33 42 36 20 35 33 41 43 20 35 33 41 30 20 35 33 39 38 20 35 33 38 46 20 35 33 38 39 20 35 33 38 32 20 35 33 37 44 20 35 33 37 34 20 35 33 36 45 20 35 33 36 38 20 35 33 36 30 20 35 33 35 41 20 35 33 35 34 20 35 33 34 38 20 35 33 34 31 20 35 33 33 42 20 35 33 33 33 20 35 33 32 43 20 35 33 32 36 20 35 33 32 31 20 35 33 31 39 20 35 33 31 31 20 35 33 30 38 20 35 33 30 32 20 35 32 46 43 20 35 32 46 34 20 35 32 45 44 20 35 32 45 36 20 35 32 44 43 20 35 32 44 36 20 35 32 44 30 20 35 32 43 44 20 35 32 43 41 20 35 32 43 34 20 35 32 42 44 20 35 32 42 35 20 35 32 41 43 20 35 32 41 37 20 35 32 41 31 20 35 32 39 43 20 35 32 39 34 20 35 32 38 46 20 35 32 38 38 20 35 32 38 31 20 35 32 37 41 20 35 32 37 35 20 35 32 36 45 20 35 32 36 37 20 35 32 36 35 20 35 32 35 46 20 35 32 35 41 20 35 32 35 33 20 35 32 34 45 20 35 32 34 42 20 35 32 34 37 20 35 32 33 46 20 35 32 33 38 20 35 32 33 35 20 35 32 32 42 20 35 32 32 36 20 35 32 32 34 20 35 32 31 46 20 35 32 31 42 20 35 32 31 35 20 35 32 31 31 20 35 32 30 44 20 35 32 30 37 20 35 32 30 31 20 35 31 46 42 20 35 31 46 36 20 35 31 46 35 20 35 31 46 30 20 35 31 45 44 20 35 31 45 36 20 35 31 45 33 20 35 31 44 46 20 35 31 44 42 20 35 31 44 33 20 35 31 43 46 20 35 31 43 45 20 35 31 43 39 20 35 31 43 32 20 35 31 42 45 20 35 31 42 39 20 35 31 42 36 20 35 31 42 35 20 35 31 42 32 20 35 31 41 44 20 35 31 41 38 20 35 31 41 36 20 35 31 41 33 20 35 31 39 45 20 35 31 39 38 20 35 31 39 33 20 35 31 39 33 20 35 31 39 30 20 35 31 38 43 20 35 31 38 37 20 35 31 38 33 20 35 31 37 44 20 35 31 32 39 20 34 46 35 37 20 34 46 32 37 20 34 46 32 32 20 34 46 32 30 20 34 46 31 42 20 34 46 31 36 20 34 46 31 30 20 34 46 30 43 20 34 46 30 36 20 34 46 30 33 20 34 46 30 31 20 34 46 30 32 20 34 46 30 30 20 34 45 46 46 20 34 45 46 44 20 30 20 33 34 34 31 20 33 34 30 31 20 33 33 44 44 20 33 33 43 31 20 33 33 42 34 20 33 33 41 45 20 33 33 41 38 20 33 33 41 31 20 33 33 39 36 20 33 33 38 35 20 33 33 38 34 20 33 33 37 45 20 33 33 37 41 20 33 33 37 37 20 33 33 37 30 20 33 33 36 39 20 33 33 36 35 20 33 33 35 41 20 33 33 35 38 20 33 33 35 32 20 33 33 34 39 20 33 33 34 37 20 33 33 33 46 20 33 33 33 41 20 33 33 33 42 20 33 33 33 43 20 33 33 33 38 20 33 33 33 38 20 33 33 33 35 20 33 33 33 35 20 33 33 33 35 20 33 33 34 31 20 33 33 35 32 20 33 33 35 46 20 33 33 36 44 20 33 33 38 35 20 33 33 39 43 20 33 33 44 45 20 33 34 31 34 20 33 34 35 45 20 33 34 39 41 20 33 35 30 35 20 33 35 31 44 20 33 35 34 38 20 33 35 43 35 20 33 36 30 38 20 33 36 35 35 20 33 36 38 30 20 33 36 42 30 20 35 30 45 32 20 35 30 45 42 20 35 30 46 30 20 35 30 46 35 20 35 30 46 36 20 35 30 46 37 20 35 30 46 37 20 35 30 46 37 20 35 30 46 36 20 35 30 46 36 20 35 30 46 37 20 35 30 46 36 20 35 30 46 36 20 35 30 46 35 20 35 30 46 35 20 35 30 46 35 20 35 30 46 36 20 35 30 46 36 20 35 30 46 35 20 35 30 46 36 20 35 30 46 43 20 30 20 32 46 46 30 20 33 30 30 35 20 33 30 30 41 20 32 46 46 42 20 33 30 30 31 20 32 46 46 39 20 32 46 45 45 20 32 46 46 35 20 32 46 45 42 20 32 46 45 31 20 32 46 44 36 20 32 46 43 46 20 32 46 44 30 20 32 46 44 32 20 32 46 44 33 20 32 46 44 33 20 32 46 43 46 20 32 46 44 30 20 32 46 44 46 20 32 46 45 36 20 32 46 45 42 20 32 46 46 31 20 32 46 46 43 20 33 30 30 44 20 33 30 31 46 20 33 30 33 33 20 33 30 34 43 20 33 30 35 44 20 33 30 36 33 20 30 20 33 39 31 34 20 33 39 31 33 20 33 39 31 41 20 33 39 32 38 20 33 39 32 38 20 33 39 32 38 20 33 39 32 44 20 33 39 32 39 20 33 39 32 42 20 33 39 32 41 20 33 39 32 46 20 33 39 33 30 20 33 39 32 45 20 33 39 32 44 20 33 39 32 44 20 33 39 32 44 20 33 39 33 32 20 33 39 33 30 20 33 39 32 43 20 33 39 32 41 20 33 39 32 45 20 33 39 33 35 20 33 39 33 38 20 33 39 33 36 20 33 39 33 41 20 33 39 33 41 20 33 39 33 42 20 33 39 33 43 20 33 39 33 44 20 33 39 33 46 20 33 39 33 45 20 33 39 34 32 20 33 39 34 38 20 33 39 34 43 20 33 39 35 35 20 33 39 35 36 20 33 39 36 31 20 33 41 46 46 20 33 43 36 33 20 33 43 36 37 20 33 43 36 41 20 33 43 36 42 20 33 43 36 44 20 33 43 36 45 20 33 43 37 30 20 33 43 37 30 20 33 43 37 32 20 33 43 37 35 20 33 43 37 38 20 33 43 37 41 20 33 43 37 43 20 33 43 37 45 20 33 43 38 30 20 33 43 38 31 20 33 43 38 32 20 33 43 38 44 20 34 30 44 46 20 34 30 45 32 20 34 30 45 38 20 34 30 45 45 20 34 30 46 30 20 34 30 44 34 20 34 30 35 38 20 34 30 34 32 20 34 30 34 30 20 34 30 34 30 20 34 30 34 31 20 34 30 35 34 20 34 30 43 44 20 34 30 43 35 20 34 30 44 35 20 34 39 36 39 20 35 31 44 32 20 35 31 45 44 20 35 31 46 39 20 35 32 30 32 20 35 32 30 45 20 35 32 31 31 20 35 32 31 34 20 35 32 31 39 20 35 32 32 31 20 35 32 32 41 20 35 32 32 46 20 35 32 33 33 20 35 32 33 41 20 35 32 33 45 20 35 32 34 34 20 35 32 34 41 20 35 32 34 45 20 35 32 35 35 20 35 32 35 42 20 35 32 36 30 20 35 32 36 36 20 35 32 36 42 20 35 32 37 33 20 35 32 37 36 20 35 32 37 38 20 35 32 37 43 20 35 32 38 34 20 35 32 38 44 20 35 32 39 33 20 35 32 39 44 20 35 32 41 35 20 35 32 41 37 20 35 32 41 41 20 35 32 42 32 20 35 32 42 42 20 35 32 43 34 20 35 32 43 36 20 35 32 43 42 20 35 32 44 32 20 35 32 45 32 20 35 32 45 36 20 35 32 45 43 20 35 32 46 33 20 35 32 46 36 20 35 33 30 30 20 35 33 30 39 20 35 33 31 30 20 35 33 31 33 20 35 33 31 42 20 35 33 32 34 20 35 33 32 42 20 35 33 33 34 20 35 33 33 45 20 35 33 34 35 20 35 33 34 44 20 35 33 35 33 20 35 33 35 37 20 35 33 35 34 20 35 33 33 42 20 35 33 30 45 20 35 32 42 41 20 35 32 32 44 20 35 32 30 36 20 35 31 43 45 20 30 20 34 46 41 45 20 34 46 41 31 20 34 46 39 39 20 35 32 36 42 20 35 33 43 31 20 35 33 43 31 20 35 37 36 30 20 36 43 45 33 20 36 43 45 43 20 36 43 46 31 20 36 43 46 39 20 36 44 30 42 20 36 44 31 39 20 36 44 32 34 20 36 44 32 44 20 36 44 33 42 20 36 44 34 33 20 36 44 34 44 20 36 44 35 36 20 36 44 36 38 20 36 44 37 30 20 36 44 38 32 20 36 44 38 36 20 36 44 39 41 20 36 44 39 46 20 36 44 41 33 20 36 44 39 43 20 36 44 38 44 20 36 44 42 30 20 36 44 44 32 20 36 44 45 38 20 36 44 46 37 20 36 45 30 32 20 36 45 31 31 20 36 45 31 46 20 36 45 32 46 20 36 45 33 43 20 36 45 34 31 20 36 45 34 45 20 36 45 35 39 20 36 45 36 43 20 36 45 37 45 20 36 45 38 36 20 30 20 41 4E 47 4C 31 20 33 46 38 30 30 30 30 30 20 43 37 30 30 30 30 30 30 20 39 45 42 31 30 20 33 34 31 20 32 30 35 20 37 45 37 43 20 37 45 37 43 20 37 45 37 44 20 37 45 34 41 20 37 45 34 42 20 37 45 34 43 20 37 45 34 45 20 37 45 34 46 20 37 45 35 31 20 37 45 35 33 20 37 45 35 34 20 37 45 35 36 20 37 45 35 38 20 37 45 35 41 20 37 45 35 42 20 37 45 35 44 20 37 45 35 45 20 37 45 35 46 20 37 45 36 30 20 37 45 36 30 20 37 45 36 31 20 37 45 36 32 20 37 45 36 32 20 37 45 36 34 20 37 45 36 34 20 37 45 36 35 20 37 45 36 36 20 37 45 36 37 20 37 45 36 38 20 37 45 36 38 20 37 45 36 39 20 37 45 36 41 20 37 45 36 42 20 37 45 36 43 20 37 45 36 44 20 37 45 36 45 20 37 45 36 45 20 37 45 36 46 20 37 45 37 30 20 37 45 37 31 20 37 45 37 32 20 37 45 37 33 20 37 45 37 33 20 37 45 37 34 20 37 45 37 35 20 37 45 37 36 20 37 45 37 37 20 37 45 37 38 20 37 45 37 39 20 37 45 37 41 20 37 45 37 42 20 37 45 37 43 20 37 45 37 43 20 37 45 37 44 20 37 45 37 45 20 37 45 37 46 20 37 45 38 30 20 37 45 38 31 20 37 45 38 32 20 37 45 38 33 20 37 45 38 34 20 37 45 38 34 20 37 45 38 35 20 37 45 38 36 20 37 45 38 37 20 37 45 38 38 20 37 45 38 39 20 37 45 38 41 20 37 45 38 42 20 37 45 38 43 20 37 45 38 44 20 37 45 38 45 20 37 45 38 46 20 37 45 39 30 20 37 45 39 30 20 37 45 38 42 20 37 45 38 42 20 37 45 38 43 20 37 45 38 44 20 37 45 38 45 20 37 45 39 31 20 37 45 39 32 20 37 45 39 34 20 37 45 39 36 20 37 45 39 38 20 37 45 39 41 20 37 45 39 42 20 37 45 39 43 20 37 45 39 44 20 37 45 39 46 20 37 45 41 30 20 37 45 41 31 20 37 45 41 32 20 37 45 41 33 20 37 45 41 34 20 37 45 41 35 20 37 45 41 36 20 37 45 41 37 20 37 45 41 38 20 37 45 41 39 20 37 45 41 41 20 37 45 41 42 20 37 45 41 43 20 37 45 41 44 20 37 45 41 45 20 37 45 41 46 20 37 45 42 30 20 37 45 42 31 20 37 45 42 32 20 37 45 42 33 20 37 45 42 34 20 37 45 42 35 20 37 45 42 36 20 37 45 42 37 20 37 45 42 38 20 37 45 42 39 20 37 45 42 41 20 37 45 42 42 20 37 45 42 43 20 37 45 42 44 20 37 45 42 45 20 37 45 42 46 20 37 45 43 30 20 37 45 43 31 20 37 45 43 32 20 37 45 43 33 20 37 45 43 34 20 37 45 43 35 20 37 45 43 36 20 37 45 43 37 20 37 45 43 38 20 37 45 43 39 20 37 45 43 41 20 37 45 43 42 20 37 45 43 43 20 37 45 43 44 20 37 45 43 45 20 37 45 43 46 20 37 45 44 30 20 37 45 44 31 20 37 45 44 33 20 37 45 44 34 20 37 45 30 34 20 37 45 44 36 20 37 45 44 36 20 37 45 30 37 20 37 45 30 38 20 37 45 30 39 20 37 45 30 41 20 37 45 30 42 20 37 45 30 44 20 37 45 30 44 20 37 45 30 46 20 37 45 30 46 20 37 45 31 31 20 37 45 31 32 20 37 45 31 33 20 37 45 31 34 20 37 45 31 35 20 37 45 31 36 20 37 45 31 37 20 37 45 31 38 20 37 45 31 39 20 37 45 31 41 20 37 45 31 42 20 37 45 31 43 20 37 45 31 44 20 37 45 31 45 20 37 45 31 46 20 37 45 32 30 20 37 45 32 31 20 37 45 32 32 20 37 45 32 33 20 37 45 32 34 20 37 45 32 35 20 37 45 32 36 20 37 45 32 37 20 37 45 32 38 20 37 45 32 39 20 37 45 32 41 20 37 45 32 42 20 37 45 32 43 20 37 45 32 44 20 37 45 32 45 20 37 45 33 30 20 37 45 33 31 20 37 45 33 32 20 37 45 33 33 20 37 45 33 34 20 37 45 33 35 20 37 45 33 36 20 37 45 33 37 20 37 45 33 38 20 37 45 33 39 20 37 45 33 41 20 37 45 33 42 20 37 45 33 43 20 37 45 33 44 20 37 45 33 45 20 37 45 33 46 20 37 45 34 30 20 37 45 34 31 20 37 45 34 32 20 37 45 34 33 20 37 45 34 34 20 37 45 34 35 20 37 45 34 36 20 37 45 34 37 20 37 45 34 38 20 37 45 34 39 20 37 45 34 41 20 37 45 34 42 20 37 45 34 43 20 37 45 34 44 20 37 45 34 45 20 37 45 34 46 20 37 45 35 30 20 37 45 35 31 20 37 45 35 32 20 37 45 35 33 20 37 45 35 33 20 37 45 35 33 20 37 45 35 34 20 37 45 35 35 20 37 45 35 37 20 37 45 35 38 20 37 45 35 38 20 37 45 35 39 20 37 45 35 41 20 37 45 35 42 20 37 45 35 43 20 37 45 35 44 20 37 45 35 46 20 37 45 36 30 20 37 45 36 31 20 37 45 38 36 20 37 45 35 30 20 37 45 35 31 20 37 45 35 32 20 37 45 35 33 20 37 45 35 34 20 37 45 35 36 20 37 45 35 37 20 37 45 35 38 20 37 45 35 41 20 37 45 35 42 20 37 45 35 43 20 37 45 35 44 20 37 45 35 46 20 37 45 36 30 20 37 45 36 31 20 37 45 36 32 20 37 45 36 34 20 37 45 36 35 20 37 45 36 36 20 37 45 36 37 20 37 45 36 39 20 37 45 36 41 20 37 45 36 42 20 37 45 36 43 20 37 45 36 44 20 37 45 36 46 20 37 45 37 30 20 37 45 37 31 20 37 45 37 32 20 37 45 37 34 20 37 45 37 35 20 37 45 37 36 20 37 45 37 37 20 37 45 37 38 20 37 45 37 41 20 37 45 37 42 20 37 45 37 43 20 37 45 37 44 20 37 45 37 46 20 37 45 38 30 20 37 45 38 31 20 37 45 38 33 20 37 45 38 34 20 37 45 38 35 20 37 45 38 36 20 37 45 38 37 20 37 45 38 38 20 37 45 38 41 20 37 45 38 42 20 37 45 38 46 20 37 45 39 30 20 37 45 39 31 20 37 45 39 32 20 37 45 39 33 20 37 45 39 33 20 37 45 39 34 20 37 45 39 35 20 37 45 39 36 20 37 45 39 37 20 37 45 39 38 20 37 45 39 38 20 37 45 39 39 20 37 45 39 41 20 37 45 39 42 20 37 44 43 42 20 37 44 43 43 20 37 44 43 44 20 37 44 43 44 20 37 44 43 45 20 37 44 43 46 20 37 44 43 44 20 37 44 44 32 20 37 44 44 33 20 37 44 44 34 20 37 44 44 35 20 37 44 44 36 20 37 44 44 37 20 37 44 44 38 20 37 44 44 39 20 37 44 44 41 20 37 44 44 42 20 37 44 44 43 20 37 44 44 44 20 37 44 44 45 20 37 44 44 46 20 37 44 45 30 20 37 44 45 31 20 37 44 45 32 20 37 44 45 33 20 37 44 45 34 20 37 44 45 35 20 37 44 45 36 20 37 44 45 37 20 37 44 45 38 20 37 44 45 39 20 37 44 45 39 20 37 44 45 41 20 37 44 45 42 20 37 44 45 43 20 37 44 45 44 20 37 44 45 43 20 37 44 45 42 20 37 44 45 43 20 37 44 45 44 20 37 44 45 44 20 37 44 45 45 20 37 44 45 46 20 37 44 46 30 20 37 44 46 30 20 37 44 46 31 20 37 44 46 32 20 37 44 46 33 20 37 44 46 33 20 37 44 46 34 20 37 44 46 35 20 37 44 46 35 20 37 44 46 36 20 37 44 46 37 20 37 44 46 37 20 37 44 46 38 20 37 44 46 39 20 37 44 46 39 20 37 44 46 41 20 37 44 46 41 20 37 44 46 42 20 37 44 46 43 20 37 44 46 43 20 37 44 46 44 20 37 44 46 44 20 37 44 46 45 20 37 44 46 46 20 37 44 46 46 20 37 45 30 30 20 37 45 30 30 20 37 45 30 31 20 37 45 30 32 20 37 45 30 32 20 37 45 30 32 20 37 45 30 32 20 37 45 30 32 20 37 45 30 33 20 37 45 30 33 20 37 45 30 34 20 37 45 30 34 20 37 45 30 35 20 37 45 30 35 20 37 45 30 35 20 37 45 30 36 20 37 45 30 36 20 37 45 30 37 20 37 45 30 37 20 37 45 30 38 20 37 45 30 38 20 37 45 30 38 20 37 45 30 39 20 37 45 30 39 20 37 45 30 38 20 37 45 30 38 20 37 45 30 38 20 37 45 30 39 20 37 45 30 39 20 37 45 30 39 20 37 45 30 41 20 37 45 30 41 20 37 45 30 42 20 37 45 30 42 20 37 45 30 43 20 37 45 30 43 20 37 45 30 43 20 37 45 30 43 20 37 45 30 43 20 37 45 30 43 20 37 44 46 30 20 37 45 30 37 20 37 45 30 37 20 37 45 30 38 20 37 45 30 38 20 37 45 30 38 20 37 45 30 39 20 37 45 30 39 20 37 45 30 39 20 37 45 30 39 20 37 45 30 41 20 37 45 30 41 20 37 45 30 41 20 37 45 30 41 20 37 45 30 42 20 37 45 30 42 20 37 45 30 42 20 37 45 30 42 20 37 45 30 42 20 37 45 30 43 20 37 45 30 43 20 37 45 30 43 20 37 45 30 43 20 37 45 30 43 20 37 45 30 43 20 37 45 30 44 20 37 45 30 44 20 37 45 30 44 20 37 45 30 44 20 37 45 30 44 20 37 45 30 44 20 37 45 30 44 20 37 45 30 44 20 37 45 30 45 20 37 45 30 45 20 37 45 30 45 20 37 45 30 45 20 37 45 30 45 20 37 45 30 45 20 37 45 30 45 20 37 45 30 45 20 37 45 30 45 20 37 45 30 45 20 37 45 30 45 20 37 44 33 45 20 37 45 30 45 20 37 45 30 45 20 37 44 33 45 20 37 44 33 45 20 37 44 33 45 20 37 44 33 45 20 37 44 33 45 20 37 44 33 45 20 37 44 33 45 20 37 44 33 45 20 37 44 33 45 20 37 44 33 45 20 37 44 33 45 20 37 45 30 45 20 37 45 30 45 20 37 45 30 45 20 37 45 30 45 20 37 45 30 45 20 37 45 30 45 20 37 45 30 45 20 37 45 30 45 20 37 45 30 45 20 37 45 30 45 20 37 45 30 45 20 37 45 30 45 20 37 45 30 44 20 37 44 33 44 20 37 45 30 43 20 37 45 30 43 20 37 44 33 43 20 37 44 33 43 20 37 45 30 43 20 37 44 33 42 20 37 44 33 42 20 37 44 33 42 20 37 44 33 42 20 37 44 33 42 20 37 44 33 42 20 37 44 33 42 20 37 44 33 42 20 37 44 33 42 20 37 44 33 42 20 37 44 33 42 20 37 44 33 42 20 37 44 33 42 20 37 44 33 41 20 37 44 33 41 20 37 44 33 41 20 37 44 33 41 20 37 44 33 41 20 37 44 33 41 20 37 44 33 41 20 37 44 33 41 20 37 44 33 39 20 37 44 33 39 20 37 44 33 39 20 37 44 33 39 20 37 44 33 39 20 37 44 33 39 20 37 44 33 39 20 37 44 33 38 20 37 44 33 38 20 37 44 33 38 20 37 44 33 38 20 30 20 30 20 30 20 30 20 30 20 30 03 }sRA LMDscandata 1 1 136AC7D 1 0 5A98 B528 A47DBC60 A47DC055 0 0 8 0 0 EA60 21C0 1 B49 0 2 DIST1 3DCCCCCD 00000000 9EB10 341 205 0 6E76 5457 5457 5463 54AC 5524 5520 55B0 55E0 5618 5691 56B2 5754 5786 57BA 57E6 57E2 57D7 57CF 57BE 57B1 57A4 5796 577F 5777 576D 5760 5754 574C 5738 572D 571F 5716 5702 56F9 56EF 56E3 56D9 56CA 56BD 56B1 56A1 5695 568A 5680 5675 5667 5660 5652 564A 5640 562D 5625 5612 560C 5604 55F4 55E6 55DE 55D2 55C3 55BF 55B6 55A7 559A 5590 557E 5578 5571 5561 5558 5551 5454 5110 5112 5109 5108 510A 5158 5263 52A7 531F 5333 537A 53E5 543F 5467 5486 5495 549C 5499 548E 5482 5472 5469 5461 545E 5453 544B 5444 5439 5431 5427 541F 541B 5410 5409 53FF 53F8 53ED 53E8 53E1 53D1 53C8 53C4 53BD 53B6 53AC 53A0 5398 538F 5389 5382 537D 5374 536E 5368 5360 535A 5354 5348 5341 533B 5333 532C 5326 5321 5319 5311 5308 5302 52FC 52F4 52ED 52E6 52DC 52D6 52D0 52CD 52CA 52C4 52BD 52B5 52AC 52A7 52A1 529C 5294 528F 5288 5281 527A 5275 526E 5267 5265 525F 525A 5253 524E 524B 5247 523F 5238 5235 522B 5226 5224 521F 521B 5215 5211 520D 5207 5201 51FB 51F6 51F5 51F0 51ED 51E6 51E3 51DF 51DB 51D3 51CF 51CE 51C9 51C2 51BE 51B9 51B6 51B5 51B2 51AD 51A8 51A6 51A3 519E 5198 5193 5193 5190 518C 5187 5183 517D 5129 4F57 4F27 4F22 4F20 4F1B 4F16 4F10 4F0C 4F06 4F03 4F01 4F02 4F00 4EFF 4EFD 0 3441 3401 33DD 33C1 33B4 33AE 33A8 33A1 3396 3385 3384 337E 337A 3377 3370 3369 3365 335A 3358 3352 3349 3347 333F 333A 333B 333C 3338 3338 3335 3335 3335 3341 3352 335F 336D 3385 339C 33DE 3414 345E 349A 3505 351D 3548 35C5 3608 3655 3680 36B0 50E2 50EB 50F0 50F5 50F6 50F7 50F7 50F7 50F6 50F6 50F7 50F6 50F6 50F5 50F5 50F5 50F6 50F6 50F5 50F6 50FC 0 2FF0 3005 300A 2FFB 3001 2FF9 2FEE 2FF5 2FEB 2FE1 2FD6 2FCF 2FD0 2FD2 2FD3 2FD3 2FCF 2FD0 2FDF 2FE6 2FEB 2FF1 2FFC 300D 301F 3033 304C 305D 3063 0 3914 3913 391A 3928 3928 3928 392D 3929 392B 392A 392F 3930 392E 392D 392D 392D 3932 3930 392C 392A 392E 3935 3938 3936 393A 393A 393B 393C 393D 393F 393E 3942 3948 394C 3955 3956 3961 3AFF 3C63 3C67 3C6A 3C6B 3C6D 3C6E 3C70 3C70 3C72 3C75 3C78 3C7A 3C7C 3C7E 3C80 3C81 3C82 3C8D 40DF 40E2 40E8 40EE 40F0 40D4 4058 4042 4040 4040 4041 4054 40CD 40C5 40D5 4969 51D2 51ED 51F9 5202 520E 5211 5214 5219 5221 522A 522F 5233 523A 523E 5244 524A 524E 5255 525B 5260 5266 526B 5273 5276 5278 527C 5284 528D 5293 529D 52A5 52A7 52AA 52B2 52BB 52C4 52C6 52CB 52D2 52E2 52E6 52EC 52F3 52F6 5300 5309 5310 5313 531B 5324 532B 5334 533E 5345 534D 5353 5357 5354 533B 530E 52BA 522D 5206 51CE 0 4FAE 4FA1 4F99 526B 53C1 53C1 5760 6CE3 6CEC 6CF1 6CF9 6D0B 6D19 6D24 6D2D 6D3B 6D43 6D4D 6D56 6D68 6D70 6D82 6D86 6D9A 6D9F 6DA3 6D9C 6D8D 6DB0 6DD2 6DE8 6DF7 6E02 6E11 6E1F 6E2F 6E3C 6E41 6E4E 6E59 6E6C 6E7E 6E86 0 ANGL1 3F800000 C7000000 9EB10 341 205 7E7C 7E7C 7E7D 7E4A 7E4B 7E4C 7E4E 7E4F 7E51 7E53 7E54 7E56 7E58 7E5A 7E5B 7E5D 7E5E 7E5F 7E60 7E60 7E61 7E62 7E62 7E64 7E64 7E65 7E66 7E67 7E68 7E68 7E69 7E6A 7E6B 7E6C 7E6D 7E6E 7E6E 7E6F 7E70 7E71 7E72 7E73 7E73 7E74 7E75 7E76 7E77 7E78 7E79 7E7A 7E7B 7E7C 7E7C 7E7D 7E7E 7E7F 7E80 7E81 7E82 7E83 7E84 7E84 7E85 7E86 7E87 7E88 7E89 7E8A 7E8B 7E8C 7E8D 7E8E 7E8F 7E90 7E90 7E8B 7E8B 7E8C 7E8D 7E8E 7E91 7E92 7E94 7E96 7E98 7E9A 7E9B 7E9C 7E9D 7E9F 7EA0 7EA1 7EA2 7EA3 7EA4 7EA5 7EA6 7EA7 7EA8 7EA9 7EAA 7EAB 7EAC 7EAD 7EAE 7EAF 7EB0 7EB1 7EB2 7EB3 7EB4 7EB5 7EB6 7EB7 7EB8 7EB9 7EBA 7EBB 7EBC 7EBD 7EBE 7EBF 7EC0 7EC1 7EC2 7EC3 7EC4 7EC5 7EC6 7EC7 7EC8 7EC9 7ECA 7ECB 7ECC 7ECD 7ECE 7ECF 7ED0 7ED1 7ED3 7ED4 7E04 7ED6 7ED6 7E07 7E08 7E09 7E0A 7E0B 7E0D 7E0D 7E0F 7E0F 7E11 7E12 7E13 7E14 7E15 7E16 7E17 7E18 7E19 7E1A 7E1B 7E1C 7E1D 7E1E 7E1F 7E20 7E21 7E22 7E23 7E24 7E25 7E26 7E27 7E28 7E29 7E2A 7E2B 7E2C 7E2D 7E2E 7E30 7E31 7E32 7E33 7E34 7E35 7E36 7E37 7E38 7E39 7E3A 7E3B 7E3C 7E3D 7E3E 7E3F 7E40 7E41 7E42 7E43 7E44 7E45 7E46 7E47 7E48 7E49 7E4A 7E4B 7E4C 7E4D 7E4E 7E4F 7E50 7E51 7E52 7E53 7E53 7E53 7E54 7E55 7E57 7E58 7E58 7E59 7E5A 7E5B 7E5C 7E5D 7E5F 7E60 7E61 7E86 7E50 7E51 7E52 7E53 7E54 7E56 7E57 7E58 7E5A 7E5B 7E5C 7E5D 7E5F 7E60 7E61 7E62 7E64 7E65 7E66 7E67 7E69 7E6A 7E6B 7E6C 7E6D 7E6F 7E70 7E71 7E72 7E74 7E75 7E76 7E77 7E78 7E7A 7E7B 7E7C 7E7D 7E7F 7E80 7E81 7E83 7E84 7E85 7E86 7E87 7E88 7E8A 7E8B 7E8F 7E90 7E91 7E92 7E93 7E93 7E94 7E95 7E96 7E97 7E98 7E98 7E99 7E9A 7E9B 7DCB 7DCC 7DCD 7DCD 7DCE 7DCF 7DCD 7DD2 7DD3 7DD4 7DD5 7DD6 7DD7 7DD8 7DD9 7DDA 7DDB 7DDC 7DDD 7DDE 7DDF 7DE0 7DE1 7DE2 7DE3 7DE4 7DE5 7DE6 7DE7 7DE8 7DE9 7DE9 7DEA 7DEB 7DEC 7DED 7DEC 7DEB 7DEC 7DED 7DED 7DEE 7DEF 7DF0 7DF0 7DF1 7DF2 7DF3 7DF3 7DF4 7DF5 7DF5 7DF6 7DF7 7DF7 7DF8 7DF9 7DF9 7DFA 7DFA 7DFB 7DFC 7DFC 7DFD 7DFD 7DFE 7DFF 7DFF 7E00 7E00 7E01 7E02 7E02 7E02 7E02 7E02 7E03 7E03 7E04 7E04 7E05 7E05 7E05 7E06 7E06 7E07 7E07 7E08 7E08 7E08 7E09 7E09 7E08 7E08 7E08 7E09 7E09 7E09 7E0A 7E0A 7E0B 7E0B 7E0C 7E0C 7E0C 7E0C 7E0C 7E0C 7DF0 7E07 7E07 7E08 7E08 7E08 7E09 7E09 7E09 7E09 7E0A 7E0A 7E0A 7E0A 7E0B 7E0B 7E0B 7E0B 7E0B 7E0C 7E0C 7E0C 7E0C 7E0C 7E0C 7E0D 7E0D 7E0D 7E0D 7E0D 7E0D 7E0D 7E0D 7E0E 7E0E 7E0E 7E0E 7E0E 7E0E 7E0E 7E0E 7E0E 7E0E 7E0E 7D3E 7E0E 7E0E 7D3E 7D3E 7D3E 7D3E 7D3E 7D3E 7D3E 7D3E 7D3E 7D3E 7D3E 7E0E 7E0E 7E0E 7E0E 7E0E 7E0E 7E0E 7E0E 7E0E 7E0E 7E0E 7E0E 7E0D 7D3D 7E0C 7E0C 7D3C 7D3C 7E0C 7D3B 7D3B 7D3B 7D3B 7D3B 7D3B 7D3B 7D3B 7D3B 7D3B 7D3B 7D3B 7D3B 7D3A 7D3A 7D3A 7D3A 7D3A 7D3A 7D3A 7D3A 7D39 7D39 7D39 7D39 7D39 7D39 7D39 7D38 7D38 7D38 7D38 0 0 0 0 0 0

应答数据比较长,按照我的理解逐个解析一下。“LMDscandata”后面的两个“1”分别是Version number和Device number,136AC7D是Serial number,后面的“1 0”是Device status,5A98是Telegram counter,B528是Scan counter,A47DBC60是Time since start up in µs,A47DC055是Time of transmission in µs,后面“0 0”是Status of digital inputs,“8 0”是Status of digital outputs,再后面“0”是former Reserved now Layer angle,EA60是Scan frequency,21C0是Measurement frequency,后面“1”是是否使用外部编码器的标志,B49是编码器的值,后面“0”是编码器的速度。

我使用的是16bits,因此按照此协议来解析后面的数据。“2”是输出通道,“DIST1”是输出内容,代表距离(后面ANGL1代表角度),3DCCCCCD是比例因子(后面3F800000h也是),00000000是比例因子偏移(C7000000也是),9EB10是起始角度,341是角度分辨率,205是数据个数。后面所有的十六进制数分别代表距离和角度。

解释一下这个205的计算方法,205转换成十进制就是517,(108 - 65)×12 + 1 = 517,加1的意思是最后一个角度会有两个距离数据与其对应。

这里面有个我没弄明白的地方,先讲出来,避免误导他人,角度的比例因子偏移C7000000我没弄明白,因此角度的计算,我就单纯用起始角度+角度分辨率算的。按照这个角度计算方式,对于坐标的计算做个简单的示例,以前两个数据为例,我的起始角度为65°,第一个距离的值为0,0为无效值,因此不做计算;第二个距离值为6E76,角度为65+1/12°(这个是角度,如果需要用弧度记得转换),通过计算可得此点的x、z坐标:

x坐标:28278 * 0.1 * cos(65.0833) = 1191.35266
z坐标:28278 * 0.1 * sin(65.0833) = 866.7

y坐标就是码值乘上比例尺,这个比例尺的计算方式在第二章介绍过了,直接换算即可,即此点的y坐标。

y坐标:2889 * 0.3061538461538462 = 884.4785

下面说一下数据正确性验证方法:解析单帧所有数据后生成点云,与第二章通过软件采集的点云放在同一个可视化软件里,注意软件采集的点云要计算上码值以及点云间距的比例因子,用CloudCompare看看它们是否重合。

2.自己编写C++程序进行通信

由于Sopas软件最多只能采集10s的点云数据,不能满足某些应用场景,在明确了通信协议的解析方法后,我们想自己写程序接收数据,相当于就是写一个TCP客户端的程序,话不多说,直接上代码。
头文件LMS4000.h:

#pragma once

#ifndef LMS4000_H_
#define LMS4000_H_
#include "conio.h"
#include "windows.h"
#include "winsock.h"
#include <stdlib.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")

#include <iostream>
#include <cstdint>
#include <thread>
#include <vector>
#include <string>

#include<math.h>
#include<pcl/point_types.h>
#include<pcl/io/pcd_io.h>
#include <pcl/io/io.h>

enum order
{
	LOG_IN = 0,								//登录
	STARTMEASURE = 1,						//开始测量
	STOPMEASURE = 2,						//停止测量
	STANDBY = 3,							//待机
	GETRESOLUTION = 4,						//获取分辨率和频率
	RUN = 5,								//运行
	GETANGLERANGE = 6,						//读取角度范围
	SINIGLEDATA = 7,						//获取上一次有效扫描的数据
	CONTINUOUSDATA = 8,						//永久发送数据
	GETSTATE = 9,							//获取设备状态
	SETENCODER = 10							//设置码值
};

typedef struct PointSick
{
	double distance;
	double angle;
}PointSick;

class LMS4000
{
private:
	SOCKET sockclient;
	HANDLE hThread;
	DWORD dwThreadId;
	//端口号
	int port;
	//服务端IP地址
	const char* ip;
	//是否服务器连接标志位
	bool bIsconnected;
	//发送的数据(十六进制)
	CHAR outbuffer0[100] = { 0 };
	//接收的数据(十六进制)
	CHAR szRecv[16000] = { 0 };
	//保存接收数据的集合
	std::vector<std::string> data;
	//order=8的标志位(只有此时才存数据)
	int flag;

	unsigned int ssstrlen(const char* str);
	int hex2char(uint8_t c);
	int Hex2Ascii(char* hex, char* ascii);
	//从外部获取指令
	int getorder(int order);

public:
	LMS4000();
	~LMS4000();
	int init();
	int connectsocket();
	int senddata(int order);
	int receivedata();
	int getpcdfile();
	int close();
};

#endif

实现文件LMS4000.cpp:

#include "LMS4000.h"

unsigned int LMS4000::ssstrlen(const char* str)
{
	const char* cp = str;
	while (*cp++);
	return (cp - str - 1);
}

int LMS4000::hex2char(uint8_t c)
{
	return ((c >= '0') && (c <= '9')) ? int(c - '0') :
		((c >= 'A') && (c <= 'F')) ? int(c - 'A' + 10) :
		((c >= 'a') && (c <= 'f')) ? int(c - 'a' + 10) :
		-1;
}

int LMS4000::Hex2Ascii(char* hex, char* ascii)
{
	int hexLen = ssstrlen(hex);
	int asciiLen = 0;

	for (int i = 0, cnt = 0; i < hexLen; i++)
	{
		char c = hex2char(hex[i]);

		if (-1 == c)
			continue;
		if (cnt) 
		{
			cnt = 0;
			ascii[asciiLen++] += c;
		}
		else 
		{
			cnt = 1;
			ascii[asciiLen] = c << 4;
		}
	}
	ascii[asciiLen++] = 0;
	return asciiLen;
}

int LMS4000::getorder(int order)
{
	flag = order;
	switch (order)
	{
	case 0:
	{
		//数据拷贝
		char outbuffer[100] = "02734D4E205365744163636573734D6F646520303320463437323437343403";
		memcpy(outbuffer0, outbuffer, strlen(outbuffer));
		break;

	}
	case 1:
	{
		//数据拷贝
		char outbuffer[100] = "02734D4E204C4D4373746172746D65617303";
		memcpy(outbuffer0, outbuffer, strlen(outbuffer));
		break;
	}
	case 2:
	{
		//数据拷贝
		char outbuffer[100] = "02734D4E204C4D4373746F706D65617303";
		memcpy(outbuffer0, outbuffer, strlen(outbuffer));
		break;
	}
	case 3:
	{
		//数据拷贝
		char outbuffer[100] = "02734D4E204C4D437374616E64627903";
		memcpy(outbuffer0, outbuffer, strlen(outbuffer));
		break;
	}
	case 4:
	{
		//数据拷贝
		char outbuffer[100] = "0273524E204C4D507363616E63666703";
		memcpy(outbuffer0, outbuffer, strlen(outbuffer));
		break;

	}
	case 5:
	{
		//数据拷贝
		char outbuffer[100] = "02734D4E2052756E03";
		memcpy(outbuffer0, outbuffer, strlen(outbuffer));
		break;
	}
	case 6:
	{
		//数据拷贝
		char outbuffer[100] = "0273524E204C4D506F757470757452616E676503";
		memcpy(outbuffer0, outbuffer, strlen(outbuffer));
		break;
	}
	case 7:
	{
		//数据拷贝
		char outbuffer[100] = "0273524E204C4D447363616E6461746103";
		memcpy(outbuffer0, outbuffer, strlen(outbuffer));
		break;
	}
	case 8:
	{
		//数据拷贝
		char outbuffer[100] = "0273454E204C4D447363616E64617461203103";
		memcpy(outbuffer0, outbuffer, strlen(outbuffer));
		break;
	}
	case 9:
	{
		//数据拷贝
		char outbuffer[100] = "0273524E205343646576696365737461746503";
		memcpy(outbuffer0, outbuffer, strlen(outbuffer));
		break;
	}
	case 10:
	{
		//数据拷贝
		char outbuffer[100] = "0273574E204C4943656E63736574203203";
		memcpy(outbuffer0, outbuffer, strlen(outbuffer));
		break;
	}
		
	default:
	{
		std::cout << "无效指令" << std::endl;
		return 1;
	}
	}
	return 0;
}

LMS4000::LMS4000()
{
	port = 2112;
	ip = "192.168.3.201";
	sockclient = INVALID_SOCKET;
	bIsconnected = false;
}

LMS4000::~LMS4000()
{
}

int LMS4000::init()
{	
	//初始化socket库
	WSADATA wsa = { 0 };
	WSAStartup(MAKEWORD(2, 2), &wsa);

	return 0;
}

int LMS4000::connectsocket()
{
	//创建socket
	sockclient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (INVALID_SOCKET == sockclient)
	{
		return 1;
	}
	//连接服务器,建立服务器端套接字地址
	struct sockaddr_in addr = { 0 };
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	//对于inet_addr()函数,它是把“xxx.xxx.xxx.xxx”形式表示的IPV4地址,转换为IN_ADDR结构体能够
	//接收的形式(unsigned long型,因为IN_ADDR结构体中的负责接收的S_addr成员变量的类型是unsigned long型)
	addr.sin_addr.S_un.S_addr = inet_addr(ip);//本机ip

	//向服务器发出连接请求,当然我们也可以通过connet函数的返回值判断到底有无连接成功。
	int iRetVal = connect(sockclient, (struct sockaddr*)&addr, sizeof(addr));
	if (SOCKET_ERROR == iRetVal)
	{
		printf("服务器连接失败!");
		closesocket(sockclient);
		return 1;
	}
	printf("服务器连接成功!\n");
	bIsconnected = true;
	return 0;
}

int LMS4000::senddata(int order)
{
	if (bIsconnected == true)
	{
		std::memset(szRecv, '\0', sizeof(szRecv));
		int state = getorder(order);
		if(state != 0)
		{
			return 1;
		}
		CHAR in[100] = { " " };
		int len = strlen(outbuffer0);
		int idx = 0;
		for (int n = 0; n < len; n++)
		{
			in[idx++] = outbuffer0[n];
			if ((n + 1) % 2 == 0)
			{
				in[idx++] = ' ';//赋一个空格
			}
		}

		//此数组要赋初值
		CHAR szSend[100] = { 0 };
		Hex2Ascii(in, szSend);

		int len1 = strlen(szSend);
		//for (int i = 0; i < len1; i++)
		//	std::cout << szSend[i];
		//std::cout << std::endl;
		// CHAR szSend[100] = "sMN LMCstandby";//"hello server";   //客户端  先发后收
		send(sockclient, szSend, sizeof(szSend), 0);  //发送函数,可以通过返回值判断发送成功与否。
		//Sleep(1500);
		return 0;
	}
	else
	{
		return 1;
	}
}

int LMS4000::receivedata()
{  
	if (bIsconnected == true)
	{
		//接收服务器回传的数据
		int a = 0;
		recv(sockclient, szRecv, 10000, 0); //接收函数
		//int len1 = strlen(szRecv);
		printf("%s\n", szRecv);//表示以字符串的格式输出服务器端发送的内容。
		std::cout << "完成一次数据传输" << std::endl;

		std::string s;
		s += szRecv;
		if (flag == 8)
		{
			data.push_back(s);
		}
	
		return 0;
	}
	else
	{
		return 1;
	}
}

int LMS4000::getpcdfile()
{
	if (bIsconnected == true)
	{
		std::vector<pcl::PointCloud<pcl::PointXYZ>::Ptr> cloud1;
		for (int i = 0; i < data.size(); i++)
		{
			std::string hex = data[i];
			//找到角度和距离的分界
			std::string::size_type position1 = hex.find("ANGL1");
			if (position1 == -1)
			{
				std::cout << "未找到符号!" << std::endl;
				continue;
			}
			//将角度和距离分为两个字符串,分别处理
			std::string hex_dis = hex.substr(0, position1);

			//cout << hex_dis << endl;
			//cout << hex_dis.length() << endl;

			std::string hex_ang = hex.substr(position1);

			//cout << hex_ang << endl;
			//cout << hex_ang.length() << endl;

			//通过检测空格的方式拆分组内数据,count用于通过计数的方法区分协议头和真实数据
			std::string::size_type position_dis = 0;
			std::string::size_type position_extra = 0;
			int count = 0;
			std::vector<double> Distances;
			int encoder = 0;
			double startangle = 0.0;
			double angle_resolution = 0.0;
			while (position_dis <= hex_dis.length())
			{
				position_dis = hex_dis.find(" ", position_extra);
				std::string hex_dis_extra = hex_dis.substr(position_extra, position_dis - position_extra);
				//cout << hex_dis_extra << endl;
				position_extra = position_dis + 1;
				count++;
				//获取码值
				if (count == 20)
				{
					encoder = std::stoi(hex_dis_extra, nullptr, 16);
				}
				//获取起始角度
				if (count == 26)
				{
					int a = std::stoi(hex_dis_extra, nullptr, 16);
					startangle = double(a) / 10000;
				}
				//获取角度分辨率
				if (count == 27)
				{
					int a = std::stoi(hex_dis_extra, nullptr, 16);
					angle_resolution = double(a) / 10000;
				}

				//29是距离数据的协议头和真实数据的分界
				if (count >= 29)
				{
					if (hex_dis_extra.length() > 4)
					{
						std::cout << "长度数据有误!" << std::endl;
						break;
					}
					if (hex_dis_extra == "")
					{
						break;
					}
					int a = std::stoi(hex_dis_extra, nullptr, 16);

					double dis = double(a) / 10;
					Distances.push_back(dis);
				}
			}

			position_extra = 0;
			count = 0;
			std::string::size_type position_ang = 0;
			std::vector<double> Angles;
			while (position_ang <= hex_ang.length())
			{
				position_ang = hex_ang.find(" ", position_extra);
				std::string hex_ang_extra = hex_ang.substr(position_extra, position_ang - position_extra);
				//cout << hex_ang_extra << endl;
				position_extra = position_ang + 1;
				count++;
				//7是角度数据的协议头和真实数据的分界
				if (count >= 7)
				{
					if (hex_ang_extra.length() > 4)
					{
						std::cout << "角度数据有误!" << std::endl;
						break;
					}
					if (hex_ang_extra == "")
					{
						break;
					}
					int a = std::stoi(hex_ang_extra, nullptr, 16);

					double ang = double(a) / 10000;
					Angles.push_back(ang);
				}
			}

			std::vector<PointSick> Points;

			for (size_t i = 0; i < Distances.size(); i++)
			{
				PointSick  pt;
				pt.distance = Distances[i];
				pt.angle = Angles[i];

				Points.push_back(pt);
			}

			pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);

			//float y = encoder * 0.3;
			//比例尺,请自行计算后修改
			float y = encoder * 0.3061538461538462;
			for (size_t i = 0; i < Points.size(); i++)
			{
				pcl::PointXYZ pt;
				pt.y = y;
				double angle = startangle + i * angle_resolution;
				if (Points[i].distance == 0)
				{
					continue;
				}
				//cout << angle << endl;
				if (angle > 90)
				{
					pt.x = Points[i].distance * cos((angle * M_PI) / 180);
					pt.z = Points[i].distance * sin((angle * M_PI) / 180);
				}
				else
				{
					pt.x = Points[i].distance * cos((angle * M_PI) / 180);
					pt.z = Points[i].distance * sin((angle * M_PI) / 180);
				}

				cloud->push_back(pt);
			}

			cloud1.push_back(cloud);
		}

		pcl::PointCloud<pcl::PointXYZ>::Ptr cloudt(new pcl::PointCloud<pcl::PointXYZ>);
		for (size_t i = 0; i < cloud1.size(); i++)
		{
			*cloudt = *cloudt + *cloud1[i];
		}
		pcl::io::savePCDFileBinary("test.pcd", *cloudt);

		return 0;
	}
	else
	{
		return 1;
	}
}

int LMS4000::close()
{
	if (bIsconnected == true)
	{
		closesocket(sockclient);
		WSACleanup();
		bIsconnected = false;
		return 0;
	}
	else
	{
		return 1;
	}
}


测试程序:

#include"LMS4000.h"

void threadFunctionB(int& n)
{
	std::cout << "Run New thread: " << n << std::endl;
	while (1)
	{
		if (_kbhit())
		{//如果有按键按下,则_kbhit()函数返回真
			n++;
			std::cout << n << std::endl;
			break;
		}
	}
}

int main()
{
	int order = 8;
	LMS4000 a;
	a.init();
	a.connectsocket();
	order = 8;
	a.senddata(order);

	if (order == 8)
	{
		int n = 2;
		std::thread newThread2(threadFunctionB, std::ref(n));
		newThread2.detach();

		while (1)
		{	
			a.receivedata();
			if (n == 3)
			{
				break;
			}
		}
	}
	else
	{
		a.receivedata();
	}

	a.getpcdfile();

	a.close();

	return 0;
}

这里面服务器的IP地址和端口可以在软件里看,根据具体值自行修改。我是通过PCL库实现保存点云的,如果本身没有这个库的朋友,可以自己声明一个三维点的结构体,把点保存进去。在测试程序里,我写了个多线程,具体功能是通过键盘按键停止接收数据。
暂时未出现一次接收多帧数据的情况,因此测试程序也未考虑此类情况。
这里有个问题困扰了我好几天。在接收程序的地方,我之前是声明了一个std::vector<char*> data,然后接收到szRecv后,就把它存到集合里,在转Pcd文件的时候,我发现data集合里存的都是同一帧的数据,我开始以为是我测试程序通信协议少了步骤,后面仔细调试程序的时候发现是保存当前帧数据的时候,会把前一帧数据也同时更新,改成当前的方式就没问题了。

由于对TCP通信以及多线程了解不多,我实现的功能也就比较基础,推荐给看博文的朋友一些参考文章以供学习,写出更优秀的代码。

【C++】多线程(thread)使用详解
VS C++ 线程篇之一创建线程
c++ 十六进制转字符串(ASCII码)
C++ TCP通讯(客户端)

  • 29
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
激光雷达SICK LMS200编译失败可能有多种原因。首先,编译错误可能是由于软件版本不匹配所引起的。如果使用的编译器或操作系统版本与激光雷达的驱动程序或SDK不兼容,就会出现编译失败。此时,我们可以尝试使用兼容的软件版本重新安装驱动程序或SDK,然后重新编译。 其次,编译失败可能是由于配置错误引起的。在使用激光雷达之前,通常需要进行一些配置,如设置环境变量、路径、端口等。如果配置不正确,编译过程中会出现错误。我们需要检查这些配置参数,确保其正确无误,并重新尝试编译。 另外,编译失败还可能是由于代码错误引起的。在编写代码时,可能会存在语法错误、变量命名错误、函数调用错误等。检查代码并修复这些错误是解决编译失败的重要步骤。我们可以仔细检查代码中的每一行,并参考相关文档或示例代码来确保代码的正确性。 最后,编译失败还可能是由于缺少依赖项或库文件引起的。在编译过程中,可能会因为缺少必要的依赖项或库文件而失败。我们需要检查是否安装了所有必须的依赖项,并将其正确地链接到编译器中。 综上所述,激光雷达SICK LMS200编译失败可能是由于软件版本不匹配、配置错误、代码错误或缺少依赖项等原因引起的。通过仔细检查并解决这些问题,我们可以顺利地编译激光雷达。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值