Skip to content

Commit ae805fc

Browse files
TomohitoAndosaka1-s
authored andcommitted
Merge pull request #1712 from tier4/cp-lane-change-bug-fixes
chore(lane change): cherry-pick bug fixes
1 parent 5357377 commit ae805fc

File tree

19 files changed

+662
-489
lines changed

19 files changed

+662
-489
lines changed

planning/behavior_path_planner/autoware_behavior_path_avoidance_by_lane_change_module/src/scene.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "autoware/behavior_path_planner_common/utils/utils.hpp"
2121
#include "autoware/behavior_path_static_obstacle_avoidance_module/utils.hpp"
2222

23+
#include <autoware/behavior_path_lane_change_module/utils/calculation.hpp>
2324
#include <autoware/behavior_path_lane_change_module/utils/utils.hpp>
2425
#include <autoware/behavior_path_static_obstacle_avoidance_module/data_structs.hpp>
2526
#include <lanelet2_extension/utility/utilities.hpp>
@@ -281,7 +282,7 @@ double AvoidanceByLaneChange::calcMinimumLaneChangeLength() const
281282
return std::numeric_limits<double>::infinity();
282283
}
283284

284-
return utils::lane_change::calcMinimumLaneChangeLength(
285+
return utils::lane_change::calculation::calc_minimum_lane_change_length(
285286
getRouteHandler(), current_lanes.back(), *lane_change_parameters_, direction_);
286287
}
287288

planning/behavior_path_planner/autoware_behavior_path_lane_change_module/README.md

+12-46
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ The Lane Change module is activated when lane change is needed and can be safely
1111
- `allow_lane_change` tags is set as `true`
1212
- During lane change request condition
1313
- The ego-vehicle isn’t on a `preferred_lane`.
14-
- There is neither intersection nor crosswalk on the path of the lane change
14+
- The ego-vehicle isn't approaching a traffic light. (condition parameterized)
15+
- The ego-vehicle isn't approaching a crosswalk. (condition parameterized)
16+
- The ego-vehicle isn't approaching an intersection. (condition parameterized)
1517
- lane change ready condition
1618
- Path of the lane change does not collide with other dynamic objects (see the figure below)
1719
- Lane change candidate path is approved by an operator.
@@ -182,11 +184,9 @@ A candidate path is considered valid if it meets the following criteria:
182184
1. The distance from the ego vehicle's current position to the end of the current lanes is sufficient to perform a single lane change.
183185
2. The distance from the ego vehicle's current position to the goal along the current lanes is adequate to complete multiple lane changes.
184186
3. The distance from the ego vehicle's current position to the end of the target lanes is adequate for completing multiple lane changes.
185-
4. Intersection requirements are met (conditions are parameterized).
186-
5. Crosswalk requirements are satisfied (conditions are parameterized).
187-
6. Traffic light regulations are adhered to (conditions are parameterized).
188-
7. The lane change can be completed after passing a parked vehicle.
189-
8. The lane change is deemed safe to execute.
187+
4. The distance from the ego vehicle's current position to the next regulatory element is adequate to perform a single lane change.
188+
5. The lane change can be completed after passing a parked vehicle.
189+
6. The lane change is deemed safe to execute.
190190

191191
The following flow chart illustrates the validity check.
192192

@@ -231,43 +231,6 @@ group check for distance #LightYellow
231231
endif
232232
end group
233233
234-
235-
236-
group evaluate on Crosswalk #LightCyan
237-
if (regulate_on_crosswalk and not enough length to crosswalk) then (yes)
238-
if (stop time < stop time threshold\n(Related to stuck detection)) then (yes)
239-
#LightPink:Reject path;
240-
stop
241-
else (no)
242-
:Allow lane change in crosswalk;
243-
endif
244-
else (no)
245-
endif
246-
end group
247-
248-
group evaluate on Intersection #LightGreen
249-
if (regulate_on_intersection and not enough length to intersection) then (yes)
250-
if (stop time < stop time threshold\n(Related to stuck detection)) then (yes)
251-
#LightPink:Reject path;
252-
stop
253-
else (no)
254-
:Allow lane change in intersection;
255-
endif
256-
else (no)
257-
endif
258-
end group
259-
260-
group evaluate on Traffic Light #Lavender
261-
if (regulate_on_traffic_light and not enough length to complete lane change before stop line) then (yes)
262-
#LightPink:Reject path;
263-
stop
264-
elseif (stopped at red traffic light within distance) then (yes)
265-
#LightPink:Reject path;
266-
stop
267-
else (no)
268-
endif
269-
end group
270-
271234
if (ego is not stuck but parked vehicle exists in target lane) then (yes)
272235
#LightPink:Reject path;
273236
stop
@@ -517,8 +480,8 @@ The function to stop by keeping a margin against forward obstacle in the previou
517480

518481
### Lane change regulations
519482

520-
If you want to regulate lane change on crosswalks or intersections, the lane change module finds a lane change path excluding it includes crosswalks or intersections.
521-
To regulate lane change on crosswalks or intersections, change `regulation.crosswalk` or `regulation.intersection` to `true`.
483+
If you want to regulate lane change on crosswalks, intersections, or traffic lights, the lane change module is disabled near any of them.
484+
To regulate lane change on crosswalks, intersections, or traffic lights, set `regulation.crosswalk`, `regulation.intersection` or `regulation.traffic_light` to `true`.
522485
If the ego vehicle gets stuck, to avoid stuck, it enables lane change in crosswalk/intersection.
523486
If the ego vehicle stops more than `stuck_detection.stop_time` seconds, it is regarded as a stuck.
524487
If the ego vehicle velocity is smaller than `stuck_detection.velocity`, it is regarded as stopping.
@@ -573,6 +536,8 @@ detach
573536
@enduml
574537
```
575538

539+
During a lane change, a safety check is made in consideration of the deceleration of the ego vehicle, and a safety check is made for `cancel.deceleration_sampling_num` deceleration patterns, and the lane change will be canceled if the abort condition is satisfied for all deceleration patterns.
540+
576541
To preventive measure for lane change path oscillations caused by alternating safe and unsafe conditions, an additional hysteresis count check is implemented before executing an abort or cancel maneuver. If unsafe, the `unsafe_hysteresis_count_` is incremented and compared against `unsafe_hysteresis_threshold`; exceeding it prompts an abort condition check, ensuring decisions are made with consideration to recent safety assessments as shown in flow chart above. This mechanism stabilizes decision-making, preventing abrupt changes due to transient unsafe conditions.
577542

578543
```plantuml
@@ -823,7 +788,8 @@ The following parameters are configurable in `lane_change.param.yaml`.
823788
| `cancel.duration` | [s] | double | The time taken to complete returning to the center line. | 3.0 |
824789
| `cancel.max_lateral_jerk` | [m/sss] | double | The maximum lateral jerk for abort path | 1000.0 |
825790
| `cancel.overhang_tolerance` | [m] | double | Lane change cancel is prohibited if the vehicle head exceeds the lane boundary more than this tolerance distance | 0.0 |
826-
| `unsafe_hysteresis_threshold` | [-] | int | threshold that helps prevent frequent switching between safe and unsafe decisions | 10 |
791+
| `cancel.unsafe_hysteresis_threshold` | [-] | int | threshold that helps prevent frequent switching between safe and unsafe decisions | 10 |
792+
| `cancel.deceleration_sampling_num` | [-] | int | Number of deceleration patterns to check safety to cancel lane change | 5 |
827793

828794
### Debug
829795

planning/behavior_path_planner/autoware_behavior_path_lane_change_module/config/lane_change.param.yaml

+2-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@
106106
general_lanes: false
107107
intersection: true
108108
turns: true
109-
prepare_segment_ignore_object_velocity_thresh: 0.1 # [m/s]
109+
stopped_object_velocity_threshold: 1.0 # [m/s]
110110
check_objects_on_current_lanes: true
111111
check_objects_on_other_lanes: true
112112
use_all_predicted_path: true
@@ -120,6 +120,7 @@
120120
max_lateral_jerk: 1000.0 # [m/s3]
121121
overhang_tolerance: 0.0 # [m]
122122
unsafe_hysteresis_threshold: 10 # [/]
123+
deceleration_sampling_num: 5 # [/]
123124

124125
lane_change_finish_judge_buffer: 2.0 # [m]
125126
finish_judge_lateral_threshold: 0.1 # [m]

planning/behavior_path_planner/autoware_behavior_path_lane_change_module/include/autoware/behavior_path_lane_change_module/scene.hpp

+21-4
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ using geometry_msgs::msg::Twist;
3737
using lane_change::LanesPolygon;
3838
using tier4_planning_msgs::msg::PathWithLaneId;
3939
using utils::path_safety_checker::ExtendedPredictedObjects;
40+
using utils::path_safety_checker::RSSparams;
4041

4142
class NormalLaneChange : public LaneChangeBase
4243
{
@@ -53,6 +54,8 @@ class NormalLaneChange : public LaneChangeBase
5354

5455
void update_lanes(const bool is_approved) final;
5556

57+
void update_filtered_objects() final;
58+
5659
void updateLaneChangeStatus() override;
5760

5861
std::pair<bool, bool> getSafePath(LaneChangePath & safe_path) const override;
@@ -106,14 +109,18 @@ class NormalLaneChange : public LaneChangeBase
106109

107110
bool isStoppedAtRedTrafficLight() const override;
108111

109-
TurnSignalInfo get_current_turn_signal_info() override;
112+
bool is_near_regulatory_element() const final;
113+
114+
TurnSignalInfo get_current_turn_signal_info() const final;
110115

111116
protected:
112117
lanelet::ConstLanelets getLaneChangeLanes(
113118
const lanelet::ConstLanelets & current_lanes, Direction direction) const override;
114119

115120
int getNumToPreferredLane(const lanelet::ConstLanelet & lane) const override;
116121

122+
TurnSignalInfo get_terminal_turn_signal_info() const final;
123+
117124
std::vector<double> sampleLongitudinalAccValues(
118125
const lanelet::ConstLanelets & current_lanes,
119126
const lanelet::ConstLanelets & target_lanes) const;
@@ -157,9 +164,7 @@ class NormalLaneChange : public LaneChangeBase
157164

158165
bool getLaneChangePaths(
159166
const lanelet::ConstLanelets & current_lanes, const lanelet::ConstLanelets & target_lanes,
160-
Direction direction, LaneChangePaths * candidate_paths,
161-
const utils::path_safety_checker::RSSparams rss_params, const bool is_stuck,
162-
const bool check_safety = true) const override;
167+
Direction direction, const bool is_stuck, LaneChangePaths * candidate_paths) const;
163168

164169
std::optional<LaneChangePath> calcTerminalLaneChangePath(
165170
const lanelet::ConstLanelets & current_lanes,
@@ -171,6 +176,17 @@ class NormalLaneChange : public LaneChangeBase
171176
const LaneChangePath & lane_change_path,
172177
const lane_change::TargetObjects & collision_check_objects,
173178
const utils::path_safety_checker::RSSparams & rss_params,
179+
const size_t deceleration_sampling_num, CollisionCheckDebugMap & debug_data) const;
180+
181+
bool has_collision_with_decel_patterns(
182+
const LaneChangePath & lane_change_path, const ExtendedPredictedObjects & objects,
183+
const size_t deceleration_sampling_num, const RSSparams & rss_param,
184+
const bool check_prepare_phase, CollisionCheckDebugMap & debug_data) const;
185+
186+
bool is_collided(
187+
const LaneChangePath & lane_change_path, const ExtendedPredictedObject & obj,
188+
const std::vector<PoseWithVelocityStamped> & ego_predicted_path,
189+
const RSSparams & selected_rss_param, const bool check_prepare_phase,
174190
CollisionCheckDebugMap & debug_data) const;
175191

176192
//! @brief Check if the ego vehicle is in stuck by a stationary obstacle.
@@ -220,6 +236,7 @@ class NormalLaneChange : public LaneChangeBase
220236
}
221237

222238
double stop_time_{0.0};
239+
static constexpr double floating_err_th{1e-3};
223240
};
224241
} // namespace autoware::behavior_path_planner
225242
#endif // AUTOWARE__BEHAVIOR_PATH_LANE_CHANGE_MODULE__SCENE_HPP_

planning/behavior_path_planner/autoware_behavior_path_lane_change_module/include/autoware/behavior_path_lane_change_module/utils/base_class.hpp

+32-8
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ class LaneChangeBase
6767

6868
virtual void update_lanes(const bool is_approved) = 0;
6969

70+
virtual void update_filtered_objects() = 0;
71+
7072
virtual void updateLaneChangeStatus() = 0;
7173

7274
virtual std::pair<bool, bool> getSafePath(LaneChangePath & safe_path) const = 0;
@@ -211,7 +213,7 @@ class LaneChangeBase
211213

212214
LaneChangeModuleType getModuleType() const { return type_; }
213215

214-
TurnSignalDecider getTurnSignalDecider() { return planner_data_->turn_signal_decider; }
216+
TurnSignalDecider getTurnSignalDecider() const { return planner_data_->turn_signal_decider; }
215217

216218
Direction getDirection() const
217219
{
@@ -227,7 +229,9 @@ class LaneChangeBase
227229

228230
void resetStopPose() { lane_change_stop_pose_ = std::nullopt; }
229231

230-
virtual TurnSignalInfo get_current_turn_signal_info() = 0;
232+
virtual TurnSignalInfo get_current_turn_signal_info() const = 0;
233+
234+
virtual bool is_near_regulatory_element() const = 0;
231235

232236
protected:
233237
virtual int getNumToPreferredLane(const lanelet::ConstLanelet & lane) const = 0;
@@ -236,19 +240,38 @@ class LaneChangeBase
236240
const lanelet::ConstLanelets & current_lanes, const double backward_path_length,
237241
const double prepare_length) const = 0;
238242

239-
virtual bool getLaneChangePaths(
240-
const lanelet::ConstLanelets & original_lanelets,
241-
const lanelet::ConstLanelets & target_lanelets, Direction direction,
242-
LaneChangePaths * candidate_paths, const utils::path_safety_checker::RSSparams rss_params,
243-
const bool is_stuck, const bool check_safety) const = 0;
244-
245243
virtual bool isValidPath(const PathWithLaneId & path) const = 0;
246244

247245
virtual bool isAbleToStopSafely() const = 0;
248246

249247
virtual lanelet::ConstLanelets getLaneChangeLanes(
250248
const lanelet::ConstLanelets & current_lanes, Direction direction) const = 0;
251249

250+
virtual TurnSignalInfo get_terminal_turn_signal_info() const = 0;
251+
252+
TurnSignalInfo get_turn_signal(const Pose & start, const Pose & end) const
253+
{
254+
TurnSignalInfo turn_signal;
255+
switch (direction_) {
256+
case Direction::LEFT:
257+
turn_signal.turn_signal.command = TurnIndicatorsCommand::ENABLE_LEFT;
258+
break;
259+
case Direction::RIGHT:
260+
turn_signal.turn_signal.command = TurnIndicatorsCommand::ENABLE_RIGHT;
261+
break;
262+
default:
263+
turn_signal.turn_signal.command = TurnIndicatorsCommand::NO_COMMAND;
264+
break;
265+
}
266+
267+
turn_signal.desired_start_point = start;
268+
turn_signal.desired_end_point = end;
269+
turn_signal.required_start_point = turn_signal.desired_start_point;
270+
turn_signal.required_end_point = turn_signal.desired_end_point;
271+
272+
return turn_signal;
273+
}
274+
252275
LaneChangeStatus status_{};
253276
PathShifter path_shifter_{};
254277

@@ -258,6 +281,7 @@ class LaneChangeBase
258281
std::shared_ptr<LaneChangePath> abort_path_{};
259282
std::shared_ptr<const PlannerData> planner_data_{};
260283
lane_change::CommonDataPtr common_data_ptr_{};
284+
FilteredByLanesExtendedObjects filtered_objects_{};
261285
BehaviorModuleOutput prev_module_output_{};
262286
std::optional<Pose> lane_change_stop_pose_{std::nullopt};
263287

planning/behavior_path_planner/autoware_behavior_path_lane_change_module/include/autoware/behavior_path_lane_change_module/utils/calculation.hpp

+19
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,12 @@
1616

1717
#include "autoware/behavior_path_lane_change_module/utils/data_structs.hpp"
1818

19+
#include <autoware/route_handler/route_handler.hpp>
20+
1921
namespace autoware::behavior_path_planner::utils::lane_change::calculation
2022
{
23+
using autoware::route_handler::Direction;
24+
using autoware::route_handler::RouteHandler;
2125
using behavior_path_planner::lane_change::CommonDataPtr;
2226
using behavior_path_planner::lane_change::LCParamPtr;
2327

@@ -96,6 +100,21 @@ double calc_maximum_prepare_length(const CommonDataPtr & common_data_ptr);
96100
double calc_ego_dist_to_lanes_start(
97101
const CommonDataPtr & common_data_ptr, const lanelet::ConstLanelets & current_lanes,
98102
const lanelet::ConstLanelets & target_lanes);
103+
104+
double calc_minimum_lane_change_length(
105+
const LaneChangeParameters & lane_change_parameters, const std::vector<double> & shift_intervals);
106+
107+
double calc_minimum_lane_change_length(
108+
const std::shared_ptr<RouteHandler> & route_handler, const lanelet::ConstLanelet & lane,
109+
const LaneChangeParameters & lane_change_parameters, Direction direction);
110+
111+
double calc_maximum_lane_change_length(
112+
const double current_velocity, const LaneChangeParameters & lane_change_parameters,
113+
const std::vector<double> & shift_intervals, const double max_acc);
114+
115+
double calc_maximum_lane_change_length(
116+
const CommonDataPtr & common_data_ptr, const lanelet::ConstLanelet & current_terminal_lanelet,
117+
const double max_acc);
99118
} // namespace autoware::behavior_path_planner::utils::lane_change::calculation
100119

101120
#endif // AUTOWARE__BEHAVIOR_PATH_LANE_CHANGE_MODULE__UTILS__CALCULATION_HPP_

planning/behavior_path_planner/autoware_behavior_path_lane_change_module/include/autoware/behavior_path_lane_change_module/utils/data_structs.hpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ struct CancelParameters
9494
// number of unsafe exceeds unsafe_hysteresis_threshold, the lane change will be cancelled or
9595
// aborted.
9696
int unsafe_hysteresis_threshold{2};
97+
98+
int deceleration_sampling_num{5};
9799
};
98100

99101
struct Parameters
@@ -131,7 +133,7 @@ struct Parameters
131133
bool enable_collision_check_for_prepare_phase_in_general_lanes{false};
132134
bool enable_collision_check_for_prepare_phase_in_intersection{true};
133135
bool enable_collision_check_for_prepare_phase_in_turns{true};
134-
double prepare_segment_ignore_object_velocity_thresh{0.1};
136+
double stopped_object_velocity_threshold{0.1};
135137
bool check_objects_on_current_lanes{true};
136138
bool check_objects_on_other_lanes{true};
137139
bool use_all_predicted_path{false};

planning/behavior_path_planner/autoware_behavior_path_lane_change_module/include/autoware/behavior_path_lane_change_module/utils/utils.hpp

+9-18
Original file line numberDiff line numberDiff line change
@@ -60,17 +60,6 @@ using tier4_planning_msgs::msg::PathWithLaneId;
6060
double calcLaneChangeResampleInterval(
6161
const double lane_changing_length, const double lane_changing_velocity);
6262

63-
double calcMinimumLaneChangeLength(
64-
const LaneChangeParameters & lane_change_parameters, const std::vector<double> & shift_intervals);
65-
66-
double calcMinimumLaneChangeLength(
67-
const std::shared_ptr<RouteHandler> & route_handler, const lanelet::ConstLanelet & lane,
68-
const LaneChangeParameters & lane_change_parameters, Direction direction);
69-
70-
double calcMaximumLaneChangeLength(
71-
const double current_velocity, const LaneChangeParameters & lane_change_parameters,
72-
const std::vector<double> & shift_intervals, const double max_acc);
73-
7463
double calcMinimumAcceleration(
7564
const double current_velocity, const double min_longitudinal_acc,
7665
const LaneChangeParameters & lane_change_parameters);
@@ -158,10 +147,9 @@ std::optional<lanelet::ConstLanelet> getLaneChangeTargetLane(
158147
const RouteHandler & route_handler, const lanelet::ConstLanelets & current_lanes,
159148
const LaneChangeModuleType type, const Direction & direction);
160149

161-
std::vector<PoseWithVelocityStamped> convertToPredictedPath(
162-
const LaneChangePath & lane_change_path, const Twist & vehicle_twist, const Pose & pose,
163-
const BehaviorPathPlannerParameters & common_parameters,
164-
const LaneChangeParameters & lane_change_parameters, const double resolution);
150+
std::vector<PoseWithVelocityStamped> convert_to_predicted_path(
151+
const CommonDataPtr & common_data_ptr, const LaneChangePath & lane_change_path,
152+
const double lane_changing_acceleration);
165153

166154
bool isParkedObject(
167155
const PathWithLaneId & path, const RouteHandler & route_handler,
@@ -189,7 +177,7 @@ std::optional<lanelet::BasicPolygon2d> createPolygon(
189177

190178
ExtendedPredictedObject transform(
191179
const PredictedObject & object, const BehaviorPathPlannerParameters & common_parameters,
192-
const LaneChangeParameters & lane_change_parameters, const bool check_at_prepare_phase);
180+
const LaneChangeParameters & lane_change_parameters);
193181

194182
bool isCollidedPolygonsInLanelet(
195183
const std::vector<Polygon2d> & collided_polygons,
@@ -314,8 +302,11 @@ bool is_before_terminal(
314302
double calc_angle_to_lanelet_segment(const lanelet::ConstLanelets & lanelets, const Pose & pose);
315303

316304
ExtendedPredictedObjects transform_to_extended_objects(
317-
const CommonDataPtr & common_data_ptr, const std::vector<PredictedObject> & objects,
318-
const bool check_prepare_phase);
305+
const CommonDataPtr & common_data_ptr, const std::vector<PredictedObject> & objects);
306+
307+
double get_distance_to_next_regulatory_element(
308+
const CommonDataPtr & common_data_ptr, const bool ignore_crosswalk = false,
309+
const bool ignore_intersection = false);
319310
} // namespace autoware::behavior_path_planner::utils::lane_change
320311

321312
namespace autoware::behavior_path_planner::utils::lane_change::debug

0 commit comments

Comments
 (0)