@@ -407,6 +407,23 @@ std::optional<FrontierCandidate> build_frontier_candidate(
407407 centroid_sum_y / static_cast <double >(new_frontier.size ()),
408408 };
409409
410+ int min_frontier_x = new_frontier.front ()->mapX ;
411+ int max_frontier_x = new_frontier.front ()->mapX ;
412+ int min_frontier_y = new_frontier.front ()->mapY ;
413+ int max_frontier_y = new_frontier.front ()->mapY ;
414+ for (auto * frontier_point : new_frontier) {
415+ min_frontier_x = std::min (min_frontier_x, frontier_point->mapX );
416+ max_frontier_x = std::max (max_frontier_x, frontier_point->mapX );
417+ min_frontier_y = std::min (min_frontier_y, frontier_point->mapY );
418+ max_frontier_y = std::max (max_frontier_y, frontier_point->mapY );
419+ }
420+ const FrontierCandidate::CellBounds visible_reveal_bounds{
421+ std::max (0 , min_frontier_x - 1 ),
422+ std::max (0 , min_frontier_y - 1 ),
423+ std::min (occupancy_map.getSizeX () - 1 , max_frontier_x + 1 ),
424+ std::min (occupancy_map.getSizeY () - 1 , max_frontier_y + 1 ),
425+ };
426+
410427 std::pair<int , int > center_cell = {new_frontier.front ()->mapX , new_frontier.front ()->mapY };
411428 std::pair<double , double > center_point = frontier_world_points.front ();
412429 double center_distance_sq = std::numeric_limits<double >::infinity ();
@@ -454,6 +471,7 @@ std::optional<FrontierCandidate> build_frontier_candidate(
454471 start_world_point,
455472 std::nullopt ,
456473 static_cast <int >(new_frontier.size ()),
474+ visible_reveal_bounds,
457475 };
458476 }
459477
@@ -524,6 +542,7 @@ std::optional<FrontierCandidate> build_frontier_candidate(
524542 start_world_point,
525543 *goal_point,
526544 static_cast <int >(new_frontier.size ()),
545+ visible_reveal_bounds,
527546 };
528547}
529548
@@ -803,7 +822,8 @@ std::optional<VisibleRevealGain> compute_visible_reveal_gain(
803822 const std::optional<OccupancyGrid2d> & local_costmap,
804823 double range_m,
805824 double fov_deg,
806- double ray_step_deg)
825+ double ray_step_deg,
826+ const std::optional<FrontierCandidate::CellBounds> & visible_reveal_bounds)
807827{
808828 // Invalid geometry means the caller should skip this optimization and keep the fallback path.
809829 if (range_m < 0.1 || fov_deg < 1.0 || fov_deg > 360.0 || ray_step_deg < 0.25 || ray_step_deg > 45.0 ) {
@@ -859,6 +879,15 @@ std::optional<VisibleRevealGain> compute_visible_reveal_gain(
859879 // Leaving the map bounds is equivalent to exhausting that ray.
860880 break ;
861881 }
882+ if (visible_reveal_bounds.has_value () &&
883+ (map_x < visible_reveal_bounds->min_x ||
884+ map_x > visible_reveal_bounds->max_x ||
885+ map_y < visible_reveal_bounds->min_y ||
886+ map_y > visible_reveal_bounds->max_y ))
887+ {
888+ // Treat the local frontier-cluster bounds as a virtual wall for visible-gain estimation.
889+ break ;
890+ }
862891
863892 if (map_x == last_map_x && map_y == last_map_y) {
864893 continue ;
0 commit comments