Correct Door Shadowing

This commit is contained in:
Steffen Illium 2021-07-28 11:26:19 +02:00
parent e8d79d40e1
commit b0aeb6f94f
5 changed files with 37 additions and 16 deletions

View File

@ -39,13 +39,13 @@ class BaseFactory(gym.Env):
elif not self.combin_agent_slices_in_obs and not self.omit_agent_slice_in_obs:
slices = self._slices.n
level_shape = (self.pomdp_radius * 2 + 1, self.pomdp_radius * 2 + 1) if self.pomdp_radius else self._level_shape
level_shape = (self.pomdp_r * 2 + 1, self.pomdp_r * 2 + 1) if self.pomdp_r else self._level_shape
space = spaces.Box(low=0, high=1, shape=(slices, *level_shape), dtype=np.float32)
return space
@property
def pomdp_diameter(self):
return self.pomdp_radius * 2 + 1
return self.pomdp_r * 2 + 1
@property
def movement_actions(self):
@ -100,7 +100,7 @@ class BaseFactory(gym.Env):
self.n_agents = n_agents
self.max_steps = max_steps
self.pomdp_radius = pomdp_radius
self.pomdp_r = pomdp_radius
self.combin_agent_slices_in_obs = combin_agent_slices_in_obs
self.omit_agent_slice_in_obs = omit_agent_slice_in_obs
self.cast_shadows = cast_shadows
@ -149,7 +149,7 @@ class BaseFactory(gym.Env):
x, y = self._slices.by_enum(c.LEVEL).shape
state = np.zeros((len(self._slices), x, y), dtype=np.float32)
state[0] = self._slices.by_enum(c.LEVEL).slice
if r := self.pomdp_radius:
if r := self.pomdp_r:
self._padded_obs_cube = np.full((len(self._slices), x + r*2, y + r*2), c.FREE_CELL.value, dtype=np.float32)
self._padded_obs_cube[0] = c.OCCUPIED_CELL.value
self._padded_obs_cube[:, r:r+x, r:r+y] = state
@ -293,14 +293,14 @@ class BaseFactory(gym.Env):
def _build_per_agent_obs(self, agent: Agent) -> np.ndarray:
first_agent_slice = self._slices.AGENTSTARTIDX
if r := self.pomdp_radius:
if r := self.pomdp_r:
x, y = self._level_shape
self._padded_obs_cube[:, r:r + x, r:r + y] = self._obs_cube
global_x, global_y = agent.pos
global_x += r
global_y += r
x0, x1 = max(0, global_x - self.pomdp_radius), global_x + self.pomdp_radius + 1
y0, y1 = max(0, global_y - self.pomdp_radius), global_y + self.pomdp_radius + 1
x0, x1 = max(0, global_x - self.pomdp_r), global_x + self.pomdp_r + 1
y0, y1 = max(0, global_y - self.pomdp_r), global_y + self.pomdp_r + 1
obs = self._padded_obs_cube[:, x0:x1, y0:y1]
else:
obs = self._obs_cube
@ -308,10 +308,29 @@ class BaseFactory(gym.Env):
if self.cast_shadows:
obs_block_light = [obs[idx] != c.OCCUPIED_CELL.value for idx, slice
in enumerate(self._slices) if slice.is_blocking_light]
door_shadowing = False
if door := self._doors.by_pos(agent.pos):
if door.is_closed:
for group in door.connectivity_subgroups:
if agent.last_pos not in group:
door_shadowing = True
if self.pomdp_r:
blocking = [tuple(np.subtract(x, agent.pos) + (self.pomdp_r, self.pomdp_r))
for x in group]
xs, ys = zip(*blocking)
else:
xs, ys = zip(*group)
obs_block_light[self._slices.get_idx(c.LEVEL)][xs, ys] = False
light_block_map = Map((np.prod(obs_block_light, axis=0) != True).astype(int))
light_block_map = light_block_map.do_fov(self.pomdp_radius, self.pomdp_radius, max(self._level_shape))
if self.pomdp_r:
light_block_map = light_block_map.do_fov(self.pomdp_r, self.pomdp_r, max(self._level_shape))
else:
light_block_map = light_block_map.do_fov(*agent.pos, max(self._level_shape))
if door_shadowing:
light_block_map[xs, ys] = 0
agent.temp_light_map = light_block_map
obs = (obs * light_block_map) - ((1 - light_block_map) * obs[self._slices.get_idx_by_name(c.LEVEL.name)])
obs = (obs * light_block_map) - ((1 - light_block_map) * obs[self._slices.get_idx(c.LEVEL)])
if self.combin_agent_slices_in_obs and self.n_agents > 1:
agent_obs = np.sum(obs[[key for key, l_slice in self._slices.items() if c.AGENT.name in l_slice.name and

View File

@ -211,6 +211,10 @@ class Door(Entity):
for a, b in possible_connections:
if not max(abs(np.subtract(a, b))) > 1:
self.connectivity.add_edge(a, b)
self.connectivity_subgroups = list(nx.algorithms.components.connected_components(self.connectivity))
for idx, group in enumerate(self.connectivity_subgroups):
for tile_pos in group:
self.connectivity.add_edge(tile_pos, idx)
if not closed_on_init:
self._open()
@ -239,7 +243,7 @@ class Door(Entity):
self.use()
def _open(self):
self.connectivity.add_edges_from([(self.pos, x) for x in self.connectivity.nodes])
self.connectivity.add_edges_from([(self.pos, x) for x in range(len(self.connectivity_subgroups))])
self._state = c.OPEN_DOOR
self.time_to_close = self.auto_close_interval

View File

@ -2,7 +2,6 @@ import numpy as np
from environments.helpers import Constants as c
FOV_RADIUS = 10
mult_array = np.asarray([
[1, 0, 0, -1, -1, 0, 0, 1],
[0, 1, -1, 0, 0, -1, 1, 0],
@ -14,11 +13,12 @@ mult_array = np.asarray([
class Map(object):
# Multipliers for transforming coordinates to other octants:
def __init__(self, map_array: np.ndarray):
def __init__(self, map_array: np.ndarray, diamond_slope: float = 0.9):
self.data = map_array
self.width, self.height = map_array.shape
self.light = np.full_like(self.data, c.FREE_CELL.value)
self.flag = c.FREE_CELL.value
self.d_slope = diamond_slope
def blocked(self, x, y):
return (x < 0 or y < 0
@ -47,7 +47,7 @@ class Map(object):
X, Y = cx + dx * xx + dy * xy, cy + dx * yx + dy * yy
# l_slope and r_slope store the slopes of the left and right
# extremities of the square we're considering:
l_slope, r_slope = (dx-0.5)/(dy+0.5), (dx+0.5)/(dy-0.5)
l_slope, r_slope = (dx-self.d_slope)/(dy+self.d_slope), (dx+self.d_slope)/(dy-self.d_slope)
if start < r_slope:
continue
elif end > l_slope:

View File

@ -60,7 +60,7 @@ class SimpleFactory(BaseFactory):
if not self._renderer: # lazy init
height, width = self._obs_cube.shape[1:]
self._renderer = Renderer(width, height, view_radius=self.pomdp_radius, fps=5)
self._renderer = Renderer(width, height, view_radius=self.pomdp_r, fps=5)
dirt_slice = self._slices.by_name(DIRT).slice
dirt = [Entity('dirt', tile.pos, min(0.15 + dirt_slice[tile.pos], 1.5), 'scale')
for tile in [tile for tile in self._tiles if dirt_slice[tile.pos]]]

View File

@ -20,8 +20,6 @@ class Constants(Enum):
CLOSED_DOOR = 1
OPEN_DOOR = -1
LEVEL_IDX = 0
ACTION = auto()
COLLISIONS = auto()
VALID = True