apollo_logo
2
0

【实践】基于插件进行开发

复制
正文
通用
图片
表格
附件
代码块
公式
超链接
提及
阅读统计
高亮信息
流程图
文本格式
正文
一级标题
二级标题
三级标题
四级标题
五级标题
六级标题
无序列表
有序列表
待办列表
引用
分割线

感知插件开发

本次实践课的目标是开发一个插件,说明感知插件开发的过程。插件二次开发的重点是代码框架搭建和配置管理。本次插件开发实现一个示例功能:过滤障碍物,fp_filter。此插件用于过滤误检目标。这里把一些尺寸不合理、置信度较低的目标作为误检目标。

准备工作

环境配置:CCF-赛事感知(Perception)环境配置

激光雷达感知参数说明:激光雷达感知参数说明


进入容器
Shell
收起
# 进入到application-perception代码库
cd application-perception

# 拉取并启动docker容器,如果已拉取不需要执行这条命令
aem start_gpu
# 进入容器
aem enter
# 下载安装依赖包: 会拉取安装core目录下的cyberfile.xml里面所有的依赖包
buildtool build --gpu


插件的创建通过命令的形式来实现,执行命令后代码框架被自动创建。

创建插件

在容器内,执行命令创建插件。fp_filter的含义是false positive filter,用于过滤误检目标。


Shell
收起
#创建插件,--namespace说明命名空间,--template说明创建的是插件,最后是插件的路径
buildtool create --namespace perception --template plugin modules/perception/fp_filter


插件创建成功后的代码结构:






插件开发

此插件应用于lidar_detection_filter,生成的插件有默认的配置,需要做修改和开发。

代码修改

  • 在cyberfile.xml中增加perception-lidar-detection-filter包依赖

Shell
收起
<depend repo_name="perception-lidar-detection-filter" type="binary">perception-lidar-detection-filter</depend>

  • 修改代码

在头文件 fp_filter.h 修改代码。其中需要修改的地方以注释的形式做了说明。


C++
收起
#pragma once

#include <memory>
#include "cyber/plugin_manager/plugin_manager.h"

#include "modules/perception/lidar_detection_filter/interface/base_object_filter.h" // 0.添加头文件

namespace apollo {
namespace perception {
namespace lidar { // 1.定义命名空间

class FpFilter : public BaseObjectFilter { // 2.继承基类
public:
FpFilter() = default; // 3.定义构造和析构函数
virtual ~FpFilter() = default;

public:
// 4.重写如下三个函数; 声明 FilterFlag 方法
bool Init(const ObjectFilterInitOptions& options = ObjectFilterInitOptions()) override;
bool Filter(const ObjectFilterOptions& options, LidarFrame* frame) override;
std::string Name() const override {
return "FalsePositiveFilter";
}
bool FilterFlag(base::ObjectPtr obj, double confidence_thresh, double volume_thresh, double height_diff_thresh);

private:
std::vector<bool> fp_flag_; // 5.定义数据结构
};

CYBER_PLUGIN_MANAGER_REGISTER_PLUGIN(apollo::perception::lidar::FpFilter, BaseObjectFilter) // 6.修改插件配置

} // namespace lidar
} // namespace perception
} // namespace apollo

  • 在plugin_fp_filter_description.xml中修改配置

C++
收起
<library path="modules/perception/fp_filter/libfp_filter.so">
<class type="apollo::perception::lidar::FpFilter" base_class="apollo::perception::lidar::BaseObjectFilter"></class>
</library>

  • 在BUILD中增加依赖项

C++
收起
apollo_plugin(
name = "libfp_filter.so",
srcs = [
"fp_filter.cc",
],
hdrs = [
"fp_filter.h",
],
description = ":plugin_fp_filter_description.xml",
deps = [
"//cyber",
"//modules/perception/fp_filter/proto:fp_filter_proto",
"//modules/perception/lidar_detection_filter:apollo_perception_lidar_detection_filter", # 增加依赖项
],
)


功能定义

修改好了头文件和插件配置。在 fp_filter.cc 中定义代码功能。功能核心点如下:

  • 过滤规则:置信度低、体积小、高度差小的目标做误检过滤;
  • 过滤目标类别:UNKNOWN、UNKNOWN_MOVABLE、UNKNOWN_UNMOVABLE、BICYCLE、PEDESTRIAN;

C++
收起
#include <memory>
#include "modules/perception/fp_filter/fp_filter.h"

namespace apollo {
namespace perception {
namespace lidar {

bool FpFilter::Init(const ObjectFilterInitOptions& options) {
fp_flag_.clear();
return true;
}

bool FpFilter::Filter(const ObjectFilterOptions& options, LidarFrame* frame) {
if (!frame) {
AINFO << "Lidar frame is nullptr.";
return false;
}
fp_flag_.clear();
size_t size = frame->segmented_objects.size();
fp_flag_.assign(size, false); // filter object if true
// 除了vehicle,对其他类别的目标做误检过滤
for (size_t i = 0; i < size; ++i) {
base::ObjectPtr obj = frame->segmented_objects.at(i);
base::ObjectType type = obj->type;
if (type == base::ObjectType::UNKNOWN || type == base::ObjectType::UNKNOWN_MOVABLE
|| type == base::ObjectType::UNKNOWN_UNMOVABLE) {
fp_flag_.at(i) = FilterFlag(obj, 0.4, 0.3, 0.3);
} else if (type == base::ObjectType::BICYCLE) {
fp_flag_.at(i) = FilterFlag(obj, 0.4, 0.4, 0.8);
} else if (type == base::ObjectType::PEDESTRIAN) {
fp_flag_.at(i) = FilterFlag(obj, 0.4, 0.3, 1.0);
}
}

// do filter
size_t valid_num = 0;
for (size_t i = 0; i < fp_flag_.size(); ++i) {
base::ObjectPtr obj = frame->segmented_objects.at(i);
if (!fp_flag_.at(i)) {
frame->segmented_objects.at(valid_num) = obj;
valid_num++;
}
}
frame->segmented_objects.resize(valid_num);
AINFO << "FalsePositiveFilter, filter fp " << size - valid_num << " objects, from " << size << " objects";

return true;
}

/**
* @brief
*
* @param obj
* @param confidence_thresh 过滤置信度较低的目标
* @param volume_thresh 过滤体积较小的目标
* @param height_diff_thresh 过滤
* @return true
* @return false
*/
bool FpFilter::FilterFlag(
base::ObjectPtr obj,
double confidence_thresh,
double volume_thresh,
double height_diff_thresh) {
// confidence
if (obj->confidence < confidence_thresh) {
return true;
}
// volume
auto obj_size = obj->size;
double volume = obj_size[0] * obj_size[1] * obj_size[2];
if (volume < volume_thresh) {
return true;
}
// height diff
double max_z = -10000.0;
double min_z = 10000.0;
for (size_t i = 0; i < obj->lidar_supplement.cloud.size(); ++i) {
double val_z = obj->lidar_supplement.cloud[i].z;
max_z = std::max(max_z, val_z);
min_z = std::min(min_z, val_z);
}
double height_diff = max_z - min_z;
if (height_diff < height_diff_thresh) {
return true;
}

return false;
}

} // namespace lidar
} // namespace perception
} // namespace apollo


插件使用

配置插件

在/apollo/modules/perception/lidar_detection_filter/data/filter_bank.pb.txt中增加 fp_fitler 插件。如下图11行所示。

fp_filter插件的配置通过硬编码写到了程序中,所以 config_path 和 config_file 都为空。






结果示例

感知启动,通过cyber_launch启动lidar感知和transform模块。






然后通过cyber_record play -f ***.record来播包,只播放三个必要的通道,通过 -c 来控制。进入到目录 /home/apollo/.apollo/resources/records,执行:


C++
收起
cyber_recorder play -f demo3_mkz_110_sunnybigloop.record -c /tf /apollo/sensor/velodyne64/compensator/PointCloud2 /apollo/localization/pose


感知结果:






通过 mainboard.INFO 查看感知日志,能够看到fp_fitler在正常工作,能够根据规则过滤目标。














原创声明,本文由作者授权发布于Apollo开发者社区,未经许可,不得转载。
发表评论已发表 0 条评论
登录后可评论,请前往 登录
暂无评论~快去发表自己的独特见解吧!
目录
感知插件开发
准备工作
创建插件
插件开发
代码修改
功能定义
插件使用
配置插件
结果示例
0 / 0
100%