pyastar2d
pyastar2d copied to clipboard
Path is not straightforward when allow_diagonal is set to True, and to extract additional information from the pathfinding object.
Dear @hjweide
This is the result when allow_diagonal is set to True, and the output shown below is not desired from the program.

This is the result when allow_diagonal is set to False, and the output shown below is what was desired from the program.

I also noticed that the path infiltrates the walls for some unknown reasons.
Update: It does not seem like an infiltration but it seems to 'glow' around the path.

The presence of imperfect grayscale pixels were taken into account for in the code below:
maze = img.astype(np.float32)
maze[img < 240] = np.inf
maze[img >= 240] = 1.0
Could I ask you for your recommendation as to how I should go about optimising this? Could it be that diagonal movements are less costly than straight movements?
On the other hand, I would also like to ask if I am able to extract the path cost (this takes into account diagonal movements that cost sqrt(2))? If not, could you recommend how I should go about modifying the package contents? (refer to code snippet below)
for i in range(len(self.PATH)-1): #calculates the cost of the path
cur = self.PATH[i]
nxt = self.PATH[i+1]
if (cur.x_pos == nxt.x_pos and cur.y_pos != nxt.y_pos): #if vertical movement
self.COST+=1
elif (cur.x_pos != nxt.x_pos and cur.y_pos == nxt.y_pos): #if horizontal movement
self.COST+=1
elif (cur.x_pos != nxt.x_pos and cur.y_pos != nxt.y_pos): #if diagonal movement
self.COST += math.sqrt(2)
This is the result when allow_diagonal is set to True, and the output shown below is not desired from the program.
This is because you have a uniform grid and so there are many shortest paths that are all optimal even if they don't "look right". The A* algorithm simply picks whichever it discovers first, which is determined by the order in which the heuristic function adds nodes to the priority queue. The cost of the path is the nodes included in that path; the direction of movement is irrelevant. If you want straight paths you either need to disable diagonal moves or use a heuristic that breaks ties to get the types of paths you want. See some of the discussion and the changes from here: https://github.com/hjweide/pyastar2d/pull/29
Also note that A* is not really meant for uniform grids and so most ways of getting A* to produce straight paths will involve hacks. See this blog post for a great discussion on this topic: https://www.redblobgames.com/pathfinding/a-star/implementation.html#troubleshooting-ugly-path
Update: It does not seem like an infiltration but it seems to 'glow' around the path.
This is just a problem with the plotting or how you are saving / viewing the image. Be sure to plot as uint8, use (0, 0, 0) and (255, 255, 255) for black and white, and use a lossless format like PNG with a viewer that does not smooth.
I am able to extract the path cost
The easiest way to get the cost of the path would be something like this:
cost = np.sum(grid[path[:, 0], path[:, 1]])
Note that the direction of movement does not affect the cost of the path.