| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- #!/usr/bin/env python3
- # -*- coding: utf-8 -*-
- """
- @author: Huiming Zhou
- """
- import numpy as np
- import matplotlib.pyplot as plt
- from matplotlib import colors
- # Makes the maze data with obstacles stored as black RGB values,
- # free space stored as white RGB values"
- def makeMaze(n, m, O):
- # Initialize to lists of 1. for RGB color index = white
- gridvals = [[[1. for i in range(3)] for col in range(n)] for row in range(m)]
- # Iterate through each obstacle
- for l in range(len(O)):
- # Find boundaries of current obstacle
- west, east = [O[l][0], O[l][1]]
- south, north = [O[l][2], O[l][3]]
- # Iterate through each cell of obstacle (clunky, but works)
- for i in range(west, east + 1):
- for j in range(south, north + 1):
- gridvals[j][i] = [0., 0., 0.] # Change entry to RGB black
- return gridvals
- # Function to actually plot the maze
- def maze(n, m, O):
- gridvals = makeMaze(n, m, O)
- fig, ax = plt.subplots() # make a figure + axes
- ax.imshow(gridvals) # Plot it
- ax.invert_yaxis() # Needed so that bottom left is (0,0)
- # ax.axis('off')
- # Checks for collisions given position x, control u, obstacle list O
- def collisionCheck(x, u, O):
- # Check input
- if u != (-1, 0) and u != (1, 0) and u != (0, -1) and u != (0, 1):
- print('collision_check error: Invalid input u!')
- return
- nextx = [x[i] + u[i] for i in range(len(x))]
- for l in range(len(O)):
- # Find boundaries of current obstacle
- west, east = [O[l][0], O[l][1]]
- south, north = [O[l][2], O[l][3]]
- # Check if nextx is contained in obstacle boundaries
- if west <= nextx[0] <= east and south <= nextx[1] <= north:
- return True
- # If we iterate through whole list and don't trigger the "if", then no collisions
- return False
- # Makes a piece of data with obstacles stored as black RGB values,
- # free space stored as white RGB values, and path stored as increasing hue of
- # yellow RGB values
- def makePath(xI, xG, path, n, m, O):
- # Obtain the grid populated with obstacles and free space RGB values first
- gridpath = makeMaze(n, m, O)
- L = len(path)
- # Iterate through the path to plot as increasing shades of yellow
- for l in range(L - 1):
- gridpath[path[l][1]][path[l][0]] = [1., 1., 1 - l / (L - 1)] # white-->yellow
- gridpath[xI[1]][xI[0]] = [0., 0., 1.] # Initial node (plotted as blue)
- gridpath[xG[1]][xG[0]] = [0., 1., 0.] # Goal node (plotted as green)
- return gridpath
- # Constructs path list from initial point and list of actions
- def getPathFromActions(xI, actions):
- L = len(actions)
- path = []
- nextx = xI
- for l in range(L):
- u = actions[l]
- if u != (-1, 0) and u != (1, 0) and u != (0, -1) and u != (0, 1):
- print('getPath error: Invalid input u!')
- return
- nextx = [nextx[i] + u[i] for i in range(len(nextx))] # nextx = nextx + u
- path.append(nextx) # Builds the path
- return path
- # If any collisions, cost is 999999, else cost is one for each action
- def getCostOfActions(xI, actions, O):
- L = len(actions)
- costsum = 0
- nextx = xI
- for l in range(L):
- u = actions[l]
- if u != (-1, 0) and u != (1, 0) and u != (0, -1) and u != (0, 1):
- print('getCostOfActions error: Invalid input u!')
- return
- collision = collisionCheck(nextx, u, O)
- if collision: return 999999999
- nextx = [nextx[i] + u[i] for i in range(len(nextx))] # nextx = nextx + u
- costsum = costsum + 1
- return costsum
- # If any collisions, cost is 999999, else cost is 2^(x[0]) for each action
- def stayWestCost(xI, actions, O):
- L = len(actions)
- costsum = 0
- nextx = xI
- for l in range(L):
- u = actions[l]
- if u != (-1, 0) and u != (1, 0) and u != (0, -1) and u != (0, 1):
- print('stayWestCost error: Invalid input u!')
- return
- collision = collisionCheck(nextx, u, O)
- if collision: return 999999999
- nextx = [nextx[i] + u[i] for i in range(len(nextx))] # nextx = nextx + u
- costsum = costsum + nextx[0] ** 2
- return costsum
- # If any collisions, cost is 999999, else cost is 2^(maxX - x[0]) for each action
- def stayEastCost(xI, actions, O):
- # Determine maximum x coordinate of workspace from obstacle list
- maxX = 0
- for k in range(len(O)):
- westxO = O[k][1]
- if westxO > maxX:
- maxX = westxO
- L = len(actions)
- costsum = 0
- nextx = xI
- for l in range(L):
- u = actions[l]
- if u != (-1, 0) and u != (1, 0) and u != (0, -1) and u != (0, 1):
- print('stayEastCost error: Invalid input u!')
- return
- collision = collisionCheck(nextx, u, O)
- if collision: return 999999999
- nextx = [nextx[i] + u[i] for i in range(len(nextx))] # nextx = nextx + u
- costsum = costsum + (maxX - nextx[0]) ** 2
- return costsum
- # Calculate different types of cost for searching algorithm
- def cost_calculation(xI, actions, O):
- simple_cost = getCostOfActions(xI, actions, O)
- west_cost = stayWestCost(xI, actions, O)
- east_cost = stayEastCost(xI, actions, O)
- return simple_cost, west_cost, east_cost
- # Extract path from results of searching algorithm
- def extractpath(xI, xG, parent, actions):
- pathback = [xG]
- actionsback = []
- actionsback.append(actions[xG])
- x_current = xG
- while parent[x_current] != x_current:
- x_current = parent[x_current]
- pathback.append(x_current)
- actionsback.append(actions[x_current])
- path_extract = list(reversed(pathback))
- actions_extract = list(reversed(actionsback))
- path_extract.pop(0)
- actions_extract.pop(0)
- return path_extract, actions_extract
- # Plots the path
- def showPath(xI, xG, path, n, m, O, name):
- gridpath = makePath(xI, xG, path, n, m, O)
- fig, ax = plt.subplots(1, 1) # make a figure + axes
- ax.imshow(gridpath) # Plot it
- ax.invert_yaxis() # Needed so that bottom left is (0,0)
- plt.title(name, fontdict=None)
- plt.show()
|