Bladeren bron

Implemented mechanism to prevent seeing through walls

Maxime Chevalier-Boisvert 7 jaren geleden
bovenliggende
commit
ed662a5597
2 gewijzigde bestanden met toevoegingen van 99 en 32 verwijderingen
  1. 1 1
      gym_minigrid/envs/playground_v1.py
  2. 98 31
      gym_minigrid/minigrid.py

+ 1 - 1
gym_minigrid/envs/playground_v1.py

@@ -107,7 +107,7 @@ class PlaygroundV1(MiniGridEnv):
         self.mission = ''
 
     def step(self, action):
-        obs, reward, done, info = super().step(self, action)
+        obs, reward, done, info = super().step(action)
         return obs, reward, done, info
 
 register(

+ 98 - 31
gym_minigrid/minigrid.py

@@ -65,6 +65,10 @@ class WorldObj:
         self.color = color
         self.contains = None
 
+    def isOpaque(self):
+        """Can the agent see objects that are behind this?"""
+        return False
+
     def canOverlap(self):
         """Can the agent overlap with this?"""
         return False
@@ -106,6 +110,9 @@ class Wall(WorldObj):
     def __init__(self, color='grey'):
         super(Wall, self).__init__('wall', color)
 
+    def isOpaque(self):
+        return True
+
     def render(self, r):
         self._setColor(r)
         r.drawPolygon([
@@ -116,10 +123,23 @@ class Wall(WorldObj):
         ])
 
 class Door(WorldObj):
-    def __init__(self, color, isOpen=False):
-        super(Door, self).__init__('door', color)
+    def __init__(self, color, isOpen=False, type='door'):
+        super().__init__('door', color)
         self.isOpen = isOpen
 
+    def isOpaque(self):
+        return not self.isOpen
+
+    def canOverlap(self):
+        """The agent can only walk over this cell when the door is open"""
+        return self.isOpen
+
+    def toggle(self, env, pos):
+        if not self.isOpen:
+            self.isOpen = True
+            return True
+        return False
+
     def render(self, r):
         c = COLORS[self.color]
         r.setLineColor(c[0], c[1], c[2])
@@ -148,21 +168,19 @@ class Door(WorldObj):
         ])
         r.drawCircle(CELL_PIXELS * 0.75, CELL_PIXELS * 0.5, 2)
 
+class LockedDoor(Door):
+    def __init__(self, color, isOpen=False):
+        super().__init__(color, isOpen, type='locked_door')
+
     def toggle(self, env, pos):
-        if not self.isOpen:
+        # If the player has the right key to open the door
+        if isinstance(env.carrying, Key) and env.carrying.color == self.color:
             self.isOpen = True
+            # The key has been used, remove it from the agent
+            env.carrying = None
             return True
         return False
 
-    def canOverlap(self):
-        """The agent can only walk over this cell when the door is open"""
-        return self.isOpen
-
-class LockedDoor(WorldObj):
-    def __init__(self, color, isOpen=False):
-        super(LockedDoor, self).__init__('locked_door', color)
-        self.isOpen = isOpen
-
     def render(self, r):
         c = COLORS[self.color]
         r.setLineColor(c[0], c[1], c[2])
@@ -196,19 +214,6 @@ class LockedDoor(WorldObj):
             CELL_PIXELS * 0.5
         )
 
-    def toggle(self, env, pos):
-        # If the player has the right key to open the door
-        if isinstance(env.carrying, Key) and env.carrying.color == self.color:
-            self.isOpen = True
-            # The key has been used, remove it from the agent
-            env.carrying = None
-            return True
-        return False
-
-    def canOverlap(self):
-        """The agent can only walk over this cell when the door is open"""
-        return self.isOpen
-
 class Key(WorldObj):
     def __init__(self, color='blue'):
         super(Key, self).__init__('key', color)
@@ -774,18 +779,80 @@ class MiniGridEnv(gym.Env):
 
         return obs, reward, done, {}
 
-    def _genObs(self):
-        """
-        Generate the agent's view (partially observable, low-resolution encoding)
-        """
+    def _getObsGrid(self):
 
         topX, topY, botX, botY = self.getViewExts()
-
         grid = self.grid.slice(topX, topY, AGENT_VIEW_SIZE, AGENT_VIEW_SIZE)
 
-        for i in range(self.agentDir + 1):
+        for i in range(self.agentDir+1):
             grid = grid.rotateLeft()
 
+        # Matrix of opaque objects (rows going forward, columns)
+        objMatrix = np.zeros((AGENT_VIEW_SIZE, AGENT_VIEW_SIZE))
+
+        for i in range(0, AGENT_VIEW_SIZE):
+            for j in range(0, AGENT_VIEW_SIZE):
+                obj = grid.get(i, AGENT_VIEW_SIZE - (1+j))
+                if obj is not None and obj.isOpaque():
+                    print('opaque')
+                    objMatrix[i, j] = 1
+
+        visMatrix = np.zeros((AGENT_VIEW_SIZE, AGENT_VIEW_SIZE))
+
+        mid = AGENT_VIEW_SIZE // 2
+
+        # The agent can see its own position
+        visMatrix[mid, 0] = 1
+
+        # Agent can see in the first row if not obstructed
+        for k in range(0, mid):
+            i = mid + 1 + k
+            if visMatrix[i-1, 0] and not objMatrix[i, 0]:
+                visMatrix[i, 0] = 1
+        for k in range(0, mid):
+            i = mid - 1 - k
+            if visMatrix[i+1, 0] and not objMatrix[i, 0]:
+                visMatrix[i, 0] = 1
+
+        # Propagate forward the region in which the agent can see
+        for i in range(0, AGENT_VIEW_SIZE):
+            for j in range(1, AGENT_VIEW_SIZE):
+                if visMatrix[i, j-1] and not objMatrix[i, j]:
+                    visMatrix[i, j] = 1
+
+        # Make cells immediately adjacent to the visible region also visible
+        adjMatrix = np.copy(visMatrix)
+        for i in range(0, AGENT_VIEW_SIZE):
+            for j in range(0, AGENT_VIEW_SIZE):
+                if j > 0 and visMatrix[i, j-1]:
+                    adjMatrix[i, j] = 1
+                if i > 0:
+                    if visMatrix[i-1, j]:
+                        adjMatrix[i, j] = 1
+                    if j > 0 and visMatrix[i-1, j-1]:
+                        adjMatrix[i, j] = 1
+                if i < AGENT_VIEW_SIZE - 1:
+                    if visMatrix[i+1, j]:
+                        adjMatrix[i, j] = 1
+                    if j > 0 and visMatrix[i+1, j-1]:
+                        adjMatrix[i, j] = 1
+        visMatrix = adjMatrix
+
+        # Hide non-visible cells
+        for i in range(0, AGENT_VIEW_SIZE):
+            for j in range(0, AGENT_VIEW_SIZE):
+                if visMatrix[i, j] == 0:
+                    grid.set(i, AGENT_VIEW_SIZE - (1+j), Wall('red'))
+
+        return grid, visMatrix
+
+    def _genObs(self):
+        """
+        Generate the agent's view (partially observable, low-resolution encoding)
+        """
+
+        grid, visMatrix = self._getObsGrid()
+
         # Make it so the agent sees what it's carrying
         # We do this by placing the carried object at the agent's position
         # in the agent's partially observable view