Skip to content

Commit 74b3470

Browse files
committed
start coding of rear_wheel_feedback simulation
1 parent 9997671 commit 74b3470

File tree

5 files changed

+379
-0
lines changed

5 files changed

+379
-0
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "PathTracking/rear_wheel_feedback/pycubicspline"]
2+
path = PathTracking/rear_wheel_feedback/pycubicspline
3+
url = https://github.com/AtsushiSakai/pycubicspline.git
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#! /usr/bin/python
2+
# -*- coding: utf-8 -*-
3+
"""
4+
5+
Reeds Shepp path planner sample code
6+
7+
author Atsushi Sakai(@Atsushi_twi)
8+
9+
License MIT
10+
11+
"""
12+
import reeds_shepp
13+
import math
14+
15+
16+
def plot_arrow(x, y, yaw, length=1.0, width=0.5, fc="r", ec="k"):
17+
u"""
18+
Plot arrow
19+
"""
20+
import matplotlib.pyplot as plt
21+
22+
if not isinstance(x, float):
23+
for (ix, iy, iyaw) in zip(x, y, yaw):
24+
plot_arrow(ix, iy, iyaw)
25+
else:
26+
plt.arrow(x, y, length * math.cos(yaw), length * math.sin(yaw),
27+
fc=fc, ec=ec, head_width=width, head_length=width)
28+
plt.plot(x, y)
29+
30+
31+
def reeds_shepp_path_planning(start_x, start_y, start_yaw,
32+
end_x, end_y, end_yaw, curvature):
33+
q0 = [start_x, start_y, start_yaw]
34+
q1 = [end_x, end_y, end_yaw]
35+
step_size = 0.1
36+
qs = reeds_shepp.path_sample(q0, q1, curvature, step_size)
37+
xs = [q[0] for q in qs]
38+
ys = [q[1] for q in qs]
39+
yaw = [q[2] for q in qs]
40+
41+
xs.append(end_x)
42+
ys.append(end_y)
43+
yaw.append(end_yaw)
44+
45+
clen = reeds_shepp.path_length(q0, q1, curvature)
46+
pathtypeTuple = reeds_shepp.path_type(q0, q1, curvature)
47+
48+
ptype = ""
49+
for t in pathtypeTuple:
50+
if t == 1:
51+
ptype += "L"
52+
elif t == 2:
53+
ptype += "S"
54+
elif t == 3:
55+
ptype += "R"
56+
57+
return xs, ys, yaw, ptype, clen
58+
59+
60+
if __name__ == '__main__':
61+
print("Reeds Shepp path planner sample start!!")
62+
import matplotlib.pyplot as plt
63+
64+
start_x = 1.0 # [m]
65+
start_y = 1.0 # [m]
66+
start_yaw = math.radians(0.0) # [rad]
67+
68+
end_x = -0.0 # [m]
69+
end_y = -3.0 # [m]
70+
end_yaw = math.radians(-45.0) # [rad]
71+
72+
curvature = 1.0
73+
74+
px, py, pyaw, mode, clen = reeds_shepp_path_planning(
75+
start_x, start_y, start_yaw, end_x, end_y, end_yaw, curvature)
76+
77+
plt.plot(px, py, label="final course " + str(mode))
78+
79+
# plotting
80+
plot_arrow(start_x, start_y, start_yaw)
81+
plot_arrow(end_x, end_y, end_yaw)
82+
83+
for (ix, iy, iyaw) in zip(px, py, pyaw):
84+
plot_arrow(ix, iy, iyaw, fc="b")
85+
# print(clen)
86+
87+
plt.legend()
88+
plt.grid(True)
89+
plt.axis("equal")
90+
plt.show()
Submodule pycubicspline added at ce074c8
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
#! /usr/bin/python
2+
"""
3+
4+
Path tracking simulation with pure pursuit steering control and PID speed control.
5+
6+
author: Atsushi Sakai
7+
8+
"""
9+
# import numpy as np
10+
import math
11+
import matplotlib.pyplot as plt
12+
import unicycle_model
13+
from pycubicspline import pycubicspline
14+
15+
Kp = 1.0 # speed propotional gain
16+
Lf = 1.0 # look-ahead distance
17+
# animation = True
18+
animation = False
19+
20+
21+
def PIDControl(target, current):
22+
a = Kp * (target - current)
23+
24+
return a
25+
26+
27+
def pure_pursuit_control(state, cx, cy, pind):
28+
29+
ind = calc_target_index(state, cx, cy)
30+
31+
if pind >= ind:
32+
ind = pind
33+
34+
# print(pind, ind)
35+
if ind < len(cx):
36+
tx = cx[ind]
37+
ty = cy[ind]
38+
else:
39+
tx = cx[-1]
40+
ty = cy[-1]
41+
ind = len(cx) - 1
42+
43+
alpha = math.atan2(ty - state.y, tx - state.x) - state.yaw
44+
45+
if state.v < 0: # back
46+
alpha = math.pi - alpha
47+
# if alpha > 0:
48+
# alpha = math.pi - alpha
49+
# else:
50+
# alpha = math.pi + alpha
51+
52+
delta = math.atan2(2.0 * unicycle_model.L * math.sin(alpha) / Lf, 1.0)
53+
54+
return delta, ind
55+
56+
57+
def calc_target_index(state, cx, cy):
58+
dx = [state.x - icx for icx in cx]
59+
dy = [state.y - icy for icy in cy]
60+
61+
d = [abs(math.sqrt(idx ** 2 + idy ** 2)) for (idx, idy) in zip(dx, dy)]
62+
63+
ind = d.index(min(d))
64+
65+
L = 0.0
66+
67+
while Lf > L and (ind + 1) < len(cx):
68+
dx = cx[ind + 1] - cx[ind]
69+
dy = cx[ind + 1] - cx[ind]
70+
L += math.sqrt(dx ** 2 + dy ** 2)
71+
ind += 1
72+
73+
return ind
74+
75+
76+
def closed_loop_prediction(cx, cy, cyaw, speed_profile, goal):
77+
78+
T = 500.0 # max simulation time
79+
goal_dis = 0.3
80+
stop_speed = 0.05
81+
82+
state = unicycle_model.State(x=-0.0, y=-0.0, yaw=0.0, v=0.0)
83+
84+
# lastIndex = len(cx) - 1
85+
time = 0.0
86+
x = [state.x]
87+
y = [state.y]
88+
yaw = [state.yaw]
89+
v = [state.v]
90+
t = [0.0]
91+
target_ind = calc_target_index(state, cx, cy)
92+
93+
while T >= time:
94+
di, target_ind = pure_pursuit_control(state, cx, cy, target_ind)
95+
ai = PIDControl(speed_profile[target_ind], state.v)
96+
state = unicycle_model.update(state, ai, di)
97+
98+
if abs(state.v) <= stop_speed:
99+
target_ind += 1
100+
101+
time = time + unicycle_model.dt
102+
103+
# check goal
104+
dx = state.x - goal[0]
105+
dy = state.y - goal[1]
106+
if math.sqrt(dx ** 2 + dy ** 2) <= goal_dis:
107+
print("Goal")
108+
break
109+
110+
x.append(state.x)
111+
y.append(state.y)
112+
yaw.append(state.yaw)
113+
v.append(state.v)
114+
t.append(time)
115+
116+
if target_ind % 20 == 0 and animation:
117+
plt.cla()
118+
plt.plot(cx, cy, "-r", label="course")
119+
plt.plot(x, y, "ob", label="trajectory")
120+
plt.plot(cx[target_ind], cy[target_ind], "xg", label="target")
121+
plt.axis("equal")
122+
plt.grid(True)
123+
plt.title("speed:" + str(round(state.v, 2)) +
124+
"tind:" + str(target_ind))
125+
plt.pause(0.0001)
126+
127+
return t, x, y, yaw, v
128+
129+
130+
def set_stop_point(target_speed, cx, cy, cyaw):
131+
speed_profile = [target_speed] * len(cx)
132+
133+
d = []
134+
direction = 1.0
135+
136+
# Set stop point
137+
for i in range(len(cx) - 1):
138+
dx = cx[i + 1] - cx[i]
139+
dy = cy[i + 1] - cy[i]
140+
td = math.sqrt(dx ** 2.0 + dy ** 2.0)
141+
d.append(td)
142+
dyaw = cyaw[i + 1] - cyaw[i]
143+
switch = math.pi / 4.0 <= dyaw < math.pi / 2.0
144+
145+
if switch:
146+
direction *= -1
147+
148+
if direction != 1.0:
149+
speed_profile[i] = - target_speed
150+
else:
151+
speed_profile[i] = target_speed
152+
153+
if switch:
154+
speed_profile[i] = 0.0
155+
156+
speed_profile[0] = 0.0
157+
speed_profile[-1] = 0.0
158+
159+
d.append(d[-1])
160+
161+
return speed_profile, d
162+
163+
164+
def calc_speed_profile(cx, cy, cyaw, target_speed):
165+
166+
speed_profile, d = set_stop_point(target_speed, cx, cy, cyaw)
167+
168+
# flg, ax = plt.subplots(1)
169+
# plt.plot(speed_profile, "-r")
170+
# plt.show()
171+
172+
return speed_profile
173+
174+
175+
def main():
176+
print("rear wheel feedback tracking start!!")
177+
ax = [0.0, 6.0, 12.5, 5.0, 7.5, 3.0, -1.0]
178+
ay = [0.0, 0.0, 5.0, 6.5, 0.0, 5.0, -2.0]
179+
goal = [ax[-1], ay[-1]]
180+
181+
cx, cy, cyaw, ck, s = pycubicspline.calc_spline_course(ax, ay, ds=0.1)
182+
target_speed = 10.0 / 3.6
183+
184+
sp = calc_speed_profile(cx, cy, cyaw, target_speed)
185+
186+
t, x, y, yaw, v = closed_loop_prediction(cx, cy, cyaw, sp, goal)
187+
188+
flg, _ = plt.subplots(1)
189+
print(len(ax), len(ay))
190+
plt.plot(ax, ay, "xb", label="input")
191+
plt.plot(cx, cy, "-r", label="spline")
192+
plt.plot(x, y, "-g", label="tracking")
193+
plt.grid(True)
194+
plt.axis("equal")
195+
plt.xlabel("x[m]")
196+
plt.ylabel("y[m]")
197+
plt.legend()
198+
199+
flg, ax = plt.subplots(1)
200+
plt.plot(s, [math.degrees(iyaw) for iyaw in cyaw], "-r", label="yaw")
201+
plt.grid(True)
202+
plt.legend()
203+
plt.xlabel("line length[m]")
204+
plt.ylabel("yaw angle[deg]")
205+
206+
flg, ax = plt.subplots(1)
207+
plt.plot(s, ck, "-r", label="curvature")
208+
plt.grid(True)
209+
plt.legend()
210+
plt.xlabel("line length[m]")
211+
plt.ylabel("curvature [1/m]")
212+
213+
plt.show()
214+
215+
216+
if __name__ == '__main__':
217+
main()
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#! /usr/bin/python
2+
# -*- coding: utf-8 -*-
3+
"""
4+
5+
6+
author Atsushi Sakai
7+
"""
8+
9+
import math
10+
11+
dt = 0.1 # [s]
12+
L = 2.9 # [m]
13+
14+
15+
class State:
16+
17+
def __init__(self, x=0.0, y=0.0, yaw=0.0, v=0.0):
18+
self.x = x
19+
self.y = y
20+
self.yaw = yaw
21+
self.v = v
22+
23+
24+
def update(state, a, delta):
25+
26+
state.x = state.x + state.v * math.cos(state.yaw) * dt
27+
state.y = state.y + state.v * math.sin(state.yaw) * dt
28+
state.yaw = state.yaw + state.v / L * math.tan(delta) * dt
29+
state.v = state.v + a * dt
30+
31+
return state
32+
33+
34+
if __name__ == '__main__':
35+
print("start unicycle simulation")
36+
import matplotlib.pyplot as plt
37+
38+
T = 100
39+
a = [1.0] * T
40+
delta = [math.radians(1.0)] * T
41+
# print(delta)
42+
# print(a, delta)
43+
44+
state = State()
45+
46+
x = []
47+
y = []
48+
yaw = []
49+
v = []
50+
51+
for (ai, di) in zip(a, delta):
52+
state = update(state, ai, di)
53+
54+
x.append(state.x)
55+
y.append(state.y)
56+
yaw.append(state.yaw)
57+
v.append(state.v)
58+
59+
flg, ax = plt.subplots(1)
60+
plt.plot(x, y)
61+
plt.axis("equal")
62+
plt.grid(True)
63+
64+
flg, ax = plt.subplots(1)
65+
plt.plot(v)
66+
plt.grid(True)
67+
68+
plt.show()

0 commit comments

Comments
 (0)