You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

116 lines
3.6 KiB

2 months ago
  1. from __future__ import annotations
  2. from minigrid.core.constants import COLOR_NAMES
  3. from minigrid.core.mission import MissionSpace
  4. from minigrid.core.roomgrid import RoomGrid
  5. from minigrid.core.world_object import Ball
  6. class BlockedUnlockPickupEnv(RoomGrid):
  7. """
  8. ## Description
  9. The agent has to pick up a box which is placed in another room, behind a
  10. locked door. The door is also blocked by a ball which the agent has to move
  11. before it can unlock the door. Hence, the agent has to learn to move the
  12. ball, pick up the key, open the door and pick up the object in the other
  13. room. This environment can be solved without relying on language.
  14. ## Mission Space
  15. "pick up the {color} {type}"
  16. {color} is the color of the box. Can be "red", "green", "blue", "purple",
  17. "yellow" or "grey".
  18. {type} is the type of the object. Can be "box" or "key".
  19. ## Action Space
  20. | Num | Name | Action |
  21. |-----|--------------|-------------------|
  22. | 0 | left | Turn left |
  23. | 1 | right | Turn right |
  24. | 2 | forward | Move forward |
  25. | 3 | pickup | Pick up an object |
  26. | 4 | drop | Unused |
  27. | 5 | toggle | Unused |
  28. | 6 | done | Unused |
  29. ## Observation Encoding
  30. - Each tile is encoded as a 3 dimensional tuple:
  31. `(OBJECT_IDX, COLOR_IDX, STATE)`
  32. - `OBJECT_TO_IDX` and `COLOR_TO_IDX` mapping can be found in
  33. [minigrid/minigrid.py](minigrid/minigrid.py)
  34. - `STATE` refers to the door state with 0=open, 1=closed and 2=locked
  35. ## Rewards
  36. A reward of '1 - 0.9 * (step_count / max_steps)' is given for success, and '0' for failure.
  37. ## Termination
  38. The episode ends if any one of the following conditions is met:
  39. 1. The agent picks up the correct box.
  40. 2. Timeout (see `max_steps`).
  41. ## Registered Configurations
  42. - `MiniGrid-BlockedUnlockPickup-v0`
  43. """
  44. def __init__(self, max_steps: int | None = None, **kwargs):
  45. mission_space = MissionSpace(
  46. mission_func=self._gen_mission,
  47. ordered_placeholders=[COLOR_NAMES, ["box", "key"]],
  48. )
  49. room_size = 6
  50. if max_steps is None:
  51. max_steps = 16 * room_size**2
  52. super().__init__(
  53. mission_space=mission_space,
  54. num_rows=1,
  55. num_cols=2,
  56. room_size=room_size,
  57. max_steps=max_steps,
  58. **kwargs,
  59. )
  60. @staticmethod
  61. def _gen_mission(color: str, obj_type: str):
  62. return f"pick up the {color} {obj_type}"
  63. def _gen_grid(self, width, height):
  64. super()._gen_grid(width, height)
  65. # Add a box to the room on the right
  66. obj, _ = self.add_object(1, 0, kind="box")
  67. # Make sure the two rooms are directly connected by a locked door
  68. door, pos = self.add_door(0, 0, 0, locked=True)
  69. # Block the door with a ball
  70. color = self._rand_color()
  71. self.grid.set(pos[0] - 1, pos[1], Ball(color))
  72. # Add a key to unlock the door
  73. self.add_object(0, 0, "key", door.color)
  74. self.place_agent(0, 0)
  75. self.obj = obj
  76. self.mission = f"pick up the {obj.color} {obj.type}"
  77. def step(self, action):
  78. obs, reward, terminated, truncated, info = super().step(action)
  79. if action == self.actions.pickup:
  80. if self.carrying and self.carrying == self.obj:
  81. reward = self._reward()
  82. terminated = True
  83. return obs, reward, terminated, truncated, info