目录
清空存储filter的成员变量,然后遍历config文件中的filter_name, 从这里看配置文件里面就一个 ROIBoundaryFilter(有需要可以自己添加),然后通过registerer实例化
PERCEPTION_REGISTER_OBJECTFILTER(ROIBoundaryFilter);
初始化filter,然后push_back到filter_bank_, 当然因为配置文件里面就一个,所以遍历结束。
filter_bank_.clear();
for (int i = 0; i < config.filter_name_size(); ++i) {
const auto& name = config.filter_name(i);
BaseObjectFilter* filter =
BaseObjectFilterRegisterer::GetInstanceByName(name);
if (!filter) {
AINFO << "Failed to find object filter: " << name << ", skipped";
continue;
}
if (!filter->Init()) {
AINFO << "Failed to init object filter: " << name << ", skipped";
continue;
}
filter_bank_.push_back(filter);
AINFO << "Filter bank add filter: " << name;
}
object_filter_bank.cc
Filter
依次执行各个filter。
for (auto& filter : filter_bank_) {
if (!filter->Filter(options, frame)) {
AINFO << "Failed to filter objects in: " << filter->Name();
}
}
按照代码的结构,应该是方便添加更多的filter。目前就只有一个ROIBoundaryFilter,所以开始执行ROIBoundaryFilter。
roi_boundary_filter
配置文件
成员变量
// params
double distance_to_boundary_threshold_ = 1.0;
double inside_threshold_ = 1.0;
float confidence_threshold_ = 0.5f;
float cross_roi_threshold_ = 0.6f;
Filter
先是检查frame中的数据,包含object,hdmap_struct. 区分障碍物前后景来判断object是否在ROI。
然后依次执行
FillObjectRoiFlag(options, frame);
BuildWorldPolygons(options, *frame);
if (distance_to_boundary_threshold_ >= 0.f) {
FilterObjectsOutsideBoundary(options, frame, &objects_valid_flag_);
}
if (inside_threshold_ >= 0.f) {
FilterObjectsInsideBoundary(options, frame, &objects_valid_flag_);
}
FilterObjectsByConfidence(options, frame, &objects_valid_flag_);
最后更新一下objects size。
BuildWorldPolygons
目前ObjectFilterOptions为空
const Eigen::Affine3d& pose = frame.lidar2world_pose;
for (size_t j = 0; j < obj->polygon.size(); ++j) {
local_point(0) = obj->polygon[j].x;
local_point(1) = obj->polygon[j].y;
local_point(2) = obj->polygon[j].z;
world_point = pose * local_point;
polygons_in_world_[i][j].x = world_point(0);
polygons_in_world_[i][j].y = world_point(1);
polygons_in_world_[i][j].z = world_point(2);
FillObjectRoiFlag
这里回答了一个问题,什么是cross?就是object有部分点云在ROI中,这就算cross。
如果object有一个点云在ROI中,就算这个object.is_in_roi。
cross就是有部分点云在ROI中,这里有个问题,假如num_points_in_roi = cloud.size ?
计算一个in roi点云占比 ratio。
如果 ratio小于阈值,或者 有部分点云在ROI中并且confidence<= .11f. 这样object就算 cross_roi。
总结,这里把object分成了is_in_roi和objects_cross_roi两种,并且cross_roi也算is_in_roi。
obj->lidar_supplement.is_in_roi =
obj->lidar_supplement.num_points_in_roi > 0;
bool cross = (obj->lidar_supplement.num_points_in_roi !=
obj->lidar_supplement.cloud.size());
float ratio = static_cast<float>(obj->lidar_supplement.num_points_in_roi) /
static_cast<float>(obj->lidar_supplement.cloud.size());
if (ratio < cross_roi_threshold_ // a hacked minimum support value
|| (cross && obj->confidence <= .11f)) {
objects_cross_roi_[i] = true;
FilterObjectsOutsideBoundary
前提条件,得确保object在roi外边
if (!obj->lidar_supplement.is_in_roi)
遍历obstacle的每一个点云
for (auto& point : polygons_in_world_[i].points()) {
dist_to_boundary = 0.0;
min_dist_to_boundary = kDoubleMax;
world_point << point.x, point.y, point.z;
然后计算点到每一个boundary的距离
for (const auto& boundary : road_boundary) {
perception::common::CalculateDistAndDirToBoundary(
world_point, boundary.left_boundary, boundary.right_boundary,
&dist_to_boundary, &direction);
用min_dist_to_boundary来保存最小的距离
if (min_dist_to_boundary > dist_to_boundary) {
min_dist_to_boundary = dist_to_boundary;
}
如果最小距离是小于阈值的,则置flag为true。
if (min_dist_to_boundary <= distance_to_boundary_threshold_) {
(*objects_valid_flag)[i] = true;
break;
}
FilterObjectsInsideBoundary
前提条件,确保object in roi
if (obj->lidar_supplement.is_in_roi && !objects_cross_roi_[i] &&
obj->confidence <= .11f)
其余步骤同上,最后的判断条件相反,因为这是是在里面,所以越里面越好。
if (min_dist_to_boundary > inside_threshold_) {
(*objects_valid_flag)[i] = true;
break;
}
FilterObjectsByConfidence
将那些cross roi但是confidence低于阈值的障碍物 object_valid_flag置为false,应该就是过滤掉了。
for (size_t i = 0; i < objects.size(); ++i) {
if (objects_cross_roi_[i] || !objects[i]->lidar_supplement.is_in_roi) {
if (objects[i]->confidence < confidence_threshold_)
(*objects_valid_flag)[i] = false;
}
}