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.
- CurvesGenerator/__init__.py +1 -0
- CurvesGenerator/bezier_path.py +145 -0
- CurvesGenerator/bspline_curve.py +80 -0
- CurvesGenerator/cubic_spline.py +262 -0
- CurvesGenerator/draw.py +66 -0
- CurvesGenerator/dubins_path.py +351 -0
- CurvesGenerator/quartic_polynomial.py +43 -0
- CurvesGenerator/quintic_polynomial.py +143 -0
- CurvesGenerator/reeds_shepp.py +720 -0
- Sampling_based_Planning/__init__.py +1 -0
- Sampling_based_Planning/rrt_2D/__init__.py +1 -0
- Sampling_based_Planning/rrt_2D/adaptively_informed_trees.py +0 -0
- Sampling_based_Planning/rrt_2D/advanced_batch_informed_trees.py +0 -0
- Sampling_based_Planning/rrt_2D/batch_informed_trees.py +402 -0
- Sampling_based_Planning/rrt_2D/dubins_rrt_star.py +321 -0
- Sampling_based_Planning/rrt_2D/dynamic_rrt.py +342 -0
- Sampling_based_Planning/rrt_2D/env.py +45 -0
- Sampling_based_Planning/rrt_2D/extended_rrt.py +251 -0
- Sampling_based_Planning/rrt_2D/fast_marching_trees.py +220 -0
- Sampling_based_Planning/rrt_2D/informed_rrt_star.py +305 -0
- Sampling_based_Planning/rrt_2D/plotting.py +115 -0
- Sampling_based_Planning/rrt_2D/queue.py +62 -0
- Sampling_based_Planning/rrt_2D/rrt.py +114 -0
- Sampling_based_Planning/rrt_2D/rrt_connect.py +156 -0
- Sampling_based_Planning/rrt_2D/rrt_sharp.py +0 -0
- Sampling_based_Planning/rrt_2D/rrt_star.py +184 -0
- Sampling_based_Planning/rrt_2D/rrt_star_smart.py +311 -0
- Sampling_based_Planning/rrt_2D/utils.py +138 -0
- Sampling_based_Planning/rrt_3D/ABIT_star3D.py +148 -0
- Sampling_based_Planning/rrt_3D/BIT_star3D.py +353 -0
- Sampling_based_Planning/rrt_3D/FMT_star3D.py +192 -0
- Sampling_based_Planning/rrt_3D/__init__.py +1 -0
- Sampling_based_Planning/rrt_3D/dynamic_rrt3D.py +239 -0
- Sampling_based_Planning/rrt_3D/env3D.py +148 -0
- Sampling_based_Planning/rrt_3D/extend_rrt3D.py +102 -0
- Sampling_based_Planning/rrt_3D/informed_rrt_star3D.py +234 -0
- Sampling_based_Planning/rrt_3D/plot_util3D.py +167 -0
- Sampling_based_Planning/rrt_3D/queue.py +86 -0
- Sampling_based_Planning/rrt_3D/rrt3D.py +72 -0
- Sampling_based_Planning/rrt_3D/rrt_connect3D.py +187 -0
- Sampling_based_Planning/rrt_3D/rrt_star3D.py +107 -0
- Sampling_based_Planning/rrt_3D/rrt_star_smart3D.py +0 -0
- Sampling_based_Planning/rrt_3D/utils3D.py +416 -0
- Search_based_Planning/Search_3D/Anytime_Dstar3D.py +245 -0
- Search_based_Planning/Search_3D/Astar3D.py +119 -0
- Search_based_Planning/Search_3D/Dstar3D.py +192 -0
- Search_based_Planning/Search_3D/DstarLite3D.py +219 -0
- Search_based_Planning/Search_3D/LP_Astar3D.py +194 -0
- Search_based_Planning/Search_3D/LRT_Astar3D.py +87 -0
- Search_based_Planning/Search_3D/RTA_Astar3D.py +78 -0
- Search_based_Planning/Search_3D/__init__.py +1 -0
- Search_based_Planning/Search_3D/bidirectional_Astar3D.py +115 -0
- Search_based_Planning/Search_3D/env3D.py +147 -0
- Search_based_Planning/Search_3D/plot_util3D.py +155 -0
- Search_based_Planning/Search_3D/queue.py +154 -0
- Search_based_Planning/Search_3D/utils3D.py +359 -0
- Search_based_Planning/__init__.py +1 -0
- Search_based_Planning/plan2d/__init__.py +17 -0
- Search_based_Planning/plan2d/anytime_dstar.py +314 -0
- Search_based_Planning/plan2d/anytime_repairing_astar.py +220 -0
- Search_based_Planning/plan2d/astar.py +225 -0
- Search_based_Planning/plan2d/best_first_search.py +67 -0
- Search_based_Planning/plan2d/bidirectional_astar.py +229 -0
- Search_based_Planning/plan2d/breadth_first_search.py +69 -0
- Search_based_Planning/plan2d/depth_first_search.py +69 -0
- Search_based_Planning/plan2d/dijkstra.py +68 -0
- Search_based_Planning/plan2d/dstar.py +304 -0
- Search_based_Planning/plan2d/dstar_lite.py +239 -0
- Search_based_Planning/plan2d/learning_realtime_astar.py +230 -0
- Search_based_Planning/plan2d/lifelong_planning_astar.py +254 -0
- Search_based_Planning/plan2d/plan2d_facade.py +494 -0
- Search_based_Planning/plan2d/realtime_adaptive_astar.py +234 -0
- Search_based_Planning/plan2d/run.py +55 -0
- Search_based_Planning/plan2d/utils/__init__.py +1 -0
- Search_based_Planning/plan2d/utils/env.py +48 -0
- Search_based_Planning/plan2d/utils/plotting.py +258 -0
- Search_based_Planning/plan2d/utils/queue.py +62 -0
- pathplanning-0.1.0.dist-info/LICENSE +21 -0
- pathplanning-0.1.0.dist-info/METADATA +354 -0
- pathplanning-0.1.0.dist-info/RECORD +86 -0
- pathplanning-0.1.0.dist-info/WHEEL +5 -0
- pathplanning-0.1.0.dist-info/top_level.txt +4 -0
- pathplanningv2/__init__.py +29 -0
- pathplanningv2/api.py +18 -0
- pathplanningv2/registry.py +107 -0
- pathplanningv2/search2d.py +15 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Curve generation utilities."""
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"""
|
|
2
|
+
bezier path
|
|
3
|
+
|
|
4
|
+
author: Atsushi Sakai(@Atsushi_twi)
|
|
5
|
+
modified: damminhtien
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
import matplotlib.pyplot as plt
|
|
10
|
+
from scipy.special import comb
|
|
11
|
+
import draw
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def calc_4points_bezier_path(sx, sy, syaw, gx, gy, gyaw, offset):
|
|
15
|
+
|
|
16
|
+
dist = np.hypot(sx - gx, sy - gy) / offset
|
|
17
|
+
control_points = np.array(
|
|
18
|
+
[[sx, sy],
|
|
19
|
+
[sx + dist * np.cos(syaw), sy + dist * np.sin(syaw)],
|
|
20
|
+
[gx - dist * np.cos(gyaw), gy - dist * np.sin(gyaw)],
|
|
21
|
+
[gx, gy]])
|
|
22
|
+
|
|
23
|
+
path = calc_bezier_path(control_points, n_points=100)
|
|
24
|
+
|
|
25
|
+
return path, control_points
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def calc_bezier_path(control_points, n_points=100):
|
|
29
|
+
traj = []
|
|
30
|
+
|
|
31
|
+
for t in np.linspace(0, 1, n_points):
|
|
32
|
+
traj.append(bezier(t, control_points))
|
|
33
|
+
|
|
34
|
+
return np.array(traj)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def Comb(n, i, t):
|
|
38
|
+
return comb(n, i) * t ** i * (1 - t) ** (n - i)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def bezier(t, control_points):
|
|
42
|
+
n = len(control_points) - 1
|
|
43
|
+
return np.sum([Comb(n, i, t) * control_points[i] for i in range(n + 1)], axis=0)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def bezier_derivatives_control_points(control_points, n_derivatives):
|
|
47
|
+
w = {0: control_points}
|
|
48
|
+
|
|
49
|
+
for i in range(n_derivatives):
|
|
50
|
+
n = len(w[i])
|
|
51
|
+
w[i + 1] = np.array([(n - 1) * (w[i][j + 1] - w[i][j])
|
|
52
|
+
for j in range(n - 1)])
|
|
53
|
+
|
|
54
|
+
return w
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def curvature(dx, dy, ddx, ddy):
|
|
58
|
+
return (dx * ddy - dy * ddx) / (dx ** 2 + dy ** 2) ** (3 / 2)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def simulation():
|
|
62
|
+
sx = [-3, 0, 4, 6]
|
|
63
|
+
sy = [2, 0, 1.5, 6]
|
|
64
|
+
|
|
65
|
+
ratio = np.linspace(0, 1, 100)
|
|
66
|
+
pathx, pathy = [], []
|
|
67
|
+
|
|
68
|
+
for t in ratio:
|
|
69
|
+
x, y = [], []
|
|
70
|
+
for i in range(len(sx) - 1):
|
|
71
|
+
x.append(sx[i + 1] * t + sx[i] * (1 - t))
|
|
72
|
+
y.append(sy[i + 1] * t + sy[i] * (1 - t))
|
|
73
|
+
|
|
74
|
+
xx, yy = [], []
|
|
75
|
+
for i in range(len(x) - 1):
|
|
76
|
+
xx.append(x[i + 1] * t + x[i] * (1 - t))
|
|
77
|
+
yy.append(y[i + 1] * t + y[i] * (1 - t))
|
|
78
|
+
|
|
79
|
+
px = xx[1] * t + xx[0] * (1 - t)
|
|
80
|
+
py = yy[1] * t + yy[0] * (1 - t)
|
|
81
|
+
pathx.append(px)
|
|
82
|
+
pathy.append(py)
|
|
83
|
+
|
|
84
|
+
plt.cla()
|
|
85
|
+
plt.plot(sx, sy, linestyle='-', marker='o', color='dimgray', label="Control Points")
|
|
86
|
+
plt.plot(x, y, color='dodgerblue')
|
|
87
|
+
plt.plot(xx, yy, color='cyan')
|
|
88
|
+
plt.plot(pathx, pathy, color='darkorange', linewidth=2, label="Bezier Path")
|
|
89
|
+
plt.plot(px, py, marker='o')
|
|
90
|
+
plt.axis("equal")
|
|
91
|
+
plt.legend()
|
|
92
|
+
plt.title("Cubic Bezier Curve demo")
|
|
93
|
+
plt.grid(True)
|
|
94
|
+
plt.pause(0.001)
|
|
95
|
+
|
|
96
|
+
plt.show()
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def main():
|
|
100
|
+
sx, sy, syaw = 10.0, 1.0, np.deg2rad(180.0)
|
|
101
|
+
gx, gy, gyaw = 0.0, -3.0, np.deg2rad(-45.0)
|
|
102
|
+
offset = 3.0
|
|
103
|
+
|
|
104
|
+
path, control_points = calc_4points_bezier_path(sx, sy, syaw, gx, gy, gyaw, offset)
|
|
105
|
+
|
|
106
|
+
t = 0.8 # Number in [0, 1]
|
|
107
|
+
x_target, y_target = bezier(t, control_points)
|
|
108
|
+
derivatives_cp = bezier_derivatives_control_points(control_points, 2)
|
|
109
|
+
point = bezier(t, control_points)
|
|
110
|
+
dt = bezier(t, derivatives_cp[1])
|
|
111
|
+
ddt = bezier(t, derivatives_cp[2])
|
|
112
|
+
# Radius of curv
|
|
113
|
+
radius = 1 / curvature(dt[0], dt[1], ddt[0], ddt[1])
|
|
114
|
+
# Normalize derivative
|
|
115
|
+
dt /= np.linalg.norm(dt, 2)
|
|
116
|
+
tangent = np.array([point, point + dt])
|
|
117
|
+
normal = np.array([point, point + [- dt[1], dt[0]]])
|
|
118
|
+
curvature_center = point + np.array([- dt[1], dt[0]]) * radius
|
|
119
|
+
circle = plt.Circle(tuple(curvature_center), radius,
|
|
120
|
+
color=(0, 0.8, 0.8), fill=False, linewidth=1)
|
|
121
|
+
|
|
122
|
+
assert path.T[0][0] == sx, "path is invalid"
|
|
123
|
+
assert path.T[1][0] == sy, "path is invalid"
|
|
124
|
+
assert path.T[0][-1] == gx, "path is invalid"
|
|
125
|
+
assert path.T[1][-1] == gy, "path is invalid"
|
|
126
|
+
|
|
127
|
+
fig, ax = plt.subplots()
|
|
128
|
+
ax.plot(path.T[0], path.T[1], label="Bezier Path")
|
|
129
|
+
ax.plot(control_points.T[0], control_points.T[1],
|
|
130
|
+
'--o', label="Control Points")
|
|
131
|
+
ax.plot(x_target, y_target)
|
|
132
|
+
ax.plot(tangent[:, 0], tangent[:, 1], label="Tangent")
|
|
133
|
+
ax.plot(normal[:, 0], normal[:, 1], label="Normal")
|
|
134
|
+
ax.add_artist(circle)
|
|
135
|
+
draw.Arrow(sx, sy, syaw, 1, "darkorange")
|
|
136
|
+
draw.Arrow(gx, gy, gyaw, 1, "darkorange")
|
|
137
|
+
plt.grid(True)
|
|
138
|
+
plt.title("Bezier Path: from Atsushi's work")
|
|
139
|
+
ax.axis("equal")
|
|
140
|
+
plt.show()
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
if __name__ == '__main__':
|
|
144
|
+
main()
|
|
145
|
+
# simulation()
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"""
|
|
2
|
+
|
|
3
|
+
Path Planner with B-Spline
|
|
4
|
+
|
|
5
|
+
author: Atsushi Sakai (@Atsushi_twi)
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
10
|
+
import matplotlib.pyplot as plt
|
|
11
|
+
import scipy.interpolate as scipy_interpolate
|
|
12
|
+
import cubic_spline as cs
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def approximate_b_spline_path(x, y, n_path_points, degree=3):
|
|
16
|
+
t = range(len(x))
|
|
17
|
+
x_tup = scipy_interpolate.splrep(t, x, k=degree)
|
|
18
|
+
y_tup = scipy_interpolate.splrep(t, y, k=degree)
|
|
19
|
+
|
|
20
|
+
x_list = list(x_tup)
|
|
21
|
+
x_list[1] = x + [0.0, 0.0, 0.0, 0.0]
|
|
22
|
+
|
|
23
|
+
y_list = list(y_tup)
|
|
24
|
+
y_list[1] = y + [0.0, 0.0, 0.0, 0.0]
|
|
25
|
+
|
|
26
|
+
ipl_t = np.linspace(0.0, len(x) - 1, n_path_points)
|
|
27
|
+
rx = scipy_interpolate.splev(ipl_t, x_list)
|
|
28
|
+
ry = scipy_interpolate.splev(ipl_t, y_list)
|
|
29
|
+
|
|
30
|
+
return rx, ry
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def interpolate_b_spline_path(x, y, n_path_points, degree=3):
|
|
34
|
+
ipl_t = np.linspace(0.0, len(x) - 1, len(x))
|
|
35
|
+
spl_i_x = scipy_interpolate.make_interp_spline(ipl_t, x, k=degree)
|
|
36
|
+
spl_i_y = scipy_interpolate.make_interp_spline(ipl_t, y, k=degree)
|
|
37
|
+
|
|
38
|
+
travel = np.linspace(0.0, len(x) - 1, n_path_points)
|
|
39
|
+
return spl_i_x(travel), spl_i_y(travel)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def main():
|
|
43
|
+
print(__file__ + " start!!")
|
|
44
|
+
# way points
|
|
45
|
+
# way_point_x = [-1.0, 3.0, 4.0, 2.0, 1.0]
|
|
46
|
+
# way_point_y = [0.0, -3.0, 1.0, 1.0, 3.0]
|
|
47
|
+
way_point_x = [-2, 2.0, 3.5, 5.5, 6.0, 8.0]
|
|
48
|
+
way_point_y = [0, 2.7, -0.5, 0.5, 3.0, 4.0]
|
|
49
|
+
|
|
50
|
+
sp = cs.Spline2D(way_point_x, way_point_y)
|
|
51
|
+
s = np.arange(0, sp.s[-1], 0.1)
|
|
52
|
+
|
|
53
|
+
rx, ry, ryaw, rk = [], [], [], []
|
|
54
|
+
for i_s in s:
|
|
55
|
+
ix, iy = sp.calc_position(i_s)
|
|
56
|
+
rx.append(ix)
|
|
57
|
+
ry.append(iy)
|
|
58
|
+
ryaw.append(sp.calc_yaw(i_s))
|
|
59
|
+
rk.append(sp.calc_curvature(i_s))
|
|
60
|
+
|
|
61
|
+
n_course_point = 100 # sampling number
|
|
62
|
+
rax, ray = approximate_b_spline_path(way_point_x, way_point_y,
|
|
63
|
+
n_course_point)
|
|
64
|
+
rix, riy = interpolate_b_spline_path(way_point_x, way_point_y,
|
|
65
|
+
n_course_point)
|
|
66
|
+
|
|
67
|
+
# show results
|
|
68
|
+
plt.plot(way_point_x, way_point_y, '-og', label="Control Points")
|
|
69
|
+
plt.plot(rax, ray, '-r', label="Approximated B-Spline path")
|
|
70
|
+
plt.plot(rix, riy, '-b', label="Interpolated B-Spline path")
|
|
71
|
+
plt.plot(rx, ry, color='dimgray', label="Cubic Spline")
|
|
72
|
+
plt.grid(True)
|
|
73
|
+
plt.title("Curves Comparison")
|
|
74
|
+
plt.legend()
|
|
75
|
+
plt.axis("equal")
|
|
76
|
+
plt.show()
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
if __name__ == '__main__':
|
|
80
|
+
main()
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
#! /usr/bin/python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
u"""
|
|
4
|
+
Cubic Spline library on python
|
|
5
|
+
|
|
6
|
+
author Atsushi Sakai
|
|
7
|
+
|
|
8
|
+
usage: see test codes as below
|
|
9
|
+
|
|
10
|
+
license: MIT
|
|
11
|
+
"""
|
|
12
|
+
import math
|
|
13
|
+
import numpy as np
|
|
14
|
+
import bisect
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Spline:
|
|
18
|
+
u"""
|
|
19
|
+
Cubic Spline class
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
def __init__(self, x, y):
|
|
23
|
+
self.b, self.c, self.d, self.w = [], [], [], []
|
|
24
|
+
|
|
25
|
+
self.x = x
|
|
26
|
+
self.y = y
|
|
27
|
+
|
|
28
|
+
self.nx = len(x) # dimension of s
|
|
29
|
+
h = np.diff(x)
|
|
30
|
+
|
|
31
|
+
# calc coefficient cBest
|
|
32
|
+
self.a = [iy for iy in y]
|
|
33
|
+
|
|
34
|
+
# calc coefficient cBest
|
|
35
|
+
A = self.__calc_A(h)
|
|
36
|
+
B = self.__calc_B(h)
|
|
37
|
+
self.c = np.linalg.solve(A, B)
|
|
38
|
+
# print(self.c1)
|
|
39
|
+
|
|
40
|
+
# calc spline coefficient b and d
|
|
41
|
+
for i in range(self.nx - 1):
|
|
42
|
+
self.d.append((self.c[i + 1] - self.c[i]) / (3.0 * h[i]))
|
|
43
|
+
tb = (self.a[i + 1] - self.a[i]) / h[i] - h[i] * \
|
|
44
|
+
(self.c[i + 1] + 2.0 * self.c[i]) / 3.0
|
|
45
|
+
self.b.append(tb)
|
|
46
|
+
|
|
47
|
+
def calc(self, t):
|
|
48
|
+
u"""
|
|
49
|
+
Calc position
|
|
50
|
+
|
|
51
|
+
if t is outside of the input s, return None
|
|
52
|
+
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
if t < self.x[0]:
|
|
56
|
+
return None
|
|
57
|
+
elif t > self.x[-1]:
|
|
58
|
+
return None
|
|
59
|
+
|
|
60
|
+
i = self.__search_index(t)
|
|
61
|
+
dx = t - self.x[i]
|
|
62
|
+
result = self.a[i] + self.b[i] * dx + \
|
|
63
|
+
self.c[i] * dx ** 2.0 + self.d[i] * dx ** 3.0
|
|
64
|
+
|
|
65
|
+
return result
|
|
66
|
+
|
|
67
|
+
def calcd(self, t):
|
|
68
|
+
u"""
|
|
69
|
+
Calc first derivative
|
|
70
|
+
|
|
71
|
+
if t is outside of the input s, return None
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
if t < self.x[0]:
|
|
75
|
+
return None
|
|
76
|
+
elif t > self.x[-1]:
|
|
77
|
+
return None
|
|
78
|
+
|
|
79
|
+
i = self.__search_index(t)
|
|
80
|
+
dx = t - self.x[i]
|
|
81
|
+
result = self.b[i] + 2.0 * self.c[i] * dx + 3.0 * self.d[i] * dx ** 2.0
|
|
82
|
+
return result
|
|
83
|
+
|
|
84
|
+
def calcdd(self, t):
|
|
85
|
+
u"""
|
|
86
|
+
Calc second derivative
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
if t < self.x[0]:
|
|
90
|
+
return None
|
|
91
|
+
elif t > self.x[-1]:
|
|
92
|
+
return None
|
|
93
|
+
|
|
94
|
+
i = self.__search_index(t)
|
|
95
|
+
dx = t - self.x[i]
|
|
96
|
+
result = 2.0 * self.c[i] + 6.0 * self.d[i] * dx
|
|
97
|
+
return result
|
|
98
|
+
|
|
99
|
+
def __search_index(self, x):
|
|
100
|
+
u"""
|
|
101
|
+
search data segment index
|
|
102
|
+
"""
|
|
103
|
+
return bisect.bisect(self.x, x) - 1
|
|
104
|
+
|
|
105
|
+
def __calc_A(self, h):
|
|
106
|
+
u"""
|
|
107
|
+
calc matrix A for spline coefficient cBest
|
|
108
|
+
"""
|
|
109
|
+
A = np.zeros((self.nx, self.nx))
|
|
110
|
+
A[0, 0] = 1.0
|
|
111
|
+
for i in range(self.nx - 1):
|
|
112
|
+
if i != (self.nx - 2):
|
|
113
|
+
A[i + 1, i + 1] = 2.0 * (h[i] + h[i + 1])
|
|
114
|
+
A[i + 1, i] = h[i]
|
|
115
|
+
A[i, i + 1] = h[i]
|
|
116
|
+
|
|
117
|
+
A[0, 1] = 0.0
|
|
118
|
+
A[self.nx - 1, self.nx - 2] = 0.0
|
|
119
|
+
A[self.nx - 1, self.nx - 1] = 1.0
|
|
120
|
+
# print(A)
|
|
121
|
+
return A
|
|
122
|
+
|
|
123
|
+
def __calc_B(self, h):
|
|
124
|
+
u"""
|
|
125
|
+
calc matrix B for spline coefficient cBest
|
|
126
|
+
"""
|
|
127
|
+
B = np.zeros(self.nx)
|
|
128
|
+
for i in range(self.nx - 2):
|
|
129
|
+
B[i + 1] = 3.0 * (self.a[i + 2] - self.a[i + 1]) / \
|
|
130
|
+
h[i + 1] - 3.0 * (self.a[i + 1] - self.a[i]) / h[i]
|
|
131
|
+
# print(B)
|
|
132
|
+
return B
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class Spline2D:
|
|
136
|
+
u"""
|
|
137
|
+
2D Cubic Spline class
|
|
138
|
+
|
|
139
|
+
"""
|
|
140
|
+
|
|
141
|
+
def __init__(self, x, y):
|
|
142
|
+
self.s = self.__calc_s(x, y)
|
|
143
|
+
self.sx = Spline(self.s, x)
|
|
144
|
+
self.sy = Spline(self.s, y)
|
|
145
|
+
|
|
146
|
+
def __calc_s(self, x, y):
|
|
147
|
+
dx = np.diff(x)
|
|
148
|
+
dy = np.diff(y)
|
|
149
|
+
self.ds = [math.sqrt(idx ** 2 + idy ** 2)
|
|
150
|
+
for (idx, idy) in zip(dx, dy)]
|
|
151
|
+
s = [0]
|
|
152
|
+
s.extend(np.cumsum(self.ds))
|
|
153
|
+
return s
|
|
154
|
+
|
|
155
|
+
def calc_position(self, s):
|
|
156
|
+
u"""
|
|
157
|
+
calc position
|
|
158
|
+
"""
|
|
159
|
+
x = self.sx.calc(s)
|
|
160
|
+
y = self.sy.calc(s)
|
|
161
|
+
|
|
162
|
+
return x, y
|
|
163
|
+
|
|
164
|
+
def calc_curvature(self, s):
|
|
165
|
+
u"""
|
|
166
|
+
calc curvature
|
|
167
|
+
"""
|
|
168
|
+
dx = self.sx.calcd(s)
|
|
169
|
+
ddx = self.sx.calcdd(s)
|
|
170
|
+
dy = self.sy.calcd(s)
|
|
171
|
+
ddy = self.sy.calcdd(s)
|
|
172
|
+
k = (ddy * dx - ddx * dy) / (dx ** 2 + dy ** 2)
|
|
173
|
+
return k
|
|
174
|
+
|
|
175
|
+
def calc_yaw(self, s):
|
|
176
|
+
u"""
|
|
177
|
+
calc yaw
|
|
178
|
+
"""
|
|
179
|
+
dx = self.sx.calcd(s)
|
|
180
|
+
dy = self.sy.calcd(s)
|
|
181
|
+
yaw = math.atan2(dy, dx)
|
|
182
|
+
return yaw
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def calc_spline_course(x, y, ds=0.1):
|
|
186
|
+
sp = Spline2D(x, y)
|
|
187
|
+
s = np.arange(0, sp.s[-1], ds)
|
|
188
|
+
|
|
189
|
+
rx, ry, ryaw, rk = [], [], [], []
|
|
190
|
+
for i_s in s:
|
|
191
|
+
ix, iy = sp.calc_position(i_s)
|
|
192
|
+
rx.append(ix)
|
|
193
|
+
ry.append(iy)
|
|
194
|
+
ryaw.append(sp.calc_yaw(i_s))
|
|
195
|
+
rk.append(sp.calc_curvature(i_s))
|
|
196
|
+
|
|
197
|
+
return rx, ry, ryaw, rk, s
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def test_spline2d():
|
|
201
|
+
print("Spline 2D test")
|
|
202
|
+
import matplotlib.pyplot as plt
|
|
203
|
+
x = [-2.5, 0.0, 2.5, 5.0, 7.5, 3.0, -1.0]
|
|
204
|
+
y = [0.7, -6, 5, 6.5, 0.0, 5.0, -2.0]
|
|
205
|
+
|
|
206
|
+
sp = Spline2D(x, y)
|
|
207
|
+
s = np.arange(0, sp.s[-1], 0.1)
|
|
208
|
+
|
|
209
|
+
rx, ry, ryaw, rk = [], [], [], []
|
|
210
|
+
for i_s in s:
|
|
211
|
+
ix, iy = sp.calc_position(i_s)
|
|
212
|
+
rx.append(ix)
|
|
213
|
+
ry.append(iy)
|
|
214
|
+
ryaw.append(sp.calc_yaw(i_s))
|
|
215
|
+
rk.append(sp.calc_curvature(i_s))
|
|
216
|
+
|
|
217
|
+
flg, ax = plt.subplots(1)
|
|
218
|
+
plt.plot(x, y, "xb", label="input")
|
|
219
|
+
plt.plot(rx, ry, "-r", label="spline")
|
|
220
|
+
plt.grid(True)
|
|
221
|
+
plt.axis("equal")
|
|
222
|
+
plt.xlabel("s[m]")
|
|
223
|
+
plt.ylabel("y[m]")
|
|
224
|
+
plt.legend()
|
|
225
|
+
|
|
226
|
+
flg, ax = plt.subplots(1)
|
|
227
|
+
plt.plot(s, [math.degrees(iyaw) for iyaw in ryaw], "-r", label="yaw")
|
|
228
|
+
plt.grid(True)
|
|
229
|
+
plt.legend()
|
|
230
|
+
plt.xlabel("line length[m]")
|
|
231
|
+
plt.ylabel("yaw angle[deg]")
|
|
232
|
+
|
|
233
|
+
flg, ax = plt.subplots(1)
|
|
234
|
+
plt.plot(s, rk, "-r", label="curvature")
|
|
235
|
+
plt.grid(True)
|
|
236
|
+
plt.legend()
|
|
237
|
+
plt.xlabel("line length[m]")
|
|
238
|
+
plt.ylabel("curvature [1/m]")
|
|
239
|
+
|
|
240
|
+
plt.show()
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def test_spline():
|
|
244
|
+
print("Spline test")
|
|
245
|
+
import matplotlib.pyplot as plt
|
|
246
|
+
x = [-0.5, 0.0, 0.5, 1.0, 1.5]
|
|
247
|
+
y = [3.2, 2.7, 6, 5, 6.5]
|
|
248
|
+
|
|
249
|
+
spline = Spline(x, y)
|
|
250
|
+
rx = np.arange(-2.0, 4, 0.01)
|
|
251
|
+
ry = [spline.calc(i) for i in rx]
|
|
252
|
+
|
|
253
|
+
plt.plot(x, y, "xb")
|
|
254
|
+
plt.plot(rx, ry, "-r")
|
|
255
|
+
plt.grid(True)
|
|
256
|
+
plt.axis("equal")
|
|
257
|
+
plt.show()
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
if __name__ == '__main__':
|
|
261
|
+
test_spline()
|
|
262
|
+
# test_spline2d()
|
CurvesGenerator/draw.py
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import matplotlib.pyplot as plt
|
|
2
|
+
import numpy as np
|
|
3
|
+
PI = np.pi
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Arrow:
|
|
7
|
+
def __init__(self, x, y, theta, L, c):
|
|
8
|
+
angle = np.deg2rad(30)
|
|
9
|
+
d = 0.5 * L
|
|
10
|
+
w = 2
|
|
11
|
+
|
|
12
|
+
x_start = x
|
|
13
|
+
y_start = y
|
|
14
|
+
x_end = x + L * np.cos(theta)
|
|
15
|
+
y_end = y + L * np.sin(theta)
|
|
16
|
+
|
|
17
|
+
theta_hat_L = theta + PI - angle
|
|
18
|
+
theta_hat_R = theta + PI + angle
|
|
19
|
+
|
|
20
|
+
x_hat_start = x_end
|
|
21
|
+
x_hat_end_L = x_hat_start + d * np.cos(theta_hat_L)
|
|
22
|
+
x_hat_end_R = x_hat_start + d * np.cos(theta_hat_R)
|
|
23
|
+
|
|
24
|
+
y_hat_start = y_end
|
|
25
|
+
y_hat_end_L = y_hat_start + d * np.sin(theta_hat_L)
|
|
26
|
+
y_hat_end_R = y_hat_start + d * np.sin(theta_hat_R)
|
|
27
|
+
|
|
28
|
+
plt.plot([x_start, x_end], [y_start, y_end], color=c, linewidth=w)
|
|
29
|
+
plt.plot([x_hat_start, x_hat_end_L],
|
|
30
|
+
[y_hat_start, y_hat_end_L], color=c, linewidth=w)
|
|
31
|
+
plt.plot([x_hat_start, x_hat_end_R],
|
|
32
|
+
[y_hat_start, y_hat_end_R], color=c, linewidth=w)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class Car:
|
|
36
|
+
def __init__(self, x, y, yaw, w, L):
|
|
37
|
+
theta_B = PI + yaw
|
|
38
|
+
|
|
39
|
+
xB = x + L / 4 * np.cos(theta_B)
|
|
40
|
+
yB = y + L / 4 * np.sin(theta_B)
|
|
41
|
+
|
|
42
|
+
theta_BL = theta_B + PI / 2
|
|
43
|
+
theta_BR = theta_B - PI / 2
|
|
44
|
+
|
|
45
|
+
x_BL = xB + w / 2 * np.cos(theta_BL) # Bottom-Left vertex
|
|
46
|
+
y_BL = yB + w / 2 * np.sin(theta_BL)
|
|
47
|
+
x_BR = xB + w / 2 * np.cos(theta_BR) # Bottom-Right vertex
|
|
48
|
+
y_BR = yB + w / 2 * np.sin(theta_BR)
|
|
49
|
+
|
|
50
|
+
x_FL = x_BL + L * np.cos(yaw) # Front-Left vertex
|
|
51
|
+
y_FL = y_BL + L * np.sin(yaw)
|
|
52
|
+
x_FR = x_BR + L * np.cos(yaw) # Front-Right vertex
|
|
53
|
+
y_FR = y_BR + L * np.sin(yaw)
|
|
54
|
+
|
|
55
|
+
plt.plot([x_BL, x_BR, x_FR, x_FL, x_BL],
|
|
56
|
+
[y_BL, y_BR, y_FR, y_FL, y_BL],
|
|
57
|
+
linewidth=1, color='black')
|
|
58
|
+
|
|
59
|
+
Arrow(x, y, yaw, L / 2, 'black')
|
|
60
|
+
# plt.axis("equal")
|
|
61
|
+
# plt.show()
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
if __name__ == '__main__':
|
|
65
|
+
# Arrow(-1, 2, 60)
|
|
66
|
+
Car(0, 0, 1, 2, 60)
|