Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed
Embedded/Maze/maze_solver.cpp
- Committer:
- ryan_whr
- Date:
- 2017-05-21
- Revision:
- 25:7155cb993870
File content as of revision 25:7155cb993870:
#include "maze_solver.h" #include "drivecontrol.h" DriveControl * driver = new DriveControl (); //============================================================== Maze:: Maze(){ int goal1 = MAZE_SIZE / 2; int goal2 = (MAZE_SIZE - 1) / 2; for (int i = 0; i < MAZE_SIZE; i++) { for (int j = 0; j < MAZE_SIZE; j++) { int min = min4(manhattan_dist(i, goal1, j, goal1), manhattan_dist(i, goal1, j, goal2), manhattan_dist(i, goal2, j, goal1), manhattan_dist(i, goal2, j, goal2)); maze[i][j] = new Cell(i, j, min); if (i == MAZE_SIZE - 1) { maze[i][j]->top_wall = true; } if (j == MAZE_SIZE - 1) { maze[i][j]->right_wall = true; } } } } int Maze:: manhattan_dist(int x1, int x2, int y1, int y2) { return abs(x1 - x2) + abs(y1 - y2); } // Function that takes the minimum of the four given distances int Maze:: min4(int a, int b, int c, int d) { int min; (a < b) ? min = a : min = b; if (c < min) min = c; if (d < min) min = d; return min; } bool Maze:: is_center(Cell *cell) { int x = cell->x; int y = cell->y; int goal1 = MAZE_SIZE / 2; int goal2 = (MAZE_SIZE - 1) / 2; if (manhattan_dist(y, goal1, x, goal1) == 0 || manhattan_dist(y, goal1, x, goal2) == 0 || manhattan_dist(y, goal2, x, goal1) == 0 || manhattan_dist(y, goal2, x, goal2) == 0) { return true; } return false; } bool Maze:: is_center(int x, int y) { int goal1 = MAZE_SIZE / 2; int goal2 = (MAZE_SIZE - 1) / 2; if (manhattan_dist(y, goal1, x, goal1) == 0 || manhattan_dist(y, goal1, x, goal2) == 0 || manhattan_dist(y, goal2, x, goal1) == 0 || manhattan_dist(y, goal2, x, goal2) == 0) { return true; } return false; } //============================================================ int Mouse:: get_direction(){ return direction; } void Mouse:: set_direction(int dir){ direction = dir; } bool Mouse:: get_front_sensor_value(){ bool has_wall; if(direction == NORTH){ if(mouse_x == MAZE_SIZE-1){ //if the mouse is at the topest row; return 1; } // TODO: change to check front sensor value. // TODO: has_wall = reference_maze->maze[mouse_x][mouse_y]->top_wall; has_wall = driver->has_front_wall(); detected_maze->maze[mouse_x][mouse_y]->top_wall = has_wall; } else if(direction == SOUTH){ if(mouse_x == 0){ return 1; } // TODO: has_wall = reference_maze->maze[mouse_x-1][mouse_y]->top_wall; //its bottom cell's upper wall has_wall = driver->has_front_wall(); detected_maze->maze[mouse_x-1][mouse_y]->top_wall = has_wall; } else if(direction == EAST){ if(mouse_y == MAZE_SIZE-1) return 1; // TODO: has_wall = reference_maze->maze[mouse_x][mouse_y]->right_wall; has_wall = driver->has_front_wall(); detected_maze->maze[mouse_x][mouse_y]->right_wall = has_wall; } else{ //WEST if(mouse_y == 0) return 1; // TODO: has_wall = reference_maze->maze[mouse_x][mouse_y-1]->right_wall; has_wall = driver->has_front_wall(); detected_maze->maze[mouse_x][mouse_y-1]->right_wall = has_wall; } return has_wall; } bool Mouse:: get_left_sensor_value(){ bool has_wall; if(direction == NORTH){ if(mouse_y == 0) //if the mouse is at the left_most column return 1; // TODO: has_wall = reference_maze->maze[mouse_x][mouse_y-1]->right_wall; has_wall = driver->has_left_wall(); detected_maze->maze[mouse_x][mouse_y-1]->right_wall = has_wall; } else if(direction == SOUTH){ if(mouse_y == MAZE_SIZE-1) return 1; // TODO: has_wall = reference_maze->maze[mouse_x][mouse_y]->right_wall; has_wall = driver->has_left_wall(); detected_maze->maze[mouse_x][mouse_y]->right_wall = has_wall; } else if(direction == EAST){ if(mouse_x == MAZE_SIZE-1) return 1; // TODO: has_wall = reference_maze->maze[mouse_x][mouse_y]->top_wall; has_wall = driver->has_left_wall(); detected_maze->maze[mouse_x][mouse_y]->top_wall = has_wall; } else{ if(mouse_x == 0) return 1; // TODO: has_wall = reference_maze->maze[mouse_x-1][mouse_y]->top_wall; has_wall = driver->has_left_wall(); detected_maze->maze[mouse_x-1][mouse_y]->top_wall = has_wall; } return has_wall; } bool Mouse:: get_right_sensor_value(){ bool has_wall; if(direction == NORTH){ if(mouse_y == MAZE_SIZE-1) //if the mouse is at the right_most column return 1; // TODO: has_wall = reference_maze->maze[mouse_x][mouse_y]->right_wall; has_wall = driver->has_right_wall(); detected_maze->maze[mouse_x][mouse_y]->right_wall = has_wall; } else if(direction == SOUTH){ if(mouse_y == 0) return 1; // TODO: has_wall = reference_maze->maze[mouse_x][mouse_y-1]->right_wall; has_wall = driver->has_right_wall(); detected_maze->maze[mouse_x][mouse_y-1]->right_wall = has_wall; } else if(direction == EAST){ if(mouse_x == 0) return 1; // TODO: has_wall = reference_maze->maze[mouse_x-1][mouse_y]->top_wall; has_wall = driver->has_right_wall(); detected_maze->maze[mouse_x-1][mouse_y]->top_wall = has_wall; } else{ if(mouse_x == MAZE_SIZE-1) return 1; // TODO: has_wall = reference_maze->maze[mouse_x][mouse_y]->top_wall; has_wall = driver->has_right_wall(); detected_maze->maze[mouse_x][mouse_y]->top_wall = has_wall; } return has_wall; } // the front sensor is 0, then the mouse can move in this direction bool Mouse:: can_move(){ //in the real world, instead of using 0, we need to set some constant //as a threshold for the sensor value; return (get_front_sensor_value()==0); } //Assumption: the maze[0][y] and maze[x][0] has left wall and bottom wall void Mouse:: check_open_neighbor(){ right_sensor = get_right_sensor_value(); front_sensor = get_front_sensor_value(); left_sensor = get_left_sensor_value(); if(direction == NORTH){ if(prev == SOUTH){ south_open = 1; } north_open = !front_sensor; east_open = !right_sensor; west_open = !left_sensor; } else if(direction == SOUTH){ if(prev == NORTH){ north_open = 1; } south_open = !front_sensor; east_open = !left_sensor; west_open = !right_sensor; } else if(direction == EAST){ if(prev == WEST){ west_open = 1; } south_open = !right_sensor; east_open = !front_sensor; north_open = !left_sensor; } else{ //WEST if(prev == EAST){ east_open = 1; } south_open = !left_sensor; west_open = !front_sensor; north_open = !right_sensor; } } // TODO: double check /* Check the minimum from a set of neighboring cells */ int Mouse:: min_open_neighbor(vector<Cell*> cells) { int min = MAX; for (vector<Cell *>::iterator it = cells.begin(); it != cells.end(); it++) { if ((*it)->dist < min) { min = (*it)->dist; } } // printf("min %d\n", min); return min; } void Mouse:: update_distance(){ Cell * curr; vector<Cell*> neighbor; vector<Cell*> open_neighbor; int min_dist; int x, y; int count = 0; stk.push_back(detected_maze->maze[mouse_x][mouse_y]); //printf("curr dist: %d\n", curr->dist); // while(!stk.empty()){ while(!stk.empty()){ curr = stk.back(); stk.pop_back(); x = curr->x; y = curr->y; if(x < MAZE_SIZE-1){ //top cell neighbor.push_back(detected_maze->maze[x+1][y]); // if(north_open) // open_neighbor.push_back(detected_maze->maze[mouse_x + 1][mouse_y]); if(!curr->top_wall){ open_neighbor.push_back(detected_maze->maze[x + 1][y]); } } if(y > 0){ //left cell neighbor.push_back(detected_maze->maze[x][y-1]); if (!(detected_maze->maze[x][y - 1]->right_wall)) { open_neighbor.push_back(detected_maze->maze[x][y - 1]); } // if(west_open) // open_neighbor.push_back(detected_maze->maze[mouse_x][mouse_y-1]); } if(x > 0){ //bottom cell neighbor.push_back(detected_maze->maze[x-1][y]); if (!(detected_maze->maze[x-1][y]->top_wall)) { open_neighbor.push_back(detected_maze->maze[x-1][y]); } // if(south_open) // open_neighbor.push_back(detected_maze->maze[mouse_x-1][mouse_y]); } if(y < MAZE_SIZE -1){ //right_cell neighbor.push_back(detected_maze->maze[x][y+1]); // if(east_open) // open_neighbor.push_back(detected_maze->maze[mouse_x][mouse_y+1]); if(!curr->right_wall){ open_neighbor.push_back(detected_maze->maze[x][y+1]); } } if (open_neighbor.empty()) { // printf("This should never happen, error\n"); neighbor.clear(); continue; } min_dist = min_open_neighbor(open_neighbor); open_neighbor.clear(); //printf("count %d with current cell <%d, %d>, dist: %d\n", count, curr->x, curr->y, curr->dist); if (curr->dist - 1 != min_dist) { curr->dist = min_dist + 1; for (vector<Cell *>::iterator it = neighbor.begin(); it != neighbor.end(); it++) { if (!detected_maze->is_center(*it)) { stk.push_back(*it); } } neighbor.clear(); } count++; } // printf("Finishing updating the distance\n"); } //void Mouse:: print_open_direction(){ // // printf("north open: %d ", north_open); // printf("south open: %d ", south_open); // printf("east open: %d ", east_open); // printf("west open: %d\n", west_open); //} // //void Mouse:: print_sensor_reading(){ // printf("current direction: %d\n", direction); // printf("right sensor: %d ", get_right_sensor_value()); // printf("left sensor: %d ",get_left_sensor_value()); // printf("front sensor: %d\n", get_front_sensor_value()); //} void Mouse:: move_one_cell(){ //check the open neighbor and update the wall at the same time // printf("CURRENT MOUSE POSITION <%d, %d>\n", mouse_x, mouse_y); // printf("prev direction is %d\n", prev); // printf("current direction is %d\n", direction); check_open_neighbor(); // printf("finish checking open neighbor\n"); //update the distance properly update_distance(); // printf("update_distance\n"); //pick the next cell and adjust_direction // print_sensor_reading(); // print_open_direction(); int min_dist = MAX; int temp; if(north_open){ temp = detected_maze->maze[mouse_x+1][mouse_y]->dist; if (temp < min_dist) { min_dist = temp; direction = NORTH; prev = SOUTH; } } if(east_open){ temp = detected_maze->maze[mouse_x][mouse_y+1]->dist; if (temp < min_dist){ min_dist = temp; direction = EAST; prev = WEST; } } // printf("after checking north\n"); if(south_open){ temp = detected_maze->maze[mouse_x-1][mouse_y]->dist; if (temp < min_dist){ min_dist = temp; direction = SOUTH; prev = NORTH; } } // printf("after checking south\n"); // printf("after checking east\n"); if(west_open){ temp = detected_maze->maze[mouse_x][mouse_y-1]->dist; if (temp < min_dist) { min_dist = temp; direction = WEST; prev = EAST; } } // printf("Finishing pick the next cell\n"); //Move if(direction == NORTH){ mouse_x += 1; } else if(direction == SOUTH){ mouse_x -= 1; } else if (direction == EAST){ mouse_y += 1; } else{ //WEST mouse_y -= 1; } north_open = 0; south_open = 0; east_open = 0; west_open = 0; // // printf("Finishing Reset, METHOD ENDS\n"); } bool Mouse::center_reached() { return !detected_maze->is_center(mouse_x, mouse_y); } int Mouse:: solve_maze(){ const int STRAIGHT = 0, LEFT = 1, RIGHT = 2, UTURN = 3; //while the mouse has not find the center of the Maze //while(!detected_maze->is_center(mouse_x, mouse_y)){ // move_one_cell(); // print_maze(); // } // TODO: double check move_one_cell(); //printf("mouse direction: %d \n", direction); int state = 5; if (prev_mouse_dir == direction){ state = STRAIGHT; } // Mouse is facing south else if (prev_mouse_dir == SOUTH && direction == NORTH) { state = UTURN; prev_mouse_dir = NORTH; } else if (prev_mouse_dir == SOUTH && direction == EAST) { state = LEFT; prev_mouse_dir = EAST; } else if (prev_mouse_dir == SOUTH && direction == WEST) { state = RIGHT; prev_mouse_dir = WEST; } // Mouse is facing north else if (prev_mouse_dir == NORTH && direction == EAST) { state = RIGHT; prev_mouse_dir = EAST; } else if (prev_mouse_dir == NORTH && direction == WEST) { state = LEFT; prev_mouse_dir = WEST; } else if (prev_mouse_dir == NORTH && direction == SOUTH) { state = UTURN; prev_mouse_dir = SOUTH; } // Mouse is facing west else if (prev_mouse_dir == WEST && direction == NORTH) { state = RIGHT; prev_mouse_dir = NORTH; } else if (prev_mouse_dir == WEST && direction == SOUTH) { state = LEFT; prev_mouse_dir = SOUTH; } else if (prev_mouse_dir == WEST && direction == EAST) { state = UTURN; prev_mouse_dir = EAST; } // Mouse is facing west else if (prev_mouse_dir == EAST && direction == NORTH) { state = LEFT; prev_mouse_dir = NORTH; } else if (prev_mouse_dir == EAST && direction == SOUTH) { state = RIGHT; prev_mouse_dir = SOUTH; } else if (prev_mouse_dir == EAST && direction == WEST) { state = UTURN; prev_mouse_dir = WEST; } return state; } Mouse:: Mouse(){ direction = NORTH; prev = -1; prev_mouse_dir = NORTH; north_open = 0; south_open = 0; east_open = 0; west_open = 0; mouse_x = 0; mouse_y = 0; // reference_maze = new Maze(); //we should not modify any thing inside reference_maze detected_maze = new Maze(); }