A-LOAM工程笔记(二):前端点云预处置处罚及特征提取 ...

打印 上一主题 下一主题

主题 1589|帖子 1589|积分 4767

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x


一、前言

LOAM算法前端主要包含对lidar 点云的预处置处罚及点线特征和点面特征的提取。这些功能实现在scanRegistration.cpp中。
二、主要流程

  1. int main(int argc, char **argv)
  2. {
  3.     ros::init(argc, argv, "scanRegistration");
  4.     ros::NodeHandle nh;
  5.     nh.param<int>("scan_line", N_SCANS, 16);
  6.     nh.param<double>("minimum_range", MINIMUM_RANGE, 0.1);
  7.     printf("scan line number %d \n", N_SCANS);
  8.     if(N_SCANS != 16 && N_SCANS != 32 && N_SCANS != 64)
  9.     {
  10.         printf("only support velodyne with 16, 32 or 64 scan line!");
  11.         return 0;
  12.     }
  13.     ros::Subscriber subLaserCloud = nh.subscribe<sensor_msgs::PointCloud2>("/velodyne_points", 100, laserCloudHandler);
  14.     pubLaserCloud = nh.advertise<sensor_msgs::PointCloud2>("/velodyne_cloud_2", 100);
  15.     pubCornerPointsSharp = nh.advertise<sensor_msgs::PointCloud2>("/laser_cloud_sharp", 100);
  16.     pubCornerPointsLessSharp = nh.advertise<sensor_msgs::PointCloud2>("/laser_cloud_less_sharp", 100);
  17.     pubSurfPointsFlat = nh.advertise<sensor_msgs::PointCloud2>("/laser_cloud_flat", 100);
  18.     pubSurfPointsLessFlat = nh.advertise<sensor_msgs::PointCloud2>("/laser_cloud_less_flat", 100);
  19.     pubRemovePoints = nh.advertise<sensor_msgs::PointCloud2>("/laser_remove_points", 100);
  20.     if(PUB_EACH_LINE)
  21.     {
  22.         for(int i = 0; i < N_SCANS; i++)
  23.         {
  24.             ros::Publisher tmp = nh.advertise<sensor_msgs::PointCloud2>("/laser_scanid_" + std::to_string(i), 100);
  25.             pubEachScan.push_back(tmp);
  26.         }
  27.     }
  28.     ros::spin();
  29.     return 0;
  30. }
复制代码
主要流程包含:
(1)ros节点和句柄初始化,雷达线数"scan_line"和盲区"minimum_range"两个参数的设置,分别设置为16线和0.1m。
(2) 订阅topic"/velodyne_points",绑定回调函数laserCloudHandler(重要),对吸收到的点云举行处置处罚。
(3)pubLaserCloud发布原始点云;pubCornerPointsSharp发布曲率大的角点点云;pubCornerPointsLessSharp发布曲率小一些的角点点云;pubSurfPointsFlat发布面点点云;pubSurfPointsLessFlat发布曲率更小面点点云;pubRemovePoints发布移除的点云。
(4)若PUB_EACH_LINE设置的是true,根据laser_scanid发布差别id的点云。
三、点云预处置处罚

1)removeClosedPointCloud():
  1. template <typename PointT>
  2. void removeClosedPointCloud(const pcl::PointCloud<PointT> &cloud_in,
  3.                               pcl::PointCloud<PointT> &cloud_out, float thres)
  4. {
  5.     if (&cloud_in != &cloud_out)
  6.     {
  7.         cloud_out.header = cloud_in.header;
  8.         cloud_out.points.resize(cloud_in.points.size());
  9.     }
  10.     size_t j = 0;
  11.     for (size_t i = 0; i < cloud_in.points.size(); ++i)
  12.     {
  13.         if (cloud_in.points[i].x * cloud_in.points[i].x + cloud_in.points[i].y * cloud_in.points[i].y +
  14.            cloud_in.points[i].z * cloud_in.points[i].z < thres * thres)
  15.             continue;
  16.         cloud_out.points[j] = cloud_in.points[i];
  17.         j++;
  18.     }
  19.     if (j != cloud_in.points.size())
  20.     {
  21.         cloud_out.points.resize(j);
  22.     }
  23.     cloud_out.height = 1;
  24.     cloud_out.width = static_cast<uint32_t>(j);
  25.     cloud_out.is_dense = true;
  26. }
复制代码
根据设置的参数thres,剔除小于这个距离内过于靠近的点云. 设置点云宽度(当前束激光保留点云个数),高度1(拆分成了单束),is_dense = true。
2)laserCloudHandler():
  1. void laserCloudHandler(const sensor_msgs::PointCloud2ConstPtr &laserCloudMsg)
  2. {
  3.     if (!systemInited)
  4.     {
  5.         systemInitCount++;
  6.         if (systemInitCount >= systemDelay)
  7.         {
  8.             systemInited = true;
  9.         }
  10.         else
  11.             return;
  12.     }
  13.     TicToc t_whole;
  14.     TicToc t_prepare;
  15.     std::vector<int> scanStartInd(N_SCANS, 0);
  16.     std::vector<int> scanEndInd(N_SCANS, 0);
  17.     pcl::PointCloud<pcl::PointXYZ> laserCloudIn;
  18.     pcl::fromROSMsg(*laserCloudMsg, laserCloudIn);
  19.     std::vector<int> indices;
  20.     // ���ȶԵ����˲���ȥ��NaNֵ����Ч���ƣ��Լ���Lidar����ϵԭ��MINIMUM_RANGE�������ڵĵ�
  21.     pcl::removeNaNFromPointCloud(laserCloudIn, laserCloudIn, indices);
  22.     removeClosedPointCloud(laserCloudIn, laserCloudIn, MINIMUM_RANGE);
  23.     int cloudSize = laserCloudIn.points.size();
  24.     float startOri = -atan2(laserCloudIn.points[0].y, laserCloudIn.points[0].x);
  25.     float endOri = -atan2(laserCloudIn.points[cloudSize - 1].y,
  26.                           laserCloudIn.points[cloudSize - 1].x) +
  27.                    2 * M_PI;
  28.     if (endOri - startOri > 3 * M_PI)
  29.     {
  30.         endOri -= 2 * M_PI;
  31.     }
  32.     else if (endOri - startOri < M_PI)
  33.     {
  34.         endOri += 2 * M_PI;
  35.     }
  36.     //printf("end Ori %f\n", endOri);
  37.     bool halfPassed = false;
  38.     int count = cloudSize;
  39.     PointType point;
  40.     std::vector<pcl::PointCloud<PointType>> laserCloudScans(N_SCANS);
  41.     for (int i = 0; i < cloudSize; i++)
  42.     {
  43.         point.x = laserCloudIn.points[i].x;
  44.         point.y = laserCloudIn.points[i].y;
  45.         point.z = laserCloudIn.points[i].z;
  46.         float angle = atan(point.z / sqrt(point.x * point.x + point.y * point.y)) * 180 / M_PI;
  47.         int scanID = 0;
  48.         if (N_SCANS == 16)
  49.         {
  50.             scanID = int((angle + 15) / 2 + 0.5);
  51.             if (scanID > (N_SCANS - 1) || scanID < 0)
  52.             {
  53.                 count--;
  54.                 continue;
  55.             }
  56.         }
  57.         else if (N_SCANS == 32)
  58.         {
  59.             scanID = int((angle + 92.0/3.0) * 3.0 / 4.0);
  60.             if (scanID > (N_SCANS - 1) || scanID < 0)
  61.             {
  62.                 count--;
  63.                 continue;
  64.             }
  65.         }
  66.         else if (N_SCANS == 64)
  67.         {   
  68.             if (angle >= -8.83)
  69.                 scanID = int((2 - angle) * 3.0 + 0.5);
  70.             else
  71.                 scanID = N_SCANS / 2 + int((-8.83 - angle) * 2.0 + 0.5);
  72.             // use [0 50]  > 50 remove outlies
  73.             if (angle > 2 || angle < -24.33 || scanID > 50 || scanID < 0)
  74.             {
  75.                 count--;
  76.                 continue;
  77.             }
  78.         }
  79.         else
  80.         {
  81.             printf("wrong scan number\n");
  82.             ROS_BREAK();
  83.         }
  84.         //printf("angle %f scanID %d \n
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

用户云卷云舒

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表