示例#1
0
    def __init__(self):
        self.cell_matrix = [[None for y in range(MAP_ROW)] for x in range(MAP_COL)] #initialise the matrix

        for y in range(MAP_ROW): #create Cell objects for each cell in the matrix
            for x in range(MAP_COL):
                coord = Coord(x, y)
                self.cell_matrix[coord.get_x()][coord.get_y()] = Cell(coord)

        self.mark_border_cells_dangerous()
示例#2
0
 def orientation_to_unit_displacement(orientation: Orientation) -> Coord:
     if orientation == Orientation.EAST: return Coord(1, 0)
     elif orientation == Orientation.WEST: return Coord(-1, 0)
     elif orientation == Orientation.NORTH: return Coord(0, 1)
     elif orientation == Orientation.SOUTH: return Coord(0, -1)
     else:
         raise Exception(
             f'Invalid orientation: tried moving {orientation.name}. orientation_to_unit_displacement only implemented for cardinal directions'
         )
示例#3
0
 def calculate_rwh_vantage(self, ue: Coord) -> list:
     # vantage points are cells where robot will stand next to an obstacle
     rwh_vantage_points = []
     
     for disp in [(-2,0), (0,2), (0,-2), (2,0)]:
         coord = Coord(disp[0], disp[1])
         rwh_vantage_points.append(ue.add(coord))
         
     return rwh_vantage_points
示例#4
0
 def calculate_vantage_points(self, ue: Coord) -> list:
     # vantage points are cells where robot can see unexplored cells
     vantage_points_matrix = []
     for i in range(SURE_VIEW_RANGE):
         vantage_points = []
         for disp in [(0,i+2), (i+2,0), (0,-i-2), (-i-2,0), (-1,i+2), (1,i+2), (i+2,1), (i+2,-1), (1,-i-2), (-1,-i-2), (-i-2,-1), (-i-2,1)]:
             coord = Coord(disp[0], disp[1])
             vantage_points.append(ue.add(coord))
         vantage_points_matrix.append(vantage_points)
     return vantage_points_matrix
示例#5
0
 def displacement_to_orientation(displacement: Coord) -> Orientation:
     x = displacement.get_x()
     y = displacement.get_y()
     # this if list should be refactored into a constant, along with the one in Arena.py
     if x > 0 and y == 0: return Orientation.EAST
     elif x < 0 and y == 0: return Orientation.WEST
     elif x == 0 and y > 0: return Orientation.NORTH
     elif x == 0 and y < 0: return Orientation.SOUTH
     else:
         raise Exception(
             f'Invalid displacement: tried moving {x}, {y}. displacement_to_orientation only implemented for cardinal directions'
         )
示例#6
0
    def print_mdf(self):
        explored_bin_str = "11"
        obstacle_bin_str = ""

        for y in range(MAP_ROW):
            for x in range(MAP_COL):
                coord = Coord(x,y)
                if self.arena.get_cell_at_coord(coord).is_explored():
                    explored_bin_str += "1"
                    if self.arena.get_cell_at_coord(coord).is_obstacle():
                        obstacle_bin_str += "1"
                    else:
                        obstacle_bin_str += "0"
                else:
                    explored_bin_str += "0"

        explored_bin_str += "11"

        if len(obstacle_bin_str) % 8 != 0:
            num_pad_bits = 8 - len(obstacle_bin_str) % 8
            obstacle_bin_str += "0" * num_pad_bits 

        explored_hex_str = f"{int(explored_bin_str, 2):X}"
        print(explored_hex_str)

        obstacle_hex_str = f"{int(obstacle_bin_str, 2):X}"
        num_pad_bits = math.ceil(len(obstacle_bin_str) / 4) - len(obstacle_hex_str)
        print("0" * num_pad_bits + obstacle_hex_str)
示例#7
0
    def convert_arena_to_mdf(self, arena):
        explored_bin_str = "11"
        obstacle_bin_str = ""

        for y in range(MAP_ROW):
            for x in range(MAP_COL):
                coord = Coord(x, y)
                if arena.get_cell_at_coord(coord).is_explored():
                    explored_bin_str += "1"
                    if arena.get_cell_at_coord(coord).is_obstacle():
                        obstacle_bin_str += "1"
                    else:
                        obstacle_bin_str += "0"
                else:
                    explored_bin_str += "0"

        explored_bin_str += "11"

        if len(obstacle_bin_str) % 8 != 0:
            num_pad_bits = 8 - len(obstacle_bin_str) % 8
            obstacle_bin_str += "0" * num_pad_bits

        explored_hex_str = f"{int(explored_bin_str, 2):X}"  # explored bin string is never empty (only 0s)

        if obstacle_bin_str:
            obstacle_hex_str = f"{int(obstacle_bin_str, 2):X}"
            num_pad_bits = math.ceil(
                len(obstacle_bin_str) / 4) - len(obstacle_hex_str)
            padded_obstacle_hex_str = "0" * num_pad_bits + obstacle_hex_str
        else:
            padded_obstacle_hex_str = ""

        return explored_hex_str, padded_obstacle_hex_str
示例#8
0
 def get_eight_adjacent_in_arena(self, coord: Coord) -> list:
     adj = []
     for displacement in Arena.EIGHT_ADJACENCY:
         adj_coord = coord.add(displacement)
         if self.coord_is_valid(adj_coord):
             adj.append(adj_coord)
     return adj
示例#9
0
 def update_dangerous_cells(self) -> None:
     for y in range(MAP_ROW):
         for x in range(MAP_COL):
             cur = Coord(x, y)
             cell = self.get_cell_at_coord(cur)
             if cell.is_obstacle():
                 cell.set_is_dangerous(True)
             else:
                 cell.set_is_dangerous(False)
             for displacement in Arena.EIGHT_ADJACENCY:
                 adj = cur.add(displacement)
                 if not self.coord_is_valid(adj):
                     continue
                 if self.get_cell_at_coord(adj).is_obstacle():
                     self.get_cell_at_coord(cur).set_is_dangerous(True)
                     break
     self.mark_border_cells_dangerous()
示例#10
0
 def list_known_obstacles(self) -> list:
     l = []
     for y in range(MAP_ROW):
         for x in range(MAP_COL):
             coord = Coord(x,y)
             if self.get_cell_at_coord(coord).is_obstacle():
                 l.append(coord)
     return l
示例#11
0
 def list_unexplored_coords(self) -> list:
     l = []
     for y in range(MAP_ROW):
         for x in range(MAP_COL):
             coord = Coord(x,y)
             if not self.get_cell_at_coord(coord).is_explored():
                 l.append(coord)
     return l
示例#12
0
    def get_coverage_percentage(self) -> int:
        explored = 0
        for y in range(MAP_ROW): 
            for x in range(MAP_COL):
                coord = Coord(x, y)
                if self.get_cell_at_coord(coord).is_explored():
                    explored += 1

        return explored / 300 * 100
示例#13
0
    def main(self):
        i = 0
        while True:
            data = self.rx.recv_json()
            # print(data)

            print('qsize ', self.q_size)
            if data['type'] == 'sensor':
                if self.agent_task == AgentTask.EXPLORE or self.agent_task == AgentTask.IMAGEREC:
                    self.update_percepts(data)
                if self.q_size == 0:
                    self.step()
                print('got sensor data')
            elif data['type'] == 'move_done':
                self.q_size -= 1
                print('got move_done')
            elif data['type'] == 'start':
                self.q_size = 0
                if self.agent_task == AgentTask.FAST:
                    while not self.agent.get_robot_info().get_coord().is_equal(
                            Coord(13, 18)):
                        self.update_percepts(None)
                        self.step()
                else:
                    self.step()
                print('got start')
            elif data['type'] == 'init':
                self.init(data)
                self.q_size = 1
                print('got init')
            elif data['type'] == 'waypoint':
                self.waypoint = Coord(data['data']['x'], data['data']['y'])
                print('got waypoint')
            elif data['type'] == 'ping':
                self.tx.send_json({'type': 'pong'})
            elif data['type'] == 'terminate':
                print('got terminate, quitting')
                return

            print('received message ', i)
            i += 1
示例#14
0
 def get_coords_in_line(self, sensor_displacement: Coord,
                        displacement_per_step: Coord,
                        view_range: int) -> list:
     all_possible_visible_coords = []
     cur_coord = self.robot_info.get_coord()
     for i in range(view_range):
         coord = cur_coord.add(sensor_displacement).add(
             displacement_per_step.multiply(i))
         if self.arena.coord_is_valid(coord):
             all_possible_visible_coords.append(coord)
         else:
             break
     return all_possible_visible_coords
示例#15
0
    def parse_arena_string(string: str) -> Arena:
        cl = list(string)
        arena = Arena()

        # set obstacles in arena
        obstacle_list = []
        i=0
        for y in range(MAP_ROW-1, -1, -1): # counting from top to bottom
            for x in range(MAP_COL):
                coord = Coord(x, y)
                if cl[i] == '\n':
                    i = i + 1
                if cl[i] == '1':
                    arena.get_cell_at_coord(coord).increment_is_obstacle(delta=4)
                    obstacle_list.append(coord)
                elif cl[i] == '0':
                    pass # not obstacle assumed
                i = i+1
                if y in [0,MAP_ROW-1] or x in [0,MAP_COL-1]:
                    # cells at edge of arena are too close to the walls
                    arena.get_cell_at_coord(coord).set_is_dangerous(True)

        # set danger flag for cells too close to obstacles
        for obs in obstacle_list:
            displacements = [
                Coord(-1, -1),
                Coord(-1, 0),
                Coord(-1, 1),
                Coord(0, -1),
                Coord(0, 1),
                Coord(1, -1),
                Coord(1, 0),
                Coord(1, 1)
            ]
            for d in displacements:
                dangerous_coord = obs.add(d)
                if 0 <= dangerous_coord.get_x() < 15 and 0 <= dangerous_coord.get_y() < 20:
                    arena.get_cell_at_coord(dangerous_coord).set_is_dangerous(True)
        
        return arena
示例#16
0
 def mark_border_cells_dangerous(self) -> None:
     for y in range(MAP_ROW):
         for x in range(MAP_COL):
             if y in [0,MAP_ROW-1] or x in [0,MAP_COL-1]:
                 # cells at edge of arena are too close to the walls
                 self.get_cell_at_coord(Coord(x,y)).set_is_dangerous(True)
示例#17
0
class Arena:

    ADJACENCY = [
        Coord(0, 1),
        Coord(1, 0),
        Coord(0, -1),
        Coord(-1, 0)
    ]

    EIGHT_ADJACENCY = [
        Coord(1, 1),
        Coord(0, 1),
        Coord(-1, 1),
        Coord(-1, 0),
        Coord(-1, -1),
        Coord(0, -1),
        Coord(1, -1),
        Coord(1, 0)
    ]

    def __init__(self):
        self.cell_matrix = [[None for y in range(MAP_ROW)] for x in range(MAP_COL)] #initialise the matrix

        for y in range(MAP_ROW): #create Cell objects for each cell in the matrix
            for x in range(MAP_COL):
                coord = Coord(x, y)
                self.cell_matrix[coord.get_x()][coord.get_y()] = Cell(coord)

        self.mark_border_cells_dangerous()

    def coord_is_valid(self, coord: Coord) -> bool:
        return coord.get_x() in range(MAP_COL) and coord.get_y() in range(MAP_ROW)

    def get_cell_at_coord(self, coord):
        return self.cell_matrix[coord.get_x()][coord.get_y()]

    def get_four_adjacent_in_arena(self, coord: Coord) -> list:
        adj = []
        for displacement in Arena.ADJACENCY:
            adj_coord = coord.add(displacement)
            if self.coord_is_valid(adj_coord):
                adj.append(adj_coord)
        return adj

    def get_eight_adjacent_in_arena(self, coord: Coord) -> list:
        adj = []
        for displacement in Arena.EIGHT_ADJACENCY:
            adj_coord = coord.add(displacement)
            if self.coord_is_valid(adj_coord):
                adj.append(adj_coord)
        return adj

    def calculate_adjacent_lists(self, coord) -> dict:
        adj_safe, adj_unb, adj_blocked = [], [], []
        for adj_coord in self.get_four_adjacent_in_arena(coord):
            cell = self.get_cell_at_coord(adj_coord)
            if cell.is_obstacle():
                adj_blocked.append(adj_coord)
            else:
                adj_unb.append(adj_coord)
                if not cell.is_dangerous():
                    adj_safe.append(adj_coord)
        return {
            'safe': adj_safe,
            'unblocked': adj_unb,
            'blocked': adj_blocked
        }
    
    # def get_adjacent_blocked(self, coord) -> list:
    #     return self.calculate_adjacent_lists(coord)['blocked']

    def get_adjacent_safe(self, coord) -> list:
        return self.calculate_adjacent_lists(coord)['safe']

    # def get_adjacent_unblocked(self, coord) -> list:
    #     return self.calculate_adjacent_lists(coord)['unblocked']
    
    # def mark_dangerous_cells_around_obstacle(self, coord, is_dangerous):
    #     for displacement in Arena.EIGHT_ADJACENCY:
    #         adj_coord = coord.add(displacement)
    #         if self.coord_is_valid(adj_coord):
    #             self.get_cell_at_coord(adj_coord).set_is_dangerous(is_dangerous)

    def update_dangerous_cells(self) -> None:
        for y in range(MAP_ROW):
            for x in range(MAP_COL):
                cur = Coord(x, y)
                cell = self.get_cell_at_coord(cur)
                if cell.is_obstacle():
                    cell.set_is_dangerous(True)
                else:
                    cell.set_is_dangerous(False)
                for displacement in Arena.EIGHT_ADJACENCY:
                    adj = cur.add(displacement)
                    if not self.coord_is_valid(adj):
                        continue
                    if self.get_cell_at_coord(adj).is_obstacle():
                        self.get_cell_at_coord(cur).set_is_dangerous(True)
                        break
        self.mark_border_cells_dangerous()

    def get_coverage_percentage(self) -> int:
        explored = 0
        for y in range(MAP_ROW): 
            for x in range(MAP_COL):
                coord = Coord(x, y)
                if self.get_cell_at_coord(coord).is_explored():
                    explored += 1

        return explored / 300 * 100
    
    def list_unexplored_cells(self) -> list:
        # returns CELLS not coords
        l = []
        for row in self.cell_matrix:
            for cell in row:
                if not cell.is_explored():
                    l.append(cell)
        return l

    def list_unexplored_coords(self) -> list:
        l = []
        for y in range(MAP_ROW):
            for x in range(MAP_COL):
                coord = Coord(x,y)
                if not self.get_cell_at_coord(coord).is_explored():
                    l.append(coord)
        return l

    def set_all_explored(self) -> None:
        for row in self.cell_matrix:
            for cell in row:
                cell.set_is_explored(True)

    def mark_border_cells_dangerous(self) -> None:
        for y in range(MAP_ROW):
            for x in range(MAP_COL):
                if y in [0,MAP_ROW-1] or x in [0,MAP_COL-1]:
                    # cells at edge of arena are too close to the walls
                    self.get_cell_at_coord(Coord(x,y)).set_is_dangerous(True)


# Used in Image Rec Algo:
    def all_obstacles_seen(self) -> bool:
        for coord in self.list_known_obstacles():
            if not self.get_cell_at_coord(coord).is_seen():
                return False
        return True
    
    def list_known_obstacles(self) -> list:
        l = []
        for y in range(MAP_ROW):
            for x in range(MAP_COL):
                coord = Coord(x,y)
                if self.get_cell_at_coord(coord).is_obstacle():
                    l.append(coord)
        return l

    def get_nearest_obstacle_adj_coord(self, cur_coord: Coord) -> Coord: # if empty is true, return the adj coord, else return the obstacle itself
        obstacle_coord_list = self.list_known_obstacles()
        unseen_obstacles_list = []
        target = None

        for item in obstacle_coord_list:
            if not self.get_cell_at_coord(item).is_seen():
                if item.get_x() != 0 and item.get_x() != 14 and item.get_y() != 0 and item.get_y() != 19:
                    unseen_obstacles_list.append(item)

        # store a list of all vantages, then take the nearest one
        rwh_vantage_list = []
        for obstacle in unseen_obstacles_list:
            for rwh_vantage in self.calculate_rwh_vantage(obstacle): # iterate through the obstacle's vantage points
                if not self.coord_is_valid(rwh_vantage):
                    continue
                if self.get_cell_at_coord(rwh_vantage).is_obstacle():
                    continue
                if self.get_cell_at_coord(rwh_vantage).is_dangerous():
                    continue
                if not self.get_cell_at_coord(rwh_vantage).is_explored():
                    continue

                distance = rwh_vantage.subtract(cur_coord).manhattan_distance()
                rwh_vantage_list.append((distance, rwh_vantage, obstacle))

        try:
            target = sorted(rwh_vantage_list, key=lambda x: x[0])[0]
            return target[1], target[2]
        except IndexError:
            print("NO MORE UNSEEN OBSTACLES")
            return None, None

        


    def calculate_rwh_vantage(self, ue: Coord) -> list:
        # vantage points are cells where robot will stand next to an obstacle
        rwh_vantage_points = []
        
        for disp in [(-2,0), (0,2), (0,-2), (2,0)]:
            coord = Coord(disp[0], disp[1])
            rwh_vantage_points.append(ue.add(coord))
            
        return rwh_vantage_points
示例#18
0
 def coord_is_valid(self, coord: Coord) -> bool:
     return coord.get_x() in range(MAP_COL) and coord.get_y() in range(MAP_ROW)
 def heuristic(cur: Coord, target: Coord) -> int:
     return target.subtract(cur).manhattan_distance()
示例#20
0
grey = [100, 100, 100]
red = [255, 0, 0]
green = [0, 255, 0]
yellow = [255, 255, 0]
purple = [138, 43, 226]
light_blue = [135, 206, 250]

# Defining map dimensions
MAP_ROW = 20
MAP_COL = 15
TILE_SIZE = 20
DIS_X = 300
DIS_Y = 400

# Defining start, end and waypoint coord
START_COORD = Coord(1, 1)
END_COORD = Coord(13, 18)
WAYPOINT = Coord(4, 4)

ALGO_RETURNS_FULL_PATH = False


class ArenaDisplayMode(Enum):
    OBSERVED = 0
    TRUE = 1


ARENA_DISPLAY_MODE = ArenaDisplayMode.OBSERVED


class Orientation(Enum):