class_docstr: Encapsulates an agent, space interfaces and a stack of wrappers, to make the agent's MazeActions accessible to
  an external env.
  
  Note: The policy, env, and wrappers parameters are compatible with hydra configuration used for rollouts
  (alternatively, an already instantiated policy/env can be passed in as well).
  
  How it works:
  
  External env should supply states to agent deployment object, and can query it for agent MazeActions. The
  agent with the supplied policy (or multiple policies) is run on a separate thread.
  
  Note that the two threads (main thread running this wrapper and the second thread running the agent, wrappers etc.)
  never run in parallel, i.e. one is always suspended. This is enforced using the queues. Either the main thread
  runs and the agent thread is waiting for the state to be passed from the main thread, or the agent thread is
  running (computing the MazeAction) and the main thread is waiting until the MazeAction is passed back (then,
  the second thread is suspended again until the next state is passed in via the queue).
  
  Queues have max size of one, enforcing that one step can be taken at a time.
  
  :param policy: Structured policy to query for actions, or a config which will be used to built the policy.
  :param env: Either an instantiated simulation environment which will be used for action and observation processing
              (i.e., the Maze env, wrapper stack and env context will be used), or a config for instantiating
              such env.
  :param wrappers: Configuration for (additional) wrappers, if required.
class_docstr_tok: ["Encapsulates","an","agent",",","space","interfaces","and","a","stack","of","wrappers",",","to","make","the","agent","'s","MazeActions","accessible","to","an","external","env",".","Note",":","The","policy",",","env",",","and","wrappers","parameters","are","compatible","with","hydra","configuration","used","for","rollouts","(","alternatively",",","an","already","instantiated","policy\/env","can","be","passed","in","as","well",")",".","How","it","works",":","External","env","should","supply","states","to","agent","deployment","object",",","and","can","query","it","for","agent","MazeActions",".","The","agent","with","the","supplied","policy","(","or","multiple","policies",")","is","run","on","a","separate","thread",".","Note","that","the","two","threads","(","main","thread","running","this","wrapper","and","the","second","thread","running","the","agent",",","wrappers","etc",".",")","never","run","in","parallel",",","i.e",".","one","is","always","suspended",".","This","is","enforced","using","the","queues",".","Either","the","main","thread","runs","and","the","agent","thread","is","waiting","for","the","state","to","be","passed","from","the","main","thread",",","or","the","agent","thread","is","running","(","computing","the","MazeAction",")","and","the","main","thread","is","waiting","until","the","MazeAction","is","passed","back","(","then",",","the","second","thread","is","suspended","again","until","the","next","state","is","passed","in","via","the","queue",")",".","Queues","have","max","size","of","one",",","enforcing","that","one","step","can","be","taken","at","a","time",".",":","param","policy",":","Structured","policy","to","query","for","actions",",","or","a","config","which","will","be","used","to","built","the","policy",".",":","param","env",":","Either","an","instantiated","simulation","environment","which","will","be","used","for","action","and","observation","processing","(","i.e.",",","the","Maze","env",",","wrapper","stack","and","env","context","will","be","used",")",",","or","a","config","for","instantiating","such","env",".",":","param","wrappers",":","Configuration","for","(","additional",")","wrappers",",","if","required","."]
code: def __init__(
      self,
      policy: ConfigType,
      env: ConfigType,
      wrappers: CollectionOfConfigType = None,
  ):
      self.rollout_done = False
  
      # Thread synchronisation
      self.state_queue = Queue(maxsize=1)
      self.maze_action_queue = Queue(maxsize=1)
      self.rollout_done_event = Event()
  
      # Build simulation env from config (like we would do during training), then swap core env for external one
      self.env = EnvFactory(env, wrappers if wrappers else {})()
      if not isinstance(self.env, LogStatsWrapper):
          self.env = LogStatsWrapper.wrap(self.env)
      self.external_core_env = ExternalCoreEnv(
          context=self.env.core_env.context,
          state_queue=self.state_queue,
          maze_action_queue=self.maze_action_queue,
          rollout_done_event=self.rollout_done_event,
          renderer=self.env.core_env.get_renderer(),
      )
  
      # Due to the fake subclass hierarchy generated in each Wrapper, we need to make sure
      # we swap the core env directly on the MazeEnv, not on any wrapper above it
      maze_env = self.env
      while isinstance(maze_env.env, MazeEnv):
          maze_env = maze_env.env
      maze_env.core_env = self.external_core_env
  
      # Policy executor, running the rollout loop on a separate thread
      self.policy = Factory(base_type=Policy).instantiate(policy)
      self.policy_executor = PolicyExecutor(
          env=self.env,
          policy=self.policy,
          rollout_done_event=self.rollout_done_event,
          exception_queue=self.maze_action_queue,
      )
      self.policy_thread = Thread(
          target=self.policy_executor.run_rollout_loop, daemon=True
      )
      self.policy_thread.start()
  
file_path: maze/maze/core/agent_deployment/agent_deployment.py
imports: from queue import Queue
  from threading import Event, Thread
  from typing import Any, Dict, Union, List, Optional
  import numpy
  from maze.core.agent.policy import Policy
  from maze.core.agent_deployment.external_core_env import ExternalCoreEnv
  from maze.core.agent_deployment.policy_executor import PolicyExecutor, ExceptionReport
  from maze.core.env.maze_action import MazeActionType
  from maze.core.env.maze_env import MazeEnv
  from maze.core.env.maze_state import MazeStateType
  from maze.core.env.structured_env import ActorID
  from maze.core.events.event_record import EventRecord
  from maze.core.utils.config_utils import EnvFactory
  from maze.core.utils.factory import ConfigType, CollectionOfConfigType, Factory
  from maze.core.wrappers.log_stats_wrapper import LogStatsWrapper
label_desc: Use image node_id 1 to create a new AgentDeployment object  with example: obj = AgentDeployment(policy, env, wrappers)