class BoxCom(object): """Handle all technical aspects of simulation instanciation and communication""" def __init__(self, sim, cfg, debug = False, java_output = False): self.sim = sim self.cfg = sim.cfg self.cfg.update(defaultcfg, overwrite = False) self.client = Client() port = self.find_port() self.simproc = self.launch_sim(port) self.connect(port) def print_debug(self, s): if self.cfg.debug: print("{}dbg{}: {}{}".format(gfx.red, gfx.end, s, '\033[K')) def print_status(self, s): if self.cfg.verbose: print("{}sim{}: {}{}".format(prefixcolor, gfx.end, s, '\033[K')) def find_port(self): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) sock.bind(('', 0)) sock.listen(socket.SOMAXCONN) ipaddr, port = sock.getsockname() sock.close() return port def launch_sim(self, port): interact_file = os.path.dirname(__file__) + '/' + 'interact.jar' assert os.path.exists(interact_file), "The file {} does not exist. Did you build the java code ?".format(interact_file) if self.cfg.visu: cmd = "java -cp {} experiments.interact.ProcSketch {}".format(interact_file, port) else: cmd = "java -cp {} experiments.interact.StandAlone {}".format(interact_file, port) if self.cfg.java_output: DEVNULL = None else: DEVNULL = open(os.devnull, 'wb') proc = subprocess.Popen(cmd, stdout=DEVNULL, shell=True, preexec_fn=os.setsid) time.sleep(5) return proc def receive_sensors(self): """Interprets and return results""" resmsg = self.client.sendAndReceive(OutboundMessage(MSG_SENSOR, [])) assert resmsg.type == MSG_SENSOR results = self.process_sensors(resmsg) self.print_debug("Received results: {}".format(", ".join(["%+2.1f" % e for e in results]),)) return results def process_sensors(self, resmsg): n_size = resmsg.readInt() return tuple(resmsg.readDouble() for _ in range(n_size)) def send_order(self, init_pos, order, nsteps, conf): """Send an order, run nsteps, and return result""" self.print_debug("Reseting the simulation") resetMsg = self.client.sendAndReceive(OutboundMessage(MSG_RESET, [len(init_pos)] + init_pos + conf)) assert resetMsg.type == MSG_SENSOR self.print_debug("Sending order({})".format(", ".join(["%+2.1f" % o for o in order]), prefixcolor, gfx.end)) orderConfirm = self.client.sendAndReceive(OutboundMessage(MSG_ORDER, [len(order)]+order )) assert orderConfirm.type == MSG_ORDER self.print_debug("Requesting {} steps run".format(nsteps)) stepConfirm = self.client.sendAndReceive(OutboundMessage(MSG_STEP, [nsteps]), timeout = 1000) assert stepConfirm.type == MSG_STEP return self.process_sensors(resetMsg), self.receive_sensors() def close(self): os.killpg(self.simproc.pid, signal.SIGTERM) def connect(self, port): b = self.client.connect(IP, port) try: if b: msg = self.client.sendAndReceive(OutboundMessage(type_msg=MSG_HELLO), timeout = 1.0) self.print_status("connected on port {}".format(self.client.port)) else: self.print_status("ERROR") except KeyboardInterrupt: exit(1) except: traceback.print_exc() self.client.disconnect() def send_conf(self, conf): msg = self.client.sendAndReceive(OutboundMessage(MSG_CONF, [60.0, 3, 20, 20] + conf)) assert msg.type == MSG_CONF reachable_space = ((msg.readDouble(), msg.readDouble()), (msg.readDouble(), msg.readDouble())) self.print_status("sent configuration {}".format(", ".join("{:+3.1f}".format(c_i) if type(c_i) == float else "{}".format(c_i) for c_i in [60.0, 3, 20, 20] + conf))) self.print_status("reachable space: x:({:+3.1f}, {:+3.1f}), y:({:+3.1f}, {:+3.1f})".format( reachable_space[0][0], reachable_space[0][1], reachable_space[1][0], reachable_space[1][1])) return reachable_space def disconnect(self): self.print_status("disconnecting") msg = self.client.sendAndReceive(OutboundMessage(MSG_BYE, ["Bye Server !"])) assert msg.type == MSG_BYE self.client.disconnect() self.print_status("disconnected") self.close()