mazemods.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. """
  4. @author: Huiming Zhou
  5. """
  6. import numpy as np
  7. import matplotlib.pyplot as plt
  8. from matplotlib import colors
  9. # Makes the maze data with obstacles stored as black RGB values,
  10. # free space stored as white RGB values"
  11. def makeMaze(n, m, O):
  12. # Initialize to lists of 1. for RGB color index = white
  13. gridvals = [[[1. for i in range(3)] for col in range(n)] for row in range(m)]
  14. # Iterate through each obstacle
  15. for l in range(len(O)):
  16. # Find boundaries of current obstacle
  17. west, east = [O[l][0], O[l][1]]
  18. south, north = [O[l][2], O[l][3]]
  19. # Iterate through each cell of obstacle (clunky, but works)
  20. for i in range(west, east + 1):
  21. for j in range(south, north + 1):
  22. gridvals[j][i] = [0., 0., 0.] # Change entry to RGB black
  23. return gridvals
  24. # Function to actually plot the maze
  25. def maze(n, m, O):
  26. gridvals = makeMaze(n, m, O)
  27. fig, ax = plt.subplots() # make a figure + axes
  28. ax.imshow(gridvals) # Plot it
  29. ax.invert_yaxis() # Needed so that bottom left is (0,0)
  30. # ax.axis('off')
  31. # Checks for collisions given position x, control u, obstacle list O
  32. def collisionCheck(x, u, O):
  33. # Check input
  34. if u != (-1, 0) and u != (1, 0) and u != (0, -1) and u != (0, 1):
  35. print('collision_check error: Invalid input u!')
  36. return
  37. nextx = [x[i] + u[i] for i in range(len(x))]
  38. for l in range(len(O)):
  39. # Find boundaries of current obstacle
  40. west, east = [O[l][0], O[l][1]]
  41. south, north = [O[l][2], O[l][3]]
  42. # Check if nextx is contained in obstacle boundaries
  43. if west <= nextx[0] <= east and south <= nextx[1] <= north:
  44. return True
  45. # If we iterate through whole list and don't trigger the "if", then no collisions
  46. return False
  47. # Makes a piece of data with obstacles stored as black RGB values,
  48. # free space stored as white RGB values, and path stored as increasing hue of
  49. # yellow RGB values
  50. def makePath(xI, xG, path, n, m, O):
  51. # Obtain the grid populated with obstacles and free space RGB values first
  52. gridpath = makeMaze(n, m, O)
  53. L = len(path)
  54. # Iterate through the path to plot as increasing shades of yellow
  55. for l in range(L - 1):
  56. gridpath[path[l][1]][path[l][0]] = [1., 1., 1 - l / (L - 1)] # white-->yellow
  57. gridpath[xI[1]][xI[0]] = [0., 0., 1.] # Initial node (plotted as blue)
  58. gridpath[xG[1]][xG[0]] = [0., 1., 0.] # Goal node (plotted as green)
  59. return gridpath
  60. # Constructs path list from initial point and list of actions
  61. def getPathFromActions(xI, actions):
  62. L = len(actions)
  63. path = []
  64. nextx = xI
  65. for l in range(L):
  66. u = actions[l]
  67. if u != (-1, 0) and u != (1, 0) and u != (0, -1) and u != (0, 1):
  68. print('getPath error: Invalid input u!')
  69. return
  70. nextx = [nextx[i] + u[i] for i in range(len(nextx))] # nextx = nextx + u
  71. path.append(nextx) # Builds the path
  72. return path
  73. # If any collisions, cost is 999999, else cost is one for each action
  74. def getCostOfActions(xI, actions, O):
  75. L = len(actions)
  76. costsum = 0
  77. nextx = xI
  78. for l in range(L):
  79. u = actions[l]
  80. if u != (-1, 0) and u != (1, 0) and u != (0, -1) and u != (0, 1):
  81. print('getCostOfActions error: Invalid input u!')
  82. return
  83. collision = collisionCheck(nextx, u, O)
  84. if collision: return 999999999
  85. nextx = [nextx[i] + u[i] for i in range(len(nextx))] # nextx = nextx + u
  86. costsum = costsum + 1
  87. return costsum
  88. # If any collisions, cost is 999999, else cost is 2^(x[0]) for each action
  89. def stayWestCost(xI, actions, O):
  90. L = len(actions)
  91. costsum = 0
  92. nextx = xI
  93. for l in range(L):
  94. u = actions[l]
  95. if u != (-1, 0) and u != (1, 0) and u != (0, -1) and u != (0, 1):
  96. print('stayWestCost error: Invalid input u!')
  97. return
  98. collision = collisionCheck(nextx, u, O)
  99. if collision: return 999999999
  100. nextx = [nextx[i] + u[i] for i in range(len(nextx))] # nextx = nextx + u
  101. costsum = costsum + nextx[0] ** 2
  102. return costsum
  103. # If any collisions, cost is 999999, else cost is 2^(maxX - x[0]) for each action
  104. def stayEastCost(xI, actions, O):
  105. # Determine maximum x coordinate of workspace from obstacle list
  106. maxX = 0
  107. for k in range(len(O)):
  108. westxO = O[k][1]
  109. if westxO > maxX:
  110. maxX = westxO
  111. L = len(actions)
  112. costsum = 0
  113. nextx = xI
  114. for l in range(L):
  115. u = actions[l]
  116. if u != (-1, 0) and u != (1, 0) and u != (0, -1) and u != (0, 1):
  117. print('stayEastCost error: Invalid input u!')
  118. return
  119. collision = collisionCheck(nextx, u, O)
  120. if collision: return 999999999
  121. nextx = [nextx[i] + u[i] for i in range(len(nextx))] # nextx = nextx + u
  122. costsum = costsum + (maxX - nextx[0]) ** 2
  123. return costsum
  124. # Calculate different types of cost for searching algorithm
  125. def cost_calculation(xI, actions, O):
  126. simple_cost = getCostOfActions(xI, actions, O)
  127. west_cost = stayWestCost(xI, actions, O)
  128. east_cost = stayEastCost(xI, actions, O)
  129. return simple_cost, west_cost, east_cost
  130. # Extract path from results of searching algorithm
  131. def extractpath(xI, xG, parent, actions):
  132. pathback = [xG]
  133. actionsback = []
  134. actionsback.append(actions[xG])
  135. x_current = xG
  136. while parent[x_current] != x_current:
  137. x_current = parent[x_current]
  138. pathback.append(x_current)
  139. actionsback.append(actions[x_current])
  140. path_extract = list(reversed(pathback))
  141. actions_extract = list(reversed(actionsback))
  142. path_extract.pop(0)
  143. actions_extract.pop(0)
  144. return path_extract, actions_extract
  145. # Plots the path
  146. def showPath(xI, xG, path, n, m, O, name):
  147. gridpath = makePath(xI, xG, path, n, m, O)
  148. fig, ax = plt.subplots(1, 1) # make a figure + axes
  149. ax.imshow(gridpath) # Plot it
  150. ax.invert_yaxis() # Needed so that bottom left is (0,0)
  151. plt.title(name, fontdict=None)
  152. plt.show()