def _peek_obs(self): obs = None start_time = time.time() if not self.done: logger.debug("Peeking the client.") peek_message = "<Peek/>" comms.send_message(self.client_socket, peek_message.encode()) obs = comms.recv_message(self.client_socket) info = comms.recv_message(self.client_socket).decode('utf-8') reply = comms.recv_message(self.client_socket) done, = struct.unpack('!b', reply) self.done = done == 1 if obs is None or len(obs) == 0: if time.time() - start_time > MAX_WAIT: self.client_socket.close() self.client_socket = None raise MissionInitException( 'too long waiting for first observation') time.sleep(0.1) if self.done: raise RuntimeError( "Something went wrong resetting the environment! " "`done` was true on first frame.") # See if there is an integrated port if self._is_interacting: port = self._find_server() self.integratedServerPort = port logger.warn("MineRL agent is public, connect on port {} with Minecraft 1.11".format(port)) # Todo make a launch command. return self._process_observation(obs, info)
def _peek_obs(self): obs = None start_time = time.time() if not self.done: logger.debug("Peeking the client.") peek_message = "<Peek/>" comms.send_message(self.client_socket, peek_message.encode()) obs = comms.recv_message(self.client_socket) info = comms.recv_message(self.client_socket).decode('utf-8') reply = comms.recv_message(self.client_socket) done, = struct.unpack('!b', reply) self.done = done == 1 if obs is None or len(obs) == 0: if time.time() - start_time > MAX_WAIT: self.client_socket.close() self.client_socket = None raise MissionInitException( 'too long waiting for first observation') time.sleep(0.1) if self.done: raise RuntimeError( "Something went wrong resetting the environment! " "`done` was true on first frame.") return self._process_observation(obs, info)
def _find_server(self): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((self.instance.host, self.instance.port)) self._hello(sock) start_time = time.time() port = 0 while port == 0: comms.send_message(sock, ("<Find>" + self._get_token() + "</Find>").encode()) reply = comms.recv_message(sock) port, = struct.unpack('!I', reply) if port == 0: if time.time() - start_time > MAX_WAIT: if self.client_socket: self.client_socket.close() self.client_socket = None raise MissionInitException( 'too long finding mission to join') time.sleep(1) sock.close() # print("Found mission integrated server port " + str(port)) self.integratedServerPort = port e = self.xml.find(self.ns + 'MinecraftServerConnection') if e is not None: e.attrib['port'] = str(self.integratedServerPort)
def close(self): """gym api close""" if self.viewer is not None: self.viewer.close() self.viewer = None if self._already_closed: return try: # Purge last token from head node with <Close> message. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((self.instance.host, self.instance.port)) self._hello(sock) comms.send_message(sock, ("<Close>" + self._get_token() + "</Close>").encode()) reply = comms.recv_message(sock) ok, = struct.unpack('!I', reply) assert ok sock.close() self._already_closed = True except Exception as e: self._log_error(e) if self.client_socket: self.client_socket.close() self.client_socket = None if self.instance and self.instance.running: self.instance.kill()
def step(self, action): withinfo = MineRLEnv.STEP_OPTIONS == 0 or MineRLEnv.STEP_OPTIONS == 2 # Process the actions. malmo_command = self._process_action(action) try: if not self.done: step_message = "<Step" + str(MineRLEnv.STEP_OPTIONS) + ">" + \ malmo_command + \ "</Step" + str(MineRLEnv.STEP_OPTIONS) + " >" # Send Actions. comms.send_message(self.client_socket, step_message.encode()) # Receive the observation. obs = comms.recv_message(self.client_socket) # Receive reward done and sent. reply = comms.recv_message(self.client_socket) reward, done, sent = struct.unpack('!dbb', reply) # Receive info from the environment. if withinfo: info = comms.recv_message( self.client_socket).decode('utf-8') else: info = {} # Process the observation and done state. out_obs = self._process_observation(obs, info) self.done = (done == 1) if self._is_real_time: t0 = time.time() # Todo: Add catch-up time.sleep( max(0, TICK_LENGTH - (t0 - self._last_step_time))) self._last_step_time = time.time() return out_obs, reward, self.done, {} else: raise RuntimeError( "Attempted to step an environment with done=True") except (socket.timeout, socket.error) as e: # If the socket times out some how! We need to catch this and reset the environment. self._clean_connection() self.done = True logger.error( "Failed to take a step (timeout or error). Terminating episode and sending random observation, be aware. " "To account for this failure case in your code check to see if `'error' in info` where info is " "the info dictionary returned by the step function.") return self.observation_space.sample(), 0, self.done, { "error": "Connection timed out!" }
def request_interactor(instance, ip): sock = get_socket(instance) MineRLEnv._hello(sock) comms.send_message(sock, ("<Interact>" + ip + "</Interact>").encode()) reply = comms.recv_message(sock) ok, = struct.unpack('!I', reply) if not ok: raise RuntimeError("Failed to start interactor") sock.close()
def reinit(self): """Use carefully to reset the episode count to 0.""" sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((self.instance.host, self.instance.port)) self._hello(sock) comms.send_message( sock, ("<Init>" + self._get_token() + "</Init>").encode()) reply = comms.recv_message(sock) sock.close() ok, = struct.unpack('!I', reply) return ok != 0
def status(self): """Get status from server. head - Ping the the head node if True. """ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((self.instance.host, self.instance.port)) self._hello(sock) comms.send_message(sock, "<Status/>".encode()) status = comms.recv_message(sock).decode('utf-8') sock.close() return status
def _find_server(self): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((self.instance.host, self.instance.port)) self._hello(sock) start_time = time.time() port = 0 while port == 0: comms.send_message( sock, ("<Find>" + self._get_token() + "</Find>").encode()) reply = comms.recv_message(sock) port, = struct.unpack('!I', reply) sock.close() # print("Found mission integrated server port " + str(port)) return port
def _kill_minecraft_via_malmoenv(host, port): """Use carefully to cause the Minecraft service to exit (and hopefully restart). """ try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(1) sock.connect((host, port)) comms.send_message(sock, ("<MalmoEnv" + malmo_version + "/>").encode()) comms.send_message(sock, ("<Exit>NOW</Exit>").encode()) reply = comms.recv_message(sock) ok, = struct.unpack('!I', reply) sock.close() return ok == 1 except Exception as e: logger.error("Attempted to send kill command to minecraft process and failed.") return False
def _init_mission(self): ok = 0 num_retries = 0 logger.debug("Sending mission init!") while ok != 1: xml = etree.tostring(self.xml) token = (self._get_token() + ":" + str(self.agent_count) + ":" + str(self.synchronous).lower()).encode() comms.send_message(self.client_socket, xml) comms.send_message(self.client_socket, token) reply = comms.recv_message(self.client_socket) ok, = struct.unpack('!I', reply) if ok != 1: num_retries += 1 if num_retries > MAX_WAIT: raise socket.timeout() logger.debug("Recieved a MALMOBUSY from Malmo; trying again.") time.sleep(1)
def _quit_episode(self): comms.send_message(self.client_socket, "<Quit/>".encode()) reply = comms.recv_message(self.client_socket) ok, = struct.unpack('!I', reply) return ok != 0
def _hello(sock): comms.send_message(sock, ("<MalmoEnv" + malmo_version + "/>").encode())
def step(self, action): obs = None reward = None info = None turn = True withturnkey = self.step_options < 2 # print(withturnkey) withinfo = self.step_options == 0 or self.step_options == 2 malmo_command = self._process_action(action) try: if not self.done: step_message = "<Step" + str(self.step_options) + ">" + \ malmo_command + \ "</Step" + str(self.step_options) + " >" t0 = time.time() comms.send_message(self.client_socket, step_message.encode()) # print("send action {}".format(time.time() - t0)); t0 = time.time() if withturnkey: comms.send_message(self.client_socket, self.turn_key.encode()) obs = comms.recv_message(self.client_socket) # print("recieve obs {}".format(time.time() - t0)); t0 = time.time() reply = comms.recv_message(self.client_socket) reward, done, sent = struct.unpack('!dbb', reply) # print("recieve reward {}".format(time.time() - t0)); t0 = time.time() self.done = done == 1 if withinfo: info = comms.recv_message( self.client_socket).decode('utf-8') out_obs = self._process_observation(obs, info) turn_key = comms.recv_message( self.client_socket).decode('utf-8') if withturnkey else "" # print("[" + str(self.role) + "] TK " + turn_key + " self.TK " + str(self.turn_key)) if turn_key != "": if sent != 0: turn = False # Done turns if: turn = self.turn_key == turn_key self.turn_key = turn_key else: turn = sent == 0 # if (obs is None or len(obs) == 0) or turn: # time.sleep(0.1) # print("turnkeyprocessor {}".format(time.time() - t0)); t0 = time.time() # print("creating obs from buffer {}".format(time.time() - t0)); t0 = time.time() return out_obs, reward, self.done, {} else: raise RuntimeError( "Attempted to step an environment with done=True") except socket.timeout as e: # If the socket times out some how! We need to catch this and reset the environment. self._clean_connection() self.done = True logger.error( "Failed to take a step (timeout). Terminating episode and sending random observation, be aware. " "To account for this failure case in your code check to see if `'error' in info` where info is " "the info dictionary returned by the step function.") return self.observation_space.sample(), 0, self.done, { "error": "Connection timed out!" }