「深度解析」:探究自动驾驶中的激光雷达点云分割算法
目前常见的激光点云分割算法有基于平面拟合的方法和基于激光点云数据特点的方法两类。具体如下:
点云地面分割算法
01 基于平面拟合的方法-Ground Plane Fitting
算法思想:一种简单的处理方法就是沿着x方向(车头的方向)将空间分割成若干个子平面,然后对每个子平面使用地面平面拟合算法(GPF)从而得到能够处理陡坡的地面分割方法。该方法是在单帧点云中拟合全局平面,在点云数量较多时效果较好,点云稀疏时极易带来漏检和误检,比如16线激光雷达。
算法伪代码:
伪代码
算法流程是对于给定的点云 P ,分割的最终结果为两个点云集合,地面点云 和非地面点云。此算法有四个重要参数,如下:
- Niter : 进行奇异值分解(SVD)的次数,也即进行优化拟合的次数
- NLPR : 用于选取LPR的最低高度点的数量
- Thseed : 用于选取种子点的阈值,当点云内的点的高度小于LPR的高度加上此阈值时,我们将该点加入种子点集
- Thdist : 平面距离阈值,我们会计算点云中每一个点到我们拟合的平面的正交投影的距离,而这个平面距离阈值,就是用来判定点是否属于地面
种子点集的选择
我们首先选取一个种子点集(seed point set),这些种子点来源于点云中高度(即z值)较小的点,种子点集被用于建立描述地面的初始平面模型,那么如何选取这个种子点集呢?我们引入最低点代表(Lowest Point Representative, LPR)的概念。LPR就是NLPR个最低高度点的平均值,LPR保证了平面拟合阶段不受测量噪声的影响。
种子点的选择
输入是一帧点云,这个点云内的点已经沿着z方向(即高度)做了排序,取 num_lpr_ 个最小点,求得高度平均值 lpr_height(即LPR),选取高度小于 lpr_height + th_seeds_的点作为种子点。
具体代码实现如下
/* @brief Extract initial seeds of the given pointcloud sorted segment. This function filter ground seeds points accoring to heigt. This function will set the `g_ground_pc` to `g_seed_pc`. @param p_sorted: sorted pointcloud @param ::num_lpr_: num of LPR points @param ::th_seeds_: threshold distance of seeds @param :: */ void PlaneGroundFilter::extract_initial_seeds_(const pcl::PointCloud &p_sorted) { // LPR is the mean of low point representative double sum = 0; int cnt = 0; // Calculate the mean height value. for (int i = 0; i
平面模型
接下来我们建立一个平面模型,点云中的点到这个平面的正交投影距离小于阈值Thdist,则认为该点属于地面,否则属于非地面。采用一个简单的线性模型用于平面模型估计,如下:
ax+by+cz+d=0
即:
其中
,通过初始点集的协方差矩阵C来求解n,从而确定一个平面,种子点集作为初始点集,其协方差矩阵为
这个协方差矩阵 C 描述了种子点集的散布情况,其三个奇异向量可以通过奇异值分解(SVD)求得,这三个奇异向量描述了点集在三个主要方向的散布情况。由于是平面模型,垂直于平面的法向量 n 表示具有最小方差的方向,可以通过计算具有最小奇异值的奇异向量来求得。
那么在求得了 n 以后, d 可以通过代入种子点集的平均值 ,s(它代表属于地面的点) 直接求得。整个平面模型计算代码如下:
/* @brief The function to estimate plane model. The model parameter `normal_` and `d_`, and `th_dist_d_` is set here. The main step is performed SVD(UAV) on covariance matrix. Taking the sigular vector in U matrix according to the smallest sigular value in A, as the `normal_`. `d_` is then calculated according to mean ground points. @param g_ground_pc:global ground pointcloud ptr. */ void PlaneGroundFilter::estimate_plane_(void) { // Create covarian matrix in single pass. // TODO: compare the efficiency. Eigen::Matrix3f cov; Eigen::Vector4f pc_mean; pcl::computeMeanAndCovarianceMatrix(*g_ground_pc, cov, pc_mean); // Singular Value Decomposition: SVD JacobiSVD svd(cov, Eigen::DecompositionOptions::ComputeFullU); // use the least singular vector as normal normal_ = (svd.matrixU().col(2)); // mean ground seeds value Eigen::Vector3f seeds_mean = pc_mean.head(); // according to normal.T*[x,y,z] = -d d_ = -(normal_.transpose() * seeds_mean)(0, 0); // set distance threhold to `th_dist - d` th_dist_d_ = th_dist_ - d_; // return the equation parameters }
优化平面主循环
extract_initial_seeds_(laserCloudIn); g_ground_pc = g_seeds_pc; // Ground plane fitter mainloop for (int i = 0; i clear(); g_not_ground_pc->clear(); //pointcloud to matrix MatrixXf points(laserCloudIn_org.points.size(), 3); int j = 0; for (auto p : laserCloudIn_org.points) { points.row(j++) points.push_back(laserCloudIn_org[r]); } } }
得到这个初始的平面模型以后,我们会计算点云中每一个点到该平面的正交投影的距离,即 points * normal_,并且将这个距离与设定的阈值(即th_dist_d_) 比较,当高度差小于此阈值,我们认为该点属于地面,当高度差大于此阈值,则为非地面点。经过分类以后的所有地面点被当作下一次迭代的种子点集,迭代优化。
02 基于雷达数据本身特点的方法-Ray Ground Filter
代码
https://www.php.cn/link/a8d3b1e36a14da038a06f675d1693dd8
算法思想
Ray Ground Filter算法的核心是以射线(Ray)的形式来组织点云。将点云的 (x, y, z)三维空间降到(x,y)平面来看,计算每一个点到车辆x正方向的平面夹角 θ, 对360度进行微分,分成若干等份,每一份的角度为0.2度。
激光线束等间隔划分示意图(通常以激光雷达角度分辨率划分)
同一角度范围内激光线束在水平面的投影以及在Z轴方向的高度折线示意图
为了方便对同一角度的线束进行处理,要将原来直角坐标系的点云转换成柱坐标描述的点云数据结构。对同一夹角的线束上的点按照半径的大小进行排序,通过前后两点的坡度是否大于我们事先设定的坡度阈值,从而判断点是否为地面点。
线激光线束纵截面与俯视示意图(n=4)
通过如下公式转换成柱坐标的形式:
转换成柱坐标的公式
radius表示点到lidar的水平距离(半径),theta是点相对于车头正方向(即x方向)的夹角。对点云进行水平角度微分之后,可得到1800条射线,将这些射线中的点按照距离的远近进行排序。通过两个坡度阈值以及当前点的半径求得高度阈值,通过判断当前点的高度(即点的z值)是否在地面加减高度阈值范围内来判断当前点是为地面。
伪代码
伪代码
- local_max_slope_ :设定的同条射线上邻近两点的坡度阈值。
- general_max_slope_ :整个地面的坡度阈值
遍历1800条射线,对于每一条射线进行如下操作:
1.计算当前点和上一个点的水平距离pointdistance
2.根据local_max_slope_和pointdistance计算当前的坡度差阈值height_threshold
3.根据general_max_slope_和当前点的水平距离计算整个地面的高度差阈值general_height_threshold
4.若当前点的z坐标小于前一个点的z坐标加height_threshold并大于前一个点的z坐标减去height_threshold:
5.若当前点z坐标小于雷达安装高度减去general_height_threshold并且大于相加,认为是地面点
6.否则:是非地面点。
7.若pointdistance满足阈值并且前点的z坐标小于雷达安装高度减去height_threshold并大于雷达安装高度加上height_threshold,认为是地面点。
/*! * * @param[in] in_cloud Input Point Cloud to be organized in radial segments * @param[out] out_organized_points Custom Point Cloud filled with XYZRTZColor data * @param[out] out_radial_divided_indices Indices of the points in the original cloud for each radial segment * @param[out] out_radial_ordered_clouds Vector of Points Clouds, each element will contain the points ordered */ void PclTestCore::XYZI_to_RTZColor(const pcl::PointCloud::Ptr in_cloud, PointCloudXYZIRTColor &out_organized_points, std::vector &out_radial_divided_indices, std::vector &out_radial_ordered_clouds) { out_organized_points.resize(in_cloud->points.size()); out_radial_divided_indices.clear(); out_radial_divided_indices.resize(radial_dividers_num_); out_radial_ordered_clouds.resize(radial_dividers_num_); for (size_t i = 0; i points.size(); i++) { PointXYZIRTColor new_point; //计算radius和theta //方便转到柱坐标下。 auto radius = (float)sqrt( in_cloud->points[i].x * in_cloud->points[i].x + in_cloud->points[i].y * in_cloud->points[i].y); auto theta = (float)atan2(in_cloud->points[i].y, in_cloud->points[i].x) * 180 / M_PI; if (theta points[i]; new_point.radius = radius; new_point.theta = theta; new_point.radial_div = radial_div; new_point.concentric_div = concentric_div; new_point.original_index = i; out_organized_points[i] = new_point; //radial divisions更加角度的微分组织射线 out_radial_divided_indices[radial_div].indices.push_back(i); out_radial_ordered_clouds[radial_div].push_back(new_point); } //end for //将同一根射线上的点按照半径(距离)排序 #pragma omp for for (size_t i = 0; i
03 基于雷达数据本身特点的方法-urban road filter
原文
Real-Time LIDAR-Based Urban Road and Sidewalk Detection for Autonomous Vehicles
代码
https://www.php.cn/link/305fa4e2c0e76dd586553d64c975a626
z_zero_method
z_zero_method
首先将数据组织成[channels][thetas]
对于每一条线,对角度进行排序
- 以当前点p为中心,向左选k个点,向右选k个点
- 分别计算左边及右边k个点与当前点在x和y方向差值的均值
- 同时计算左边及右边k个点的最大z值max1及max2
- 根据余弦定理求解余弦角
如果余弦角度满足阈值且max1减去p.z满足阈值或max2减去p.z满足阈值且max2-max1满足阈值,认为此点为障碍物,否则就认为是地面点。
x_zero_method
X-zero和Z-zero方法可以找到避开测量的X和Z分量的人行道,X-zero和Z-zero方法都考虑了体素的通道数,因此激光雷达必须与路面平面不平行,这是上述两种算法以及整个城市道路滤波方法的已知局限性。X-zero方法去除了X方向的值,使用柱坐标代替。
x_zero_method
首先将数据组织成[channels][thetas]
对于每一条线,对角度进行排序
- 以当前点p为中心,向右选第k/2个点p1和第k个点p2
- 分别计算p及p1、p1及p2、p及p2间z方向的距离
- 根据余弦定理求解余弦角
如果余弦角度满足阈值且p1.z-p.z满足阈值或p1.z-p2.z满足阈值且p.z-p2.z满足阈值,认为此点为障碍物
star_search_method
该方法将点云划分为矩形段,这些形状的组合像一颗星;这就是名字的来源,从每个路段提取可能的人行道起点,其中创建的算法对基于Z坐标的高度变化不敏感,这意味着在实践中,即使当激光雷达相对于路面平面倾斜时,该算法也会表现良好,在柱坐标系中处理点云。
具体实现:
star_search_method
以上是「深度解析」:探究自动驾驶中的激光雷达点云分割算法的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

写在前面&笔者的个人理解三维Gaussiansplatting(3DGS)是近年来在显式辐射场和计算机图形学领域出现的一种变革性技术。这种创新方法的特点是使用了数百万个3D高斯,这与神经辐射场(NeRF)方法有很大的不同,后者主要使用隐式的基于坐标的模型将空间坐标映射到像素值。3DGS凭借其明确的场景表示和可微分的渲染算法,不仅保证了实时渲染能力,而且引入了前所未有的控制和场景编辑水平。这将3DGS定位为下一代3D重建和表示的潜在游戏规则改变者。为此我们首次系统地概述了3DGS领域的最新发展和关

昨天面试被问到了是否做过长尾相关的问题,所以就想着简单总结一下。自动驾驶长尾问题是指自动驾驶汽车中的边缘情况,即发生概率较低的可能场景。感知的长尾问题是当前限制单车智能自动驾驶车辆运行设计域的主要原因之一。自动驾驶的底层架构和大部分技术问题已经被解决,剩下的5%的长尾问题,逐渐成了制约自动驾驶发展的关键。这些问题包括各种零碎的场景、极端的情况和无法预测的人类行为。自动驾驶中的边缘场景"长尾"是指自动驾驶汽车(AV)中的边缘情况,边缘情况是发生概率较低的可能场景。这些罕见的事件

0.写在前面&&个人理解自动驾驶系统依赖于先进的感知、决策和控制技术,通过使用各种传感器(如相机、激光雷达、雷达等)来感知周围环境,并利用算法和模型进行实时分析和决策。这使得车辆能够识别道路标志、检测和跟踪其他车辆、预测行人行为等,从而安全地操作和适应复杂的交通环境.这项技术目前引起了广泛的关注,并认为是未来交通领域的重要发展领域之一。但是,让自动驾驶变得困难的是弄清楚如何让汽车了解周围发生的事情。这需要自动驾驶系统中的三维物体检测算法可以准确地感知和描述周围环境中的物体,包括它们的位置、

一先导与重点文章主要介绍自动驾驶技术中几种常用的坐标系统,以及他们之间如何完成关联和转换,最终构建出统一的环境模型。这里重点理解自车到相机刚体转换(外参),相机到图像转换(内参),图像到像素有单位转换。3d向2d转换会有相应的畸变,平移等。重点:自车坐标系相机机体坐标系需要被重写的是:平面坐标系像素坐标系难点:要考虑图像畸变,去畸变和加畸变都是在像平面上去补偿二简介视觉系统一共有四个坐标系:像素平面坐标系(u,v)、图像坐标系(x,y)、相机坐标系()和世界坐标系()。每种坐标系之间均存在联系,

轨迹预测在自动驾驶中承担着重要的角色,自动驾驶轨迹预测是指通过分析车辆行驶过程中的各种数据,预测车辆未来的行驶轨迹。作为自动驾驶的核心模块,轨迹预测的质量对于下游的规划控制至关重要。轨迹预测任务技术栈丰富,需要熟悉自动驾驶动/静态感知、高精地图、车道线、神经网络架构(CNN&GNN&Transformer)技能等,入门难度很大!很多粉丝期望能够尽快上手轨迹预测,少踩坑,今天就为大家盘点下轨迹预测常见的一些问题和入门学习方法!入门相关知识1.预习的论文有没有切入顺序?A:先看survey,p

原标题:SIMPL:ASimpleandEfficientMulti-agentMotionPredictionBaselineforAutonomousDriving论文链接:https://arxiv.org/pdf/2402.02519.pdf代码链接:https://github.com/HKUST-Aerial-Robotics/SIMPL作者单位:香港科技大学大疆论文思路:本文提出了一种用于自动驾驶车辆的简单高效的运动预测基线(SIMPL)。与传统的以代理为中心(agent-cent

写在前面&出发点端到端的范式使用统一的框架在自动驾驶系统中实现多任务。尽管这种范式具有简单性和清晰性,但端到端的自动驾驶方法在子任务上的性能仍然远远落后于单任务方法。同时,先前端到端方法中广泛使用的密集鸟瞰图(BEV)特征使得扩展到更多模态或任务变得困难。这里提出了一种稀疏查找为中心的端到端自动驾驶范式(SparseAD),其中稀疏查找完全代表整个驾驶场景,包括空间、时间和任务,无需任何密集的BEV表示。具体来说,设计了一个统一的稀疏架构,用于包括检测、跟踪和在线地图绘制在内的任务感知。此外,重

最近一个月由于众所周知的一些原因,非常密集地和行业内的各种老师同学进行了交流。交流中必不可免的一个话题自然是端到端与火爆的特斯拉FSDV12。想借此机会,整理一下在当下这个时刻的一些想法和观点,供大家参考和讨论。如何定义端到端的自动驾驶系统,应该期望端到端解决什么问题?按照最传统的定义,端到端的系统指的是一套系统,输入传感器的原始信息,直接输出任务关心的变量。例如,在图像识别中,CNN相对于传统的特征提取器+分类器的方法就可以称之为端到端。在自动驾驶任务中,输入各种传感器的数据(相机/LiDAR
