pathplanning 0.1.0__tar.gz
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.
- pathplanning-0.1.0/CurvesGenerator/__init__.py +1 -0
- pathplanning-0.1.0/CurvesGenerator/bezier_path.py +145 -0
- pathplanning-0.1.0/CurvesGenerator/bspline_curve.py +80 -0
- pathplanning-0.1.0/CurvesGenerator/cubic_spline.py +262 -0
- pathplanning-0.1.0/CurvesGenerator/draw.py +66 -0
- pathplanning-0.1.0/CurvesGenerator/dubins_path.py +351 -0
- pathplanning-0.1.0/CurvesGenerator/quartic_polynomial.py +43 -0
- pathplanning-0.1.0/CurvesGenerator/quintic_polynomial.py +143 -0
- pathplanning-0.1.0/CurvesGenerator/reeds_shepp.py +720 -0
- pathplanning-0.1.0/LICENSE +21 -0
- pathplanning-0.1.0/PKG-INFO +354 -0
- pathplanning-0.1.0/README.md +298 -0
- pathplanning-0.1.0/Sampling_based_Planning/__init__.py +1 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_2D/__init__.py +1 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_2D/adaptively_informed_trees.py +0 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_2D/advanced_batch_informed_trees.py +0 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_2D/batch_informed_trees.py +402 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_2D/dubins_rrt_star.py +321 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_2D/dynamic_rrt.py +342 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_2D/env.py +45 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_2D/extended_rrt.py +251 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_2D/fast_marching_trees.py +220 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_2D/informed_rrt_star.py +305 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_2D/plotting.py +115 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_2D/queue.py +62 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_2D/rrt.py +114 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_2D/rrt_connect.py +156 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_2D/rrt_sharp.py +0 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_2D/rrt_star.py +184 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_2D/rrt_star_smart.py +311 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_2D/utils.py +138 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_3D/ABIT_star3D.py +148 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_3D/BIT_star3D.py +353 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_3D/FMT_star3D.py +192 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_3D/__init__.py +1 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_3D/dynamic_rrt3D.py +239 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_3D/env3D.py +148 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_3D/extend_rrt3D.py +102 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_3D/informed_rrt_star3D.py +234 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_3D/plot_util3D.py +167 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_3D/queue.py +86 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_3D/rrt3D.py +72 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_3D/rrt_connect3D.py +187 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_3D/rrt_star3D.py +107 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_3D/rrt_star_smart3D.py +0 -0
- pathplanning-0.1.0/Sampling_based_Planning/rrt_3D/utils3D.py +416 -0
- pathplanning-0.1.0/Search_based_Planning/Search_3D/Anytime_Dstar3D.py +245 -0
- pathplanning-0.1.0/Search_based_Planning/Search_3D/Astar3D.py +119 -0
- pathplanning-0.1.0/Search_based_Planning/Search_3D/Dstar3D.py +192 -0
- pathplanning-0.1.0/Search_based_Planning/Search_3D/DstarLite3D.py +219 -0
- pathplanning-0.1.0/Search_based_Planning/Search_3D/LP_Astar3D.py +194 -0
- pathplanning-0.1.0/Search_based_Planning/Search_3D/LRT_Astar3D.py +87 -0
- pathplanning-0.1.0/Search_based_Planning/Search_3D/RTA_Astar3D.py +78 -0
- pathplanning-0.1.0/Search_based_Planning/Search_3D/__init__.py +1 -0
- pathplanning-0.1.0/Search_based_Planning/Search_3D/bidirectional_Astar3D.py +115 -0
- pathplanning-0.1.0/Search_based_Planning/Search_3D/env3D.py +147 -0
- pathplanning-0.1.0/Search_based_Planning/Search_3D/plot_util3D.py +155 -0
- pathplanning-0.1.0/Search_based_Planning/Search_3D/queue.py +154 -0
- pathplanning-0.1.0/Search_based_Planning/Search_3D/utils3D.py +359 -0
- pathplanning-0.1.0/Search_based_Planning/__init__.py +1 -0
- pathplanning-0.1.0/Search_based_Planning/plan2d/__init__.py +17 -0
- pathplanning-0.1.0/Search_based_Planning/plan2d/anytime_dstar.py +314 -0
- pathplanning-0.1.0/Search_based_Planning/plan2d/anytime_repairing_astar.py +220 -0
- pathplanning-0.1.0/Search_based_Planning/plan2d/astar.py +225 -0
- pathplanning-0.1.0/Search_based_Planning/plan2d/best_first_search.py +67 -0
- pathplanning-0.1.0/Search_based_Planning/plan2d/bidirectional_astar.py +229 -0
- pathplanning-0.1.0/Search_based_Planning/plan2d/breadth_first_search.py +69 -0
- pathplanning-0.1.0/Search_based_Planning/plan2d/depth_first_search.py +69 -0
- pathplanning-0.1.0/Search_based_Planning/plan2d/dijkstra.py +68 -0
- pathplanning-0.1.0/Search_based_Planning/plan2d/dstar.py +304 -0
- pathplanning-0.1.0/Search_based_Planning/plan2d/dstar_lite.py +239 -0
- pathplanning-0.1.0/Search_based_Planning/plan2d/learning_realtime_astar.py +230 -0
- pathplanning-0.1.0/Search_based_Planning/plan2d/lifelong_planning_astar.py +254 -0
- pathplanning-0.1.0/Search_based_Planning/plan2d/plan2d_facade.py +494 -0
- pathplanning-0.1.0/Search_based_Planning/plan2d/realtime_adaptive_astar.py +234 -0
- pathplanning-0.1.0/Search_based_Planning/plan2d/run.py +55 -0
- pathplanning-0.1.0/Search_based_Planning/plan2d/utils/__init__.py +1 -0
- pathplanning-0.1.0/Search_based_Planning/plan2d/utils/env.py +48 -0
- pathplanning-0.1.0/Search_based_Planning/plan2d/utils/plotting.py +258 -0
- pathplanning-0.1.0/Search_based_Planning/plan2d/utils/queue.py +62 -0
- pathplanning-0.1.0/pathplanning.egg-info/PKG-INFO +354 -0
- pathplanning-0.1.0/pathplanning.egg-info/SOURCES.txt +93 -0
- pathplanning-0.1.0/pathplanning.egg-info/dependency_links.txt +1 -0
- pathplanning-0.1.0/pathplanning.egg-info/requires.txt +11 -0
- pathplanning-0.1.0/pathplanning.egg-info/top_level.txt +4 -0
- pathplanning-0.1.0/pathplanningv2/__init__.py +29 -0
- pathplanning-0.1.0/pathplanningv2/api.py +18 -0
- pathplanning-0.1.0/pathplanningv2/registry.py +107 -0
- pathplanning-0.1.0/pathplanningv2/search2d.py +15 -0
- pathplanning-0.1.0/pyproject.toml +77 -0
- pathplanning-0.1.0/setup.cfg +4 -0
- pathplanning-0.1.0/tests/test_package_api.py +22 -0
- pathplanning-0.1.0/tests/test_runtime_representative_smoke.py +22 -0
- pathplanning-0.1.0/tests/test_search2d_smoke.py +32 -0
- pathplanning-0.1.0/tests/test_supported_modules_import.py +13 -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()
|
|
@@ -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)
|