-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplanning.py
116 lines (95 loc) · 3.18 KB
/
planning.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
from enum import Enum
from queue import PriorityQueue
class Action(Enum):
"""
An action is represented by a 3 element tuple.
The first 2 values are the delta of the action relative
to the current grid position. The third and final value
is the cost of performing the action.
"""
LEFT = (0, -1, 1)
RIGHT = (0, 1, 1)
UP = (-1, 0, 1)
DOWN = (1, 0, 1)
def __str__(self):
if self == self.LEFT:
return '<'
elif self == self.RIGHT:
return '>'
elif self == self.UP:
return '^'
elif self == self.DOWN:
return 'v'
@property
def cost(self):
return self.value[2]
@property
def delta(self):
return (self.value[0], self.value[1])
def valid_actions(grid, current_node):
"""
Returns a list of valid actions given a grid and current node.
"""
valid = [Action.UP, Action.LEFT, Action.RIGHT, Action.DOWN]
n, m = grid.shape[0] - 1, grid.shape[1] - 1
x, y = current_node
# check if the node is off the grid or
# it's an obstacle
if x - 1 < 0 or grid[x - 1, y] == 1:
valid.remove(Action.UP)
if x + 1 > n or grid[x + 1, y] == 1:
valid.remove(Action.DOWN)
if y - 1 < 0 or grid[x, y - 1] == 1:
valid.remove(Action.LEFT)
if y + 1 > m or grid[x, y + 1] == 1:
valid.remove(Action.RIGHT)
return valid
def a_star(grid, h, start, goal):
try:
path = []
path_cost = 0
queue = PriorityQueue()
queue.put((0, start))
visited = set(start)
branch = {}
found = False
while not queue.empty():
item = queue.get()
current_node = item[1]
if current_node == start:
current_cost = 0.0
else:
current_cost = branch[current_node][0]
if current_node == goal:
print('Found a path.')
found = True
break
else:
for action in valid_actions(grid, current_node):
# get the tuple representation
da = action.delta
next_node = (current_node[0] + da[0], current_node[1] + da[1])
branch_cost = current_cost + action.cost
queue_cost = branch_cost + h(next_node, goal)
if next_node not in visited:
visited.add(next_node)
branch[next_node] = (branch_cost, current_node, action)
queue.put((queue_cost, next_node))
if found:
# retrace steps
n = goal
path_cost = branch[n][0]
path.append(goal)
while branch[n][1] != start:
path.append(branch[n][1])
n = branch[n][1]
path.append(branch[n][2])
else:
print('**********************')
print('Failed to find a path!')
print('**********************')
print("done")
return path[::-1], path_cost
except:
print("Type error")
return 0,0