def run(task): ''' Given a task description, starts the application, waits for the node to stop running or for the duration to lapse. Stops the application after the execution. Can be used standalone or with the run_parallel helper. Example: >>> task = { >>> 'app_filename' : 'packages/detect_net/apps/apriltags_process.app.json', >>> 'more_json' : { >>> "config": { >>> "replay.interface": {"output": {"cask_directory": root}}, >>> "record.interface": {"input": {"base_directory": apriltags_root}} >>> } >>> }, >>> 'success_node': "replay.interface", >>> 'duration': 2040.0, 'poll_interval': 1.0, 'exit_interval': 1.0 >>> } >>> >>> run(task) Args: task['app_filename'] (str): the main application json filename task['more_json'] (dict): a dictionary containing additional configuration, to serialize into json and load as more_jsons to the app task['more_jsons'] (str): a comma-separated string of additional jsons to load task['name'] (str): the name of the application task['modules'] (List(str)): a list of modules to be loaded task['argv']: Command line arguments from sys.argv task['success_node'] (string): the name of the node to wait to stop running task['duration'] (float): timeout in seconds, can run forever, if duration is None task['exit_interval'] (float): exit interval in seconds Returns: True, if the success status had been reached. False otherwise. ''' with tempfile.NamedTemporaryFile(mode='w+t', suffix='.json', delete=True) as more_json: json.dump(task['more_json'], more_json) more_json.flush() more_jsons = ((task['more_jsons'] + ',') if 'more_jsons' in task else '') + more_json.name app = Application(app_filename=task['app_filename'], more_jsons=more_jsons, name=task.get('name', None), modules=task.get('modules', None), argv=task.get('argv', sys.argv)) app.start() status = app.wait_for_node(task['success_node'], task['duration']) time.sleep(task['exit_interval']) app.stop() return status == bindings.Status.Success
widget = app.add("sight").add(app.registry.isaac.sight.SightWidget, "IO") widget.config.type = "plot" widget.config.channels = [ { "name": "ur.universal_robots/UniversalRobots/gripper" }, { "name": "ur.universal_robots/UniversalRobots/pump" }, { "name": "ur.universal_robots/UniversalRobots/valve" } ] # run app app.start() try: while True: # Make sure urcap is running when starting the nodes program_running = app.receive("ur.subgraph", "interface", "robot_program_running") if program_running is None: time.sleep(1) else: if program_running.proto.flag == True and nodes_stopped: sequence_behavior.start() repeat_behavior.start() nodes_stopped = False elif program_running.proto.flag == False and nodes_stopped == False: sequence_behavior.stop() repeat_behavior.stop()
class TestPythonAppConfig(unittest.TestCase): ''' Test setting and getting Isaac configuration parameters. ''' @classmethod def setUpClass(cls): # method will be ran once before any test is ran pass @classmethod def tearDownClass(cls): pass def setUp(self): self.app = Application( 'packages/pyalice/tests/pyapp_config_test.app.json') self.app.start() def tearDown(self): self.app.stop() def test_get_config(self): dummy_bool = self.app.nodes["node"].components["ledger"].config[ "dummy_bool"] self.assertEqual(dummy_bool, True) dummy_float = self.app.nodes["node"].components["ledger"].config[ "dummy_float"] self.assertEqual(dummy_float, 1.111) dummy_list = self.app.nodes["node"].components["ledger"].config[ "dummy_list"] self.assertEqual(dummy_list, [1, 2, 3]) dummy_dict = self.app.nodes["node"].components["ledger"].config[ "dummy_dict"] self.assertEqual(dummy_dict['value_int'], 100) self.assertEqual(dummy_dict['value_string'], 'hi') def test_set_config(self): self.app.nodes["node"].components["ledger"].config[ "dummy_bool"] = False dummy_bool = self.app.nodes["node"].components["ledger"].config[ "dummy_bool"] self.assertEqual(dummy_bool, False) self.app.nodes["node"].components["ledger"].config[ "dummy_float"] = 2.222 dummy_float = self.app.nodes["node"].components["ledger"].config[ "dummy_float"] self.assertEqual(dummy_float, 2.222) self.app.nodes["node"].components["ledger"].config["dummy_list"] = [ 4, 5, 6 ] dummy_list = self.app.nodes["node"].components["ledger"].config[ "dummy_list"] self.assertEqual(dummy_list, [4, 5, 6]) self.app.nodes["node"].components["ledger"].config["dummy_dict"] = { 'value_int': 200, 'value_string': 'hello' } dummy_dict = self.app.nodes["node"].components["ledger"].config[ "dummy_dict"] self.assertEqual(dummy_dict['value_int'], 200) self.assertEqual(dummy_dict['value_string'], 'hello') def test_erase_config(self): component_config = self.app.nodes["node"].components["ledger"].config dummy_float = component_config["dummy_float"] self.assertEqual(dummy_float, 1.111) del component_config.dummy_float dummy_float = self.app.nodes["node"].components["ledger"].config[ "dummy_float"] self.assertIsNone(dummy_float) component_config.dummy_float = 2.0 dummy_float = component_config["dummy_float"] self.assertEqual(dummy_float, 2.0) del component_config['dummy_float'] dummy_float = self.app.nodes["node"].components["ledger"].config[ "dummy_float"] self.assertIsNone(dummy_float)
class TestComponent(unittest.TestCase): ''' Test loading subgraph via the application API ''' @classmethod def setUpClass(cls): # method will be ran once before any test is ran pass @classmethod def tearDownClass(cls): # method will be ran once after all tests have run pass def setUp(self): # ran before each test return super().setUp() def tearDown(self): # ran after each test return super().tearDown() def test_component_config(self): self._app = Application() self._app.add('node') node = self._app.nodes['node'] self.assertIsNotNone(node) result = self._app.load_module('viewers') self.assertTrue(result) component = node.add(self._app.registry.isaac.viewers.ImageViewer) self.assertTrue(isinstance(component, Component.Component)) self.assertIsNotNone(component) self.assertIsNotNone(component.config) component.config.reduce_scale = 2.0 self.assertEqual(component.config.reduce_scale, 2.0) self.assertEqual(component.config['reduce_scale'], 2.0) component.config['reduce_scale'] = 3.0 self.assertEqual(component.config['reduce_scale'], 3.0) self.assertEqual(component.config.reduce_scale, 3.0) self._app.start() self._app.stop() def test_component_access(self): self._app = Application() self._app.add('node') node = self._app.nodes['node'] self.assertIsNotNone(node) result = self._app.load_module('viewers') self.assertTrue(result) node.add(self._app.registry.isaac.viewers.ImageViewer) component = node.components['ImageViewer'] self.assertTrue(isinstance(component, Component.Component)) self.assertIsNotNone(component) self.assertEqual(node.components['ImageViewer'].config['target_fps'], 30.0) component = node.components['ImageViewer'] self.assertTrue(isinstance(component, Component.Component)) self.assertIsNotNone(component) self.assertEqual(node.components['ImageViewer'].config['target_fps'], 30.0) node.components['ImageViewer'].config['target_fps'] = 45.0 self.assertEqual(node.components['ImageViewer'].config['target_fps'], 45.0)
class TestApplication(unittest.TestCase): ''' Test loading subgraph via the application API ''' @classmethod def setUpClass(cls): # method will be ran once before any test is ran pass @classmethod def tearDownClass(cls): # method will be ran once after all tests have run pass def setUp(self): # ran before each test return super().setUp() def tearDown(self): # ran after each test return super().tearDown() def test_get_component(self): self._app = Application() self._app.add('node') node = self._app.nodes['node'] self.assertIsNotNone(node) # Get None if no component has such name component = node['ledger'] self.assertIsNone(component) component = node['MessageLedger'] self.assertIsNotNone(component) self._app.start() self._app.stop() def test_load_subgraph(self): self._app = Application() self._app.add('node') # loads subgraph and checks if the node/component are created, config is good self._app.load('packages/pyalice/tests/application_test.subgraph.json', 'foo') node = self._app.nodes['foo.camera_viewer'] component = node['ImageViewer'] self.assertIsNotNone(component) fps_readback = self._app.nodes['foo.camera_viewer'].components[ 'ImageViewer'].config['target_fps'] self.assertEqual(fps_readback, 11) camera_name_readback = self._app.nodes['foo.camera_viewer'].components[ 'ImageViewer'].config['camera_name'] self.assertEqual(camera_name_readback, 'bar') # loads the subgraph again with different prefix name self._app.load('packages/pyalice/tests/application_test.subgraph.json', 'foo1') node = self._app.nodes['foo1.camera_viewer'] component = node['ImageViewer'] self.assertIsNotNone(component) fps_readback = self._app.nodes['foo1.camera_viewer'].components[ 'ImageViewer'].config['target_fps'] self.assertEqual(fps_readback, 11) camera_name_readback = self._app.nodes[ 'foo1.camera_viewer'].components['ImageViewer'].config[ 'camera_name'] self._app.start() self._app.stop() def test_load_bogus_subgraph(self): bogus_json_filename = '' with tempfile.NamedTemporaryFile('w') as f: f.write('this is bogus json') bogus_json_filename = f.name self._app = Application() with self.assertRaises(ValueError): self._app.load('/no/such/file') with self.assertRaises(ValueError): self._app.load(bogus_json_filename) def test_load_subgraph_in_asset_path(self): self._app = Application() self._app.add('node') # override the asset path to point to our test location self._app._asset_path = 'packages/pyalice/tests/mock_asset_path' # loads subgraph and checks if the node/component are created, config is good self._app.load('mock_installed_application_test.subgraph.json', 'foo') pynode = self._app.nodes['foo.camera_viewer'] self.assertIsNotNone(pynode) component = pynode['ImageViewer'] self.assertIsNotNone(component) fps_readback = self._app.nodes['foo.camera_viewer'].components[ 'ImageViewer'].config['target_fps'] self.assertEqual(fps_readback, 11) camera_name_readback = self._app.nodes['foo.camera_viewer'].components[ 'ImageViewer'].config['camera_name'] self.assertEqual(camera_name_readback, 'bar') self._app.start() self._app.stop() def test_module_explorer(self): self._app = Application() self._app.load_module('json') self._app.registry.isaac.json.JsonToProto with self.assertRaises(RuntimeError): self._app.registry.isaac.foo def test_node_accesor(self): self._app = Application() self._app.load_module('json') node = self._app.add('foo1') self.assertIsNotNone(node) component = node.add(self._app.registry.isaac.json.JsonToProto, 'bar1') self.assertIsNotNone(component) node = self._app.add('foo2') self.assertIsNotNone(node) component = node.add(self._app.registry.isaac.json.ProtoToJson, 'bar2') self.assertIsNotNone(component) self.assertIsNotNone(self._app.nodes['foo1']) self.assertIsNotNone(self._app.nodes['foo2']) self.assertIsNone(self._app.nodes['foo3']) self._app.start() self._app.stop() def test_load_module(self): self._app = Application() result = self._app.load_module('message_generators') self.assertTrue(result) component = self._app.registry.isaac.message_generators.ImageLoader self.assertIsNotNone(component) self.assertEqual(str(component), "['isaac::message_generators::ImageLoader']") def test_clock(self): self._app = Application() self._app.start() clock = self._app.clock self.assertIsNotNone(clock) self.assertIsNotNone(clock.time) cur_time = clock.time self.assertGreater(cur_time, 0.0) self.assertGreater(clock.time, cur_time) self._app.stop() def test_pose(self): self._app = Application() self._app.start() self.assertTrue( self._app.atlas.set_pose( 'foo', 'bar', 1.0, [np.quaternion(1.0, 0.0, 0.0, 0.0), np.array([0.0, 0.0, 0.0])])) self.assertTrue( self._app.atlas.set_pose( 'foo', 'bar', 2.0, [np.quaternion(1.0, 0.0, 0.0, 0.0), np.array([1.0, 2.0, 3.0])])) read_pose = self._app.atlas.pose('foo', 'bar', 1.5) self.assertIsNotNone(read_pose) self.assertEqual(len(read_pose), 2) q = read_pose[0] t = read_pose[1] self.assertLess(q.w - 1.0, 1e-6) self.assertLess(q.x - 0.0, 1e-6) self.assertLess(q.y - 0.0, 1e-6) self.assertLess(q.z - 0.0, 1e-6) self.assertLess(t[0] - 0.5, 1e-6) self.assertLess(t[1] - 1.0, 1e-6) self.assertLess(t[2] - 1.5, 1e-6) self._app.stop() def test_node_start_stop(self): self._app = Application() result = self._app.load_module('message_generators') self.assertTrue(result) node = self._app.add('src') self.assertIsNotNone(node) component = node.add( self._app.registry.isaac.message_generators.PanTiltStateGenerator, 'pantilt') component.config['tick_period'] = '20 Hz' self.assertIsNotNone(component) node_sink = self._app.add('sink') self.assertIsNotNone(node_sink) self._app.connect(component, 'target', node_sink.components['MessageLedger'], 'rcv') self._app.start() time.sleep(0.1) msg = self._app.receive('sink', 'MessageLedger', 'rcv') self.assertIsNotNone(msg) node.stop() msg = self._app.receive('sink', 'MessageLedger', 'rcv') time.sleep(0.1) msg = self._app.receive('sink', 'MessageLedger', 'rcv') self.assertIsNone(msg) time.sleep(0.1) msg = self._app.receive('sink', 'MessageLedger', 'rcv') self.assertIsNone(msg) node.start() time.sleep(0.1) msg = self._app.receive('sink', 'MessageLedger', 'rcv') self.assertIsNotNone(msg) self._app.stop() with self.assertRaises(RuntimeError): self._app.stop() def test_wait_for_node(self): self._app = Application() self._app.load_module('behavior_tree') self._app.add('node').add( self._app.registry.isaac.behavior_tree.TimerBehavior) self._app.start() status = self._app.wait_for_node('node') self._app.stop() self.assertEqual(str(status), 'Status.Success', 'Should reach Status.Success in 1 second.') def test_wait_for_node_timeout(self): self._app = Application() self._app.load_module('behavior_tree') self._app.add('node').add( self._app.registry.isaac.behavior_tree.TimerBehavior) self._app.start() status = self._app.wait_for_node('node', duration=0.1) self._app.stop() self.assertEqual(str(status), 'Status.Running', 'Should still be in Status.Running') def test_run_until_succeed(self): now_secs = time.time() self._app = Application() self._app.add('success') node_success = self._app.nodes['success'] self.assertIsNotNone(node_success) self._app.nodes['success'].add(SucceedLaterCodelet) self._app.run('success') delta_secs = time.time() - now_secs self.assertGreater(delta_secs, 0.4) def test_run_until_failure(self): now_secs = time.time() self._app = Application() self._app.add('failure') node_failure = self._app.nodes['failure'] self.assertIsNotNone(node_failure) self._app.nodes['failure'].add(FailureLaterCodelet) self._app.run('failure') delta_secs = time.time() - now_secs self.assertGreater(delta_secs, 0.4) def test_perf_report(self): PERF_REPORT_PATH = '/tmp/perf_report' if os.path.exists(PERF_REPORT_PATH): os.remove(PERF_REPORT_PATH) self._app = Application( argv=['--performance_report_out', PERF_REPORT_PATH]) self._app.load_module('behavior_tree') self._app.add('node').add( self._app.registry.isaac.behavior_tree.TimerBehavior) self._app.run(0.2) self.assertTrue(os.path.exists(PERF_REPORT_PATH)) def test_max_duration(self): time_now = time.time() self._app = Application(argv=['--max_duration', '0.5s']) self._app.load_module('behavior_tree') self._app.add('node').add( self._app.registry.isaac.behavior_tree.TimerBehavior) self._app.run(2.0) time_dt = time.time() - time_now self.assertLess(time_dt, 1.0) time_now = time.time() self._app = Application(argv=['--max_duration', '0.5s']) self._app.load_module('behavior_tree') self._app.add('node').add( self._app.registry.isaac.behavior_tree.TimerBehavior) self._app.run(2) time_dt = time.time() - time_now self.assertLess(time_dt, 1.0) def test_print_node(self): self._app = Application() self._app.add('foo') node_names = self._app.nodes._names self.assertTrue(isinstance(node_names, list) and 'foo' in node_names) self._app.add('bar') node_names = self._app.nodes._names self.assertTrue( isinstance(node_names, list) and 'foo' in node_names and 'bar' in node_names) foo_node = None bar_node = None for n in self._app.nodes: if n.name == 'foo': foo_node = n if n.name == 'bar': bar_node = n self.assertIsNotNone(foo_node) self.assertIsNotNone(bar_node) def test_expand_asset(self): self._app = Application() ws, path = self._app._app.expand_asset_path('@workspace_//foo/bar') self.assertEqual(path, 'external/workspace_/foo/bar') self.assertEqual(ws, 'workspace_') ws1 = self._app.home_workspace_name self.assertEqual(len(ws1), 0) self._app.home_workspace_name = 'workspace_' ws2 = self._app.home_workspace_name self.assertEqual(ws2, 'workspace_') ws3, path3 = self._app._app.expand_asset_path('@workspace_//foo/bar') self.assertEqual(ws3, 'workspace_') self.assertEqual(path3, 'foo/bar')