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(avoidance): wait and see ambiguous stopped vehicle (#6631) #1200

Merged
merged 1 commit into from
Mar 20, 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 @@ -133,10 +133,13 @@ void AvoidanceByLaneChangeModuleManager::init(rclcpp::Node * node)

{
const std::string ns = "avoidance.target_filtering.avoidance_for_ambiguous_vehicle.";
p.enable_force_avoidance_for_stopped_vehicle =
getOrDeclareParameter<bool>(*node, ns + "enable");
p.threshold_time_force_avoidance_for_stopped_vehicle =
getOrDeclareParameter<double>(*node, ns + "time_threshold");
p.enable_avoidance_for_ambiguous_vehicle = getOrDeclareParameter<bool>(*node, ns + "enable");
p.closest_distance_to_wait_and_see_for_ambiguous_vehicle =
getOrDeclareParameter<double>(*node, ns + "closest_distance_to_wait_and_see");
p.time_threshold_for_ambiguous_vehicle =
getOrDeclareParameter<double>(*node, ns + "condition.time_threshold");
p.distance_threshold_for_ambiguous_vehicle =
getOrDeclareParameter<double>(*node, ns + "condition.distance_threshold");
p.object_ignore_section_traffic_light_in_front_distance =
getOrDeclareParameter<double>(*node, ns + "ignore_area.traffic_light.front_distance");
p.object_ignore_section_crosswalk_in_front_distance =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,10 @@
# params for avoidance of vehicle type objects that are ambiguous as to whether they are parked.
avoidance_for_ambiguous_vehicle:
enable: false # [-]
time_threshold: 1.0 # [s]
distance_threshold: 1.0 # [m]
closest_distance_to_wait_and_see: 10.0 # [m]
condition:
time_threshold: 1.0 # [s]
distance_threshold: 1.0 # [m]
ignore_area:
traffic_light:
front_distance: 100.0 # [m]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ struct AvoidanceParameters
bool enable_cancel_maneuver{false};

// enable avoidance for all parking vehicle
bool enable_force_avoidance_for_stopped_vehicle{false};
bool enable_avoidance_for_ambiguous_vehicle{false};

// enable yield maneuver.
bool enable_yield_maneuver{false};
Expand Down Expand Up @@ -184,8 +184,9 @@ struct AvoidanceParameters
double object_check_min_road_shoulder_width{0.0};

// force avoidance
double threshold_time_force_avoidance_for_stopped_vehicle{0.0};
double force_avoidance_distance_threshold{0.0};
double closest_distance_to_wait_and_see_for_ambiguous_vehicle{0.0};
double time_threshold_for_ambiguous_vehicle{0.0};
double distance_threshold_for_ambiguous_vehicle{0.0};

// when complete avoidance motion, there is a distance margin with the object
// for longitudinal direction
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,35 @@ class AvoidanceHelper
});
}

bool isReady(const ObjectDataArray & objects) const
{
if (objects.empty()) {
return true;
}

const auto object = objects.front();

if (!object.is_ambiguous) {
return true;
}

if (!object.avoid_margin.has_value()) {
return true;
}

const auto is_object_on_right = utils::avoidance::isOnRight(object);
const auto desire_shift_length =
getShiftLength(object, is_object_on_right, object.avoid_margin.value());

const auto prepare_distance = getMinimumPrepareDistance();
const auto constant_distance = getFrontConstantDistance(object);
const auto avoidance_distance = getMinAvoidanceDistance(desire_shift_length);

return object.longitudinal <
prepare_distance + constant_distance + avoidance_distance +
parameters_->closest_distance_to_wait_and_see_for_ambiguous_vehicle;
}

bool isReady(const AvoidLineArray & new_shift_lines, const double current_shift_length) const
{
if (std::abs(current_shift_length) < 1e-3) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,13 @@ AvoidanceParameters getParameter(rclcpp::Node * node)

{
const std::string ns = "avoidance.target_filtering.avoidance_for_ambiguous_vehicle.";
p.enable_force_avoidance_for_stopped_vehicle =
getOrDeclareParameter<bool>(*node, ns + "enable");
p.threshold_time_force_avoidance_for_stopped_vehicle =
getOrDeclareParameter<double>(*node, ns + "time_threshold");
p.force_avoidance_distance_threshold =
getOrDeclareParameter<double>(*node, ns + "distance_threshold");
p.enable_avoidance_for_ambiguous_vehicle = getOrDeclareParameter<bool>(*node, ns + "enable");
p.closest_distance_to_wait_and_see_for_ambiguous_vehicle =
getOrDeclareParameter<double>(*node, ns + "closest_distance_to_wait_and_see");
p.time_threshold_for_ambiguous_vehicle =
getOrDeclareParameter<double>(*node, ns + "condition.time_threshold");
p.distance_threshold_for_ambiguous_vehicle =
getOrDeclareParameter<double>(*node, ns + "condition.distance_threshold");
p.object_ignore_section_traffic_light_in_front_distance =
getOrDeclareParameter<double>(*node, ns + "ignore_area.traffic_light.front_distance");
p.object_ignore_section_crosswalk_in_front_distance =
Expand Down
2 changes: 2 additions & 0 deletions planning/behavior_path_avoidance_module/src/debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,8 @@ MarkerArray createDebugMarkerArray(
addObjects(data.other_objects, std::string("ParallelToEgoLane"));
addObjects(data.other_objects, std::string("MergingToEgoLane"));
addObjects(data.other_objects, std::string("UnstableObject"));
addObjects(data.other_objects, std::string("AmbiguousStoppedVehicle"));
addObjects(data.other_objects, std::string("AmbiguousStoppedVehicle(wait-and-see)"));
}

// shift line pre-process
Expand Down
3 changes: 2 additions & 1 deletion planning/behavior_path_avoidance_module/src/scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,8 @@ void AvoidanceModule::fillShiftLine(AvoidancePlanningData & data, DebugData & de
*/
data.comfortable = helper_->isComfortable(data.new_shift_line);
data.safe = isSafePath(data.candidate_path, debug);
data.ready = helper_->isReady(data.new_shift_line, path_shifter_.getLastShiftLength());
data.ready = helper_->isReady(data.new_shift_line, path_shifter_.getLastShiftLength()) &&
helper_->isReady(data.target_objects);
}

void AvoidanceModule::fillEgoStatus(
Expand Down
198 changes: 131 additions & 67 deletions planning/behavior_path_avoidance_module/src/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,8 @@ bool isMergingToEgoLane(const ObjectData & object)
}

bool isParkedVehicle(
ObjectData & object, const std::shared_ptr<RouteHandler> & route_handler,
ObjectData & object, const AvoidancePlanningData & data,
const std::shared_ptr<RouteHandler> & route_handler,
const std::shared_ptr<AvoidanceParameters> & parameters)
{
using lanelet::geometry::distance2d;
Expand Down Expand Up @@ -588,57 +589,36 @@ bool isParkedVehicle(
object.shiftable_ratio > parameters->object_check_shiftable_ratio;
}

return is_left_side_parked_vehicle || is_right_side_parked_vehicle;
}

bool isAmbiguousStoppedVehicle(
ObjectData & object, const AvoidancePlanningData & data,
const std::shared_ptr<const PlannerData> & planner_data,
const std::shared_ptr<AvoidanceParameters> & parameters)
{
const auto stop_time_longer_than_threshold =
object.stop_time > parameters->threshold_time_force_avoidance_for_stopped_vehicle;

if (!stop_time_longer_than_threshold) {
if (!is_left_side_parked_vehicle && !is_right_side_parked_vehicle) {
return false;
}

const auto & object_pose = object.object.kinematics.initial_pose_with_covariance.pose;
const auto is_moving_distance_longer_than_threshold =
tier4_autoware_utils::calcDistance2d(object.init_pose, object_pose) >
parameters->force_avoidance_distance_threshold;

if (is_moving_distance_longer_than_threshold) {
return false;
}

if (object.is_within_intersection) {
RCLCPP_DEBUG(rclcpp::get_logger(__func__), "object is in the intersection area.");
return false;
}

const auto rh = planner_data->route_handler;

if (
!!rh->getRoutingGraphPtr()->right(object.overhang_lanelet) &&
!!rh->getRoutingGraphPtr()->left(object.overhang_lanelet)) {
RCLCPP_DEBUG(rclcpp::get_logger(__func__), "object isn't on the edge lane.");
object.to_centerline =
lanelet::utils::getArcCoordinates(data.current_lanelets, object_pose).distance;
if (std::abs(object.to_centerline) < parameters->threshold_distance_object_is_on_center) {
return false;
}

if (!object.is_on_ego_lane) {
return true;
}
return true;
}

bool isCloseToStopFactor(
ObjectData & object, const AvoidancePlanningData & data,
const std::shared_ptr<const PlannerData> & planner_data,
const std::shared_ptr<AvoidanceParameters> & parameters)
{
const auto & rh = planner_data->route_handler;
const auto & ego_pose = planner_data->self_odometry->pose.pose;
const auto & object_pose = object.object.kinematics.initial_pose_with_covariance.pose;

// force avoidance for stopped vehicle
bool not_parked_object = true;
bool is_close_to_stop_factor = false;

// check traffic light
const auto to_traffic_light = getDistanceToNextTrafficLight(object_pose, data.extend_lanelets);
{
not_parked_object =
is_close_to_stop_factor =
to_traffic_light < parameters->object_ignore_section_traffic_light_in_front_distance;
}

Expand All @@ -650,12 +630,89 @@ bool isAmbiguousStoppedVehicle(
const auto stop_for_crosswalk =
to_crosswalk < parameters->object_ignore_section_crosswalk_in_front_distance &&
to_crosswalk > -1.0 * parameters->object_ignore_section_crosswalk_behind_distance;
not_parked_object = not_parked_object || stop_for_crosswalk;
is_close_to_stop_factor = is_close_to_stop_factor || stop_for_crosswalk;
}

object.to_stop_factor_distance = std::min(to_traffic_light, to_crosswalk);

return !not_parked_object;
return is_close_to_stop_factor;
}

bool isNeverAvoidanceTarget(
ObjectData & object, const AvoidancePlanningData & data,
const std::shared_ptr<const PlannerData> & planner_data,
const std::shared_ptr<AvoidanceParameters> & parameters)
{
const auto & object_pose = object.object.kinematics.initial_pose_with_covariance.pose;
const auto is_moving_distance_longer_than_threshold =
tier4_autoware_utils::calcDistance2d(object.init_pose, object_pose) >
parameters->distance_threshold_for_ambiguous_vehicle;
if (is_moving_distance_longer_than_threshold) {
object.reason = AvoidanceDebugFactor::MOVING_OBJECT;
return true;
}

if (object.is_within_intersection) {
if (object.behavior == ObjectData::Behavior::NONE) {
object.reason = "ParallelToEgoLane";
RCLCPP_DEBUG(rclcpp::get_logger(__func__), "object belongs to ego lane. never avoid it.");
return true;
}

if (object.behavior == ObjectData::Behavior::MERGING) {
object.reason = "MergingToEgoLane";
RCLCPP_DEBUG(rclcpp::get_logger(__func__), "object belongs to ego lane. never avoid it.");
return true;
}
}

if (object.is_on_ego_lane) {
if (
planner_data->route_handler->getRightLanelet(object.overhang_lanelet).has_value() &&
planner_data->route_handler->getLeftLanelet(object.overhang_lanelet).has_value()) {
object.reason = AvoidanceDebugFactor::NOT_PARKING_OBJECT;
RCLCPP_DEBUG(rclcpp::get_logger(__func__), "object isn't on the edge lane. never avoid it.");
return true;
}
}

if (isCloseToStopFactor(object, data, planner_data, parameters)) {
if (object.is_on_ego_lane && !object.is_parked) {
object.reason = AvoidanceDebugFactor::NOT_PARKING_OBJECT;
RCLCPP_DEBUG(rclcpp::get_logger(__func__), "object is close to stop factor. never avoid it.");
return true;
}
}

return false;
}

bool isObviousAvoidanceTarget(
ObjectData & object, [[maybe_unused]] const AvoidancePlanningData & data,
[[maybe_unused]] const std::shared_ptr<const PlannerData> & planner_data,
[[maybe_unused]] const std::shared_ptr<AvoidanceParameters> & parameters)
{
if (!object.is_within_intersection) {
if (object.is_parked && object.behavior == ObjectData::Behavior::NONE) {
RCLCPP_DEBUG(rclcpp::get_logger(__func__), "object is obvious parked vehicle.");
return true;
}

if (!object.is_on_ego_lane && object.behavior == ObjectData::Behavior::NONE) {
RCLCPP_DEBUG(rclcpp::get_logger(__func__), "object is adjacent vehicle.");
return true;
}
}

if (!object.is_parked) {
object.reason = AvoidanceDebugFactor::NOT_PARKING_OBJECT;
}

if (object.behavior == ObjectData::Behavior::MERGING) {
object.reason = "MergingToEgoLane";
}

return false;
}

bool isSatisfiedWithCommonCondition(
Expand Down Expand Up @@ -758,50 +815,56 @@ bool isSatisfiedWithVehicleCondition(
{
object.behavior = getObjectBehavior(object, parameters);
object.is_on_ego_lane = isOnEgoLane(object);
object.is_ambiguous = isAmbiguousStoppedVehicle(object, data, planner_data, parameters);

// from here condition check for vehicle type objects.
if (object.is_ambiguous && parameters->enable_force_avoidance_for_stopped_vehicle) {
if (isNeverAvoidanceTarget(object, data, planner_data, parameters)) {
return false;
}

if (isObviousAvoidanceTarget(object, data, planner_data, parameters)) {
return true;
}

// check vehicle shift ratio
if (object.is_on_ego_lane) {
if (object.is_parked) {
return true;
} else {
object.reason = AvoidanceDebugFactor::NOT_PARKING_OBJECT;
return false;
}
// from here, filtering for ambiguous vehicle.

if (!parameters->enable_avoidance_for_ambiguous_vehicle) {
object.reason = "AmbiguousStoppedVehicle";
return false;
}

// Object is on center line -> ignore.
const auto & object_pose = object.object.kinematics.initial_pose_with_covariance.pose;
object.to_centerline =
lanelet::utils::getArcCoordinates(data.current_lanelets, object_pose).distance;
if (std::abs(object.to_centerline) < parameters->threshold_distance_object_is_on_center) {
object.reason = AvoidanceDebugFactor::TOO_NEAR_TO_CENTERLINE;
const auto stop_time_longer_than_threshold =
object.stop_time > parameters->time_threshold_for_ambiguous_vehicle;
if (!stop_time_longer_than_threshold) {
object.reason = "AmbiguousStoppedVehicle(wait-and-see)";
return false;
}

if (object.is_within_intersection) {
std::string turn_direction = object.overhang_lanelet.attributeOr("turn_direction", "else");
if (turn_direction == "straight") {
if (object.behavior == ObjectData::Behavior::DEVIATING) {
object.reason = "AmbiguousStoppedVehicle(wait-and-see)";
object.is_ambiguous = true;
return true;
}
} else {
if (object.behavior == ObjectData::Behavior::MERGING) {
object.reason = "AmbiguousStoppedVehicle(wait-and-see)";
object.is_ambiguous = true;
return true;
}

if (object.behavior == ObjectData::Behavior::NONE) {
object.reason = "ParallelToEgoLane";
return false;
if (object.behavior == ObjectData::Behavior::DEVIATING) {
object.reason = "AmbiguousStoppedVehicle(wait-and-see)";
object.is_ambiguous = true;
return true;
}
}

if (object.behavior == ObjectData::Behavior::MERGING) {
object.reason = "MergingToEgoLane";
return false;
if (object.behavior == ObjectData::Behavior::NONE) {
object.is_ambiguous = false;
return true;
}
}

return true;
object.reason = AvoidanceDebugFactor::NOT_PARKING_OBJECT;
return false;
}

bool isNoNeedAvoidanceBehavior(
Expand Down Expand Up @@ -1728,7 +1791,8 @@ void filterTargetObjects(
if (filtering_utils::isVehicleTypeObject(o)) {
o.is_within_intersection =
filtering_utils::isWithinIntersection(o, planner_data->route_handler);
o.is_parked = filtering_utils::isParkedVehicle(o, planner_data->route_handler, parameters);
o.is_parked =
filtering_utils::isParkedVehicle(o, data, planner_data->route_handler, parameters);
o.avoid_margin = filtering_utils::getAvoidMargin(o, planner_data, parameters);

if (filtering_utils::isNoNeedAvoidanceBehavior(o, parameters)) {
Expand Down
Loading