简体   繁体   中英

Expanding blocks ( dilation ) in a binary grid

For an A* implementation (to generate a path for a 'car' robot), I need to adapt my model to take into account the car's 'width' and hence avoid obstacles.

One idea I got is to expand all obstacles by the car's width, that way all the cells that are too close to an obstacle will be also marked as obstacles.

I tried using two naive algorithms to do this, but it's still too slow (especially on big grids) because it goes through the same cells many times:

    unreachable = set()
    # I first add all the unreachables to a set to avoid 'propagation'
    for line in self.grid:
        for cell in line:
            if not cell.reachable:
                unreachable.add(cell)

    for cell in unreachable:
        # I set as unreachable all the cell's neighbours in a certain radius
        for nCell in self.neighbours( cell, int(radius/division) ):
            nCell.reachable = False

Here's the definition of neighbours:

def neighbours(self, cell, radius = 1, unreachables = False):
    neighbours = set()
    for i in xrange(-radius, radius + 1):
        for j in xrange(-radius, radius + 1):
            x = cell.x + j
            y = cell.y + i
            if 0 <= y < self.height and 0 <= x < self.width and (self.grid[y][x].reachable or unreachables )) :
                neighbours.add(self.grid[y][x])

    return neighbours

Is there any sequential algorithm (or O(n.log(n))) that could do the same thing ?

您要寻找的是所谓的Minkowski sum ,并且如果您的障碍物和汽车是凸的,则有一个线性算法可以对其进行计算。

I ended up using convolution product, with my 'map' (a matrix where '1' is an obstacle and '0' is a free cell) as the first operand and a matrix of the car's size and all filled with '1's as the second operand.

The convolution product of those two matrices gives a matrix where the cells that weren't in reach of any obstacle (that is: didn't have any obstacle in the neighberhood) have a value of '0', and those who had at least one obstacle in their neighberhood (that is a cell equal to '1') have a value != 0.

Here's the Python implementation (using scipy for the convolution product) :

    # r: car's radius; 1 : Unreachable ; 0 : Reachable
    car = scipy.array( [[1 for i in xrange(r)] for j in xrange(r)] )
    # Converting my map to a binary matrix
    grid = scipy.array( [[0 if self.grid[i][j].reachable else 1 for j in xrange(self.width)] for i in xrange(self.height)] )

    result = scipy.signal.fftconvolve( grid, car, 'same' )

    # Updating the map with the result
    for i in xrange(self.height):
        for j in xrange(self.width):
            self.grid[i][j].reachable = int(result[i][j]) == 0

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM