[关闭]
@iStarLee 2019-07-10T07:57:26.000000Z 字数 3675 阅读 588

LeGO-LOAM算法解析

SLAM-LaserSLAM


Author Wenqiang Chen, Pengpeng Su, Silin Li
Data 07/01/2019

1 ImageProjection模块

1.1 激光雷达数据处理数学模型

1.2 3D点云投影到2D深度图

1.2 去除地面点

image_1df8rsejpu9o1ego1rgm1ioj1v0n9.png-67kB
上图是去除地面点的原理示意图,如果上下两线之间点的XYZ坐标差构成的的俯仰角小于一定的阈值,程序中设置的是10°,那么可以认为是地面点。

核心代码如下

  1. // 如果俯仰角在10度以内,则判定(i,j)为地面点,groundMat[i][j]=1
  2. // 否则,则不是地面点,初始化为0,进行后续操作
  3. diffX = fullCloud->points[upperInd].x - fullCloud->points[lowerInd].x;
  4. diffY = fullCloud->points[upperInd].y - fullCloud->points[lowerInd].y;
  5. diffZ = fullCloud->points[upperInd].z - fullCloud->points[lowerInd].z;
  6. angle = atan2(diffZ, sqrt(diffX*diffX + diffY*diffY))*180/M_PI;
  7. if (abs(angle - sensorMountAngle) <= 10)
  8. {
  9. groundMat.at<int8_t>(i, j) = 1;
  10. groundMat.at<int8_t>(i + 1, j) = 1;
  11. }

1.3 点云分割

1.3.1 物体聚类算法原理

image_1df8ukotk15qrjn0jf31pda11n7m.png-113.5kB
image_1df8um3a6v591qdo1nqr6r61pq613.png-68kB

从顶视图看,这是1束激光(一共有16束)先后扫描到的两个点A和点B。OA和OB是扫描点和激光雷达传感器之间的距离。 我们可以在图中计算角。

上面的角可以按照激光雷达的水平角分辨率来设置阈值。
同样在竖直方向上,上下两个激光束之间扫描到的两个点也可以按照这种方法进行判断分类,只不过角度阈值设置为激光雷达垂直分辨率罢了。

1.3.2 分割算法流程

根据前面的处理,我们得到了如下信息:

1.3.3 labelComponents算法

事实上是一个四邻域查找算法,算法伪代码如下:

  1. //全局变量
  2. label = 1
  3. rangeMat(rangeMat0的位置是没有标记过的)
  4. void labelComponents(row, col, label)
  5. {
  6. queue_size = 1;
  7. queue.push(row,col);
  8. all_queue.push(row,col);
  9. lineCountFlag[SCAN_ID] = false;//SCAN_ID=16雷达扫描线束总数
  10. while(queue.size>0)
  11. {
  12. row, col = queue.top();
  13. labelMat(row, col) = label;
  14. for(iter : neighbors of (row, col))//遍历该元素的四邻域
  15. {
  16. row,col = iter.row, iter.col;
  17. //标记过的点直接忽略
  18. if (labelMat(row,col) != 0)
  19. continue;
  20. //得到分离物体的角度阈值
  21. if(iter->position == horizon)
  22. beta_threshold = 0.2;//激光雷达水平角分辨率
  23. else
  24. beta_threshold = 2;//激光雷达垂直角分辨率
  25. //根据分割算法原理计算当前beta角
  26. beta_angle = atan2(d2*sin(alpha), (d1 - d2*cos(alpha)));
  27. if(beta_angle > beta_threshold)
  28. {
  29. queue.push(row, col);//将此neighbor加入queue
  30. all_queue.push(row, col)
  31. labelMat(row, col) = label;
  32. lineCountFlag[this_scan_id] = true;//垂直方向标记计数
  33. }
  34. }
  35. }
  36. //分辨是否是有效聚类,如果是则增加labelCount,标记下一块,如果不是,就标记为outliers点
  37. feasibleSegment = false;
  38. if(all_queue.size>=30)// 如果聚类超过30个点,直接标记为一个可用聚类
  39. feasibleSegment = true;
  40. else if(all_queue.size>=5)// 如果聚类点数小于30大于等于5,统计竖直方向上的聚类点数
  41. {
  42. //遍历lineCountFlag[SCAN_ID]统计true的个数lineCount
  43. if(lineCount>=3)
  44. feasibleSegment = true;// 竖直方向上超过3个也将它标记为有效聚类
  45. }
  46. if(feasibleSegment==true)
  47. {
  48. label++;
  49. }
  50. else
  51. {
  52. for(iter : all_queue)
  53. {
  54. row, col = iter.row, iter.col;
  55. labelMat(row, col) = 999999;//如果不是有效聚类则标记outliers点
  56. }
  57. }
  58. }

2 FeatureAssociation模块

2.1 IMU去除重力影响

IMU的重力加速度模型,在世界坐标系下表示为


其中

加速计测量得到的值在世界坐标系下表示如下

换算到Body坐标系下

化简为

其中,是加速度计在Body系下的测量值, 是加速度计在Body系下的真实加速度值。通过这个公式可以将重力加速度从加速度计的测量值中去除。

回顾从I系到B系的坐标变换,此时我们使用ZYX欧拉角表示方法


其中,


image_1dfa71djc1bld1m47qjusdl1fbv9.png-33.9kB

所以,

2.2 点云畸变矫正(Adjust Distortion)

3 MapOptimazation模块

4 TransformFusion模块

Note:

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注