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