From 9d8460217aafbeb3acac544022c4934a8f8c4607 Mon Sep 17 00:00:00 2001 From: Josh Date: Mon, 30 Sep 2024 16:16:25 -0400 Subject: [PATCH 1/4] fix adding sequence nodes --- src/social_norms_trees/mutate_tree.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/social_norms_trees/mutate_tree.py b/src/social_norms_trees/mutate_tree.py index 5e5933f5..020fca6f 100644 --- a/src/social_norms_trees/mutate_tree.py +++ b/src/social_norms_trees/mutate_tree.py @@ -10,7 +10,7 @@ from datetime import datetime -from social_norms_trees.custom_node_library import CustomBehavior +from social_norms_trees.custom_node_library import CustomBehavior, CustomSequence T = TypeVar("T", bound=py_trees.behaviour.Behaviour) @@ -153,7 +153,7 @@ def format_parents_with_indices(composite: py_trees.composites.Composite) -> str index_strings = [] i = 0 for b in iterate_nodes(composite): - if b.children: + if b.__class__.__name__ == "CustomSequence" or b.__class__.__name__ == "CustomSelector": index_strings.append(str(i)) else: index_strings.append("_") @@ -537,11 +537,19 @@ def add_node( behavior = prompt_select_node(behavior_library, f"Which behavior do you want to add?") - new_node = CustomBehavior( - name=behavior['display_name'], - id_=behavior['id'], - display_name=behavior['display_name'] - ) + if behavior['type'] == "Dummy": + new_node = CustomBehavior( + name=behavior['display_name'], + id_=behavior['id'], + display_name=behavior['display_name'] + ) + + elif behavior['type'] == "Sequence": + new_node = CustomSequence( + name=behavior['display_name'], + id_=behavior['id'], + display_name=behavior['display_name'], + ) new_parent = prompt_identify_parent_node( tree, f"What should its parent be?", display_nodes=True From cfa56acbf724b7990ca822b5ca903ef28938888f Mon Sep 17 00:00:00 2001 From: Josh Date: Thu, 3 Oct 2024 14:23:26 -0400 Subject: [PATCH 2/4] add error checking for behavior nodes, as well as overal node attributes --- src/social_norms_trees/serialize_tree.py | 31 ++++++++++++++++++++++-- src/social_norms_trees/ui_wrapper.py | 10 ++++++-- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/social_norms_trees/serialize_tree.py b/src/social_norms_trees/serialize_tree.py index 60526129..8faecd20 100644 --- a/src/social_norms_trees/serialize_tree.py +++ b/src/social_norms_trees/serialize_tree.py @@ -15,12 +15,30 @@ def serialize_node(node): def deserialize_tree(tree, behavior_library): def deserialize_node(node): + assert type(node['type'] == str), ( + f"\nThere was an invalid configuration detected in the inputted behavior tree: " + f"Invalid type for node attribute 'type' found for node '{node['name']}'. " + f"Please ensure that the 'name' attribute is a string." + ) + assert type(node['name'] == str), ( + f"\nThere was an invalid configuration detected in the inputted behavior tree: " + f"Invalid type for node attribute 'name' found for node '{node['name']}'. " + f"Please ensure that the 'name' attribute is a string." + ) + node_type = node['type'] - children = [deserialize_node(child) for child in node['children']] + assert node_type in ["Sequence", "Selector", "Behavior"], ( + f"\nThere was an invalid configuration detected in the inputted behavior tree: " + f"Invalid node type '{node_type}' found for node '{node['name']}'. " + f"Please ensure that all node types are correct and supported." + ) behavior = behavior_library.get_behavior_by_display_name(node['name']) if node_type == 'Sequence': + + children = [deserialize_node(child) for child in node['children']] + if behavior: return CustomSequence( name=behavior['display_name'], @@ -30,8 +48,17 @@ def deserialize_node(node): ) else: raise ValueError(f"Behavior {node['name']} not found in behavior library") + + #TODO: node type Selector elif node_type == 'Behavior': + + assert ('children' not in node or len(node['children']) == 0), ( + f"\nThere was an invalid configuration detected in the inputted behavior tree: " + f"Children were detected for Behavior type node '{node['name']}': " + f"Behavior nodes should not have any children. Please check the structure of your behavior tree." + ) + if behavior: return CustomBehavior( name=behavior['display_name'], @@ -40,5 +67,5 @@ def deserialize_node(node): ) else: raise ValueError(f"Behavior {node['name']} not found in behavior library") - + return deserialize_node(tree) \ No newline at end of file diff --git a/src/social_norms_trees/ui_wrapper.py b/src/social_norms_trees/ui_wrapper.py index ebd745d4..96ed5271 100644 --- a/src/social_norms_trees/ui_wrapper.py +++ b/src/social_norms_trees/ui_wrapper.py @@ -129,7 +129,7 @@ def run_experiment(db, origin_tree, experiment_id, behavior_library): origin_tree, action_log = add_node(origin_tree, behavior_library) db[experiment_id]["action_history"].append(action_log) - else: + else: print("Invalid choice, please select a valid number (1, 2, or 3).\n") else: @@ -154,7 +154,13 @@ def main(): #load tree to run experiment on, and behavior library RESOURCES_FILE = "resources.json" - original_tree, behavior_library = load_resources(RESOURCES_FILE) + try: + original_tree, behavior_library = load_resources(RESOURCES_FILE) + except Exception as e: + print(f"An error occured when loading resources for this experiment: {e}\n") + print("\nSimulation has ended.") + + return participant_id, experiment_id = experiment_setup(db, original_tree) db = run_experiment(db, original_tree, experiment_id, behavior_library) From 2d111eca186888b882312418e6f8655e01ba932e Mon Sep 17 00:00:00 2001 From: Josh Date: Fri, 4 Oct 2024 15:42:33 -0400 Subject: [PATCH 3/4] remove try/except from main --- src/social_norms_trees/ui_wrapper.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/social_norms_trees/ui_wrapper.py b/src/social_norms_trees/ui_wrapper.py index d28c959e..53240683 100644 --- a/src/social_norms_trees/ui_wrapper.py +++ b/src/social_norms_trees/ui_wrapper.py @@ -163,15 +163,9 @@ def main(): #load tree to run experiment on, and behavior library RESOURCES_FILE = "resources.json" - try: - original_tree, behavior_library, context_paragraph = load_resources(RESOURCES_FILE) - print(f"\nContext of this experiment: {context_paragraph}") - - except Exception as e: - print(f"An error occured when loading resources for this experiment: {e}\n") - print("\nSimulation has ended.") + original_tree, behavior_library, context_paragraph = load_resources(RESOURCES_FILE) + print(f"\nContext of this experiment: {context_paragraph}") - return participant_id, experiment_id = experiment_setup(db, original_tree) db = run_experiment(db, original_tree, experiment_id, behavior_library) From 455ad075a82e0f8deda9226473b15e03117a7f46 Mon Sep 17 00:00:00 2001 From: Josh Date: Fri, 4 Oct 2024 15:45:18 -0400 Subject: [PATCH 4/4] fix bugs with new behavior class --- src/social_norms_trees/mutate_tree.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/social_norms_trees/mutate_tree.py b/src/social_norms_trees/mutate_tree.py index 30923d11..82e3eb2e 100644 --- a/src/social_norms_trees/mutate_tree.py +++ b/src/social_norms_trees/mutate_tree.py @@ -512,7 +512,7 @@ def exchange_nodes( def prompt_select_node(behavior_library, text): - for idx, tree_name in enumerate(behavior_library.behaviors.keys(), 1): + for idx, tree_name in enumerate(behavior_library.behavior_from_display_name.keys(), 1): print(f"{idx}. {tree_name}") choices = [str(i + 1) for i in range(len(behavior_library.behaviors))] @@ -522,10 +522,9 @@ def prompt_select_node(behavior_library, text): show_choices=False ) - node_key = list(behavior_library.behaviors.keys())[int(node_index)-1] - behavior = behavior_library.behaviors[node_key] + node_key = list(behavior_library.behavior_from_display_name.keys())[node_index-1] - return behavior + return behavior_library.behavior_from_display_name[node_key] def add_node( @@ -542,7 +541,7 @@ def add_node( behavior = prompt_select_node(behavior_library, f"Which behavior do you want to add?") - if behavior['type'] == "Dummy": + if behavior['type'] == "Behavior": new_node = CustomBehavior( name=behavior['display_name'], id_=behavior['id'],