def test_rover_create_and_setup(tmpdir): directory = str(tmpdir.realpath()) pilot = QueueReceiver() teleop = QueueReceiver() ipc_chatter = QueueReceiver() ipc_server = CollectServer() app = RoverApplication(config_dir=directory) app.image_publisher = CollectPublisher() app.state_publisher = CollectPublisher() app.ipc_server = ipc_server app.pilot = lambda: pilot.get_latest() app.teleop = lambda: teleop.get_latest() app.ipc_chatter = lambda: ipc_chatter.pop_latest() try: # The application writes a new user configuration file if none exists at the configuration location. assert len(glob.glob(os.path.join(directory, 'config.ini'))) == 0 app.setup() assert len(glob.glob(os.path.join(directory, 'config.ini'))) == 1 # The settings must result in a workable instance. assert len(ipc_server.collect()) == 1 assert not bool(ipc_server.get_latest()) assert app.get_hz() > 0 # # Change the configuration and request a restart. # Write a new config file. previous_process_frequency = app.get_hz() new_process_frequency = previous_process_frequency + 10 _parser = SafeConfigParser() _parser.add_section('vehicle') _parser.set('vehicle', 'clock.hz', str(new_process_frequency)) with open(os.path.join(directory, 'test_config.ini'), 'wb') as f: _parser.write(f) # # Issue the restart request. ipc_chatter.add(dict(command='restart')) app.step() assert len(ipc_server.collect()) == 2 assert not bool(ipc_server.get_latest()) assert app.get_hz() == new_process_frequency finally: app.finish()
def test_command_history_reset(): relay = MyRelay() publisher = CollectPublisher(topic='test/status') platform = MyPlatform() # With hz=1 the command history threshold is 180. application = MainApplication(relay=relay, hz=1) application.platform = platform application.publisher = publisher application.setup() # Send the first commands to do valid communication. command = dict(steering=0.1, throttle=0.2, reverse=0) list( map( lambda _: (platform.send( dict(time=timestamp(), method='ras/servo/drive', data=command) ), application.step()), list(range(10)))) platform.send( dict(time=timestamp(), method='ras/servo/drive', data=dict(wakeup=1))) application.step() assert not relay.is_open() publisher.clear() # Send zero commands until just below the threshold. zero = dict(steering=0, throttle=0, reverse=0) list( map( lambda _: (platform.send( dict(time=timestamp(), method='ras/servo/drive', data=zero)), application.step()), list(range(180)))) assert not relay.is_open() publisher.clear() # And then a good command and some zero commands again. # The relay should remain open. platform.send( dict(time=timestamp(), method='ras/servo/drive', data=command)) application.step() list( map( lambda _: (platform.send( dict(time=timestamp(), method='ras/servo/drive', data=zero)), application.step()), list(range(10)))) assert not relay.is_open() publisher.clear() application.finish()
def test_relay_wakeup_reset(): relay = MyRelay() publisher = CollectPublisher(topic='test/status') platform = MyPlatform() # With hz=1 the command history threshold is 180. application = MainApplication(relay=relay, hz=1) application.platform = platform application.publisher = publisher application.setup() # Send the first commands to do valid communication. command = dict(steering=0.1, throttle=0.2, reverse=0) list( map( lambda _: (platform.send( dict(time=timestamp(), method='ras/servo/drive', data=command) ), application.step()), list(range(10)))) platform.send( dict(time=timestamp(), method='ras/servo/drive', data=dict(wakeup=1))) application.step() assert not relay.is_open() publisher.clear() # Send the zero commands and wakeup. zero = dict(steering=0, throttle=0, reverse=0) list( map( lambda _: (platform.send( dict(time=timestamp(), method='ras/servo/drive', data=zero)), application.step()), list(range(180)))) platform.send( dict(time=timestamp(), method='ras/servo/drive', data=dict(wakeup=1))) application.step() assert not relay.is_open() publisher.clear() # After wakeup the counters need to have been reset in order not to revert immediately. list( map( lambda _: (platform.send( dict(time=timestamp(), method='ras/servo/drive', data=zero)), application.step()), list(range(10)))) assert not relay.is_open() publisher.clear() application.finish()
def test_create_and_setup(tmpdir): directory = str(tmpdir.realpath()) ipc_server = CollectServer() pilot = QueueReceiver() teleop = QueueReceiver() ipc_chatter = QueueReceiver() runner = TFRunner(navigator=FakeNavigator()) app = InferenceApplication(runner=runner, config_dir=directory, internal_models=directory) app.publisher = CollectPublisher() app.camera = QueueCamera() app.ipc_server = ipc_server app.teleop = lambda: teleop.get_latest() app.pilot = lambda: pilot.get_latest() app.ipc_chatter = lambda: ipc_chatter.pop_latest() try: # The default settings must result in a workable instance. app.setup() assert len(ipc_server.collect()) == 1 assert not bool(ipc_server.get_latest()) assert app.get_process_frequency() != 0 # # Change the configuration and request a restart. # Write a new config file. previous_process_frequency = app.get_process_frequency() new_process_frequency = previous_process_frequency + 10 _parser = SafeConfigParser() _parser.add_section('inference') _parser.set('inference', 'clock.hz', str(new_process_frequency)) with open(os.path.join(directory, 'test_config.ini'), 'w') as f: _parser.write(f) # # Issue the restart request. ipc_chatter.add(dict(command='restart')) app.step() assert len(ipc_server.collect()) == 2 assert not bool(ipc_server.get_latest()) assert app.get_process_frequency() == new_process_frequency finally: app.finish()
def test_relay_cycle(): relay = MyRelay() publisher = CollectPublisher(topic='test/status') platform = MyPlatform() application = MainApplication(relay=relay) application.platform = platform application.publisher = publisher application.setup() # Without reliable communication the relay is open. application.step() assert relay.is_open() publisher.clear() # A non-zero command. command = dict(steering=0.1, throttle=0.2, reverse=0) # Send the first commands to do valid communication. # The integrity protocol does not assume valid by default. list( map( lambda _: (platform.send( dict(time=timestamp(), method='ras/servo/drive', data=command) ), application.step()), list(range(10)))) assert relay.is_open() publisher.clear() # Send wakeup to close the relay after startup. platform.send( dict(time=timestamp(), method='ras/servo/drive', data=dict(wakeup=1))) application.step() assert not relay.is_open() publisher.clear() # Simulate communication violations. list( map( lambda i: (platform.send( dict(time=timestamp() + i * 1e6, method='ras/servo/drive', data=command)), application.step()), list(range(10)))) assert relay.is_open() publisher.clear() # And resume. list( map( lambda _: (platform.send( dict(time=timestamp(), method='ras/servo/drive', data=command) ), application.step()), list(range(10)))) assert not relay.is_open() publisher.clear() # Pretend missing commands but valid communication. _null_command = dict(steering=0, throttle=0, reverse=0) list( map( lambda _: (platform.send( dict(time=timestamp(), method='ras/servo/drive', data=_null_command)), application.step()), list(range(5000)))) assert relay.is_open() publisher.clear() # The communication requirements must still be met to let the other side know we are operational. platform.send( dict(time=timestamp(), method='ras/servo/drive', data=_null_command)) application.step() assert len(publisher.collect()) > 0 publisher.clear() # Wakeup again. platform.send( dict(time=timestamp(), method='ras/servo/drive', data=dict(wakeup=1))) application.step() assert not relay.is_open() application.finish() assert relay.is_open()
def test_create_and_setup(tmpdir): directory = str(tmpdir.realpath()) publisher = CollectPublisher() ipc_server = CollectServer() teleop = QueueReceiver() ros = QueueReceiver() vehicle = QueueReceiver() ipc_chatter = QueueReceiver() route_store = ReloadableDataSource( FileSystemRouteDataSource(directory=directory, load_instructions=True)) app = PilotApplication(CommandProcessor(route_store), config_dir=directory) app.publisher = publisher app.ipc_server = ipc_server app.teleop = lambda: teleop.get_latest() app.ros = lambda: ros.get_latest() app.vehicle = lambda: vehicle.get_latest() app.inference = lambda: None app.ipc_chatter = lambda: ipc_chatter.get_latest() try: # The default settings must result in a workable instance. app.setup() assert len(ipc_server.collect()) == 1 assert not bool(ipc_server.get_latest()) # # Switch to direct driver mode. teleop.add(dict(time=timestamp(), navigator=dict(), button_b=1)) app.step() teleop.add(dict(time=timestamp(), navigator=dict())) vehicle.add(dict(time=timestamp())) app.step() status = publisher.get_latest() assert status.get('driver') == 'driver_mode.teleop.direct' map(lambda x: x.clear(), [teleop, vehicle, publisher]) # # Change the configuration and request a restart. # Write a new config file. previous_process_frequency = app.get_process_frequency() new_process_frequency = previous_process_frequency + 10 _parser = SafeConfigParser() _parser.add_section('pilot') _parser.set('pilot', 'clock.hz', str(new_process_frequency)) with open(os.path.join(directory, 'test_config.ini'), 'wb') as f: _parser.write(f) # # Issue the restart request. ipc_chatter.add(dict(command='restart')) app.step() assert len(ipc_server.collect()) == 2 assert not bool(ipc_server.get_latest()) assert app.get_process_frequency() == new_process_frequency # The driver should still be in direct mode. teleop.add(dict(time=timestamp(), navigator=dict())) vehicle.add(dict(time=timestamp())) app.step() status = publisher.get_latest() assert status.get('driver') == 'driver_mode.teleop.direct' map(lambda x: x.clear(), [teleop, vehicle, publisher]) finally: app.finish()