当前位置:首页 > 文章列表 > 科技周边 > 人工智能 > 一文解读自动驾驶中的激光雷达点云分割算法

一文解读自动驾驶中的激光雷达点云分割算法

来源:51CTO.COM 2023-04-30 07:44:47 0浏览 收藏

怎么入门科技周边编程?需要学习哪些知识点?这是新手们刚接触编程时常见的问题;下面golang学习网就来给大家整理分享一些知识点,希望能够给初学者一些帮助。本篇文章就来介绍《一文解读自动驾驶中的激光雷达点云分割算法》,涉及到,有需要的可以收藏一下

目前常见的激光点云分割算法有基于平面拟合的方法和基于激光点云数据特点的方法两类。具体如下:

图片

点云地面分割算法

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://github.com/suyunzzz/ray_filter_ground​

算法思想

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://github.com/jkk-research/urban_road_filter​

z_zero_method

图片

z_zero_method

首先将数据组织成[channels][thetas]

对于每一条线,对角度进行排序

  1. 以当前点p为中心,向左选k个点,向右选k个点
  2. 分别计算左边及右边k个点与当前点在x和y方向差值的均值
  3. 同时计算左边及右边k个点的最大z值max1及max2
  4. 根据余弦定理求解余弦角

如果余弦角度满足阈值且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]

对于每一条线,对角度进行排序

  1. 以当前点p为中心,向右选第k/2个点p1和第k个点p2
  2. 分别计算p及p1、p1及p2、p及p2间z方向的距离
  3. 根据余弦定理求解余弦角

如果余弦角度满足阈值且p1.z-p.z满足阈值或p1.z-p2.z满足阈值且p.z-p2.z满足阈值,认为此点为障碍物

star_search_method

该方法将点云划分为矩形段,这些形状的组合像一颗星;这就是名字的来源,从每个路段提取可能的人行道起点,其中创建的算法对基于Z坐标的高度变化不敏感,这意味着在实践中,即使当激光雷达相对于路面平面倾斜时,该算法也会表现良好,在柱坐标系中处理点云。

具体实现:

图片

star_search_method

好了,本文到此结束,带大家了解了《一文解读自动驾驶中的激光雷达点云分割算法》,希望本文对你有所帮助!关注golang学习网公众号,给大家分享更多科技周边知识!

版本声明
本文转载于:51CTO.COM 如有侵犯,请联系study_golang@163.com删除
Apple 的 35W 双 USB-C 电源适配器 [U:照片]Apple 的 35W 双 USB-C 电源适配器 [U:照片]
上一篇
Apple 的 35W 双 USB-C 电源适配器 [U:照片]
Windows 11 Build 25131 (Dev):你应该知道的一切
下一篇
Windows 11 Build 25131 (Dev):你应该知道的一切
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    542次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    508次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    497次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    484次学习
查看更多
AI推荐
  • AI Make Song:零门槛AI音乐创作平台,助你轻松制作个性化音乐
    AI Make Song
    AI Make Song是一款革命性的AI音乐生成平台,提供文本和歌词转音乐的双模式输入,支持多语言及商业友好版权体系。无论你是音乐爱好者、内容创作者还是广告从业者,都能在这里实现“用文字创造音乐”的梦想。平台已生成超百万首原创音乐,覆盖全球20个国家,用户满意度高达95%。
    7次使用
  • SongGenerator.io:零门槛AI音乐生成器,快速创作高质量音乐
    SongGenerator
    探索SongGenerator.io,零门槛、全免费的AI音乐生成器。无需注册,通过简单文本输入即可生成多风格音乐,适用于内容创作者、音乐爱好者和教育工作者。日均生成量超10万次,全球50国家用户信赖。
    7次使用
  •  BeArt AI换脸:免费在线工具,轻松实现照片、视频、GIF换脸
    BeArt AI换脸
    探索BeArt AI换脸工具,免费在线使用,无需下载软件,即可对照片、视频和GIF进行高质量换脸。体验快速、流畅、无水印的换脸效果,适用于娱乐创作、影视制作、广告营销等多种场景。
    6次使用
  • SEO标题协启动:AI驱动的智能对话与内容生成平台 - 提升创作效率
    协启动
    SEO摘要协启动(XieQiDong Chatbot)是由深圳协启动传媒有限公司运营的AI智能服务平台,提供多模型支持的对话服务、文档处理和图像生成工具,旨在提升用户内容创作与信息处理效率。平台支持订阅制付费,适合个人及企业用户,满足日常聊天、文案生成、学习辅助等需求。
    13次使用
  • Brev AI:零注册门槛的全功能免费AI音乐创作平台
    Brev AI
    探索Brev AI,一个无需注册即可免费使用的AI音乐创作平台,提供多功能工具如音乐生成、去人声、歌词创作等,适用于内容创作、商业配乐和个人创作,满足您的音乐需求。
    14次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码