SICK激光传感器:LMS400生成表面点云

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/YunLaowang/article/details/89709268
简介

SICK LMS400是德国SICK公司生产的单线型激光传感器,主要应用于室内场景的测量,打出的激光是650nm可见红光,其主要参数如下:

  • 性能:扫描频率300Hz-500Hz、角度分辨率0.1°-1.0°可选、工作区域0.7m-3.0m、水平测量角度70°、测量精度±4mm;
  • 接口:Ethernet(TCP/IP协议)、RS232串口;
  • 电子参数:供电电压24VDC、功耗25W、外壳防护等级IP65;
  • 机械参数:外壳材质压铸铝、尺寸(长 x 宽 x 高)179 mm x 107 mm x 130 mm;
  • 温度:工作环境温度0°C…+40°C,储存温度–20°C…+70°C;
  • 最小可检测物体:30 mm x 30 mm;

LMS400扫描的结果是二维平面点云,其工作区域如下图所示,需要注意的是,当激光如下Fig.3图放置时,其坐标系是Y轴朝前为正、X朝右为正,而且扫描的点云结果是按照X坐标由大到小(如图从右往左)进行存储的,即下述代码中的lines.ranges.front()代表最右边的有效点,lines.ranges.back()代表最左边的有效点,千万不要搞反。

工作区域图表:


代码

环境:Win10+VS2015+PCL1.8

// LMS400连续扫描
#include<iostream>
#include<stdio.h>
#include<fstream>

//pcl
#include <pcl/point_types.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/io/io.h>   
#include <pcl/io/pcd_io.h> 
#include <conio.h>

#include "LMS400.h"
#define KEYDOWN( vk ) ( 0x8000 & ::GetAsyncKeyState( vk ) )

using namespace std;

int main(int argc, char** argv)
{
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2, 2), &wsaData); 
	LMS400* m_lms = new LMS400();

	// pcl
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
	boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("Single Lines Viewer"));

	double layer = 0; // 点云的层次

	while (true)
	{
		if (KEYDOWN(VK_ESCAPE) > 0) // 按ESC退出
			break;

		// 激光扫描
		m_lms->spin();
		LaserScan lines = m_lms->getLaserScan();

		// pcl
		for (size_t i = 0; i < lines.size(); i++)
		{
			pcl::PointXYZRGB p;

			p.x = lines[i].getX(); // 等效于lines.ranges[i].getX(),重载了操作符:[]
			p.y = lines[i].getY(); // z值
			p.z = layer;

			p.b = 0;
			p.g = 0;
			p.r = 255;
			cloud->points.push_back(p);
		}
		layer += 0.005; // 将扫描的结果间隔0.005mm进行存储
		cout << "spining" << endl;
	}
	// 设置并保存点云
	cloud->height = 1;
	cloud->width = cloud->points.size();
	cout << "point cloud size = " << cloud->points.size() << endl;
	cloud->is_dense = false;
	pcl::io::savePCDFile("pointcloud.pcd", *cloud);
	
	// 显示结果
	viewer->addCoordinateSystem(0.3); // X(红)Y(绿)Z(蓝)
	viewer->setPosition(0, 0);		// 设置在视图坐标系的位置

	viewer->addPointCloud<pcl::PointXYZRGB>(cloud, "sample cloud"); // 将点云数据添加到视窗中

	//用于改变显示点云的尺寸,可以利用该方法控制点云在视窗中的显示方法,
	viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "sample cloud");// 设置点云显示属性,
		
	while (!viewer->wasStopped())
	{
		viewer->spinOnce(100);
		boost::this_thread::sleep(boost::posix_time::microseconds(1000));
	}

	delete m_lms;
	WSACleanup();

	return 0;
}

代码的底层是基于TCP/IP协议进行通讯,如向激光发送ASCII码协议:"sMN mLRstopdata"对于LMS400代表的就是停止测量;如"sMN SetAccessMode 03 B18244B6"对应的是设置用户等级为authorized client等等,更多协议参见官方文档。

注意:上述操作激光的流程是:打开一次激光(构造函数内的start()函数)、多次采集数据(while循环)、关闭一次激光(析构函数内的stop()函数);但是如果你的需求是只在有需要的时候才打激光采集数据,而不是打完激光一直采数据的话,则其执行流程应该修改为:打开1次-采数据1次-关闭1次,相应的代码应修改为start()-采数据-stop(),否则可能会出现只能采集1次数据,第2次采集的数据完全不对的问题。总之,关闭激光以后,再次采集数据之前重新打开激光即可。

结果

使用LMS400扫描的书包:

资源链接
  1. SICK官方Github:https://github.com/SICKAG/
  2. LMS400相关的API: asr_sick_lms_400 Namespace Reference
  3. ROS相关:asr_sick_lms_400-ROS Wiki
备注
  1. 完整工程CSDN下载链接:SICK—LMS400激光传感器测距程序【Win10+VS2015】
  2. 该代码是在官方提供ROS驱动的基础上进行的二次封装,相关src及include文件在Github上也能找到。

猜你喜欢

转载自blog.csdn.net/YunLaowang/article/details/89709268