<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-Hans-CN">
	<id>https://wiki.lessokaji.com/index.php?action=history&amp;feed=atom&amp;title=2D%E6%BF%80%E5%85%89%E9%9B%B7%E8%BE%BE%E9%80%82%E9%85%8D</id>
	<title>2D激光雷达适配 - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.lessokaji.com/index.php?action=history&amp;feed=atom&amp;title=2D%E6%BF%80%E5%85%89%E9%9B%B7%E8%BE%BE%E9%80%82%E9%85%8D"/>
	<link rel="alternate" type="text/html" href="https://wiki.lessokaji.com/index.php?title=2D%E6%BF%80%E5%85%89%E9%9B%B7%E8%BE%BE%E9%80%82%E9%85%8D&amp;action=history"/>
	<updated>2026-04-15T16:06:20Z</updated>
	<subtitle>本wiki上该页面的版本历史</subtitle>
	<generator>MediaWiki 1.40.0</generator>
	<entry>
		<id>https://wiki.lessokaji.com/index.php?title=2D%E6%BF%80%E5%85%89%E9%9B%B7%E8%BE%BE%E9%80%82%E9%85%8D&amp;diff=881&amp;oldid=prev</id>
		<title>Artheru：​创建页面，内容为“2D雷达适配时，引用LidarController，声明一个MainIOObject类，继承于Lidar2DIOObject。写一个方法读取雷达数据，当一帧读完，放入cachedLidar，调用Output()。  == 1.雷达适配参数含义 ==  === 1.1 2D点云数据结构 ===  '''public''' '''class''' '''LidarPoint2D'''      {          '''public''' '''float''' th;//点云角度          '''public''' '''float''' d;//点云距离          '''public''' '''float''' intensity;//物…”</title>
		<link rel="alternate" type="text/html" href="https://wiki.lessokaji.com/index.php?title=2D%E6%BF%80%E5%85%89%E9%9B%B7%E8%BE%BE%E9%80%82%E9%85%8D&amp;diff=881&amp;oldid=prev"/>
		<updated>2025-03-10T12:21:43Z</updated>

		<summary type="html">&lt;p&gt;创建页面，内容为“2D雷达适配时，引用LidarController，声明一个MainIOObject类，继承于Lidar2DIOObject。写一个方法读取雷达数据，当一帧读完，放入cachedLidar，调用Output()。  == 1.雷达适配参数含义 ==  === 1.1 2D点云数据结构 ===  &amp;#039;&amp;#039;&amp;#039;public&amp;#039;&amp;#039;&amp;#039; &amp;#039;&amp;#039;&amp;#039;class&amp;#039;&amp;#039;&amp;#039; &amp;#039;&amp;#039;&amp;#039;LidarPoint2D&amp;#039;&amp;#039;&amp;#039;      {          &amp;#039;&amp;#039;&amp;#039;public&amp;#039;&amp;#039;&amp;#039; &amp;#039;&amp;#039;&amp;#039;float&amp;#039;&amp;#039;&amp;#039; th;//点云角度          &amp;#039;&amp;#039;&amp;#039;public&amp;#039;&amp;#039;&amp;#039; &amp;#039;&amp;#039;&amp;#039;float&amp;#039;&amp;#039;&amp;#039; d;//点云距离          &amp;#039;&amp;#039;&amp;#039;public&amp;#039;&amp;#039;&amp;#039; &amp;#039;&amp;#039;&amp;#039;float&amp;#039;&amp;#039;&amp;#039; intensity;//物…”&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新页面&lt;/b&gt;&lt;/p&gt;&lt;div&gt;2D雷达适配时，引用LidarController，声明一个MainIOObject类，继承于Lidar2DIOObject。写一个方法读取雷达数据，当一帧读完，放入cachedLidar，调用Output()。&lt;br /&gt;
&lt;br /&gt;
== 1.雷达适配参数含义 ==&lt;br /&gt;
&lt;br /&gt;
=== 1.1 2D点云数据结构 ===&lt;br /&gt;
 '''public''' '''class''' '''LidarPoint2D'''&lt;br /&gt;
     {&lt;br /&gt;
         '''public''' '''float''' th;//点云角度&lt;br /&gt;
         '''public''' '''float''' d;//点云距离&lt;br /&gt;
         '''public''' '''float''' intensity;//物体反光度（注意，本意为reflectivity，但由于历史原因一直称为intensity了）&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
=== 1.2 其余参数说明 ===&lt;br /&gt;
&lt;br /&gt;
* fname: simulatelidar专用的，指当前点云用的是哪个文件&lt;br /&gt;
* ScanAngleSgn: 雷达硬件属性--扫描方向 1为逆时针，-1为顺时针 对应detour雷达配置中的angleSgn&lt;br /&gt;
* ScanStartAngle: 雷达硬件属性--一帧扫描起始角度（-180°~+180°）&lt;br /&gt;
* ScanEndAngle: 雷达硬件属性--一帧扫描结束角度（-180°~+180°）对应detour雷达配置中的endAngle&lt;br /&gt;
* angleStart: 过滤点云角度用 最小角度&lt;br /&gt;
* angleEnd: 过滤点云角度用 最大角度&lt;br /&gt;
* maxDist: 过滤点云距离用 最大距离&lt;br /&gt;
* minDist: 过滤点云距离用 最小距离&lt;br /&gt;
* ReflexRange: 归一化尺度,从雷达解析的反光度需要除以该值&lt;br /&gt;
* cachedLidar :缓存用于output的帧数据&lt;br /&gt;
* frame: output一帧后加一 output 的帧数量&lt;br /&gt;
* tick: output前更新当前tick&lt;br /&gt;
* scanC: 雷达提供的自上电起帧数量&lt;br /&gt;
* maxReflex: 当前一帧数据中最强的反光率&lt;br /&gt;
* pointsN: 一帧数据的点数&lt;br /&gt;
* mirror: 是否倒装 倒装为true&lt;br /&gt;
&lt;br /&gt;
== 2. 2D雷达适配流程 ==&lt;br /&gt;
注意：适配时，雷达正前方为0°&lt;br /&gt;
&lt;br /&gt;
流程示例：&lt;br /&gt;
 '''using''' '''LidarController''';//引用雷达父类库&lt;br /&gt;
 '''namespace''' '''WLR716Lidar'''//(工程名为厂商(WLR)+雷达型号(716Lidar))&lt;br /&gt;
 {&lt;br /&gt;
     '''public''' '''class''' '''MainIOObject''' : Lidar2DIOObject//类名统一为MainIOObject 继承Lidar2DIOObject&lt;br /&gt;
     {&lt;br /&gt;
         //通信变量定义&lt;br /&gt;
         '''private''' '''string''' _ip;&lt;br /&gt;
         '''private''' '''int''' _port = '''2110''';&lt;br /&gt;
         '''public''' '''MainIOObject'''()&lt;br /&gt;
         {&lt;br /&gt;
             //在初始化函数中填入雷达正装时对应的,扫描起始角度,结束角度,扫描方向(从产品手册或者厂家处获取)&lt;br /&gt;
             ScanStartAngle = -'''135''';&lt;br /&gt;
             ScanEndAngle = '''135''';&lt;br /&gt;
             ScanAngleSgn = '''1''';&lt;br /&gt;
         }&lt;br /&gt;
         //定义Loop函数用于连接设备,之后循环解析并output数据&lt;br /&gt;
         '''private''' '''void''' '''Loop'''()&lt;br /&gt;
         {&lt;br /&gt;
             //连接设备取流(不通设备通信方式可能不同)&lt;br /&gt;
             Console.'''WriteLine'''(&amp;quot;WLR716Lidar Starting...&amp;quot;);&lt;br /&gt;
             '''var''' tcpclient = '''new''' '''TcpClient'''(_ip, _port);&lt;br /&gt;
             '''var''' ns = tcpclient.'''GetStream'''();&lt;br /&gt;
 			//在while循环外定义一下四个列表用于存储解析的数据&lt;br /&gt;
             List&amp;lt;LidarPoint2D&amp;gt; cloud = '''new''' List&amp;lt;LidarPoint2D&amp;gt;();&lt;br /&gt;
             List&amp;lt;'''float'''&amp;gt; thetaList = '''new''' List&amp;lt;'''float'''&amp;gt;();&lt;br /&gt;
             List&amp;lt;'''int'''&amp;gt; distList = '''new''' List&amp;lt;'''int'''&amp;gt;();&lt;br /&gt;
             List&amp;lt;'''float'''&amp;gt; intensityList = '''new''' List&amp;lt;'''float'''&amp;gt;();&lt;br /&gt;
 			//pck数组用于存读取的原始报文&lt;br /&gt;
             '''byte'''[] pck = '''new''' '''byte'''['''1024'''];&lt;br /&gt;
             &lt;br /&gt;
             DateTime ticStart = DateTime.Now;//扫描一帧点云开始时间&lt;br /&gt;
             Console.'''WriteLine'''($&amp;quot;Start streaming on port {_port}&amp;quot;);&lt;br /&gt;
            &lt;br /&gt;
             '''while''' ('''true''')&lt;br /&gt;
             {&lt;br /&gt;
 &lt;br /&gt;
                 '''int''' len = '''898''';&lt;br /&gt;
                 '''int''' n = ns.'''Read'''(pck, '''0''', len);//读取报文到pck中&lt;br /&gt;
                 '''if''' (len != '''ToInt32Rev'''(pck, '''4''') + '''9''')//校验报文长度&lt;br /&gt;
                     Console.'''WriteLine'''(&amp;quot;pck len does not match&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
                 '''var''' thisScanC = '''ToInt32Rev'''(pck, '''46''');//读取当前帧&lt;br /&gt;
                 '''if''' (scanC != thisScanC)//如果上一帧读取完成(例如读取到的帧号不同,判断方法可以不通),赋值cachedLidar,并output&lt;br /&gt;
                 {&lt;br /&gt;
                     scanC = thisScanC;//赋值scanC&lt;br /&gt;
                     '''if''' (thetaList.Count=='''0''') '''continue''';&lt;br /&gt;
                     //将存储的角度,距离,反光度信息转换为点云列表&lt;br /&gt;
                     '''for''' ('''int''' i = '''0'''; i &amp;lt; thetaList.Count; ++i)&lt;br /&gt;
                     {&lt;br /&gt;
                         cloud.'''Add'''('''new''' LidarPoint2D&lt;br /&gt;
                         {&lt;br /&gt;
                             th = (mirror ? -thetaList[i] : thetaList[i]),//倒转角度取反&lt;br /&gt;
                             d = distList[i],&lt;br /&gt;
                             intensity = intensityList[i] / ReflexRange // 反光度归一化,(如何设备返回的是回波强度,不是反光度,需要转换为反广度,例如乘以距离,具体转换效果需要实测,观察点云可视化,通过调整ReflexRange需要让反光板处点云明显比别处点云偏红)&lt;br /&gt;
                         });&lt;br /&gt;
                     }&lt;br /&gt;
                     cachedLidar = cloud.'''Where'''(pt =&amp;gt; pt.th &amp;gt;= angleStart &amp;amp;&amp;amp; pt.th &amp;lt;= angleEnd &amp;amp;&amp;amp; pt.d&amp;gt;minDist &amp;amp;&amp;amp; pt.d&amp;lt;maxDist).'''ToArray'''();//将th in [angleStart,angleEnd],d in [minDist,maxDist] 范围内的点云赋值给cachedlidar&lt;br /&gt;
                     maxReflex = cachedLidar.'''Select'''(p=&amp;gt;p.intensity).'''Max'''();//更新当前帧的最大反光度&lt;br /&gt;
                     frame += '''1''';//frame累加一次&lt;br /&gt;
                     interval = (DateTime.Now - ticStart).TotalMilliseconds;//更新扫描一帧点云的时间&lt;br /&gt;
                     ticStart = DateTime.Now;//重置开始时间&lt;br /&gt;
                     tick = DateTime.Now.Ticks;//更新当前tick&lt;br /&gt;
                     '''output'''();//上传数据&lt;br /&gt;
                     //清空四个列表&lt;br /&gt;
                     cloud.'''Clear'''();&lt;br /&gt;
                     thetaList.'''Clear'''();&lt;br /&gt;
                     distList.'''Clear'''();&lt;br /&gt;
                     intensityList.'''Clear'''();&lt;br /&gt;
                 }&lt;br /&gt;
 				//解析pck中的数据填写到thetaList,distList,intensityList中&lt;br /&gt;
                 '''FillData'''();//根据不通雷达的报文协议进行解析&lt;br /&gt;
                 //如果原始雷达定义的角度0°方向不在雷达正前方,需要将读到的点云角度加上一个固定的角度,使0°方向在雷达正前方,然后加入thetaList中&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
 		//定义启动函数&lt;br /&gt;
         '''public''' '''void''' '''Start'''('''string''' ip,'''int''' port = '''2110''')&lt;br /&gt;
         {&lt;br /&gt;
             Console.'''WriteLine'''($&amp;quot;WLR716Lidar on {ip}&amp;quot;);&lt;br /&gt;
             '''this'''._ip = ip;&lt;br /&gt;
             //新建线程进行连接读取,如果读取异常,重新执行Loop函数&lt;br /&gt;
             '''new''' '''Thread'''(() =&amp;gt;&lt;br /&gt;
             {&lt;br /&gt;
                 Console.'''WriteLine'''($&amp;quot;Try WLR716Lidar&amp;quot;);&lt;br /&gt;
                 '''while''' ('''true''')&lt;br /&gt;
                 {&lt;br /&gt;
                     '''try'''&lt;br /&gt;
                     {&lt;br /&gt;
                         ConnectTimes+='''1''';//连接次数+1&lt;br /&gt;
                         '''Loop'''();&lt;br /&gt;
                     }&lt;br /&gt;
                     '''catch''' (Exception ex)&lt;br /&gt;
                     {&lt;br /&gt;
                         Console.'''WriteLine'''($&amp;quot;msg:{ex.Message}, stack:{ex.StackTrace}&amp;quot;);&lt;br /&gt;
                         Thread.'''Sleep'''('''1000''');&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             }).'''Start'''();&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
生成插件后，需在Medulla的startup.iocmd中增加以下代码：&lt;br /&gt;
 //io load xxx.dll时，会寻找dll里面class MainIOObject并实例化相应的对象赋值给等号左侧的lidar&lt;br /&gt;
 lidar=io load plugins/WLR716Lidar.dll&lt;br /&gt;
 //Start对应Start函数，传的参数放在后面，空格隔开。如WLR716雷达中Start方法有ip和port两个参数，所以需要传两个参数&lt;br /&gt;
 lidar Start '''192.168'''.'''0.2''' '''2110'''&lt;/div&gt;</summary>
		<author><name>Artheru</name></author>
	</entry>
</feed>