def test_engines(self): """Test that engines use fuel and accelerate at the expected.""" with PhysicsEngine('tests/habitat.json') as physics_engine: # In this test case, there is a single entity that has 300 kg fuel. # heading, velocity, and position are all 0. throttle = 1 t_delta = 5 physics_engine.handle_requests([ network.Request(ident=network.Request.HAB_THROTTLE_SET, throttle_set=throttle) ], requested_t=0) initial = physics_engine.get_state(0) moved = physics_engine.get_state(t_delta) self.assertAlmostEqual(initial[0].heading, 0) self.assertAlmostEqual( moved[0].fuel, (initial[0].fuel - t_delta * throttle * common.craft_capabilities[HABITAT].fuel_cons)) self.assertTrue( moved[0].vx < (t_delta * calc.engine_acceleration(moved))) t_no_fuel = ( initial[0].fuel / (throttle * common.craft_capabilities[HABITAT].fuel_cons)) empty_fuel = physics_engine.get_state(t_no_fuel) after_empty_fuel = physics_engine.get_state(t_no_fuel + t_delta) self.assertEqual(round(empty_fuel[0].fuel), 0) self.assertEqual(round(after_empty_fuel[0].vx), round(empty_fuel[0].vx))
def _load_hook(self, textbox: vpython.winput): full_path = common.savefile(textbox.text) if full_path.is_file(): self._commands.append( network.Request(ident=network.Request.LOAD_SAVEFILE, loadfile=textbox.text)) textbox.text = f'Loaded {full_path}!' else: log.warning(f'Ignored non-existent loadfile: {full_path}') textbox.text = f'{full_path} not found!'
def main(args: argparse.Namespace): orbitx_connection = network.StateClient( network.Request.COMPAT, args.physics_server) log.info(f'Connecting to OrbitX Physics Server: {args.physics_server}') intermediary = orbitv_file_interface.OrbitVIntermediary( Path(args.piloting)) try: # Make sure we have a connection before continuing. orbitx_connection.get_state( [network.Request(ident=network.Request.NOOP)]) except grpc.RpcError as err: log.error(f'Could not connect to Physics Server: {err.code()}') StartupFailedGui(args.physics_server, err) return gui = CompatGui(args.physics_server, intermediary) last_orbitsse_modified_time = 0.0 last_orbitsse_read_datetime = datetime.fromtimestamp(0) try: while True: orbitsse_modified_time = intermediary.orbitsse.stat().st_mtime if orbitsse_modified_time == last_orbitsse_modified_time: # We've already seen this version of ORBITSSE.RND. update = network.Request(ident=network.Request.NOOP) else: last_orbitsse_modified_time = orbitsse_modified_time last_orbitsse_read_datetime = datetime.now() update = intermediary.read_engineering_update() state = orbitx_connection.get_state([update]) intermediary.write_state(state) gui.update( update, state._entity_names, last_orbitsse_read_datetime) except grpc.RpcError as err: log.error( f'Got response code {err.code()} from orbitx, shutting down') gui.notify_shutdown(err)
def test_performance(): # This just runs for 10 seconds and collects profiling data. import time with PhysicsEngine('OCESS.json') as physics_engine: physics_engine.handle_requests([ network.Request(ident=network.Request.TIME_ACC_SET, time_acc_set=common.TIME_ACCS[-2].value) ]) end_time = time.time() + 10 print(f"Profiling performance for {end_time - time.time()} seconds.") common.start_profiling() while time.time() < end_time: time.sleep(0.05) physics_engine.get_state()
def main(args: argparse.Namespace): orbitx_connection = network.NetworkedStateClient(network.Request.MIST, args.physics_server) log.info(f'Connecting to OrbitX Physics Server: {args.physics_server}') random.seed() try: while True: print( random.choice( ['ASTRONAUT STATUS: DYING', 'astronaut status: okay'])) print( orbitx_connection.get_state([network.Request()])['Earth'].pos) time.sleep(1) except grpc.RpcError as err: log.error(f'Got response code {err.code()} from orbitx, shutting down') raise err
def test_longterm_stable_landing(self): """Test that landed ships have stable altitude in the long term.""" savestate = common.load_savefile(common.savefile('OCESS.json')) initial_t = savestate.timestamp with PhysicsEngine('OCESS.json') as physics_engine: initial = physics_engine.get_state(initial_t + 10) physics_engine.handle_requests([ network.Request(ident=network.Request.TIME_ACC_SET, time_acc_set=common.TIME_ACCS[-1].value) ], requested_t=initial_t + 10) final = physics_engine.get_state(initial_t + 100_000) self.assertAlmostEqual(calc.fastnorm(initial['Earth'].pos - initial['Habitat'].pos), initial['Earth'].r + initial['Habitat'].r, delta=1) self.assertAlmostEqual(calc.fastnorm(final['Earth'].pos - final['Habitat'].pos), final['Earth'].r + final['Habitat'].r, delta=1)
def test_srbs(self): """Test that SRBs move the craft, and run out of fuel.""" with PhysicsEngine('tests/habitat.json') as physics_engine: t_delta = 5 physics_engine.handle_requests( [network.Request(ident=network.Request.IGNITE_SRBS)], requested_t=0) initial = physics_engine.get_state(0) moved = physics_engine.get_state(t_delta) self.assertAlmostEqual(initial[0].heading, 0) self.assertAlmostEqual(initial[0].vx, 0) self.assertAlmostEqual(moved[0].vx, t_delta * calc.engine_acceleration(moved)) srb_empty = physics_engine.get_state(common.SRB_BURNTIME) after_srb_empty = physics_engine.get_state(common.SRB_BURNTIME + 5) self.assertAlmostEqual(srb_empty[0].vx, after_srb_empty[0].vx)
def _read_update_from_orbitsse( orbitsse_path: Path, orbitv_names: List[str]) \ -> network.Request.EngineeringUpdate: """Reads information from ORBITSSE.RND and returns an ENGINEERING_UPDATE that contains the information.""" command = network.Request(ident=network.Request.ENGINEERING_UPDATE) with open(orbitsse_path, 'rb') as orbitsse: # See enghabv.bas at label 820 to find out what data is written at what # offsets in orbitsse.rnd orbitsse.seek(1) # Skip CHKbyte # This list mirrors Zvar in enghabv.bas, or Ztel in orbit5v Zvar: List[float] = [] for _ in range(0, 26): Zvar.append(_read_double(orbitsse)) command.engineering_update.nav_malfunction = round(Zvar[0]) command.engineering_update.max_thrust = Zvar[1] command.engineering_update.hab_fuel = Zvar[2] command.engineering_update.ayse_fuel = Zvar[3] command.engineering_update.hab_meltdown = bool(Zvar[4]) command.engineering_update.ayse_meltdown = bool(Zvar[5]) command.engineering_update.module_state = \ MODFLAG_TO_MODSTATE[round(Zvar[6])] command.engineering_update.radar = bool(2 & round(Zvar[7])) command.engineering_update.ins = bool(4 & round(Zvar[7])) command.engineering_update.los = bool(8 & round(Zvar[7])) # Zvar[8] is related to whether rad shields are on, but isn't used. # Zvar[9] has something to do with parachute or SRBs? # Zvar[10] and [11] are not referenced anywhere. # Zvar[12] is just if AYSE is connected?? unsure. command.engineering_update.wind_source_entity = \ orbitv_names[round(Zvar[13])] command.engineering_update.wind_speed = Zvar[14] command.engineering_update.wind_angle = Zvar[15] # Zvar[16] is something to do with a ufo? # It's called 'Zufo' in orbi5vs.bas:392. # later Zvar values look like a bunch of UFO-related stuff. return command