Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(out_of_lane): cut predicted paths after red lights #6478

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
# if false, assume the object moves at constant velocity along *all* lanelets it currently is located in.
predicted_path_min_confidence : 0.1 # when using predicted paths, ignore the ones whose confidence is lower than this value.
distance_buffer: 1.0 # [m] distance buffer used to determine if a collision will occur in the other lane
cut_predicted_paths_beyond_red_lights: true # if true, predicted paths are cut beyond the stop line of red traffic lights

overlap:
minimum_distance: 0.0 # [m] minimum distance inside a lanelet for an overlap to be considered
Expand Down
1 change: 1 addition & 0 deletions planning/behavior_velocity_out_of_lane_module/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
<depend>tf2</depend>
<depend>tier4_autoware_utils</depend>
<depend>tier4_planning_msgs</depend>
<depend>traffic_light_utils</depend>
<depend>vehicle_info_util</depend>
<depend>visualization_msgs</depend>

Expand Down
14 changes: 13 additions & 1 deletion planning/behavior_velocity_out_of_lane_module/src/decisions.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2023 TIER IV, Inc.

Check notice on line 1 in planning/behavior_velocity_out_of_lane_module/src/decisions.cpp

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

ℹ Getting worse: Overall Code Complexity

The mean cyclomatic complexity increases from 5.62 to 6.08, threshold = 4. This file has many conditional statements (e.g. if, for, while) across its implementation, leading to lower code health. Avoid adding more conditionals.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -73,11 +73,13 @@
if (!object_is_incoming(object_point, route_handler, range.lane)) return {};

const auto max_deviation = object.shape.dimensions.y + range.inside_distance + dist_buffer;
const auto max_lon_deviation = object.shape.dimensions.x / 2.0;

Check warning on line 76 in planning/behavior_velocity_out_of_lane_module/src/decisions.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_out_of_lane_module/src/decisions.cpp#L76

Added line #L76 was not covered by tests
auto worst_enter_time = std::optional<double>();
auto worst_exit_time = std::optional<double>();

for (const auto & predicted_path : object.kinematics.predicted_paths) {
const auto unique_path_points = motion_utils::removeOverlapPoints(predicted_path.path);
if (unique_path_points.size() < 2) continue;
const auto time_step = rclcpp::Duration(predicted_path.time_step).seconds();
const auto enter_point =
geometry_msgs::msg::Point().set__x(range.entering_point.x()).set__y(range.entering_point.y());
Expand Down Expand Up @@ -121,7 +123,17 @@
max_deviation);
continue;
}
// else we rely on the interpolation to estimate beyond the end of the predicted path
const auto is_last_predicted_path_point =
(exit_segment_idx + 2 == unique_path_points.size() ||
enter_segment_idx + 2 == unique_path_points.size());
const auto does_not_reach_overlap =
is_last_predicted_path_point && (std::min(exit_offset, enter_offset) > max_lon_deviation);
if (does_not_reach_overlap) {
RCLCPP_DEBUG(
logger, " * does not reach the overlap = %2.2fm | max_dev = %2.2fm\n",
std::min(exit_offset, enter_offset), max_lon_deviation);
continue;
}

Check warning on line 136 in planning/behavior_velocity_out_of_lane_module/src/decisions.cpp

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ Getting worse: Complex Method

object_time_to_range increases in cyclomatic complexity from 14 to 19, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.

Check warning on line 136 in planning/behavior_velocity_out_of_lane_module/src/decisions.cpp

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ Getting worse: Complex Method

object_time_to_range increases in cyclomatic complexity from 13 to 14, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.

Check warning on line 136 in planning/behavior_velocity_out_of_lane_module/src/decisions.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_out_of_lane_module/src/decisions.cpp#L135-L136

Added lines #L135 - L136 were not covered by tests

const auto same_driving_direction_as_ego = enter_time < exit_time;
if (same_driving_direction_as_ego) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
// Copyright 2023-2024 TIER IV, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "filter_predicted_objects.hpp"

#include <motion_utils/trajectory/trajectory.hpp>
#include <traffic_light_utils/traffic_light_utils.hpp>

#include <boost/geometry/algorithms/intersects.hpp>

#include <lanelet2_core/geometry/LaneletMap.h>
#include <lanelet2_core/primitives/BasicRegulatoryElements.h>

#include <algorithm>

namespace behavior_velocity_planner::out_of_lane
{
void cut_predicted_path_beyond_line(

Check warning on line 29 in planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp#L29

Added line #L29 was not covered by tests
autoware_auto_perception_msgs::msg::PredictedPath & predicted_path,
const lanelet::BasicLineString2d & stop_line, const double object_front_overhang)
{
auto stop_line_idx = 0UL;
bool found = false;
lanelet::BasicSegment2d path_segment;
path_segment.first.x() = predicted_path.path.front().position.x;
path_segment.first.y() = predicted_path.path.front().position.y;

Check warning on line 37 in planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp#L36-L37

Added lines #L36 - L37 were not covered by tests
for (stop_line_idx = 1; stop_line_idx < predicted_path.path.size(); ++stop_line_idx) {
path_segment.second.x() = predicted_path.path[stop_line_idx].position.x;
path_segment.second.y() = predicted_path.path[stop_line_idx].position.y;

Check warning on line 40 in planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp#L39-L40

Added lines #L39 - L40 were not covered by tests
if (boost::geometry::intersects(stop_line, path_segment)) {
found = true;
break;
}
path_segment.first = path_segment.second;
}
if (found) {
auto cut_idx = stop_line_idx;
double arc_length = 0;
while (cut_idx > 0 && arc_length < object_front_overhang) {
arc_length += tier4_autoware_utils::calcDistance2d(
predicted_path.path[cut_idx], predicted_path.path[cut_idx - 1]);

Check warning on line 52 in planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp#L51-L52

Added lines #L51 - L52 were not covered by tests
--cut_idx;
}
predicted_path.path.resize(cut_idx);

Check warning on line 55 in planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp#L55

Added line #L55 was not covered by tests
}
}

Check warning on line 57 in planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ New issue: Bumpy Road Ahead

cut_predicted_path_beyond_line has 2 blocks with nested conditional logic. Any nesting of 2 or deeper is considered. Threshold is one single, nested block per function. The Bumpy Road code smell is a function that contains multiple chunks of nested conditional logic. The deeper the nesting and the more bumps, the lower the code health.

Check warning on line 57 in planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp#L57

Added line #L57 was not covered by tests

std::optional<const lanelet::BasicLineString2d> find_next_stop_line(

Check warning on line 59 in planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp#L59

Added line #L59 was not covered by tests
const autoware_auto_perception_msgs::msg::PredictedPath & path, const PlannerData & planner_data)
{
lanelet::ConstLanelets lanelets;
lanelet::BasicLineString2d query_line;
for (const auto & p : path.path) query_line.emplace_back(p.position.x, p.position.y);
const auto query_results = lanelet::geometry::findWithin2d(
planner_data.route_handler_->getLaneletMapPtr()->laneletLayer, query_line);
for (const auto & r : query_results) lanelets.push_back(r.second);
for (const auto & ll : lanelets) {
for (const auto & element : ll.regulatoryElementsAs<lanelet::TrafficLight>()) {
const auto traffic_signal_stamped = planner_data.getTrafficSignal(element->id());
if (

Check warning on line 71 in planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp#L71

Added line #L71 was not covered by tests
traffic_signal_stamped.has_value() && element->stopLine().has_value() &&

Check warning on line 72 in planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ New issue: Complex Conditional

find_next_stop_line has 1 complex conditionals with 2 branches, threshold = 2. A complex conditional is an expression inside a branch (e.g. if, for, while) which consists of multiple, logical operators such as AND/OR. The more logical operators in an expression, the more severe the code smell.
traffic_light_utils::isTrafficSignalStop(ll, traffic_signal_stamped.value().signal)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When we turn left, and the traffic signal for the vehicle coming from the left is unknown, which is actually green, the out_of_lane module ignores the vehicle as not expected.

Am I understanding correct? I think it's okay for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your understanding is correct and I will think about what should be the behavior in the UNKNOWN traffic light case.

lanelet::BasicLineString2d stop_line;
for (const auto & p : *(element->stopLine())) stop_line.emplace_back(p.x(), p.y());
return stop_line;
}
}

Check warning on line 78 in planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp#L78

Added line #L78 was not covered by tests
}
return std::nullopt;
}

Check warning on line 81 in planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ New issue: Complex Method

find_next_stop_line has a cyclomatic complexity of 9, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.

Check warning on line 81 in planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ New issue: Deep, Nested Complexity

find_next_stop_line has a nested complexity depth of 4, threshold = 4. This function contains deeply nested logic such as if statements and/or loops. The deeper the nesting, the lower the code health.

Check warning on line 81 in planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp#L80-L81

Added lines #L80 - L81 were not covered by tests

void cut_predicted_path_beyond_red_lights(

Check warning on line 83 in planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp#L83

Added line #L83 was not covered by tests
autoware_auto_perception_msgs::msg::PredictedPath & predicted_path,
const PlannerData & planner_data, const double object_front_overhang)
{
const auto stop_line = find_next_stop_line(predicted_path, planner_data);

Check warning on line 87 in planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp#L87

Added line #L87 was not covered by tests
if (stop_line) cut_predicted_path_beyond_line(predicted_path, *stop_line, object_front_overhang);
}

Check warning on line 89 in planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp#L89

Added line #L89 was not covered by tests

autoware_auto_perception_msgs::msg::PredictedObjects filter_predicted_objects(
const PlannerData & planner_data, const EgoData & ego_data, const PlannerParam & params)
{
autoware_auto_perception_msgs::msg::PredictedObjects filtered_objects;
filtered_objects.header = planner_data.predicted_objects->header;
for (const auto & object : planner_data.predicted_objects->objects) {
const auto is_pedestrian =
std::find_if(object.classification.begin(), object.classification.end(), [](const auto & c) {
return c.label == autoware_auto_perception_msgs::msg::ObjectClassification::PEDESTRIAN;
}) != object.classification.end();
if (is_pedestrian) continue;

auto filtered_object = object;
const auto is_invalid_predicted_path = [&](const auto & predicted_path) {
const auto is_low_confidence = predicted_path.confidence < params.objects_min_confidence;
const auto no_overlap_path = motion_utils::removeOverlapPoints(predicted_path.path);

Check warning on line 106 in planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp#L104-L106

Added lines #L104 - L106 were not covered by tests
if (no_overlap_path.size() <= 1) return true;
const auto lat_offset_to_current_ego =
std::abs(motion_utils::calcLateralOffset(no_overlap_path, ego_data.pose.position));
const auto is_crossing_ego =

Check warning on line 110 in planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp#L110

Added line #L110 was not covered by tests
lat_offset_to_current_ego <=
object.shape.dimensions.y / 2.0 + std::max(
params.left_offset + params.extra_left_offset,

Check warning on line 113 in planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp#L112-L113

Added lines #L112 - L113 were not covered by tests
params.right_offset + params.extra_right_offset);
return is_low_confidence || is_crossing_ego;

Check warning on line 115 in planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp#L115

Added line #L115 was not covered by tests
};
if (params.objects_use_predicted_paths) {
auto & predicted_paths = filtered_object.kinematics.predicted_paths;
const auto new_end =
std::remove_if(predicted_paths.begin(), predicted_paths.end(), is_invalid_predicted_path);

Check warning on line 120 in planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp#L120

Added line #L120 was not covered by tests
predicted_paths.erase(new_end, predicted_paths.end());
if (params.objects_cut_predicted_paths_beyond_red_lights)
for (auto & predicted_path : predicted_paths)
cut_predicted_path_beyond_red_lights(
predicted_path, planner_data, filtered_object.shape.dimensions.x);
predicted_paths.erase(
std::remove_if(

Check warning on line 127 in planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp#L127

Added line #L127 was not covered by tests
predicted_paths.begin(), predicted_paths.end(),
[](const auto & p) { return p.path.empty(); }),
predicted_paths.end());
}

if (!params.objects_use_predicted_paths || !filtered_object.kinematics.predicted_paths.empty())
filtered_objects.objects.push_back(filtered_object);
}

Check warning on line 135 in planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp#L135

Added line #L135 was not covered by tests
return filtered_objects;
}

Check warning on line 137 in planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ New issue: Complex Method

filter_predicted_objects has a cyclomatic complexity of 11, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.

Check warning on line 137 in planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ New issue: Bumpy Road Ahead

filter_predicted_objects has 2 blocks with nested conditional logic. Any nesting of 2 or deeper is considered. Threshold is one single, nested block per function. The Bumpy Road code smell is a function that contains multiple chunks of nested conditional logic. The deeper the nesting and the more bumps, the lower the code health.

Check warning on line 137 in planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_velocity_out_of_lane_module/src/filter_predicted_objects.cpp#L137

Added line #L137 was not covered by tests

} // namespace behavior_velocity_planner::out_of_lane
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2023 TIER IV, Inc.
// Copyright 2023-2024 TIER IV, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -17,56 +17,41 @@

#include "types.hpp"

#include <motion_utils/trajectory/trajectory.hpp>
#include <behavior_velocity_planner_common/planner_data.hpp>

#include <string>
#include <optional>

namespace behavior_velocity_planner::out_of_lane
{
/// @brief cut a predicted path beyond the given stop line
/// @param [inout] predicted_path predicted path to cut
/// @param [in] stop_line stop line used for cutting
/// @param [in] object_front_overhang extra distance to cut ahead of the stop line
void cut_predicted_path_beyond_line(
autoware_auto_perception_msgs::msg::PredictedPath & predicted_path,
const lanelet::BasicLineString2d & stop_line, const double object_front_overhang);

/// @brief find the next red light stop line along the given path
/// @param [in] path predicted path to check for a stop line
/// @param [in] planner_data planner data with stop line information
/// @return the first red light stop line found along the path (if any)
std::optional<const lanelet::BasicLineString2d> find_next_stop_line(
const autoware_auto_perception_msgs::msg::PredictedPath & path, const PlannerData & planner_data);

/// @brief cut predicted path beyond stop lines of red lights
/// @param [inout] predicted_path predicted path to cut
/// @param [in] planner_data planner data to get the map and traffic light information
void cut_predicted_path_beyond_red_lights(
autoware_auto_perception_msgs::msg::PredictedPath & predicted_path,
const PlannerData & planner_data, const double object_front_overhang);

/// @brief filter predicted objects and their predicted paths
/// @param [in] objects predicted objects to filter
/// @param [in] planner_data planner data
/// @param [in] ego_data ego data
/// @param [in] params parameters
/// @return filtered predicted objects
autoware_auto_perception_msgs::msg::PredictedObjects filter_predicted_objects(
const autoware_auto_perception_msgs::msg::PredictedObjects & objects, const EgoData & ego_data,
const PlannerParam & params)
{
autoware_auto_perception_msgs::msg::PredictedObjects filtered_objects;
filtered_objects.header = objects.header;
for (const auto & object : objects.objects) {
const auto is_pedestrian =
std::find_if(object.classification.begin(), object.classification.end(), [](const auto & c) {
return c.label == autoware_auto_perception_msgs::msg::ObjectClassification::PEDESTRIAN;
}) != object.classification.end();
if (is_pedestrian) continue;

auto filtered_object = object;
const auto is_invalid_predicted_path = [&](const auto & predicted_path) {
const auto is_low_confidence = predicted_path.confidence < params.objects_min_confidence;
const auto no_overlap_path = motion_utils::removeOverlapPoints(predicted_path.path);
if (no_overlap_path.size() <= 1) return true;
const auto lat_offset_to_current_ego =
std::abs(motion_utils::calcLateralOffset(no_overlap_path, ego_data.pose.position));
const auto is_crossing_ego =
lat_offset_to_current_ego <=
object.shape.dimensions.y / 2.0 + std::max(
params.left_offset + params.extra_left_offset,
params.right_offset + params.extra_right_offset);
return is_low_confidence || is_crossing_ego;
};
if (params.objects_use_predicted_paths) {
auto & predicted_paths = filtered_object.kinematics.predicted_paths;
const auto new_end =
std::remove_if(predicted_paths.begin(), predicted_paths.end(), is_invalid_predicted_path);
predicted_paths.erase(new_end, predicted_paths.end());
}
if (!params.objects_use_predicted_paths || !filtered_object.kinematics.predicted_paths.empty())
filtered_objects.objects.push_back(filtered_object);
}
return filtered_objects;
}

const PlannerData & planner_data, const EgoData & ego_data, const PlannerParam & params);
} // namespace behavior_velocity_planner::out_of_lane

#endif // FILTER_PREDICTED_OBJECTS_HPP_
2 changes: 2 additions & 0 deletions planning/behavior_velocity_out_of_lane_module/src/manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ OutOfLaneModuleManager::OutOfLaneModuleManager(rclcpp::Node & node)
pp.objects_min_confidence =
getOrDeclareParameter<double>(node, ns + ".objects.predicted_path_min_confidence");
pp.objects_dist_buffer = getOrDeclareParameter<double>(node, ns + ".objects.distance_buffer");
pp.objects_cut_predicted_paths_beyond_red_lights =
getOrDeclareParameter<bool>(node, ns + ".objects.cut_predicted_paths_beyond_red_lights");

pp.overlap_min_dist = getOrDeclareParameter<double>(node, ns + ".overlap.minimum_distance");
pp.overlap_extra_length = getOrDeclareParameter<double>(node, ns + ".overlap.extra_length");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,91 +108,94 @@
const auto ranges =
calculate_overlapping_ranges(path_footprints, path_lanelets, other_lanelets, params_);
const auto calculate_overlapping_ranges_us = stopwatch.toc("calculate_overlapping_ranges");
// Calculate stop and slowdown points
stopwatch.tic("calculate_decisions");
DecisionInputs inputs;
inputs.ranges = ranges;
inputs.ego_data = ego_data;
inputs.objects = filter_predicted_objects(*planner_data_->predicted_objects, ego_data, params_);
stopwatch.tic("filter_predicted_objects");
inputs.objects = filter_predicted_objects(*planner_data_, ego_data, params_);
const auto filter_predicted_objects_ms = stopwatch.toc("filter_predicted_objects");
inputs.route_handler = planner_data_->route_handler_;
inputs.lanelets = other_lanelets;
stopwatch.tic("calculate_decisions");
const auto decisions = calculate_decisions(inputs, params_, logger_);
const auto calculate_decisions_us = stopwatch.toc("calculate_decisions");
stopwatch.tic("calc_slowdown_points");
if ( // reset the previous inserted point if the timer expired
prev_inserted_point_ &&
(clock_->now() - prev_inserted_point_time_).seconds() > params_.min_decision_duration)
prev_inserted_point_.reset();
auto point_to_insert =
calculate_slowdown_point(ego_data, decisions, prev_inserted_point_, params_);
const auto calc_slowdown_points_us = stopwatch.toc("calc_slowdown_points");
stopwatch.tic("insert_slowdown_points");
debug_data_.slowdowns.clear();
if ( // reset the timer if there is no previous inserted point or if we avoid the same lane
point_to_insert &&
(!prev_inserted_point_ || prev_inserted_point_->slowdown.lane_to_avoid.id() ==
point_to_insert->slowdown.lane_to_avoid.id()))
prev_inserted_point_time_ = clock_->now();
// reuse previous stop point if there is no new one or if its velocity is not higher than the new
// one and its arc length is lower
const auto should_use_prev_inserted_point = [&]() {
if (
point_to_insert && prev_inserted_point_ &&
prev_inserted_point_->slowdown.velocity <= point_to_insert->slowdown.velocity) {
const auto arc_length = motion_utils::calcSignedArcLength(
path->points, 0LU, point_to_insert->point.point.pose.position);
const auto prev_arc_length = motion_utils::calcSignedArcLength(
path->points, 0LU, prev_inserted_point_->point.point.pose.position);
return prev_arc_length < arc_length;
}
return !point_to_insert && prev_inserted_point_;
}();
if (should_use_prev_inserted_point) {
// if the path changed the prev point is no longer on the path so we project it
const auto insert_arc_length = motion_utils::calcSignedArcLength(
path->points, 0LU, prev_inserted_point_->point.point.pose.position);
prev_inserted_point_->point.point.pose =
motion_utils::calcInterpolatedPose(path->points, insert_arc_length);
point_to_insert = prev_inserted_point_;
}
if (point_to_insert) {
prev_inserted_point_ = point_to_insert;
RCLCPP_INFO(logger_, "Avoiding lane %lu", point_to_insert->slowdown.lane_to_avoid.id());
RCLCPP_DEBUG(logger_, "Avoiding lane %lu", point_to_insert->slowdown.lane_to_avoid.id());
debug_data_.slowdowns = {*point_to_insert};
auto path_idx = motion_utils::findNearestSegmentIndex(
path->points, point_to_insert->point.point.pose.position) +
1;
planning_utils::insertVelocity(
*path, point_to_insert->point, point_to_insert->slowdown.velocity, path_idx);
if (point_to_insert->slowdown.velocity == 0.0) {
tier4_planning_msgs::msg::StopFactor stop_factor;
stop_factor.stop_pose = point_to_insert->point.point.pose;
stop_factor.dist_to_stop_pose = motion_utils::calcSignedArcLength(
path->points, ego_data.pose.position, point_to_insert->point.point.pose.position);
planning_utils::appendStopReason(stop_factor, stop_reason);
}
velocity_factor_.set(
path->points, planner_data_->current_odometry->pose, point_to_insert->point.point.pose,
VelocityFactor::UNKNOWN);
} else if (!decisions.empty()) {
RCLCPP_WARN(logger_, "Could not insert stop point (would violate max deceleration limits)");
}
const auto insert_slowdown_points_us = stopwatch.toc("insert_slowdown_points");
debug_data_.ranges = inputs.ranges;

const auto total_time_us = stopwatch.toc();
RCLCPP_DEBUG(
logger_,
"Total time = %2.2fus\n"
"\tcalculate_lanelets = %2.0fus\n"
"\tcalculate_path_footprints = %2.0fus\n"
"\tcalculate_overlapping_ranges = %2.0fus\n"
"\tfilter_pred_objects = %2.0fus\n"
"\tcalculate_decisions = %2.0fus\n"
"\tcalc_slowdown_points = %2.0fus\n"
"\tinsert_slowdown_points = %2.0fus\n",
total_time_us, calculate_lanelets_us, calculate_path_footprints_us,
calculate_overlapping_ranges_us, calculate_decisions_us, calc_slowdown_points_us,
insert_slowdown_points_us);
calculate_overlapping_ranges_us, filter_predicted_objects_ms, calculate_decisions_us,
calc_slowdown_points_us, insert_slowdown_points_us);

Check warning on line 198 in planning/behavior_velocity_out_of_lane_module/src/scene_out_of_lane.cpp

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ Getting worse: Complex Method

OutOfLaneModule::modifyPathVelocity already has high cyclomatic complexity, and now it increases in Lines of Code from 130 to 133. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.
return true;
}

Expand Down
6 changes: 4 additions & 2 deletions planning/behavior_velocity_out_of_lane_module/src/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,10 @@ struct PlannerParam
double ego_min_velocity; // [m/s] minimum velocity of ego used to calculate its ttc or time range

bool objects_use_predicted_paths; // whether to use the objects' predicted paths
double objects_min_vel; // [m/s] objects lower than this velocity will be ignored
double objects_min_confidence; // minimum confidence to consider a predicted path
bool objects_cut_predicted_paths_beyond_red_lights; // whether to cut predicted paths beyond red
// lights' stop lines
double objects_min_vel; // [m/s] objects lower than this velocity will be ignored
double objects_min_confidence; // minimum confidence to consider a predicted path
double objects_dist_buffer; // [m] distance buffer used to determine if a collision will occur in
// the other lane

Expand Down
Loading