def __init__(self, xml, port): InstanceManager.configure_malmo_base_port(port) self.action_to_command_array = [ 'move 1', 'camera 0 270', 'camera 0 90' ] super().__init__( xml, gym.spaces.Box(low=0, high=255, shape=(84, 84, 3), dtype=np.uint8), gym.spaces.Discrete(3)) self.metadata['video.frames_per_second'] = 2
def run_interactor(ip, port, interactor_port=INTERACTOR_PORT): try: InstanceManager.add_existing_instance(interactor_port) instance = InstanceManager.get_instance(-1) print(instance) except AssertionError as e: logger.warning("No existing interactor found on port {}. Starting a new interactor.".format(interactor_port)) instance = InstanceManager.Instance(interactor_port) instance.launch(daemonize=True) request_interactor( instance, '{}:{}'.format(ip, port) )
def _get_new_instance(self, port=None, instance_id=None): """ Gets a new instance and sets up a logger if need be. """ if not port is None: instance = InstanceManager.add_existing_instance(port) else: instance = InstanceManager.get_instance(os.getpid(), instance_id=instance_id) if InstanceManager.is_remote(): launch_queue_logger_thread(instance, self.is_closed) instance.launch() return instance
def _robust_get_new_instance( self, port=None, instance_id=None, max_tries=3, ) -> InstanceManager: """Launch and return a new InstanceManager. Attempt up to `max_tries` times in face of known Gradle race condition..""" InstanceManager().shutdown() for i in range(max_tries): instance = self._get_new_instance(port=port, instance_id=instance_id) try: instance.launch() except malmo.IntermittentBuildError: instance.kill() instance = None if instance is not None: return instance else: log_str = ( "Minecraft build or launch just failed on attempt {j}/{max_tries}." "This is probably an intermittent race condition. " "Trying again (max tries {max_tries}).").format( j=i + 1, max_tries=max_tries) logger.warning(log_str) time.sleep(2) raise RuntimeError(f"Failed to build and launch Minecraft instance " f"{max_tries} times. Giving up.")
def _clean_connection(self): self.client_socket.shutdown(socket.SHUT_RDWR) self.client_socket.close() self.client_socket = None if self.had_to_clean: # Connect to a new instance!! logger.error( "Connection with Minecraft client cleaned more than once; restarting." ) if self.instance: self.instance.kill() self.instance = InstanceManager.get_instance().__enter__() self.had_to_clean = False else: self.had_to_clean = True
def _clean_connection(self): logger.error("Cleaning connection! Something must have gone wrong.") try: if self.client_socket: self.client_socket.shutdown(socket.SHUT_RDWR) self.client_socket.close() except (BrokenPipeError, OSError, socket.error): # There is no connection left! pass self.client_socket = None if self.had_to_clean: # Connect to a new instance!! logger.error( "Connection with Minecraft client cleaned more than once; restarting." ) if self.instance: self.instance.kill() self.instance = InstanceManager.get_instance() self.had_to_clean = False else: self.had_to_clean = True
def init(self, observation_space, action_space, port=None): """Initializes the MineRL Environment. Note: This is called automatically when the environment is made. Args: observation_space (gym.Space): The observation for the environment. action_space (gym.Space): The action space for the environment. port (int, optional): The port of an exisitng Malmo environment. Defaults to None. Raises: EnvException: If the Mission XML is malformed this is thrown. ValueError: The space specified for this environment does not have a default action. NotImplementedError: When multiagent environments are attempted to be used. """ step_options = 0 resync = 0 episode = 0 exp_uid = None if self.instance == None: if not port is None: self.instance = InstanceManager.add_existing_instance(port) else: self.instance = InstanceManager.get_instance().__enter__() # Parse XML file with open(self.xml_file, 'r') as f: xml_text = f.read() xml = xml_text.replace('$(MISSIONS_DIR)', missions_dir) # Bootstrap the environment if it hasn't been. role = 0 if not xml.startswith('<Mission'): i = xml.index("<Mission") if i == -1: raise EnvException("Mission xml must contain <Mission> tag.") xml = xml[i:] self.xml = etree.fromstring(xml) self.role = role if exp_uid is None: self.exp_uid = str(uuid.uuid4()) else: self.exp_uid = exp_uid self.action_space = action_space self.observation_space = observation_space def map_space(space): if isinstance(space, gym.spaces.Discrete) or isinstance( space, minerl.env.spaces.Enum): return 0 elif isinstance(space, gym.spaces.Box): return np.zeros(shape=space.shape, dtype=space.dtype) else: try: return space.default() except NameError: raise ValueError( 'Specify non-None default_action in gym.register or extend all action spaces with default() method' ) if self._default_action is None: self._default_action = { key: map_space(space) for key, space in action_space.spaces.items() } def noop_func(a): return deepcopy(self._default_action) boundmethd = _bind(self.action_space, noop_func) self.action_space.noop = boundmethd # Force single agent self.agent_count = 1 turn_based = self.xml.find('.//' + self.ns + 'TurnBasedCommands') is not None if turn_based: raise NotImplementedError( "Turn based or multi-agent environments not supported.") else: self.turn_key = "" # Unclear what step_options does. if step_options is None: self.step_options = 0 if not turn_based else 2 else: self.step_options = step_options self.done = True self.resync_period = resync self.resets = episode e = etree.fromstring( """<MissionInit xmlns="http://ProjectMalmo.microsoft.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" SchemaVersion="" PlatformVersion=""" + '\"' + malmo_version + '\"' + """> <ExperimentUID></ExperimentUID> <ClientRole>0</ClientRole> <ClientAgentConnection> <ClientIPAddress>127.0.0.1</ClientIPAddress> <ClientMissionControlPort>0</ClientMissionControlPort> <ClientCommandsPort>0</ClientCommandsPort> <AgentIPAddress>127.0.0.1</AgentIPAddress> <AgentMissionControlPort>0</AgentMissionControlPort> <AgentVideoPort>0</AgentVideoPort> <AgentDepthPort>0</AgentDepthPort> <AgentLuminancePort>0</AgentLuminancePort> <AgentObservationsPort>0</AgentObservationsPort> <AgentRewardsPort>0</AgentRewardsPort> <AgentColourMapPort>0</AgentColourMapPort> </ClientAgentConnection> </MissionInit>""") e.insert(0, self.xml) self.xml = e self.xml.find(self.ns + 'ClientRole').text = str(self.role) self.xml.find(self.ns + 'ExperimentUID').text = self.exp_uid if self.role != 0 and self.agent_count > 1: e = etree.Element(self.ns + 'MinecraftServerConnection', attrib={ 'address': self.instance.host, 'port': str(0) }) self.xml.insert(2, e) video_producers = self.xml.findall('.//' + self.ns + 'VideoProducer') assert len(video_producers) == self.agent_count video_producer = video_producers[self.role] # Todo: Deprecate width, height, and POV forcing. self.width = int(video_producer.find(self.ns + 'Width').text) self.height = int(video_producer.find(self.ns + 'Height').text) want_depth = video_producer.attrib["want_depth"] self.depth = 4 if want_depth is not None and ( want_depth == "true" or want_depth == "1" or want_depth is True) else 3 # print(etree.tostring(self.xml)) self.has_init = True
def __init__( self, seeds: [int], file_name: Optional[str] = None, worker_id: int = 0, base_port: int = 5005, docker_training: bool = False, no_graphics: bool = False, # timeout_wait: int = 30, # args: Optional[List[str]] = None, num_envs: int = 1): """ Starts a new unity environment and establishes a connection with the environment. Notice: Currently communication between Unity and Python takes place over an open socket without authentication. Ensure that the network where training takes place is secure. :string file_name: Name of Unity environment binary. :int base_port: Baseline port number to connect to Unity environment over. worker_id increments over this. :int worker_id: Number to add to communication port (5005) [0]. Used for asynchronous agent scenarios. :bool docker_training: Informs this class whether the process is being run within a container. :bool no_graphics: Whether to run the Unity simulator in no-graphics mode :int timeout_wait: Time (in seconds) to wait for connection from environment. :bool train_mode: Whether to run in training mode, speeding up the simulation, by default. """ atexit.register(self._close) self.port = base_port + worker_id self._buffer_size = 12000 self._version_ = "API-10" self._loaded = ( False ) # If true, this means the environment was successfully loaded self.proc1 = ( None ) # The process that is started. If None, no process was started # self.communicator = self.get_communicator(worker_id, base_port, timeout_wait) self._worker_id = worker_id self._is_first_message = True from minerl.env.malmo import InstanceManager self._envs: Dict[str, [Env]] = {} self._agent_ids: Dict[str, [str]] = {} self._n_agents: Dict[str, int] = {} self._academy_name = 'MineRLUnityAcademy' self._log_path = 'log_path' self._brains: Dict[str, BrainParameters] = {} self._brain_names: List[str] = [] self._external_brain_names: List[str] = [] InstanceManager.configure_malmo_base_port(base_port + worker_id) for i in range(num_envs): print('InstanceManager:', InstanceManager) try: print('.MAXINSTANCES', InstanceManager.MAXINSTANCES) except AttributeError: print('.MAXINSTANCES', 'None') pass print('.REMOTE', InstanceManager.is_remote()) try: print('.ninstances', InstanceManager.ninstances) except AttributeError: print('.ninstances', 'None') pass try: print('.DEFAULT_IP', InstanceManager.DEFAULT_IP) except AttributeError: print('.DEFAULT_IP', 'None') pass env = gym.make(file_name) env = MineRLToMLAgentWrapper(env, seeds[i]) env = RefineObservationsWrapper(env) env = NormalizeObservationsWrapper(env) VISUALIZE = bool(os.getenv('VISUALIZE', None)) if VISUALIZE and self.worker_id is 0: env = KeyboardControlWrapper(env) # env = HardwireActionsWrapper(env) env = PruneActionsWrapper( env, [ # 'attack_jump' # ,'camera_left_right' # 'camera_up_down' # ,'forward_back' # 'left_right' # ,'place' # ,'sneak_sprint' ]) env = PruneVisualObservationsWrapper(env, hack_ignor=True) # env = VisualObsAsFloatWrapper(env) env = FrameStackMono(env, 2, 10) EVALUATION_STAGE = os.getenv('EVALUATION_STAGE', '') if EVALUATION_STAGE != 'testing': env = EarlyExitWrapper(env) env = DingRewardOnDoneWrapper(env) # note: should be the last wrapper env = ResetOnDoneWrapper(env) MineRLToMLAgentWrapper.set_wrappers_for_pretraining(file_name, env) brain_name = env.brain_parameters.brain_name if brain_name not in self._agent_ids: self._envs[brain_name] = [] self._agent_ids[brain_name] = [] self._n_agents[brain_name] = 0 self._brain_names.append(brain_name) brain = env.brain_parameters self._external_brain_names.append(brain_name) self._brains[brain_name] = brain self._envs[brain_name].append(env) self._agent_ids[brain_name].append(env.agent_id) self._n_agents[brain_name] += 1 self._loaded = True self._num_brains = len(self._brain_names) self._num_external_brains = len(self._external_brain_names) # self._resetParameters = dict(aca_params.environment_parameters.float_parameters) self._resetParameters = dict() logger.info("\n'{0}' started successfully!\n{1}".format( self._academy_name, str(self))) if self._num_external_brains == 0: logger.warning( " No Learning Brains set to train found in the Unity Environment. " "You will not be able to pass actions to your agent(s).")
from minerl.env.malmo import InstanceManager if __name__ == '__main__': instance = InstanceManager.Instance(9000) instance.launch() print("Running...") input("Enter keyboard to stop")