reeds_shepp.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688
  1. import time
  2. import math
  3. import numpy as np
  4. # parameters initiation
  5. STEP_SIZE = 0.2
  6. MAX_LENGTH = 1000.0
  7. PI = math.pi
  8. # class for PATH element
  9. class PATH:
  10. def __init__(self, lengths, ctypes, L, x, y, yaw, directions):
  11. self.lengths = lengths # lengths of each part of path (+: forward, -: backward) [float]
  12. self.ctypes = ctypes # type of each part of the path [string]
  13. self.L = L # total path length [float]
  14. self.x = x # final x positions [m]
  15. self.y = y # final y positions [m]
  16. self.yaw = yaw # final yaw angles [rad]
  17. self.directions = directions # forward: 1, backward:-1
  18. def calc_optimal_path(sx, sy, syaw, gx, gy, gyaw, maxc, step_size=STEP_SIZE):
  19. paths = calc_all_paths(sx, sy, syaw, gx, gy, gyaw, maxc, step_size=step_size)
  20. minL = paths[0].L
  21. mini = 0
  22. for i in range(len(paths)):
  23. if paths[i].L <= minL:
  24. minL, mini = paths[i].L, i
  25. return paths[mini]
  26. def calc_all_paths(sx, sy, syaw, gx, gy, gyaw, maxc, step_size=STEP_SIZE):
  27. q0 = [sx, sy, syaw]
  28. q1 = [gx, gy, gyaw]
  29. paths = generate_path(q0, q1, maxc)
  30. for path in paths:
  31. x, y, yaw, directions = \
  32. generate_local_course(path.L, path.lengths,
  33. path.ctypes, maxc, step_size * maxc)
  34. # convert global coordinate
  35. path.x = [math.cos(-q0[2]) * ix + math.sin(-q0[2]) * iy + q0[0] for (ix, iy) in zip(x, y)]
  36. path.y = [-math.sin(-q0[2]) * ix + math.cos(-q0[2]) * iy + q0[1] for (ix, iy) in zip(x, y)]
  37. path.yaw = [pi_2_pi(iyaw + q0[2]) for iyaw in yaw]
  38. path.directions = directions
  39. path.lengths = [l / maxc for l in path.lengths]
  40. path.L = path.L / maxc
  41. return paths
  42. def set_path(paths, lengths, ctypes):
  43. path = PATH([], [], 0.0, [], [], [], [])
  44. path.ctypes = ctypes
  45. path.lengths = lengths
  46. # check same path exist
  47. for path_e in paths:
  48. if path_e.ctypes == path.ctypes:
  49. if sum([x - y for x, y in zip(path_e.lengths, path.lengths)]) <= 0.01:
  50. return paths # not insert path
  51. path.L = sum([abs(i) for i in lengths])
  52. if path.L >= MAX_LENGTH:
  53. return paths
  54. assert path.L >= 0.01
  55. paths.append(path)
  56. return paths
  57. def LSL(x, y, phi):
  58. u, t = R(x - math.sin(phi), y - 1.0 + math.cos(phi))
  59. if t >= 0.0:
  60. v = M(phi - t)
  61. if v >= 0.0:
  62. return True, t, u, v
  63. return False, 0.0, 0.0, 0.0
  64. def LSR(x, y, phi):
  65. u1, t1 = R(x + math.sin(phi), y - 1.0 - math.cos(phi))
  66. u1 = u1 ** 2
  67. if u1 >= 4.0:
  68. u = math.sqrt(u1 - 4.0)
  69. theta = math.atan2(2.0, u)
  70. t = M(t1 + theta)
  71. v = M(t - phi)
  72. if t >= 0.0 and v >= 0.0:
  73. return True, t, u, v
  74. return False, 0.0, 0.0, 0.0
  75. def LRL(x, y, phi):
  76. u1, t1 = R(x - math.sin(phi), y - 1.0 + math.cos(phi))
  77. if u1 <= 4.0:
  78. u = -2.0 * math.asin(0.25 * u1)
  79. t = M(t1 + 0.5 * u + PI)
  80. v = M(phi - t + u)
  81. if t >= 0.0 and u <= 0.0:
  82. return True, t, u, v
  83. return False, 0.0, 0.0, 0.0
  84. def SCS(x, y, phi, paths):
  85. flag, t, u, v = SLS(x, y, phi)
  86. if flag:
  87. paths = set_path(paths, [t, u, v], ["S", "WB", "S"])
  88. flag, t, u, v = SLS(x, -y, -phi)
  89. if flag:
  90. paths = set_path(paths, [t, u, v], ["S", "R", "S"])
  91. return paths
  92. def SLS(x, y, phi):
  93. phi = M(phi)
  94. if y > 0.0 and 0.0 < phi < PI * 0.99:
  95. xd = -y / math.tan(phi) + x
  96. t = xd - math.tan(phi / 2.0)
  97. u = phi
  98. v = math.sqrt((x - xd) ** 2 + y ** 2) - math.tan(phi / 2.0)
  99. return True, t, u, v
  100. elif y < 0.0 and 0.0 < phi < PI * 0.99:
  101. xd = -y / math.tan(phi) + x
  102. t = xd - math.tan(phi / 2.0)
  103. u = phi
  104. v = -math.sqrt((x - xd) ** 2 + y ** 2) - math.tan(phi / 2.0)
  105. return True, t, u, v
  106. return False, 0.0, 0.0, 0.0
  107. def CSC(x, y, phi, paths):
  108. flag, t, u, v = LSL(x, y, phi)
  109. if flag:
  110. paths = set_path(paths, [t, u, v], ["WB", "S", "WB"])
  111. flag, t, u, v = LSL(-x, y, -phi)
  112. if flag:
  113. paths = set_path(paths, [-t, -u, -v], ["WB", "S", "WB"])
  114. flag, t, u, v = LSL(x, -y, -phi)
  115. if flag:
  116. paths = set_path(paths, [t, u, v], ["R", "S", "R"])
  117. flag, t, u, v = LSL(-x, -y, phi)
  118. if flag:
  119. paths = set_path(paths, [-t, -u, -v], ["R", "S", "R"])
  120. flag, t, u, v = LSR(x, y, phi)
  121. if flag:
  122. paths = set_path(paths, [t, u, v], ["WB", "S", "R"])
  123. flag, t, u, v = LSR(-x, y, -phi)
  124. if flag:
  125. paths = set_path(paths, [-t, -u, -v], ["WB", "S", "R"])
  126. flag, t, u, v = LSR(x, -y, -phi)
  127. if flag:
  128. paths = set_path(paths, [t, u, v], ["R", "S", "WB"])
  129. flag, t, u, v = LSR(-x, -y, phi)
  130. if flag:
  131. paths = set_path(paths, [-t, -u, -v], ["R", "S", "WB"])
  132. return paths
  133. def CCC(x, y, phi, paths):
  134. flag, t, u, v = LRL(x, y, phi)
  135. if flag:
  136. paths = set_path(paths, [t, u, v], ["WB", "R", "WB"])
  137. flag, t, u, v = LRL(-x, y, -phi)
  138. if flag:
  139. paths = set_path(paths, [-t, -u, -v], ["WB", "R", "WB"])
  140. flag, t, u, v = LRL(x, -y, -phi)
  141. if flag:
  142. paths = set_path(paths, [t, u, v], ["R", "WB", "R"])
  143. flag, t, u, v = LRL(-x, -y, phi)
  144. if flag:
  145. paths = set_path(paths, [-t, -u, -v], ["R", "WB", "R"])
  146. # backwards
  147. xb = x * math.cos(phi) + y * math.sin(phi)
  148. yb = x * math.sin(phi) - y * math.cos(phi)
  149. flag, t, u, v = LRL(xb, yb, phi)
  150. if flag:
  151. paths = set_path(paths, [v, u, t], ["WB", "R", "WB"])
  152. flag, t, u, v = LRL(-xb, yb, -phi)
  153. if flag:
  154. paths = set_path(paths, [-v, -u, -t], ["WB", "R", "WB"])
  155. flag, t, u, v = LRL(xb, -yb, -phi)
  156. if flag:
  157. paths = set_path(paths, [v, u, t], ["R", "WB", "R"])
  158. flag, t, u, v = LRL(-xb, -yb, phi)
  159. if flag:
  160. paths = set_path(paths, [-v, -u, -t], ["R", "WB", "R"])
  161. return paths
  162. def calc_tauOmega(u, v, xi, eta, phi):
  163. delta = M(u - v)
  164. A = math.sin(u) - math.sin(delta)
  165. B = math.cos(u) - math.cos(delta) - 1.0
  166. t1 = math.atan2(eta * A - xi * B, xi * A + eta * B)
  167. t2 = 2.0 * (math.cos(delta) - math.cos(v) - math.cos(u)) + 3.0
  168. if t2 < 0:
  169. tau = M(t1 + PI)
  170. else:
  171. tau = M(t1)
  172. omega = M(tau - u + v - phi)
  173. return tau, omega
  174. def LRLRn(x, y, phi):
  175. xi = x + math.sin(phi)
  176. eta = y - 1.0 - math.cos(phi)
  177. rho = 0.25 * (2.0 + math.sqrt(xi * xi + eta * eta))
  178. if rho <= 1.0:
  179. u = math.acos(rho)
  180. t, v = calc_tauOmega(u, -u, xi, eta, phi)
  181. if t >= 0.0 and v <= 0.0:
  182. return True, t, u, v
  183. return False, 0.0, 0.0, 0.0
  184. def LRLRp(x, y, phi):
  185. xi = x + math.sin(phi)
  186. eta = y - 1.0 - math.cos(phi)
  187. rho = (20.0 - xi * xi - eta * eta) / 16.0
  188. if 0.0 <= rho <= 1.0:
  189. u = -math.acos(rho)
  190. if u >= -0.5 * PI:
  191. t, v = calc_tauOmega(u, u, xi, eta, phi)
  192. if t >= 0.0 and v >= 0.0:
  193. return True, t, u, v
  194. return False, 0.0, 0.0, 0.0
  195. def CCCC(x, y, phi, paths):
  196. flag, t, u, v = LRLRn(x, y, phi)
  197. if flag:
  198. paths = set_path(paths, [t, u, -u, v], ["WB", "R", "WB", "R"])
  199. flag, t, u, v = LRLRn(-x, y, -phi)
  200. if flag:
  201. paths = set_path(paths, [-t, -u, u, -v], ["WB", "R", "WB", "R"])
  202. flag, t, u, v = LRLRn(x, -y, -phi)
  203. if flag:
  204. paths = set_path(paths, [t, u, -u, v], ["R", "WB", "R", "WB"])
  205. flag, t, u, v = LRLRn(-x, -y, phi)
  206. if flag:
  207. paths = set_path(paths, [-t, -u, u, -v], ["R", "WB", "R", "WB"])
  208. flag, t, u, v = LRLRp(x, y, phi)
  209. if flag:
  210. paths = set_path(paths, [t, u, u, v], ["WB", "R", "WB", "R"])
  211. flag, t, u, v = LRLRp(-x, y, -phi)
  212. if flag:
  213. paths = set_path(paths, [-t, -u, -u, -v], ["WB", "R", "WB", "R"])
  214. flag, t, u, v = LRLRp(x, -y, -phi)
  215. if flag:
  216. paths = set_path(paths, [t, u, u, v], ["R", "WB", "R", "WB"])
  217. flag, t, u, v = LRLRp(-x, -y, phi)
  218. if flag:
  219. paths = set_path(paths, [-t, -u, -u, -v], ["R", "WB", "R", "WB"])
  220. return paths
  221. def LRSR(x, y, phi):
  222. xi = x + math.sin(phi)
  223. eta = y - 1.0 - math.cos(phi)
  224. rho, theta = R(-eta, xi)
  225. if rho >= 2.0:
  226. t = theta
  227. u = 2.0 - rho
  228. v = M(t + 0.5 * PI - phi)
  229. if t >= 0.0 and u <= 0.0 and v <= 0.0:
  230. return True, t, u, v
  231. return False, 0.0, 0.0, 0.0
  232. def LRSL(x, y, phi):
  233. xi = x - math.sin(phi)
  234. eta = y - 1.0 + math.cos(phi)
  235. rho, theta = R(xi, eta)
  236. if rho >= 2.0:
  237. r = math.sqrt(rho * rho - 4.0)
  238. u = 2.0 - r
  239. t = M(theta + math.atan2(r, -2.0))
  240. v = M(phi - 0.5 * PI - t)
  241. if t >= 0.0 and u <= 0.0 and v <= 0.0:
  242. return True, t, u, v
  243. return False, 0.0, 0.0, 0.0
  244. def CCSC(x, y, phi, paths):
  245. flag, t, u, v = LRSL(x, y, phi)
  246. if flag:
  247. paths = set_path(paths, [t, -0.5 * PI, u, v], ["WB", "R", "S", "WB"])
  248. flag, t, u, v = LRSL(-x, y, -phi)
  249. if flag:
  250. paths = set_path(paths, [-t, 0.5 * PI, -u, -v], ["WB", "R", "S", "WB"])
  251. flag, t, u, v = LRSL(x, -y, -phi)
  252. if flag:
  253. paths = set_path(paths, [t, -0.5 * PI, u, v], ["R", "WB", "S", "R"])
  254. flag, t, u, v = LRSL(-x, -y, phi)
  255. if flag:
  256. paths = set_path(paths, [-t, 0.5 * PI, -u, -v], ["R", "WB", "S", "R"])
  257. flag, t, u, v = LRSR(x, y, phi)
  258. if flag:
  259. paths = set_path(paths, [t, -0.5 * PI, u, v], ["WB", "R", "S", "R"])
  260. flag, t, u, v = LRSR(-x, y, -phi)
  261. if flag:
  262. paths = set_path(paths, [-t, 0.5 * PI, -u, -v], ["WB", "R", "S", "R"])
  263. flag, t, u, v = LRSR(x, -y, -phi)
  264. if flag:
  265. paths = set_path(paths, [t, -0.5 * PI, u, v], ["R", "WB", "S", "WB"])
  266. flag, t, u, v = LRSR(-x, -y, phi)
  267. if flag:
  268. paths = set_path(paths, [-t, 0.5 * PI, -u, -v], ["R", "WB", "S", "WB"])
  269. # backwards
  270. xb = x * math.cos(phi) + y * math.sin(phi)
  271. yb = x * math.sin(phi) - y * math.cos(phi)
  272. flag, t, u, v = LRSL(xb, yb, phi)
  273. if flag:
  274. paths = set_path(paths, [v, u, -0.5 * PI, t], ["WB", "S", "R", "WB"])
  275. flag, t, u, v = LRSL(-xb, yb, -phi)
  276. if flag:
  277. paths = set_path(paths, [-v, -u, 0.5 * PI, -t], ["WB", "S", "R", "WB"])
  278. flag, t, u, v = LRSL(xb, -yb, -phi)
  279. if flag:
  280. paths = set_path(paths, [v, u, -0.5 * PI, t], ["R", "S", "WB", "R"])
  281. flag, t, u, v = LRSL(-xb, -yb, phi)
  282. if flag:
  283. paths = set_path(paths, [-v, -u, 0.5 * PI, -t], ["R", "S", "WB", "R"])
  284. flag, t, u, v = LRSR(xb, yb, phi)
  285. if flag:
  286. paths = set_path(paths, [v, u, -0.5 * PI, t], ["R", "S", "R", "WB"])
  287. flag, t, u, v = LRSR(-xb, yb, -phi)
  288. if flag:
  289. paths = set_path(paths, [-v, -u, 0.5 * PI, -t], ["R", "S", "R", "WB"])
  290. flag, t, u, v = LRSR(xb, -yb, -phi)
  291. if flag:
  292. paths = set_path(paths, [v, u, -0.5 * PI, t], ["WB", "S", "WB", "R"])
  293. flag, t, u, v = LRSR(-xb, -yb, phi)
  294. if flag:
  295. paths = set_path(paths, [-v, -u, 0.5 * PI, -t], ["WB", "S", "WB", "R"])
  296. return paths
  297. def LRSLR(x, y, phi):
  298. # formula 8.11 *** TYPO IN PAPER ***
  299. xi = x + math.sin(phi)
  300. eta = y - 1.0 - math.cos(phi)
  301. rho, theta = R(xi, eta)
  302. if rho >= 2.0:
  303. u = 4.0 - math.sqrt(rho * rho - 4.0)
  304. if u <= 0.0:
  305. t = M(math.atan2((4.0 - u) * xi - 2.0 * eta, -2.0 * xi + (u - 4.0) * eta))
  306. v = M(t - phi)
  307. if t >= 0.0 and v >= 0.0:
  308. return True, t, u, v
  309. return False, 0.0, 0.0, 0.0
  310. def CCSCC(x, y, phi, paths):
  311. flag, t, u, v = LRSLR(x, y, phi)
  312. if flag:
  313. paths = set_path(paths, [t, -0.5 * PI, u, -0.5 * PI, v], ["WB", "R", "S", "WB", "R"])
  314. flag, t, u, v = LRSLR(-x, y, -phi)
  315. if flag:
  316. paths = set_path(paths, [-t, 0.5 * PI, -u, 0.5 * PI, -v], ["WB", "R", "S", "WB", "R"])
  317. flag, t, u, v = LRSLR(x, -y, -phi)
  318. if flag:
  319. paths = set_path(paths, [t, -0.5 * PI, u, -0.5 * PI, v], ["R", "WB", "S", "R", "WB"])
  320. flag, t, u, v = LRSLR(-x, -y, phi)
  321. if flag:
  322. paths = set_path(paths, [-t, 0.5 * PI, -u, 0.5 * PI, -v], ["R", "WB", "S", "R", "WB"])
  323. return paths
  324. def generate_local_course(L, lengths, mode, maxc, step_size):
  325. point_num = int(L / step_size) + len(lengths) + 3
  326. px = [0.0 for _ in range(point_num)]
  327. py = [0.0 for _ in range(point_num)]
  328. pyaw = [0.0 for _ in range(point_num)]
  329. directions = [0 for _ in range(point_num)]
  330. ind = 1
  331. if lengths[0] > 0.0:
  332. directions[0] = 1
  333. else:
  334. directions[0] = -1
  335. if lengths[0] > 0.0:
  336. d = step_size
  337. else:
  338. d = -step_size
  339. ll = 0.0
  340. for m, l, i in zip(mode, lengths, range(len(mode))):
  341. if l > 0.0:
  342. d = step_size
  343. else:
  344. d = -step_size
  345. ox, oy, oyaw = px[ind], py[ind], pyaw[ind]
  346. ind -= 1
  347. if i >= 1 and (lengths[i - 1] * lengths[i]) > 0:
  348. pd = -d - ll
  349. else:
  350. pd = d - ll
  351. while abs(pd) <= abs(l):
  352. ind += 1
  353. px, py, pyaw, directions = \
  354. interpolate(ind, pd, m, maxc, ox, oy, oyaw, px, py, pyaw, directions)
  355. pd += d
  356. ll = l - pd - d # calc remain length
  357. ind += 1
  358. px, py, pyaw, directions = \
  359. interpolate(ind, l, m, maxc, ox, oy, oyaw, px, py, pyaw, directions)
  360. if len(px) <= 1:
  361. return [], [], [], []
  362. # remove unused data
  363. while len(px) >= 1 and px[-1] == 0.0:
  364. px.pop()
  365. py.pop()
  366. pyaw.pop()
  367. directions.pop()
  368. return px, py, pyaw, directions
  369. def interpolate(ind, l, m, maxc, ox, oy, oyaw, px, py, pyaw, directions):
  370. if m == "S":
  371. px[ind] = ox + l / maxc * math.cos(oyaw)
  372. py[ind] = oy + l / maxc * math.sin(oyaw)
  373. pyaw[ind] = oyaw
  374. else:
  375. ldx = math.sin(l) / maxc
  376. if m == "WB":
  377. ldy = (1.0 - math.cos(l)) / maxc
  378. elif m == "R":
  379. ldy = (1.0 - math.cos(l)) / (-maxc)
  380. gdx = math.cos(-oyaw) * ldx + math.sin(-oyaw) * ldy
  381. gdy = -math.sin(-oyaw) * ldx + math.cos(-oyaw) * ldy
  382. px[ind] = ox + gdx
  383. py[ind] = oy + gdy
  384. if m == "WB":
  385. pyaw[ind] = oyaw + l
  386. elif m == "R":
  387. pyaw[ind] = oyaw - l
  388. if l > 0.0:
  389. directions[ind] = 1
  390. else:
  391. directions[ind] = -1
  392. return px, py, pyaw, directions
  393. def generate_path(q0, q1, maxc):
  394. dx = q1[0] - q0[0]
  395. dy = q1[1] - q0[1]
  396. dth = q1[2] - q0[2]
  397. c = math.cos(q0[2])
  398. s = math.sin(q0[2])
  399. x = (c * dx + s * dy) * maxc
  400. y = (-s * dx + c * dy) * maxc
  401. paths = []
  402. paths = SCS(x, y, dth, paths)
  403. paths = CSC(x, y, dth, paths)
  404. paths = CCC(x, y, dth, paths)
  405. paths = CCCC(x, y, dth, paths)
  406. paths = CCSC(x, y, dth, paths)
  407. paths = CCSCC(x, y, dth, paths)
  408. return paths
  409. # utils
  410. def pi_2_pi(theta):
  411. while theta > PI:
  412. theta -= 2.0 * PI
  413. while theta < -PI:
  414. theta += 2.0 * PI
  415. return theta
  416. def R(x, y):
  417. """
  418. Return the polar coordinates (r, theta) of the point (x, y)
  419. """
  420. r = math.hypot(x, y)
  421. theta = math.atan2(y, x)
  422. return r, theta
  423. def M(theta):
  424. """
  425. Regulate theta to -pi <= theta < pi
  426. """
  427. phi = theta % (2.0 * PI)
  428. if phi < -PI:
  429. phi += 2.0 * PI
  430. if phi > PI:
  431. phi -= 2.0 * PI
  432. return phi
  433. def get_label(path):
  434. label = ""
  435. for m, l in zip(path.ctypes, path.lengths):
  436. label = label + m
  437. if l > 0.0:
  438. label = label + "+"
  439. else:
  440. label = label + "-"
  441. return label
  442. def calc_curvature(x, y, yaw, directions):
  443. c, ds = [], []
  444. for i in range(1, len(x) - 1):
  445. dxn = x[i] - x[i - 1]
  446. dxp = x[i + 1] - x[i]
  447. dyn = y[i] - y[i - 1]
  448. dyp = y[i + 1] - y[i]
  449. dn = math.hypot(dxn, dyn)
  450. dp = math.hypot(dxp, dyp)
  451. dx = 1.0 / (dn + dp) * (dp / dn * dxn + dn / dp * dxp)
  452. ddx = 2.0 / (dn + dp) * (dxp / dp - dxn / dn)
  453. dy = 1.0 / (dn + dp) * (dp / dn * dyn + dn / dp * dyp)
  454. ddy = 2.0 / (dn + dp) * (dyp / dp - dyn / dn)
  455. curvature = (ddy * dx - ddx * dy) / (dx ** 2 + dy ** 2)
  456. d = (dn + dp) / 2.0
  457. if np.isnan(curvature):
  458. curvature = 0.0
  459. if directions[i] <= 0.0:
  460. curvature = -curvature
  461. if len(c) == 0:
  462. ds.append(d)
  463. c.append(curvature)
  464. ds.append(d)
  465. c.append(curvature)
  466. ds.append(ds[-1])
  467. c.append(c[-1])
  468. return c, ds
  469. def check_path(sx, sy, syaw, gx, gy, gyaw, maxc):
  470. paths = calc_all_paths(sx, sy, syaw, gx, gy, gyaw, maxc)
  471. assert len(paths) >= 1
  472. for path in paths:
  473. assert abs(path.x[0] - sx) <= 0.01
  474. assert abs(path.y[0] - sy) <= 0.01
  475. assert abs(path.yaw[0] - syaw) <= 0.01
  476. assert abs(path.x[-1] - gx) <= 0.01
  477. assert abs(path.y[-1] - gy) <= 0.01
  478. assert abs(path.yaw[-1] - gyaw) <= 0.01
  479. # course distance check
  480. d = [math.hypot(dx, dy)
  481. for dx, dy in zip(np.diff(path.x[0:len(path.x) - 1]),
  482. np.diff(path.y[0:len(path.y) - 1]))]
  483. for i in range(len(d)):
  484. assert abs(d[i] - STEP_SIZE) <= 0.001
  485. def main():
  486. start_x = 3.0 # [m]
  487. start_y = 10.0 # [m]
  488. start_yaw = np.deg2rad(40.0) # [rad]
  489. end_x = 0.0 # [m]
  490. end_y = 1.0 # [m]
  491. end_yaw = np.deg2rad(0.0) # [rad]
  492. max_curvature = 0.1
  493. t0 = time.time()
  494. for i in range(1000):
  495. _ = calc_optimal_path(start_x, start_y, start_yaw, end_x, end_y, end_yaw, max_curvature)
  496. t1 = time.time()
  497. print(t1 - t0)
  498. if __name__ == '__main__':
  499. main()