diff --git a/robowaiter/behavior_lib/_base/Behavior.py b/robowaiter/behavior_lib/_base/Behavior.py index 5bfcff3..1feed88 100644 --- a/robowaiter/behavior_lib/_base/Behavior.py +++ b/robowaiter/behavior_lib/_base/Behavior.py @@ -15,24 +15,17 @@ class Bahavior(ptree.behaviour.Behaviour): scene = None print_name_prefix = "" tables_for_placement = {'Bar', 'Bar2', 'WaterTable', 'CoffeeTable', 'Table1', 'Table2', 'Table3',"BrightTable6"} - # all_object = {'Coffee', 'Water', 'Dessert', 'Softdrink', 'BottledDrink', 'Yogurt', 'ADMilk', 'MilkDrink', 'Milk', - # 'VacuumCup'} - all_object = { 'Coffee', 'Water', 'Dessert', 'Softdrink', 'BottledDrink', 'Yogurt', 'ADMilk', 'MilkDrink', 'Milk','VacuumCup', 'Chips', 'NFCJuice', 'Bernachon', 'ADMilk', 'SpringWater'} - - # BrightTable5 = Table4 tables_for_guiding = {"QuietTable1","QuietTable2", "BrightTable1","BrightTable2","BrightTable3","BrightTable4","BrightTable5","BrightTable6" 'CoffeeTable','WaterTable','Table1', 'Table2', 'Table3'} - # all_place = {'Bar', 'WaterTable', 'CoffeeTable'} - # all_object = {'Coffee', 'Water', 'Dessert', 'Softdrink', 'Yogurt'} - # all_object = {'Coffee', 'Water'} - # all_object = set() - # all_place=set() + # tables_for_placement = {'Bar', 'WaterTable', 'CoffeeTable'} + # all_object = {'Coffee', 'Water', 'Dessert', 'Softdrink', 'Yogurt'} + num_of_obj_on_place={ 'Bar': 0, # (247.0, 520.0, 100.0) diff --git a/robowaiter/behavior_lib/act/FreeHands.py b/robowaiter/behavior_lib/act/FreeHands.py index c391bc3..f3e6ca7 100644 --- a/robowaiter/behavior_lib/act/FreeHands.py +++ b/robowaiter/behavior_lib/act/FreeHands.py @@ -15,7 +15,8 @@ class FreeHands(Act): @classmethod def get_info(cls): info = {} - info["pre"]= set() + # info["pre"]= set() + info["pre"] ={f'Holding(Nothing)'} info['add'] = {f'Holding(Nothing)'} info['del_set'] = {f'Holding({obj})' for obj in cls.all_object} info['cost'] = 0 diff --git a/robowaiter/behavior_tree/obtea/BTExpansionAlgorithm.py b/robowaiter/behavior_tree/obtea/BTExpansionAlgorithm.py new file mode 100644 index 0000000..e340eda --- /dev/null +++ b/robowaiter/behavior_tree/obtea/BTExpansionAlgorithm.py @@ -0,0 +1,297 @@ +import random +import numpy as np +import copy +import time +from robowaiter.behavior_tree.obtea.BehaviorTree import Leaf,ControlBT +from robowaiter.behavior_tree.obtea.OptimalBTExpansionAlgorithm import Action,generate_random_state,state_transition,conflict + + + +# 本文所提出的完备规划算法 +class BTalgorithm: + def __init__(self,verbose=False): + self.bt = None + self.nodes = [] + self.traversed = [] + self.conditions = [] + self.conditions_index = [] + self.verbose = verbose + # print (self.conditions_list[0]) + + def clear(self): + self.bt = None + self.nodes = [] + self.traversed = [] + self.conditions = [] + self.conditions_index = [] + + # 运行规划算法,从初始状态、目标状态和可用行动,计算行为树self.bt + def run_algorithm(self, start, goal, actions): + # 初始行为树只包含目标条件 + self.bt = ControlBT(type='cond') + g_node = Leaf(type='cond', content=goal,mincost=0) + self.bt.add_child([g_node]) + + self.conditions.append(goal) + self.nodes.append(g_node) # condition node list + # 尝试在初始状态执行行为树 + val, obj = self.bt.tick(start) + canrun = False + if val == 'success' or val == 'running': + canrun = True + # 循环扩展,直到行为树能够在初始状态运行 + while not canrun: + index = -1 + for i in range(0, len(self.nodes)): + if self.nodes[i].content in self.traversed: + continue + else: + c_node = self.nodes[i] + index = i + break + if index == -1: # 树中结点扩展完毕,仍无法运行行为树,返回失败 + print('Failure') + return False + # 根据所选择条件结点扩展子树 + subtree = ControlBT(type='?') + subtree.add_child([copy.deepcopy(c_node)]) # 子树首先保留所扩展结点 + c = c_node.content # 子树所扩展结点对应的条件(一个文字的set) + + for i in range(0, len(actions)): # 选择符合条件的行动, + # print("have action") + if not c & ((actions[i].pre | actions[i].add) - actions[i].del_set) <= set(): + # print ("pass add") + if (c - actions[i].del_set) == c: + # print("pass delete") + c_attr = (actions[i].pre | c) - actions[i].add + valid = True + + # 这样剪枝存在错误性 + if conflict(c_attr): + continue + + for j in self.traversed: # 剪枝操作 + if j <= c_attr: + valid = False + break + + if valid: + # print("pass prune") + # 构建行动的顺序结构 + sequence_structure = ControlBT(type='>') + c_attr_node = Leaf(type='cond', content=c_attr, mincost=0) + a_node = Leaf(type='act', content=actions[i], mincost=0) + sequence_structure.add_child([c_attr_node, a_node]) + # 将顺序结构添加到子树 + subtree.add_child([sequence_structure]) + + self.nodes.append(c_attr_node) + # 将原条件结点c_node替换为扩展后子树subtree + parent_of_c = c_node.parent + parent_of_c.children[0] = subtree + # 记录已扩展条件 + self.traversed.append(c) + # 尝试在初始状态运行行为树 + val, obj = self.bt.tick(start) + canrun = False + if val == 'success' or val == 'running': + canrun = True + return True + + def print_solution(self): + print(len(self.nodes)) + # for i in self.nodes: + # if isinstance(i,Node): + # print (i.content) + # else: + # print (i) + + # 树的dfs + def dfs_ptml(self,parnode,is_root=False): + for child in parnode.children: + if isinstance(child, Leaf): + if child.type == 'cond': + + if is_root and len(child.content) > 1: + # 把多个 cond 串起来 + self.ptml_string += "sequence{\n" + self.ptml_string += "cond " + c_set_str = '\n cond '.join(map(str, child.content)) + "\n" + self.ptml_string += c_set_str + self.ptml_string += '}\n' + else: + self.ptml_string += "cond " + c_set_str = '\n cond '.join(map(str, child.content)) + "\n" + self.ptml_string += c_set_str + + elif child.type == 'act': + if '(' not in child.content.name: + self.ptml_string += 'act ' + child.content.name + "()\n" + else: + self.ptml_string += 'act ' + child.content.name + "\n" + elif isinstance(child, ControlBT): + if child.type == '?': + self.ptml_string += "selector{\n" + self.dfs_ptml(parnode=child) + elif child.type == '>': + self.ptml_string += "sequence{\n" + self.dfs_ptml( parnode=child) + self.ptml_string += '}\n' + + + def get_ptml(self): + self.ptml_string = "selector{\n" + self.dfs_ptml(self.bt.children[0],is_root=True) + self.ptml_string += '}\n' + return self.ptml_string + + + def save_ptml_file(self,file_name): + self.ptml_string = "selector{\n" + self.dfs_ptml(self.bt.children[0]) + self.ptml_string += '}\n' + with open(f'./{file_name}.ptml', 'w') as file: + file.write(self.ptml_string) + return self.ptml_string + + +# 所对比的基准算法,具体扩展细节有差异 + + + +if __name__ == '__main__': + random.seed(1) + # 设置生成规划问题集的超参数:文字数、解深度、迭代次数 + literals_num = 10 + depth = 10 + iters = 10 + total_tree_size = [] + total_action_num = [] + total_state_num = [] + total_steps_num = [] + # fail_count=0 + # danger_count=0 + success_count = 0 + failure_count = 0 + planning_time_total = 0.0 + # 实验1000次 + for count in range(0, 1000): + # 生成一个规划问题,包括随机的状态和行动,以及目标状态 + states = [] + actions = [] + start = generate_random_state(literals_num) + state = start + states.append(state) + # print (state) + for i in range(0, depth): + a = Action() + a.generate_from_state(state, literals_num) + if not a in actions: + actions.append(a) + state = state_transition(state, a) + if state in states: + pass + else: + states.append(state) + # print(state) + + goal = states[-1] + state = start + for i in range(0, iters): + a = Action() + a.generate_from_state(state, literals_num) + if not a in actions: + actions.append(a) + state = state_transition(state, a) + if state in states: + pass + else: + states.append(state) + state = random.sample(states, 1)[0] + # 选择测试本文算法btalgorithm,或对比算法weakalgorithm + algo = BTalgorithm() + # algo = Weakalgorithm() + start_time = time.time() + if algo.run_algorithm(start, goal, list(actions)): # 运行算法,规划后行为树为algo.bt + total_tree_size.append(algo.bt.count_size() - 1) + else: + print("error") + end_time = time.time() + planning_time_total += (end_time - start_time) + + # 开始从初始状态运行行为树,测试 + state = start + steps = 0 + val, obj = algo.bt.tick(state) # tick行为树,obj为所运行的行动 + while val != 'success' and val != 'failure': # 运行直到行为树成功或失败 + state = state_transition(state, obj) + val, obj = algo.bt.tick(state) + if (val == 'failure'): + print("bt fails at step", steps) + steps += 1 + if (steps >= 500): # 至多运行500步 + break + if not goal <= state: # 错误解,目标条件不在执行后状态满足 + # print ("wrong solution",steps) + failure_count += 1 + + else: # 正确解,满足目标条件 + # print ("right solution",steps) + success_count += 1 + total_steps_num.append(steps) + algo.clear() + total_action_num.append(len(actions)) + total_state_num.append(len(states)) + print(success_count, failure_count) # 算法成功和失败次数 + + print(np.mean(total_tree_size), np.std(total_tree_size, ddof=1)) # 1000次测试树大小 + print(np.mean(total_steps_num), np.std(total_steps_num, ddof=1)) + print(np.mean(total_state_num)) # 1000次问题的平均状态数 + print(np.mean(total_action_num)) # 1000次问题的平均行动数 + print(planning_time_total, planning_time_total / 1000.0) + + # print(total_state_num) + + # casestudy begin 对应论文的case study,包含三个行动的移动机械臂场景 + + actions = [] + a = Action(name='movebtob') + a.pre = {1, 2} + a.add = {3} + a.del_set = {1, 4} + actions.append(a) + a = Action(name='moveatob') + a.pre = {1} + a.add = {5, 2} + a.del_set = {1, 6} + actions.append(a) + a = Action(name='moveatoa') + a.pre = {7} + a.add = {8, 2} + a.del_set = {7, 6} + actions.append(a) + + start = {1, 7, 4, 6} + goal = {3} + algo = BTalgorithm() + algo.clear() + algo.run_algorithm(start, goal, list(actions)) + state = start + steps = 0 + val, obj = algo.bt.tick(state) + while val != 'success' and val != 'failure': + state = state_transition(state, obj) + print(obj.name) + val, obj = algo.bt.tick(state) + if (val == 'failure'): + print("bt fails at step", steps) + steps += 1 + if not goal <= state: + print("wrong solution", steps) + else: + print("right solution", steps) + # algo.bt.print_nodes() + print(algo.bt.count_size() - 1) + algo.clear() + +# case study end diff --git a/robowaiter/behavior_tree/obtea/OptimalBTExpansionAlgorithm.py b/robowaiter/behavior_tree/obtea/OptimalBTExpansionAlgorithm.py index f23a6d6..b883fcd 100644 --- a/robowaiter/behavior_tree/obtea/OptimalBTExpansionAlgorithm.py +++ b/robowaiter/behavior_tree/obtea/OptimalBTExpansionAlgorithm.py @@ -20,6 +20,24 @@ class Action: def __str__(self): return self.name + # 从状态随机生成一个行动 + def generate_from_state(self,state,num): + for i in range(0,num): + if i in state: + if random.random() >0.5: + self.pre.add(i) + if random.random() >0.5: + self.del_set.add(i) + continue + if random.random() > 0.5: + self.add.add(i) + continue + if random.random() >0.5: + self.del_set.add(i) + def print_action(self): + print (self.pre) + print(self.add) + print(self.del_set) #生成随机状态 def generate_random_state(num): @@ -68,9 +86,9 @@ class OptBTExpAlgorithm: self.conditions_index = [] #运行规划算法,从初始状态、目标状态和可用行动,计算行为树self.bt - def run_algorithm(self,goal,actions,scene): - - self.scene = scene + # def run_algorithm(self,goal,actions,scene): + def run_algorithm(self, start, goal, actions): + # self.scene = scene if self.verbose: print("\n算法开始!") @@ -113,7 +131,6 @@ class OptBTExpAlgorithm: min_cost = cond_anc_pair.cond_leaf.mincost pair_node = copy.deepcopy(cond_anc_pair) index = i - break if self.verbose: print("选择扩展条件结点:",pair_node.cond_leaf.content) @@ -141,7 +158,8 @@ class OptBTExpAlgorithm: subtree.add_child([copy.deepcopy(sequence_structure)]) # subtree 是回不断变化的,它的父亲是self.bt self.expanded.append(copy.deepcopy(pair_node)) # 增加实时条件判断,满足条件就不再扩展 - if c <= self.scene.state["condition_set"]: + # if c <= self.scene.state["condition_set"]: + if c <= start: return True else: subtree.add_child([copy.deepcopy(pair_node.act_leaf)]) @@ -158,6 +176,11 @@ class OptBTExpAlgorithm: current_mincost = pair_node.cond_leaf.mincost # 当前的最短路径是多少 for i in range(0, len(actions)): + + + if actions[i].name == 'FreeHands()': + kk=1 + if not c & ((actions[i].pre | actions[i].add) - actions[i].del_set) <= set(): if (c - actions[i].del_set) == c: if self.verbose: diff --git a/robowaiter/behavior_tree/obtea/opt_bt_exp_main.py b/robowaiter/behavior_tree/obtea/opt_bt_exp_main.py index 9a7829f..112d144 100644 --- a/robowaiter/behavior_tree/obtea/opt_bt_exp_main.py +++ b/robowaiter/behavior_tree/obtea/opt_bt_exp_main.py @@ -1,5 +1,6 @@ from robowaiter.behavior_tree.obtea.OptimalBTExpansionAlgorithm import Action,OptBTExpAlgorithm,state_transition # 调用最优行为树扩展算法 +from robowaiter.behavior_tree.obtea.BTExpansionAlgorithm import BTalgorithm # 调用最优行为树扩展算法 from robowaiter.behavior_tree.obtea.examples import * @@ -23,6 +24,8 @@ class BTOptExpInterface: self.has_processed = False self.scene = scene + self.bt_algo_opt = self.scene.bt_algo_opt + def process(self, goal): """ @@ -31,9 +34,15 @@ class BTOptExpInterface: :return: A PTML string representing the outcome of the behavior tree. """ self.goal = goal - self.algo = OptBTExpAlgorithm(verbose=False) + if self.bt_algo_opt: + self.algo = OptBTExpAlgorithm(verbose=False) + else: + self.algo = BTalgorithm(verbose=False) + self.algo.clear() - self.algo.run_algorithm(self.goal, self.actions,self.scene) # 调用算法得到行为树保存至 algo.bt + self.algo.run_algorithm(self.scene.state["condition_set"],self.goal, self.actions) # 调用算法得到行为树保存至 algo.bt + + self.ptml_string = self.algo.get_ptml() self.has_processed = True # algo.print_solution() # print behavior tree diff --git a/robowaiter/llm_client/data/fix_questions.txt b/robowaiter/llm_client/data/fix_questions.txt index 701f909..077a7b1 100644 --- a/robowaiter/llm_client/data/fix_questions.txt +++ b/robowaiter/llm_client/data/fix_questions.txt @@ -222,12 +222,6 @@ get_object_info 好的,我明白了,那么我们推荐您到大厅的桌子,那里的空间比较宽敞,环境也比较明亮,适合带着孩子一起用餐。 -冰红茶 -好的 -create_sub_task -{"goal":"On(Yogurt,WaterTable)"} - - 水杯 好的 create_sub_task @@ -258,4 +252,9 @@ create_sub_task 点心 好的 create_sub_task -{"goal":"On(Dessert,Bar)"} \ No newline at end of file +{"goal":"On(Dessert,Bar)"} + +打开空调并降低空调温度 +好的,没问题 +create_sub_task +{"goal":"Is(ACTemperature,Down)"} \ No newline at end of file diff --git a/robowaiter/robot/robot.py b/robowaiter/robot/robot.py index f9ed11d..7d85300 100644 --- a/robowaiter/robot/robot.py +++ b/robowaiter/robot/robot.py @@ -19,7 +19,7 @@ root_path = get_root_path() ptml_path = os.path.join(root_path, 'robowaiter/robot/Default.ptml') behavior_lib_path = os.path.join(root_path, 'robowaiter/behavior_lib') - +from robowaiter.utils.bt.draw import render_dot_tree class Robot(object): scene = None @@ -79,6 +79,7 @@ class Robot(object): file.write(ptml_string) sub_task_bt = load_bt_from_ptml(self.scene, file_path,self.behavior_lib_path) + render_dot_tree(sub_task_bt.root, target_directory=self.scene.output_path, name="expanded_bt", png_only=False) # 加入删除子树的节点 seq = Sequence(name="Sequence", memory=False) diff --git a/robowaiter/scene/outputs/expanded_bt.dot b/robowaiter/scene/outputs/expanded_bt.dot new file mode 100644 index 0000000..dc21bbf --- /dev/null +++ b/robowaiter/scene/outputs/expanded_bt.dot @@ -0,0 +1,37 @@ +digraph pastafarianism { +ordering=out; +graph [fontname="times-roman"]; +node [fontname="times-roman"]; +edge [fontname="times-roman"]; +"87355232-8ad6-484e-b363-38536e737846" [fillcolor=cyan, fontcolor=black, fontsize=20, height=0.01, label=Selector, shape=diamond, style=filled, width=0.01]; +"3f017683-7aa3-40d3-b2be-cc32784313a1" [fillcolor=yellow, fontcolor=black, fontsize=20, label="Is(ACTemperature,Down)", shape=ellipse, style=filled]; +"87355232-8ad6-484e-b363-38536e737846" -> "3f017683-7aa3-40d3-b2be-cc32784313a1"; +"b900e9cb-c0a8-4e8d-8a9b-d871012abefb" [fillcolor=orange, fontcolor=black, fontsize=20, height=0.01, label=Sequence, shape=octagon, style=filled, width=0.01]; +"87355232-8ad6-484e-b363-38536e737846" -> "b900e9cb-c0a8-4e8d-8a9b-d871012abefb"; +"10ef3ff4-7acb-4991-9e63-6e489c3ef22d" [fillcolor=yellow, fontcolor=black, fontsize=20, label="Holding(Nothing)", shape=ellipse, style=filled]; +"b900e9cb-c0a8-4e8d-8a9b-d871012abefb" -> "10ef3ff4-7acb-4991-9e63-6e489c3ef22d"; +"a3869371-404d-4085-932b-232e188fb133" [fillcolor=yellow, fontcolor=black, fontsize=20, label="Is(AC,On)", shape=ellipse, style=filled]; +"b900e9cb-c0a8-4e8d-8a9b-d871012abefb" -> "a3869371-404d-4085-932b-232e188fb133"; +"3a5cbe8f-7672-4a34-91d1-87502aed457c" [fillcolor=lawngreen, fontcolor=black, fontsize=20, label="Turn(ACTemperature,Down)", shape=box, style=filled]; +"b900e9cb-c0a8-4e8d-8a9b-d871012abefb" -> "3a5cbe8f-7672-4a34-91d1-87502aed457c"; +"b64db1a4-d79f-47b4-99db-f184b38d1361" [fillcolor=orange, fontcolor=black, fontsize=20, height=0.01, label=Sequence, shape=octagon, style=filled, width=0.01]; +"87355232-8ad6-484e-b363-38536e737846" -> "b64db1a4-d79f-47b4-99db-f184b38d1361"; +"c6eca6dd-9fca-4bd3-b054-9b43fe02613a" [fillcolor=yellow, fontcolor=black, fontsize=20, label="Is(AC,On)", shape=ellipse, style=filled]; +"b64db1a4-d79f-47b4-99db-f184b38d1361" -> "c6eca6dd-9fca-4bd3-b054-9b43fe02613a"; +"df04f6f4-d471-4519-ab9e-5d5bd8dfbd4c" [fillcolor=lawngreen, fontcolor=black, fontsize=20, label="FreeHands()", shape=box, style=filled]; +"b64db1a4-d79f-47b4-99db-f184b38d1361" -> "df04f6f4-d471-4519-ab9e-5d5bd8dfbd4c"; +"8108bcba-dbeb-4784-8f1f-eb9ede4ffb0e" [fillcolor=orange, fontcolor=black, fontsize=20, height=0.01, label=Sequence, shape=octagon, style=filled, width=0.01]; +"87355232-8ad6-484e-b363-38536e737846" -> "8108bcba-dbeb-4784-8f1f-eb9ede4ffb0e"; +"82a23405-c3c6-47dc-bf7b-0636e3efe52c" [fillcolor=yellow, fontcolor=black, fontsize=20, label="Holding(Nothing)", shape=ellipse, style=filled]; +"8108bcba-dbeb-4784-8f1f-eb9ede4ffb0e" -> "82a23405-c3c6-47dc-bf7b-0636e3efe52c"; +"010d42ee-18b3-4a0e-9be1-eab67afaca60" [fillcolor=yellow, fontcolor=black, fontsize=20, label="Is(AC,Off)", shape=ellipse, style=filled]; +"8108bcba-dbeb-4784-8f1f-eb9ede4ffb0e" -> "010d42ee-18b3-4a0e-9be1-eab67afaca60"; +"90cdf2ff-98b0-4454-803b-feee5f5475bf" [fillcolor=lawngreen, fontcolor=black, fontsize=20, label="Turn(AC,On)", shape=box, style=filled]; +"8108bcba-dbeb-4784-8f1f-eb9ede4ffb0e" -> "90cdf2ff-98b0-4454-803b-feee5f5475bf"; +"e65ce322-edaa-4677-ab68-4795e57648da" [fillcolor=orange, fontcolor=black, fontsize=20, height=0.01, label=Sequence, shape=octagon, style=filled, width=0.01]; +"87355232-8ad6-484e-b363-38536e737846" -> "e65ce322-edaa-4677-ab68-4795e57648da"; +"7d0c1403-c5d9-4bcd-a0db-f3e527a3be93" [fillcolor=yellow, fontcolor=black, fontsize=20, label="Is(AC,Off)", shape=ellipse, style=filled]; +"e65ce322-edaa-4677-ab68-4795e57648da" -> "7d0c1403-c5d9-4bcd-a0db-f3e527a3be93"; +"931d4ea6-c661-4ea8-9016-2d4e17d30b19" [fillcolor=lawngreen, fontcolor=black, fontsize=20, label="FreeHands()", shape=box, style=filled]; +"e65ce322-edaa-4677-ab68-4795e57648da" -> "931d4ea6-c661-4ea8-9016-2d4e17d30b19"; +} diff --git a/robowaiter/scene/outputs/expanded_bt.png b/robowaiter/scene/outputs/expanded_bt.png new file mode 100644 index 0000000..256e26c Binary files /dev/null and b/robowaiter/scene/outputs/expanded_bt.png differ diff --git a/robowaiter/scene/outputs/expanded_bt.svg b/robowaiter/scene/outputs/expanded_bt.svg new file mode 100644 index 0000000..8242020 --- /dev/null +++ b/robowaiter/scene/outputs/expanded_bt.svg @@ -0,0 +1,199 @@ + + + + + + +pastafarianism + + + +87355232-8ad6-484e-b363-38536e737846 + +Selector + + + +3f017683-7aa3-40d3-b2be-cc32784313a1 + +Is(ACTemperature,Down) + + + +87355232-8ad6-484e-b363-38536e737846->3f017683-7aa3-40d3-b2be-cc32784313a1 + + + + + +b900e9cb-c0a8-4e8d-8a9b-d871012abefb + +Sequence + + + +87355232-8ad6-484e-b363-38536e737846->b900e9cb-c0a8-4e8d-8a9b-d871012abefb + + + + + +b64db1a4-d79f-47b4-99db-f184b38d1361 + +Sequence + + + +87355232-8ad6-484e-b363-38536e737846->b64db1a4-d79f-47b4-99db-f184b38d1361 + + + + + +8108bcba-dbeb-4784-8f1f-eb9ede4ffb0e + +Sequence + + + +87355232-8ad6-484e-b363-38536e737846->8108bcba-dbeb-4784-8f1f-eb9ede4ffb0e + + + + + +e65ce322-edaa-4677-ab68-4795e57648da + +Sequence + + + +87355232-8ad6-484e-b363-38536e737846->e65ce322-edaa-4677-ab68-4795e57648da + + + + + +10ef3ff4-7acb-4991-9e63-6e489c3ef22d + +Holding(Nothing) + + + +b900e9cb-c0a8-4e8d-8a9b-d871012abefb->10ef3ff4-7acb-4991-9e63-6e489c3ef22d + + + + + +a3869371-404d-4085-932b-232e188fb133 + +Is(AC,On) + + + +b900e9cb-c0a8-4e8d-8a9b-d871012abefb->a3869371-404d-4085-932b-232e188fb133 + + + + + +3a5cbe8f-7672-4a34-91d1-87502aed457c + +Turn(ACTemperature,Down) + + + +b900e9cb-c0a8-4e8d-8a9b-d871012abefb->3a5cbe8f-7672-4a34-91d1-87502aed457c + + + + + +c6eca6dd-9fca-4bd3-b054-9b43fe02613a + +Is(AC,On) + + + +b64db1a4-d79f-47b4-99db-f184b38d1361->c6eca6dd-9fca-4bd3-b054-9b43fe02613a + + + + + +df04f6f4-d471-4519-ab9e-5d5bd8dfbd4c + +FreeHands() + + + +b64db1a4-d79f-47b4-99db-f184b38d1361->df04f6f4-d471-4519-ab9e-5d5bd8dfbd4c + + + + + +82a23405-c3c6-47dc-bf7b-0636e3efe52c + +Holding(Nothing) + + + +8108bcba-dbeb-4784-8f1f-eb9ede4ffb0e->82a23405-c3c6-47dc-bf7b-0636e3efe52c + + + + + +010d42ee-18b3-4a0e-9be1-eab67afaca60 + +Is(AC,Off) + + + +8108bcba-dbeb-4784-8f1f-eb9ede4ffb0e->010d42ee-18b3-4a0e-9be1-eab67afaca60 + + + + + +90cdf2ff-98b0-4454-803b-feee5f5475bf + +Turn(AC,On) + + + +8108bcba-dbeb-4784-8f1f-eb9ede4ffb0e->90cdf2ff-98b0-4454-803b-feee5f5475bf + + + + + +7d0c1403-c5d9-4bcd-a0db-f3e527a3be93 + +Is(AC,Off) + + + +e65ce322-edaa-4677-ab68-4795e57648da->7d0c1403-c5d9-4bcd-a0db-f3e527a3be93 + + + + + +931d4ea6-c661-4ea8-9016-2d4e17d30b19 + +FreeHands() + + + +e65ce322-edaa-4677-ab68-4795e57648da->931d4ea6-c661-4ea8-9016-2d4e17d30b19 + + + + + diff --git a/robowaiter/scene/scene.py b/robowaiter/scene/scene.py index f3af272..da6c5b2 100644 --- a/robowaiter/scene/scene.py +++ b/robowaiter/scene/scene.py @@ -215,12 +215,14 @@ class Scene: "sub_goal_list": [], # 子目标列表 "status": None, # 仿真器中的观测信息,见下方详细解释 "condition_set": {'At(Robot,Bar)', 'Is(AC,Off)', - 'Holding(Nothing)', 'Exist(Yogurt)', 'Exist(BottledDrink)', - 'Exist(Softdrink)', + 'Exist(Yogurt)', 'Exist(BottledDrink)','Exist(Softdrink)', # 'On(Yogurt,Bar)','On(BottledDrink,Bar)', # 'Exist(Softdrink)', 'On(Softdrink,Table1)', 'Exist(Chips)', 'Exist(NFCJuice)', 'Exist(Bernachon)', 'Exist(ADMilk)', 'Exist(SpringWater)', - + + # 'Holding(Nothing)', + 'Holding(Coffee)', + 'Exist(VacuumCup)', 'On(VacuumCup,Table2)', 'Is(HallLight,Off)', 'Is(TubeLight,On)', 'Is(Curtain,On)', 'Is(Table1,Dirty)', 'Is(Floor,Dirty)', 'Is(Chairs,Dirty)'}, @@ -264,7 +266,7 @@ class Scene: # 是否展示UI self.show_ui = False # 图像分割 - self.take_picture = True + self.take_picture = False self.map_ratio = 5 self.map_map = np.zeros((math.ceil(950 / self.map_ratio), math.ceil(1850 / self.map_ratio))) self.db = DBSCAN(eps=self.map_ratio, min_samples=int(self.map_ratio / 2)) @@ -272,6 +274,8 @@ class Scene: self.is_nav_walk = False + self.bt_algo_opt = True + file_name = os.path.join(root_path,'robowaiter/algos/navigator/map_5.pkl') if os.path.exists(file_name): with open(file_name, 'rb') as file: @@ -451,6 +455,7 @@ class Scene: print(f'event: {t}, {func.__name__}') self.signal_event_list.pop(0) self.last_event_time = self.time + print("==== *args ======:",*args) func(*args) def deal_event(self): @@ -474,6 +479,7 @@ class Scene: def set_goal(self, goal): g = eval("{'" + goal + "'}") + print("====== g =======:",g) def set_sub_task(): self.state['chat_list'].append(("Goal", g)) diff --git a/tasks_no_ui/BtTest/Open_tasks.py b/tasks_no_ui/BtTest/Open_tasks.py new file mode 100644 index 0000000..4b5bdb2 --- /dev/null +++ b/tasks_no_ui/BtTest/Open_tasks.py @@ -0,0 +1,48 @@ +""" +人提出请求,机器人完成任务 +1. 做咖啡(固定动画):接收到做咖啡指令、走到咖啡机、拿杯子、操作咖啡机、取杯子、送到客人桌子上 +2. 倒水 +3. 夹点心 + +具体描述:设计一套点单规则(如菜单包含咖啡、水、点心等),按照规则拟造随机的订单。在收到订单后,通过大模型让机器人输出合理的备餐计划,并尝试在模拟环境中按照这个规划实现任务。 + +""" +import time + +# todo: 接收点单信息,大模型生成任务规划 + +from robowaiter.scene.scene import Scene + +class SceneOT(Scene): + + def __init__(self, robot): + super().__init__(robot) + # 在这里加入场景中发生的事件 + # self.event_list = [ + # # (3, self.set_goal("On(VacuumCup,Bar)")) + # (3, self.set_goal("On(Yogurt,Bar)")) + # ] + self.signal_event_list =[ + # (3, self.set_goal,("On(Yogurt,Bar)",)), + # (3, self.customer_say, ("System", "把盒装冰红茶放到水桌")), + (3, self.customer_say, ("System", "打开空调并降低空调温度")), + ] + + def _reset(self): + scene = self.add_walkers([[0, 0], [250, 1200], [-55, 750], [70, -200]]) + pass + + def _run(self): + pass + + +if __name__ == '__main__': + import os + from robowaiter.robot.robot import Robot + + robot = Robot() + + # create task + task = SceneOT(robot) + task.reset() + task.run()