@@ -1041,7 +1041,8 @@ IntersectionModule::DecisionResult IntersectionModule::modifyPathVelocityDetail(
1041
1041
const auto default_stopline_idx_opt = intersection_stoplines.default_stopline ;
1042
1042
const auto first_attention_stopline_idx_opt = intersection_stoplines.first_attention_stopline ;
1043
1043
const auto occlusion_peeking_stopline_idx_opt = intersection_stoplines.occlusion_peeking_stopline ;
1044
- const auto default_pass_judge_line_idx = intersection_stoplines.first_pass_judge_line ;
1044
+ const auto first_pass_judge_line_idx = intersection_stoplines.first_pass_judge_line ;
1045
+ const auto second_pass_judge_line_idx = intersection_stoplines.second_pass_judge_line ;
1045
1046
const auto occlusion_wo_tl_pass_judge_line_idx =
1046
1047
intersection_stoplines.occlusion_wo_tl_pass_judge_line ;
1047
1048
@@ -1221,44 +1222,76 @@ IntersectionModule::DecisionResult IntersectionModule::modifyPathVelocityDetail(
1221
1222
prev_occlusion_status_ = occlusion_status;
1222
1223
}
1223
1224
1224
- // TODO(Mamoru Sobue): this part needs more formal handling
1225
- const size_t pass_judge_line_idx = [=]() {
1225
+ const size_t pass_judge_line_idx = [&]() {
1226
1226
if (enable_occlusion_detection_) {
1227
- // if occlusion detection is enabled, pass_judge position is beyond the boundary of first
1228
- // attention area
1229
1227
if (has_traffic_light_) {
1230
- return occlusion_stopline_idx;
1228
+ // if ego passed the first_pass_judge_line while it is peeking to occlusion, then its
1229
+ // position is occlusion_stopline_idx. Otherwise it is first_pass_judge_line
1230
+ if (passed_1st_judge_line_while_peeking_) {
1231
+ return occlusion_stopline_idx;
1232
+ }
1233
+ const bool is_over_first_pass_judge_line =
1234
+ util::isOverTargetIndex (*path, closest_idx, current_pose, first_pass_judge_line_idx);
1235
+ if (is_occlusion_state && is_over_first_pass_judge_line) {
1236
+ passed_1st_judge_line_while_peeking_ = true ;
1237
+ return occlusion_stopline_idx;
1238
+ } else {
1239
+ return first_pass_judge_line_idx;
1240
+ }
1231
1241
} else if (is_occlusion_state) {
1232
1242
// if there is no traffic light and occlusion is detected, pass_judge position is beyond
1233
1243
// the boundary of first attention area
1234
1244
return occlusion_wo_tl_pass_judge_line_idx;
1235
1245
} else {
1236
1246
// if there is no traffic light and occlusion is not detected, pass_judge position is
1237
1247
// default
1238
- return default_pass_judge_line_idx ;
1248
+ return first_pass_judge_line_idx ;
1239
1249
}
1240
1250
}
1241
- return default_pass_judge_line_idx ;
1251
+ return first_pass_judge_line_idx ;
1242
1252
}();
1243
- debug_data_.pass_judge_wall_pose =
1244
- planning_utils::getAheadPose (pass_judge_line_idx, baselink2front, *path);
1245
- const bool is_over_pass_judge_line =
1246
- util::isOverTargetIndex (*path, closest_idx, current_pose, pass_judge_line_idx);
1247
- const double vel_norm = std::hypot (
1248
- planner_data_->current_velocity ->twist .linear .x ,
1249
- planner_data_->current_velocity ->twist .linear .y );
1250
- const bool keep_detection =
1251
- (vel_norm < planner_param_.collision_detection .keep_detection_velocity_threshold );
1253
+
1252
1254
const bool was_safe = std::holds_alternative<IntersectionModule::Safe>(prev_decision_result_);
1253
- // if ego is over the pass judge line and not stopped
1254
- if (is_over_default_stopline && !is_over_pass_judge_line && keep_detection) {
1255
- RCLCPP_DEBUG (logger_, " is_over_default_stopline && !is_over_pass_judge_line && keep_detection" );
1256
- // do nothing
1257
- } else if (
1258
- (was_safe && is_over_default_stopline && is_over_pass_judge_line && is_go_out_) ||
1255
+
1256
+ const bool is_over_1st_pass_judge_line =
1257
+ util::isOverTargetIndex (*path, closest_idx, current_pose, pass_judge_line_idx);
1258
+ if (is_over_1st_pass_judge_line && was_safe && !safely_passed_1st_judge_line_time_) {
1259
+ safely_passed_1st_judge_line_time_ = clock_->now ();
1260
+ }
1261
+ debug_data_.first_pass_judge_wall_pose =
1262
+ planning_utils::getAheadPose (pass_judge_line_idx, baselink2front, *path);
1263
+ debug_data_.passed_first_pass_judge = safely_passed_1st_judge_line_time_.has_value ();
1264
+ const bool is_over_2nd_pass_judge_line =
1265
+ util::isOverTargetIndex (*path, closest_idx, current_pose, second_pass_judge_line_idx);
1266
+ if (is_over_2nd_pass_judge_line && was_safe && !safely_passed_2nd_judge_line_time_) {
1267
+ safely_passed_2nd_judge_line_time_ = clock_->now ();
1268
+ }
1269
+ debug_data_.second_pass_judge_wall_pose =
1270
+ planning_utils::getAheadPose (second_pass_judge_line_idx, baselink2front, *path);
1271
+ debug_data_.passed_second_pass_judge = safely_passed_2nd_judge_line_time_.has_value ();
1272
+
1273
+ if (
1274
+ ((is_over_default_stopline ||
1275
+ planner_param_.common .enable_pass_judge_before_default_stopline ) &&
1276
+ is_over_2nd_pass_judge_line && was_safe) ||
1259
1277
is_permanent_go_) {
1260
- // is_go_out_: previous RTC approval
1261
- // activated_: current RTC approval
1278
+ /*
1279
+ * This body is active if ego is
1280
+ * - over the default stopline AND
1281
+ * - over the 1st && 2nd pass judge line AND
1282
+ * - previously safe
1283
+ * ,
1284
+ * which means ego can stop even if it is over the 1st pass judge line but
1285
+ * - before default stopline OR
1286
+ * - before the 2nd pass judge line OR
1287
+ * - or previously unsafe
1288
+ * .
1289
+ * In order for ego to continue peeking or collision detection when occlusion is detected after
1290
+ * ego passed the 1st pass judge line, it needs to be
1291
+ * - before the default stopline OR
1292
+ * - before the 2nd pass judge line OR
1293
+ * - previously unsafe
1294
+ */
1262
1295
is_permanent_go_ = true ;
1263
1296
return IntersectionModule::Indecisive{" over the pass judge line. no plan needed" };
1264
1297
}
@@ -1309,10 +1342,14 @@ IntersectionModule::DecisionResult IntersectionModule::modifyPathVelocityDetail(
1309
1342
: (planner_param_.collision_detection .collision_detection_hold_time -
1310
1343
collision_state_machine_.getDuration ());
1311
1344
1345
+ // TODO(Mamoru Sobue): if ego is over 1st/2nd pass judge line and collision is expected at 1st/2nd
1346
+ // pass judge line respectively, ego should go
1347
+ const auto second_attention_stopline_idx = intersection_stoplines.second_attention_stopline ;
1348
+ const auto last_intersection_stopline_candidate_idx =
1349
+ second_attention_stopline_idx ? second_attention_stopline_idx.value () : occlusion_stopline_idx;
1312
1350
const bool has_collision = checkCollision (
1313
- *path, &target_objects, path_lanelets, closest_idx,
1314
- std::min<size_t >(occlusion_stopline_idx, path->points .size () - 1 ), time_to_restart,
1315
- traffic_prioritized_level);
1351
+ *path, &target_objects, path_lanelets, closest_idx, last_intersection_stopline_candidate_idx,
1352
+ time_to_restart, traffic_prioritized_level);
1316
1353
collision_state_machine_.setStateWithMarginTime (
1317
1354
has_collision ? StateMachine::State::STOP : StateMachine::State::GO,
1318
1355
logger_.get_child (" collision state_machine" ), *clock_);
@@ -1808,16 +1845,19 @@ std::optional<IntersectionStopLines> IntersectionModule::generateIntersectionSto
1808
1845
second_attention_area, interpolated_path_info, local_footprint, baselink2front);
1809
1846
if (first_footprint_inside_2nd_attention_ip_opt) {
1810
1847
second_attention_stopline_ip_int = first_footprint_inside_2nd_attention_ip_opt.value ();
1848
+ second_attention_stopline_valid = true ;
1811
1849
}
1812
1850
}
1813
1851
const auto second_attention_stopline_ip =
1814
1852
second_attention_stopline_ip_int >= 0 ? static_cast <size_t >(second_attention_stopline_ip_int)
1815
1853
: 0 ;
1816
1854
1817
- // (8) second pass judge lie position on interpolated path
1818
- int second_pass_judge_ip_int = second_attention_stopline_ip_int - std::ceil (braking_dist / ds);
1855
+ // (8) second pass judge line position on interpolated path. It is the same as first pass judge
1856
+ // line if second_attention_lane is null
1857
+ int second_pass_judge_ip_int = occlusion_wo_tl_pass_judge_line_ip;
1819
1858
const auto second_pass_judge_line_ip =
1820
- static_cast <size_t >(std::max<int >(second_pass_judge_ip_int, 0 ));
1859
+ second_attention_area_opt ? static_cast <size_t >(std::max<int >(second_pass_judge_ip_int, 0 ))
1860
+ : first_pass_judge_line_ip;
1821
1861
1822
1862
struct IntersectionStopLinesTemp
1823
1863
{
@@ -2803,8 +2843,6 @@ TimeDistanceArray IntersectionModule::calcIntersectionPassingTime(
2803
2843
return std::nullopt;
2804
2844
}
2805
2845
}();
2806
- const bool has_upstream_stopline = upstream_stopline_idx_opt.has_value ();
2807
- const size_t upstream_stopline_ind = upstream_stopline_idx_opt.value_or (0 );
2808
2846
2809
2847
for (size_t i = smoothed_path_closest_idx; i < smoothed_reference_path.points .size () - 1 ; ++i) {
2810
2848
const auto & p1 = smoothed_reference_path.points .at (i);
@@ -2818,7 +2856,7 @@ TimeDistanceArray IntersectionModule::calcIntersectionPassingTime(
2818
2856
(p1.point .longitudinal_velocity_mps + p2.point .longitudinal_velocity_mps ) / 2.0 ;
2819
2857
const double passing_velocity = [=]() {
2820
2858
if (use_upstream_velocity) {
2821
- if (has_upstream_stopline && i > upstream_stopline_ind ) {
2859
+ if (upstream_stopline_idx_opt && i > upstream_stopline_idx_opt. value () ) {
2822
2860
return minimum_upstream_velocity;
2823
2861
}
2824
2862
return std::max<double >(average_velocity, minimum_ego_velocity);
0 commit comments