From fdcaadb6d377e38b52794ea52cf968598deb2000 Mon Sep 17 00:00:00 2001 From: huxiaoyi-ovo Date: Thu, 29 Oct 2026 05:02:47 -0400 Subject: [PATCH 1/3] fix(greedy): reconstruct reachable paths once and report no-path --- .../greedy_best_first_search.py | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/PathPlanning/GreedyBestFirstSearch/greedy_best_first_search.py b/PathPlanning/GreedyBestFirstSearch/greedy_best_first_search.py index b259beb870..fd5eb74784 100644 --- a/PathPlanning/GreedyBestFirstSearch/greedy_best_first_search.py +++ b/PathPlanning/GreedyBestFirstSearch/greedy_best_first_search.py @@ -99,9 +99,7 @@ def planning(self, sx, sy, gx, gy): if current.x == ngoal.x and current.y == ngoal.y: print("Found goal") - ngoal.pind = current.pind - ngoal.cost = current.cost - break + return self.calc_final_path(current) # expand_grid search grid based on motion model for i, _ in enumerate(self.motion): @@ -124,19 +122,16 @@ def planning(self, sx, sy, gx, gy): else: if open_set[n_id].cost > node.cost: open_set[n_id] = node - closed_set[ngoal.pind] = current - rx, ry = self.calc_final_path(ngoal, closed_set) - return rx, ry - - def calc_final_path(self, ngoal, closedset): - # generate final course - rx, ry = [self.calc_grid_position(ngoal.x, self.minx)], [ - self.calc_grid_position(ngoal.y, self.miny)] - n = closedset[ngoal.pind] - while n is not None: - rx.append(self.calc_grid_position(n.x, self.minx)) - ry.append(self.calc_grid_position(n.y, self.miny)) - n = n.parent + return [], [] + + def calc_final_path(self, goal_node): + # Follow parent pointers directly, from goal back to start. + rx, ry = [], [] + node = goal_node + while node is not None: + rx.append(self.calc_grid_position(node.x, self.minx)) + ry.append(self.calc_grid_position(node.y, self.miny)) + node = node.parent return rx, ry From fff7123c90a711f32155e9e0617466c0e75ffd0e Mon Sep 17 00:00:00 2001 From: huxiaoyi-ovo Date: Thu, 29 Oct 2026 05:03:08 -0400 Subject: [PATCH 2/3] test(greedy): cover unreachable, adjacent, and coincident goals --- tests/test_greedy_best_first_search.py | 44 ++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/tests/test_greedy_best_first_search.py b/tests/test_greedy_best_first_search.py index e573ecf625..19d57a2c96 100644 --- a/tests/test_greedy_best_first_search.py +++ b/tests/test_greedy_best_first_search.py @@ -7,5 +7,49 @@ def test_1(): m.main() + +def _make_bounded_map(block_center=False): + ox, oy = [], [] + for i in range(8): + ox.extend([i, i, 0, 7]) + oy.extend([0, 7, i, i]) + if block_center: + for y in range(1, 7): + ox.append(3) + oy.append(y) + return ox, oy + + +def test_unreachable_goal_returns_empty_path(): + m.show_animation = False + ox, oy = _make_bounded_map(block_center=True) + planner = m.BestFirstSearchPlanner(ox, oy, 1.0, 0.0) + + rx, ry = planner.planning(1.0, 2.0, 5.0, 2.0) + + assert rx == [] + assert ry == [] + + +def test_adjacent_goal_appears_only_once(): + m.show_animation = False + ox, oy = _make_bounded_map() + planner = m.BestFirstSearchPlanner(ox, oy, 1.0, 0.0) + + rx, ry = planner.planning(1.0, 2.0, 2.0, 2.0) + + assert list(zip(rx, ry)) == [(2.0, 2.0), (1.0, 2.0)] + + +def test_start_equals_goal_returns_single_point(): + m.show_animation = False + ox, oy = _make_bounded_map() + planner = m.BestFirstSearchPlanner(ox, oy, 1.0, 0.0) + + rx, ry = planner.planning(1.0, 2.0, 1.0, 2.0) + + assert list(zip(rx, ry)) == [(1.0, 2.0)] + + if __name__ == '__main__': conftest.run_this_test(__file__) From 4bedacf5a155f87cde18f09957259c358500393d Mon Sep 17 00:00:00 2001 From: huxiaoyi-ovo Date: Thu, 29 Oct 2026 05:03:46 -0400 Subject: [PATCH 3/3] style(tests): keep standard spacing between Greedy planner cases --- tests/test_greedy_best_first_search.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_greedy_best_first_search.py b/tests/test_greedy_best_first_search.py index 19d57a2c96..a4134bb935 100644 --- a/tests/test_greedy_best_first_search.py +++ b/tests/test_greedy_best_first_search.py @@ -7,7 +7,6 @@ def test_1(): m.main() - def _make_bounded_map(block_center=False): ox, oy = [], [] for i in range(8):