def main(args: argparse.Namespace): loadfile: Path if os.path.isabs(args.loadfile): loadfile = Path(args.loadfile) else: # Take paths relative to 'data/saves/' loadfile = common.savefile(args.loadfile) physics_engine = physics.PhysicsEngine(common.load_savefile(loadfile)) initial_state = physics_engine.get_state() gui = flight_gui.FlightGui(initial_state, title=name, running_as_mirror=False) atexit.register(gui.shutdown) if args.flamegraph: common.start_flamegraphing() if args.profile: common.start_profiling() while True: state = physics_engine.get_state() # If we have any commands, process them so the simthread has as # much time as possible to restart before next update. physics_engine.handle_requests(gui.pop_commands()) gui.draw(state) gui.rate(common.FRAMERATE)
def __init__(self, client: protos.Command.ClientType, hostname: str): self.channel = grpc.insecure_channel(f'{hostname}:{DEFAULT_PORT}') self.stub = grpc_stubs.StateServerStub(self.channel) self.client_type = client initial_state = PhysicsState( None, self.stub.get_physical_state( iter([Request(ident=Request.NOOP, client=self.client_type)]))) self._caching_physics_engine = physics.PhysicsEngine(initial_state) self._time_of_next_network_update = 0.0
def main(args: argparse.Namespace): # Before you make changes to this function, keep in mind that this function # starts a GRPC server that runs in a separate thread! state_server = network.StateServer() loadfile: Path if os.path.isabs(args.loadfile): loadfile = Path(args.loadfile) else: # Take paths relative to 'data/saves/' loadfile = common.savefile(args.loadfile) physics_engine = physics.PhysicsEngine(common.load_savefile(loadfile)) initial_state = physics_engine.get_state() TICKS_BETWEEN_CLIENT_LIST_REFRESHES = 150 ticks_until_next_client_list_refresh = 0 server = grpc.server( concurrent.futures.ThreadPoolExecutor(max_workers=4)) atexit.register(lambda: server.stop(grace=2)) grpc_stubs.add_StateServerServicer_to_server(state_server, server) server.add_insecure_port(f'[::]:{network.DEFAULT_PORT}') state_server.notify_state_change(initial_state.as_proto()) server.start() # This doesn't block! gui = ServerGui() try: if args.flamegraph: common.start_flamegraphing() if args.profile: common.start_profiling() while True: # If we have any commands, process them immediately so input lag # is minimized. commands = state_server.pop_commands() + gui.pop_commands() physics_engine.handle_requests(commands) state = physics_engine.get_state() state_server.notify_state_change(state.as_proto()) if ticks_until_next_client_list_refresh == 0: ticks_until_next_client_list_refresh = \ TICKS_BETWEEN_CLIENT_LIST_REFRESHES state_server.refresh_client_list() ticks_until_next_client_list_refresh -= 1 gui.update(state, state_server.addr_to_connected_clients.values()) finally: server.stop(grace=1)
def main(args: argparse.Namespace): log.info(f'Connecting to physics server {args.physics_server}.') time_of_next_network_update = 0.0 lead_server_connection = network.StateClient(Request.HAB_FLIGHT, args.physics_server) state = lead_server_connection.get_state() physics_engine = physics.PhysicsEngine(state) gui = flight_gui.FlightGui(state, title=name, running_as_mirror=False) atexit.register(gui.shutdown) while True: gui.draw(state) user_commands = gui.pop_commands() current_time = time.monotonic() # If there are user commands or we've gone a while since our last # contact with the physics server, request an update. if user_commands or current_time > time_of_next_network_update: # Our state is stale, get the latest update # TODO: what if this fails? Do anything smarter than an exception? state = lead_server_connection.get_state(user_commands) physics_engine.set_state(state) if len(user_commands) == 0: time_of_next_network_update = ( current_time + common.TIME_BETWEEN_NETWORK_UPDATES) else: # If we sent a user command, still ask for an update soon so # the user input can be reflected in hab flight's GUI as soon # as possible. # Magic number alert! The constant we add should be enough that # the physics server has had enough time to simulate the effect # of our input, but we should minimize the constant to minimize # input lag. time_of_next_network_update = current_time + 0.15 else: state = physics_engine.get_state() gui.rate(common.FRAMERATE)
def main(args: argparse.Namespace): time_of_last_network_update = 0.0 networking = True # Whether data is requested over the network log.info(f'Connecting to physics server {args.physics_server}.') lead_server_connection = network.StateClient(Request.MC_FLIGHT, args.physics_server) state = lead_server_connection.get_state() physics_engine = physics.PhysicsEngine(state) gui = flight_gui.FlightGui(state, title=name, running_as_mirror=True) atexit.register(gui.shutdown) while True: old_networking = networking networking = gui.requesting_read_from_physics_server() if old_networking != networking: log.info(('STARTED' if networking else 'STOPPED') + ' networking with the physics server at ' + args.physics_server) if (networking and time.monotonic() - time_of_last_network_update > common.TIME_BETWEEN_NETWORK_UPDATES): # Our state is stale, get the latest update # TODO: what if this fails? Set networking to False? state = lead_server_connection.get_state() physics_engine.set_state(state) time_of_last_network_update = time.monotonic() else: state = physics_engine.get_state() gui.draw(state) if not networking: # When we're not networking, allow user input. physics_engine.handle_requests(gui.pop_commands()) gui.rate(common.FRAMERATE)
def __init__(self, savefile): self.physics_engine = physics.PhysicsEngine( common.load_savefile(common.savefile(savefile)))