SICK LMS200激光数据采集程序说明

转自:http://www.cnblogs.com/qq78292959/archive/2009/09/22/2077085.html


SICK LMS200激光数据采集程序说明

1.设计功能

SICK LMS200激光扫描仪是将扫描得到的距离数据通过COM端口传送到接收端,再由终端设备对数据进行处理,完成对周边空间的探测。本程序分以下几部分:

一、串口通讯功能:发送、接收、显示数据;

二、数据处理功能:周期数据的截取,十六进制转十进制;

三、坐标标定功能:将距离数据标定在坐标系中;

2.串口通讯功能

2.1简介 

由于激光扫描仪的数据量大,而且是实时产生的。为了提高串口读取数据的高速实时性,本程序的串口通讯部分是基于CSerialPort类完成的。该类支持线连接的串口编程,而且是基于多线程的。

2.2函数功能介绍

1.设置串口参数函数原型:

BOOL CSerialPort::InitPort(CWnd* pPortOwner, // the owner (CWnd) of the port (receives message)

UINT portnr, // portnumber (1..4)

UINT baud, // baudratechar parity, // parity 

UINT databits, // databits 

UINT stopbits, // stopbits DWORD dwCommEvents, // EV_RXCHAR, EV_CTS etcUINT writebuffersize) // size to the writebuffer

2.串口监测线程:

BOOL CSerialPort::StartMonitoring() 

BOOL CSerialPort::RestartMonitoring()

BOOL CSerialPort::StopMonitoring()

void CSerialPort::WriteChar(CSerialPort* port)

void CSerialPort::ReceiveChar(CSerialPort* port, COMSTAT comstat)

void CSerialPort::WriteToPort(char* string)

3.监测线程接收事件信息,再进行消息处理即可

2.3串口设置界面类

CconfigDlg完成串口的设置和事件的处理,设置界面如下图。

2.4发送数据

LMS200只识别十六进制的数据,因此在发送控制指令前要把指令转为十六进制。发送数据有单次发送,定时发送两张模式。

工作流程:

1:在“发送指令”编辑框中输入控制指令;

2:在“发送设置”中选择发送类型;

3:点击“单次发送”或“定时发送”根据选择的发送模式发送指令;

实现函数:

////////////////////////////////////////////////

将发送数据转为十六进制

void CSerialTestDlg::SendHexData(char*buf)

////////////////////////////////////////////////

将发送数据转为ASCII码

void CSerialTestDlg::SendAsciiData(char *buf)

2.5接收数据

终端接收到的数据形式如下:

06 02 80 03 00 A0 00 10 16 0A 02 80 D6 02 B0 69 41 20 02 15 02 F2 01 99 01 61 01 30 01 0D 01 06 01 F4 00 DC 00 D3 00 D1 00 C3 00 CF 00 CC 00 D3 00 C7 00 D3 00 D0 00 D0 00 D6 00

 CserialPort类中监视线程接收事件信息WM_COMM_RXCHAR与CSerialTestDlg::OnCommunication(WPARAM Char, LPARAM num)函数建立消息响应,接收LMS200返回的数据,然后根据用户要求转换为十六进制和ACII码。

实现函数:

////////////////////////////////////////////////

接收串口数据

LONG CSerialTestDlg::OnCommunication(WPARAM Char, LPARAM num)

3.数据处理功能

LMS200返回的数据结构如下:

3.1.具体说明

1:发送启动指令后LMS200首先是返回一个06 02 80 03 00 A0 00字符串 10位。 因采样角频率而不同。

2:校验位3位,每个周期都不一样;

3:返回数据6位,每个周期都不变;

4:距离数据722位;

5:下一周期重复2-4步;

3.2.数据处理

以采样角频率为10 为例,对数据的分析可知,距离数据的字符串长度为722*3=2166(含有空格),本程序的是按每行51个字符串显示如图所示。这样我们可以知道需要44行的数据才包含一个周期的数据,44*51=2244即存储这段数据的字符串的总长度是2244,而有效的距离数据是从51~2215这段字符串。总字符串转化成字符数组,用数组char array[2245],arraydata[2166]分别来存储总的字符和距离字符。 

 现在就是对距离字符数组进行处理,每两个十六进制表示一个返回的距离数据,低位在前,高位在后。所以处理第一步先把高低位互换,再把十六进制转为十进制。

1:0F 02 12 02 E7 01

2:02 0F 02 12 01 E7

3:020F 0212 01E7

4:527 530 487 

 接着把一个周期的数据存储在Data[361](0.50)或Data1[181](10)中,完成对一个周期数据的截取。

3.3实现函数

////////////////////////////////////////////////

将接收到的十六进制数据转换为十进制

void CSerialTestDlg::HexToDec(CString str){}

////////////////////////////////////////////////

完成对应采样角频率的处理

if(m_angleComb.GetCurSel()==0){} 0.50

if(m_angleComb.GetCurSel()==1){} 10

////////////////////////////////////////////////

截取需要的字符串长度

StrData.GetLength()==2244

////////////////////////////////////////////////

高位,低位换位 

for(k=0;k<=2160;k+=6){}

////////////////////////////////////////////////

十六进制转为十进制

do

{}

while(j);


4.坐标标定

根据采样角频率的不同,一个周期的距离数据分别有181个(10 )和361个(0.50 )数据。如下图所示:d为我们得到的数据,a为对应的角度,对应到笛卡尔坐标中:

x=d*cosa                   (1)
y=d*sina                   (2)

4.1坐标系的绘制
实现函数
void CSerialTestDlg::DrawPoint(int dis[]){}
为了方便重复绘制和清除旧图,程序中的坐标系为加载的位图在void CSerialTestDlg::OnPaint()中加载。资源中位图文件为IDB_BITMAP1。加载后的如下图:

4.2数据标定

       首先初始化double angle[361]和double angle1[181]这两个数据,分别存储0.50 和10 两种采样角频率的361个(00~3600)和181(00~1800)个角度。
       根据转换到笛卡尔坐标的转换式,算出坐标中的x,y值:
x=dis*cos(angle1*PI/180);
                                   y=dis*sin(angle1*PI/180);
由于计算机中对屏幕坐标的定义如左图所示:y轴是下正上负。为了按正常视觉效果来显示,需要对y坐标值取负。
                     CPoint m_ptEnd;
m_ptEnd.x=x;
                     m_ptEnd.y=-y;



用小圆点来显示
pDC->Ellipse(m_ptEnd.x - 2, m_ptEnd.y - 2, m_ptEnd.x + 2, m_ptEnd.y + 2);
图像的重绘
在绘制好图像后,移动对话框会使得界面刷新,导致图像消失,所以需要加入图像的重绘。
在程序中定义了一个CGrap类用来保存各个点的坐标值,在void CSerialTestDlg::OnPaint()中对图像进行重绘;
for(int i=0;i               {
pDC->Ellipse(((CGrap*)m_ptrArray.GetAt(i))->m_ptEnd.x-2, ((CGrap*)m_ptrArray.GetAt(i))->m_ptEnd.y-2, ((CGrap*)m_ptrArray.GetAt(i))->m_ptEnd.x+2, ((CGrap*)m_ptrArray.GetAt(i))->m_ptEnd.y + 2);
}
4.3最终效果

你可能感兴趣的:(激光雷达)