pathplanning 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. CurvesGenerator/__init__.py +1 -0
  2. CurvesGenerator/bezier_path.py +145 -0
  3. CurvesGenerator/bspline_curve.py +80 -0
  4. CurvesGenerator/cubic_spline.py +262 -0
  5. CurvesGenerator/draw.py +66 -0
  6. CurvesGenerator/dubins_path.py +351 -0
  7. CurvesGenerator/quartic_polynomial.py +43 -0
  8. CurvesGenerator/quintic_polynomial.py +143 -0
  9. CurvesGenerator/reeds_shepp.py +720 -0
  10. Sampling_based_Planning/__init__.py +1 -0
  11. Sampling_based_Planning/rrt_2D/__init__.py +1 -0
  12. Sampling_based_Planning/rrt_2D/adaptively_informed_trees.py +0 -0
  13. Sampling_based_Planning/rrt_2D/advanced_batch_informed_trees.py +0 -0
  14. Sampling_based_Planning/rrt_2D/batch_informed_trees.py +402 -0
  15. Sampling_based_Planning/rrt_2D/dubins_rrt_star.py +321 -0
  16. Sampling_based_Planning/rrt_2D/dynamic_rrt.py +342 -0
  17. Sampling_based_Planning/rrt_2D/env.py +45 -0
  18. Sampling_based_Planning/rrt_2D/extended_rrt.py +251 -0
  19. Sampling_based_Planning/rrt_2D/fast_marching_trees.py +220 -0
  20. Sampling_based_Planning/rrt_2D/informed_rrt_star.py +305 -0
  21. Sampling_based_Planning/rrt_2D/plotting.py +115 -0
  22. Sampling_based_Planning/rrt_2D/queue.py +62 -0
  23. Sampling_based_Planning/rrt_2D/rrt.py +114 -0
  24. Sampling_based_Planning/rrt_2D/rrt_connect.py +156 -0
  25. Sampling_based_Planning/rrt_2D/rrt_sharp.py +0 -0
  26. Sampling_based_Planning/rrt_2D/rrt_star.py +184 -0
  27. Sampling_based_Planning/rrt_2D/rrt_star_smart.py +311 -0
  28. Sampling_based_Planning/rrt_2D/utils.py +138 -0
  29. Sampling_based_Planning/rrt_3D/ABIT_star3D.py +148 -0
  30. Sampling_based_Planning/rrt_3D/BIT_star3D.py +353 -0
  31. Sampling_based_Planning/rrt_3D/FMT_star3D.py +192 -0
  32. Sampling_based_Planning/rrt_3D/__init__.py +1 -0
  33. Sampling_based_Planning/rrt_3D/dynamic_rrt3D.py +239 -0
  34. Sampling_based_Planning/rrt_3D/env3D.py +148 -0
  35. Sampling_based_Planning/rrt_3D/extend_rrt3D.py +102 -0
  36. Sampling_based_Planning/rrt_3D/informed_rrt_star3D.py +234 -0
  37. Sampling_based_Planning/rrt_3D/plot_util3D.py +167 -0
  38. Sampling_based_Planning/rrt_3D/queue.py +86 -0
  39. Sampling_based_Planning/rrt_3D/rrt3D.py +72 -0
  40. Sampling_based_Planning/rrt_3D/rrt_connect3D.py +187 -0
  41. Sampling_based_Planning/rrt_3D/rrt_star3D.py +107 -0
  42. Sampling_based_Planning/rrt_3D/rrt_star_smart3D.py +0 -0
  43. Sampling_based_Planning/rrt_3D/utils3D.py +416 -0
  44. Search_based_Planning/Search_3D/Anytime_Dstar3D.py +245 -0
  45. Search_based_Planning/Search_3D/Astar3D.py +119 -0
  46. Search_based_Planning/Search_3D/Dstar3D.py +192 -0
  47. Search_based_Planning/Search_3D/DstarLite3D.py +219 -0
  48. Search_based_Planning/Search_3D/LP_Astar3D.py +194 -0
  49. Search_based_Planning/Search_3D/LRT_Astar3D.py +87 -0
  50. Search_based_Planning/Search_3D/RTA_Astar3D.py +78 -0
  51. Search_based_Planning/Search_3D/__init__.py +1 -0
  52. Search_based_Planning/Search_3D/bidirectional_Astar3D.py +115 -0
  53. Search_based_Planning/Search_3D/env3D.py +147 -0
  54. Search_based_Planning/Search_3D/plot_util3D.py +155 -0
  55. Search_based_Planning/Search_3D/queue.py +154 -0
  56. Search_based_Planning/Search_3D/utils3D.py +359 -0
  57. Search_based_Planning/__init__.py +1 -0
  58. Search_based_Planning/plan2d/__init__.py +17 -0
  59. Search_based_Planning/plan2d/anytime_dstar.py +314 -0
  60. Search_based_Planning/plan2d/anytime_repairing_astar.py +220 -0
  61. Search_based_Planning/plan2d/astar.py +225 -0
  62. Search_based_Planning/plan2d/best_first_search.py +67 -0
  63. Search_based_Planning/plan2d/bidirectional_astar.py +229 -0
  64. Search_based_Planning/plan2d/breadth_first_search.py +69 -0
  65. Search_based_Planning/plan2d/depth_first_search.py +69 -0
  66. Search_based_Planning/plan2d/dijkstra.py +68 -0
  67. Search_based_Planning/plan2d/dstar.py +304 -0
  68. Search_based_Planning/plan2d/dstar_lite.py +239 -0
  69. Search_based_Planning/plan2d/learning_realtime_astar.py +230 -0
  70. Search_based_Planning/plan2d/lifelong_planning_astar.py +254 -0
  71. Search_based_Planning/plan2d/plan2d_facade.py +494 -0
  72. Search_based_Planning/plan2d/realtime_adaptive_astar.py +234 -0
  73. Search_based_Planning/plan2d/run.py +55 -0
  74. Search_based_Planning/plan2d/utils/__init__.py +1 -0
  75. Search_based_Planning/plan2d/utils/env.py +48 -0
  76. Search_based_Planning/plan2d/utils/plotting.py +258 -0
  77. Search_based_Planning/plan2d/utils/queue.py +62 -0
  78. pathplanning-0.1.0.dist-info/LICENSE +21 -0
  79. pathplanning-0.1.0.dist-info/METADATA +354 -0
  80. pathplanning-0.1.0.dist-info/RECORD +86 -0
  81. pathplanning-0.1.0.dist-info/WHEEL +5 -0
  82. pathplanning-0.1.0.dist-info/top_level.txt +4 -0
  83. pathplanningv2/__init__.py +29 -0
  84. pathplanningv2/api.py +18 -0
  85. pathplanningv2/registry.py +107 -0
  86. pathplanningv2/search2d.py +15 -0
@@ -0,0 +1,321 @@
1
+ """
2
+ DUBINS_RRT_STAR 2D
3
+ @author: damminhtien
4
+ """
5
+
6
+ import os
7
+ import sys
8
+ import math
9
+ import random
10
+ import numpy as np
11
+ import matplotlib.pyplot as plt
12
+ import matplotlib.patches as patches
13
+ from scipy.spatial.transform import Rotation as Rot
14
+
15
+ sys.path.append(os.path.dirname(os.path.abspath(__file__)) +
16
+ "/../../Sampling_based_Planning/")
17
+
18
+ from Sampling_based_Planning.rrt_2D import env, plotting, utils
19
+ import CurvesGenerator.dubins_path as dubins
20
+ import CurvesGenerator.draw as draw
21
+
22
+
23
+ class Node:
24
+ def __init__(self, x, y, yaw):
25
+ self.x = x
26
+ self.y = y
27
+ self.yaw = yaw
28
+ self.parent = None
29
+ self.cost = 0.0
30
+ self.path_x = []
31
+ self.path_y = []
32
+ self.paty_yaw = []
33
+
34
+
35
+ class DubinsRRTStar:
36
+ def __init__(self, sx, sy, syaw, gx, gy, gyaw, vehicle_radius, step_len,
37
+ goal_sample_rate, search_radius, iter_max):
38
+ self.s_start = Node(sx, sy, syaw)
39
+ self.s_goal = Node(gx, gy, gyaw)
40
+ self.vr = vehicle_radius
41
+ self.step_len = step_len
42
+ self.goal_sample_rate = goal_sample_rate
43
+ self.search_radius = search_radius
44
+ self.iter_max = iter_max
45
+ self.curv = 1
46
+
47
+ self.env = env.Env()
48
+ self.utils = utils.Utils()
49
+
50
+ self.fig, self.ax = plt.subplots()
51
+ self.delta = self.utils.delta
52
+ self.x_range = self.env.x_range
53
+ self.y_range = self.env.y_range
54
+ self.obs_circle = self.obs_circle()
55
+ self.obs_boundary = self.env.obs_boundary
56
+ self.utils.update_obs(self.obs_circle, self.obs_boundary, [])
57
+
58
+ self.V = [self.s_start]
59
+ self.path = None
60
+
61
+ def planning(self):
62
+
63
+ for i in range(self.iter_max):
64
+ print("Iter:", i, ", number of nodes:", len(self.V))
65
+ rnd = self.Sample()
66
+ node_nearest = self.Nearest(self.V, rnd)
67
+ new_node = self.Steer(node_nearest, rnd)
68
+
69
+ if new_node and not self.is_collision(new_node):
70
+ near_indexes = self.Near(self.V, new_node)
71
+ new_node = self.choose_parent(new_node, near_indexes)
72
+
73
+ if new_node:
74
+ self.V.append(new_node)
75
+ self.rewire(new_node, near_indexes)
76
+
77
+ if i % 5 == 0:
78
+ self.draw_graph()
79
+
80
+ last_index = self.search_best_goal_node()
81
+
82
+ path = self.generate_final_course(last_index)
83
+ print("get!")
84
+ px = [s[0] for s in path]
85
+ py = [s[1] for s in path]
86
+ plt.plot(px, py, '-r')
87
+ plt.pause(0.01)
88
+ plt.show()
89
+
90
+ def draw_graph(self, rnd=None):
91
+ plt.cla()
92
+ # for stopping simulation with the esc key.
93
+ plt.gcf().canvas.mpl_connect('key_release_event',
94
+ lambda event: [exit(0) if event.key == 'escape' else None])
95
+ for node in self.V:
96
+ if node.parent:
97
+ plt.plot(node.path_x, node.path_y, "-g")
98
+
99
+ self.plot_grid("dubins rrt*")
100
+ plt.plot(self.s_start.x, self.s_start.y, "xr")
101
+ plt.plot(self.s_goal.x, self.s_goal.y, "xr")
102
+ plt.grid(True)
103
+ self.plot_start_goal_arrow()
104
+ plt.pause(0.01)
105
+
106
+ def plot_start_goal_arrow(self):
107
+ draw.Arrow(self.s_start.x, self.s_start.y, self.s_start.yaw, 2, "darkorange")
108
+ draw.Arrow(self.s_goal.x, self.s_goal.y, self.s_goal.yaw, 2, "darkorange")
109
+
110
+ def generate_final_course(self, goal_index):
111
+ print("final")
112
+ path = [[self.s_goal.x, self.s_goal.y]]
113
+ node = self.V[goal_index]
114
+ while node.parent:
115
+ for (ix, iy) in zip(reversed(node.path_x), reversed(node.path_y)):
116
+ path.append([ix, iy])
117
+ node = node.parent
118
+ path.append([self.s_start.x, self.s_start.y])
119
+ return path
120
+
121
+ def calc_dist_to_goal(self, x, y):
122
+ dx = x - self.s_goal.x
123
+ dy = y - self.s_goal.y
124
+ return math.hypot(dx, dy)
125
+
126
+ def search_best_goal_node(self):
127
+ dist_to_goal_list = [self.calc_dist_to_goal(n.x, n.y) for n in self.V]
128
+ goal_inds = [dist_to_goal_list.index(i) for i in dist_to_goal_list if i <= self.step_len]
129
+
130
+ safe_goal_inds = []
131
+ for goal_ind in goal_inds:
132
+ t_node = self.Steer(self.V[goal_ind], self.s_goal)
133
+ if t_node and not self.is_collision(t_node):
134
+ safe_goal_inds.append(goal_ind)
135
+
136
+ if not safe_goal_inds:
137
+ return None
138
+
139
+ min_cost = min([self.V[i].cost for i in safe_goal_inds])
140
+ for i in safe_goal_inds:
141
+ if self.V[i].cost == min_cost:
142
+ return i
143
+
144
+ return None
145
+
146
+ def rewire(self, new_node, near_inds):
147
+ for i in near_inds:
148
+ near_node = self.V[i]
149
+ edge_node = self.Steer(new_node, near_node)
150
+ if not edge_node:
151
+ continue
152
+ edge_node.cost = self.calc_new_cost(new_node, near_node)
153
+
154
+ no_collision = ~self.is_collision(edge_node)
155
+ improved_cost = near_node.cost > edge_node.cost
156
+
157
+ if no_collision and improved_cost:
158
+ self.V[i] = edge_node
159
+ self.propagate_cost_to_leaves(new_node)
160
+
161
+ def choose_parent(self, new_node, near_inds):
162
+ if not near_inds:
163
+ return None
164
+
165
+ costs = []
166
+ for i in near_inds:
167
+ near_node = self.V[i]
168
+ t_node = self.Steer(near_node, new_node)
169
+ if t_node and not self.is_collision(t_node):
170
+ costs.append(self.calc_new_cost(near_node, new_node))
171
+ else:
172
+ costs.append(float("inf")) # the cost of collision node
173
+ min_cost = min(costs)
174
+
175
+ if min_cost == float("inf"):
176
+ print("There is no good path.(min_cost is inf)")
177
+ return None
178
+
179
+ min_ind = near_inds[costs.index(min_cost)]
180
+ new_node = self.Steer(self.V[min_ind], new_node)
181
+
182
+ return new_node
183
+
184
+ def calc_new_cost(self, from_node, to_node):
185
+ d, _ = self.get_distance_and_angle(from_node, to_node)
186
+ return from_node.cost + d
187
+
188
+ def propagate_cost_to_leaves(self, parent_node):
189
+ for node in self.V:
190
+ if node.parent == parent_node:
191
+ node.cost = self.calc_new_cost(parent_node, node)
192
+ self.propagate_cost_to_leaves(node)
193
+
194
+ @staticmethod
195
+ def get_distance_and_angle(node_start, node_end):
196
+ dx = node_end.x - node_start.x
197
+ dy = node_end.y - node_start.y
198
+ return math.hypot(dx, dy), math.atan2(dy, dx)
199
+
200
+ def Near(self, nodelist, node):
201
+ n = len(nodelist) + 1
202
+ r = min(self.search_radius * math.sqrt((math.log(n)) / n), self.step_len)
203
+
204
+ dist_table = [(nd.x - node.x) ** 2 + (nd.y - node.y) ** 2 for nd in nodelist]
205
+ node_near_ind = [ind for ind in range(len(dist_table)) if dist_table[ind] <= r ** 2]
206
+
207
+ return node_near_ind
208
+
209
+ def Steer(self, node_start, node_end):
210
+ sx, sy, syaw = node_start.x, node_start.y, node_start.yaw
211
+ gx, gy, gyaw = node_end.x, node_end.y, node_end.yaw
212
+ maxc = self.curv
213
+
214
+ path = dubins.calc_dubins_path(sx, sy, syaw, gx, gy, gyaw, maxc)
215
+
216
+ if len(path.x) <= 1:
217
+ return None
218
+
219
+ node_new = Node(path.x[-1], path.y[-1], path.yaw[-1])
220
+ node_new.path_x = path.x
221
+ node_new.path_y = path.y
222
+ node_new.path_yaw = path.yaw
223
+ node_new.cost = node_start.cost + path.L
224
+ node_new.parent = node_start
225
+
226
+ return node_new
227
+
228
+ def Sample(self):
229
+ delta = self.utils.delta
230
+
231
+ if random.random() > self.goal_sample_rate:
232
+ return Node(random.uniform(self.x_range[0] + delta, self.x_range[1] - delta),
233
+ random.uniform(self.y_range[0] + delta, self.y_range[1] - delta),
234
+ random.uniform(-math.pi, math.pi))
235
+ else:
236
+ return self.s_goal
237
+
238
+ @staticmethod
239
+ def Nearest(nodelist, n):
240
+ return nodelist[int(np.argmin([(nd.x - n.x) ** 2 + (nd.y - n.y) ** 2
241
+ for nd in nodelist]))]
242
+
243
+ def is_collision(self, node):
244
+ for ox, oy, r in self.obs_circle:
245
+ dx = [ox - x for x in node.path_x]
246
+ dy = [oy - y for y in node.path_y]
247
+ dist = np.hypot(dx, dy)
248
+
249
+ if min(dist) < r + self.delta:
250
+ return True
251
+
252
+ return False
253
+
254
+ def animation(self):
255
+ self.plot_grid("dubins rrt*")
256
+ self.plot_arrow()
257
+ plt.show()
258
+
259
+ def plot_arrow(self):
260
+ draw.Arrow(self.s_start.x, self.s_start.y, self.s_start.yaw, 2.5, "darkorange")
261
+ draw.Arrow(self.s_goal.x, self.s_goal.y, self.s_goal.yaw, 2.5, "darkorange")
262
+
263
+ def plot_grid(self, name):
264
+
265
+ for (ox, oy, w, h) in self.obs_boundary:
266
+ self.ax.add_patch(
267
+ patches.Rectangle(
268
+ (ox, oy), w, h,
269
+ edgecolor='black',
270
+ facecolor='black',
271
+ fill=True
272
+ )
273
+ )
274
+
275
+ for (ox, oy, r) in self.obs_circle:
276
+ self.ax.add_patch(
277
+ patches.Circle(
278
+ (ox, oy), r,
279
+ edgecolor='black',
280
+ facecolor='gray',
281
+ fill=True
282
+ )
283
+ )
284
+
285
+ plt.plot(self.s_start.x, self.s_start.y, "bs", linewidth=3)
286
+ plt.plot(self.s_goal.x, self.s_goal.y, "gs", linewidth=3)
287
+
288
+ plt.title(name)
289
+ plt.axis("equal")
290
+
291
+ @staticmethod
292
+ def obs_circle():
293
+ obs_cir = [
294
+ [10, 10, 3],
295
+ [15, 22, 3],
296
+ [22, 8, 2.5],
297
+ [26, 16, 2],
298
+ [37, 10, 3],
299
+ [37, 23, 3],
300
+ [45, 15, 2]
301
+ ]
302
+
303
+ return obs_cir
304
+
305
+
306
+ def main():
307
+ sx, sy, syaw = 5, 5, np.deg2rad(90)
308
+ gx, gy, gyaw = 45, 25, np.deg2rad(0)
309
+ goal_sample_rate = 0.1
310
+ search_radius = 50.0
311
+ step_len = 30.0
312
+ iter_max = 250
313
+ vehicle_radius = 2.0
314
+
315
+ drrtstar = DubinsRRTStar(sx, sy, syaw, gx, gy, gyaw, vehicle_radius, step_len,
316
+ goal_sample_rate, search_radius, iter_max)
317
+ drrtstar.planning()
318
+
319
+
320
+ if __name__ == '__main__':
321
+ main()
@@ -0,0 +1,342 @@
1
+ """
2
+ DYNAMIC_RRT_2D
3
+ @author: damminhtien
4
+ """
5
+
6
+ import os
7
+ import sys
8
+ import math
9
+ import copy
10
+ import numpy as np
11
+ import matplotlib.pyplot as plt
12
+ import matplotlib.patches as patches
13
+
14
+ sys.path.append(os.path.dirname(os.path.abspath(__file__)) +
15
+ "/../../Sampling_based_Planning/")
16
+
17
+ from Sampling_based_Planning.rrt_2D import env, plotting, utils
18
+
19
+
20
+ class Node:
21
+ def __init__(self, n):
22
+ self.x = n[0]
23
+ self.y = n[1]
24
+ self.parent = None
25
+ self.flag = "VALID"
26
+
27
+
28
+ class Edge:
29
+ def __init__(self, n_p, n_c):
30
+ self.parent = n_p
31
+ self.child = n_c
32
+ self.flag = "VALID"
33
+
34
+
35
+ class DynamicRrt:
36
+ def __init__(self, s_start, s_goal, step_len, goal_sample_rate, waypoint_sample_rate, iter_max):
37
+ self.s_start = Node(s_start)
38
+ self.s_goal = Node(s_goal)
39
+ self.step_len = step_len
40
+ self.goal_sample_rate = goal_sample_rate
41
+ self.waypoint_sample_rate = waypoint_sample_rate
42
+ self.iter_max = iter_max
43
+ self.vertex = [self.s_start]
44
+ self.vertex_old = []
45
+ self.vertex_new = []
46
+ self.edges = []
47
+
48
+ self.env = env.Env()
49
+ self.plotting = plotting.Plotting(s_start, s_goal)
50
+ self.utils = utils.Utils()
51
+ self.fig, self.ax = plt.subplots()
52
+
53
+ self.x_range = self.env.x_range
54
+ self.y_range = self.env.y_range
55
+ self.obs_circle = self.env.obs_circle
56
+ self.obs_rectangle = self.env.obs_rectangle
57
+ self.obs_boundary = self.env.obs_boundary
58
+ self.obs_add = [0, 0, 0]
59
+
60
+ self.path = []
61
+ self.waypoint = []
62
+
63
+ def planning(self):
64
+ for i in range(self.iter_max):
65
+ node_rand = self.generate_random_node(self.goal_sample_rate)
66
+ node_near = self.nearest_neighbor(self.vertex, node_rand)
67
+ node_new = self.new_state(node_near, node_rand)
68
+
69
+ if node_new and not self.utils.is_collision(node_near, node_new):
70
+ self.vertex.append(node_new)
71
+ self.edges.append(Edge(node_near, node_new))
72
+ dist, _ = self.get_distance_and_angle(node_new, self.s_goal)
73
+
74
+ if dist <= self.step_len:
75
+ self.new_state(node_new, self.s_goal)
76
+
77
+ path = self.extract_path(node_new)
78
+ self.plot_grid("Dynamic_RRT")
79
+ self.plot_visited()
80
+ self.plot_path(path)
81
+ self.path = path
82
+ self.waypoint = self.extract_waypoint(node_new)
83
+ self.fig.canvas.mpl_connect('button_press_event', self.on_press)
84
+ plt.show()
85
+
86
+ return
87
+
88
+ return None
89
+
90
+ def on_press(self, event):
91
+ x, y = event.xdata, event.ydata
92
+ if x < 0 or x > 50 or y < 0 or y > 30:
93
+ print("Please choose right area!")
94
+ else:
95
+ x, y = int(x), int(y)
96
+ print("Add circle obstacle at: s =", x, ",", "y =", y)
97
+ self.obs_add = [x, y, 2]
98
+ self.obs_circle.append([x, y, 2])
99
+ self.utils.update_obs(self.obs_circle, self.obs_boundary, self.obs_rectangle)
100
+ self.InvalidateNodes()
101
+
102
+ if self.is_path_invalid():
103
+ print("Path is Replanning ...")
104
+ path, waypoint = self.replanning()
105
+
106
+ print("len_vertex: ", len(self.vertex))
107
+ print("len_vertex_old: ", len(self.vertex_old))
108
+ print("len_vertex_new: ", len(self.vertex_new))
109
+
110
+ plt.cla()
111
+ self.plot_grid("Dynamic_RRT")
112
+ self.plot_vertex_old()
113
+ self.plot_path(self.path, color='blue')
114
+ self.plot_vertex_new()
115
+ self.vertex_new = []
116
+ self.plot_path(path)
117
+ self.path = path
118
+ self.waypoint = waypoint
119
+ else:
120
+ print("Trimming Invalid Nodes ...")
121
+ self.TrimRRT()
122
+
123
+ plt.cla()
124
+ self.plot_grid("Dynamic_RRT")
125
+ self.plot_visited(animation=False)
126
+ self.plot_path(self.path)
127
+
128
+ self.fig.canvas.draw_idle()
129
+
130
+ def InvalidateNodes(self):
131
+ for edge in self.edges:
132
+ if self.is_collision_obs_add(edge.parent, edge.child):
133
+ edge.child.flag = "INVALID"
134
+
135
+ def is_path_invalid(self):
136
+ for node in self.waypoint:
137
+ if node.flag == "INVALID":
138
+ return True
139
+
140
+ def is_collision_obs_add(self, start, end):
141
+ delta = self.utils.delta
142
+ obs_add = self.obs_add
143
+
144
+ if math.hypot(start.x - obs_add[0], start.y - obs_add[1]) <= obs_add[2] + delta:
145
+ return True
146
+
147
+ if math.hypot(end.x - obs_add[0], end.y - obs_add[1]) <= obs_add[2] + delta:
148
+ return True
149
+
150
+ o, d = self.utils.get_ray(start, end)
151
+ if self.utils.is_intersect_circle(o, d, [obs_add[0], obs_add[1]], obs_add[2]):
152
+ return True
153
+
154
+ return False
155
+
156
+ def replanning(self):
157
+ self.TrimRRT()
158
+
159
+ for i in range(self.iter_max):
160
+ node_rand = self.generate_random_node_replanning(self.goal_sample_rate, self.waypoint_sample_rate)
161
+ node_near = self.nearest_neighbor(self.vertex, node_rand)
162
+ node_new = self.new_state(node_near, node_rand)
163
+
164
+ if node_new and not self.utils.is_collision(node_near, node_new):
165
+ self.vertex.append(node_new)
166
+ self.vertex_new.append(node_new)
167
+ self.edges.append(Edge(node_near, node_new))
168
+ dist, _ = self.get_distance_and_angle(node_new, self.s_goal)
169
+
170
+ if dist <= self.step_len:
171
+ self.new_state(node_new, self.s_goal)
172
+ path = self.extract_path(node_new)
173
+ waypoint = self.extract_waypoint(node_new)
174
+ print("path: ", len(path))
175
+ print("waypoint: ", len(waypoint))
176
+
177
+ return path, waypoint
178
+
179
+ return None
180
+
181
+ def TrimRRT(self):
182
+ for i in range(1, len(self.vertex)):
183
+ node = self.vertex[i]
184
+ node_p = node.parent
185
+ if node_p.flag == "INVALID":
186
+ node.flag = "INVALID"
187
+
188
+ self.vertex = [node for node in self.vertex if node.flag == "VALID"]
189
+ self.vertex_old = copy.deepcopy(self.vertex)
190
+ self.edges = [Edge(node.parent, node) for node in self.vertex[1:len(self.vertex)]]
191
+
192
+ def generate_random_node(self, goal_sample_rate):
193
+ delta = self.utils.delta
194
+
195
+ if np.random.random() > goal_sample_rate:
196
+ return Node((np.random.uniform(self.x_range[0] + delta, self.x_range[1] - delta),
197
+ np.random.uniform(self.y_range[0] + delta, self.y_range[1] - delta)))
198
+
199
+ return self.s_goal
200
+
201
+ def generate_random_node_replanning(self, goal_sample_rate, waypoint_sample_rate):
202
+ delta = self.utils.delta
203
+ p = np.random.random()
204
+
205
+ if p < goal_sample_rate:
206
+ return self.s_goal
207
+ elif goal_sample_rate < p < goal_sample_rate + waypoint_sample_rate:
208
+ return self.waypoint[np.random.randint(0, len(self.waypoint) - 1)]
209
+ else:
210
+ return Node((np.random.uniform(self.x_range[0] + delta, self.x_range[1] - delta),
211
+ np.random.uniform(self.y_range[0] + delta, self.y_range[1] - delta)))
212
+
213
+ @staticmethod
214
+ def nearest_neighbor(node_list, n):
215
+ return node_list[int(np.argmin([math.hypot(nd.x - n.x, nd.y - n.y)
216
+ for nd in node_list]))]
217
+
218
+ def new_state(self, node_start, node_end):
219
+ dist, theta = self.get_distance_and_angle(node_start, node_end)
220
+
221
+ dist = min(self.step_len, dist)
222
+ node_new = Node((node_start.x + dist * math.cos(theta),
223
+ node_start.y + dist * math.sin(theta)))
224
+ node_new.parent = node_start
225
+
226
+ return node_new
227
+
228
+ def extract_path(self, node_end):
229
+ path = [(self.s_goal.x, self.s_goal.y)]
230
+ node_now = node_end
231
+
232
+ while node_now.parent is not None:
233
+ node_now = node_now.parent
234
+ path.append((node_now.x, node_now.y))
235
+
236
+ return path
237
+
238
+ def extract_waypoint(self, node_end):
239
+ waypoint = [self.s_goal]
240
+ node_now = node_end
241
+
242
+ while node_now.parent is not None:
243
+ node_now = node_now.parent
244
+ waypoint.append(node_now)
245
+
246
+ return waypoint
247
+
248
+ @staticmethod
249
+ def get_distance_and_angle(node_start, node_end):
250
+ dx = node_end.x - node_start.x
251
+ dy = node_end.y - node_start.y
252
+ return math.hypot(dx, dy), math.atan2(dy, dx)
253
+
254
+ def plot_grid(self, name):
255
+
256
+ for (ox, oy, w, h) in self.obs_boundary:
257
+ self.ax.add_patch(
258
+ patches.Rectangle(
259
+ (ox, oy), w, h,
260
+ edgecolor='black',
261
+ facecolor='black',
262
+ fill=True
263
+ )
264
+ )
265
+
266
+ for (ox, oy, w, h) in self.obs_rectangle:
267
+ self.ax.add_patch(
268
+ patches.Rectangle(
269
+ (ox, oy), w, h,
270
+ edgecolor='black',
271
+ facecolor='gray',
272
+ fill=True
273
+ )
274
+ )
275
+
276
+ for (ox, oy, r) in self.obs_circle:
277
+ self.ax.add_patch(
278
+ patches.Circle(
279
+ (ox, oy), r,
280
+ edgecolor='black',
281
+ facecolor='gray',
282
+ fill=True
283
+ )
284
+ )
285
+
286
+ plt.plot(self.s_start.x, self.s_start.y, "bs", linewidth=3)
287
+ plt.plot(self.s_goal.x, self.s_goal.y, "gs", linewidth=3)
288
+
289
+ plt.title(name)
290
+ plt.axis("equal")
291
+
292
+ def plot_visited(self, animation=True):
293
+ if animation:
294
+ count = 0
295
+ for node in self.vertex:
296
+ count += 1
297
+ if node.parent:
298
+ plt.plot([node.parent.x, node.x], [node.parent.y, node.y], "-g")
299
+ plt.gcf().canvas.mpl_connect('key_release_event',
300
+ lambda event:
301
+ [exit(0) if event.key == 'escape' else None])
302
+ if count % 10 == 0:
303
+ plt.pause(0.001)
304
+ else:
305
+ for node in self.vertex:
306
+ if node.parent:
307
+ plt.plot([node.parent.x, node.x], [node.parent.y, node.y], "-g")
308
+
309
+ def plot_vertex_old(self):
310
+ for node in self.vertex_old:
311
+ if node.parent:
312
+ plt.plot([node.parent.x, node.x], [node.parent.y, node.y], "-g")
313
+
314
+ def plot_vertex_new(self):
315
+ count = 0
316
+
317
+ for node in self.vertex_new:
318
+ count += 1
319
+ if node.parent:
320
+ plt.plot([node.parent.x, node.x], [node.parent.y, node.y], color='darkorange')
321
+ plt.gcf().canvas.mpl_connect('key_release_event',
322
+ lambda event:
323
+ [exit(0) if event.key == 'escape' else None])
324
+ if count % 10 == 0:
325
+ plt.pause(0.001)
326
+
327
+ @staticmethod
328
+ def plot_path(path, color='red'):
329
+ plt.plot([x[0] for x in path], [x[1] for x in path], linewidth=2, color=color)
330
+ plt.pause(0.01)
331
+
332
+
333
+ def main():
334
+ x_start = (2, 2) # Starting node
335
+ x_goal = (49, 24) # Goal node
336
+
337
+ drrt = DynamicRrt(x_start, x_goal, 0.5, 0.1, 0.6, 5000)
338
+ drrt.planning()
339
+
340
+
341
+ if __name__ == '__main__':
342
+ main()
@@ -0,0 +1,45 @@
1
+ """
2
+ Environment for rrt_2D
3
+ @author: damminhtien
4
+ """
5
+
6
+
7
+ class Env:
8
+ def __init__(self):
9
+ self.x_range = (0, 50)
10
+ self.y_range = (0, 30)
11
+ self.obs_boundary = self.obs_boundary()
12
+ self.obs_circle = self.obs_circle()
13
+ self.obs_rectangle = self.obs_rectangle()
14
+
15
+ @staticmethod
16
+ def obs_boundary():
17
+ obs_boundary = [
18
+ [0, 0, 1, 30],
19
+ [0, 30, 50, 1],
20
+ [1, 0, 50, 1],
21
+ [50, 1, 1, 30]
22
+ ]
23
+ return obs_boundary
24
+
25
+ @staticmethod
26
+ def obs_rectangle():
27
+ obs_rectangle = [
28
+ [14, 12, 8, 2],
29
+ [18, 22, 8, 3],
30
+ [26, 7, 2, 12],
31
+ [32, 14, 10, 2]
32
+ ]
33
+ return obs_rectangle
34
+
35
+ @staticmethod
36
+ def obs_circle():
37
+ obs_cir = [
38
+ [7, 12, 3],
39
+ [46, 20, 2],
40
+ [15, 5, 2],
41
+ [37, 7, 3],
42
+ [37, 23, 3]
43
+ ]
44
+
45
+ return obs_cir