Skip to content

Commit 9d81a98

Browse files
committed
add grid map lib and code clean up
1 parent 7f3031d commit 9d81a98

File tree

4 files changed

+251
-10
lines changed

4 files changed

+251
-10
lines changed

Mapping/grid_map_lib/__init__.py

Whitespace-only changes.
Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
"""
2+
3+
Grid map library in python
4+
5+
author: Atsushi Sakai
6+
7+
"""
8+
9+
import matplotlib.pyplot as plt
10+
import numpy as np
11+
12+
13+
class GridMap:
14+
"""
15+
GridMap class
16+
"""
17+
18+
def __init__(self, width, height, resolution,
19+
center_x, center_y, init_val=0.0):
20+
"""__init__
21+
22+
:param width: number of grid for width
23+
:param height: number of grid for heigt
24+
:param resolution: grid resolution [m]
25+
:param center_x: center x position [m]
26+
:param center_y: center y position [m]
27+
:param init_val: initial value for all grid
28+
"""
29+
self.width = width
30+
self.height = height
31+
self.resolution = resolution
32+
self.center_x = center_x
33+
self.center_y = center_y
34+
35+
self.left_lower_x = self.center_x - \
36+
(self.width / 2.0) * self.resolution
37+
self.left_lower_y = self.center_y - \
38+
(self.height / 2.0) * self.resolution
39+
40+
self.ndata = self.width * self.height
41+
self.data = [init_val] * self.ndata
42+
43+
def get_value_from_xy_index(self, x_ind, y_ind):
44+
"""get_value_from_xy_index
45+
46+
when the index is out of grid map area, return None
47+
48+
:param x_ind: x index
49+
:param y_ind: y index
50+
"""
51+
52+
grid_ind = self.calc_grid_index_from_xy_index(x_ind, y_ind)
53+
54+
if 0 <= grid_ind <= self.ndata:
55+
return self.data[grid_ind]
56+
else:
57+
return None
58+
59+
def get_xy_index_from_xy_pos(self, x_pos, y_pos):
60+
"""get_xy_index_from_xy_pos
61+
62+
:param x_pos: x position [m]
63+
:param y_pos: y position [m]
64+
"""
65+
x_ind = self.calc_xy_index_from_position(
66+
x_pos, self.left_lower_x, self.width)
67+
y_ind = self.calc_xy_index_from_position(
68+
y_pos, self.left_lower_y, self.height)
69+
70+
return x_ind, y_ind
71+
72+
def set_value_from_xy_pos(self, x_pos, y_pos, val):
73+
"""set_value_from_xy_pos
74+
75+
return bool flag, which means setting value is succeeded or not
76+
77+
:param x_pos: x position [m]
78+
:param y_pos: y position [m]
79+
:param val: grid value
80+
"""
81+
82+
x_ind, y_ind = self.get_xy_index_from_xy_pos(x_pos, y_pos)
83+
84+
if (not x_ind) or (not y_ind):
85+
return False # NG
86+
87+
flag = self.set_value_from_xy_index(x_ind, y_ind, val)
88+
89+
return flag
90+
91+
def set_value_from_xy_index(self, x_ind, y_ind, val):
92+
"""set_value_from_xy_index
93+
94+
return bool flag, which means setting value is succeeded or not
95+
96+
:param x_ind: x index
97+
:param y_ind: y index
98+
:param val: grid value
99+
"""
100+
101+
grid_ind = int(y_ind * self.width + x_ind)
102+
103+
if 0 <= grid_ind <= self.ndata:
104+
self.data[grid_ind] = val
105+
return True # OK
106+
else:
107+
return False # NG
108+
109+
def set_value_from_polygon(self, pol_x, pol_y, val, inside=True):
110+
"""set_value_from_polygon
111+
112+
Setting value inside or outside polygon
113+
114+
:param pol_x: x position list for a polygon
115+
:param pol_y: y position list for a polygon
116+
:param val: grid value
117+
:param inside: setting data inside or outside
118+
"""
119+
120+
# making ring polygon
121+
if (pol_x[0] != pol_x[-1]) or (pol_y[0] != pol_y[-1]):
122+
pol_x.append(pol_x[0])
123+
pol_y.append(pol_y[0])
124+
125+
# setting value for all grid
126+
for x_ind in range(self.width):
127+
for y_ind in range(self.height):
128+
x_pos, y_pos = self.calc_grid_central_xy_position_from_xy_index(
129+
x_ind, y_ind)
130+
131+
flag = self.check_inside_polygon(x_pos, y_pos, pol_x, pol_y)
132+
133+
if flag is inside:
134+
self.set_value_from_xy_index(x_ind, y_ind, val)
135+
136+
def calc_grid_index_from_xy_index(self, x_ind, y_ind):
137+
grid_ind = int(y_ind * self.width + x_ind)
138+
return grid_ind
139+
140+
def calc_grid_central_xy_position_from_xy_index(self, x_ind, y_ind):
141+
x_pos = self.calc_grid_central_xy_position_from_index(
142+
x_ind, self.left_lower_x)
143+
y_pos = self.calc_grid_central_xy_position_from_index(
144+
y_ind, self.left_lower_y)
145+
146+
return x_pos, y_pos
147+
148+
def calc_grid_central_xy_position_from_index(self, index, lower_pos):
149+
return lower_pos + index * self.resolution + self.resolution / 2.0
150+
151+
def calc_xy_index_from_position(self, pos, lower_pos, max_index):
152+
ind = int(np.floor((pos - lower_pos) / self.resolution))
153+
if 0 <= ind <= max_index:
154+
return ind
155+
else:
156+
return None
157+
158+
def check_occupied_from_xy_index(self, xind, yind, occupied_val=1.0):
159+
160+
val = self.get_value_from_xy_index(xind, yind)
161+
162+
if val >= occupied_val:
163+
return True
164+
else:
165+
return False
166+
167+
@staticmethod
168+
def check_inside_polygon(iox, ioy, x, y):
169+
170+
npoint = len(x) - 1
171+
inside = False
172+
for i1 in range(npoint):
173+
i2 = (i1 + 1) % (npoint + 1)
174+
175+
if x[i1] >= x[i2]:
176+
min_x, max_x = x[i2], x[i1]
177+
else:
178+
min_x, max_x = x[i1], x[i2]
179+
if not min_x < iox < max_x:
180+
continue
181+
182+
if (y[i1] + (y[i2] - y[i1]) / (x[i2] - x[i1])
183+
* (iox - x[i1]) - ioy) > 0.0:
184+
inside = not inside
185+
186+
return inside
187+
188+
def plot_grid_map(self):
189+
190+
grid_data = np.reshape(np.array(self.data), (self.height, self.width))
191+
fig, ax = plt.subplots()
192+
heat_map = ax.pcolor(grid_data, cmap="Blues", vmin=0.0, vmax=1.0)
193+
plt.axis("equal")
194+
plt.show()
195+
196+
return heat_map
197+
198+
199+
def test_polygon_set():
200+
ox = [0.0, 20.0, 50.0, 100.0, 130.0, 40.0]
201+
oy = [0.0, -20.0, 0.0, 30.0, 60.0, 80.0]
202+
203+
grid_map = GridMap(600, 290, 0.7, 60.0, 30.5)
204+
205+
grid_map.set_value_from_polygon(ox, oy, 1.0, inside=False)
206+
207+
grid_map.plot_grid_map()
208+
209+
plt.axis("equal")
210+
plt.grid(True)
211+
212+
213+
def test_position_set():
214+
grid_map = GridMap(100, 120, 0.5, 10.0, -0.5)
215+
216+
grid_map.set_value_from_xy_pos(10.1, -1.1, 1.0)
217+
grid_map.set_value_from_xy_pos(10.1, -0.1, 1.0)
218+
grid_map.set_value_from_xy_pos(10.1, 1.1, 1.0)
219+
grid_map.set_value_from_xy_pos(11.1, 0.1, 1.0)
220+
grid_map.set_value_from_xy_pos(10.1, 0.1, 1.0)
221+
grid_map.set_value_from_xy_pos(9.1, 0.1, 1.0)
222+
223+
grid_map.plot_grid_map()
224+
225+
226+
def main():
227+
print("start!!")
228+
229+
test_position_set()
230+
test_polygon_set()
231+
232+
plt.show()
233+
234+
print("done!!")
235+
236+
237+
if __name__ == '__main__':
238+
main()

PathTracking/lqr_speed_steer_control/lqr_speed_steer_control.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
1-
import cubic_spline_planner
2-
import scipy.linalg as la
3-
import matplotlib.pyplot as plt
4-
import math
5-
import numpy as np
61
"""
72
83
Path tracking simulation with LQR speed and steering control
94
105
author Atsushi Sakai (@Atsushi_twi)
116
127
"""
8+
import math
139
import sys
10+
11+
import matplotlib.pyplot as plt
12+
import numpy as np
13+
import scipy.linalg as la
14+
1415
sys.path.append("../../PathPlanning/CubicSpline/")
16+
import cubic_spline_planner
1517

1618

1719
# LQR parameter
@@ -59,6 +61,7 @@ def solve_DARE(A, B, Q, R):
5961
solve a discrete time_Algebraic Riccati equation (DARE)
6062
"""
6163
X = Q
64+
Xn = Q
6265
maxiter = 150
6366
eps = 0.01
6467

@@ -85,9 +88,9 @@ def dlqr(A, B, Q, R):
8588
# compute the LQR gain
8689
K = la.inv(B.T @ X @ B + R) @ (B.T @ X @ A)
8790

88-
eigVals, eigVecs = la.eig(A - B @ K)
91+
eigs = la.eig(A - B @ K)
8992

90-
return K, X, eigVals
93+
return K, X, eigs[0]
9194

9295

9396
def lqr_steering_control(state, cx, cy, cyaw, ck, pe, pth_e, sp):

tests/test_rrt_star.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
from unittest import TestCase
2-
import sys
31
import os
2+
import sys
3+
from unittest import TestCase
4+
45
sys.path.append(os.path.dirname(os.path.abspath(__file__)) +
56
"/../PathPlanning/RRTstar/")
67

@@ -23,4 +24,3 @@ def test1(self):
2324
if __name__ == '__main__': # pragma: no cover
2425
test = Test()
2526
test.test1()
26-
print(aa)

0 commit comments

Comments
 (0)