zoukankan      html  css  js  c++  java
  • 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, // baudrate
    char parity, // parity 
    UINT databits, // databits 
    UINT stopbits, // stopbits 
    DWORD dwCommEvents, // EV_RXCHAR, EV_CTS etc
    UINT writebuffersize) // size to the writebuffer2.串口监测线程
    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<len2);
    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<m_ptrArray.GetSize();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最终效果
  • 相关阅读:
    python数据类型
    集合(set)内置方法
    python第三天
    剑指offer-什么是1G/2G/3G/4G/5G
    经典交换实验-二层交换机实现pc隔离&vlan通信
    linux运维神器-htop&mtr
    三分钟速学linux-进程管理命令
    三分钟速学文件权限管理
    三分钟速学网卡管理配置-nmcli命令
    三分钟速学linux-centos/redhat常见包管理器
  • 原文地址:https://www.cnblogs.com/qq78292959/p/2077085.html
Copyright © 2011-2022 走看看