Skip to content

Commit d74c5ca

Browse files
authored
Merge pull request #1223 from tier4/cp-lane-change-intersection
fix(lane_change): cherry pick for improvements
2 parents 149fe06 + a940adc commit d74c5ca

File tree

11 files changed

+432
-143
lines changed

11 files changed

+432
-143
lines changed

planning/behavior_path_lane_change_module/README.md

+280-123
Large diffs are not rendered by default.

planning/behavior_path_lane_change_module/config/lane_change.param.yaml

+3-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,9 @@
8989
stop_time: 3.0 # [s]
9090

9191
# collision check
92-
enable_prepare_segment_collision_check: true
92+
enable_collision_check_for_prepare_phase:
93+
general_lanes: false
94+
intersection: true
9395
prepare_segment_ignore_object_velocity_thresh: 0.1 # [m/s]
9496
check_objects_on_current_lanes: true
9597
check_objects_on_other_lanes: true
Loading
Loading
Loading

planning/behavior_path_lane_change_module/include/behavior_path_lane_change_module/scene.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ class NormalLaneChange : public LaneChangeBase
172172

173173
bool isVehicleStuck(const lanelet::ConstLanelets & current_lanes) const;
174174

175+
bool check_prepare_phase() const;
176+
175177
double calcMaximumLaneChangeLength(
176178
const lanelet::ConstLanelet & current_terminal_lanelet, const double max_acc) const;
177179

planning/behavior_path_lane_change_module/include/behavior_path_lane_change_module/utils/data_structs.hpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ struct LaneChangeParameters
107107
double max_longitudinal_acc{1.0};
108108

109109
// collision check
110-
bool enable_prepare_segment_collision_check{true};
110+
bool enable_collision_check_for_prepare_phase_in_general_lanes{false};
111+
bool enable_collision_check_for_prepare_phase_in_intersection{true};
111112
double prepare_segment_ignore_object_velocity_thresh{0.1};
112113
bool check_objects_on_current_lanes{true};
113114
bool check_objects_on_other_lanes{true};

planning/behavior_path_lane_change_module/include/behavior_path_lane_change_module/utils/utils.hpp

+55-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "rclcpp/logger.hpp"
2424

2525
#include <route_handler/route_handler.hpp>
26+
#include <tier4_autoware_utils/geometry/boost_geometry.hpp>
2627

2728
#include <autoware_auto_perception_msgs/msg/predicted_objects.hpp>
2829
#include <autoware_auto_planning_msgs/msg/path_with_lane_id.hpp>
@@ -31,6 +32,7 @@
3132

3233
#include <lanelet2_core/Forward.h>
3334

35+
#include <memory>
3436
#include <string>
3537
#include <vector>
3638

@@ -189,7 +191,7 @@ std::optional<lanelet::BasicPolygon2d> createPolygon(
189191

190192
ExtendedPredictedObject transform(
191193
const PredictedObject & object, const BehaviorPathPlannerParameters & common_parameters,
192-
const LaneChangeParameters & lane_change_parameters);
194+
const LaneChangeParameters & lane_change_parameters, const bool check_at_prepare_phase);
193195

194196
bool isCollidedPolygonsInLanelet(
195197
const std::vector<Polygon2d> & collided_polygons, const lanelet::ConstLanelets & lanes);
@@ -224,5 +226,57 @@ lanelet::ConstLanelets generateExpandedLanelets(
224226
* @return rclcpp::Logger The logger instance configured for the specified lane change type.
225227
*/
226228
rclcpp::Logger getLogger(const std::string & type);
229+
230+
/**
231+
* @brief Computes the current footprint of the ego vehicle based on its pose and size.
232+
*
233+
* This function calculates the 2D polygon representing the current footprint of the ego vehicle.
234+
* The footprint is determined by the vehicle's pose and its dimensions, including the distance
235+
* from the base to the front and rear ends of the vehicle, as well as its width.
236+
*
237+
* @param ego_pose The current pose of the ego vehicle.
238+
* @param ego_info The structural information of the ego vehicle, such as its maximum longitudinal
239+
* offset, rear overhang, and width.
240+
*
241+
* @return Polygon2d A polygon representing the current 2D footprint of the ego vehicle.
242+
*/
243+
Polygon2d getEgoCurrentFootprint(
244+
const Pose & ego_pose, const vehicle_info_util::VehicleInfo & ego_info);
245+
246+
/**
247+
* @brief Checks if the given polygon is within an intersection area.
248+
*
249+
* This function evaluates whether a specified polygon is located within the bounds of an
250+
* intersection. It identifies the intersection area by checking the attributes of the provided
251+
* lanelet. If the lanelet has an attribute indicating it is part of an intersection, the function
252+
* then checks if the polygon is fully contained within this area.
253+
*
254+
* @param route_handler a shared pointer to the route_handler
255+
* @param lanelet A lanelet to check against the
256+
* intersection area.
257+
* @param polygon The polygon to check for containment within the intersection area.
258+
*
259+
* @return bool True if the polygon is within the intersection area, false otherwise.
260+
*/
261+
bool isWithinIntersection(
262+
const std::shared_ptr<RouteHandler> & route_handler, const lanelet::ConstLanelet & lanelet,
263+
const Polygon2d & polygon);
264+
265+
/**
266+
* @brief Calculates the distance required during a lane change operation.
267+
*
268+
* Used for computing prepare or lane change length based on current and maximum velocity,
269+
* acceleration, and duration, returning the lesser of accelerated distance or distance at max
270+
* velocity.
271+
*
272+
* @param velocity The current velocity of the vehicle in meters per second (m/s).
273+
* @param maximum_velocity The maximum velocity the vehicle can reach in meters per second (m/s).
274+
* @param acceleration The acceleration of the vehicle in meters per second squared (m/s^2).
275+
* @param duration The duration of the lane change in seconds (s).
276+
* @return The calculated minimum distance in meters (m).
277+
*/
278+
double calcPhaseLength(
279+
const double velocity, const double maximum_velocity, const double acceleration,
280+
const double time);
227281
} // namespace behavior_path_planner::utils::lane_change
228282
#endif // BEHAVIOR_PATH_LANE_CHANGE_MODULE__UTILS__UTILS_HPP_

planning/behavior_path_lane_change_module/src/manager.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,10 @@ void LaneChangeModuleManager::initParams(rclcpp::Node * node)
6868
p.max_longitudinal_acc = getOrDeclareParameter<double>(*node, parameter("max_longitudinal_acc"));
6969

7070
// collision check
71-
p.enable_prepare_segment_collision_check =
72-
getOrDeclareParameter<bool>(*node, parameter("enable_prepare_segment_collision_check"));
71+
p.enable_collision_check_for_prepare_phase_in_general_lanes = getOrDeclareParameter<bool>(
72+
*node, parameter("enable_collision_check_for_prepare_phase.general_lanes"));
73+
p.enable_collision_check_for_prepare_phase_in_intersection = getOrDeclareParameter<bool>(
74+
*node, parameter("enable_collision_check_for_prepare_phase.intersection"));
7375
p.prepare_segment_ignore_object_velocity_thresh = getOrDeclareParameter<double>(
7476
*node, parameter("prepare_segment_ignore_object_velocity_thresh"));
7577
p.check_objects_on_current_lanes =

planning/behavior_path_lane_change_module/src/scene.cpp

+43-11
Original file line numberDiff line numberDiff line change
@@ -870,23 +870,27 @@ LaneChangeTargetObjects NormalLaneChange::getTargetObjects(
870870
target_objects.other_lane.reserve(target_obj_index.other_lane.size());
871871

872872
// objects in current lane
873+
const auto is_check_prepare_phase = check_prepare_phase();
873874
for (const auto & obj_idx : target_obj_index.current_lane) {
874875
const auto extended_object = utils::lane_change::transform(
875-
objects.objects.at(obj_idx), common_parameters, *lane_change_parameters_);
876+
objects.objects.at(obj_idx), common_parameters, *lane_change_parameters_,
877+
is_check_prepare_phase);
876878
target_objects.current_lane.push_back(extended_object);
877879
}
878880

879881
// objects in target lane
880882
for (const auto & obj_idx : target_obj_index.target_lane) {
881883
const auto extended_object = utils::lane_change::transform(
882-
objects.objects.at(obj_idx), common_parameters, *lane_change_parameters_);
884+
objects.objects.at(obj_idx), common_parameters, *lane_change_parameters_,
885+
is_check_prepare_phase);
883886
target_objects.target_lane.push_back(extended_object);
884887
}
885888

886889
// objects in other lane
887890
for (const auto & obj_idx : target_obj_index.other_lane) {
888891
const auto extended_object = utils::lane_change::transform(
889-
objects.objects.at(obj_idx), common_parameters, *lane_change_parameters_);
892+
objects.objects.at(obj_idx), common_parameters, *lane_change_parameters_,
893+
is_check_prepare_phase);
890894
target_objects.other_lane.push_back(extended_object);
891895
}
892896

@@ -950,8 +954,8 @@ LaneChangeTargetObjectIndices NormalLaneChange::filterObject(
950954
const auto obj_velocity_norm = std::hypot(
951955
object.kinematics.initial_twist_with_covariance.twist.linear.x,
952956
object.kinematics.initial_twist_with_covariance.twist.linear.y);
953-
const auto extended_object =
954-
utils::lane_change::transform(object, common_parameters, *lane_change_parameters_);
957+
const auto extended_object = utils::lane_change::transform(
958+
object, common_parameters, *lane_change_parameters_, check_prepare_phase());
955959

956960
const auto obj_polygon = tier4_autoware_utils::toPolygon2d(object);
957961

@@ -1270,9 +1274,8 @@ bool NormalLaneChange::getLaneChangePaths(
12701274
(prepare_duration < 1e-3) ? 0.0
12711275
: ((prepare_velocity - current_velocity) / prepare_duration);
12721276

1273-
const double prepare_length =
1274-
current_velocity * prepare_duration +
1275-
0.5 * longitudinal_acc_on_prepare * std::pow(prepare_duration, 2);
1277+
const auto prepare_length = utils::lane_change::calcPhaseLength(
1278+
current_velocity, getCommonParam().max_vel, longitudinal_acc_on_prepare, prepare_duration);
12761279

12771280
auto prepare_segment = getPrepareSegment(current_lanes, backward_path_length, prepare_length);
12781281

@@ -1324,9 +1327,9 @@ bool NormalLaneChange::getLaneChangePaths(
13241327
utils::lane_change::calcLaneChangingAcceleration(
13251328
initial_lane_changing_velocity, max_path_velocity, lane_changing_time,
13261329
sampled_longitudinal_acc);
1327-
const auto lane_changing_length =
1328-
initial_lane_changing_velocity * lane_changing_time +
1329-
0.5 * longitudinal_acc_on_lane_changing * lane_changing_time * lane_changing_time;
1330+
const auto lane_changing_length = utils::lane_change::calcPhaseLength(
1331+
initial_lane_changing_velocity, getCommonParam().max_vel,
1332+
longitudinal_acc_on_lane_changing, lane_changing_time);
13301333
const auto terminal_lane_changing_velocity = std::min(
13311334
initial_lane_changing_velocity + longitudinal_acc_on_lane_changing * lane_changing_time,
13321335
getCommonParam().max_vel);
@@ -2118,4 +2121,33 @@ void NormalLaneChange::updateStopTime()
21182121
stop_watch_.tic("stop_time");
21192122
}
21202123

2124+
bool NormalLaneChange::check_prepare_phase() const
2125+
{
2126+
const auto & route_handler = getRouteHandler();
2127+
const auto & vehicle_info = getCommonParam().vehicle_info;
2128+
2129+
const auto check_in_general_lanes =
2130+
lane_change_parameters_->enable_collision_check_for_prepare_phase_in_general_lanes;
2131+
2132+
lanelet::ConstLanelet current_lane;
2133+
if (!route_handler->getClosestLaneletWithinRoute(getEgoPose(), &current_lane)) {
2134+
RCLCPP_DEBUG(
2135+
logger_, "Unable to get current lane. Default to %s.",
2136+
(check_in_general_lanes ? "true" : "false"));
2137+
return check_in_general_lanes;
2138+
}
2139+
2140+
const auto ego_footprint = utils::lane_change::getEgoCurrentFootprint(getEgoPose(), vehicle_info);
2141+
2142+
const auto check_in_intersection = std::invoke([&]() {
2143+
if (!lane_change_parameters_->enable_collision_check_for_prepare_phase_in_intersection) {
2144+
return false;
2145+
}
2146+
2147+
return utils::lane_change::isWithinIntersection(route_handler, current_lane, ego_footprint);
2148+
});
2149+
2150+
return check_in_intersection || check_in_general_lanes;
2151+
}
2152+
21212153
} // namespace behavior_path_planner

planning/behavior_path_lane_change_module/src/utils/utils.cpp

+43-4
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,11 @@
3131
#include <motion_utils/trajectory/path_with_lane_id.hpp>
3232
#include <motion_utils/trajectory/trajectory.hpp>
3333
#include <rclcpp/rclcpp.hpp>
34+
#include <tier4_autoware_utils/geometry/boost_geometry.hpp>
3435
#include <tier4_autoware_utils/geometry/boost_polygon_utils.hpp>
36+
#include <vehicle_info_util/vehicle_info.hpp>
37+
38+
#include <geometry_msgs/msg/detail/pose__struct.hpp>
3539

3640
#include <lanelet2_core/LaneletMap.h>
3741
#include <lanelet2_core/geometry/LineString.h>
@@ -435,7 +439,8 @@ PathWithLaneId getReferencePathFromTargetLane(
435439
.get_child("getReferencePathFromTargetLane"),
436440
"start: %f, end: %f", s_start, s_end);
437441

438-
if (s_end - s_start < lane_changing_length) {
442+
constexpr double epsilon = 1e-4;
443+
if (s_end - s_start + epsilon < lane_changing_length) {
439444
return PathWithLaneId();
440445
}
441446

@@ -1123,7 +1128,7 @@ std::optional<lanelet::BasicPolygon2d> createPolygon(
11231128
ExtendedPredictedObject transform(
11241129
const PredictedObject & object,
11251130
[[maybe_unused]] const BehaviorPathPlannerParameters & common_parameters,
1126-
const LaneChangeParameters & lane_change_parameters)
1131+
const LaneChangeParameters & lane_change_parameters, const bool check_at_prepare_phase)
11271132
{
11281133
ExtendedPredictedObject extended_object;
11291134
extended_object.uuid = object.object_id;
@@ -1133,8 +1138,6 @@ ExtendedPredictedObject transform(
11331138
extended_object.shape = object.shape;
11341139

11351140
const auto & time_resolution = lane_change_parameters.prediction_time_resolution;
1136-
const auto & check_at_prepare_phase =
1137-
lane_change_parameters.enable_prepare_segment_collision_check;
11381141
const auto & prepare_duration = lane_change_parameters.lane_change_prepare_duration;
11391142
const auto & velocity_threshold =
11401143
lane_change_parameters.prepare_segment_ignore_object_velocity_thresh;
@@ -1192,4 +1195,40 @@ rclcpp::Logger getLogger(const std::string & type)
11921195
{
11931196
return rclcpp::get_logger("lane_change").get_child(type);
11941197
}
1198+
1199+
Polygon2d getEgoCurrentFootprint(
1200+
const Pose & ego_pose, const vehicle_info_util::VehicleInfo & ego_info)
1201+
{
1202+
const auto base_to_front = ego_info.max_longitudinal_offset_m;
1203+
const auto base_to_rear = ego_info.rear_overhang_m;
1204+
const auto width = ego_info.vehicle_width_m;
1205+
1206+
return tier4_autoware_utils::toFootprint(ego_pose, base_to_front, base_to_rear, width);
1207+
}
1208+
1209+
bool isWithinIntersection(
1210+
const std::shared_ptr<RouteHandler> & route_handler, const lanelet::ConstLanelet & lanelet,
1211+
const Polygon2d & polygon)
1212+
{
1213+
const std::string id = lanelet.attributeOr("intersection_area", "else");
1214+
if (id == "else") {
1215+
return false;
1216+
}
1217+
1218+
const auto lanelet_polygon =
1219+
route_handler->getLaneletMapPtr()->polygonLayer.get(std::atoi(id.c_str()));
1220+
1221+
return boost::geometry::within(
1222+
polygon, utils::toPolygon2d(lanelet::utils::to2D(lanelet_polygon.basicPolygon())));
1223+
}
1224+
1225+
double calcPhaseLength(
1226+
const double velocity, const double maximum_velocity, const double acceleration,
1227+
const double duration)
1228+
{
1229+
const auto length_with_acceleration =
1230+
velocity * duration + 0.5 * acceleration * std::pow(duration, 2);
1231+
const auto length_with_max_velocity = maximum_velocity * duration;
1232+
return std::min(length_with_acceleration, length_with_max_velocity);
1233+
}
11951234
} // namespace behavior_path_planner::utils::lane_change

0 commit comments

Comments
 (0)