@@ -437,10 +437,27 @@ bool AvoidanceModule::canYieldManeuver(const AvoidancePlanningData & data) const
437
437
{
438
438
// transit yield maneuver only when the avoidance maneuver is not initiated.
439
439
if (helper_.isShifted ()) {
440
+ RCLCPP_DEBUG (getLogger (), " avoidance maneuver already initiated." );
440
441
return false ;
441
442
}
442
443
444
+ // prevent sudden steering.
445
+ const auto registered_lines = path_shifter_.getShiftLines ();
446
+ if (!registered_lines.empty ()) {
447
+ const size_t idx = planner_data_->findEgoIndex (path_shifter_.getReferencePath ().points );
448
+ const auto to_shift_start_point = calcSignedArcLength (
449
+ path_shifter_.getReferencePath ().points , idx, registered_lines.front ().start_idx );
450
+ if (to_shift_start_point < helper_.getMinimumPrepareDistance ()) {
451
+ RCLCPP_DEBUG (
452
+ getLogger (),
453
+ " Distance to shift start point is less than minimum prepare distance. The distance is not "
454
+ " enough." );
455
+ return false ;
456
+ }
457
+ }
458
+
443
459
if (!data.stop_target_object ) {
460
+ RCLCPP_DEBUG (getLogger (), " can pass by the object safely without avoidance maneuver." );
444
461
return true ;
445
462
}
446
463
@@ -920,8 +937,9 @@ AvoidOutlines AvoidanceModule::generateAvoidOutline(
920
937
const auto & base_link2rear = planner_data_->parameters .base_link2rear ;
921
938
922
939
// Calculate feasible shift length
923
- const auto get_shift_length =
924
- [&](auto & object, const auto & desire_shift_length) -> boost::optional<double > {
940
+ const auto get_shift_profile =
941
+ [&](
942
+ auto & object, const auto & desire_shift_length) -> std::optional<std::pair<double , double >> {
925
943
// use each object param
926
944
const auto object_type = utils::getHighestProbLabel (object.object .classification );
927
945
const auto object_parameter = parameters_->object_parameters .at (object_type);
@@ -931,55 +949,57 @@ AvoidOutlines AvoidanceModule::generateAvoidOutline(
931
949
const auto avoiding_shift = desire_shift_length - current_ego_shift;
932
950
const auto nominal_avoid_distance = helper_.getMaxAvoidanceDistance (avoiding_shift);
933
951
952
+ // calculate remaining distance.
953
+ const auto prepare_distance = helper_.getNominalPrepareDistance ();
954
+ const auto & additional_buffer_longitudinal =
955
+ object_parameter.use_conservative_buffer_longitudinal
956
+ ? planner_data_->parameters .base_link2front
957
+ : 0.0 ;
958
+ const auto constant = object_parameter.safety_buffer_longitudinal +
959
+ additional_buffer_longitudinal + prepare_distance;
960
+ const auto has_enough_distance = object.longitudinal > constant + nominal_avoid_distance;
961
+ const auto remaining_distance = object.longitudinal - constant;
962
+ const auto avoidance_distance =
963
+ has_enough_distance ? nominal_avoid_distance : remaining_distance;
964
+
965
+ // nominal case. avoidable.
966
+ if (has_enough_distance) {
967
+ return std::make_pair (desire_shift_length, avoidance_distance);
968
+ }
969
+
934
970
if (!isBestEffort (parameters_->policy_lateral_margin )) {
935
- return desire_shift_length;
971
+ return std::make_pair ( desire_shift_length, avoidance_distance) ;
936
972
}
937
973
938
974
// ego already has enough positive shift.
939
975
const auto has_enough_positive_shift = avoiding_shift < -1e-3 && desire_shift_length > 1e-3 ;
940
976
if (is_object_on_right && has_enough_positive_shift) {
941
- return desire_shift_length;
977
+ return std::make_pair ( desire_shift_length, avoidance_distance) ;
942
978
}
943
979
944
980
// ego already has enough negative shift.
945
981
const auto has_enough_negative_shift = avoiding_shift > 1e-3 && desire_shift_length < -1e-3 ;
946
982
if (!is_object_on_right && has_enough_negative_shift) {
947
- return desire_shift_length;
983
+ return std::make_pair ( desire_shift_length, avoidance_distance) ;
948
984
}
949
985
950
986
// don't relax shift length since it can stop in front of the object.
951
987
if (object.is_stoppable && !parameters_->use_shorten_margin_immediately ) {
952
- return desire_shift_length;
988
+ return std::make_pair ( desire_shift_length, avoidance_distance) ;
953
989
}
954
990
955
- // calculate remaining distance.
956
- const auto prepare_distance = helper_.getNominalPrepareDistance ();
957
- const auto & additional_buffer_longitudinal =
958
- object_parameter.use_conservative_buffer_longitudinal
959
- ? planner_data_->parameters .base_link2front
960
- : 0.0 ;
961
- const auto constant = object_parameter.safety_buffer_longitudinal +
962
- additional_buffer_longitudinal + prepare_distance;
963
- const auto has_enough_distance = object.longitudinal > constant + nominal_avoid_distance;
964
- const auto remaining_distance = object.longitudinal - constant;
965
-
966
991
// the avoidance path is already approved
967
992
const auto & object_pos = object.object .kinematics .initial_pose_with_covariance .pose .position ;
968
993
const auto is_approved = (helper_.getShift (object_pos) > 0.0 && is_object_on_right) ||
969
994
(helper_.getShift (object_pos) < 0.0 && !is_object_on_right);
970
995
if (is_approved) {
971
- return desire_shift_length;
996
+ return std::make_pair ( desire_shift_length, avoidance_distance) ;
972
997
}
973
998
974
999
// prepare distance is not enough. unavoidable.
975
1000
if (remaining_distance < 1e-3 ) {
976
1001
object.reason = AvoidanceDebugFactor::REMAINING_DISTANCE_LESS_THAN_ZERO;
977
- return boost::none;
978
- }
979
-
980
- // nominal case. avoidable.
981
- if (has_enough_distance) {
982
- return desire_shift_length;
1002
+ return std::nullopt;
983
1003
}
984
1004
985
1005
// calculate lateral jerk.
@@ -988,13 +1008,13 @@ AvoidOutlines AvoidanceModule::generateAvoidOutline(
988
1008
989
1009
// relax lateral jerk limit. avoidable.
990
1010
if (required_jerk < helper_.getLateralMaxJerkLimit ()) {
991
- return desire_shift_length;
1011
+ return std::make_pair ( desire_shift_length, avoidance_distance) ;
992
1012
}
993
1013
994
1014
// avoidance distance is not enough. unavoidable.
995
1015
if (!isBestEffort (parameters_->policy_deceleration )) {
996
1016
object.reason = AvoidanceDebugFactor::TOO_LARGE_JERK;
997
- return boost::none ;
1017
+ return std::nullopt ;
998
1018
}
999
1019
1000
1020
// output avoidance path under lateral jerk constraints.
@@ -1003,7 +1023,7 @@ AvoidOutlines AvoidanceModule::generateAvoidOutline(
1003
1023
1004
1024
if (std::abs (feasible_relative_shift_length) < parameters_->lateral_execution_threshold ) {
1005
1025
object.reason = " LessThanExecutionThreshold" ;
1006
- return boost::none ;
1026
+ return std::nullopt ;
1007
1027
}
1008
1028
1009
1029
const auto feasible_shift_length =
@@ -1017,7 +1037,7 @@ AvoidOutlines AvoidanceModule::generateAvoidOutline(
1017
1037
RCLCPP_WARN_THROTTLE (
1018
1038
getLogger (), *clock_, 1000 , " feasible shift length is not enough to avoid. " );
1019
1039
object.reason = AvoidanceDebugFactor::TOO_LARGE_JERK;
1020
- return boost::none ;
1040
+ return std::nullopt ;
1021
1041
}
1022
1042
1023
1043
{
@@ -1026,7 +1046,7 @@ AvoidOutlines AvoidanceModule::generateAvoidOutline(
1026
1046
std::abs (avoiding_shift), feasible_relative_shift_length);
1027
1047
}
1028
1048
1029
- return feasible_shift_length;
1049
+ return std::make_pair ( feasible_shift_length, avoidance_distance) ;
1030
1050
};
1031
1051
1032
1052
const auto is_forward_object = [](const auto & object) { return object.longitudinal > 0.0 ; };
@@ -1061,9 +1081,9 @@ AvoidOutlines AvoidanceModule::generateAvoidOutline(
1061
1081
// use each object param
1062
1082
const auto object_type = utils::getHighestProbLabel (o.object .classification );
1063
1083
const auto object_parameter = parameters_->object_parameters .at (object_type);
1064
- const auto feasible_shift_length = get_shift_length (o, desire_shift_length);
1084
+ const auto feasible_shift_profile = get_shift_profile (o, desire_shift_length);
1065
1085
1066
- if (!feasible_shift_length ) {
1086
+ if (!feasible_shift_profile. has_value () ) {
1067
1087
if (o.avoid_required && is_forward_object (o)) {
1068
1088
break ;
1069
1089
} else {
@@ -1072,10 +1092,8 @@ AvoidOutlines AvoidanceModule::generateAvoidOutline(
1072
1092
}
1073
1093
1074
1094
// use absolute dist for return-to-center, relative dist from current for avoiding.
1075
- const auto feasible_avoid_distance =
1076
- helper_.getMaxAvoidanceDistance (feasible_shift_length.get () - current_ego_shift);
1077
1095
const auto feasible_return_distance =
1078
- helper_.getMaxAvoidanceDistance (feasible_shift_length. get () );
1096
+ helper_.getMaxAvoidanceDistance (feasible_shift_profile. value (). first );
1079
1097
1080
1098
AvoidLine al_avoid;
1081
1099
{
@@ -1091,14 +1109,15 @@ AvoidOutlines AvoidanceModule::generateAvoidOutline(
1091
1109
1092
1110
// start point (use previous linear shift length as start shift length.)
1093
1111
al_avoid.start_longitudinal = [&]() {
1094
- const auto nearest_avoid_distance = std::max (to_shift_end - feasible_avoid_distance, 1e-3 );
1112
+ const auto nearest_avoid_distance =
1113
+ std::max (to_shift_end - feasible_shift_profile.value ().second , 1e-3 );
1095
1114
1096
1115
if (data.to_start_point > to_shift_end) {
1097
1116
return nearest_avoid_distance;
1098
1117
}
1099
1118
1100
1119
const auto minimum_avoid_distance =
1101
- helper_.getMinAvoidanceDistance (feasible_shift_length. get () - current_ego_shift);
1120
+ helper_.getMinAvoidanceDistance (feasible_shift_profile. value (). first - current_ego_shift);
1102
1121
const auto furthest_avoid_distance = std::max (to_shift_end - minimum_avoid_distance, 1e-3 );
1103
1122
1104
1123
return std::clamp (data.to_start_point , nearest_avoid_distance, furthest_avoid_distance);
@@ -1110,7 +1129,7 @@ AvoidOutlines AvoidanceModule::generateAvoidOutline(
1110
1129
al_avoid.start_shift_length = helper_.getLinearShift (al_avoid.start .position );
1111
1130
1112
1131
// end point
1113
- al_avoid.end_shift_length = feasible_shift_length. get () ;
1132
+ al_avoid.end_shift_length = feasible_shift_profile. value (). first ;
1114
1133
al_avoid.end_longitudinal = to_shift_end;
1115
1134
1116
1135
// misc
@@ -1125,7 +1144,7 @@ AvoidOutlines AvoidanceModule::generateAvoidOutline(
1125
1144
const auto to_shift_start = o.longitudinal + offset;
1126
1145
1127
1146
// start point
1128
- al_return.start_shift_length = feasible_shift_length. get () ;
1147
+ al_return.start_shift_length = feasible_shift_profile. value (). first ;
1129
1148
al_return.start_longitudinal = to_shift_start;
1130
1149
1131
1150
// end point
@@ -1652,6 +1671,10 @@ void AvoidanceModule::applySmallShiftFilter(
1652
1671
continue ;
1653
1672
}
1654
1673
1674
+ if (s.start_longitudinal < helper_.getMinimumPrepareDistance ()) {
1675
+ continue ;
1676
+ }
1677
+
1655
1678
shift_lines.push_back (s);
1656
1679
}
1657
1680
}
@@ -2405,9 +2428,8 @@ AvoidLineArray AvoidanceModule::findNewShiftLine(
2405
2428
for (size_t i = 0 ; i < shift_lines.size (); ++i) {
2406
2429
const auto & candidate = shift_lines.at (i);
2407
2430
2408
- // new shift points must exist in front of Ego
2409
- // this value should be larger than -eps consider path shifter calculation error.
2410
- if (candidate.start_idx < avoid_data_.ego_closest_path_index ) {
2431
+ // prevent sudden steering.
2432
+ if (candidate.start_longitudinal < helper_.getMinimumPrepareDistance ()) {
2411
2433
break ;
2412
2434
}
2413
2435
0 commit comments