Skip to content

Commit

Permalink
Added separate robot reset.
Browse files Browse the repository at this point in the history
  • Loading branch information
Matthijs den Toom authored and Matthijs den Toom committed Feb 13, 2019
1 parent 9e6dc2d commit 88a62e0
Show file tree
Hide file tree
Showing 9 changed files with 111 additions and 62 deletions.
8 changes: 6 additions & 2 deletions gym_multi_robot/envs/foraging_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import numpy as np

from gym_multi_robot.envs.foraging_game import ForagingGame, ForagingGameStorage, StaticForagingGame
from gym_multi_robot.envs.foraging_robot import ForagingRobot
from gym_multi_robot.envs.multi_robot_env import MultiRobotEnv, check_path
from gym_multi_robot.envs.robot_reset import RandomRobotReset


class ForagingEnv(MultiRobotEnv):
Expand All @@ -12,12 +14,14 @@ class ForagingEnv(MultiRobotEnv):
a designated area.
"""

def __init__(self, x_dim=7, y_dim=5, num_tiles=2, target_area=(0, 0, 1, 1), seed=None, num_robots=5, env_storage_path=None):
def __init__(self, x_dim=7, y_dim=5, num_tiles=2, target_area=(0, 0, 1, 1), seed=None, num_robots=5,
env_storage_path=None):
super().__init__(seed)

if env_storage_path is not None:
env_storage = self.get_static_storage(env_storage_path)
assert isinstance(env_storage, ForagingGameStorage)
self.game = StaticForagingGame(env_storage)
else:
self.game = ForagingGame((x_dim, y_dim), num_tiles, target_area, num_robots)
self.game = ForagingGame((x_dim, y_dim), num_tiles, target_area,
RandomRobotReset(ForagingRobot, num_robots))
13 changes: 4 additions & 9 deletions gym_multi_robot/envs/foraging_game.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@

from gym_multi_robot.envs.foraging_robot import ForagingRobot
from gym_multi_robot.envs.multi_robot_game import MultiRobotGame
from gym_multi_robot.envs.robot_reset import StaticRobotReset


class ForagingGame(MultiRobotGame):
"""
This class represent the foraging game, with as goal bringing as many tiles as possible to the foraging area.
"""

def __init__(self, grid_size, num_tiles, target_area, num_robots=5):
def __init__(self, grid_size, num_tiles, target_area, robot_reset):
""" Target Area should be a tuple (x, y, x_length, y_length). """
super().__init__(grid_size, num_robots)
super().__init__(grid_size, robot_reset)

self.target_area = target_area
self.num_tiles = num_tiles
Expand Down Expand Up @@ -78,15 +79,9 @@ class StaticForagingGame(ForagingGame):
def __init__(self, game_storage):
assert isinstance(game_storage, ForagingGameStorage)
super().__init__(game_storage.grid.shape, game_storage.num_tiles, game_storage.target_area,
len(game_storage.robot_pos))
StaticRobotReset(ForagingRobot, game_storage.robot_pos))
self.default_grid = np.copy(game_storage.grid)
self.default_robot_pos = game_storage.robot_pos # contains a position at index 0 and a heading at index 1

def reset_grid(self):
self.grid = np.copy(self.default_grid)

def reset_robots(self):
self.robots = [ForagingRobot(i, self.default_robot_pos[i][1], self.default_robot_pos[i][0])
for i in range(len(self.default_robot_pos))]

return [robot.get_observation(self) for robot in self.robots]
23 changes: 6 additions & 17 deletions gym_multi_robot/envs/multi_robot_game.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
class MultiRobotGame:
""" This class defines a multi-robot game in a grid world."""

def __init__(self, grid_size, num_robots):
def __init__(self, grid_size, robot_reset):
self.grid_size = grid_size
self.grid = np.zeros((self.GRID_W, self.GRID_H), dtype=int)
self.robot_reset = robot_reset

self.num_robots = num_robots
self.robots = []
self.done = False
self.robot_cls = None # This variable should set the robot that is used.
Expand All @@ -33,13 +33,11 @@ def reset(self):
def reset_robots(self):
""" The method creates new robots at random positions."""

self.robots.clear()
for i in range(self.num_robots):
self.robots.append(self.randomly_drop_robot(i))
self.robot_reset.reset(self)
return [robot.get_observation(self) for robot in self.robots]

observations = [robot.get_observation(self) for robot in self.robots]

return observations
def add_robot(self, robot):
self.robots.append(robot)

def randomly_drop_tile(self):
while True:
Expand All @@ -48,15 +46,6 @@ def randomly_drop_tile(self):
self.grid[rand_loc[0]][rand_loc[1]] = 1
break

def randomly_drop_robot(self, identifier):
""" This function randomly drops a robot at a non occupied place."""
while True: # Return statement breaks the loop.
rand_loc = (random.randrange(0, self.GRID_W), random.randrange(0, self.GRID_H))

if not self.has_robot(rand_loc):
rand_heading = Heading.random_heading()
return self.robot_cls(identifier, location=rand_loc, heading=rand_heading)

def has_tile(self, location):
""" Returns true if the location has a grid."""
if self.inside_grid(location):
Expand Down
60 changes: 60 additions & 0 deletions gym_multi_robot/envs/robot_reset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import random

from gym_multi_robot.envs.gripping_robot import Heading


class RobotReset:
""" This class is an abstract class used for resetting a robot.."""

def __init__(self, robot_cls):
self.robot_cls = robot_cls

def reset(self, robot):
pass

@staticmethod
def clear_robots(game):
""" This function clears all robots from the given game."""

game.robots.clear()

@staticmethod
def add_robot(game, robot):
""" This function adds the robot to the given game."""
game.robots.append(robot)


class StaticRobotReset(RobotReset):
""" This class resets the robots by putting them on the grid at predefined locations."""

def __init__(self, robot_cls, robot_pos):
super().__init__(robot_cls)
self.robot_pos = robot_pos

def reset(self, game):
self.clear_robots(game)

for i in range(len(self.robot_pos)):
robot = self.robot_cls(i, self.robot_pos[i][1], self.robot_pos[i][0])
self.add_robot(game, robot)


class RandomRobotReset(RobotReset):
""" This class resets the robots by randomly putting them in the grid."""

def __init__(self, robot_cls, num_robots):
super().__init__(robot_cls)
self.num_robots = num_robots

def reset(self, game):
self.clear_robots(game)

for i in range(self.num_robots):
while True: # Return statement breaks the loop.
rand_loc = (random.randrange(0, game.GRID_W), random.randrange(0, game.GRID_H))

if not game.has_robot(rand_loc):
rand_heading = Heading.random_heading()
robot = self.robot_cls(i, rand_heading, rand_loc)
self.add_robot(game, robot)
break
26 changes: 14 additions & 12 deletions gym_multi_robot/envs/tests/test_foraging_game.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@
import unittest

from gym_multi_robot.envs.foraging_game import ForagingGame, StaticForagingGame, ForagingGameStorage
from gym_multi_robot.envs.foraging_robot import ForagingRobot
from gym_multi_robot.envs.gripping_robot import Heading
from gym_multi_robot.envs.robot_reset import RandomRobotReset


def static_correct_storage():

game = ForagingGame((7, 5), 2, (2, 2, 2, 2))
game = ForagingGame((7, 5), 2, (2, 2, 2, 2), RandomRobotReset(ForagingRobot, 5))
game.grid = np.zeros((7, 5), dtype=int)
game.grid[0][0] = 1
game.grid[0][1] = 1
Expand All @@ -18,13 +20,13 @@ def static_correct_storage():
class TestForagingGame(unittest.TestCase):

def test_one_by_one_field(self):
game = ForagingGame((1, 1), 1, (2, 2, 1, 1), 0)
game = ForagingGame((1, 1), 1, (2, 2, 1, 1), RandomRobotReset(ForagingRobot, 0))
game.reset()
self.assertEqual(1, game.num_tiles)
self.assertTrue(game.grid[0][0])

def test_on_target_location(self):
game = ForagingGame((7, 5), 1, (2, 2, 2, 2))
game = ForagingGame((7, 5), 1, (2, 2, 2, 2), RandomRobotReset(ForagingRobot, 5))
self.assertTrue(game.on_target_area((2, 2)))
self.assertTrue(game.on_target_area((2, 3)))
self.assertTrue(game.on_target_area((3, 2)))
Expand All @@ -35,17 +37,17 @@ def test_on_target_location(self):
self.assertFalse(game.on_target_area((4, 2)))

def test_no_drop_in_target_area(self):
game = ForagingGame((3, 3), 8, (2, 2, 1, 1))
game = ForagingGame((3, 3), 8, (2, 2, 1, 1), RandomRobotReset(ForagingRobot, 5))
self.assertTrue(game.on_target_area((2, 2)))
self.assertFalse(game.has_tile((2, 2)))

def test_get_fitness(self):
game = ForagingGame((3, 3), 8, (2, 2, 1, 1))
game = ForagingGame((3, 3), 8, (2, 2, 1, 1), RandomRobotReset(ForagingRobot, 5))
game.collected = 2
self.assertEqual(2, game.get_fitness())

def test_reset(self):
game = ForagingGame((3, 3), 8, (2, 2, 1, 1))
game = ForagingGame((3, 3), 8, (2, 2, 1, 1), RandomRobotReset(ForagingRobot, 5))
game.collected = 2

game.reset()
Expand All @@ -60,32 +62,32 @@ def test_static_pattern_reset(self):
self.assertTrue(game.has_tile((0, 1)))

def test_direction_to_target_area_1(self):
game = ForagingGame((4, 4), 8, (1, 2, 1, 1))
game = ForagingGame((4, 4), 8, (1, 2, 1, 1), RandomRobotReset(ForagingRobot, 5))

self.assertEqual((0, 0, 0, 0), game.direction_to_target_area((1, 2)))

def test_direction_to_target_area_2(self):
game = ForagingGame((4, 4), 8, (1, 2, 1, 1))
game = ForagingGame((4, 4), 8, (1, 2, 1, 1), RandomRobotReset(ForagingRobot, 5))

self.assertEqual((0, 1, 0, 0), game.direction_to_target_area((0, 2)))

def test_direction_to_target_area_3(self):
game = ForagingGame((4, 4), 8, (1, 2, 1, 1))
game = ForagingGame((4, 4), 8, (1, 2, 1, 1), RandomRobotReset(ForagingRobot, 5))

self.assertEqual((0, 0, 1, 0), game.direction_to_target_area((1, 1)))

def test_direction_to_target_area_4(self):
game = ForagingGame((4, 4), 8, (1, 2, 1, 1))
game = ForagingGame((4, 4), 8, (1, 2, 1, 1), RandomRobotReset(ForagingRobot, 5))

self.assertEqual((0, 0, 0, 1), game.direction_to_target_area((2, 2)))

def test_direction_to_target_area_5(self):
game = ForagingGame((4, 4), 8, (1, 2, 1, 1))
game = ForagingGame((4, 4), 8, (1, 2, 1, 1), RandomRobotReset(ForagingRobot, 5))

self.assertEqual((1, 0, 0, 0), game.direction_to_target_area((1, 3)))

def test_direction_to_target_area_angles(self):
game = ForagingGame((4, 4), 8, (1, 2, 1, 1))
game = ForagingGame((4, 4), 8, (1, 2, 1, 1), RandomRobotReset(ForagingRobot, 5))

self.assertEqual((0, 1, 1, 0), game.direction_to_target_area((0, 0)))
self.assertEqual((1, 0, 0, 1), game.direction_to_target_area((3, 3)))
Expand Down
9 changes: 5 additions & 4 deletions gym_multi_robot/envs/tests/test_foraging_robot.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from gym_multi_robot.envs.foraging_game import ForagingGame
from gym_multi_robot.envs.foraging_robot import ForagingRobot
from gym_multi_robot.envs.gripping_robot import Heading
from gym_multi_robot.envs.robot_reset import RandomRobotReset


class TestForagingRobot(unittest.TestCase):
Expand All @@ -27,7 +28,7 @@ def test_heading_observation_4(self):
def test_drop(self):
robot = ForagingRobot(10, Heading.WEST, (1, 1))
robot.hold_object = True
game = ForagingGame((2, 2), 2, (0, 0, 1, 1))
game = ForagingGame((2, 2), 2, (0, 0, 1, 1), RandomRobotReset(ForagingRobot, 5))
game.grid[1][1] = False
robot.drop(game)

Expand All @@ -37,7 +38,7 @@ def test_drop(self):
def test_drop_occupied(self):
robot = ForagingRobot(10, Heading.WEST)
robot.hold_object = True
game = ForagingGame((2, 2), 2, (1, 1, 1, 1))
game = ForagingGame((2, 2), 2, (1, 1, 1, 1), RandomRobotReset(ForagingRobot, 5))
game.grid[0][0] = True
robot.drop(game)

Expand All @@ -47,7 +48,7 @@ def test_drop_occupied(self):
def test_drop_foraging_area(self):
robot = ForagingRobot(10, Heading.WEST)
robot.hold_object = True
game = ForagingGame((2, 2), 2, (0, 0, 1, 1))
game = ForagingGame((2, 2), 2, (0, 0, 1, 1), RandomRobotReset(ForagingRobot, 5))
game.grid[0][0] = False
self.assertEqual(0, game.get_fitness())

Expand All @@ -57,7 +58,7 @@ def test_drop_foraging_area(self):

def test_empty_observation(self):
robot = ForagingRobot(10, Heading.NORTH, (5, 5))
game = ForagingGame((10, 10), 2, (0, 0, 1, 1))
game = ForagingGame((10, 10), 2, (0, 0, 1, 1), RandomRobotReset(ForagingRobot, 5))
game.grid = np.zeros((10, 10))
observation = robot.get_observation(game)

Expand Down
5 changes: 3 additions & 2 deletions gym_multi_robot/envs/tests/test_gripping_robot.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import numpy as np

from gym_multi_robot.envs.gripping_robot import Heading, GripperRobot
from gym_multi_robot.envs.robot_reset import RandomRobotReset
from gym_multi_robot.envs.tiling_pattern_game import TilingPatternGame


Expand Down Expand Up @@ -62,7 +63,7 @@ def test_rotate_robot_8(self):

def test_pickup(self):
robot = GripperRobot(10, Heading.WEST)
game = TilingPatternGame((1, 1), 1, 0)
game = TilingPatternGame((1, 1), 1, RandomRobotReset(GripperRobot, 0))
game.reset()
self.assertTrue(game.grid[0][0])
robot.pickup(game)
Expand Down Expand Up @@ -157,7 +158,7 @@ def test_move_off_screen_test_3(self):

def test_pickup_action(self):
robot = GripperRobot(10, Heading.WEST)
game = TilingPatternGame((1, 1), 1, 0)
game = TilingPatternGame((1, 1), 1, RandomRobotReset(GripperRobot, 0))
game.reset()
self.assertTrue(game.grid[0][0])
robot.step([False, 0, True, False], game)
Expand Down
15 changes: 8 additions & 7 deletions gym_multi_robot/envs/tests/test_tiling_pattern_game.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

import numpy as np

from gym_multi_robot.envs.gripping_robot import Heading
from gym_multi_robot.envs.gripping_robot import Heading, GripperRobot
from gym_multi_robot.envs.robot_reset import RandomRobotReset
from gym_multi_robot.envs.tiling_pattern_game import TilingPatternGame, StaticTilingPatternGame, \
TilingPatternGameStorage

Expand All @@ -22,34 +23,34 @@ def static_correct_storage():
class TestTilingPatternGame(unittest.TestCase):

def test_one_by_one_field(self):
game = TilingPatternGame((1, 1), 1, 0)
game = TilingPatternGame((1, 1), 1, RandomRobotReset(GripperRobot, 0))
game.reset()
self.assertEqual(1, game.num_tiles)
self.assertTrue(game.grid[0][0])

def test_2_by_2_field(self):
game = TilingPatternGame((2, 2), 2, 0)
game = TilingPatternGame((2, 2), 2, RandomRobotReset(GripperRobot, 0))
self.assertEqual(1, game.num_tiles)

def test_5x5_field(self):
game = TilingPatternGame((7, 5), 2, 0)
game = TilingPatternGame((7, 5), 2, RandomRobotReset(GripperRobot, 0))
self.assertEqual(12, game.num_tiles)

def test_11x11_field(self):
game = TilingPatternGame((11, 11), 2, 0)
game = TilingPatternGame((11, 11), 2, RandomRobotReset(GripperRobot, 0))
game.reset()
self.assertEqual(36, game.num_tiles)
self.assertEqual(36, np.sum(np.sum(game.grid)))

def test_inside_grid_true(self):
game = TilingPatternGame((11, 11), 2, 0)
game = TilingPatternGame((11, 11), 2, RandomRobotReset(GripperRobot, 0))
self.assertTrue(game.inside_grid((0, 0)))
self.assertTrue(game.inside_grid((10, 0)))
self.assertTrue(game.inside_grid((10, 10)))
self.assertTrue(game.inside_grid((0, 10)))

def test_inside_grid_false(self):
game = TilingPatternGame((11, 11), 2, 0)
game = TilingPatternGame((11, 11), 2, RandomRobotReset(GripperRobot, 0))
self.assertFalse(game.inside_grid((-1, 0)))
self.assertFalse(game.inside_grid((0, -1)))
self.assertFalse(game.inside_grid((-1, -1)))
Expand Down
Loading

0 comments on commit 88a62e0

Please sign in to comment.