bfs.py 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. """
  4. @author: huiming zhou
  5. """
  6. import queue
  7. import plotting
  8. import env
  9. class BFS:
  10. def __init__(self, x_start, x_goal):
  11. self.xI, self.xG = x_start, x_goal
  12. self.Env = env.Env()
  13. self.u_set = self.Env.motions # feasible input set
  14. self.obs = self.Env.obs # position of obstacles
  15. [self.path, self.policy, self.visited] = self.searching(self.xI, self.xG)
  16. self.fig_name = "Breadth-first Searching"
  17. plotting.animation(self.xI, self.xG, self.obs,
  18. self.path, self.visited, self.fig_name) # animation generate
  19. def searching(self, xI, xG):
  20. """
  21. Searching using BFS.
  22. :return: planning path, action in each node, visited nodes in the planning process
  23. """
  24. q_bfs = queue.QueueFIFO() # first-in-first-out queue
  25. q_bfs.put(xI)
  26. parent = {xI: xI} # record parents of nodes
  27. action = {xI: (0, 0)} # record actions of nodes
  28. visited = []
  29. while not q_bfs.empty():
  30. x_current = q_bfs.get()
  31. if x_current == xG:
  32. break
  33. visited.append(x_current)
  34. for u_next in self.u_set: # explore neighborhoods of current node
  35. x_next = tuple([x_current[i] + u_next[i] for i in range(len(x_current))])
  36. if x_next not in parent and x_next not in self.obs: # node not visited and not in obstacles
  37. q_bfs.put(x_next)
  38. parent[x_next], action[x_next] = x_current, u_next
  39. [path, policy] = self.extract_path(xI, xG, parent, action) # extract path
  40. return path, policy, visited
  41. def extract_path(self, xI, xG, parent, policy):
  42. """
  43. Extract the path based on the relationship of nodes.
  44. :param xI: Starting node
  45. :param xG: Goal node
  46. :param parent: Relationship between nodes
  47. :param policy: Action needed for transfer between two nodes
  48. :return: The planning path
  49. """
  50. path_back = [xG]
  51. acts_back = [policy[xG]]
  52. x_current = xG
  53. while True:
  54. x_current = parent[x_current]
  55. path_back.append(x_current)
  56. acts_back.append(policy[x_current])
  57. if x_current == xI: break
  58. return list(path_back), list(acts_back)
  59. if __name__ == '__main__':
  60. x_Start = (5, 5) # Starting node
  61. x_Goal = (49, 5) # Goal node
  62. bfs = BFS(x_Start, x_Goal)