Exemple #1
0
    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
Exemple #2
0
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)
    )
Exemple #3
0
    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
Exemple #4
0
    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.")
Exemple #5
0
 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
Exemple #6
0
    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
Exemple #7
0
    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
Exemple #8
0
    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")