def step(self) -> List[EnvironmentStep]:
        # Queue steps for any workers which aren't in the "waiting" state.
        self._queue_steps()

        worker_steps: List[EnvironmentResponse] = []
        step_workers: Set[int] = set()
        # Poll the step queue for completed steps from environment workers until we retrieve
        # 1 or more, which we will then return as StepInfos
        while len(worker_steps) < 1:
            try:
                while True:
                    step = self.step_queue.get_nowait()
                    if step.name == "env_close":
                        raise UnityCommunicationException(
                            "At least one of the environments has closed."
                        )
                    self.env_workers[step.worker_id].waiting = False
                    if step.worker_id not in step_workers:
                        worker_steps.append(step)
                        step_workers.add(step.worker_id)
            except EmptyQueueException:
                pass

        step_infos = self._postprocess_steps(worker_steps)
        return step_infos
예제 #2
0
 def recv(self) -> EnvironmentResponse:
     try:
         response: EnvironmentResponse = self.conn.recv()
         return response
     except (BrokenPipeError, EOFError):
         raise UnityCommunicationException(
             "UnityEnvironment worker: recv failed.")
예제 #3
0
 def send(self, name: str, payload: Any = None) -> None:
     try:
         cmd = EnvironmentCommand(name, payload)
         self.conn.send(cmd)
     except (BrokenPipeError, EOFError):
         raise UnityCommunicationException(
             "UnityEnvironment worker: send failed.")
 def on_message_received(self, data: bytearray) -> None:
     """
     Is called by the environment to the side channel. Can be called
     multiple times per step if multiple messages are meant for that
     SideChannel.
     Note that Python should never receive an engine configuration from
     Unity
     """
     raise UnityCommunicationException(
         "The EngineConfigurationChannel received a message from Unity, " +
         "this should not have happend.")
예제 #5
0
 def reset(self) -> None:
     if self._loaded:
         outputs = self.communicator.exchange(self._generate_reset_input())
         if outputs is None:
             raise UnityCommunicationException("Communicator has stopped.")
         self._update_group_specs(outputs)
         rl_output = outputs.rl_output
         self._update_state(rl_output)
         self._is_first_message = False
         self._env_actions.clear()
     else:
         raise UnityEnvironmentException("No Unity environment is loaded.")
예제 #6
0
 def step(self) -> None:
     if self._is_first_message:
         return self.reset()
     if not self._loaded:
         raise UnityEnvironmentException("No Unity environment is loaded.")
     # fill the blanks for missing actions
     for group_name in self._env_specs:
         if group_name not in self._env_actions:
             n_agents = 0
             if group_name in self._env_state:
                 n_agents = self._env_state[group_name].n_agents()
             self._env_actions[group_name] = self._env_specs[
                 group_name
             ].create_empty_action(n_agents)
     step_input = self._generate_step_input(self._env_actions)
     with hierarchical_timer("communicator.exchange"):
         outputs = self.communicator.exchange(step_input)
     if outputs is None:
         raise UnityCommunicationException("Communicator has stopped.")
     self._update_group_specs(outputs)
     rl_output = outputs.rl_output
     self._update_state(rl_output)
     self._env_actions.clear()