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

chore(lane change): cherry-pick bug fixes #1712

Merged
merged 12 commits into from
Dec 21, 2024
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 @@ -20,6 +20,7 @@
#include "autoware/behavior_path_planner_common/utils/utils.hpp"
#include "autoware/behavior_path_static_obstacle_avoidance_module/utils.hpp"

#include <autoware/behavior_path_lane_change_module/utils/calculation.hpp>
#include <autoware/behavior_path_lane_change_module/utils/utils.hpp>
#include <autoware/behavior_path_static_obstacle_avoidance_module/data_structs.hpp>
#include <lanelet2_extension/utility/utilities.hpp>
Expand Down Expand Up @@ -281,7 +282,7 @@ double AvoidanceByLaneChange::calcMinimumLaneChangeLength() const
return std::numeric_limits<double>::infinity();
}

return utils::lane_change::calcMinimumLaneChangeLength(
return utils::lane_change::calculation::calc_minimum_lane_change_length(
getRouteHandler(), current_lanes.back(), *lane_change_parameters_, direction_);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ The Lane Change module is activated when lane change is needed and can be safely
- `allow_lane_change` tags is set as `true`
- During lane change request condition
- The ego-vehicle isn’t on a `preferred_lane`.
- There is neither intersection nor crosswalk on the path of the lane change
- The ego-vehicle isn't approaching a traffic light. (condition parameterized)
- The ego-vehicle isn't approaching a crosswalk. (condition parameterized)
- The ego-vehicle isn't approaching an intersection. (condition parameterized)
- lane change ready condition
- Path of the lane change does not collide with other dynamic objects (see the figure below)
- Lane change candidate path is approved by an operator.
Expand Down Expand Up @@ -182,11 +184,9 @@ A candidate path is considered valid if it meets the following criteria:
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.
2. The distance from the ego vehicle's current position to the goal along the current lanes is adequate to complete multiple lane changes.
3. The distance from the ego vehicle's current position to the end of the target lanes is adequate for completing multiple lane changes.
4. Intersection requirements are met (conditions are parameterized).
5. Crosswalk requirements are satisfied (conditions are parameterized).
6. Traffic light regulations are adhered to (conditions are parameterized).
7. The lane change can be completed after passing a parked vehicle.
8. The lane change is deemed safe to execute.
4. The distance from the ego vehicle's current position to the next regulatory element is adequate to perform a single lane change.
5. The lane change can be completed after passing a parked vehicle.
6. The lane change is deemed safe to execute.

The following flow chart illustrates the validity check.

Expand Down Expand Up @@ -231,43 +231,6 @@ group check for distance #LightYellow
endif
end group



group evaluate on Crosswalk #LightCyan
if (regulate_on_crosswalk and not enough length to crosswalk) then (yes)
if (stop time < stop time threshold\n(Related to stuck detection)) then (yes)
#LightPink:Reject path;
stop
else (no)
:Allow lane change in crosswalk;
endif
else (no)
endif
end group

group evaluate on Intersection #LightGreen
if (regulate_on_intersection and not enough length to intersection) then (yes)
if (stop time < stop time threshold\n(Related to stuck detection)) then (yes)
#LightPink:Reject path;
stop
else (no)
:Allow lane change in intersection;
endif
else (no)
endif
end group

group evaluate on Traffic Light #Lavender
if (regulate_on_traffic_light and not enough length to complete lane change before stop line) then (yes)
#LightPink:Reject path;
stop
elseif (stopped at red traffic light within distance) then (yes)
#LightPink:Reject path;
stop
else (no)
endif
end group

if (ego is not stuck but parked vehicle exists in target lane) then (yes)
#LightPink:Reject path;
stop
Expand Down Expand Up @@ -517,8 +480,8 @@ The function to stop by keeping a margin against forward obstacle in the previou

### Lane change regulations

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.
To regulate lane change on crosswalks or intersections, change `regulation.crosswalk` or `regulation.intersection` to `true`.
If you want to regulate lane change on crosswalks, intersections, or traffic lights, the lane change module is disabled near any of them.
To regulate lane change on crosswalks, intersections, or traffic lights, set `regulation.crosswalk`, `regulation.intersection` or `regulation.traffic_light` to `true`.
If the ego vehicle gets stuck, to avoid stuck, it enables lane change in crosswalk/intersection.
If the ego vehicle stops more than `stuck_detection.stop_time` seconds, it is regarded as a stuck.
If the ego vehicle velocity is smaller than `stuck_detection.velocity`, it is regarded as stopping.
Expand Down Expand Up @@ -573,6 +536,8 @@ detach
@enduml
```

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.

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.

```plantuml
Expand Down Expand Up @@ -823,7 +788,8 @@ The following parameters are configurable in `lane_change.param.yaml`.
| `cancel.duration` | [s] | double | The time taken to complete returning to the center line. | 3.0 |
| `cancel.max_lateral_jerk` | [m/sss] | double | The maximum lateral jerk for abort path | 1000.0 |
| `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 |
| `unsafe_hysteresis_threshold` | [-] | int | threshold that helps prevent frequent switching between safe and unsafe decisions | 10 |
| `cancel.unsafe_hysteresis_threshold` | [-] | int | threshold that helps prevent frequent switching between safe and unsafe decisions | 10 |
| `cancel.deceleration_sampling_num` | [-] | int | Number of deceleration patterns to check safety to cancel lane change | 5 |

### Debug

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@
general_lanes: false
intersection: true
turns: true
prepare_segment_ignore_object_velocity_thresh: 0.1 # [m/s]
stopped_object_velocity_threshold: 1.0 # [m/s]
check_objects_on_current_lanes: true
check_objects_on_other_lanes: true
use_all_predicted_path: true
Expand All @@ -120,6 +120,7 @@
max_lateral_jerk: 1000.0 # [m/s3]
overhang_tolerance: 0.0 # [m]
unsafe_hysteresis_threshold: 10 # [/]
deceleration_sampling_num: 5 # [/]

lane_change_finish_judge_buffer: 2.0 # [m]
finish_judge_lateral_threshold: 0.1 # [m]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ using geometry_msgs::msg::Twist;
using lane_change::LanesPolygon;
using tier4_planning_msgs::msg::PathWithLaneId;
using utils::path_safety_checker::ExtendedPredictedObjects;
using utils::path_safety_checker::RSSparams;

class NormalLaneChange : public LaneChangeBase
{
Expand All @@ -53,6 +54,8 @@ class NormalLaneChange : public LaneChangeBase

void update_lanes(const bool is_approved) final;

void update_filtered_objects() final;

void updateLaneChangeStatus() override;

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

bool isStoppedAtRedTrafficLight() const override;

TurnSignalInfo get_current_turn_signal_info() override;
bool is_near_regulatory_element() const final;

TurnSignalInfo get_current_turn_signal_info() const final;

protected:
lanelet::ConstLanelets getLaneChangeLanes(
const lanelet::ConstLanelets & current_lanes, Direction direction) const override;

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

TurnSignalInfo get_terminal_turn_signal_info() const final;

std::vector<double> sampleLongitudinalAccValues(
const lanelet::ConstLanelets & current_lanes,
const lanelet::ConstLanelets & target_lanes) const;
Expand Down Expand Up @@ -157,9 +164,7 @@ class NormalLaneChange : public LaneChangeBase

bool getLaneChangePaths(
const lanelet::ConstLanelets & current_lanes, const lanelet::ConstLanelets & target_lanes,
Direction direction, LaneChangePaths * candidate_paths,
const utils::path_safety_checker::RSSparams rss_params, const bool is_stuck,
const bool check_safety = true) const override;
Direction direction, const bool is_stuck, LaneChangePaths * candidate_paths) const;

std::optional<LaneChangePath> calcTerminalLaneChangePath(
const lanelet::ConstLanelets & current_lanes,
Expand All @@ -171,6 +176,17 @@ class NormalLaneChange : public LaneChangeBase
const LaneChangePath & lane_change_path,
const lane_change::TargetObjects & collision_check_objects,
const utils::path_safety_checker::RSSparams & rss_params,
const size_t deceleration_sampling_num, CollisionCheckDebugMap & debug_data) const;

bool has_collision_with_decel_patterns(
const LaneChangePath & lane_change_path, const ExtendedPredictedObjects & objects,
const size_t deceleration_sampling_num, const RSSparams & rss_param,
const bool check_prepare_phase, CollisionCheckDebugMap & debug_data) const;

bool is_collided(
const LaneChangePath & lane_change_path, const ExtendedPredictedObject & obj,
const std::vector<PoseWithVelocityStamped> & ego_predicted_path,
const RSSparams & selected_rss_param, const bool check_prepare_phase,
CollisionCheckDebugMap & debug_data) const;

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

double stop_time_{0.0};
static constexpr double floating_err_th{1e-3};
};
} // namespace autoware::behavior_path_planner
#endif // AUTOWARE__BEHAVIOR_PATH_LANE_CHANGE_MODULE__SCENE_HPP_
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ class LaneChangeBase

virtual void update_lanes(const bool is_approved) = 0;

virtual void update_filtered_objects() = 0;

virtual void updateLaneChangeStatus() = 0;

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

LaneChangeModuleType getModuleType() const { return type_; }

TurnSignalDecider getTurnSignalDecider() { return planner_data_->turn_signal_decider; }
TurnSignalDecider getTurnSignalDecider() const { return planner_data_->turn_signal_decider; }

Direction getDirection() const
{
Expand All @@ -227,7 +229,9 @@ class LaneChangeBase

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

virtual TurnSignalInfo get_current_turn_signal_info() = 0;
virtual TurnSignalInfo get_current_turn_signal_info() const = 0;

virtual bool is_near_regulatory_element() const = 0;

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

virtual bool getLaneChangePaths(
const lanelet::ConstLanelets & original_lanelets,
const lanelet::ConstLanelets & target_lanelets, Direction direction,
LaneChangePaths * candidate_paths, const utils::path_safety_checker::RSSparams rss_params,
const bool is_stuck, const bool check_safety) const = 0;

virtual bool isValidPath(const PathWithLaneId & path) const = 0;

virtual bool isAbleToStopSafely() const = 0;

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

virtual TurnSignalInfo get_terminal_turn_signal_info() const = 0;

TurnSignalInfo get_turn_signal(const Pose & start, const Pose & end) const
{
TurnSignalInfo turn_signal;
switch (direction_) {
case Direction::LEFT:
turn_signal.turn_signal.command = TurnIndicatorsCommand::ENABLE_LEFT;
break;
case Direction::RIGHT:
turn_signal.turn_signal.command = TurnIndicatorsCommand::ENABLE_RIGHT;
break;
default:
turn_signal.turn_signal.command = TurnIndicatorsCommand::NO_COMMAND;
break;
}

turn_signal.desired_start_point = start;
turn_signal.desired_end_point = end;
turn_signal.required_start_point = turn_signal.desired_start_point;
turn_signal.required_end_point = turn_signal.desired_end_point;

return turn_signal;
}

LaneChangeStatus status_{};
PathShifter path_shifter_{};

Expand All @@ -258,6 +281,7 @@ class LaneChangeBase
std::shared_ptr<LaneChangePath> abort_path_{};
std::shared_ptr<const PlannerData> planner_data_{};
lane_change::CommonDataPtr common_data_ptr_{};
FilteredByLanesExtendedObjects filtered_objects_{};
BehaviorModuleOutput prev_module_output_{};
std::optional<Pose> lane_change_stop_pose_{std::nullopt};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@

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

#include <autoware/route_handler/route_handler.hpp>

namespace autoware::behavior_path_planner::utils::lane_change::calculation
{
using autoware::route_handler::Direction;
using autoware::route_handler::RouteHandler;
using behavior_path_planner::lane_change::CommonDataPtr;
using behavior_path_planner::lane_change::LCParamPtr;

Expand Down Expand Up @@ -96,6 +100,21 @@ double calc_maximum_prepare_length(const CommonDataPtr & common_data_ptr);
double calc_ego_dist_to_lanes_start(
const CommonDataPtr & common_data_ptr, const lanelet::ConstLanelets & current_lanes,
const lanelet::ConstLanelets & target_lanes);

double calc_minimum_lane_change_length(
const LaneChangeParameters & lane_change_parameters, const std::vector<double> & shift_intervals);

double calc_minimum_lane_change_length(
const std::shared_ptr<RouteHandler> & route_handler, const lanelet::ConstLanelet & lane,
const LaneChangeParameters & lane_change_parameters, Direction direction);

double calc_maximum_lane_change_length(
const double current_velocity, const LaneChangeParameters & lane_change_parameters,
const std::vector<double> & shift_intervals, const double max_acc);

double calc_maximum_lane_change_length(
const CommonDataPtr & common_data_ptr, const lanelet::ConstLanelet & current_terminal_lanelet,
const double max_acc);
} // namespace autoware::behavior_path_planner::utils::lane_change::calculation

#endif // AUTOWARE__BEHAVIOR_PATH_LANE_CHANGE_MODULE__UTILS__CALCULATION_HPP_
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ struct CancelParameters
// number of unsafe exceeds unsafe_hysteresis_threshold, the lane change will be cancelled or
// aborted.
int unsafe_hysteresis_threshold{2};

int deceleration_sampling_num{5};
};

struct Parameters
Expand Down Expand Up @@ -131,7 +133,7 @@ struct Parameters
bool enable_collision_check_for_prepare_phase_in_general_lanes{false};
bool enable_collision_check_for_prepare_phase_in_intersection{true};
bool enable_collision_check_for_prepare_phase_in_turns{true};
double prepare_segment_ignore_object_velocity_thresh{0.1};
double stopped_object_velocity_threshold{0.1};
bool check_objects_on_current_lanes{true};
bool check_objects_on_other_lanes{true};
bool use_all_predicted_path{false};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,6 @@ using tier4_planning_msgs::msg::PathWithLaneId;
double calcLaneChangeResampleInterval(
const double lane_changing_length, const double lane_changing_velocity);

double calcMinimumLaneChangeLength(
const LaneChangeParameters & lane_change_parameters, const std::vector<double> & shift_intervals);

double calcMinimumLaneChangeLength(
const std::shared_ptr<RouteHandler> & route_handler, const lanelet::ConstLanelet & lane,
const LaneChangeParameters & lane_change_parameters, Direction direction);

double calcMaximumLaneChangeLength(
const double current_velocity, const LaneChangeParameters & lane_change_parameters,
const std::vector<double> & shift_intervals, const double max_acc);

double calcMinimumAcceleration(
const double current_velocity, const double min_longitudinal_acc,
const LaneChangeParameters & lane_change_parameters);
Expand Down Expand Up @@ -147,10 +136,9 @@ std::optional<lanelet::ConstLanelet> getLaneChangeTargetLane(
const RouteHandler & route_handler, const lanelet::ConstLanelets & current_lanes,
const LaneChangeModuleType type, const Direction & direction);

std::vector<PoseWithVelocityStamped> convertToPredictedPath(
const LaneChangePath & lane_change_path, const Twist & vehicle_twist, const Pose & pose,
const BehaviorPathPlannerParameters & common_parameters,
const LaneChangeParameters & lane_change_parameters, const double resolution);
std::vector<PoseWithVelocityStamped> convert_to_predicted_path(
const CommonDataPtr & common_data_ptr, const LaneChangePath & lane_change_path,
const double lane_changing_acceleration);

bool isParkedObject(
const PathWithLaneId & path, const RouteHandler & route_handler,
Expand Down Expand Up @@ -178,7 +166,7 @@ std::optional<lanelet::BasicPolygon2d> createPolygon(

ExtendedPredictedObject transform(
const PredictedObject & object, const BehaviorPathPlannerParameters & common_parameters,
const LaneChangeParameters & lane_change_parameters, const bool check_at_prepare_phase);
const LaneChangeParameters & lane_change_parameters);

bool isCollidedPolygonsInLanelet(
const std::vector<Polygon2d> & collided_polygons,
Expand Down Expand Up @@ -303,8 +291,11 @@ bool is_before_terminal(
double calc_angle_to_lanelet_segment(const lanelet::ConstLanelets & lanelets, const Pose & pose);

ExtendedPredictedObjects transform_to_extended_objects(
const CommonDataPtr & common_data_ptr, const std::vector<PredictedObject> & objects,
const bool check_prepare_phase);
const CommonDataPtr & common_data_ptr, const std::vector<PredictedObject> & objects);

double get_distance_to_next_regulatory_element(
const CommonDataPtr & common_data_ptr, const bool ignore_crosswalk = false,
const bool ignore_intersection = false);
} // namespace autoware::behavior_path_planner::utils::lane_change

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