mirror of
https://github.com/illiumst/marl-factory-grid.git
synced 2025-05-23 07:16:44 +02:00
Correct Door Shadowing
This commit is contained in:
parent
e8d79d40e1
commit
b0aeb6f94f
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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]]]
|
||||
|
@ -20,8 +20,6 @@ class Constants(Enum):
|
||||
CLOSED_DOOR = 1
|
||||
OPEN_DOOR = -1
|
||||
|
||||
LEVEL_IDX = 0
|
||||
|
||||
ACTION = auto()
|
||||
COLLISIONS = auto()
|
||||
VALID = True
|
||||
|
Loading…
x
Reference in New Issue
Block a user