@@ -222,40 +222,105 @@ void RVO2Planner::overrideTargetPosition(crane_msgs::msg::RobotCommands & msg)
222
222
Point target_pos;
223
223
target_pos << command.position_target_mode .front ().target_x ,
224
224
command.position_target_mode .front ().target_y ;
225
+
226
+ bool is_near_our_penalty_area =
227
+ (std::signbit (world_model->getOurGoalCenter ().x ()) == std::signbit (command.current_pose .x ));
228
+ Box penalty_area = [&]() {
229
+ if (is_near_our_penalty_area) {
230
+ return world_model->getOurPenaltyArea ();
231
+ } else {
232
+ return world_model->getTheirPenaltyArea ();
233
+ }
234
+ }();
235
+ const Point goal_pos = [&]() {
236
+ if (is_near_our_penalty_area) {
237
+ return world_model->getOurGoalCenter ();
238
+ } else {
239
+ return world_model->getTheirGoalCenter ();
240
+ }
241
+ }();
225
242
if (not command.local_planner_config .disable_goal_area_avoidance ) {
226
- bool is_in_our_penalty_area = isInBox (world_model->getOurPenaltyArea (), target_pos);
227
- bool is_in_their_penalty_area = isInBox (world_model->getTheirPenaltyArea (), target_pos);
228
- if (is_in_our_penalty_area or is_in_their_penalty_area) {
243
+ bool is_in_penalty_area = isInBox (penalty_area, target_pos, 0.2 );
244
+ constexpr double SURROUNDING_OFFSET = 0.3 ;
245
+ constexpr double PENALTY_AREA_OFFSET = 0.1 ;
246
+ if (isInBox (
247
+ penalty_area, Point (command.current_pose .x , command.current_pose .y ),
248
+ PENALTY_AREA_OFFSET)) {
249
+ // 目標点をペナルティエリアの外に出るようにする
250
+ target_pos = Point (command.current_pose .x , command.current_pose .y );
251
+ while (isInBox (penalty_area, target_pos, PENALTY_AREA_OFFSET)) {
252
+ target_pos +=
253
+ (target_pos - goal_pos).normalized () * 0.05 ; // ゴールから5cmずつ離れていく
254
+ }
255
+ } else if (isInBox (penalty_area, target_pos, PENALTY_AREA_OFFSET)) {
229
256
// ペナルティエリア内にいる場合は、ペナルティエリアの外に出るようにする
230
- const Point goal_pos = [&]() {
231
- if (is_in_our_penalty_area) {
232
- return world_model->getOurGoalCenter ();
233
- } else {
234
- return world_model->getTheirGoalCenter ();
235
- }
236
- }();
237
-
238
257
// ゴールの後ろに回り込んだ場合は、ゴールの前に出るようにする
239
258
if (std::abs (target_pos.x ()) > world_model->field_size .x () / 2.0 ) {
240
259
target_pos.x () = std::copysign (world_model->field_size .x () / 2.0 , target_pos.x ());
241
260
}
242
261
243
262
// 目標点をペナルティエリアの外に出るようにする
244
- while ([&]() {
245
- if (is_in_our_penalty_area) {
246
- return isInBox (world_model->getOurPenaltyArea (), target_pos);
247
- } else {
248
- return isInBox (world_model->getTheirPenaltyArea (), target_pos);
249
- }
250
- }()) {
263
+ while (isInBox (penalty_area, target_pos, PENALTY_AREA_OFFSET)) {
251
264
target_pos +=
252
265
(target_pos - goal_pos).normalized () * 0.05 ; // ゴールから5cmずつ離れていく
253
266
}
254
267
}
268
+ // ペナルティエリアを通り抜ける場合は、一旦角に
269
+ const Point current_pos = Point (command.current_pose .x , command.current_pose .y );
270
+ Segment move_line (current_pos, target_pos);
271
+ if (bg::intersects (move_line, penalty_area)) {
272
+ const auto penalty_area_size = world_model->penalty_area_size ;
273
+ Point corner_1 = goal_pos + Point (
274
+ std::copysign (penalty_area_size.x (), -goal_pos.x ()),
275
+ world_model->penalty_area_size .y () * 0.5 );
276
+ Point around_corner_1 =
277
+ goal_pos + Point (
278
+ std::copysign (penalty_area_size.x () + SURROUNDING_OFFSET, -goal_pos.x ()),
279
+ world_model->penalty_area_size .y () * 0.5 + SURROUNDING_OFFSET);
280
+
281
+ Point corner_2 = goal_pos + Point (
282
+ std::copysign (penalty_area_size.x (), -goal_pos.x ()),
283
+ -world_model->penalty_area_size .y () * 0.5 );
284
+ Point around_corner_2 =
285
+ goal_pos + Point (
286
+ std::copysign (penalty_area_size.x () + SURROUNDING_OFFSET, -goal_pos.x ()),
287
+ -world_model->penalty_area_size .y () * 0.5 - SURROUNDING_OFFSET);
288
+
289
+ auto [distance_1, closest_point_1] = getClosestPointAndDistance (corner_1, move_line);
290
+ auto [distance_2, closest_point_2] = getClosestPointAndDistance (corner_2, move_line);
291
+
292
+ const double penalty_area_min_x = world_model->field_size .x () * 0.5 -
293
+ world_model->penalty_area_size .x () -
294
+ PENALTY_AREA_OFFSET;
295
+ if (
296
+ std::abs (closest_point_1.x ()) > penalty_area_min_x &&
297
+ std::abs (closest_point_2.x ()) > penalty_area_min_x) {
298
+ // 横切る場合は、近い方の角に向かう
299
+ if (bg::distance (corner_1, current_pos) < bg::distance (corner_2, current_pos)) {
300
+ target_pos = around_corner_1;
301
+ } else {
302
+ target_pos = around_corner_2;
303
+ }
304
+ } else if (isInBox (penalty_area, closest_point_1, PENALTY_AREA_OFFSET)) {
305
+ target_pos = around_corner_1;
306
+ } else if (isInBox (penalty_area, closest_point_2, PENALTY_AREA_OFFSET)) {
307
+ target_pos = around_corner_2;
308
+ } else {
309
+ std::stringstream what;
310
+ what << " Failed to find a target position outside the penalty area." ;
311
+ what << " current_pos: " << current_pos.x () << " , " << current_pos.y ();
312
+ what << " target_pos: " << target_pos.x () << " , " << target_pos.y ();
313
+ what << " closest_point_1: " << closest_point_1.x () << " , " << closest_point_1.y ();
314
+ what << " closest_point_2: " << closest_point_2.x () << " , " << closest_point_2.y ();
315
+ throw std::runtime_error (what.str ());
316
+ }
317
+ }
255
318
}
256
319
257
320
command.position_target_mode .front ().target_x = target_pos.x ();
258
321
command.position_target_mode .front ().target_y = target_pos.y ();
322
+ visualizer->addLine (
323
+ target_pos, Point (command.current_pose .x , command.current_pose .y ), 1 , " yellow" );
259
324
}
260
325
}
261
326
}
0 commit comments