Skip to content

Commit a5aad31

Browse files
committed
Getting rid of OpenCV2
1 parent 5d6927a commit a5aad31

File tree

2 files changed

+169
-53
lines changed

2 files changed

+169
-53
lines changed

Mapping/lidar_to_grid_map/lidar_to_grid_map.py

Lines changed: 76 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@
88

99
import math
1010
import numpy as np
11-
import cv2
1211
import matplotlib.pyplot as plt
12+
from collections import deque
1313

1414
EXTEND_AREA = 1.0
1515

16+
1617
def file_read(f):
1718
"""
1819
Reading LIDAR laser beams (angles and corresponding distance data)
@@ -27,6 +28,7 @@ def file_read(f):
2728
distances = np.array(distances)
2829
return angles, distances
2930

31+
3032
def bresenham(start, end):
3133
"""
3234
Implementation of Bresenham's line drawing algorithm
@@ -70,6 +72,7 @@ def bresenham(start, end):
7072
points = np.array(points)
7173
return points
7274

75+
7376
def calc_grid_map_config(ox, oy, xyreso):
7477
"""
7578
Calculates the size, and the maximum distances according to the the measurement center
@@ -83,28 +86,84 @@ def calc_grid_map_config(ox, oy, xyreso):
8386
print("The grid map is ", xw, "x", yw, ".")
8487
return minx, miny, maxx, maxy, xw, yw
8588

89+
8690
def atan_zero_to_twopi(y, x):
8791
angle = math.atan2(y, x)
8892
if angle < 0.0:
8993
angle += math.pi * 2.0
9094
return angle
9195

92-
def generate_ray_casting_grid_map(ox, oy, xyreso, yawreso, breshen = True):
96+
97+
def init_floodfill(cpoint, opoints, xypoints, mincoord, xyreso):
98+
"""
99+
cpoint: center point
100+
opoints: detected obstacles points (x,y)
101+
xypoints: (x,y) point pairs
102+
"""
103+
centix, centiy = cpoint
104+
prev_ix, prev_iy = centix - 1, centiy
105+
ox, oy = opoints
106+
xw, yw = xypoints
107+
minx, miny = mincoord
108+
pmap = (np.ones((xw, yw))) * 0.5
109+
for (x, y) in zip(ox, oy):
110+
ix = int(round((x - minx) / xyreso)) # x coordinate of the the occupied area
111+
iy = int(round((y - miny) / xyreso)) # y coordinate of the the occupied area
112+
free_area = bresenham((prev_ix, prev_iy), (ix, iy))
113+
for fa in free_area:
114+
pmap[fa[0]][fa[1]] = 0 # free area 0.0
115+
prev_ix = ix
116+
prev_iy = iy
117+
return pmap
118+
119+
120+
def flood_fill(cpoint, pmap):
121+
"""
122+
cpoint: starting point (x,y) of fill
123+
pmap: occupancy map generated from Bresenham ray-tracing
124+
"""
125+
# Fill empty areas with queue method
126+
sx, sy = pmap.shape
127+
fringe = deque()
128+
fringe.appendleft(cpoint)
129+
while len(fringe)>0:
130+
n = fringe.pop()
131+
nx, ny = n
132+
# West
133+
if nx > 0:
134+
if pmap[nx - 1, ny] == 0.5:
135+
pmap[nx - 1, ny] = 0.0
136+
fringe.appendleft((nx - 1, ny))
137+
# East
138+
if nx < sx - 1:
139+
if pmap[nx + 1, ny] == 0.5:
140+
pmap[nx + 1, ny] = 0.0
141+
fringe.appendleft((nx + 1, ny))
142+
# North
143+
if ny > 0:
144+
if pmap[nx, ny - 1] == 0.5:
145+
pmap[nx, ny - 1] = 0.0
146+
fringe.appendleft((nx, ny - 1))
147+
# South
148+
if ny < sy - 1:
149+
if pmap[nx, ny + 1] == 0.5:
150+
pmap[nx, ny + 1] = 0.0
151+
fringe.appendleft((nx, ny + 1))
152+
153+
154+
def generate_ray_casting_grid_map(ox, oy, xyreso, breshen=True):
93155
"""
94156
The breshen boolean tells if it's computed with bresenham ray casting (True) or with flood fill (False)
95157
"""
96158
minx, miny, maxx, maxy, xw, yw = calc_grid_map_config(ox, oy, xyreso)
97159
pmap = np.ones((xw, yw))/2 # default 0.5 -- [[0.5 for i in range(yw)] for i in range(xw)]
98160
centix = int(round(-minx / xyreso)) # center x coordinate of the grid map
99161
centiy = int(round(-miny / xyreso)) # center y coordinate of the grid map
100-
#print(centix, centiy)
101-
prev_ix, prev_iy = centix - 1, centiy
102162
# occupancy grid computed with bresenham ray casting
103163
if breshen:
104164
for (x, y) in zip(ox, oy):
105-
angle = atan_zero_to_twopi(y, x)
106-
ix = int(round((x - minx) / xyreso)) # x coordinte of the the occupied area
107-
iy = int(round((y - miny) / xyreso)) # y coordinte of the the occupied area
165+
ix = int(round((x - minx) / xyreso)) # x coordinate of the the occupied area
166+
iy = int(round((y - miny) / xyreso)) # y coordinate of the the occupied area
108167
laser_beams = bresenham((centix, centiy), (ix, iy)) # line form the lidar to the cooupied point
109168
for laser_beam in laser_beams:
110169
pmap[laser_beam[0]][laser_beam[1]] = 0.0 # free area 0.0
@@ -114,19 +173,10 @@ def generate_ray_casting_grid_map(ox, oy, xyreso, yawreso, breshen = True):
114173
pmap[ix+1][iy+1] = 1.0 # extend the occupied area
115174
# occupancy grid computed with with flood fill
116175
else:
117-
pmap = (np.ones((xw, yw), dtype=np.uint8)) * 5 # food fill does not work with float numbers such as 0.5; so 5 is the default and later it is divided by 10
118-
for (x, y) in zip(ox, oy):
119-
ix = int(round((x - minx) / xyreso)) # x coordinte of the the occupied area
120-
iy = int(round((y - miny) / xyreso)) # y coordinte of the the occupied area
121-
free_area = bresenham((prev_ix, prev_iy), (ix, iy))
122-
for fa in free_area:
123-
pmap[fa[0]][fa[1]] = 0 # free area 0.0
124-
prev_ix = ix
125-
prev_iy = iy
126-
cv2.floodFill(pmap, None, (centix, centiy), 0) # filling the free spaces with 0, stating from the center
176+
pmap = init_floodfill((centix, centiy), (ox, oy), (xw, yw), (minx, miny), xyreso)
177+
flood_fill((centix, centiy), pmap)
127178
pmap = np.array(pmap, dtype=np.float)
128-
pmap /= 10
129-
for (x, y) in zip(ox, oy):
179+
for (x, y) in zip(ox, oy):
130180
ix = int(round((x - minx) / xyreso))
131181
iy = int(round((y - miny) / xyreso))
132182
pmap[ix][iy] = 1.0 # occupied area 1.0
@@ -135,25 +185,25 @@ def generate_ray_casting_grid_map(ox, oy, xyreso, yawreso, breshen = True):
135185
pmap[ix+1][iy+1] = 1.0 # extend the occupied area
136186
return pmap, minx, maxx, miny, maxy, xyreso
137187

188+
138189
def main():
139190
"""
140191
Example usage
141192
"""
142193
print(__file__, "start")
143194
xyreso = 0.02 # x-y grid resolution
144-
yawreso = math.radians(3.1) # yaw angle resolution [rad]
145195
ang, dist = file_read("lidar01.csv")
146196
ox = np.sin(ang) * dist
147197
oy = np.cos(ang) * dist
148-
pmap, minx, maxx, miny, maxy, xyreso = generate_ray_casting_grid_map(ox, oy, xyreso, yawreso, True)
198+
pmap, minx, maxx, miny, maxy, xyreso = generate_ray_casting_grid_map(ox, oy, xyreso, True)
149199
xyres = np.array(pmap).shape
150200
plt.figure(1, figsize=(10,4))
151201
plt.subplot(122)
152-
plt.imshow(pmap, cmap = "PiYG_r") # cmap = "binary" "PiYG_r" "PiYG_r" "bone" "bone_r" "RdYlGn_r"
202+
plt.imshow(pmap, cmap="PiYG_r") # cmap = "binary" "PiYG_r" "PiYG_r" "bone" "bone_r" "RdYlGn_r"
153203
plt.clim(-0.4, 1.4)
154-
plt.gca().set_xticks(np.arange(-.5, xyres[1], 1), minor = True)
155-
plt.gca().set_yticks(np.arange(-.5, xyres[0], 1), minor = True)
156-
plt.grid(True, which="minor", color="w", linewidth = .6, alpha = 0.5)
204+
plt.gca().set_xticks(np.arange(-.5, xyres[1], 1), minor=True)
205+
plt.gca().set_yticks(np.arange(-.5, xyres[0], 1), minor=True)
206+
plt.grid(True, which="minor", color="w", linewidth=0.6, alpha=0.5)
157207
plt.colorbar()
158208
plt.subplot(121)
159209
plt.plot([oy, np.zeros(np.size(oy))], [ox, np.zeros(np.size(oy))], "ro-")
@@ -164,7 +214,7 @@ def main():
164214
plt.ylim((top, bottom)) # rescale y axis, to match the grid orientation
165215
plt.grid(True)
166216
plt.show()
217+
167218

168219
if __name__ == '__main__':
169220
main()
170-

Mapping/lidar_to_grid_map/lidar_to_grid_map_tutorial.ipynb

Lines changed: 93 additions & 27 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)