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,351 @@
1
+ """
2
+ Dubins Path
3
+ """
4
+
5
+ import math
6
+ import numpy as np
7
+ import matplotlib.pyplot as plt
8
+ from scipy.spatial.transform import Rotation as Rot
9
+ import CurvesGenerator.draw as draw
10
+
11
+
12
+ # class for PATH element
13
+ class PATH:
14
+ def __init__(self, L, mode, x, y, yaw):
15
+ self.L = L # total path length [float]
16
+ self.mode = mode # type of each part of the path [string]
17
+ self.x = x # final s positions [m]
18
+ self.y = y # final y positions [m]
19
+ self.yaw = yaw # final yaw angles [rad]
20
+
21
+
22
+ # utils
23
+ def pi_2_pi(theta):
24
+ while theta > math.pi:
25
+ theta -= 2.0 * math.pi
26
+
27
+ while theta < -math.pi:
28
+ theta += 2.0 * math.pi
29
+
30
+ return theta
31
+
32
+
33
+ def mod2pi(theta):
34
+ return theta - 2.0 * math.pi * math.floor(theta / math.pi / 2.0)
35
+
36
+
37
+ def LSL(alpha, beta, dist):
38
+ sin_a = math.sin(alpha)
39
+ sin_b = math.sin(beta)
40
+ cos_a = math.cos(alpha)
41
+ cos_b = math.cos(beta)
42
+ cos_a_b = math.cos(alpha - beta)
43
+
44
+ p_lsl = 2 + dist ** 2 - 2 * cos_a_b + 2 * dist * (sin_a - sin_b)
45
+
46
+ if p_lsl < 0:
47
+ return None, None, None, ["L", "S", "L"]
48
+ else:
49
+ p_lsl = math.sqrt(p_lsl)
50
+
51
+ denominate = dist + sin_a - sin_b
52
+ t_lsl = mod2pi(-alpha + math.atan2(cos_b - cos_a, denominate))
53
+ q_lsl = mod2pi(beta - math.atan2(cos_b - cos_a, denominate))
54
+
55
+ return t_lsl, p_lsl, q_lsl, ["L", "S", "L"]
56
+
57
+
58
+ def RSR(alpha, beta, dist):
59
+ sin_a = math.sin(alpha)
60
+ sin_b = math.sin(beta)
61
+ cos_a = math.cos(alpha)
62
+ cos_b = math.cos(beta)
63
+ cos_a_b = math.cos(alpha - beta)
64
+
65
+ p_rsr = 2 + dist ** 2 - 2 * cos_a_b + 2 * dist * (sin_b - sin_a)
66
+
67
+ if p_rsr < 0:
68
+ return None, None, None, ["R", "S", "R"]
69
+ else:
70
+ p_rsr = math.sqrt(p_rsr)
71
+
72
+ denominate = dist - sin_a + sin_b
73
+ t_rsr = mod2pi(alpha - math.atan2(cos_a - cos_b, denominate))
74
+ q_rsr = mod2pi(-beta + math.atan2(cos_a - cos_b, denominate))
75
+
76
+ return t_rsr, p_rsr, q_rsr, ["R", "S", "R"]
77
+
78
+
79
+ def LSR(alpha, beta, dist):
80
+ sin_a = math.sin(alpha)
81
+ sin_b = math.sin(beta)
82
+ cos_a = math.cos(alpha)
83
+ cos_b = math.cos(beta)
84
+ cos_a_b = math.cos(alpha - beta)
85
+
86
+ p_lsr = -2 + dist ** 2 + 2 * cos_a_b + 2 * dist * (sin_a + sin_b)
87
+
88
+ if p_lsr < 0:
89
+ return None, None, None, ["L", "S", "R"]
90
+ else:
91
+ p_lsr = math.sqrt(p_lsr)
92
+
93
+ rec = math.atan2(-cos_a - cos_b, dist + sin_a + sin_b) - math.atan2(-2.0, p_lsr)
94
+ t_lsr = mod2pi(-alpha + rec)
95
+ q_lsr = mod2pi(-mod2pi(beta) + rec)
96
+
97
+ return t_lsr, p_lsr, q_lsr, ["L", "S", "R"]
98
+
99
+
100
+ def RSL(alpha, beta, dist):
101
+ sin_a = math.sin(alpha)
102
+ sin_b = math.sin(beta)
103
+ cos_a = math.cos(alpha)
104
+ cos_b = math.cos(beta)
105
+ cos_a_b = math.cos(alpha - beta)
106
+
107
+ p_rsl = -2 + dist ** 2 + 2 * cos_a_b - 2 * dist * (sin_a + sin_b)
108
+
109
+ if p_rsl < 0:
110
+ return None, None, None, ["R", "S", "L"]
111
+ else:
112
+ p_rsl = math.sqrt(p_rsl)
113
+
114
+ rec = math.atan2(cos_a + cos_b, dist - sin_a - sin_b) - math.atan2(2.0, p_rsl)
115
+ t_rsl = mod2pi(alpha - rec)
116
+ q_rsl = mod2pi(beta - rec)
117
+
118
+ return t_rsl, p_rsl, q_rsl, ["R", "S", "L"]
119
+
120
+
121
+ def RLR(alpha, beta, dist):
122
+ sin_a = math.sin(alpha)
123
+ sin_b = math.sin(beta)
124
+ cos_a = math.cos(alpha)
125
+ cos_b = math.cos(beta)
126
+ cos_a_b = math.cos(alpha - beta)
127
+
128
+ rec = (6.0 - dist ** 2 + 2.0 * cos_a_b + 2.0 * dist * (sin_a - sin_b)) / 8.0
129
+
130
+ if abs(rec) > 1.0:
131
+ return None, None, None, ["R", "L", "R"]
132
+
133
+ p_rlr = mod2pi(2 * math.pi - math.acos(rec))
134
+ t_rlr = mod2pi(alpha - math.atan2(cos_a - cos_b, dist - sin_a + sin_b) + mod2pi(p_rlr / 2.0))
135
+ q_rlr = mod2pi(alpha - beta - t_rlr + mod2pi(p_rlr))
136
+
137
+ return t_rlr, p_rlr, q_rlr, ["R", "L", "R"]
138
+
139
+
140
+ def LRL(alpha, beta, dist):
141
+ sin_a = math.sin(alpha)
142
+ sin_b = math.sin(beta)
143
+ cos_a = math.cos(alpha)
144
+ cos_b = math.cos(beta)
145
+ cos_a_b = math.cos(alpha - beta)
146
+
147
+ rec = (6.0 - dist ** 2 + 2.0 * cos_a_b + 2.0 * dist * (sin_b - sin_a)) / 8.0
148
+
149
+ if abs(rec) > 1.0:
150
+ return None, None, None, ["L", "R", "L"]
151
+
152
+ p_lrl = mod2pi(2 * math.pi - math.acos(rec))
153
+ t_lrl = mod2pi(-alpha - math.atan2(cos_a - cos_b, dist + sin_a - sin_b) + p_lrl / 2.0)
154
+ q_lrl = mod2pi(mod2pi(beta) - alpha - t_lrl + mod2pi(p_lrl))
155
+
156
+ return t_lrl, p_lrl, q_lrl, ["L", "R", "L"]
157
+
158
+
159
+ def interpolate(ind, l, m, maxc, ox, oy, oyaw, px, py, pyaw, directions):
160
+ if m == "S":
161
+ px[ind] = ox + l / maxc * math.cos(oyaw)
162
+ py[ind] = oy + l / maxc * math.sin(oyaw)
163
+ pyaw[ind] = oyaw
164
+ else:
165
+ ldx = math.sin(l) / maxc
166
+ if m == "L":
167
+ ldy = (1.0 - math.cos(l)) / maxc
168
+ elif m == "R":
169
+ ldy = (1.0 - math.cos(l)) / (-maxc)
170
+
171
+ gdx = math.cos(-oyaw) * ldx + math.sin(-oyaw) * ldy
172
+ gdy = -math.sin(-oyaw) * ldx + math.cos(-oyaw) * ldy
173
+ px[ind] = ox + gdx
174
+ py[ind] = oy + gdy
175
+
176
+ if m == "L":
177
+ pyaw[ind] = oyaw + l
178
+ elif m == "R":
179
+ pyaw[ind] = oyaw - l
180
+
181
+ if l > 0.0:
182
+ directions[ind] = 1
183
+ else:
184
+ directions[ind] = -1
185
+
186
+ return px, py, pyaw, directions
187
+
188
+
189
+ def generate_local_course(L, lengths, mode, maxc, step_size):
190
+ point_num = int(L / step_size) + len(lengths) + 3
191
+
192
+ px = [0.0 for _ in range(point_num)]
193
+ py = [0.0 for _ in range(point_num)]
194
+ pyaw = [0.0 for _ in range(point_num)]
195
+ directions = [0 for _ in range(point_num)]
196
+ ind = 1
197
+
198
+ if lengths[0] > 0.0:
199
+ directions[0] = 1
200
+ else:
201
+ directions[0] = -1
202
+
203
+ if lengths[0] > 0.0:
204
+ d = step_size
205
+ else:
206
+ d = -step_size
207
+
208
+ ll = 0.0
209
+
210
+ for m, l, i in zip(mode, lengths, range(len(mode))):
211
+ if l > 0.0:
212
+ d = step_size
213
+ else:
214
+ d = -step_size
215
+
216
+ ox, oy, oyaw = px[ind], py[ind], pyaw[ind]
217
+
218
+ ind -= 1
219
+ if i >= 1 and (lengths[i - 1] * lengths[i]) > 0:
220
+ pd = -d - ll
221
+ else:
222
+ pd = d - ll
223
+
224
+ while abs(pd) <= abs(l):
225
+ ind += 1
226
+ px, py, pyaw, directions = \
227
+ interpolate(ind, pd, m, maxc, ox, oy, oyaw, px, py, pyaw, directions)
228
+ pd += d
229
+
230
+ ll = l - pd - d # calc remain length
231
+
232
+ ind += 1
233
+ px, py, pyaw, directions = \
234
+ interpolate(ind, l, m, maxc, ox, oy, oyaw, px, py, pyaw, directions)
235
+
236
+ if len(px) <= 1:
237
+ return [], [], [], []
238
+
239
+ # remove unused data
240
+ while len(px) >= 1 and px[-1] == 0.0:
241
+ px.pop()
242
+ py.pop()
243
+ pyaw.pop()
244
+ directions.pop()
245
+
246
+ return px, py, pyaw, directions
247
+
248
+
249
+ def planning_from_origin(gx, gy, gyaw, curv, step_size):
250
+ D = math.hypot(gx, gy)
251
+ d = D * curv
252
+
253
+ theta = mod2pi(math.atan2(gy, gx))
254
+ alpha = mod2pi(-theta)
255
+ beta = mod2pi(gyaw - theta)
256
+
257
+ planners = [LSL, RSR, LSR, RSL, RLR, LRL]
258
+
259
+ best_cost = float("inf")
260
+ bt, bp, bq, best_mode = None, None, None, None
261
+
262
+ for planner in planners:
263
+ t, p, q, mode = planner(alpha, beta, d)
264
+
265
+ if t is None:
266
+ continue
267
+
268
+ cost = (abs(t) + abs(p) + abs(q))
269
+ if best_cost > cost:
270
+ bt, bp, bq, best_mode = t, p, q, mode
271
+ best_cost = cost
272
+ lengths = [bt, bp, bq]
273
+
274
+ x_list, y_list, yaw_list, directions = generate_local_course(
275
+ sum(lengths), lengths, best_mode, curv, step_size)
276
+
277
+ return x_list, y_list, yaw_list, best_mode, best_cost
278
+
279
+
280
+ def calc_dubins_path(sx, sy, syaw, gx, gy, gyaw, curv, step_size=0.1):
281
+ gx = gx - sx
282
+ gy = gy - sy
283
+
284
+ l_rot = Rot.from_euler('z', syaw).as_dcm()[0:2, 0:2]
285
+ le_xy = np.stack([gx, gy]).T @ l_rot
286
+ le_yaw = gyaw - syaw
287
+
288
+ lp_x, lp_y, lp_yaw, mode, lengths = planning_from_origin(
289
+ le_xy[0], le_xy[1], le_yaw, curv, step_size)
290
+
291
+ rot = Rot.from_euler('z', -syaw).as_dcm()[0:2, 0:2]
292
+ converted_xy = np.stack([lp_x, lp_y]).T @ rot
293
+ x_list = converted_xy[:, 0] + sx
294
+ y_list = converted_xy[:, 1] + sy
295
+ yaw_list = [pi_2_pi(i_yaw + syaw) for i_yaw in lp_yaw]
296
+
297
+ return PATH(lengths, mode, x_list, y_list, yaw_list)
298
+
299
+
300
+ def main():
301
+ # choose states pairs: (s, y, yaw)
302
+ # simulation-1
303
+ states = [(0, 0, 0), (10, 10, -90), (20, 5, 60), (30, 10, 120),
304
+ (35, -5, 30), (25, -10, -120), (15, -15, 100), (0, -10, -90)]
305
+
306
+ # simulation-2
307
+ # states = [(-3, 3, 120), (10, -7, 30), (10, 13, 30), (20, 5, -25),
308
+ # (35, 10, 180), (32, -10, 180), (5, -12, 90)]
309
+
310
+ max_c = 0.25 # max curvature
311
+ path_x, path_y, yaw = [], [], []
312
+
313
+ for i in range(len(states) - 1):
314
+ s_x = states[i][0]
315
+ s_y = states[i][1]
316
+ s_yaw = np.deg2rad(states[i][2])
317
+ g_x = states[i + 1][0]
318
+ g_y = states[i + 1][1]
319
+ g_yaw = np.deg2rad(states[i + 1][2])
320
+
321
+ path_i = calc_dubins_path(s_x, s_y, s_yaw, g_x, g_y, g_yaw, max_c)
322
+
323
+ for x, y, iyaw in zip(path_i.x, path_i.y, path_i.yaw):
324
+ path_x.append(x)
325
+ path_y.append(y)
326
+ yaw.append(iyaw)
327
+
328
+ # animation
329
+ plt.ion()
330
+ plt.figure(1)
331
+
332
+ for i in range(len(path_x)):
333
+ plt.clf()
334
+ plt.plot(path_x, path_y, linewidth=1, color='gray')
335
+
336
+ for x, y, theta in states:
337
+ draw.Arrow(x, y, np.deg2rad(theta), 2, 'blueviolet')
338
+
339
+ draw.Car(path_x[i], path_y[i], yaw[i], 1.5, 3)
340
+
341
+ plt.axis("equal")
342
+ plt.title("Simulation of Dubins Path")
343
+ plt.axis([-10, 42, -20, 20])
344
+ plt.draw()
345
+ plt.pause(0.001)
346
+
347
+ plt.pause(1)
348
+
349
+
350
+ if __name__ == '__main__':
351
+ main()
@@ -0,0 +1,43 @@
1
+ """
2
+ Quartic Polynomial
3
+ """
4
+
5
+ import numpy as np
6
+
7
+
8
+ class QuarticPolynomial:
9
+ def __init__(self, x0, v0, a0, v1, a1, T):
10
+ A = np.array([[3 * T ** 2, 4 * T ** 3],
11
+ [6 * T, 12 * T ** 2]])
12
+ b = np.array([v1 - v0 - a0 * T,
13
+ a1 - a0])
14
+ X = np.linalg.solve(A, b)
15
+
16
+ self.a0 = x0
17
+ self.a1 = v0
18
+ self.a2 = a0 / 2.0
19
+ self.a3 = X[0]
20
+ self.a4 = X[1]
21
+
22
+ def calc_xt(self, t):
23
+ xt = self.a0 + self.a1 * t + self.a2 * t ** 2 + \
24
+ self.a3 * t ** 3 + self.a4 * t ** 4
25
+
26
+ return xt
27
+
28
+ def calc_dxt(self, t):
29
+ xt = self.a1 + 2 * self.a2 * t + \
30
+ 3 * self.a3 * t ** 2 + 4 * self.a4 * t ** 3
31
+
32
+ return xt
33
+
34
+ def calc_ddxt(self, t):
35
+ xt = 2 * self.a2 + 6 * self.a3 * t + 12 * self.a4 * t ** 2
36
+
37
+ return xt
38
+
39
+ def calc_dddxt(self, t):
40
+ xt = 6 * self.a3 + 24 * self.a4 * t
41
+
42
+ return xt
43
+
@@ -0,0 +1,143 @@
1
+ """
2
+ Quintic Polynomial
3
+ """
4
+
5
+ import math
6
+ import numpy as np
7
+ import matplotlib.pyplot as plt
8
+
9
+ import draw
10
+
11
+
12
+ class QuinticPolynomial:
13
+ def __init__(self, x0, v0, a0, x1, v1, a1, T):
14
+ A = np.array([[T ** 3, T ** 4, T ** 5],
15
+ [3 * T ** 2, 4 * T ** 3, 5 * T ** 4],
16
+ [6 * T, 12 * T ** 2, 20 * T ** 3]])
17
+ b = np.array([x1 - x0 - v0 * T - a0 * T ** 2 / 2,
18
+ v1 - v0 - a0 * T,
19
+ a1 - a0])
20
+ X = np.linalg.solve(A, b)
21
+
22
+ self.a0 = x0
23
+ self.a1 = v0
24
+ self.a2 = a0 / 2.0
25
+ self.a3 = X[0]
26
+ self.a4 = X[1]
27
+ self.a5 = X[2]
28
+
29
+ def calc_xt(self, t):
30
+ xt = self.a0 + self.a1 * t + self.a2 * t ** 2 + \
31
+ self.a3 * t ** 3 + self.a4 * t ** 4 + self.a5 * t ** 5
32
+
33
+ return xt
34
+
35
+ def calc_dxt(self, t):
36
+ dxt = self.a1 + 2 * self.a2 * t + \
37
+ 3 * self.a3 * t ** 2 + 4 * self.a4 * t ** 3 + 5 * self.a5 * t ** 4
38
+
39
+ return dxt
40
+
41
+ def calc_ddxt(self, t):
42
+ ddxt = 2 * self.a2 + 6 * self.a3 * t + 12 * self.a4 * t ** 2 + 20 * self.a5 * t ** 3
43
+
44
+ return ddxt
45
+
46
+ def calc_dddxt(self, t):
47
+ dddxt = 6 * self.a3 + 24 * self.a4 * t + 60 * self.a5 * t ** 2
48
+
49
+ return dddxt
50
+
51
+
52
+ class Trajectory:
53
+ def __init__(self):
54
+ self.t = []
55
+ self.x = []
56
+ self.y = []
57
+ self.yaw = []
58
+ self.v = []
59
+ self.a = []
60
+ self.jerk = []
61
+
62
+
63
+ def simulation():
64
+ sx, sy, syaw, sv, sa = 10.0, 10.0, np.deg2rad(10.0), 1.0, 0.1
65
+ gx, gy, gyaw, gv, ga = 30.0, -10.0, np.deg2rad(180.0), 1.0, 0.1
66
+
67
+ MAX_ACCEL = 1.0 # max accel [m/s2]
68
+ MAX_JERK = 0.5 # max jerk [m/s3]
69
+ dt = 0.1 # T tick [s]
70
+
71
+ MIN_T = 5
72
+ MAX_T = 100
73
+ T_STEP = 5
74
+
75
+ sv_x = sv * math.cos(syaw)
76
+ sv_y = sv * math.sin(syaw)
77
+ gv_x = gv * math.cos(gyaw)
78
+ gv_y = gv * math.sin(gyaw)
79
+
80
+ sa_x = sa * math.cos(syaw)
81
+ sa_y = sa * math.sin(syaw)
82
+ ga_x = ga * math.cos(gyaw)
83
+ ga_y = ga * math.sin(gyaw)
84
+
85
+ path = Trajectory()
86
+
87
+ for T in np.arange(MIN_T, MAX_T, T_STEP):
88
+ path = Trajectory()
89
+ xqp = QuinticPolynomial(sx, sv_x, sa_x, gx, gv_x, ga_x, T)
90
+ yqp = QuinticPolynomial(sy, sv_y, sa_y, gy, gv_y, ga_y, T)
91
+
92
+ for t in np.arange(0.0, T + dt, dt):
93
+ path.t.append(t)
94
+ path.x.append(xqp.calc_xt(t))
95
+ path.y.append(yqp.calc_xt(t))
96
+
97
+ vx = xqp.calc_dxt(t)
98
+ vy = yqp.calc_dxt(t)
99
+ path.v.append(np.hypot(vx, vy))
100
+ path.yaw.append(math.atan2(vy, vx))
101
+
102
+ ax = xqp.calc_ddxt(t)
103
+ ay = yqp.calc_ddxt(t)
104
+ a = np.hypot(ax, ay)
105
+
106
+ if len(path.v) >= 2 and path.v[-1] - path.v[-2] < 0.0:
107
+ a *= -1
108
+ path.a.append(a)
109
+
110
+ jx = xqp.calc_dddxt(t)
111
+ jy = yqp.calc_dddxt(t)
112
+ j = np.hypot(jx, jy)
113
+
114
+ if len(path.a) >= 2 and path.a[-1] - path.a[-2] < 0.0:
115
+ j *= -1
116
+ path.jerk.append(j)
117
+
118
+ if max(np.abs(path.a)) <= MAX_ACCEL and max(np.abs(path.jerk)) <= MAX_JERK:
119
+ break
120
+
121
+ print("t_len: ", path.t, "s")
122
+ print("max_v: ", max(path.v), "m/s")
123
+ print("max_a: ", max(np.abs(path.a)), "m/s2")
124
+ print("max_jerk: ", max(np.abs(path.jerk)), "m/s3")
125
+
126
+ for i in range(len(path.t)):
127
+ plt.cla()
128
+ plt.gcf().canvas.mpl_connect('key_release_event',
129
+ lambda event: [exit(0) if event.key == 'escape' else None])
130
+ plt.axis("equal")
131
+ plt.plot(path.x, path.y, linewidth=2, color='gray')
132
+ draw.Car(sx, sy, syaw, 1.5, 3)
133
+ draw.Car(gx, gy, gyaw, 1.5, 3)
134
+ draw.Car(path.x[i], path.y[i], path.yaw[i], 1.5, 3)
135
+ plt.title("Quintic Polynomial Curves")
136
+ plt.grid(True)
137
+ plt.pause(0.001)
138
+
139
+ plt.show()
140
+
141
+
142
+ if __name__ == '__main__':
143
+ simulation()