예제 #1
0
    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))
예제 #2
0
 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!'
예제 #3
0
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)
예제 #4
0
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()
예제 #5
0
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
예제 #6
0
 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)
예제 #7
0
    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)
예제 #8
0
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