前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >自动驾驶 Apollo 源码分析系列,感知篇(七):Lidar 障碍物检测基本流程

自动驾驶 Apollo 源码分析系列,感知篇(七):Lidar 障碍物检测基本流程

作者头像
Frank909
发布2021-12-06 11:45:12
1.4K0
发布2021-12-06 11:45:12
举报
文章被收录于专栏:Frank909

Apollo 系统传感器是以 Lidar 为主的,本文整理在 Apollo 6.0 中 Lidar 的基本代码流程。

1. 从 Component 出发

因为有了之前红绿灯检测代码分析的经验,我们自然能够知道感知任务先从它的 component 开始。

lidar 检测的 component 是 modules/perception/onboard/component/detection_component.cc

梳理代码可以得到基础的流程框架:

在这里插入图片描述
在这里插入图片描述
1.1 initConfig

initConfig 从本地目录中读取 proto 文件,然后配置变量。 那么,如何知道从哪里读取呢? modules/perception/production/dag/dag_streaming_perception_lidar.dag 在 dag 目录下有配置。

在这里插入图片描述
在这里插入图片描述

我们只需找到 lane_detection_component.config 文件。

/apollo/modules/perception/production/conf/perception/lidar/velodyne128_detection_conf.pb.txt

在这里插入图片描述
在这里插入图片描述

配置文件说明了激活高精度地图,然后检测的结果存放在 DetectionObjects 这个 channel。

1.2 initAlgorithmPlugin
在这里插入图片描述
在这里插入图片描述

代码非常简单,创建一个 LidarObstacleDetection 对象,然后赋值给 detector_ 并初始化。 我们应该能够察觉到 LidarObstacleDetection 是算法核心实现类,后面我们将重点关注它。

1.3 Proc 和 InternalProc

Proc 方法中内部调用了 InternalProc 。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

InternalProc 的逻辑非常简单,主要是做一个消息结构体的转换。

代码语言:javascript
复制
in_message --> out_message

实际上就是

代码语言:javascript
复制
PointCloud --> LidarFrameMessage

点云数据到 LidarFrame 数据的转换。

实际上通过 detector_->Process() 完成。

我们可以把目光移到 LidarObstacleDetection 这个类上

2. detector_->Process() 算法逻辑

路径是:

代码语言:javascript
复制
modules/perception/lidar/app/lidar_obstacle_detection.cc
在这里插入图片描述
在这里插入图片描述

我们阅读代码,可以得到这样的流程图:

在这里插入图片描述
在这里插入图片描述

其实整个过程非常的清晰,分 2 步走。

代码语言:javascript
复制
1. 点云预处理
2. 点云检测
2.1 点云 Preprocesses() 和 ProcessCommon()

点云预处理比较简单,就是将 PointCloud 中的点云过滤,然后复制到 LidarFrame 结构体对应的 cloud 中。 代码地址:

代码语言:javascript
复制
modules/perception/lidar/lib/pointcloud_preprocessor/pointcloud_preprocessor.cc

代码片断

在这里插入图片描述
在这里插入图片描述

那好,下面看看 ProcessCommon() 中发生了什么?

在这里插入图片描述
在这里插入图片描述

这里面又有一个 detector,代码调用了其 Detect() 方法,所有的真相应该可以在这里揭开。

查看变量声明,不难找出 detector 是个什么东西。

在这里插入图片描述
在这里插入图片描述

detector 是由 PointPillarsDetection 实现的。

2.2 PointPillarsDetection

代码路径:

代码语言:javascript
复制
modules/perception/lidar/lib/detection/lidar_point_pillars/point_pillars_detection.cc

Apollo 6.0 中激光雷达检测算法是由 PointPillar 模型实现的,我之前有文章介绍了其模型设计思想:自动驾驶激光点云 3D 目标检测 PointPillar 论文简述

在本文我关注于 Lidar 整体检测流程而不是 PointPillar 模型思想,所以不会过多介绍 PointPillar 本身,有兴趣的同学可以查看我上面的链接。

Detect() 方法代码比较多,这里没法直接张贴,根据代码注释绘制了流程图。

在这里插入图片描述
在这里插入图片描述

点云送到模型检测前要经过 downsample 步骤。 downsample 还经过 2 次:

  • DownSamplePointCloudBeams
  • DownSampleByVoxelGrid
在这里插入图片描述
在这里插入图片描述

在这里 downsample_factor 是大于 1 的整数,是下采样的因子,有点像卷积操作中的 stride,每隔 downsample_factor 取一点,最终减少了总体点云数据量。

下采样之后,要进入 fuse 阶段。 fuse 的是当前的点云和之前的点云。

在这里插入图片描述
在这里插入图片描述

融合也不代表所有的历史点云都参与融合。

代码语言:javascript
复制
// before fusing
    while (!prev_world_clouds_.empty() &&
           frame->timestamp - prev_world_clouds_.front()->get_timestamp() >
               FLAGS_fuse_time_interval) {
      prev_world_clouds_.pop_front();
    }

超过 FLAGS_fuse_time_interval 就直接被剔除。

在这里插入图片描述
在这里插入图片描述

把过滤掉无效点云的历史数据全部加入当前点云当中。 问题:为什么点云需要前后数据的融合呢? 在代码中我直接看不明白,但我个人的猜测是:

无论是历史数据还是当前测量的数量,其实都存在误差,两者融合就有些像训练神经网络前处理中的数据增强,这样能够有效减少数据误差同时提升神经网络模型做点云检测的准确性和稳定性。

当然,这只是我个人的猜想,有不同理解的同学可以留言一起参与讨论。

数据融合之后,再做一些 shuffle 之类的操作就直接送到推断引擎中去做前向推断了,最后又通过神经网络输出的结果得到最终的检测目标。

在这里插入图片描述
在这里插入图片描述

推断引擎应用的是工厂模式,之前车道线检测的文章已经分析过,这里不再赘述。 倒是对 PointPillar 模型本身感兴趣的同学可以看下:

在这里插入图片描述
在这里插入图片描述

可以看到模型文件是 onnx 格式的,之前有的模型是 caffe2,有的是 libtorch,这说明 Apollo 框架确实强大。

最后的 GetObjects() 方法中代码比较长,就不张贴了。 大致内容是取得 Object 的方向、边框、类别。

在这里插入图片描述
在这里插入图片描述

到此,Lidar 检测的代码流程基本上介绍完毕。

总结

通过梳理代码可以发现

  1. Apollo 是个很厉害的自动驾驶框架,各个感知任务的 Component 工作流差不多一样,有固定的套路,这也让大家能够比较轻松地学习它,可以一个模块一个模块地学。
  2. Apollo 支持现有的神经网络模型导入并灵活配置,比如 Lidar 用 PointPillar,以后有新的模型也可以比较容易替换。
  3. 算法是自动驾驶一部分,我们经常看见论文中讲得模型有多厉害,但实际编码中还需要前处理、后处理过程,这其实就是传统的代码能力,所以,大家不要小看自动驾驶,在嵌入式平台上跑,算法模型重要,代码更加重要,两者是相辅相成的。不要轻代码重算法,也不要重代码轻算法。当然,如果团队够大,大家各司其职就好了,这一部分的压力是要系统架构师承担的。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/06/14 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 从 Component 出发
    • 1.1 initConfig
      • 1.2 initAlgorithmPlugin
        • 1.3 Proc 和 InternalProc
        • 2. detector_->Process() 算法逻辑
          • 2.1 点云 Preprocesses() 和 ProcessCommon()
            • 2.2 PointPillarsDetection
            • 总结
            相关产品与服务
            腾讯云代码分析
            腾讯云代码分析(内部代号CodeDog)是集众多代码分析工具的云原生、分布式、高性能的代码综合分析跟踪管理平台,其主要功能是持续跟踪分析代码,观测项目代码质量,支撑团队传承代码文化。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档