From 9189dc5d4d4b529633f8c5056cadbc22dad0f076 Mon Sep 17 00:00:00 2001 From: Christian Henkel Date: Fri, 1 Mar 2024 09:50:48 +0100 Subject: [PATCH 1/2] can plot xml Signed-off-by: Christian Henkel --- bt_view/src/bt_view/bt_view.py | 2 +- bt_view/src/bt_view/main.py | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/bt_view/src/bt_view/bt_view.py b/bt_view/src/bt_view/bt_view.py index 54eae5c..fe40339 100644 --- a/bt_view/src/bt_view/bt_view.py +++ b/bt_view/src/bt_view/bt_view.py @@ -198,7 +198,7 @@ def _make_history_image( def draw_pygraphviz( g: nx.Graph, fname: str, - modifier, + modifier: Optional[callable] = None, ): A = nx.nx_agraph.to_agraph(g) # convert to a graphviz graph for node in A.nodes(): diff --git a/bt_view/src/bt_view/main.py b/bt_view/src/bt_view/main.py index e8265fb..18e7720 100755 --- a/bt_view/src/bt_view/main.py +++ b/bt_view/src/bt_view/main.py @@ -20,10 +20,12 @@ import sys try: + from bt_view import draw_pygraphviz # type: ignore from bt_view import draw_pygraphviz_w_history # type: ignore from bt_view import draw_pygraphviz_w_returnstates # type: ignore from bt_view import draw_pygraphviz_w_valuemod # type: ignore except ImportError: + from .bt_view import draw_pygraphviz from .bt_view import draw_pygraphviz_w_history from .bt_view import draw_pygraphviz_w_returnstates from .bt_view import draw_pygraphviz_w_valuemod @@ -76,7 +78,7 @@ def main(args=sys.argv[1:]): parser.print_help() sys.exit(1) - if arguments.bt_xml_fname and arguments.bt_log_fbl_fname: + if arguments.bt_xml_fname and arguments.bt_log_fbl_fnames: print('When reading FBL log file, XML file is not needed ' 'and will be ignored') arguments.bt_xml_fname = None @@ -93,6 +95,7 @@ def main(args=sys.argv[1:]): g, _ = xml_to_networkx(bt_xml_fname) # if arguments.assemble_subtrees: # g, xpi = assemble_subtrees(g, xpi) + draw_pygraphviz(g, os.path.splitext(bt_xml_fname)[0]) # read fbl log file if arguments.bt_log_fbl_fnames: From 45c872e6889abfe71e49357f63d2b7edec8f0f47 Mon Sep 17 00:00:00 2001 From: Christian Henkel Date: Fri, 1 Mar 2024 10:17:58 +0100 Subject: [PATCH 2/2] testcase for the xml reading Signed-off-by: Christian Henkel --- bt_view/test/_test_data/behavior_tree.xml | 10 ++ .../_test_data/reference/behavior_tree.png | Bin 0 -> 41270 bytes .../_test_data/reference/behavior_tree.svg | 92 ++++++++++++++++++ bt_view/test/systemtests/test_bt_view_main.py | 35 ++++++- 4 files changed, 134 insertions(+), 3 deletions(-) create mode 100644 bt_view/test/_test_data/behavior_tree.xml create mode 100644 bt_view/test/_test_data/reference/behavior_tree.png create mode 100644 bt_view/test/_test_data/reference/behavior_tree.svg diff --git a/bt_view/test/_test_data/behavior_tree.xml b/bt_view/test/_test_data/behavior_tree.xml new file mode 100644 index 0000000..a45573d --- /dev/null +++ b/bt_view/test/_test_data/behavior_tree.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/bt_view/test/_test_data/reference/behavior_tree.png b/bt_view/test/_test_data/reference/behavior_tree.png new file mode 100644 index 0000000000000000000000000000000000000000..6ed2ddf2a8ba5b8e9d33e2b4b9ff46b22f5f3c50 GIT binary patch literal 41270 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 + + + + + + + + +10 + +BehaviorTree +ID: MainTree +category: NODECAT.ROOT +root: True + + + +100 + +Sequence +category: NODECAT.CONTROL +name: root_sequence + + + +10->100 + + + + + +1000 + +SaySomething +category: NODECAT.ACTION +message: Hello +name: action_hello + + + +100->1000 + + + + + +1001 + +OpenGripper +category: NODECAT.ACTION +name: open_gripper + + + +100->1001 + + + + + +1002 + +ApproachObject +category: NODECAT.ACTION +name: approach_object + + + +100->1002 + + + + + +1003 + +CloseGripper +category: NODECAT.ACTION +name: close_gripper + + + +100->1003 + + + + + diff --git a/bt_view/test/systemtests/test_bt_view_main.py b/bt_view/test/systemtests/test_bt_view_main.py index fb1908d..a9abbbd 100644 --- a/bt_view/test/systemtests/test_bt_view_main.py +++ b/bt_view/test/systemtests/test_bt_view_main.py @@ -82,7 +82,7 @@ def test_bt_view_main_single_fbl(self): fname = os.path.join( TEST_DATA_DIR, f'bt_trace{no}_fbl_log_{data}.svg') # load svg file - with open(fname, 'r') as f: + with open(fname, 'r', encoding='utf-8') as f: svg = f.read() svg_hashes_fbl[fname] = hash(svg) self._check_svg_for_nodenames(svg) @@ -227,14 +227,14 @@ def test_bt_view_main_multiple_fbl_files_merge(self): fname = os.path.join( TEST_DATA_DIR, f'bt_trace{no}_fbl_log_{data}.svg') # load svg file - with open(fname, 'r') as f: + with open(fname, 'r', encoding='utf-8') as f: svg = f.read() svg_hashes_fbl[fname] = hash(svg) self._check_svg_for_nodenames(svg) # also hash the combined svg files for fname in fnames_combined_svg: - with open(fname, 'r') as f: + with open(fname, 'r', encoding='utf-8') as f: svg = f.read() svg_hashes_fbl[fname] = hash(svg) self._check_svg_for_nodenames(svg) @@ -270,3 +270,32 @@ def test_bt_view_main_coverage(self): main(['--bt_log_fbl_fname', fname_2, '--coverage-threshold', '0.8']) self.assertEqual(cm.exception.code, 1) + + def test_bt_view_main_xml(self): + """Test if the correct images are created for XML input.""" + base_name: str = 'behavior_tree' + xml_fname = os.path.join( + TEST_DATA_DIR, + f'{base_name}.xml') + main(['--bt_xml_fname', xml_fname]) + + # make sure the files have been created + for ext in self.img_exts: + fname = os.path.join( + TEST_DATA_DIR, f'{base_name}.{ext}') + self.assertTrue(os.path.isfile(fname)) + + # make sure they match the reference + for ext in self.img_exts: + with open(os.path.join( + TEST_DATA_DIR, + f'{base_name}.{ext}' + ), 'rb') as f: + out = f.read() + with open(os.path.join( + TEST_DATA_DIR, + 'reference', + f'{base_name}.{ext}' + ), 'rb') as f: + ref = f.read() + self.assertEqual(out, ref)