mirror of
https://github.com/AtsushiSakai/PythonRobotics.git
synced 2026-02-11 12:26:08 -05:00
Getting rid of OpenCV2
This commit is contained in:
@@ -8,11 +8,12 @@ author: Erno Horvath, Csaba Hajdu based on Atsushi Sakai's scripts (@Atsushi_twi
|
|||||||
|
|
||||||
import math
|
import math
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import cv2
|
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
|
from collections import deque
|
||||||
|
|
||||||
EXTEND_AREA = 1.0
|
EXTEND_AREA = 1.0
|
||||||
|
|
||||||
|
|
||||||
def file_read(f):
|
def file_read(f):
|
||||||
"""
|
"""
|
||||||
Reading LIDAR laser beams (angles and corresponding distance data)
|
Reading LIDAR laser beams (angles and corresponding distance data)
|
||||||
@@ -27,6 +28,7 @@ def file_read(f):
|
|||||||
distances = np.array(distances)
|
distances = np.array(distances)
|
||||||
return angles, distances
|
return angles, distances
|
||||||
|
|
||||||
|
|
||||||
def bresenham(start, end):
|
def bresenham(start, end):
|
||||||
"""
|
"""
|
||||||
Implementation of Bresenham's line drawing algorithm
|
Implementation of Bresenham's line drawing algorithm
|
||||||
@@ -70,6 +72,7 @@ def bresenham(start, end):
|
|||||||
points = np.array(points)
|
points = np.array(points)
|
||||||
return points
|
return points
|
||||||
|
|
||||||
|
|
||||||
def calc_grid_map_config(ox, oy, xyreso):
|
def calc_grid_map_config(ox, oy, xyreso):
|
||||||
"""
|
"""
|
||||||
Calculates the size, and the maximum distances according to the the measurement center
|
Calculates the size, and the maximum distances according to the the measurement center
|
||||||
@@ -83,13 +86,72 @@ def calc_grid_map_config(ox, oy, xyreso):
|
|||||||
print("The grid map is ", xw, "x", yw, ".")
|
print("The grid map is ", xw, "x", yw, ".")
|
||||||
return minx, miny, maxx, maxy, xw, yw
|
return minx, miny, maxx, maxy, xw, yw
|
||||||
|
|
||||||
|
|
||||||
def atan_zero_to_twopi(y, x):
|
def atan_zero_to_twopi(y, x):
|
||||||
angle = math.atan2(y, x)
|
angle = math.atan2(y, x)
|
||||||
if angle < 0.0:
|
if angle < 0.0:
|
||||||
angle += math.pi * 2.0
|
angle += math.pi * 2.0
|
||||||
return angle
|
return angle
|
||||||
|
|
||||||
def generate_ray_casting_grid_map(ox, oy, xyreso, yawreso, breshen = True):
|
|
||||||
|
def init_floodfill(cpoint, opoints, xypoints, mincoord, xyreso):
|
||||||
|
"""
|
||||||
|
cpoint: center point
|
||||||
|
opoints: detected obstacles points (x,y)
|
||||||
|
xypoints: (x,y) point pairs
|
||||||
|
"""
|
||||||
|
centix, centiy = cpoint
|
||||||
|
prev_ix, prev_iy = centix - 1, centiy
|
||||||
|
ox, oy = opoints
|
||||||
|
xw, yw = xypoints
|
||||||
|
minx, miny = mincoord
|
||||||
|
pmap = (np.ones((xw, yw))) * 0.5
|
||||||
|
for (x, y) in zip(ox, oy):
|
||||||
|
ix = int(round((x - minx) / xyreso)) # x coordinate of the the occupied area
|
||||||
|
iy = int(round((y - miny) / xyreso)) # y coordinate of the the occupied area
|
||||||
|
free_area = bresenham((prev_ix, prev_iy), (ix, iy))
|
||||||
|
for fa in free_area:
|
||||||
|
pmap[fa[0]][fa[1]] = 0 # free area 0.0
|
||||||
|
prev_ix = ix
|
||||||
|
prev_iy = iy
|
||||||
|
return pmap
|
||||||
|
|
||||||
|
|
||||||
|
def flood_fill(cpoint, pmap):
|
||||||
|
"""
|
||||||
|
cpoint: starting point (x,y) of fill
|
||||||
|
pmap: occupancy map generated from Bresenham ray-tracing
|
||||||
|
"""
|
||||||
|
# Fill empty areas with queue method
|
||||||
|
sx, sy = pmap.shape
|
||||||
|
fringe = deque()
|
||||||
|
fringe.appendleft(cpoint)
|
||||||
|
while len(fringe)>0:
|
||||||
|
n = fringe.pop()
|
||||||
|
nx, ny = n
|
||||||
|
# West
|
||||||
|
if nx > 0:
|
||||||
|
if pmap[nx - 1, ny] == 0.5:
|
||||||
|
pmap[nx - 1, ny] = 0.0
|
||||||
|
fringe.appendleft((nx - 1, ny))
|
||||||
|
# East
|
||||||
|
if nx < sx - 1:
|
||||||
|
if pmap[nx + 1, ny] == 0.5:
|
||||||
|
pmap[nx + 1, ny] = 0.0
|
||||||
|
fringe.appendleft((nx + 1, ny))
|
||||||
|
# North
|
||||||
|
if ny > 0:
|
||||||
|
if pmap[nx, ny - 1] == 0.5:
|
||||||
|
pmap[nx, ny - 1] = 0.0
|
||||||
|
fringe.appendleft((nx, ny - 1))
|
||||||
|
# South
|
||||||
|
if ny < sy - 1:
|
||||||
|
if pmap[nx, ny + 1] == 0.5:
|
||||||
|
pmap[nx, ny + 1] = 0.0
|
||||||
|
fringe.appendleft((nx, ny + 1))
|
||||||
|
|
||||||
|
|
||||||
|
def generate_ray_casting_grid_map(ox, oy, xyreso, breshen=True):
|
||||||
"""
|
"""
|
||||||
The breshen boolean tells if it's computed with bresenham ray casting (True) or with flood fill (False)
|
The breshen boolean tells if it's computed with bresenham ray casting (True) or with flood fill (False)
|
||||||
"""
|
"""
|
||||||
@@ -97,14 +159,11 @@ def generate_ray_casting_grid_map(ox, oy, xyreso, yawreso, breshen = True):
|
|||||||
pmap = np.ones((xw, yw))/2 # default 0.5 -- [[0.5 for i in range(yw)] for i in range(xw)]
|
pmap = np.ones((xw, yw))/2 # default 0.5 -- [[0.5 for i in range(yw)] for i in range(xw)]
|
||||||
centix = int(round(-minx / xyreso)) # center x coordinate of the grid map
|
centix = int(round(-minx / xyreso)) # center x coordinate of the grid map
|
||||||
centiy = int(round(-miny / xyreso)) # center y coordinate of the grid map
|
centiy = int(round(-miny / xyreso)) # center y coordinate of the grid map
|
||||||
#print(centix, centiy)
|
|
||||||
prev_ix, prev_iy = centix - 1, centiy
|
|
||||||
# occupancy grid computed with bresenham ray casting
|
# occupancy grid computed with bresenham ray casting
|
||||||
if breshen:
|
if breshen:
|
||||||
for (x, y) in zip(ox, oy):
|
for (x, y) in zip(ox, oy):
|
||||||
angle = atan_zero_to_twopi(y, x)
|
ix = int(round((x - minx) / xyreso)) # x coordinate of the the occupied area
|
||||||
ix = int(round((x - minx) / xyreso)) # x coordinte of the the occupied area
|
iy = int(round((y - miny) / xyreso)) # y coordinate of the the occupied area
|
||||||
iy = int(round((y - miny) / xyreso)) # y coordinte of the the occupied area
|
|
||||||
laser_beams = bresenham((centix, centiy), (ix, iy)) # line form the lidar to the cooupied point
|
laser_beams = bresenham((centix, centiy), (ix, iy)) # line form the lidar to the cooupied point
|
||||||
for laser_beam in laser_beams:
|
for laser_beam in laser_beams:
|
||||||
pmap[laser_beam[0]][laser_beam[1]] = 0.0 # free area 0.0
|
pmap[laser_beam[0]][laser_beam[1]] = 0.0 # free area 0.0
|
||||||
@@ -114,18 +173,9 @@ def generate_ray_casting_grid_map(ox, oy, xyreso, yawreso, breshen = True):
|
|||||||
pmap[ix+1][iy+1] = 1.0 # extend the occupied area
|
pmap[ix+1][iy+1] = 1.0 # extend the occupied area
|
||||||
# occupancy grid computed with with flood fill
|
# occupancy grid computed with with flood fill
|
||||||
else:
|
else:
|
||||||
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
|
pmap = init_floodfill((centix, centiy), (ox, oy), (xw, yw), (minx, miny), xyreso)
|
||||||
for (x, y) in zip(ox, oy):
|
flood_fill((centix, centiy), pmap)
|
||||||
ix = int(round((x - minx) / xyreso)) # x coordinte of the the occupied area
|
|
||||||
iy = int(round((y - miny) / xyreso)) # y coordinte of the the occupied area
|
|
||||||
free_area = bresenham((prev_ix, prev_iy), (ix, iy))
|
|
||||||
for fa in free_area:
|
|
||||||
pmap[fa[0]][fa[1]] = 0 # free area 0.0
|
|
||||||
prev_ix = ix
|
|
||||||
prev_iy = iy
|
|
||||||
cv2.floodFill(pmap, None, (centix, centiy), 0) # filling the free spaces with 0, stating from the center
|
|
||||||
pmap = np.array(pmap, dtype=np.float)
|
pmap = np.array(pmap, dtype=np.float)
|
||||||
pmap /= 10
|
|
||||||
for (x, y) in zip(ox, oy):
|
for (x, y) in zip(ox, oy):
|
||||||
ix = int(round((x - minx) / xyreso))
|
ix = int(round((x - minx) / xyreso))
|
||||||
iy = int(round((y - miny) / xyreso))
|
iy = int(round((y - miny) / xyreso))
|
||||||
@@ -135,25 +185,25 @@ def generate_ray_casting_grid_map(ox, oy, xyreso, yawreso, breshen = True):
|
|||||||
pmap[ix+1][iy+1] = 1.0 # extend the occupied area
|
pmap[ix+1][iy+1] = 1.0 # extend the occupied area
|
||||||
return pmap, minx, maxx, miny, maxy, xyreso
|
return pmap, minx, maxx, miny, maxy, xyreso
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""
|
"""
|
||||||
Example usage
|
Example usage
|
||||||
"""
|
"""
|
||||||
print(__file__, "start")
|
print(__file__, "start")
|
||||||
xyreso = 0.02 # x-y grid resolution
|
xyreso = 0.02 # x-y grid resolution
|
||||||
yawreso = math.radians(3.1) # yaw angle resolution [rad]
|
|
||||||
ang, dist = file_read("lidar01.csv")
|
ang, dist = file_read("lidar01.csv")
|
||||||
ox = np.sin(ang) * dist
|
ox = np.sin(ang) * dist
|
||||||
oy = np.cos(ang) * dist
|
oy = np.cos(ang) * dist
|
||||||
pmap, minx, maxx, miny, maxy, xyreso = generate_ray_casting_grid_map(ox, oy, xyreso, yawreso, True)
|
pmap, minx, maxx, miny, maxy, xyreso = generate_ray_casting_grid_map(ox, oy, xyreso, True)
|
||||||
xyres = np.array(pmap).shape
|
xyres = np.array(pmap).shape
|
||||||
plt.figure(1, figsize=(10,4))
|
plt.figure(1, figsize=(10,4))
|
||||||
plt.subplot(122)
|
plt.subplot(122)
|
||||||
plt.imshow(pmap, cmap = "PiYG_r") # cmap = "binary" "PiYG_r" "PiYG_r" "bone" "bone_r" "RdYlGn_r"
|
plt.imshow(pmap, cmap="PiYG_r") # cmap = "binary" "PiYG_r" "PiYG_r" "bone" "bone_r" "RdYlGn_r"
|
||||||
plt.clim(-0.4, 1.4)
|
plt.clim(-0.4, 1.4)
|
||||||
plt.gca().set_xticks(np.arange(-.5, xyres[1], 1), minor = True)
|
plt.gca().set_xticks(np.arange(-.5, xyres[1], 1), minor=True)
|
||||||
plt.gca().set_yticks(np.arange(-.5, xyres[0], 1), minor = True)
|
plt.gca().set_yticks(np.arange(-.5, xyres[0], 1), minor=True)
|
||||||
plt.grid(True, which="minor", color="w", linewidth = .6, alpha = 0.5)
|
plt.grid(True, which="minor", color="w", linewidth=0.6, alpha=0.5)
|
||||||
plt.colorbar()
|
plt.colorbar()
|
||||||
plt.subplot(121)
|
plt.subplot(121)
|
||||||
plt.plot([oy, np.zeros(np.size(oy))], [ox, np.zeros(np.size(oy))], "ro-")
|
plt.plot([oy, np.zeros(np.size(oy))], [ox, np.zeros(np.size(oy))], "ro-")
|
||||||
@@ -165,6 +215,6 @@ def main():
|
|||||||
plt.grid(True)
|
plt.grid(True)
|
||||||
plt.show()
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user