Skip to content

Commit d23ccf5

Browse files
committed
feat(object_lanelet_filter): add velocity direction based object lanelet filter (autowarefoundation#7107)
* chore: refactor lanelet filter function Signed-off-by: yoshiri <yoshiyoshidetteiu@gmail.com> * feat: add lanelet direction filter Signed-off-by: yoshiri <yoshiyoshidetteiu@gmail.com> * fix: do not change default settings Signed-off-by: yoshiri <yoshiyoshidetteiu@gmail.com> * feat: skip orientation unavailable objects Signed-off-by: yoshiri <yoshiyoshidetteiu@gmail.com> * fix: feature variable name Signed-off-by: yoshiri <yoshiyoshidetteiu@gmail.com> --------- Signed-off-by: yoshiri <yoshiyoshidetteiu@gmail.com>
1 parent fe851d9 commit d23ccf5

File tree

3 files changed

+124
-15
lines changed

3 files changed

+124
-15
lines changed

perception/detected_object_validation/config/object_lanelet_filter.param.yaml

+10
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,13 @@
99
MOTORCYCLE : false
1010
BICYCLE : false
1111
PEDESTRIAN : false
12+
13+
filter_settings:
14+
# polygon overlap based filter
15+
polygon_overlap_filter:
16+
enabled: true
17+
# velocity direction based filter
18+
lanelet_direction_filter:
19+
enabled: false
20+
velocity_yaw_threshold: 0.785398 # [rad] (45 deg)
21+
object_speed_threshold: 3.0 # [m/s]

perception/detected_object_validation/include/detected_object_filter/object_lanelet_filter.hpp

+18-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include <lanelet2_extension/utility/message_conversion.hpp>
2121
#include <lanelet2_extension/utility/query.hpp>
22+
#include <lanelet2_extension/utility/utilities.hpp>
2223
#include <rclcpp/rclcpp.hpp>
2324
#include <tier4_autoware_utils/geometry/geometry.hpp>
2425

@@ -58,11 +59,27 @@ class ObjectLaneletFilterNode : public rclcpp::Node
5859
tf2_ros::TransformListener tf_listener_;
5960

6061
utils::FilterTargetLabel filter_target_;
61-
62+
struct FilterSettings
63+
{
64+
bool polygon_overlap_filter;
65+
bool lanelet_direction_filter;
66+
double lanelet_direction_filter_velocity_yaw_threshold;
67+
double lanelet_direction_filter_object_speed_threshold;
68+
} filter_settings_;
69+
70+
bool filterObject(
71+
const autoware_auto_perception_msgs::msg::DetectedObject & transformed_object,
72+
const autoware_auto_perception_msgs::msg::DetectedObject & input_object,
73+
const lanelet::ConstLanelets & intersected_road_lanelets,
74+
const lanelet::ConstLanelets & intersected_shoulder_lanelets,
75+
autoware_auto_perception_msgs::msg::DetectedObjects & output_object_msg);
6276
LinearRing2d getConvexHull(const autoware_auto_perception_msgs::msg::DetectedObjects &);
6377
lanelet::ConstLanelets getIntersectedLanelets(
6478
const LinearRing2d &, const lanelet::ConstLanelets &);
6579
bool isPolygonOverlapLanelets(const Polygon2d &, const lanelet::ConstLanelets &);
80+
bool isSameDirectionWithLanelets(
81+
const lanelet::ConstLanelets & lanelets,
82+
const autoware_auto_perception_msgs::msg::DetectedObject & object);
6683
geometry_msgs::msg::Polygon setFootprint(
6784
const autoware_auto_perception_msgs::msg::DetectedObject &);
6885
};

perception/detected_object_validation/src/object_lanelet_filter.cpp

+96-14
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,15 @@ ObjectLaneletFilterNode::ObjectLaneletFilterNode(const rclcpp::NodeOptions & nod
4141
filter_target_.MOTORCYCLE = declare_parameter<bool>("filter_target_label.MOTORCYCLE", false);
4242
filter_target_.BICYCLE = declare_parameter<bool>("filter_target_label.BICYCLE", false);
4343
filter_target_.PEDESTRIAN = declare_parameter<bool>("filter_target_label.PEDESTRIAN", false);
44+
// Set filter settings
45+
filter_settings_.polygon_overlap_filter =
46+
declare_parameter<bool>("filter_settings.polygon_overlap_filter.enabled");
47+
filter_settings_.lanelet_direction_filter =
48+
declare_parameter<bool>("filter_settings.lanelet_direction_filter.enabled");
49+
filter_settings_.lanelet_direction_filter_velocity_yaw_threshold =
50+
declare_parameter<double>("filter_settings.lanelet_direction_filter.velocity_yaw_threshold");
51+
filter_settings_.lanelet_direction_filter_object_speed_threshold =
52+
declare_parameter<double>("filter_settings.lanelet_direction_filter.object_speed_threshold");
4453

4554
// Set publisher/subscriber
4655
map_sub_ = this->create_subscription<autoware_auto_mapping_msgs::msg::HADMapBin>(
@@ -87,27 +96,64 @@ void ObjectLaneletFilterNode::objectCallback(
8796
// get intersected lanelets
8897
lanelet::ConstLanelets intersected_lanelets = getIntersectedLanelets(convex_hull, road_lanelets_);
8998

90-
int index = 0;
91-
for (const auto & object : transformed_objects.objects) {
92-
const auto footprint = setFootprint(object);
93-
const auto & label = object.classification.front().label;
94-
if (filter_target_.isTarget(label)) {
99+
// filtering process
100+
for (size_t index = 0; index < transformed_objects.objects.size(); ++index) {
101+
const auto & transformed_object = transformed_objects.objects.at(index);
102+
const auto & input_object = input_msg->objects.at(index);
103+
filterObject(
104+
transformed_object, input_object, intersected_road_lanelets, intersected_shoulder_lanelets,
105+
output_object_msg);
106+
}
107+
object_pub_->publish(output_object_msg);
108+
}
109+
110+
bool ObjectLaneletFilterNode::filterObject(
111+
const autoware_auto_perception_msgs::msg::DetectedObject & transformed_object,
112+
const autoware_auto_perception_msgs::msg::DetectedObject & input_object,
113+
const lanelet::ConstLanelets & intersected_road_lanelets,
114+
const lanelet::ConstLanelets & intersected_shoulder_lanelets,
115+
autoware_auto_perception_msgs::msg::DetectedObjects & output_object_msg)
116+
{
117+
const auto & label = transformed_object.classification.front().label;
118+
if (filter_target_.isTarget(label)) {
119+
bool filter_pass = true;
120+
// 1. is polygon overlap with road lanelets or shoulder lanelets
121+
if (filter_settings_.polygon_overlap_filter) {
95122
Polygon2d polygon;
123+
const auto footprint = setFootprint(transformed_object);
96124
for (const auto & point : footprint.points) {
97-
const geometry_msgs::msg::Point32 point_transformed =
98-
tier4_autoware_utils::transformPoint(point, object.kinematics.pose_with_covariance.pose);
125+
const geometry_msgs::msg::Point32 point_transformed = tier4_autoware_utils::transformPoint(
126+
point, transformed_object.kinematics.pose_with_covariance.pose);
99127
polygon.outer().emplace_back(point_transformed.x, point_transformed.y);
100128
}
101129
polygon.outer().push_back(polygon.outer().front());
102-
if (isPolygonOverlapLanelets(polygon, intersected_lanelets)) {
103-
output_object_msg.objects.emplace_back(input_msg->objects.at(index));
104-
}
105-
} else {
106-
output_object_msg.objects.emplace_back(input_msg->objects.at(index));
130+
const bool is_polygon_overlap =
131+
isPolygonOverlapLanelets(polygon, intersected_road_lanelets) ||
132+
isPolygonOverlapLanelets(polygon, intersected_shoulder_lanelets);
133+
filter_pass = filter_pass && is_polygon_overlap;
107134
}
108-
++index;
135+
136+
// 2. check if objects velocity is the same with the lanelet direction
137+
const bool orientation_not_available =
138+
transformed_object.kinematics.orientation_availability ==
139+
autoware_auto_perception_msgs::msg::TrackedObjectKinematics::UNAVAILABLE;
140+
if (filter_settings_.lanelet_direction_filter && !orientation_not_available) {
141+
const bool is_same_direction =
142+
isSameDirectionWithLanelets(intersected_road_lanelets, transformed_object) ||
143+
isSameDirectionWithLanelets(intersected_shoulder_lanelets, transformed_object);
144+
filter_pass = filter_pass && is_same_direction;
145+
}
146+
147+
// push back to output object
148+
if (filter_pass) {
149+
output_object_msg.objects.emplace_back(input_object);
150+
return true;
151+
}
152+
} else {
153+
output_object_msg.objects.emplace_back(input_object);
154+
return true;
109155
}
110-
object_pub_->publish(output_object_msg);
156+
return false;
111157
}
112158

113159
geometry_msgs::msg::Polygon ObjectLaneletFilterNode::setFootprint(
@@ -176,6 +222,42 @@ bool ObjectLaneletFilterNode::isPolygonOverlapLanelets(
176222
return false;
177223
}
178224

225+
bool ObjectLaneletFilterNode::isSameDirectionWithLanelets(
226+
const lanelet::ConstLanelets & lanelets,
227+
const autoware_auto_perception_msgs::msg::DetectedObject & object)
228+
{
229+
const double object_yaw = tf2::getYaw(object.kinematics.pose_with_covariance.pose.orientation);
230+
const double object_velocity_norm = std::hypot(
231+
object.kinematics.twist_with_covariance.twist.linear.x,
232+
object.kinematics.twist_with_covariance.twist.linear.y);
233+
const double object_velocity_yaw = std::atan2(
234+
object.kinematics.twist_with_covariance.twist.linear.y,
235+
object.kinematics.twist_with_covariance.twist.linear.x) +
236+
object_yaw;
237+
238+
if (object_velocity_norm < filter_settings_.lanelet_direction_filter_object_speed_threshold) {
239+
return true;
240+
}
241+
for (const auto & lanelet : lanelets) {
242+
const bool is_in_lanelet =
243+
lanelet::utils::isInLanelet(object.kinematics.pose_with_covariance.pose, lanelet, 0.0);
244+
if (!is_in_lanelet) {
245+
continue;
246+
}
247+
const double lane_yaw = lanelet::utils::getLaneletAngle(
248+
lanelet, object.kinematics.pose_with_covariance.pose.position);
249+
const double delta_yaw = object_velocity_yaw - lane_yaw;
250+
const double normalized_delta_yaw = tier4_autoware_utils::normalizeRadian(delta_yaw);
251+
const double abs_norm_delta_yaw = std::fabs(normalized_delta_yaw);
252+
253+
if (abs_norm_delta_yaw < filter_settings_.lanelet_direction_filter_velocity_yaw_threshold) {
254+
return true;
255+
}
256+
}
257+
258+
return false;
259+
}
260+
179261
} // namespace object_lanelet_filter
180262

181263
#include <rclcpp_components/register_node_macro.hpp>

0 commit comments

Comments
 (0)