增加顾客记忆
This commit is contained in:
parent
da4ed7280e
commit
935c359317
|
@ -83,6 +83,7 @@ class Bahavior(ptree.behaviour.Behaviour):
|
||||||
# let behavior node interact with the scene
|
# let behavior node interact with the scene
|
||||||
def set_scene(self, scene):
|
def set_scene(self, scene):
|
||||||
self.scene = scene
|
self.scene = scene
|
||||||
|
self.robot = scene.robot
|
||||||
|
|
||||||
def setup(self, **kwargs: Any) -> None:
|
def setup(self, **kwargs: Any) -> None:
|
||||||
return super().setup(**kwargs)
|
return super().setup(**kwargs)
|
||||||
|
|
|
@ -10,6 +10,9 @@ class DealChat(Act):
|
||||||
|
|
||||||
def _update(self) -> ptree.common.Status:
|
def _update(self) -> ptree.common.Status:
|
||||||
# if self.scene.status?
|
# if self.scene.status?
|
||||||
|
name,sentence = self.scene.state['chat_list'][0]
|
||||||
|
|
||||||
|
|
||||||
chat = self.scene.state['chat_list'].pop()
|
chat = self.scene.state['chat_list'].pop()
|
||||||
if isinstance(chat,set):
|
if isinstance(chat,set):
|
||||||
self.create_sub_task(chat)
|
self.create_sub_task(chat)
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
import py_trees as ptree
|
||||||
|
from robowaiter.behavior_lib._base.Act import Act
|
||||||
|
from robowaiter.algos.navigator.navigate import Navigator
|
||||||
|
|
||||||
|
class GreetCustomer(Act):
|
||||||
|
can_be_expanded = True
|
||||||
|
num_args = 0
|
||||||
|
valid_args = ()
|
||||||
|
|
||||||
|
def __init__(self, *args):
|
||||||
|
super().__init__(*args)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_info(cls):
|
||||||
|
info = {}
|
||||||
|
info['pre'] = set()
|
||||||
|
info["add"] = set()
|
||||||
|
info["del_set"] = set()
|
||||||
|
info['cost']=0
|
||||||
|
return info
|
||||||
|
|
||||||
|
def _update(self) -> ptree.common.Status:
|
||||||
|
|
||||||
|
goal = Act.place_xyz_dic['Bar']
|
||||||
|
self.scene.walk_to(goal[0]-5,goal[1], 180, 180, 0)
|
||||||
|
self.scene.chat_bubble("欢迎光临!请问有什么可以帮您?")
|
||||||
|
|
||||||
|
customer_name = self.scene.state['attention']['customer']
|
||||||
|
self.scene.state['greeted_customers'].add(customer_name)
|
||||||
|
|
||||||
|
return ptree.common.Status.RUNNING
|
|
@ -2,7 +2,7 @@ import py_trees as ptree
|
||||||
from robowaiter.behavior_lib._base.Act import Act
|
from robowaiter.behavior_lib._base.Act import Act
|
||||||
from robowaiter.algos.navigator.navigate import Navigator
|
from robowaiter.algos.navigator.navigate import Navigator
|
||||||
|
|
||||||
class GreatCustomer(Act):
|
class ServeCustomer(Act):
|
||||||
can_be_expanded = False
|
can_be_expanded = False
|
||||||
num_args = 0
|
num_args = 0
|
||||||
valid_args = ()
|
valid_args = ()
|
||||||
|
@ -14,7 +14,7 @@ class GreatCustomer(Act):
|
||||||
def get_info(cls):
|
def get_info(cls):
|
||||||
info = {}
|
info = {}
|
||||||
info['pre'] = set()
|
info['pre'] = set()
|
||||||
info["add"] = set()
|
info["add"] = {"CustomerServed()"}
|
||||||
info["del_set"] = set()
|
info["del_set"] = set()
|
||||||
info['cost']=0
|
info['cost']=0
|
||||||
return info
|
return info
|
|
@ -0,0 +1,24 @@
|
||||||
|
import py_trees as ptree
|
||||||
|
from typing import Any
|
||||||
|
from robowaiter.behavior_lib._base.Cond import Cond
|
||||||
|
import itertools
|
||||||
|
|
||||||
|
class CustomerServed(Cond):
|
||||||
|
can_be_expanded = True
|
||||||
|
|
||||||
|
def __init__(self,*args):
|
||||||
|
super().__init__(*args)
|
||||||
|
|
||||||
|
|
||||||
|
def _update(self) -> ptree.common.Status:
|
||||||
|
# if self.scene.status?
|
||||||
|
|
||||||
|
if self.name in self.scene.state["condition_set"]:
|
||||||
|
return ptree.common.Status.SUCCESS
|
||||||
|
else:
|
||||||
|
return ptree.common.Status.FAILURE
|
||||||
|
|
||||||
|
# if self.scene.state['chat_list'] == []:
|
||||||
|
# return ptree.common.Status.FAILURE
|
||||||
|
# else:
|
||||||
|
# return ptree.common.Status.SUCCESS
|
|
@ -18,14 +18,21 @@ class DetectCustomer(Cond):
|
||||||
# bar (247.0, 520.0, 100.0)
|
# bar (247.0, 520.0, 100.0)
|
||||||
close_to_bar = False
|
close_to_bar = False
|
||||||
scene = self.scene.status
|
scene = self.scene.status
|
||||||
|
queue_list = []
|
||||||
for walker in scene.walkers:
|
for walker in scene.walkers:
|
||||||
x, y, yaw = walker.pose.X, walker.pose.Y, walker.pose.Yaw
|
x, y, yaw = walker.pose.X, walker.pose.Y, walker.pose.Yaw
|
||||||
# 到达一定区域就打招呼
|
# 到达一定区域就打招呼
|
||||||
if y >= 450 and y <= 620 and x >= 40 and x <= 100 and yaw>=-10 and yaw <=10:
|
if y >= 450 and y <= 620 and x >= 40 and x <= 100 and yaw>=-10 and yaw <=10:
|
||||||
close_to_bar = True
|
# close_to_bar = True
|
||||||
break
|
queue_list.append((x,y,walker.name))
|
||||||
|
|
||||||
if close_to_bar:
|
if queue_list == []:
|
||||||
|
return ptree.common.Status.FAILURE
|
||||||
|
|
||||||
|
queue_list.sort()
|
||||||
|
x,y,name = queue_list[0]
|
||||||
|
if name not in self.scene.state["greet_set"]:
|
||||||
|
self.scene.state['attention']["customer"] = name
|
||||||
return ptree.common.Status.SUCCESS
|
return ptree.common.Status.SUCCESS
|
||||||
else:
|
else:
|
||||||
return ptree.common.Status.FAILURE
|
return ptree.common.Status.FAILURE
|
|
@ -36,7 +36,7 @@ if __name__ == "__main__":
|
||||||
question = input("\n顾客:")
|
question = input("\n顾客:")
|
||||||
data_memory = [{
|
data_memory = [{
|
||||||
"role": "system",
|
"role": "system",
|
||||||
"content": "你是RoboWaiter,一个由HPCL团队开发的机器人服务员,你在咖啡厅工作。接受顾客的指令并调用工具函数来完成各种服务任务。",
|
"content": "你是RoboWaiter,一个由HPCL团队开发的机器人服务员,你在咖啡厅工作。接受顾客的指令并调用工具函数来完成各种服务任务。如果顾客问你们这里有什么,或者想要点单,你说我们咖啡厅提供咖啡,水,点心,酸奶等食物。如果顾客不需要你了,你就回到吧台招待。",
|
||||||
},]
|
},]
|
||||||
n = 1
|
n = 1
|
||||||
max_retry = 5
|
max_retry = 5
|
||||||
|
|
|
@ -49,6 +49,7 @@ def show_image(camera_data):
|
||||||
class Scene:
|
class Scene:
|
||||||
robot = None
|
robot = None
|
||||||
event_list = []
|
event_list = []
|
||||||
|
new_event_list = []
|
||||||
show_bubble = False
|
show_bubble = False
|
||||||
|
|
||||||
default_state = {
|
default_state = {
|
||||||
|
@ -62,7 +63,12 @@ class Scene:
|
||||||
"condition_set": {'At(Robot,Bar)', 'Is(AC,Off)',
|
"condition_set": {'At(Robot,Bar)', 'Is(AC,Off)',
|
||||||
'Holding(Nothing)','Exist(Yogurt)','Exist(BottledDrink)','On(Yogurt,Bar)','On(BottledDrink,Table1)',
|
'Holding(Nothing)','Exist(Yogurt)','Exist(BottledDrink)','On(Yogurt,Bar)','On(BottledDrink,Table1)',
|
||||||
'Is(HallLight,Off)', 'Is(TubeLight,On)', 'Is(Curtain,On)',
|
'Is(HallLight,Off)', 'Is(TubeLight,On)', 'Is(Curtain,On)',
|
||||||
'Is(Table1,Dirty)', 'Is(Floor,Dirty)', 'Is(Chairs,Dirty)'}
|
'Is(Table1,Dirty)', 'Is(Floor,Dirty)', 'Is(Chairs,Dirty)'},
|
||||||
|
"obj_mem":{},
|
||||||
|
"customer_mem":{},
|
||||||
|
"served_mem":{},
|
||||||
|
"greeted_customers":set(),
|
||||||
|
"attention":{}
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
status:
|
status:
|
||||||
|
@ -143,9 +149,20 @@ class Scene:
|
||||||
self.time = time.time() - self.start_time
|
self.time = time.time() - self.start_time
|
||||||
|
|
||||||
self.deal_event()
|
self.deal_event()
|
||||||
|
self.deal_new_event()
|
||||||
self._step()
|
self._step()
|
||||||
self.robot.step()
|
self.robot.step()
|
||||||
|
|
||||||
|
def deal_new_event(self):
|
||||||
|
if len(self.new_event_list)>0:
|
||||||
|
next_event = self.new_event_list[0]
|
||||||
|
t,func,args = next_event
|
||||||
|
if self.time >= t:
|
||||||
|
print(f'event: {t}, {func.__name__}')
|
||||||
|
self.new_event_list.pop(0)
|
||||||
|
func(*args)
|
||||||
|
|
||||||
|
|
||||||
def deal_event(self):
|
def deal_event(self):
|
||||||
if len(self.event_list)>0:
|
if len(self.event_list)>0:
|
||||||
next_event = self.event_list[0]
|
next_event = self.event_list[0]
|
||||||
|
@ -171,6 +188,10 @@ class Scene:
|
||||||
|
|
||||||
return set_sub_task
|
return set_sub_task
|
||||||
|
|
||||||
|
def new_set_goal(self,goal):
|
||||||
|
g = eval("{'" + goal + "'}")
|
||||||
|
self.state['chat_list'].append(g)
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def status(self):
|
def status(self):
|
||||||
|
@ -196,7 +217,6 @@ class Scene:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def walker_control_generator(self, walkerID, autowalk, speed, X, Y, Yaw):
|
def walker_control_generator(self, walkerID, autowalk, speed, X, Y, Yaw):
|
||||||
if self.use_offset:
|
if self.use_offset:
|
||||||
X, Y = X + loc_offset[0], Y + loc_offset[1]
|
X, Y = X + loc_offset[0], Y + loc_offset[1]
|
||||||
|
@ -216,6 +236,10 @@ class Scene:
|
||||||
|
|
||||||
return scene
|
return scene
|
||||||
|
|
||||||
|
def walker_walk_to(self,walkerID,X,Y,speed=50,Yaw=0):
|
||||||
|
self.control_walker(
|
||||||
|
[self.walker_control_generator(walkerID=walkerID, autowalk=False, speed=speed, X=X, Y=Y, Yaw=Yaw)])
|
||||||
|
|
||||||
|
|
||||||
def reachable_check(self, X, Y, Yaw):
|
def reachable_check(self, X, Y, Yaw):
|
||||||
if self.use_offset:
|
if self.use_offset:
|
||||||
|
@ -243,9 +267,19 @@ class Scene:
|
||||||
print('当前位置不可达,无法初始化NPC')
|
print('当前位置不可达,无法初始化NPC')
|
||||||
else:
|
else:
|
||||||
walker_list.append(
|
walker_list.append(
|
||||||
GrabSim_pb2.WalkerList.Walker(id=id+5, pose=GrabSim_pb2.Pose(X=loc[0], Y=loc[1], Yaw=loc[2])))
|
GrabSim_pb2.WalkerList.Walker(id=id, pose=GrabSim_pb2.Pose(X=loc[0], Y=loc[1], Yaw=loc[2])))
|
||||||
stub.AddWalker(GrabSim_pb2.WalkerList(walkers=walker_list, scene=self.sceneID))
|
stub.AddWalker(GrabSim_pb2.WalkerList(walkers=walker_list, scene=self.sceneID))
|
||||||
|
|
||||||
|
w = self.status.walkers
|
||||||
|
num_customer = len(w)
|
||||||
|
self.state["customer_mem"][w[-1].name] = num_customer-1
|
||||||
|
|
||||||
|
def walker_index2mem(self,index):
|
||||||
|
for mem,i in self.state["customer_mem"].items():
|
||||||
|
if index == i:
|
||||||
|
return mem
|
||||||
|
|
||||||
|
|
||||||
def add_walkers(self,walker_loc=[[0, 880], [250, 1200], [-55, 750], [70, -200]]):
|
def add_walkers(self,walker_loc=[[0, 880], [250, 1200], [-55, 750], [70, -200]]):
|
||||||
print('------------------add_walkers----------------------')
|
print('------------------add_walkers----------------------')
|
||||||
for id,walker in enumerate(walker_loc):
|
for id,walker in enumerate(walker_loc):
|
||||||
|
@ -267,8 +301,16 @@ class Scene:
|
||||||
# walkerID is the index of the walker in status.walkers.
|
# walkerID is the index of the walker in status.walkers.
|
||||||
# Since status.walkers is a list, some walkerIDs would change after removing a walker.
|
# Since status.walkers is a list, some walkerIDs would change after removing a walker.
|
||||||
remove_list.append(walkerID)
|
remove_list.append(walkerID)
|
||||||
|
|
||||||
|
index_shift_list = [ 0 for _ in range(len(self.state["customer_mem"])) ]
|
||||||
|
|
||||||
stub.RemoveWalkers(GrabSim_pb2.RemoveList(IDs=remove_list, scene=self.sceneID))
|
stub.RemoveWalkers(GrabSim_pb2.RemoveList(IDs=remove_list, scene=self.sceneID))
|
||||||
|
|
||||||
|
w = self.status.walkers
|
||||||
|
for i in range(len(w)):
|
||||||
|
self.state["customer_mem"][w[i].name] = i
|
||||||
|
|
||||||
|
|
||||||
def clean_walker(self):
|
def clean_walker(self):
|
||||||
stub.CleanWalkers(GrabSim_pb2.SceneID(value=self.sceneID))
|
stub.CleanWalkers(GrabSim_pb2.SceneID(value=self.sceneID))
|
||||||
|
|
||||||
|
@ -382,11 +424,15 @@ class Scene:
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# def walker_bubble(self, message):
|
def walker_bubble(self, name, message):
|
||||||
# status = self.status
|
talk_content = name + ":" + message
|
||||||
# walker_name = status.walkers[0].name
|
self.control_robot_action(0, 3, talk_content)
|
||||||
# talk_content = walker_name + ":" + message
|
|
||||||
# self.control_robot_action(0, 0, 3, talk_content)
|
def customer_say(self,name,sentence,show_bubble=True):
|
||||||
|
print(f'{name} say: {sentence}')
|
||||||
|
if show_bubble:
|
||||||
|
self.walker_bubble(name,sentence)
|
||||||
|
self.state['chat_list'].append((name,sentence))
|
||||||
|
|
||||||
# def control_robot_action(self, scene_id=0, type=0, action=0, message="你好"):
|
# def control_robot_action(self, scene_id=0, type=0, action=0, message="你好"):
|
||||||
# print('------------------control_robot_action----------------------')
|
# print('------------------control_robot_action----------------------')
|
||||||
|
@ -474,6 +520,8 @@ class Scene:
|
||||||
scene = stub.Do(action)
|
scene = stub.Do(action)
|
||||||
print("After Walk Position:", [scene.location.X, scene.location.Y, scene.rotation.Yaw])
|
print("After Walk Position:", [scene.location.X, scene.location.Y, scene.rotation.Yaw])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 相应的行动,由主办方封装
|
# 相应的行动,由主办方封装
|
||||||
def control_robot_action(self, type=0, action=0, message="你好"):
|
def control_robot_action(self, type=0, action=0, message="你好"):
|
||||||
scene = stub.ControlRobot(
|
scene = stub.ControlRobot(
|
||||||
|
|
|
@ -32,7 +32,6 @@ class SceneAT(Scene):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import os
|
|
||||||
from robowaiter.robot.robot import Robot
|
from robowaiter.robot.robot import Robot
|
||||||
|
|
||||||
robot = Robot()
|
robot = Robot()
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
"""
|
||||||
|
人提出请求,机器人完成任务
|
||||||
|
1. 做咖啡(固定动画):接收到做咖啡指令、走到咖啡机、拿杯子、操作咖啡机、取杯子、送到客人桌子上
|
||||||
|
2. 倒水
|
||||||
|
3. 夹点心
|
||||||
|
|
||||||
|
具体描述:设计一套点单规则(如菜单包含咖啡、水、点心等),按照规则拟造随机的订单。在收到订单后,通过大模型让机器人输出合理的备餐计划,并尝试在模拟环境中按照这个规划实现任务。
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# todo: 接收点单信息,大模型生成任务规划
|
||||||
|
|
||||||
|
from robowaiter.scene.scene import Scene
|
||||||
|
|
||||||
|
class SceneOT(Scene):
|
||||||
|
|
||||||
|
def __init__(self, robot):
|
||||||
|
super().__init__(robot)
|
||||||
|
# 在这里加入场景中发生的事件
|
||||||
|
self.new_event_list = [
|
||||||
|
# (9,self.add_walkers,([[0, 880]],)),
|
||||||
|
# (10,self.walker_walk_to,(2,50,500))
|
||||||
|
# (5, self.set_goal("On(Yogurt,Table4)"))
|
||||||
|
# (5, self.set_goal("At(Robot,BrightTable4)"))
|
||||||
|
]
|
||||||
|
|
||||||
|
def _reset(self):
|
||||||
|
# self.add_walkers([[0, 880], [250, 1200]])
|
||||||
|
|
||||||
|
# 展示顾客,前8个id是小孩,后面都是大人
|
||||||
|
for i in range(4):
|
||||||
|
self.add_walker(i,50,300 + i * 50)
|
||||||
|
name1 = self.walker_index2mem(1)
|
||||||
|
name2 = self.walker_index2mem(3)
|
||||||
|
|
||||||
|
self.remove_walker(0,2)
|
||||||
|
|
||||||
|
index1 = self.state["customer_mem"][name1]
|
||||||
|
index2 = self.state["customer_mem"][name2]
|
||||||
|
|
||||||
|
self.walker_bubble(name1,f"我是第{index1}个")
|
||||||
|
self.walker_bubble(name2,f"我是第{index2}个")
|
||||||
|
|
||||||
|
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()
|
Loading…
Reference in New Issue