now with correct seeding per setting and preperations for items

This commit is contained in:
Steffen Illium 2021-08-08 22:05:55 +02:00
parent 0f1de62f91
commit 244d4eed68
4 changed files with 47 additions and 11 deletions

View File

@ -1,3 +1,4 @@
import time
from pathlib import Path from pathlib import Path
from typing import List, Union, Iterable from typing import List, Union, Iterable
@ -97,6 +98,7 @@ class BaseFactory(gym.Env):
assert frames_to_stack != 1 and frames_to_stack >= 0, "'frames_to_stack' cannot be negative or 1." assert frames_to_stack != 1 and frames_to_stack >= 0, "'frames_to_stack' cannot be negative or 1."
# Attribute Assignment # Attribute Assignment
self._base_rng = np.random.default_rng(kwargs.get('seed', default=time.time_ns()))
self.movement_properties = movement_properties self.movement_properties = movement_properties
self.level_name = level_name self.level_name = level_name
self._level_shape = None self._level_shape = None
@ -173,7 +175,7 @@ class BaseFactory(gym.Env):
self._doors = Doors.from_tiles(tiles, context=self._tiles, has_area=self.doors_have_area) self._doors = Doors.from_tiles(tiles, context=self._tiles, has_area=self.doors_have_area)
# Agent Init on random positions # Agent Init on random positions
self._agents = Agents.from_tiles(np.random.choice(self._tiles, self.n_agents)) self._agents = Agents.from_tiles(self._base_rng.choice(self._tiles, self.n_agents))
entities = Entities() entities = Entities()
entities.register_additional_items([self._agents]) entities.register_additional_items([self._agents])

View File

@ -1,15 +1,15 @@
import time
from collections import deque
from typing import List, Union, NamedTuple from typing import List, Union, NamedTuple
import random
import numpy as np import numpy as np
from environments.helpers import Constants as c from environments.helpers import Constants as c
from environments import helpers as h from environments import helpers as h
from environments.factory.base.base_factory import BaseFactory from environments.factory.base.base_factory import BaseFactory
from environments.factory.base.objects import Agent, Action, Object, Slice from environments.factory.base.objects import Agent, Action, Object, Slice, Entity
from environments.factory.base.registers import Entities from environments.factory.base.registers import Entities
from environments.factory.renderer import Renderer, Entity from environments.factory.renderer import Renderer
from environments.utility_classes import MovementProperties from environments.utility_classes import MovementProperties
@ -23,16 +23,38 @@ NO_ITEM = 0
ITEM_DROP_OFF = -1 ITEM_DROP_OFF = -1
def inventory_slice_name(agent):
return f'{agent.name}_{INVENTORY}'
class DropOffLocation(Entity):
def __init__(self, *args, storage_size_until_full: int = 5, **kwargs):
super(DropOffLocation, self).__init__(*args, **kwargs)
self.storage = deque(maxlen=storage_size_until_full)
def place_item(self, item):
self.storage.append(item)
return True
@property
def is_full(self):
return self.storage.maxlen == len(self.storage)
class ItemProperties(NamedTuple): class ItemProperties(NamedTuple):
n_items: int = 1 # How much does the robot clean with one actions. n_items: int = 1 # How many items are there at the same time
spawn_frequency: int = 5 # Spawn Frequency in Steps spawn_frequency: int = 5 # Spawn Frequency in Steps
max_dropoff_storage_size: int = 5 # How many items are needed until the drop off is full
max_agent_storage_size: int = 5 # How many items are needed until the agent inventory is full
# noinspection PyAttributeOutsideInit # noinspection PyAttributeOutsideInit
class ItemFactory(BaseFactory): class ItemFactory(BaseFactory):
def __init__(self, item_properties: ItemProperties, *args, **kwargs): def __init__(self, item_properties: ItemProperties, *args, **kwargs):
super(ItemFactory, self).__init__(*args, **kwargs)
self.item_properties = item_properties self.item_properties = item_properties
self._item_rng = np.random.default_rng(kwargs.get('seed', default=time.time_ns()))
super(ItemFactory, self).__init__(*args, **kwargs)
@property @property
def additional_actions(self) -> Union[str, List[str]]: def additional_actions(self) -> Union[str, List[str]]:
@ -44,7 +66,8 @@ class ItemFactory(BaseFactory):
@property @property
def additional_slices(self) -> Union[Slice, List[Slice]]: def additional_slices(self) -> Union[Slice, List[Slice]]:
return [Slice(ITEM, np.zeros(self._level_shape)), Slice(INVENTORY, np.zeros(self._level_shape))] return [Slice(ITEM, np.zeros(self._level_shape))] + [
Slice(inventory_slice_name(agent), np.zeros(self._level_shape)) for agent in self._agents]
def _is_item_action(self, action): def _is_item_action(self, action):
if isinstance(action, str): if isinstance(action, str):
@ -53,10 +76,14 @@ class ItemFactory(BaseFactory):
def do_item_action(self, agent): def do_item_action(self, agent):
item_slice = self._slices.by_name(ITEM).slice item_slice = self._slices.by_name(ITEM).slice
inventory_slice = self._slices.by_name(inventory_slice_name(agent)).slice
if item := item_slice[agent.pos]: if item := item_slice[agent.pos]:
if item == ITEM_DROP_OFF: if item == ITEM_DROP_OFF:
self._slices.by_name(INVENTORY).slice[agent.pos] = item valid = self._item_drop_off.place_item(inventory_slice.sum())
item_slice[agent.pos] = NO_ITEM item_slice[agent.pos] = NO_ITEM
return True return True
else: else:
@ -75,6 +102,10 @@ class ItemFactory(BaseFactory):
if self.n_items > 1: if self.n_items > 1:
self._next_item_spawn = self.item_properties.spawn_frequency self._next_item_spawn = self.item_properties.spawn_frequency
def spawn_drop_off_location(self):
single_empty_tile = self._tiles.empty_tiles[0]
self._item_drop_off = DropOffLocation(storage_size_until_full=self.item_properties.max_dropoff_storage_size)
def calculate_reward(self) -> (int, dict): def calculate_reward(self) -> (int, dict):
pass pass

View File

@ -1,3 +1,4 @@
import time
from typing import List, Union, NamedTuple from typing import List, Union, NamedTuple
import random import random
@ -59,6 +60,7 @@ class SimpleFactory(BaseFactory):
def __init__(self, *args, dirt_properties: DirtProperties = DirtProperties(), **kwargs): def __init__(self, *args, dirt_properties: DirtProperties = DirtProperties(), **kwargs):
self.dirt_properties = dirt_properties self.dirt_properties = dirt_properties
self._renderer = None # expensive - don't use it when not required ! self._renderer = None # expensive - don't use it when not required !
self._dirt_rng = np.random.default_rng(kwargs.get('seed', default=time.time_ns()))
super(SimpleFactory, self).__init__(*args, **kwargs) super(SimpleFactory, self).__init__(*args, **kwargs)
def _flush_state(self): def _flush_state(self):
@ -108,7 +110,8 @@ class SimpleFactory(BaseFactory):
free_for_dirt = self._tiles.empty_tiles free_for_dirt = self._tiles.empty_tiles
# randomly distribute dirt across the grid # randomly distribute dirt across the grid
n_dirt_tiles = max(0, int(random.uniform(0, self.dirt_properties.max_spawn_ratio) * len(free_for_dirt))) new_spawn = self._dirt_rng.uniform(0, self.dirt_properties.max_spawn_ratio)
n_dirt_tiles = max(0, int(new_spawn * len(free_for_dirt)))
for tile in free_for_dirt[:n_dirt_tiles]: for tile in free_for_dirt[:n_dirt_tiles]:
new_value = dirt_slice[tile.pos] + self.dirt_properties.gain_amount new_value = dirt_slice[tile.pos] + self.dirt_properties.gain_amount
dirt_slice[tile.pos] = min(new_value, self.dirt_properties.max_local_amount) dirt_slice[tile.pos] = min(new_value, self.dirt_properties.max_local_amount)

View File

@ -109,7 +109,7 @@ if __name__ == '__main__':
with SimpleFactory(n_agents=1, dirt_properties=dirt_props, pomdp_radius=2, max_steps=400, parse_doors=True, with SimpleFactory(n_agents=1, dirt_properties=dirt_props, pomdp_radius=2, max_steps=400, parse_doors=True,
movement_properties=move_props, level_name='rooms', frames_to_stack=3, movement_properties=move_props, level_name='rooms', frames_to_stack=3,
omit_agent_slice_in_obs=True, combin_agent_slices_in_obs=True, record_episodes=False, omit_agent_slice_in_obs=True, combin_agent_slices_in_obs=True, record_episodes=False,
cast_shadows=True, doors_have_area=False cast_shadows=True, doors_have_area=False, seed=seed
) as env: ) as env:
if modeL_type.__name__ in ["PPO", "A2C"]: if modeL_type.__name__ in ["PPO", "A2C"]: