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

fix(lane_change): relax finish judge #8133

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 @@ -618,6 +618,61 @@ The last behavior will also occur if the ego vehicle has departed from the curre

![stop](./images/lane_change-cant_cancel_no_abort.png)

## Lane change completion checks

To determine if the ego vehicle has successfully changed lanes, one of two criteria must be met: either the longitudinal or the lateral criteria.

For the longitudinal criteria, the ego vehicle must pass the lane-changing end pose and be within the `finish_judge_buffer` distance from it. The module then checks if the ego vehicle is in the target lane. If true, the module returns success. This check ensures that the planner manager updates the root lanelet correctly based on the ego vehicle's current pose. Without this check, if the ego vehicle is changing lanes while avoiding an obstacle and its current pose is in the original lane, the planner manager might set the root lanelet as the original lane. This would force the ego vehicle to perform the lane change again. With the target lane check, the ego vehicle is confirmed to be in the target lane, and the planner manager can correctly update the root lanelets.

If the longitudinal criteria are not met, the module evaluates the lateral criteria. For the lateral criteria, the ego vehicle must be within `finish_judge_lateral_threshold` distance from the target lane's centerline, and the angle deviation must be within `finish_judge_lateral_angle_deviation` degrees. The angle deviation check ensures there is no sudden steering. If the angle deviation is set too high, the ego vehicle's orientation could deviate significantly from the centerline, causing the trajectory follower to aggressively correct the steering to return to the centerline. Keeping the angle deviation value as small as possible avoids this issue.

The process of determining lane change completion is shown in the following diagram.

```plantuml
@startuml
skinparam defaultTextAlignment center
skinparam backgroundColor #WHITE

title Lane change completion judge

start

:Calculate distance from current ego pose to lane change end pose;

if (Is ego velocity < 1.0?) then (<color:green><b>YES</b></color>)
:Set <b>finish_judge_buffer</b> to 0.0;
else (<color:red><b>NO</b></color>)
:Set <b>finish_judge_buffer</b> to lane_change_finish_judge_buffer;
endif

if (ego has passed the end_pose and ego is <b>finish_judge_buffer</b> meters away from end_pose?) then (<color:green><b>YES</b></color>)
if (Current ego pose is in target lanes' polygon?) then (<color:green><b>YES</b></color>)
:Lane change is <color:green><b>completed</b></color>;
stop
else (<color:red><b>NO</b></color>)
:Lane change is <color:red><b>NOT</b></color> completed;
stop
endif
else (<color:red><b>NO</b></color>)
endif

if (ego's yaw deviation to centerline exceeds finish_judge_lateral_angle_deviation?) then (<color:red><b>YES</b></color>)
:Lane change is <color:red><b>NOT</b></color> completed;
stop
else (<color:green><b>NO</b></color>)
:Calculate distance to the target lanes' centerline;
if (abs(distance to the target lanes' centerline) is less than finish_judge_lateral_threshold?) then (<color:green><b>YES</b></color>)
:Lane change is <color:green><b>completed</b></color>;
stop
else (<color:red><b>NO</b></color>)
:Lane change is <color:red><b>NOT</b></color> completed;
stop
endif
endif

@enduml
```

## Parameters

### Essential lane change parameters
Expand All @@ -631,7 +686,6 @@ The following parameters are configurable in [lane_change.param.yaml](https://gi
| `backward_length_buffer_for_end_of_lane` | [m] | double | The end of lane buffer to ensure ego vehicle has enough distance to start lane change | 3.0 |
| `backward_length_buffer_for_blocking_object` | [m] | double | The end of lane buffer to ensure ego vehicle has enough distance to start lane change when there is an object in front | 3.0 |
| `lane_change_finish_judge_buffer` | [m] | double | The additional buffer used to confirm lane change process completion | 2.0 |
| `finish_judge_lateral_threshold` | [m] | double | Lateral distance threshold to confirm lane change process completion | 0.2 |
| `lane_changing_lateral_jerk` | [m/s3] | double | Lateral jerk value for lane change path generation | 0.5 |
| `minimum_lane_changing_velocity` | [m/s] | double | Minimum speed during lane changing process. | 2.78 |
| `prediction_time_resolution` | [s] | double | Time resolution for object's path interpolation and collision check. | 0.5 |
Expand All @@ -647,6 +701,16 @@ The following parameters are configurable in [lane_change.param.yaml](https://gi
| `lateral_acceleration.min_values` | [m/ss] | double | Min lateral acceleration values corresponding to velocity (look up table) | [0.4, 0.4, 0.4] |
| `lateral_acceleration.max_values` | [m/ss] | double | Max lateral acceleration values corresponding to velocity (look up table) | [0.65, 0.65, 0.65] |

### Parameter to judge if lane change is completed

The following parameters are used to judge lane change completion.

| Name | Unit | Type | Description | Default value |
| :------------------------------------- | ----- | ------ | ---------------------------------------------------------------------------------------------------------------------- | ------------- |
| `lane_change_finish_judge_buffer` | [m] | double | The longitudinal distance starting from the lane change end pose. | 2.0 |
| `finish_judge_lateral_threshold` | [m] | double | The lateral distance from targets lanes' centerline. Used in addition with `finish_judge_lateral_angle_deviation` | 0.1 |
| `finish_judge_lateral_angle_deviation` | [deg] | double | Ego angle deviation with reference to target lanes' centerline. Used in addition with `finish_judge_lateral_threshold` | 2.0 |

### Lane change regulations

| Name | Unit | Type | Description | Default value |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

backward_length_buffer_for_end_of_lane: 3.0 # [m]
backward_length_buffer_for_blocking_object: 3.0 # [m]
lane_change_finish_judge_buffer: 2.0 # [m]

lane_changing_lateral_jerk: 0.5 # [m/s3]

Expand Down Expand Up @@ -109,7 +108,9 @@
overhang_tolerance: 0.0 # [m]
unsafe_hysteresis_threshold: 10 # [/]

finish_judge_lateral_threshold: 0.2 # [m]
lane_change_finish_judge_buffer: 2.0 # [m]
finish_judge_lateral_threshold: 0.1 # [m]
finish_judge_lateral_angle_deviation: 1.0 # [deg]

# debug
publish_debug_marker: false
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include <autoware/behavior_path_planner_common/parameters.hpp>
#include <autoware/route_handler/route_handler.hpp>
#include <autoware/universe_utils/math/unit_conversion.hpp>
#include <interpolation/linear_interpolation.hpp>

#include <nav_msgs/msg/odometry.hpp>
Expand Down Expand Up @@ -109,7 +110,6 @@ struct Parameters
double lane_changing_lateral_jerk{0.5};
double minimum_lane_changing_velocity{5.6};
double lane_change_prepare_duration{4.0};
double lane_change_finish_judge_buffer{3.0};
LateralAccelerationMap lane_change_lat_acc_map;

// parked vehicle
Expand Down Expand Up @@ -157,7 +157,10 @@ struct Parameters
// abort
CancelParameters cancel{};

// finish judge parameter
double lane_change_finish_judge_buffer{3.0};
double finish_judge_lateral_threshold{0.2};
double finish_judge_lateral_angle_deviation{autoware::universe_utils::deg2rad(3.0)};

// debug marker
bool publish_debug_marker{false};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,8 @@ bool is_ahead_of_ego(
bool is_before_terminal(
const CommonDataPtr & common_data_ptr, const PathWithLaneId & path,
const PredictedObject & object);

double calc_angle_to_lanelet_segment(const lanelet::ConstLanelets & lanelets, const Pose & pose);
} // namespace autoware::behavior_path_planner::utils::lane_change

namespace autoware::behavior_path_planner::utils::lane_change::debug
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,67 +165,72 @@
p.minimum_lane_changing_velocity =
getOrDeclareParameter<double>(*node, parameter("minimum_lane_changing_velocity"));
p.minimum_lane_changing_velocity =
std::min(p.minimum_lane_changing_velocity, max_acc * p.lane_change_prepare_duration);
p.lane_change_finish_judge_buffer =
getOrDeclareParameter<double>(*node, parameter("lane_change_finish_judge_buffer"));

if (p.backward_length_buffer_for_end_of_lane < 1.0) {
RCLCPP_WARN_STREAM(
node->get_logger().get_child(name()),
"Lane change buffer must be more than 1 meter. Modifying the buffer.");
}

// lateral acceleration map for lane change
const auto lateral_acc_velocity =
getOrDeclareParameter<std::vector<double>>(*node, parameter("lateral_acceleration.velocity"));
const auto min_lateral_acc =
getOrDeclareParameter<std::vector<double>>(*node, parameter("lateral_acceleration.min_values"));
const auto max_lateral_acc =
getOrDeclareParameter<std::vector<double>>(*node, parameter("lateral_acceleration.max_values"));
if (
lateral_acc_velocity.size() != min_lateral_acc.size() ||
lateral_acc_velocity.size() != max_lateral_acc.size()) {
RCLCPP_ERROR(
node->get_logger().get_child(name()),
"Lane change lateral acceleration map has invalid size.");
exit(EXIT_FAILURE);
}
for (size_t i = 0; i < lateral_acc_velocity.size(); ++i) {
p.lane_change_lat_acc_map.add(
lateral_acc_velocity.at(i), min_lateral_acc.at(i), max_lateral_acc.at(i));
}

// target object
{
const std::string ns = "lane_change.target_object.";
p.object_types_to_check.check_car = getOrDeclareParameter<bool>(*node, ns + "car");
p.object_types_to_check.check_truck = getOrDeclareParameter<bool>(*node, ns + "truck");
p.object_types_to_check.check_bus = getOrDeclareParameter<bool>(*node, ns + "bus");
p.object_types_to_check.check_trailer = getOrDeclareParameter<bool>(*node, ns + "trailer");
p.object_types_to_check.check_unknown = getOrDeclareParameter<bool>(*node, ns + "unknown");
p.object_types_to_check.check_bicycle = getOrDeclareParameter<bool>(*node, ns + "bicycle");
p.object_types_to_check.check_motorcycle =
getOrDeclareParameter<bool>(*node, ns + "motorcycle");
p.object_types_to_check.check_pedestrian =
getOrDeclareParameter<bool>(*node, ns + "pedestrian");
}

// lane change cancel
p.cancel.enable_on_prepare_phase =
getOrDeclareParameter<bool>(*node, parameter("cancel.enable_on_prepare_phase"));
p.cancel.enable_on_lane_changing_phase =
getOrDeclareParameter<bool>(*node, parameter("cancel.enable_on_lane_changing_phase"));
p.cancel.delta_time = getOrDeclareParameter<double>(*node, parameter("cancel.delta_time"));
p.cancel.duration = getOrDeclareParameter<double>(*node, parameter("cancel.duration"));
p.cancel.max_lateral_jerk =
getOrDeclareParameter<double>(*node, parameter("cancel.max_lateral_jerk"));
p.cancel.overhang_tolerance =
getOrDeclareParameter<double>(*node, parameter("cancel.overhang_tolerance"));
p.cancel.unsafe_hysteresis_threshold =
getOrDeclareParameter<int>(*node, parameter("cancel.unsafe_hysteresis_threshold"));

// finish judge parameters
p.lane_change_finish_judge_buffer =
getOrDeclareParameter<double>(*node, parameter("lane_change_finish_judge_buffer"));
p.finish_judge_lateral_threshold =
getOrDeclareParameter<double>(*node, parameter("finish_judge_lateral_threshold"));
const auto finish_judge_lateral_angle_deviation =
getOrDeclareParameter<double>(*node, parameter("finish_judge_lateral_angle_deviation"));
p.finish_judge_lateral_angle_deviation =
autoware::universe_utils::deg2rad(finish_judge_lateral_angle_deviation);

Check warning on line 233 in planning/behavior_path_planner/autoware_behavior_path_lane_change_module/src/manager.cpp

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ Getting worse: Complex Method

LaneChangeModuleManager::initParams already has high cyclomatic complexity, and now it increases in Lines of Code from 199 to 203. 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.

// debug marker
p.publish_debug_marker = getOrDeclareParameter<bool>(*node, parameter("publish_debug_marker"));
Expand Down
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_path_planner/autoware_behavior_path_lane_change_module/src/scene.cpp

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

ℹ Getting worse: Lines of Code in a Single File

The lines of code increases from 1763 to 1773, improve code health by reducing it to 1000. The number of Lines of Code in a single file. More Lines of Code lowers the code health.

Check notice on line 1 in planning/behavior_path_planner/autoware_behavior_path_lane_change_module/src/scene.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.26 to 5.28, 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 All @@ -23,6 +23,7 @@
#include "autoware/behavior_path_planner_common/utils/utils.hpp"

#include <autoware/universe_utils/geometry/boost_polygon_utils.hpp>
#include <autoware/universe_utils/math/unit_conversion.hpp>
#include <autoware/universe_utils/system/time_keeper.hpp>
#include <autoware_lanelet2_extension/utility/message_conversion.hpp>
#include <autoware_lanelet2_extension/utility/utilities.hpp>
Expand Down Expand Up @@ -689,21 +690,33 @@
const auto & lane_change_end = status_.lane_change_path.info.shift_line.end;
const auto & target_lanes = get_target_lanes();
const double dist_to_lane_change_end =
utils::getSignedDistance(current_pose, lane_change_end, get_target_lanes());
double finish_judge_buffer = lane_change_parameters_->lane_change_finish_judge_buffer;
utils::getSignedDistance(current_pose, lane_change_end, target_lanes);

Check warning on line 693 in planning/behavior_path_planner/autoware_behavior_path_lane_change_module/src/scene.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_path_planner/autoware_behavior_path_lane_change_module/src/scene.cpp#L693

Added line #L693 was not covered by tests

// If ego velocity is low, relax finish judge buffer
const double ego_velocity = getEgoVelocity();
if (std::abs(ego_velocity) < 1.0) {
finish_judge_buffer = 0.0;
}
const auto finish_judge_buffer = std::invoke([&]() {
const double ego_velocity = getEgoVelocity();
// If ego velocity is low, relax finish judge buffer
if (std::abs(ego_velocity) < 1.0) {
return 0.0;
}
return lane_change_parameters_->lane_change_finish_judge_buffer;

Check warning on line 701 in planning/behavior_path_planner/autoware_behavior_path_lane_change_module/src/scene.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_path_planner/autoware_behavior_path_lane_change_module/src/scene.cpp#L701

Added line #L701 was not covered by tests
});

const auto reach_lane_change_end = dist_to_lane_change_end + finish_judge_buffer < 0.0;
const auto has_passed_end_pose = dist_to_lane_change_end + finish_judge_buffer < 0.0;

Check warning on line 704 in planning/behavior_path_planner/autoware_behavior_path_lane_change_module/src/scene.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_path_planner/autoware_behavior_path_lane_change_module/src/scene.cpp#L704

Added line #L704 was not covered by tests

lane_change_debug_.distance_to_lane_change_finished =
dist_to_lane_change_end + finish_judge_buffer;

if (!reach_lane_change_end) {
if (has_passed_end_pose) {
const auto & lanes_polygon = common_data_ptr_->lanes_polygon_ptr->target;
return !boost::geometry::disjoint(

Check warning on line 711 in planning/behavior_path_planner/autoware_behavior_path_lane_change_module/src/scene.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_path_planner/autoware_behavior_path_lane_change_module/src/scene.cpp#L711

Added line #L711 was not covered by tests
lanes_polygon.value(),
lanelet::utils::to2D(lanelet::utils::conversion::toLaneletPoint(current_pose.position)));
}

const auto yaw_deviation_to_centerline =
utils::lane_change::calc_angle_to_lanelet_segment(target_lanes, current_pose);

Check warning on line 717 in planning/behavior_path_planner/autoware_behavior_path_lane_change_module/src/scene.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_path_planner/autoware_behavior_path_lane_change_module/src/scene.cpp#L717

Added line #L717 was not covered by tests

if (yaw_deviation_to_centerline > lane_change_parameters_->finish_judge_lateral_angle_deviation) {
return false;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2021 Tier IV, Inc.

Check notice on line 1 in planning/behavior_path_planner/autoware_behavior_path_lane_change_module/src/utils/utils.cpp

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

ℹ Getting worse: Lines of Code in a Single File

The lines of code increases from 1086 to 1095, improve code health by reducing it to 1000. The number of Lines of Code in a single file. More Lines of Code lowers the code health.

Check notice on line 1 in planning/behavior_path_planner/autoware_behavior_path_lane_change_module/src/utils/utils.cpp

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

✅ Getting better: Overall Code Complexity

The mean cyclomatic complexity decreases from 4.20 to 4.16, 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.

Check notice on line 1 in planning/behavior_path_planner/autoware_behavior_path_lane_change_module/src/utils/utils.cpp

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

✅ Getting better: Primitive Obsession

The ratio of primitive types in function arguments decreases from 30.43% to 30.06%, threshold = 30.0%. The functions in this file have too many primitive types (e.g. int, double, float) in their function argument lists. Using many primitive types lead to the code smell Primitive Obsession. Avoid adding more primitive arguments.
//
// 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 @@ -1343,6 +1343,17 @@
}
return current_max_dist >= 0.0;
}

double calc_angle_to_lanelet_segment(const lanelet::ConstLanelets & lanelets, const Pose & pose)

Check warning on line 1347 in planning/behavior_path_planner/autoware_behavior_path_lane_change_module/src/utils/utils.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_path_planner/autoware_behavior_path_lane_change_module/src/utils/utils.cpp#L1347

Added line #L1347 was not covered by tests
{
lanelet::ConstLanelet closest_lanelet;

Check warning on line 1349 in planning/behavior_path_planner/autoware_behavior_path_lane_change_module/src/utils/utils.cpp

View check run for this annotation

Codecov / codecov/patch

planning/behavior_path_planner/autoware_behavior_path_lane_change_module/src/utils/utils.cpp#L1349

Added line #L1349 was not covered by tests

if (!lanelet::utils::query::getClosestLanelet(lanelets, pose, &closest_lanelet)) {
return autoware::universe_utils::deg2rad(180);
}
const auto closest_pose = lanelet::utils::getClosestCenterPose(closest_lanelet, pose.position);
return std::abs(autoware::universe_utils::calcYawDeviation(closest_pose, pose));
}
} // namespace autoware::behavior_path_planner::utils::lane_change

namespace autoware::behavior_path_planner::utils::lane_change::debug
Expand Down
Loading