def main(): # Open Image File as a coloured image img = utils.open_image(settings.settingsImagePath) # Retrieve filtered image walls = utils.apply_vision_filter(img) ground = utils.apply_ground_filter(img) # Initialize Bot with startup settings bot = robot.Robot(x=settings.settingsStartX, y=settings.settingsStartY, direction=settings.settingsFaceDirection, wall_map=walls, ground_map=ground, no_of_squares_per_side=settings.settingsGridSideSquares, cell_side_length=len(img) // settings.settingsGridSideSquares) # Initialize user bot scripts src = settings.settingsSrcClass(bot) # Run setup src.setup() loop_img = numpy.copy(img) while True: # Refresh Screen utils.refresh_screen(loop_img, bot) # Loop loop_img = numpy.copy(img) ret = src.loop(loop_img) if ret == SimulationRunStatus.STOP_SIMULATION: # If stop simulation signal, Exit break
def dijkstra(stdscr, matrix, coordinates, animated_flag): """This is a Dijkstra's algorithm implementation for a weighted graph. This algorithm works with a weighted graph, but changes the given matrix. The weighted graph is simply converted from the matrix, and all weights are equal to 1.0. This implementation does not degrade to the BFS algorithm in the same named module, because BFS there doesn't use a graph, where neighbors of a node aren't listed in the order used in the utils.MOVES dictionary, so the node expansion order is not the same here. This is well visible due to the animation of these two algorithms using testovaci_data/test_5.txt input file. :param stdscr: a curses screen to animate the process :param matrix: a matrix with a pattern to work with :param coordinates: start and end points :param animated_flag: a flag - do we want to animate the process or not :return: the changed matrix, the start and end points coordinates, a number of opened nodes and a length of path to be printed either to the terminal or written to the output file """ start_node = coordinates[0] end_node = coordinates[1] matrix[start_node[1]][start_node[0]] = utils.START_NODE matrix[end_node[1]][end_node[0]] = utils.END_NODE graph = utils.matrix_to_weighted_graph(matrix) distances = {node: float('inf') for node in graph.keys()} priority_queue = [(0, start_node)] parents = {} visited_nodes = set() found = False distances[start_node] = 0.0 while len(priority_queue) > 0: utils.refresh_screen(stdscr, matrix, animated_flag) current_distance, current_node = heapq.heappop(priority_queue) if current_node == end_node: found = True for neighbor, cost in graph[current_node].items(): neighbor_distance = current_distance + cost if distances[neighbor] > neighbor_distance: distances[neighbor] = neighbor_distance if neighbor != start_node: matrix[neighbor[1]][neighbor[0]] = utils.OPENED_NODE visited_nodes.add(neighbor) heapq.heappush(priority_queue, (neighbor_distance, neighbor)) parents[neighbor] = current_node if current_node not in [start_node, end_node]: matrix[current_node[1]][current_node[0]] = utils.CLOSED_NODE if found: break path = utils.reconstruct_path(start_node, end_node, parents) path_length = len(path) node_count = len(visited_nodes) for col, row in path[:-1]: matrix[row][col] = utils.PATH_NODE matrix[end_node[1]][end_node[0]] = utils.END_NODE utils.show_path(stdscr, path, animated_flag) utils.show_final_message(stdscr, matrix.shape[0], 0, animated_flag) return matrix, coordinates, node_count, path_length
def refresh_screen(self, img: numpy.array) -> bool: """Refreshes Screen""" utils.refresh_screen(img, self.bot) return self.user_pressed_exit(self.waitDuration)
def random_search(stdscr, matrix, coordinates, animated_flag): """This is a Random Search algorithm implementation for an adjacency matrix. This algorithm doesn't convert a matrix into graph. It uses utils.MOVES dictionary to get all four possible directions of steps and then checks if the next node is valid to move to it. :param stdscr: a curses screen to animate the process :param matrix: a matrix with a pattern to work with :param coordinates: start and end points :param animated_flag: a flag - do we want to animate the process or not :return: the changed matrix, the start and end points coordinates, a number of opened nodes and a length of path to be printed either to the terminal or written to the output file """ start_node = coordinates[0] end_node = coordinates[1] matrix[start_node[1]][start_node[0]] = utils.START_NODE matrix[end_node[1]][end_node[0]] = utils.END_NODE node_counter = 0 found = False p = {} q = [start_node] while q: utils.refresh_screen(stdscr, matrix, animated_flag) current_node = random.choice(q) q.remove(current_node) if current_node == end_node: found = True for move_col, move_row in utils.MOVES.values(): next_col = current_node[0] + move_col next_row = current_node[1] + move_row if next_col < 0 or next_col > matrix.shape[1] - 1 \ or next_row < 0 or next_row > matrix.shape[0] - 1: continue elif matrix[next_row][next_col] in [ utils.FREE_NODE, utils.END_NODE ]: matrix[next_row][next_col] = utils.OPENED_NODE q.append((next_col, next_row)) p[(next_col, next_row)] = current_node node_counter += 1 if current_node not in [start_node, end_node]: matrix[current_node[1]][current_node[0]] = utils.CLOSED_NODE if found: break path = utils.reconstruct_path(start_node, end_node, p) path_length = len(path) for col, row in path[:-1]: matrix[row][col] = utils.PATH_NODE matrix[end_node[1]][end_node[0]] = utils.END_NODE utils.show_path(stdscr, path, animated_flag) utils.show_final_message(stdscr, matrix.shape[0], 0, animated_flag) return matrix, coordinates, node_counter, path_length
def greedy_search(stdscr, matrix, coordinates, animated_flag): """This is a Greedy Search algorithm implementation for a weighted graph. This algorithm works with a weighted graph, but changes the given matrix. The weighted graph is simply converted from the matrix, and all weights are equal to 1.0. Heuristics is built by the utils.build_heuristics(...) function and then applied to get the priority of a node to be extended. :param stdscr: a curses screen to animate the process :param matrix: a matrix with a pattern to work with :param coordinates: start and end points :param animated_flag: a flag - do we want to animate the process or not :return: the changed matrix, the start and end points coordinates, a number of opened nodes and a length of path to be printed either to the terminal or written to the output file """ start_node = coordinates[0] end_node = coordinates[1] matrix[start_node[1]][start_node[0]] = utils.START_NODE matrix[end_node[1]][end_node[0]] = utils.END_NODE graph = utils.matrix_to_weighted_graph(matrix) heuristics = utils.build_heuristics(end_node, graph) priority_queue = [(heuristics[start_node], start_node)] closed_nodes = set() parents = {} found = False node_counter = 0 while len(priority_queue) > 0: utils.refresh_screen(stdscr, matrix, animated_flag) _, current_node = heapq.heappop(priority_queue) if current_node == end_node: found = True for neighbor in graph[current_node].keys(): if (heuristics[neighbor], neighbor) not in priority_queue and neighbor not in closed_nodes: matrix[neighbor[1]][neighbor[0]] = utils.OPENED_NODE heapq.heappush(priority_queue, (heuristics[neighbor], neighbor)) parents[neighbor] = current_node node_counter += 1 closed_nodes.add(current_node) if current_node not in [start_node, end_node]: matrix[current_node[1]][current_node[0]] = utils.CLOSED_NODE if found: break path = utils.reconstruct_path(start_node, end_node, parents) path_length = len(path) for col, row in path[:-1]: matrix[row][col] = utils.PATH_NODE matrix[end_node[1]][end_node[0]] = utils.END_NODE utils.show_path(stdscr, path, animated_flag) utils.show_final_message(stdscr, matrix.shape[0], 0, animated_flag) return matrix, coordinates, node_counter, path_length
def refresh_screen(self, img: numpy.array) -> bool: """Refreshes Screen""" utils.refresh_screen(img, self.bot) return self.user_pressed_exit(WAIT_DURATION)