Skip to content

Commit aa3f511

Browse files
authored
Add files via upload
1 parent 22c43f4 commit aa3f511

File tree

1 file changed

+151
-0
lines changed
  • PathPlanning/DynamicWindowApproach

1 file changed

+151
-0
lines changed
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
import math
2+
import numpy as np
3+
from enum import Enum
4+
import matplotlib.pyplot as plt
5+
6+
class RobotType(Enum):
7+
circle = 0
8+
rectangle = 1
9+
10+
class Config:
11+
def __init__(self):
12+
self.max_speed = 1.0 # [m/s]
13+
self.min_speed = -0.5 # [m/s]
14+
self.max_yaw_rate = 40.0 * math.pi / 180.0 # [rad/s]
15+
self.max_accel = 0.2 # [m/ss]
16+
self.max_delta_yaw_rate = 40.0 * math.pi / 180.0 # [rad/ss]
17+
self.v_resolution = 0.01 # [m/s]
18+
self.yaw_rate_resolution = 0.1 * math.pi / 180.0 # [rad/s]
19+
self.dt = 0.1 # [s] Time tick for motion prediction
20+
self.predict_time = 3.0 # [s]
21+
self.to_goal_cost_gain = 0.15
22+
self.speed_cost_gain = 1.0
23+
self.obstacle_cost_gain = 1.0
24+
self.robot_stuck_flag_cons = 0.001 # constant to prevent robot stucked
25+
self.robot_type = RobotType.circle
26+
self.robot_radius = 1.0 # [m] for collision check
27+
self.robot_width = 0.5 # [m] for collision check
28+
self.robot_length = 1.2 # [m] for collision check
29+
self.ob = np.array([[51.74531, 0.47058], [51.73484, 0.45986], [51.715071, 0.4858], [51.75032, 0.48405], [51.74856, 0.48624], [51.73793, 0.48606], [51.76216, 0.47748], [51.76928, 0.46855]]) # Initialize with empty array
30+
31+
@property
32+
def robot_type(self):
33+
return self._robot_type
34+
35+
@robot_type.setter
36+
def robot_type(self, value):
37+
if not isinstance(value, RobotType):
38+
raise TypeError("robot_type must be an instance of RobotType")
39+
self._robot_type = value
40+
41+
def motion(x, u, dt):
42+
x[2] += u[1] * dt
43+
x[0] += u[0] * math.cos(x[2]) * dt
44+
x[1] += u[0] * math.sin(x[2]) * dt
45+
x[3] = u[0]
46+
x[4] = u[1]
47+
return x
48+
49+
def dwa_control(x, config, goal, ob):
50+
dw = calc_dynamic_window(x, config)
51+
u, trajectory = calc_control_and_trajectory(x, dw, config, goal, ob)
52+
return u, trajectory
53+
54+
def calc_dynamic_window(x, config):
55+
Vs = [config.min_speed, config.max_speed,
56+
-config.max_yaw_rate, config.max_yaw_rate]
57+
Vd = [x[3] - config.max_accel * config.dt,
58+
x[3] + config.max_accel * config.dt,
59+
x[4] - config.max_delta_yaw_rate * config.dt,
60+
x[4] + config.max_delta_yaw_rate * config.dt]
61+
dw = [max(Vs[0], Vd[0]), min(Vs[1], Vd[1]),
62+
max(Vs[2], Vd[2]), min(Vs[3], Vd[3])]
63+
return dw
64+
65+
def predict_trajectory(x_init, v, y, config):
66+
x = np.array(x_init)
67+
trajectory = np.array(x)
68+
time = 0
69+
while time <= config.predict_time:
70+
x = motion(x, [v, y], config.dt)
71+
trajectory = np.vstack((trajectory, x))
72+
time += config.dt
73+
return trajectory
74+
75+
def calc_control_and_trajectory(x, dw, config, goal, ob):
76+
x_init = x[:]
77+
min_cost = float("inf")
78+
best_u = [0.0, 0.0]
79+
best_trajectory = np.array([x])
80+
for v in np.arange(dw[0], dw[1], config.v_resolution):
81+
for y in np.arange(dw[2], dw[3], config.yaw_rate_resolution):
82+
trajectory = predict_trajectory(x_init, v, y, config)
83+
to_goal_cost = config.to_goal_cost_gain * calc_to_goal_cost(trajectory, goal)
84+
speed_cost = config.speed_cost_gain * (config.max_speed - trajectory[-1, 3])
85+
ob_cost = config.obstacle_cost_gain * calc_obstacle_cost(trajectory, ob, config)
86+
final_cost = to_goal_cost + speed_cost + ob_cost
87+
if min_cost >= final_cost:
88+
min_cost = final_cost
89+
best_u = [v, y]
90+
best_trajectory = trajectory
91+
if abs(best_u[0]) < config.robot_stuck_flag_cons and abs(x[3]) < config.robot_stuck_flag_cons:
92+
best_u[1] = -config.max_delta_yaw_rate
93+
return best_u, best_trajectory
94+
95+
def calc_obstacle_cost(trajectory, ob, config):
96+
ox = ob[:, 0]
97+
oy = ob[:, 1]
98+
dx = trajectory[:, 0] - ox[:, None]
99+
dy = trajectory[:, 1] - oy[:, None]
100+
r = np.hypot(dx, dy)
101+
if config.robot_type == RobotType.rectangle:
102+
yaw = trajectory[:, 2]
103+
rot = np.array([[np.cos(yaw), -np.sin(yaw)], [np.sin(yaw), np.cos(yaw)]])
104+
rot = np.transpose(rot, [2, 0, 1])
105+
local_ob = ob[:, None] - trajectory[:, 0:2]
106+
local_ob = local_ob.reshape(-1, local_ob.shape[-1])
107+
local_ob = np.array([local_ob @ x for x in rot])
108+
local_ob = local_ob.reshape(-1, local_ob.shape[-1])
109+
upper_check = local_ob[:, 0] <= config.robot_length / 2
110+
right_check = local_ob[:, 1] <= config.robot_width / 2
111+
bottom_check = local_ob[:, 0] >= -config.robot_length / 2
112+
left_check = local_ob[:, 1] >= -config.robot_width / 2
113+
if (np.logical_and(np.logical_and(upper_check, right_check),
114+
np.logical_and(bottom_check, left_check))).any():
115+
return float("Inf")
116+
elif config.robot_type == RobotType.circle:
117+
if np.array(r <= config.robot_radius).any():
118+
return float("Inf")
119+
min_r = np.min(r)
120+
return 1.0 / min_r
121+
122+
def calc_to_goal_cost(trajectory, goal):
123+
dx = goal[0] - trajectory[-1, 0]
124+
dy = goal[1] - trajectory[-1, 1]
125+
error_angle = math.atan2(dy, dx)
126+
cost_angle = error_angle - trajectory[-1, 2]
127+
cost = abs(math.atan2(math.sin(cost_angle), math.cos(cost_angle)))
128+
return cost
129+
130+
def plot_robot(x, y, yaw, config):
131+
if config.robot_type == RobotType.rectangle:
132+
outline = np.array([[-config.robot_length / 2, config.robot_length / 2,
133+
(config.robot_length / 2), -config.robot_length / 2,
134+
-config.robot_length / 2],
135+
[config.robot_width / 2, config.robot_width / 2,
136+
- config.robot_width / 2, -config.robot_width / 2,
137+
config.robot_width / 2]])
138+
Rot1 = np.array([[math.cos(yaw), math.sin(yaw)],
139+
[-math.sin(yaw), math.cos(yaw)]])
140+
outline = (outline.T.dot(Rot1)).T
141+
outline[0, :] += x
142+
outline[1, :] += y
143+
plt.plot(np.array(outline[0, :]).flatten(),
144+
np.array(outline[1, :]).flatten(), "-k")
145+
elif config.robot_type == RobotType.circle:
146+
circle = plt.Circle((x, y), config.robot_radius, color="b")
147+
plt.gcf().gca().add_artist(circle)
148+
out_x, out_y = (np.array([x, y]) +
149+
np.array([np.cos(yaw), np.sin(yaw)]) * config.robot_radius)
150+
plt.plot([x, out_x], [y, out_y], "-k")
151+

0 commit comments

Comments
 (0)