From 5320acc838d00638f2b1769283818dba8e89133f Mon Sep 17 00:00:00 2001 From: ChenXL97 <908926798@qq.com> Date: Thu, 9 Nov 2023 16:07:02 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=88=A0=E9=99=A4=E5=AD=90?= =?UTF-8?q?=E8=A1=8C=E4=B8=BA=E6=A0=91bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bracket_ptml.ptml | 4 - robowaiter/behavior_lib/_base/Act.py | 1 + robowaiter/behavior_lib/_base/Behavior.py | 14 +- robowaiter/behavior_lib/_base/Cond.py | 1 + robowaiter/behavior_lib/_base/Selector.py | 1 + robowaiter/behavior_lib/_base/Sequence.py | 1 + robowaiter/behavior_lib/act/DealChat.py | 3 +- robowaiter/behavior_lib/act/DelSubTree.py | 2 - robowaiter/behavior_tree/__init__.py | 1 - .../behavior_tree/ptml/test/ptml_test.py | 7 +- robowaiter/behavior_tree/ptml/test/test.dot | 46 +-- robowaiter/behavior_tree/ptml/test/test.png | Bin 35138 -> 53221 bytes robowaiter/behavior_tree/ptml/test/test.svg | 192 +++++----- robowaiter/llm_client/ask_llm.py | 5 +- robowaiter/robot/robot.py | 36 +- robowaiter/scene/tasks/VLM.py | 9 +- robowaiter/utils/__init__.py | 5 + robowaiter/utils/bt/__init__.py | 0 robowaiter/utils/bt/draw.py | 331 ++++++++++++++++++ .../utils.py => utils/bt/load.py} | 12 - robowaiter/utils/bt/visitor.py | 30 ++ run_robowaiter.py | 2 +- sub_task.ptml | 6 +- 23 files changed, 520 insertions(+), 189 deletions(-) delete mode 100644 bracket_ptml.ptml create mode 100644 robowaiter/utils/__init__.py create mode 100644 robowaiter/utils/bt/__init__.py create mode 100644 robowaiter/utils/bt/draw.py rename robowaiter/{behavior_tree/utils.py => utils/bt/load.py} (79%) create mode 100644 robowaiter/utils/bt/visitor.py diff --git a/bracket_ptml.ptml b/bracket_ptml.ptml deleted file mode 100644 index be5a831..0000000 --- a/bracket_ptml.ptml +++ /dev/null @@ -1,4 +0,0 @@ -selector{ -cond At(Robot, Table) -} -} \ No newline at end of file diff --git a/robowaiter/behavior_lib/_base/Act.py b/robowaiter/behavior_lib/_base/Act.py index aed1bc2..b402ed9 100644 --- a/robowaiter/behavior_lib/_base/Act.py +++ b/robowaiter/behavior_lib/_base/Act.py @@ -2,6 +2,7 @@ from robowaiter.behavior_lib._base.Behavior import Bahavior class Act(Bahavior): print_name_prefix = "act " + type = 'Act' def __init__(self,*args): super().__init__(*args) diff --git a/robowaiter/behavior_lib/_base/Behavior.py b/robowaiter/behavior_lib/_base/Behavior.py index 74a1831..2a99f03 100644 --- a/robowaiter/behavior_lib/_base/Behavior.py +++ b/robowaiter/behavior_lib/_base/Behavior.py @@ -1,18 +1,7 @@ import py_trees as ptree from typing import Any import enum - -class Status(enum.Enum): - """An enumerator representing the status of a behavior.""" - - SUCCESS = ptree.common.Status.SUCCESS - """Behaviour check has passed, or execution of its action has finished with a successful result.""" - FAILURE = ptree.common.Status.FAILURE - """Behaviour check has failed, or execution of its action finished with a failed result.""" - RUNNING = ptree.common.Status.RUNNING - """Behaviour is in the middle of executing some action, result still pending.""" - INVALID = ptree.common.Status.INVALID - """Behaviour is uninitialised and/or in an inactive state, i.e. not currently being ticked.""" +from py_trees.common import Status # _base Behavior @@ -53,7 +42,6 @@ class Bahavior(ptree.behaviour.Behaviour): def update(self) -> Status: re = self._update() - print(f"{self.__class__.__name__}: {re.value}") return re def terminate(self, new_status: Status) -> None: diff --git a/robowaiter/behavior_lib/_base/Cond.py b/robowaiter/behavior_lib/_base/Cond.py index dc9f1d9..f8da01d 100644 --- a/robowaiter/behavior_lib/_base/Cond.py +++ b/robowaiter/behavior_lib/_base/Cond.py @@ -4,6 +4,7 @@ from robowaiter.behavior_lib._base.Behavior import Bahavior, Status class Cond(Bahavior): print_name_prefix = "cond " + type = 'Cond' def __init__(self,*args): super().__init__(*args) diff --git a/robowaiter/behavior_lib/_base/Selector.py b/robowaiter/behavior_lib/_base/Selector.py index 0dfd032..1c84639 100644 --- a/robowaiter/behavior_lib/_base/Selector.py +++ b/robowaiter/behavior_lib/_base/Selector.py @@ -3,6 +3,7 @@ from typing import Any class Selector(ptree.composites.Selector): print_name = "Selector" + type = "Selector" def __init__(self,*args,**kwargs): super().__init__(*args,**kwargs) diff --git a/robowaiter/behavior_lib/_base/Sequence.py b/robowaiter/behavior_lib/_base/Sequence.py index 281ccfb..702a0d9 100644 --- a/robowaiter/behavior_lib/_base/Sequence.py +++ b/robowaiter/behavior_lib/_base/Sequence.py @@ -3,6 +3,7 @@ from typing import Any class Sequence(ptree.composites.Sequence): print_name = "Sequence" + type = "Sequence" def __init__(self,*args,**kwargs): super().__init__(*args,**kwargs) diff --git a/robowaiter/behavior_lib/act/DealChat.py b/robowaiter/behavior_lib/act/DealChat.py index 5a0c406..d30b7fd 100644 --- a/robowaiter/behavior_lib/act/DealChat.py +++ b/robowaiter/behavior_lib/act/DealChat.py @@ -1,8 +1,7 @@ import py_trees as ptree -from typing import Any from robowaiter.behavior_lib._base.Act import Act from robowaiter.llm_client.ask_llm import ask_llm -from robowaiter.behavior_tree.utils import load_bt_from_ptml,print_tree_from_root + fixed_answers = { "测试VLM:做一杯咖啡": ''' diff --git a/robowaiter/behavior_lib/act/DelSubTree.py b/robowaiter/behavior_lib/act/DelSubTree.py index 9b857d5..9c43c00 100644 --- a/robowaiter/behavior_lib/act/DelSubTree.py +++ b/robowaiter/behavior_lib/act/DelSubTree.py @@ -10,7 +10,5 @@ class DelSubTree(Act): def _update(self) -> ptree.common.Status: sub_task_tree = self.parent - print(self.scene.sub_task_seq.children) - print(sub_task_tree) self.scene.sub_task_seq.children.remove(sub_task_tree) return Status.RUNNING \ No newline at end of file diff --git a/robowaiter/behavior_tree/__init__.py b/robowaiter/behavior_tree/__init__.py index ae3102d..8c15ec4 100644 --- a/robowaiter/behavior_tree/__init__.py +++ b/robowaiter/behavior_tree/__init__.py @@ -1,3 +1,2 @@ # from robowaiter.behavior_tree.behavior_tree import BehaviorTree -from robowaiter.behavior_tree.utils import load_bt_from_ptml \ No newline at end of file diff --git a/robowaiter/behavior_tree/ptml/test/ptml_test.py b/robowaiter/behavior_tree/ptml/test/ptml_test.py index cfec608..70d629f 100644 --- a/robowaiter/behavior_tree/ptml/test/ptml_test.py +++ b/robowaiter/behavior_tree/ptml/test/ptml_test.py @@ -1,12 +1,9 @@ -import os -import py_trees as ptree - # from robowaiter.scene.scene import Scene # from robowaiter.behavior_tree.ptml.ptmlCompiler import load import os from robowaiter import Robot, task_map - +from robowaiter.utils.bt.draw import render_dot_tree if __name__ == '__main__': TASK_NAME = 'OT' @@ -21,7 +18,7 @@ if __name__ == '__main__': # create task task = task_map[TASK_NAME](robot) - ptree.display.render_dot_tree(robot.bt.root,name="test") + render_dot_tree(robot.bt.root,name="test") # build and tick # scene.BT = ptree.trees.BehaviourTree(scene.BT) # todo: tick this bt diff --git a/robowaiter/behavior_tree/ptml/test/test.dot b/robowaiter/behavior_tree/ptml/test/test.dot index c8831ce..1efeebd 100644 --- a/robowaiter/behavior_tree/ptml/test/test.dot +++ b/robowaiter/behavior_tree/ptml/test/test.dot @@ -3,27 +3,27 @@ ordering=out; graph [fontname="times-roman"]; node [fontname="times-roman"]; edge [fontname="times-roman"]; -Selector [fillcolor=cyan, fontcolor=black, fontsize=9, label=Selector, shape=octagon, style=filled]; -"Selector*" [fillcolor=cyan, fontcolor=black, fontsize=9, label="Selector*", shape=octagon, style=filled]; -Selector -> "Selector*"; -HasMap [fillcolor=gray, fontcolor=black, fontsize=9, label=HasMap, shape=ellipse, style=filled]; -"Selector*" -> HasMap; -ExploreEnv [fillcolor=gray, fontcolor=black, fontsize=9, label=ExploreEnv, shape=ellipse, style=filled]; -"Selector*" -> ExploreEnv; -Sequence [fillcolor=orange, fontcolor=black, fontsize=9, label=Sequence, shape=box, style=filled]; -Selector -> Sequence; -Chatting [fillcolor=gray, fontcolor=black, fontsize=9, label=Chatting, shape=ellipse, style=filled]; -Sequence -> Chatting; -DealChat [fillcolor=gray, fontcolor=black, fontsize=9, label=DealChat, shape=ellipse, style=filled]; -Sequence -> DealChat; -"Sequence*" [fillcolor=orange, fontcolor=black, fontsize=9, label="Sequence*", shape=box, style=filled]; -Selector -> "Sequence*"; -HasSubTask [fillcolor=gray, fontcolor=black, fontsize=9, label=HasSubTask, shape=ellipse, style=filled]; -"Sequence*" -> HasSubTask; -"Sequence**" [fillcolor=orange, fontcolor=black, fontsize=9, label="Sequence**", shape=box, style=filled]; -"Sequence*" -> "Sequence**"; -"At(Robot,Table)" [fillcolor=gray, fontcolor=black, fontsize=9, label="At(Robot,Table)", shape=ellipse, style=filled]; -"Sequence**" -> "At(Robot,Table)"; -"At(Robot,Table)*" [fillcolor=gray, fontcolor=black, fontsize=9, label="At(Robot,Table)*", shape=ellipse, style=filled]; -"Sequence*" -> "At(Robot,Table)*"; +"34d1cf8a-42d6-49de-a458-0c7d3bffc436" [fillcolor=cyan, fontcolor=black, fontsize=20, height=0.01, label="?", shape=diamond, style=filled, width=0.01]; +"33446211-2d5c-4e1d-bdb5-5ded443a713c" [fillcolor=cyan, fontcolor=black, fontsize=20, height=0.01, label="?", shape=diamond, style=filled, width=0.01]; +"34d1cf8a-42d6-49de-a458-0c7d3bffc436" -> "33446211-2d5c-4e1d-bdb5-5ded443a713c"; +"96622c49-e2f6-4de9-9284-0c5eabbdd741" [fillcolor=yellow, fontcolor=black, fontsize=20, label=HasMap, shape=ellipse, style=filled]; +"33446211-2d5c-4e1d-bdb5-5ded443a713c" -> "96622c49-e2f6-4de9-9284-0c5eabbdd741"; +"dc007c72-0338-4616-bac2-bc39c81d2b77" [fillcolor=lawngreen, fontcolor=black, fontsize=20, label=ExploreEnv, shape=box, style=filled]; +"33446211-2d5c-4e1d-bdb5-5ded443a713c" -> "dc007c72-0338-4616-bac2-bc39c81d2b77"; +"6fe9e522-557f-473a-a582-2f0d17d1a4f1" [fillcolor=orange, fontcolor=black, fontsize=20, height=0.01, label=">", shape=octagon, style=filled, width=0.01]; +"34d1cf8a-42d6-49de-a458-0c7d3bffc436" -> "6fe9e522-557f-473a-a582-2f0d17d1a4f1"; +"cf3e4033-88b1-41bb-a638-26cc06e7a3dd" [fillcolor=yellow, fontcolor=black, fontsize=20, label=Chatting, shape=ellipse, style=filled]; +"6fe9e522-557f-473a-a582-2f0d17d1a4f1" -> "cf3e4033-88b1-41bb-a638-26cc06e7a3dd"; +"d2e8364e-dd83-4abb-8234-8466ff0c0483" [fillcolor=lawngreen, fontcolor=black, fontsize=20, label=DealChat, shape=box, style=filled]; +"6fe9e522-557f-473a-a582-2f0d17d1a4f1" -> "d2e8364e-dd83-4abb-8234-8466ff0c0483"; +"d78eaf31-cc9d-484d-b564-dbd5912378fa" [fillcolor=orange, fontcolor=black, fontsize=20, height=0.01, label=">", shape=octagon, style=filled, width=0.01]; +"34d1cf8a-42d6-49de-a458-0c7d3bffc436" -> "d78eaf31-cc9d-484d-b564-dbd5912378fa"; +"85284b02-fc8e-4418-8d6b-7a154d2004f6" [fillcolor=yellow, fontcolor=black, fontsize=20, label=HasSubTask, shape=ellipse, style=filled]; +"d78eaf31-cc9d-484d-b564-dbd5912378fa" -> "85284b02-fc8e-4418-8d6b-7a154d2004f6"; +"eb1bba56-55b1-4a71-8b31-0381812f588a" [fillcolor=orange, fontcolor=black, fontsize=20, height=0.01, label=">", shape=octagon, style=filled, width=0.01]; +"d78eaf31-cc9d-484d-b564-dbd5912378fa" -> "eb1bba56-55b1-4a71-8b31-0381812f588a"; +"20b57b46-d59d-4b04-a4ed-eff12e6adc91" [fillcolor=yellow, fontcolor=black, fontsize=20, label="At(Robot,Table)", shape=ellipse, style=filled]; +"eb1bba56-55b1-4a71-8b31-0381812f588a" -> "20b57b46-d59d-4b04-a4ed-eff12e6adc91"; +"3d7f6aa9-62b5-4852-ab3e-ac0199cc46a8" [fillcolor=yellow, fontcolor=black, fontsize=20, label="At(Robot,Table)", shape=ellipse, style=filled]; +"d78eaf31-cc9d-484d-b564-dbd5912378fa" -> "3d7f6aa9-62b5-4852-ab3e-ac0199cc46a8"; } diff --git a/robowaiter/behavior_tree/ptml/test/test.png b/robowaiter/behavior_tree/ptml/test/test.png index 4eb2c3bfb89ac6789cd9db51b5c1c64497473a64..df4a1f98b95584499d3fb6683b1143a32e22f714 100644 GIT binary patch literal 53221 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 literal 35138 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 t`ZW4~11F+XRz|(lZ~TNoS$RXVvW*|JhorW - - + + pastafarianism - - + + -Selector - -Selector +34d1cf8a-42d6-49de-a458-0c7d3bffc436 + +? - + -Selector* - -Selector* +33446211-2d5c-4e1d-bdb5-5ded443a713c + +? - + -Selector->Selector* - - +34d1cf8a-42d6-49de-a458-0c7d3bffc436->33446211-2d5c-4e1d-bdb5-5ded443a713c + + - + -Sequence - -Sequence +6fe9e522-557f-473a-a582-2f0d17d1a4f1 + +> - + -Selector->Sequence - - +34d1cf8a-42d6-49de-a458-0c7d3bffc436->6fe9e522-557f-473a-a582-2f0d17d1a4f1 + + - + -Sequence* - -Sequence* +d78eaf31-cc9d-484d-b564-dbd5912378fa + +> - + -Selector->Sequence* - - +34d1cf8a-42d6-49de-a458-0c7d3bffc436->d78eaf31-cc9d-484d-b564-dbd5912378fa + + - + -HasMap - -HasMap +96622c49-e2f6-4de9-9284-0c5eabbdd741 + +HasMap - + -Selector*->HasMap - - +33446211-2d5c-4e1d-bdb5-5ded443a713c->96622c49-e2f6-4de9-9284-0c5eabbdd741 + + - + -ExploreEnv - -ExploreEnv +dc007c72-0338-4616-bac2-bc39c81d2b77 + +ExploreEnv - + -Selector*->ExploreEnv - - +33446211-2d5c-4e1d-bdb5-5ded443a713c->dc007c72-0338-4616-bac2-bc39c81d2b77 + + - + -Chatting - -Chatting +cf3e4033-88b1-41bb-a638-26cc06e7a3dd + +Chatting - + -Sequence->Chatting - - +6fe9e522-557f-473a-a582-2f0d17d1a4f1->cf3e4033-88b1-41bb-a638-26cc06e7a3dd + + - + -DealChat - -DealChat +d2e8364e-dd83-4abb-8234-8466ff0c0483 + +DealChat - + -Sequence->DealChat - - +6fe9e522-557f-473a-a582-2f0d17d1a4f1->d2e8364e-dd83-4abb-8234-8466ff0c0483 + + - + -HasSubTask - -HasSubTask +85284b02-fc8e-4418-8d6b-7a154d2004f6 + +HasSubTask - + -Sequence*->HasSubTask - - +d78eaf31-cc9d-484d-b564-dbd5912378fa->85284b02-fc8e-4418-8d6b-7a154d2004f6 + + - + -Sequence** - -Sequence** +eb1bba56-55b1-4a71-8b31-0381812f588a + +> - + -Sequence*->Sequence** - - +d78eaf31-cc9d-484d-b564-dbd5912378fa->eb1bba56-55b1-4a71-8b31-0381812f588a + + - + -At(Robot,Table)* - -At(Robot,Table)* +3d7f6aa9-62b5-4852-ab3e-ac0199cc46a8 + +At(Robot,Table) - + -Sequence*->At(Robot,Table)* - - +d78eaf31-cc9d-484d-b564-dbd5912378fa->3d7f6aa9-62b5-4852-ab3e-ac0199cc46a8 + + - + -At(Robot,Table) - -At(Robot,Table) +20b57b46-d59d-4b04-a4ed-eff12e6adc91 + +At(Robot,Table) - + -Sequence**->At(Robot,Table) - - +eb1bba56-55b1-4a71-8b31-0381812f588a->20b57b46-d59d-4b04-a4ed-eff12e6adc91 + + diff --git a/robowaiter/llm_client/ask_llm.py b/robowaiter/llm_client/ask_llm.py index f82ce28..4644b6b 100644 --- a/robowaiter/llm_client/ask_llm.py +++ b/robowaiter/llm_client/ask_llm.py @@ -37,10 +37,7 @@ def ask_llm(question): if __name__ == '__main__': question = ''' - 以下是环境信息,请回答对话和目标状态 - [环境信息] - State: {At(Robot, Table), NotHolding, Available(SpongeGourd)} - chat_list: [(Customer, "桌子有点脏,能帮我擦一下吗?")] + python中如何通过类名字符串的方式来代替isinstance的作用 ''' print(ask_llm(question)) \ No newline at end of file diff --git a/robowaiter/robot/robot.py b/robowaiter/robot/robot.py index ef9a744..1f46560 100644 --- a/robowaiter/robot/robot.py +++ b/robowaiter/robot/robot.py @@ -1,8 +1,10 @@ import io import contextlib -from robowaiter.behavior_tree.utils import load_bt_from_ptml,find_node_by_name,print_tree_from_root -from robowaiter.behavior_tree.obtea.OptimalBTExpansionAlgorithm import Action,OptBTExpAlgorithm,state_transition # 调用最优行为树扩展算法 +from robowaiter.utils.bt.load import load_bt_from_ptml,find_node_by_name,print_tree_from_root +from robowaiter.utils.bt.visitor import StatusVisitor + +from robowaiter.behavior_tree.obtea.OptimalBTExpansionAlgorithm import Action # 调用最优行为树扩展算法 from robowaiter.behavior_tree.obtea.opt_bt_exp_main import BTOptExpInterface from robowaiter.behavior_lib.act.DelSubTree import DelSubTree @@ -22,6 +24,7 @@ class Robot(object): self.last_tick_output = "" self.action_list = None + def set_scene(self,scene): self.scene = scene @@ -32,7 +35,10 @@ class Robot(object): sub_task_seq = sub_task_place_holder.parent sub_task_seq.children.pop() self.scene.sub_task_seq = sub_task_seq - print(self.scene.sub_task_seq) + + self.bt_visitor = StatusVisitor() + self.bt.visitors.append(self.bt_visitor) + def expand_sub_task_tree(self,goal): if self.action_list is None: @@ -52,12 +58,12 @@ class Robot(object): # 加入删除子树的节点 seq = Sequence(name="Sequence", memory=False) - seq.children.append(sub_task_bt.root) + seq.add_child(sub_task_bt.root) del_sub_tree = DelSubTree() del_sub_tree.set_scene(self.scene) - seq.children.append(del_sub_tree) + seq.add_child(del_sub_tree) - self.scene.sub_task_seq.children.append(seq) + self.scene.sub_task_seq.add_child(seq) print("当前行为树为:") print_tree_from_root(self.bt.root) @@ -75,24 +81,16 @@ class Robot(object): self.next_response_time += self.response_frequency self.step_num += 1 - # 创建一个StringIO对象 - output = io.StringIO() + self.bt.tick() + bt_output = self.bt_visitor.output_str - # 将print输出重定向到StringIO对象 - with contextlib.redirect_stdout(output): - self.bt.tick() - - # 获取StringIO对象中的字符串值 - contents = output.getvalue() - output.close() - - if contents != self.last_tick_output: + if bt_output != self.last_tick_output: print(f"==== time:{self.scene.time:f}s ======") - print(contents) + print(bt_output) print("\n") - self.last_tick_output = contents + self.last_tick_output = bt_output if __name__ == '__main__': pass \ No newline at end of file diff --git a/robowaiter/scene/tasks/VLM.py b/robowaiter/scene/tasks/VLM.py index c4186fe..88cdecd 100644 --- a/robowaiter/scene/tasks/VLM.py +++ b/robowaiter/scene/tasks/VLM.py @@ -24,9 +24,10 @@ class SceneVLM(Scene): # self.move_task_area(i) # self.op_task_execute(i) - if op_type<=10: - self.move_task_area(op_type) - self.op_task_execute(op_type) - + # if op_type<=10: + # self.move_task_area(op_type) + # self.op_task_execute(op_type) + pass + def _step(self): pass diff --git a/robowaiter/utils/__init__.py b/robowaiter/utils/__init__.py new file mode 100644 index 0000000..af2a9db --- /dev/null +++ b/robowaiter/utils/__init__.py @@ -0,0 +1,5 @@ + + +from robowaiter.utils import * +from robowaiter.utils import * + diff --git a/robowaiter/utils/bt/__init__.py b/robowaiter/utils/bt/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/robowaiter/utils/bt/draw.py b/robowaiter/utils/bt/draw.py new file mode 100644 index 0000000..4ab4852 --- /dev/null +++ b/robowaiter/utils/bt/draw.py @@ -0,0 +1,331 @@ + +############################################################################## +# Imports +############################################################################## + +import os +import typing +import uuid + +import pydot +from py_trees import behaviour +from py_trees import blackboard +from py_trees import common +from py_trees import composites +from py_trees import decorators +from py_trees import utilities + +COMPOSITE_NODE_SIZE = 0.01 + + +def dot_tree( + root: behaviour.Behaviour, + visibility_level: common.VisibilityLevel = common.VisibilityLevel.DETAIL, + collapse_decorators: bool = False, + with_blackboard_variables: bool = False, + with_qualified_names: bool = False): + """ + Paint your tree on a pydot graph. + + .. seealso:: :py:func:`render_dot_tree`. + + Args: + root (:class:`~py_trees.behaviour.Behaviour`): the root of a tree, or subtree + visibility_level (optional): collapse subtrees at or under this level + collapse_decorators (optional): only show the decorator (not the child), defaults to False + with_blackboard_variables (optional): add nodes for the blackboard variables + with_qualified_names (optional): print the class information for each behaviour in each node, defaults to False + + Returns: + pydot.Dot: graph + + Examples: + + .. code-block:: python + + # convert the pydot graph to a string object + print("{}".format(py_trees.display.dot_graph(root).to_string())) + """ + + def get_node_attributes(node): + blackbox_font_colours = {common.BlackBoxLevel.DETAIL: "dodgerblue", + common.BlackBoxLevel.COMPONENT: "lawngreen", + common.BlackBoxLevel.BIG_PICTURE: "white" + } + if node.type =="Selector": + attributes = ('diamond', 'cyan', 'black') # octagon + elif node.type =="Sequence": + attributes = ('octagon', 'orange', 'black') + elif isinstance(node, composites.Parallel): + attributes = ('parallelogram', 'gold', 'black') + elif isinstance(node, decorators.Decorator): + attributes = ('ellipse', 'ghostwhite', 'black') + elif node.type =="Act": + attributes = ('box', 'lawngreen', 'black') + else: + attributes = ('ellipse', 'yellow', 'black') + + try: + if node.blackbox_level != common.BlackBoxLevel.NOT_A_BLACKBOX: + attributes = (attributes[0], 'gray20', blackbox_font_colours[node.blackbox_level]) + except AttributeError: + # it's a blackboard client, not a behaviour, just pass + pass + return attributes + + def get_node_label(node_name, behaviour): + """ + This extracts a more detailed string (when applicable) to append to + that which will be used for the node name. + """ + # Custom handling of composites provided by this library. Not currently + # providing a generic mechanism for others to customise visualisations + # for their derived composites. + # prefix = "" + # policy = "" + ''' + if isinstance(behaviour, composites.Composite): + try: + if behaviour.memory: + prefix += console.circled_m + except AttributeError: + pass + try: + if behaviour.policy.synchronise: + prefix += console.lightning_bolt + except AttributeError: + pass + try: + policy = behaviour.policy.__class__.__name__ + except AttributeError: + pass + try: + indices = [str(behaviour.children.index(child)) for child in behaviour.policy.children] + policy += "({})".format(', '.join(sorted(indices))) + except AttributeError: + pass + + node_label = f"{prefix} {node_name}" if prefix else node_name + if policy: + node_label += f"\n{str(policy)}" + if with_qualified_names: + node_label += f"\n({utilities.get_fully_qualified_name(behaviour)})" + ''' + if node_name == "Sequence": + node_name = ">" + if node_name == "Selector": + node_name = "?" + return node_name + + fontsize = 20 + blackboard_colour = "blue" # "dimgray" + graph = pydot.Dot(graph_type='digraph', ordering="out") + graph.set_name("pastafarianism") # consider making this unique to the tree sometime, e.g. based on the root name + # fonts: helvetica, times-bold, arial (times-roman is the default, but this helps some viewers, like kgraphviewer) + graph.set_graph_defaults(fontname='times-roman') # splines='curved' is buggy on 16.04, but would be nice to have + graph.set_node_defaults(fontname='times-roman') + graph.set_edge_defaults(fontname='times-roman') + (node_shape, node_colour, node_font_colour) = get_node_attributes(root) + root_name = str(root.id) + node_root = pydot.Node( + name=root_name, + label=get_node_label(root.name, root), + shape=node_shape, + style="filled", + fillcolor=node_colour, + fontsize=fontsize, + fontcolor=node_font_colour, + ) + if isinstance(root, composites.Composite): + node_root.set_height(COMPOSITE_NODE_SIZE) + node_root.set_width(COMPOSITE_NODE_SIZE) + graph.add_node(node_root) + behaviour_id_name_map = {root.id: str(root.id)} + + def add_children_and_edges(root, root_node, root_dot_name, visibility_level, collapse_decorators): + if isinstance(root, decorators.Decorator) and collapse_decorators: + return + if visibility_level < root.blackbox_level: + node_names = [] + for c in root.children: + (node_shape, node_colour, node_font_colour) = get_node_attributes(c) + node_name = str(c.id) + # while node_name in behaviour_id_name_map.values(): + # node_name += "" + behaviour_id_name_map[c.id] = node_name + # Node attributes can be found on page 5 of + # https://graphviz.gitlab.io/_pages/pdf/dot.1.pdf + # Attributes that may be useful: tooltip, xlabel + node = pydot.Node( + name=str(c.id), + label=get_node_label(c.name, c), + shape=node_shape, + style="filled", + fillcolor=node_colour, + fontsize=fontsize, + fontcolor=node_font_colour, + ) + if isinstance(c, composites.Composite): + node.set_height(COMPOSITE_NODE_SIZE) + node.set_width(COMPOSITE_NODE_SIZE) + node_names.append(node_name) + graph.add_node(node) + edge = pydot.Edge(root_dot_name, node_name) + graph.add_edge(edge) + if c.children != []: + add_children_and_edges(c, node, node_name, visibility_level, collapse_decorators) + + add_children_and_edges(root, node_root, root_name, visibility_level, collapse_decorators) + + def create_blackboard_client_node(blackboard_client_name: str): + return pydot.Node( + name=blackboard_client_name, + label=blackboard_client_name, + shape="ellipse", + style="filled", + color=blackboard_colour, + fillcolor="gray", + fontsize=fontsize - 2, + fontcolor=blackboard_colour, + ) + + def add_blackboard_nodes(blackboard_id_name_map: typing.Dict[uuid.UUID, str]): + data = blackboard.Blackboard.storage + metadata = blackboard.Blackboard.metadata + clients = blackboard.Blackboard.clients + # add client (that are not behaviour) nodes + subgraph = pydot.Subgraph( + graph_name="Blackboard", + id="Blackboard", + label="Blackboard", + rank="sink", + ) + + for unique_identifier, client_name in clients.items(): + if unique_identifier not in blackboard_id_name_map: + subgraph.add_node( + create_blackboard_client_node(client_name) + ) + # add key nodes + for key in blackboard.Blackboard.keys(): + try: + value = utilities.truncate(str(data[key]), 20) + label = key + ": " + "{}".format(value) + except KeyError: + label = key + ": " + "-" + blackboard_node = pydot.Node( + key, + label=label, + shape='box', + style="filled", + color=blackboard_colour, + fillcolor='white', + fontsize=fontsize - 1, + fontcolor=blackboard_colour, + width=0, height=0, fixedsize=False, # only big enough to fit text + ) + subgraph.add_node(blackboard_node) + for unique_identifier in metadata[key].read: + try: + edge = pydot.Edge( + blackboard_node, + blackboard_id_name_map[unique_identifier], + color="green", + constraint=False, + weight=0, + ) + except KeyError: + edge = pydot.Edge( + blackboard_node, + clients[unique_identifier].__getattribute__("name"), + color="green", + constraint=False, + weight=0, + ) + graph.add_edge(edge) + for unique_identifier in metadata[key].write: + try: + edge = pydot.Edge( + blackboard_id_name_map[unique_identifier], + blackboard_node, + color=blackboard_colour, + constraint=False, + weight=0, + ) + except KeyError: + edge = pydot.Edge( + clients[unique_identifier].__getattribute__("name"), + blackboard_node, + color=blackboard_colour, + constraint=False, + weight=0, + ) + graph.add_edge(edge) + graph.add_subgraph(subgraph) + + if with_blackboard_variables: + blackboard_id_name_map = {} + for b in root.iterate(): + for bb in b.blackboards: + blackboard_id_name_map[bb.id()] = behaviour_id_name_map[b.id] + add_blackboard_nodes(blackboard_id_name_map) + + return graph + + +def render_dot_tree(root: behaviour.Behaviour, + visibility_level: common.VisibilityLevel = common.VisibilityLevel.DETAIL, + collapse_decorators: bool = False, + name: str = None, + target_directory: str = os.getcwd(), + with_blackboard_variables: bool = False, + with_qualified_names: bool = False): + """ + Render the dot tree to .dot, .svg, .png. files in the current + working directory. These will be named with the root behaviour name. + + Args: + root: the root of a tree, or subtree + visibility_level: collapse subtrees at or under this level + collapse_decorators: only show the decorator (not the child) + name: name to use for the created files (defaults to the root behaviour name) + target_directory: default is to use the current working directory, set this to redirect elsewhere + with_blackboard_variables: add nodes for the blackboard variables + with_qualified_names: print the class names of each behaviour in the dot node + + Example: + + Render a simple tree to dot/svg/png file: + + .. graphviz:: dot/sequence.dot + + .. code-block:: python + + root = py_trees.composites.Sequence("Sequence") + for job in ["Action 1", "Action 2", "Action 3"]: + success_after_two = py_trees.behaviours.Count(name=job, + fail_until=0, + running_until=1, + success_until=10) + root.add_child(success_after_two) + py_trees.display.render_dot_tree(root) + + .. tip:: + + A good practice is to provide a command line argument for optional rendering of a program so users + can quickly visualise what tree the program will execute. + """ + graph = dot_tree( + root, visibility_level, collapse_decorators, + with_blackboard_variables=with_blackboard_variables, + with_qualified_names=with_qualified_names) + filename_wo_extension_to_convert = root.name if name is None else name + filename_wo_extension = utilities.get_valid_filename(filename_wo_extension_to_convert) + filenames = {} + for extension, writer in {"dot": graph.write, "png": graph.write_png, "svg": graph.write_svg}.items(): + filename = filename_wo_extension + '.' + extension + pathname = os.path.join(target_directory, filename) + print("Writing {}".format(pathname)) + writer(pathname) + filenames[extension] = pathname + return filenames diff --git a/robowaiter/behavior_tree/utils.py b/robowaiter/utils/bt/load.py similarity index 79% rename from robowaiter/behavior_tree/utils.py rename to robowaiter/utils/bt/load.py index 52e25df..cb7f61a 100644 --- a/robowaiter/behavior_tree/utils.py +++ b/robowaiter/utils/bt/load.py @@ -14,18 +14,6 @@ def load_bt_from_ptml(scene, ptml_path, behavior_lib_path): # print(ptree.display.unicode_tree(root=bt.root, show_status=True)) return bt -def load_bt_from_ptml_str(scene, ptml_path, behavior_lib_path): - ptml_bt = ptmlCompiler.load(scene, ptml_path, behavior_lib_path) - bt = ptree.trees.BehaviourTree(ptml_bt) - - with open(ptml_path, 'r') as f: - ptml = f.read() - - print(f'BT loaded:') - print_tree_from_root(bt.root) - # print(ptree.display.unicode_tree(root=bt.root, show_status=True)) - return bt - def print_tree_from_root(node, indent=0): """ diff --git a/robowaiter/utils/bt/visitor.py b/robowaiter/utils/bt/visitor.py new file mode 100644 index 0000000..8353ab6 --- /dev/null +++ b/robowaiter/utils/bt/visitor.py @@ -0,0 +1,30 @@ + +from py_trees.visitors import VisitorBase + + +class StatusVisitor(VisitorBase): + """ + Logging is done with the behaviour's logger. + """ + + def __init__(self) -> None: + super(StatusVisitor, self).__init__(full=False) + self.output_str = "" + + def initialise(self) -> None: + """Override if any resetting of variables needs to be performed between ticks (i.e. visitations).""" + self.output_str = "" + + + def run(self, behavior) -> None: + """ + Log behaviour information on the debug channel. + + Args: + behavior: behaviour being visited. + """ + if behavior.type in ("Sequence","Selector"): + return + else: + self.output_str += f"{behavior.print_name}: {behavior.status.value}\n" + diff --git a/run_robowaiter.py b/run_robowaiter.py index 8592471..1c11b81 100644 --- a/run_robowaiter.py +++ b/run_robowaiter.py @@ -1,7 +1,7 @@ import os from robowaiter import Robot, task_map -TASK_NAME = 'VLN' +TASK_NAME = 'VLM' # create robot project_path = "./robowaiter" diff --git a/sub_task.ptml b/sub_task.ptml index 5829971..3473e6b 100644 --- a/sub_task.ptml +++ b/sub_task.ptml @@ -1,7 +1,7 @@ selector{ -cond At(Robot,Table) +cond At(Coffee,Bar) selector{ -cond At(Robot,Bar) -act MoveTo(Table) +cond At(Robot,CoffeeMachine) +act MakeCoffee } }