Skip to content

Commit 17e2803

Browse files
committed
start implement stanley controller
1 parent 13e172d commit 17e2803

File tree

4 files changed

+175
-2
lines changed

4 files changed

+175
-2
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,6 @@
2828
[submodule "PathPlanning/DynamicWindowApproach/matplotrecorder"]
2929
path = PathPlanning/DynamicWindowApproach/matplotrecorder
3030
url = https://github.com/AtsushiSakai/matplotrecorder
31+
[submodule "PathTracking/stanley_controller/pycubicspline"]
32+
path = PathTracking/stanley_controller/pycubicspline
33+
url = https://github.com/AtsushiSakai/pycubicspline

PathTracking/pure_pursuit/pure_pursuit.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
Path tracking simulation with pure pursuit steering control and PID speed control.
44
5-
author: Atsushi Sakai
5+
author: Atsushi Sakai (@Atsushi_twi)
66
77
"""
88
import numpy as np
@@ -13,7 +13,7 @@
1313
Lfc = 1.0 # look-ahead distance
1414
Kp = 1.0 # speed propotional gain
1515
dt = 0.1 # [s]
16-
L = 2.9 # [m] Tread of vehicle
16+
L = 2.9 # [m] wheel base of vehicle
1717

1818

1919
show_animation = True
Submodule pycubicspline added at 34b741f
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
"""
2+
3+
Path tracking simulation with Stanley steering control and PID speed control.
4+
5+
author: Atsushi Sakai (@Atsushi_twi)
6+
7+
"""
8+
# import numpy as np
9+
import math
10+
import matplotlib.pyplot as plt
11+
12+
from pycubicspline import pycubicspline
13+
14+
k = 0.5 # look forward gain
15+
Kp = 1.0 # speed propotional gain
16+
dt = 0.1 # [s] time difference
17+
L = 2.9 # [m] Wheel base of vehicle
18+
max_steer = math.radians(30.0) # [rad] max steering angle
19+
20+
show_animation = True
21+
22+
23+
class State:
24+
25+
def __init__(self, x=0.0, y=0.0, yaw=0.0, v=0.0):
26+
self.x = x
27+
self.y = y
28+
self.yaw = yaw
29+
self.v = v
30+
31+
32+
def update(state, a, delta):
33+
34+
if delta >= max_steer:
35+
delta = max_steer
36+
elif delta <= -max_steer:
37+
delta = -max_steer
38+
39+
state.x = state.x + state.v * math.cos(state.yaw) * dt
40+
state.y = state.y + state.v * math.sin(state.yaw) * dt
41+
state.yaw = state.yaw + state.v / L * math.tan(delta) * dt
42+
state.yaw = pi_2_pi(state.yaw)
43+
state.v = state.v + a * dt
44+
45+
return state
46+
47+
48+
def PIDControl(target, current):
49+
a = Kp * (target - current)
50+
51+
return a
52+
53+
54+
def stanley_control(state, cx, cy, cyaw, pind):
55+
56+
ind, efa = calc_target_index(state, cx, cy)
57+
58+
if pind >= ind:
59+
ind = pind
60+
61+
theta_e = pi_2_pi(cyaw[ind] - state.yaw)
62+
theta_d = math.atan2(k * efa, state.v)
63+
delta = theta_e + theta_d
64+
65+
print(delta, theta_e, theta_d, state.yaw, cyaw[ind], efa)
66+
# input()
67+
68+
return delta, ind
69+
70+
71+
def pi_2_pi(angle):
72+
while (angle > math.pi):
73+
angle = angle - 2.0 * math.pi
74+
75+
while (angle < -math.pi):
76+
angle = angle + 2.0 * math.pi
77+
78+
return angle
79+
80+
81+
def calc_target_index(state, cx, cy):
82+
83+
# calc frant axle position
84+
fx = state.x + L * math.cos(state.yaw)
85+
fy = state.y + L * math.sin(state.yaw)
86+
87+
# search nearest point index
88+
dx = [fx - icx for icx in cx]
89+
dy = [fy - icy for icy in cy]
90+
d = [math.sqrt(idx ** 2 + idy ** 2) for (idx, idy) in zip(dx, dy)]
91+
mind = min(d)
92+
ind = d.index(mind)
93+
94+
tyaw = math.atan2(fy - cy[ind], fx - cx[ind]) - state.yaw
95+
print(tyaw)
96+
if tyaw > 0.0:
97+
mind = - mind
98+
99+
return ind, mind
100+
101+
102+
def main():
103+
# target course
104+
ax = [0.0, 100.0, 100.0, 50.0]
105+
ay = [0.0, 0.0, -30.0, -20.0]
106+
107+
cx, cy, cyaw, ck, s = pycubicspline.calc_spline_course(ax, ay, ds=0.1)
108+
109+
target_speed = 30.0 / 3.6 # [m/s]
110+
111+
T = 100.0 # max simulation time
112+
113+
# initial state
114+
state = State(x=-0.0, y=5.0, yaw=math.radians(20.0), v=0.0)
115+
116+
lastIndex = len(cx) - 1
117+
time = 0.0
118+
x = [state.x]
119+
y = [state.y]
120+
yaw = [state.yaw]
121+
v = [state.v]
122+
t = [0.0]
123+
target_ind, mind = calc_target_index(state, cx, cy)
124+
125+
while T >= time and lastIndex > target_ind:
126+
ai = PIDControl(target_speed, state.v)
127+
di, target_ind = stanley_control(state, cx, cy, cyaw, target_ind)
128+
state = update(state, ai, di)
129+
130+
time = time + dt
131+
132+
x.append(state.x)
133+
y.append(state.y)
134+
yaw.append(state.yaw)
135+
v.append(state.v)
136+
t.append(time)
137+
138+
if show_animation:
139+
plt.cla()
140+
plt.plot(cx, cy, ".r", label="course")
141+
plt.plot(x, y, "-b", label="trajectory")
142+
plt.plot(cx[target_ind], cy[target_ind], "xg", label="target")
143+
plt.axis("equal")
144+
plt.grid(True)
145+
plt.title("Speed[km/h]:" + str(state.v * 3.6)[:4])
146+
plt.pause(0.001)
147+
148+
# Test
149+
assert lastIndex >= target_ind, "Cannot goal"
150+
151+
if show_animation:
152+
plt.plot(cx, cy, ".r", label="course")
153+
plt.plot(x, y, "-b", label="trajectory")
154+
plt.legend()
155+
plt.xlabel("x[m]")
156+
plt.ylabel("y[m]")
157+
plt.axis("equal")
158+
plt.grid(True)
159+
160+
flg, ax = plt.subplots(1)
161+
plt.plot(t, [iv * 3.6 for iv in v], "-r")
162+
plt.xlabel("Time[s]")
163+
plt.ylabel("Speed[km/h]")
164+
plt.grid(True)
165+
plt.show()
166+
167+
168+
if __name__ == '__main__':
169+
main()

0 commit comments

Comments
 (0)