@@ -165,8 +165,7 @@ BehaviorModuleOutput NormalLaneChange::generateOutput()
165
165
output.path .points , output.path .points .front ().point .pose .position , getEgoPosition ());
166
166
const auto stop_dist =
167
167
-(current_velocity * current_velocity / (2.0 * planner_data_->parameters .min_acc ));
168
- const auto stop_point = utils::insertStopPoint (stop_dist + current_dist, output.path );
169
- setStopPose (stop_point.point .pose );
168
+ set_stop_pose (stop_dist + current_dist, output.path );
170
169
} else {
171
170
insertStopPoint (status_.target_lanes , output.path );
172
171
}
@@ -204,7 +203,7 @@ void NormalLaneChange::extendOutputDrivableArea(BehaviorModuleOutput & output)
204
203
void NormalLaneChange::insertStopPoint (
205
204
const lanelet::ConstLanelets & lanelets, PathWithLaneId & path)
206
205
{
207
- if (lanelets.empty ()) {
206
+ if (lanelets.empty () || status_. current_lanes . empty () ) {
208
207
return ;
209
208
}
210
209
@@ -214,133 +213,119 @@ void NormalLaneChange::insertStopPoint(
214
213
return ;
215
214
}
216
215
217
- const auto shift_intervals = route_handler->getLateralIntervalsToPreferredLane (lanelets.back ());
218
- const double lane_change_buffer =
219
- utils::lane_change::calcMinimumLaneChangeLength (*lane_change_parameters_, shift_intervals, 0.0 );
216
+ const auto & current_lanes = status_.current_lanes ;
217
+ const auto is_current_lane = lanelets.front ().id () == current_lanes.front ().id () &&
218
+ lanelets.back ().id () == current_lanes.back ().id ();
219
+
220
+ // if input is not current lane, we can just insert the points at terminal.
221
+ if (!is_current_lane) {
222
+ const auto shift_intervals = route_handler->getLateralIntervalsToPreferredLane (lanelets.back ());
223
+ const auto min_dist_buffer = utils::lane_change::calcMinimumLaneChangeLength (
224
+ *lane_change_parameters_, shift_intervals, 0.0 );
225
+ const auto backward_length_buffer =
226
+ lane_change_parameters_->backward_length_buffer_for_end_of_lane ;
227
+ const auto arc_length_to_stop_pose =
228
+ motion_utils::calcArcLength (path.points ) - backward_length_buffer + min_dist_buffer;
229
+ set_stop_pose (arc_length_to_stop_pose, path);
230
+ return ;
231
+ }
220
232
221
- const auto getDistanceAlongLanelet = [&](const geometry_msgs::msg::Pose & target) {
222
- return utils::getSignedDistance (path.points .front ().point .pose , target, lanelets);
223
- };
233
+ insert_stop_point_on_current_lanes (path);
234
+ }
224
235
225
- // If lanelets.back() is in goal route section, get distance to goal.
226
- // Otherwise, get distance to end of lane.
227
- double distance_to_terminal = 0.0 ;
228
- if (route_handler->isInGoalRouteSection (lanelets.back ())) {
229
- const auto goal = route_handler->getGoalPose ();
230
- distance_to_terminal = getDistanceAlongLanelet (goal);
231
- } else {
232
- distance_to_terminal = utils::getDistanceToEndOfLane (path.points .front ().point .pose , lanelets);
233
- }
236
+ void NormalLaneChange::insert_stop_point_on_current_lanes (PathWithLaneId & path)
237
+ {
238
+ const auto & path_front_pose = path.points .front ().point .pose ;
239
+ const auto & route_handler_ptr = getRouteHandler ();
240
+ const auto & current_lanes = status_.current_lanes ;
241
+ const auto current_path =
242
+ route_handler_ptr->getCenterLinePath (current_lanes, 0.0 , std::numeric_limits<double >::max ());
243
+ const auto & center_line = current_path.points ;
244
+ const auto get_arc_length_along_lanelet = [&](const geometry_msgs::msg::Pose & target) {
245
+ return motion_utils::calcSignedArcLength (
246
+ center_line, path_front_pose.position , target.position );
247
+ };
234
248
235
- const double stop_point_buffer = lane_change_parameters_->backward_length_buffer_for_end_of_lane ;
236
- const auto target_objects = getTargetObjects (status_.current_lanes , status_.target_lanes );
237
- double stopping_distance = distance_to_terminal - lane_change_buffer - stop_point_buffer;
238
-
239
- const auto is_valid_start_point = std::invoke ([&]() -> bool {
240
- auto lc_start_point = lanelet::utils::conversion::toLaneletPoint (
241
- status_.lane_change_path .info .lane_changing_start .position );
242
- const auto target_neighbor_preferred_lane_poly_2d =
243
- utils::lane_change::getTargetNeighborLanesPolygon (
244
- *route_handler, status_.current_lanes , type_);
245
- return boost::geometry::covered_by (
246
- lanelet::traits::to2D (lc_start_point), target_neighbor_preferred_lane_poly_2d);
249
+ const auto dist_to_terminal = std::invoke ([&]() -> double {
250
+ const auto target_pose = route_handler_ptr->isInGoalRouteSection (current_lanes.back ())
251
+ ? route_handler_ptr->getGoalPose ()
252
+ : center_line.back ().point .pose ;
253
+ return get_arc_length_along_lanelet (target_pose);
247
254
});
248
255
249
- if (!is_valid_start_point) {
250
- const auto stop_point = utils::insertStopPoint (stopping_distance, path);
251
- setStopPose (stop_point.point .pose );
256
+ const auto shift_intervals =
257
+ route_handler_ptr->getLateralIntervalsToPreferredLane (current_lanes.back ());
258
+ const auto min_dist_buffer =
259
+ utils::lane_change::calcMinimumLaneChangeLength (*lane_change_parameters_, shift_intervals, 0.0 );
260
+ const auto backward_length_buffer =
261
+ lane_change_parameters_->backward_length_buffer_for_end_of_lane ;
262
+ const auto dist_to_terminal_start = dist_to_terminal - min_dist_buffer - backward_length_buffer;
252
263
264
+ const auto filtered_objects = getTargetObjects (status_.current_lanes , status_.target_lanes );
265
+ if (filtered_objects.current_lane .empty ()) {
266
+ set_stop_pose (dist_to_terminal_start, path);
253
267
return ;
254
268
}
255
269
256
- // calculate minimum distance from path front to the stationary object on the ego lane.
257
- const auto distance_to_ego_lane_obj = [&]() -> double {
258
- double distance_to_obj = distance_to_terminal;
259
- const double distance_to_ego = getDistanceAlongLanelet (getEgoPose ());
260
-
261
- for (const auto & object : target_objects.current_lane ) {
262
- // check if stationary
263
- const auto obj_v = std::abs (object.initial_twist .twist .linear .x );
264
- if (obj_v > lane_change_parameters_->stop_velocity_threshold ) {
265
- continue ;
266
- }
267
-
268
- // calculate distance from path front to the stationary object polygon on the ego lane.
269
- const auto polygon =
270
- tier4_autoware_utils::toPolygon2d (object.initial_pose .pose , object.shape ).outer ();
271
- for (const auto & polygon_p : polygon) {
272
- const auto p_fp = tier4_autoware_utils::toMsg (polygon_p.to_3d ());
273
- const auto lateral_fp = motion_utils::calcLateralOffset (path.points , p_fp);
270
+ const auto dist_to_target_lane_start = std::invoke ([&]() -> double {
271
+ const auto & front_lane = status_.target_lanes .front ();
272
+ const auto & ll_front_pt = front_lane.centerline2d ().front ();
273
+ const auto front_pt = lanelet::utils::conversion::toGeomMsgPt (ll_front_pt);
274
+ const auto yaw = lanelet::utils::getLaneletAngle (front_lane, front_pt);
275
+ Pose target_front;
276
+ target_front.position = front_pt;
277
+ tf2::Quaternion tf_quat;
278
+ tf_quat.setRPY (0 , 0 , yaw);
279
+ target_front.orientation = tf2::toMsg (tf_quat);
274
280
275
- // ignore if the point is around the ego path
276
- if (std::abs (lateral_fp) > planner_data_->parameters .vehicle_width ) {
277
- continue ;
278
- }
281
+ return get_arc_length_along_lanelet (target_front);
282
+ });
279
283
280
- const double current_distance_to_obj = calcSignedArcLength (path.points , 0 , p_fp);
284
+ const auto arc_length_to_current_obj = utils::lane_change::get_min_dist_to_current_lanes_obj (
285
+ filtered_objects, getCommonParam (), *lane_change_parameters_, dist_to_target_lane_start,
286
+ getEgoPose (), path);
281
287
282
- // ignore backward object
283
- if (current_distance_to_obj < distance_to_ego) {
284
- continue ;
285
- }
286
- distance_to_obj = std::min (distance_to_obj, current_distance_to_obj);
287
- }
288
- }
289
- return distance_to_obj;
290
- }();
291
-
292
- // Need to stop before blocking obstacle
293
- if (distance_to_ego_lane_obj < distance_to_terminal) {
294
- // consider rss distance when the LC need to avoid obstacles
295
- const auto rss_dist = calcRssDistance (
296
- 0.0 , lane_change_parameters_->minimum_lane_changing_velocity ,
297
- lane_change_parameters_->rss_params );
298
- const double lane_change_buffer_for_blocking_object =
299
- utils::lane_change::calcMinimumLaneChangeLength (*lane_change_parameters_, shift_intervals);
300
-
301
- const auto stopping_distance_for_obj =
302
- distance_to_ego_lane_obj - lane_change_buffer_for_blocking_object -
303
- lane_change_parameters_->backward_length_buffer_for_blocking_object - rss_dist -
304
- getCommonParam ().base_link2front ;
305
-
306
- // If the target lane in the lane change section is blocked by a stationary obstacle, there
307
- // is no reason for stopping with a lane change margin. Instead, stop right behind the
308
- // obstacle.
309
- // ----------------------------------------------------------
310
- // [obj]>
311
- // ----------------------------------------------------------
312
- // [ego]> | <--- lane change margin ---> [obj]>
313
- // ----------------------------------------------------------
314
- const bool has_blocking_target_lane_obj = std::any_of (
315
- target_objects.target_lane .begin (), target_objects.target_lane .end (), [&](const auto & o) {
316
- const auto v = std::abs (o.initial_twist .twist .linear .x );
317
- if (v > lane_change_parameters_->stop_velocity_threshold ) {
318
- return false ;
319
- }
288
+ // margin with leading vehicle
289
+ // consider rss distance when the LC need to avoid obstacles
290
+ const auto rss_dist = calcRssDistance (
291
+ 0.0 , lane_change_parameters_->minimum_lane_changing_velocity ,
292
+ lane_change_parameters_->rss_params );
320
293
321
- // target_objects includes objects out of target lanes, so filter them out
322
- if (!boost::geometry::intersects (
323
- tier4_autoware_utils::toPolygon2d (o.initial_pose .pose , o.shape ).outer (),
324
- lanelet::utils::combineLaneletsShape (status_.target_lanes )
325
- .polygon2d ()
326
- .basicPolygon ())) {
327
- return false ;
328
- }
294
+ const auto min_single_lc_length = utils::lane_change::calcMinimumLaneChangeLength (
295
+ *lane_change_parameters_, {shift_intervals.front ()}, 0.0 );
296
+ const auto stop_margin = min_single_lc_length +
297
+ lane_change_parameters_->backward_length_buffer_for_blocking_object +
298
+ rss_dist + getCommonParam ().base_link2front ;
299
+ const auto stop_arc_length_behind_obj = arc_length_to_current_obj - stop_margin;
329
300
330
- const double distance_to_target_lane_obj = getDistanceAlongLanelet (o. initial_pose . pose );
331
- return stopping_distance_for_obj < distance_to_target_lane_obj &&
332
- distance_to_target_lane_obj < distance_to_ego_lane_obj ;
333
- });
301
+ if (stop_arc_length_behind_obj < dist_to_target_lane_start) {
302
+ set_stop_pose (dist_to_target_lane_start, path);
303
+ return ;
304
+ }
334
305
335
- if (!has_blocking_target_lane_obj ) {
336
- stopping_distance = stopping_distance_for_obj ;
337
- }
306
+ if (stop_arc_length_behind_obj > dist_to_terminal_start ) {
307
+ set_stop_pose (dist_to_terminal_start, path) ;
308
+ return ;
338
309
}
339
310
340
- if (stopping_distance > 0.0 ) {
341
- const auto stop_point = utils::insertStopPoint (stopping_distance, path);
342
- setStopPose (stop_point.point .pose );
311
+ // If the target lane in the lane change section is blocked by a stationary obstacle, there
312
+ // is no reason for stopping with a lane change margin. Instead, stop right behind the
313
+ // obstacle.
314
+ // ----------------------------------------------------------
315
+ // [obj]>
316
+ // ----------------------------------------------------------
317
+ // [ego]> | <--- stop margin ---> [obj]>
318
+ // ----------------------------------------------------------
319
+ const auto has_blocking_target_lane_obj = utils::lane_change::has_blocking_target_object (
320
+ status_.target_lanes , filtered_objects, *lane_change_parameters_, stop_arc_length_behind_obj,
321
+ getEgoPose (), path);
322
+
323
+ if (has_blocking_target_lane_obj || stop_arc_length_behind_obj <= 0.0 ) {
324
+ set_stop_pose (dist_to_terminal_start, path);
325
+ return ;
343
326
}
327
+
328
+ set_stop_pose (stop_arc_length_behind_obj, path);
344
329
}
345
330
346
331
PathWithLaneId NormalLaneChange::getReferencePath () const
@@ -1842,9 +1827,10 @@ bool NormalLaneChange::isVehicleStuck(const lanelet::ConstLanelets & current_lan
1842
1827
return isVehicleStuck (current_lanes, detection_distance);
1843
1828
}
1844
1829
1845
- void NormalLaneChange::setStopPose (const Pose & stop_pose )
1830
+ void NormalLaneChange::set_stop_pose (const double arc_length_to_stop_pose, PathWithLaneId & path )
1846
1831
{
1847
- lane_change_stop_pose_ = stop_pose;
1832
+ const auto stop_point = utils::insertStopPoint (arc_length_to_stop_pose, path);
1833
+ lane_change_stop_pose_ = stop_point.point .pose ;
1848
1834
}
1849
1835
1850
1836
void NormalLaneChange::updateStopTime ()
0 commit comments