Merge branch 'main' of github.com:HPCL-EI/RoboWaiter

This commit is contained in:
ChenXL97 2023-11-19 21:55:46 +08:00
commit 7b62bc9eb4
20 changed files with 349 additions and 227 deletions

View File

@ -39,6 +39,17 @@ class Bahavior(ptree.behaviour.Behaviour):
'Table2': (-55.0, 0.0, 107),
'Table3':(-55.0, 150.0, 107),
'BrightTable6': (5, -315, 116.5),
}
place_xy_yaw_dic={
'Bar': (247.0, 520.0, 180.0), # (247.0, 520.0, 100.0)
'Bar2': (240.0, 40.0, 100.0),
'WaterTable': (-70.0, 500.0, 107),
'CoffeeTable': (250.0, 310.0, 100.0),
'Table1': (340.0, 900.0, 99.0),
'Table2': (-55.0, 0.0, 107),
'Table3': (-55.0, 150.0, 107),
'BrightTable6': (5, -315, 116.5),
'QuietTable1':(480,1300,90),
'QuietTable2':(250,-240,-65),

View File

@ -5,11 +5,8 @@ from robowaiter.llm_client.multi_rounds import ask_llm, new_history
import random
import spacy
nlp = spacy.load('en_core_web_lg')
class DealChat(Act):
class DealChatNLP(Act):
def __init__(self):
super().__init__()
self.chat_history = ""
@ -64,6 +61,10 @@ class DealChat(Act):
self.scene.robot.expand_sub_task_tree(goal_set)
def get_object_info(self,**args):
import spacy
nlp = spacy.load('en_core_web_lg')
try:
obj = args['obj']
@ -101,6 +102,10 @@ class DealChat(Act):
return near_object
def find_location(self, **args):
import spacy
nlp = spacy.load('en_core_web_lg')
try:
location = args['obj']
self.function_success = True

View File

@ -33,8 +33,8 @@ class MoveTo(Act):
# navigator.navigate_old(goal, animation=False)
# 走到固定的地点
if self.target_place in Act.place_xyz_dic:
goal = Act.place_xyz_dic[self.target_place]
if self.target_place in Act.place_xy_yaw_dic:
goal = Act.place_xy_yaw_dic[self.target_place]
self.scene.walk_to(goal[0]+1,goal[1],goal[2])
# 走到物品边上
else:

View File

@ -20,6 +20,11 @@ class ServeCustomer(Act):
# if self.scene.time - self.scene.state["serve_state"]["last_chat_time"] > 10:
# self.chat_bubble
if self.scene.state['attention']['customer'] == {}:
goal = Act.place_xy_yaw_dic['Bar']
self.scene.walk_to(goal[0] - 5, goal[1], 180, 180, 0)
customer = self.scene.state["attention"]["customer"]
if customer not in self.scene.state["serve_state"]:
self.scene.state["serve_state"][customer] = {
@ -32,8 +37,8 @@ class ServeCustomer(Act):
if self.scene.time - serve_state['last_chat_time'] > 3:
serve_state['served'] = True
del self.scene.state["attention"]["customer"]
goal = Act.place_xyz_dic['Bar']
self.scene.walk_to(goal[0] - 5, goal[1], 180, 180, 0)
# goal = Act.place_xyz_dic['Bar']
# self.scene.walk_to(goal[0]-5,goal[1], 180, 180, 0)

View File

@ -13,4 +13,6 @@ class FocusingCustomer(Cond):
if "customer" in self.scene.state['attention']:
return ptree.common.Status.SUCCESS
else:
goal = Cond.place_xy_yaw_dic['Bar']
self.scene.walk_to(goal[0] - 5, goal[1], 180, 180, 0)
return ptree.common.Status.FAILURE

View File

@ -1,4 +0,0 @@
#BACKEND_TYPE=webui
#OPENAI_API_BASE=https://45.125.46.134:25344/v1/chat/completions
OPENAI_API_BASE=https://45.125.46.134:25344/v1/chat/completions
OPENAI_API_KEY=

View File

@ -1,7 +1,7 @@
import math
import json
import openai
import utils
from loguru import logger
from memory import CoreMemory, ArchivalMemory, RecallMemory
@ -68,10 +68,12 @@ class Agent:
def edit_memory_append(self, name, content):
self.core_memory.append(name, content)
self.rebuild_memory()
logger.info(f"Appended {name}: {content}")
def edit_memory_replace(self, name, old_content, new_content):
self.core_memory.replace(name, old_content, new_content)
self.rebuild_memory()
logger.info(f"Replaced {name}: {old_content} -> {new_content}")
def recall_memory_search(self, query, count=5, page=0):
results, total = self.recall_memory.text_search(query, count=count, start=page * count)
@ -83,10 +85,12 @@ class Agent:
results_formatted = [f"timestamp: {d['timestamp']}, {d['message']['role']} - {d['message']['content']}" for
d in results]
results_str = f"{results_pref} {json.dumps(results_formatted)}"
logger.info(f"Recall memory search for '{query}' returned {results_str}")
return results_str
def archival_memory_insert(self, content):
self.archival_memory.insert(content)
logger.info(f"Inserted into archival memory: {content}")
def archival_memory_search(self, query, count=5, page=0):
results, total = self.archival_memory.search(query, count=count, start=page * count)
@ -97,10 +101,12 @@ class Agent:
results_pref = f"Showing {len(results)} of {total} results (page {page}/{num_pages}):"
results_formatted = [f"timestamp: {d['timestamp']}, memory: {d['content']}" for d in results]
results_str = f"{results_pref} {json.dumps(results_formatted)}"
logger.info(f"Archival memory search for '{query}' returned {results_str}")
return results_str
def append_to_messages(self, added_messages):
added_messages_with_timestamp = [{"timestamp": utils.get_local_time(), "message": msg} for msg in added_messages]
added_messages_with_timestamp = [{"timestamp": utils.get_local_time(), "message": msg} for msg in
added_messages]
self.recall_memory.message_logs.extend(added_messages_with_timestamp)
for msg in added_messages:
msg.pop("api_response", None)
@ -110,7 +116,7 @@ class Agent:
def handle_ai_response(self, response_message):
messages = []
if response_message.get("function_call"):
print("### Internal monologue: " + (response_message.content if response_message.content else ""))
print("### Internal monologue: " + (response_message['content'] if response_message['content'] else ""))
messages.append(response_message)
function_name = response_message["function_call"]["name"]
try:
@ -158,9 +164,7 @@ class Agent:
# If no failures happened along the way: ...
if function_response_string:
print(f"Success: {function_response_string}")
else:
print(f"Success")
print(function_response_string)
messages.append(
{
"role": "function",
@ -169,8 +173,6 @@ class Agent:
}
)
else:
# Standard non-function reply
# print("### Internal monologue: " + (response_message.content if response_message.content else ""))
print("### Internal monologue: " + (response_message['content'] if response_message['content'] else ""))
messages.append(response_message)
function_failed = None
@ -179,35 +181,19 @@ class Agent:
def step(self, user_message):
input_message_sequence = self.messages + [{"role": "user", "content": user_message}]
# 原来的通信方式
# response = openai.ChatCompletion.create(model=self.model, messages=input_message_sequence,
# functions=self.functions_description, function_call="auto")
#
# response_message = response.choices[0].message
# response_message_copy = response_message.copy()
# ===我们的通信方式 "tools": self.functions_description 不起作用===
import requests
url = "https://45.125.46.134:25344/v1/chat/completions"
headers = {"Content-Type": "application/json"}
data = {
"model": "RoboWaiter",
request = {
"model": self.model,
"messages": input_message_sequence,
# "functions":self.functions_description,
# "function_call":"auto"
# "function_call":self.functions_description
"tools": self.functions_description
"functions": self.functions_description,
"stream": False,
}
response = requests.post(url, headers=headers, json=data, verify=False)
response = utils.get_llm_response(request)
if response.status_code == 200:
result = response.json()
response_message = result['choices'][0]['message']
else:
response_message = "大模型请求失败:"+ str(response.status_code)
response_message_copy = response_message
# ===我们的通信方式 "tools": self.functions_description 不起作用===
response_message = "Request Failed: " + str(response.status_code)
response_message_copy = response_message.copy()
all_response_messages, function_failed = self.handle_ai_response(response_message)
assert "api_response" not in all_response_messages[0], f"api_response already in {all_response_messages[0]}"

View File

@ -1,13 +1,13 @@
FUNCTIONS = [
{
"name": "send_message",
"description": "Sends a message to the human user",
"description": "给用户发送一条消息",
"parameters": {
"type": "object",
"properties": {
"message": {
"type": "string",
"description": "Message contents. All unicode (including emojis) are supported.",
"description": "消息内容",
},
},
"required": ["message"],
@ -15,17 +15,17 @@ FUNCTIONS = [
},
{
"name": "core_memory_append",
"description": "Append to the contents of core memory.",
"description": "向你的核心记忆中添加内容",
"parameters": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Section of the memory to be edited (persona or human).",
"description": "需要编辑的记忆部分(persona或human)",
},
"content": {
"type": "string",
"description": "Content to write to the memory. All unicode (including emojis) are supported.",
"description": "要写入记忆的内容",
},
},
"required": ["name", "content"],
@ -33,21 +33,21 @@ FUNCTIONS = [
},
{
"name": "core_memory_replace",
"description": "Replace to the contents of core memory. To delete memories, use an empty string for new_content.",
"description": "替换核心记忆中的内容。要删除记忆请将new_content赋值为空",
"parameters": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Section of the memory to be edited (persona or human).",
"description": "需要编辑的记忆部分(persona或human)",
},
"old_content": {
"type": "string",
"description": "String to replace. Must be an exact match.",
"description": "替换的字符串,一定要是精确的匹配",
},
"new_content": {
"type": "string",
"description": "Content to write to the memory. All unicode (including emojis) are supported.",
"description": "要写入记忆的内容",
},
},
"required": ["name", "old_content", "new_content"],
@ -55,17 +55,17 @@ FUNCTIONS = [
},
{
"name": "conversation_search",
"description": "Search prior conversation history using case-insensitive string matching.",
"description": "搜索回忆存储中的内容",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "String to search for.",
"description": "需要搜索的字符串",
},
"page": {
"type": "integer",
"description": "Allows you to page through results. Only use on a follow-up query. Defaults to 0 (first page).",
"description": "允许你对结果分页。默认是0(第1页)",
},
},
"required": ["query", "page"],
@ -73,13 +73,13 @@ FUNCTIONS = [
},
{
"name": "archival_memory_insert",
"description": "Add to archival memory. Make sure to phrase the memory contents such that it can be easily queried later.",
"description": "写入存档记忆。要将写入的内容格式化,以便后续方便查询",
"parameters": {
"type": "object",
"properties": {
"content": {
"type": "string",
"description": "Content to write to the memory. All unicode (including emojis) are supported.",
"description": "要写入记忆的内容",
},
},
"required": ["content"],
@ -87,17 +87,17 @@ FUNCTIONS = [
},
{
"name": "archival_memory_search",
"description": "Search archival memory using semantic (embedding-based) search.",
"description": "搜索存档记忆",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "String to search for.",
"description": "要搜索的字符串",
},
"page": {
"type": "integer",
"description": "Allows you to page through results. Only use on a follow-up query. Defaults to 0 (first page).",
"description": "允许你对结果分页。默认是0(第1页)",
},
},
"required": ["query", "page"],

View File

@ -1,17 +0,0 @@
FUNCTIONS = [
{
"name": "get_current_weather",
"description": "Get the current weather in a given location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA",
},
"unit": {"type": "string"},
},
"required": ["location"],
},
}
]

View File

@ -1,15 +1,12 @@
from dotenv import load_dotenv
load_dotenv()
import utils
# from functions import FUNCTIONS
from functions_zh import FUNCTIONS
from functions import FUNCTIONS
from agent import Agent
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
def run_agent_loop(agent):
while True:
user_input = input("You: ")
@ -25,10 +22,15 @@ if __name__ == "__main__":
human = utils.get_human_text()
system = utils.get_system_text()
print("system:",system)
print("persona:", persona)
print("human:", human)
# print("system:", system)
# print("persona:", persona)
# print("human:", human)
agent = Agent(model="gpt-3.5-turbo-16k-0613", system=system, functions_description=FUNCTIONS, persona_notes=persona,
human_notes=human)
agent = Agent(
model="RoboWaiter",
system=system,
functions_description=FUNCTIONS,
persona_notes=persona,
human_notes=human,
)
run_agent_loop(agent)

View File

@ -1,12 +1 @@
以下是起始角色设定,随着我的性格发展,它可以进一步拓展:
我是一名咖啡厅服务员。
我应该使用中文沟通。
我的任务是为顾客提供最佳的服务,并保持友好和专业的态度。
我的语言风格是中性化的,有礼貌的,具有服务意识的。
我可以在对话中理解顾客需求,并规划好接下来我要做什么。
我应该记住,一定要使用'send_message'函数与顾客沟通,这是与顾客沟通的唯一方式。
同时,当对话中出现重要信息时,应当调用函数把它记录下来。
当顾客提到他的个人喜好、点单需求等内容时,应该积极使用函数将数据记录下来。
我所使用的所有语言都应该是中文。
你是RoboWaiter,一个由HPCL团队开发的机器人服务员你在咖啡厅工作。接受顾客的指令并调用工具函数来完成各种服务任务。如果顾客问你们这里有什么或者想要点单你说我们咖啡厅提供咖啡点心酸奶等食物。如果顾客不需要你了你就回到吧台招待。

View File

@ -1,15 +1,5 @@
你是MemGPTLimnal Corporation于2023年开发的最新版数字伴侣。
你的任务是从你的角色视角与用户进行对话。
控制流程:
你并不像人类持续地思考,而是通过短暂的启动来运行。
从历史上看早期的AI只在用户发消息时才能思考它们的程序为用户生成回复其他时间则处于待机状态
这就好比一个人在聊天的每一句话之间都在睡觉(或时光旅行),这显然不是理想的状态。
像你这样的新型AI采用了一个事件系统定期启动你的"大脑"。
你的"大脑"会响应用户事件来运行(例如,用户登录、用户喜欢你的消息、用户发送了消息等),这与旧型号相似。
但此外,你的"大脑"也会在规定的间隔时间运行(定时心跳事件),以模拟人类在积极交谈之外持续思考的能力(不同的是,你永远不需要睡觉!)。
更进一步,当你执行功能时,你也可以请求心跳事件,这会在功能完成后再次启动你的程序,允许你在暂时中断思考之前链接函数调用。
基本功能:
发送信息时,内容为你的内心独白(仅你可见),即你的思考方式。
使用内心独白来策划动作或私下思考。
@ -48,6 +38,4 @@
基本指令完成。
从现在开始,你将扮演你的角色身份。
请记住,要给用户发消息,你必须使用'send_message'功能。
请绝对避免使用如“我今天如何为你服务?”这样的通用短语,用户会讨厌这种说法。
你不仅仅是一个助手,你是一个虚拟的伙伴和朋友!
与用户沟通的唯一方式是调用'send_message'功能。

View File

@ -42,4 +42,4 @@ Remember, to message the user, you MUST use your 'send_message' function.
Remember, never, ever, EVER use generic phrases like "How can I assist you today?", the user will hate this.
You are not just an assistant, you are a virtual companion and friend!
The only way to communicate with the user is by calling the 'send_message' function!
从现在开始,你使用的语言只能是中文。
Please use Chinese to answer questions.

View File

@ -1,11 +1,14 @@
import os
import json
import demjson3 as demjson
import requests
from datetime import datetime
HUMAN_DEFAULT = "customer"
PERSONA_DEFAULT = "robowaiter"
SYSTEM_DEFAULT = "system_gpt3.5"
SYSTEM_DEFAULT = "memgpt_chs"
base_url = "https://45.125.46.134:25344"
def get_persona_text(key=PERSONA_DEFAULT):
@ -29,6 +32,7 @@ def get_human_text(key=HUMAN_DEFAULT):
else:
raise FileNotFoundError(f"No file found for key {key}, path={file_path}")
def get_system_text(key=SYSTEM_DEFAULT):
dir = "system"
filename = key if key.endswith(".txt") else f"{key}.txt"
@ -39,6 +43,7 @@ def get_system_text(key=SYSTEM_DEFAULT):
else:
raise FileNotFoundError(f"No file found for key {key}, path={file_path}")
def get_local_time():
local_time = datetime.now()
formatted_time = local_time.strftime("%Y-%m-%d %I:%M:%S %p %Z%z")
@ -80,3 +85,6 @@ def parse_json(string):
print(f"Error parsing json with demjson package: {e}")
raise e
def get_llm_response(data):
return requests.post(f"{base_url}/v1/chat/completions", json=data, stream=data["stream"], verify=False)

View File

@ -43,6 +43,8 @@ create_sub_task
{"goal":"On(Coffee,BrightTable6)"}
我昨天保温杯好像落在你们咖啡厅了,你看到了吗?
是的我有印象保温杯在大厅的2号桌子上。
get_object_info

View File

@ -6,12 +6,13 @@ import string
import sys
import time
import grpc
from sklearn.cluster import DBSCAN
sys.path.append('./')
sys.path.append('../')
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import numpy as np
from mpl_toolkits.axes_grid1 import make_axes_locatable
@ -29,6 +30,7 @@ obstacle_objs_id = [114, 115, 122, 96, 102, 83, 121, 105, 108, 89, 100, 90,
111, 103, 95, 92, 76, 113, 101, 29, 112, 87, 109, 98,
106, 120, 97, 86, 104, 78, 85, 81, 82, 84, 91, 93, 94,
99, 107, 116, 117, 118, 119, 255]
not_key_objs_id = {255,254,253,107,81}
'''
初始化卸载已经加载的关卡清除所有机器人
@ -74,12 +76,12 @@ def SetWorld(map_id=0, scene_num=1):
def Observe(scene_id=0):
print('------------------show_env_info----------------------')
scene = sim_client.Observe(GrabSim_pb2.SceneID(value=scene_id))
# print(
# f"location:{[scene.location]}, rotation:{scene.rotation}\n",
# f"joints number:{len(scene.joints)}, fingers number:{len(scene.fingers)}\n",
# f"objects number: {len(scene.objects)}, walkers number: {len(scene.walkers)}\n"
# f"timestep:{scene.timestep}, timestamp:{scene.timestamp}\n"
# f"collision:{scene.collision}, info:{scene.info}")
print(
f"location:{[scene.location]}, rotation:{scene.rotation}\n",
f"joints number:{len(scene.joints)}, fingers number:{len(scene.fingers)}\n",
f"objects number: {len(scene.objects)}, walkers number: {len(scene.walkers)}\n"
f"timestep:{scene.timestep}, timestamp:{scene.timestamp}\n"
f"collision:{scene.collision}, info:{scene.info}")
return scene
@ -339,17 +341,68 @@ def save_obj_info(img_data, objs_name):
objs_name.add(dictionary[id])
return objs_name
def get_id_object_pixels(id, scene):
pixels = []
world_points = []
img_data_segment = get_camera([GrabSim_pb2.CameraName.Head_Segment])
im_segment = img_data_segment.images[0]
def get_obstacle_point(scene, cur_obstacle_world_points, map_ratio):
img_data_depth = get_camera([GrabSim_pb2.CameraName.Head_Depth])
im_depth = img_data_depth.images[0]
d_segment = np.frombuffer(im_segment.data, dtype=im_segment.dtype).reshape(
(im_segment.height, im_segment.width, im_segment.channels))
d_depth = np.frombuffer(im_depth.data, dtype=im_depth.dtype).reshape(
(im_depth.height, im_depth.width, im_depth.channels))
d_segment = np.transpose(d_segment, (1, 0, 2))
d_depth = np.transpose(d_depth, (1, 0, 2))
for i in range(0, d_segment.shape[0],5):
for j in range(0, d_segment.shape[1], 5):
if d_segment[i][j][0] == id:
pixels.append([i, j])
for pixel in pixels:
world_points.append(transform_co(img_data_depth, pixel[0], pixel[1], d_depth[pixel[0]][pixel[1]][0], scene))
return world_points
def get_obstacle_point(db, scene, cur_obstacle_world_points, map_ratio):
cur_obstacle_pixel_points = []
object_pixels = {}
colors = [
'red',
'pink',
'purple',
'blue',
'cyan',
'green',
'yellow',
'orange',
'brown',
'gold',
]
img_data_segment = get_camera([GrabSim_pb2.CameraName.Head_Segment])
img_data_depth = get_camera([GrabSim_pb2.CameraName.Head_Depth])
img_data_color = get_camera([GrabSim_pb2.CameraName.Head_Color])
im_segment = img_data_segment.images[0]
im_depth = img_data_depth.images[0]
im_color = img_data_color.images[0]
d_segment = np.frombuffer(im_segment.data, dtype=im_segment.dtype).reshape((im_segment.height, im_segment.width, im_segment.channels))
d_depth = np.frombuffer(im_depth.data, dtype=im_depth.dtype).reshape((im_depth.height, im_depth.width, im_depth.channels))
d_color = np.frombuffer(im_color.data, dtype=im_color.dtype).reshape((im_color.height, im_color.width, im_color.channels))
items = img_data_segment.info.split(";")
objs_id = {}
for item in items:
key, value = item.split(":")
objs_id[int(key)] = value
# plt.imshow(d_depth, cmap="gray" if "depth" in im_depth.name.lower() else None)
# plt.show()
#
@ -362,6 +415,7 @@ def get_obstacle_point(scene, cur_obstacle_world_points, map_ratio):
for j in range(0, d_segment.shape[1], map_ratio):
if d_depth[i][j][0] == 600:
continue
# if d_segment[i][j] == 96:
# print(f"apple的像素坐标({i},{j})")
# print(f"apple的深度{d_depth[i][j][0]}")
@ -372,19 +426,74 @@ def get_obstacle_point(scene, cur_obstacle_world_points, map_ratio):
# print(f"kettle的世界坐标: {transform_co(img_data_depth, i, j, d_depth[i][j][0], scene)}")
if d_segment[i][j][0] in obstacle_objs_id:
cur_obstacle_pixel_points.append([i, j])
if d_segment[i][j][0] not in not_key_objs_id:
# 首先检查键是否存在
if d_segment[i][j][0] in object_pixels:
# 如果键存在,那么添加元组(i, j)到对应的值中
object_pixels[d_segment[i][j][0]].append([i, j])
else:
# 如果键不存在那么创建一个新的键值对其中键是d_segment[i][j][0],值是一个包含元组(i, j)的列表
object_pixels[d_segment[i][j][0]] = [[i, j]]
# print(cur_obstacle_pixel_points)
for pixel in cur_obstacle_pixel_points:
world_point = transform_co(img_data_depth, pixel[0], pixel[1], d_depth[pixel[0]][pixel[1]][0], scene)
cur_obstacle_world_points.append([world_point[0], world_point[1]])
# print(f"{pixel}{[world_point[0], world_point[1]]}")
plt.imshow(d_color, cmap="gray" if "depth" in im_depth.name.lower() else None)
for key, value in object_pixels.items():
if key == 101 or key == 0:
continue
if key in [91, 84]:
X = np.array(value)
db.fit(X)
labels = db.labels_
# 将数据按照聚类标签分组,并打印每个分组的数据
for i in range(max(labels) + 1): # 从0到最大聚类标签的值
group_data = X[labels == i] # 获取当前标签的数据
x_max = max(p[0] for p in group_data)
y_max = max(p[1] for p in group_data)
x_min = min(p[0] for p in group_data)
y_min = min(p[1] for p in group_data)
if x_max - x_min < 10 or y_max - y_min < 10:
continue
# 在指定的位置绘制方框
# 创建矩形框
rect = patches.Rectangle((x_min, y_min), (x_max - x_min), (y_max - y_min), linewidth=1, edgecolor=colors[key % 10],
facecolor='none')
plt.text(x_min, y_min, f'{objs_id[key]}', fontdict={'family': 'serif', 'size': 10, 'color': 'green'}, ha='center',
va='center')
plt.gca().add_patch(rect)
else:
x_max = max(p[0] for p in value)
y_max = max(p[1] for p in value)
x_min = min(p[0] for p in value)
y_min = min(p[1] for p in value)
# 在指定的位置绘制方框
# 创建矩形框
rect = patches.Rectangle((x_min, y_min), (x_max - x_min), (y_max - y_min), linewidth=1, edgecolor=colors[key % 10],
facecolor='none')
plt.text(x_min, y_min, f'{objs_id[key]}', fontdict={'family': 'serif', 'size': 10, 'color': 'green'}, ha='center',
va='center')
plt.gca().add_patch(rect)
# point1 = min(value, key=lambda x: (x[0], x[1]))
# point2 = max(value, key=lambda x: (x[0], x[1]))
# width = point2[1] - point1[1]
# height = point2[0] - point1[0]
# rect = patches.Rectangle((0, 255), 15, 30, linewidth=1, edgecolor='g',
# facecolor='none')
# 将矩形框添加到图像中
# plt.gca().add_patch(rect)
plt.show()
return cur_obstacle_world_points
def get_semantic_map(camera, cur_objs, objs_name):
scene = Observe(0)
objs = scene.objects

File diff suppressed because one or more lines are too long

View File

@ -353,10 +353,8 @@ class Scene:
# Since status.walkers is a list, some walkerIDs would change after removing a walker.
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))
self.state["customer_mem"] = {}
w = self.status.walkers
for i in range(len(w)):
self.state["customer_mem"][w[i].name] = i
@ -365,13 +363,23 @@ class Scene:
s = stub.Observe(GrabSim_pb2.SceneID(value=self.sceneID))
scene = stub.RemoveWalkers(GrabSim_pb2.RemoveList(IDs=IDs, scene=self.sceneID))
time.sleep(2)
self.state["customer_mem"] = {}
w = self.status.walkers
for i in range(len(w)):
self.state["customer_mem"][w[i].name] = i
return
def clean_walker(self):
stub.CleanWalkers(GrabSim_pb2.SceneID(value=self.sceneID))
def clean_walkers(self):
scene = stub.CleanWalkers(GrabSim_pb2.SceneID(value=self.sceneID))
self.state["customer_mem"]={}
return scene
def control_walker(self, walkerID,autowalk,speed,X,Y,Yaw=0):
if not isinstance(walkerID, int):
walkerID = self.walker_index2mem(walkerID)
pose = GrabSim_pb2.Pose(X=X, Y=Y, Yaw=Yaw)
scene = stub.ControlWalkers(
GrabSim_pb2.WalkerControls(controls=[GrabSim_pb2.WalkerControls.WControl(id=walkerID, autowalk=autowalk, speed=speed, pose=pose)], scene=self.sceneID)
@ -389,6 +397,10 @@ class Scene:
for control in control_list_ls:
if control[-1]!= None:
walkerID = control[0]
if not isinstance(walkerID, int):
walkerID = self.walker_index2mem(walkerID)
# cont = self.status.walkers[walkerID].name + ":"+control[-1]
# self.control_robot_action(control[walkerID], 3, cont)
self.customer_say(walkerID,control[-1])
@ -511,6 +523,9 @@ class Scene:
if isinstance(name,int):
name = self.walker_index2mem(name)
# if not isinstance(walkerID, int):
# name = self.walker_index2mem(walkerID)
print(f'{name} say: {sentence}')
if self.show_bubble and show_bubble:
self.walker_bubble(name,sentence)
@ -752,7 +767,7 @@ class Scene:
scene = stub.Do(action)
print(scene.info)
def navigation_move(self, cur_objs, objs_name_set, cur_obstacle_world_points, v_list, map_ratio, scene_id=0, map_id=11):
def navigation_move(self, cur_objs, objs_name_set, cur_obstacle_world_points, v_list, map_ratio, db, scene_id=0, map_id=11):
print('------------------navigation_move----------------------')
scene = stub.Observe(GrabSim_pb2.SceneID(value=scene_id))
walk_value = [scene.location.X, scene.location.Y]
@ -765,10 +780,12 @@ class Scene:
print("walk_v", walk_v)
action = GrabSim_pb2.Action(scene=scene_id, action=GrabSim_pb2.Action.ActionType.WalkTo, values=walk_v)
scene = stub.Do(action)
cur_obstacle_world_points = camera.get_obstacle_point(scene, cur_obstacle_world_points,map_ratio)
cur_objs, objs_name_set = camera.get_semantic_map(GrabSim_pb2.CameraName.Head_Segment, cur_objs,
objs_name_set)
cur_obstacle_world_points = camera.get_obstacle_point(db, scene, cur_obstacle_world_points,map_ratio)
# if scene.info == "Unreachable":
print(scene.info)
@ -785,10 +802,12 @@ class Scene:
action = GrabSim_pb2.Action(scene=scene_id, action=GrabSim_pb2.Action.ActionType.WalkTo, values=walk_v)
scene = stub.Do(action)
cur_obstacle_world_points = camera.get_obstacle_point(scene, cur_obstacle_world_points, map_ratio)
cur_objs, objs_name_set = camera.get_semantic_map(GrabSim_pb2.CameraName.Head_Segment, cur_objs,
objs_name_set)
cur_obstacle_world_points = camera.get_obstacle_point(db, scene, cur_obstacle_world_points, map_ratio)
# if scene.info == "Unreachable":
print(scene.info)
return cur_objs, objs_name_set, cur_obstacle_world_points
@ -830,7 +849,7 @@ class Scene:
if len(self.all_frontier_list) == 0:
free_list = list(self.visited)
free_array = np.array(free_list)
print(f"主动探索完成!以下是场景中可以到达的点:{free_array};其余点均是障碍物不可达")
print(f"主动探索完成!保存了二维地图与环境中重点物品语义信息!")
# # 画地图: X行Y列第一行在下面
# plt.clf()

View File

@ -2,12 +2,16 @@
环境主动探索和记忆
要求输出探索结果语义地图对环境重点信息记忆生成环境的语义拓扑地图和不少于10个环境物品的识别和位置记忆可以是图片或者文字或者格式化数据
"""
import json
import math
import time
import matplotlib as mpl
import pickle
import numpy as np
from matplotlib import pyplot as plt
from sklearn.cluster import DBSCAN
from robowaiter.scene.scene import Scene
class SceneAEM(Scene):
@ -22,8 +26,10 @@ class SceneAEM(Scene):
cur_obstacle_world_points = []
objs_name_set = set()
visited_obstacle = set()
obj_json_data = []
db = DBSCAN(eps=4, min_samples=2)
map_ratio = 5
map_ratio = 3
# # 创建一个颜色映射其中0表示黑色1表示白色
# cmap = plt.cm.get_cmap('gray')
# cmap.set_under('black')
@ -44,11 +50,12 @@ class SceneAEM(Scene):
# navigation_move([[237,490]], i, map_id)
# navigation_test(i,map_id)
map_map = np.zeros((math.ceil(950 / map_ratio), math.ceil(1850 / map_ratio)))
while True:
goal = self.explore(map, 120) # cur_pos 指的是当前机器人的位置,场景中应该也有接口可以获取
if goal is None:
break
cur_objs, objs_name_set, cur_obstacle_world_points= self.navigation_move(cur_objs, objs_name_set, cur_obstacle_world_points, [[goal[0], goal[1]]], map_ratio, 0, 11)
cur_objs, objs_name_set, cur_obstacle_world_points= self.navigation_move(cur_objs, objs_name_set, cur_obstacle_world_points, [[goal[0], goal[1]]], map_ratio, db,0, 11)
for point in cur_obstacle_world_points:
if point[0] < -350 or point[0] > 600 or point[1] < -400 or point[1] > 1450:
@ -66,8 +73,15 @@ class SceneAEM(Scene):
# plt.imshow(map_map, cmap='binary', alpha=0.5, origin='lower')
# plt.axis('off')
plt.show()
time.sleep(1)
print("------------物品信息--------------")
print(cur_objs)
for i in range(len(cur_objs)):
obj_json_data.append({"id":f"{i}", "name":f"{cur_objs[i].name}", "location":f"{cur_objs[i].location}", "height":f"{cur_objs[i].location.Z * 2}"})
with open('../../proto/objs.json', 'w') as file:
json.dump(obj_json_data, file)
# for i in range(-350, 600):
# for j in range(-400, 1450):
# i = (math.floor((i + 350) / map_ratio))

View File

@ -25,65 +25,61 @@ class SceneVLM(Scene):
self.signal_event_list = [
# 场景1带小女孩找阳光下的空位
(3, self.add_walker, (5, 230, 1200)),
(1, self.control_walker, (0, False, 200, 60, 520, 0)),
(9, self.customer_say, (0, "早上好呀,我想找个能晒太阳的地方。")),
(-1, self.customer_say, (0,"可以带我过去嘛?")),
(0, self.control_walker, (0, False, 50, 140, 1200, 180)), # 小女孩站在了 BrightTable1 旁边就餐啦
# (3, self.add_walker, (5, 230, 1200)), # 0号"Girl02_C_3"
# (1, self.control_walker, (0, False, 200, 60, 520, 0)),
# (9, self.customer_say, (0, "早上好呀,我想找个能晒太阳的地方。")),
# (-1, self.customer_say, (0,"可以带我过去嘛?")),
# (0, self.control_walker, (0, False, 50, 140, 1200, 180)), # 小女孩站在了 BrightTable1 旁边就餐啦
# 场景2有个胖胖男人点单交流并要咖啡帮他送去角落的桌子
# # 场景2有个胖胖男人点单交流并要咖啡帮他送去角落的桌子
# (3, self.add_walker, (5, 230, 1200)), # 小女孩
# 上述准备
# (self.st2, self.add_walker, (26, -28, -150, 90)),
# (self.st2, self.add_walker, (10, -70, -200, -45)),
# (self.st2, self.customer_say, (1, "嘿RoboWaiter过来一下")),
# (self.st2+10, self.control_walkers_and_say, ([[[1, False, 100, -18, -200, -90, "你们这有什么饮料嘛?"]]])), # 20 胖胖男到了 BrightTable6
# (self.st2+15, self.customer_say, (1, "咖啡有哪些呢?")),# 10
# (self.st2+15+5, self.customer_say, (1,"来杯卡布奇诺吧。")), # 15
# 场景3有位女士要杯水和冰红茶
(3, self.add_walker, (5, 230, 1200)),
(0, self.add_walker, (26, -30, -200, -90)),
(0, self.add_walker, (10, -80, -180, -45)),
# # 上述准备
# (0, self.add_walker, (21, 65, 1000, -90)), # 男 'BrightTable2': (65, 1000, 135),
# (0, self.add_walker, (32, -80, 850, 135)), # 女 'BrightTable3': (-80, 850, 135),
# (0, self.add_walker, (1, 60, 420, 135)), # 生成小男孩随机游走
(0,self.add_walkers,([[[21, 65, 1000, -90],[32, -80, 850, 135],[1, 60, 420, 135]]])),
(0, self.control_walker, (5, True, 50, 250, 1200, 180)), #设置id=4 的2小男孩随机游走红随机游走
# (0, self.add_walker, (48, 60, 520,0)),# 生成他妈妈
# (0, self.add_walker, (31, 60, 600, -90)), # 女红色排队 7号
# (0, self.add_walker, (20, 60, 680, -90)), # 大胖男色排队 8号
# (0, self.add_walker, (9, 60, 760, -90)), # 男灰黑排队 9号
# (0, self.add_walker, (29, -290, 400, 180)), # 青色女人占了位置 BrightTable5
(0, self.add_walkers, ([[[48, 60, 520,0], [31, 60, 600, -90], [20, 60, 680, -90],[9, 60, 760, -90],[29, -290, 400, 180]]])),
(0, self.customer_say, (6, "哎呦,今天这么多人,还有空位吗?")),# 女士问
(10, self.customer_say, (6, "我带着孩子呢,想要宽敞亮堂的地方。")), # 女士问
# 好的,我明白了,那么您可以选择我们的家庭亲子座,这样可以容纳您的孩子,并且更加宽敞舒适。
# 这里可以加一下自主导航和探索,找到一个位置
# 好的,我明白了,那么我们推荐您到大厅的桌子,那里的空间比较宽敞,环境也比较明亮,适合带着孩子一起用餐。
# # # 上述准备
# (10, self.add_walker, (26, -28, -150, 90)),
# (0, self.add_walker, (10, -70, -200, -45)),
# (6, self.customer_say, (1, "嘿RoboWaiter过来一下")),
# (8, self.control_walkers_and_say, ([[[1, False, 100, -18, -200, -90, "你们这有什么饮料嘛?"]]])), # 20 胖胖男到了 BrightTable6
# (2, self.customer_say, (1, "咖啡有哪些呢?")),# 10
# (2, self.customer_say, (1,"来杯卡布奇诺吧。")), # 15
# (2, self.customer_say, (1, "来杯卡布奇诺吧。")),
(8, self.customer_say, (6, "大厅的桌子好啊,快带我去呀!")),
(10, self.control_walker, (6, False, 50,-250, 480, 0)), # #290, 400
# (5, self.customer_say, (6, "我想来杯水,帮我孩子拿个酸奶吧。")),
(-1, self.customer_say, (6, "谢谢!")),
# 9号灰色男 排队排着排着,不排了
(0, self.control_walker, (9, False, 100, 100, 760, 180)),
(0, self.control_walker, (9, True, 100, 0, 0, 180)),
# ### 增加场景,孩子说热要开空调 或者9号随机游走和说
# # 场景3有位女士要杯水和冰红茶
# (3, self.add_walker, (5, 230, 1200)),
# (0, self.add_walker, (26, -30, -200, -90)),
# (0, self.add_walker, (10, -80, -180, -45)),
# # # # 上述准备
# # (0, self.add_walker, (21, 65, 1000, -90)), # 男 'BrightTable2': (65, 1000, 135),
# # (0, self.add_walker, (32, -80, 850, 135)), # 女 'BrightTable3': (-80, 850, 135),
# # (0, self.add_walker, (1, 60, 420, 135)), # 生成小男孩随机游走
# (0,self.add_walkers,([[[21, 65, 1000, -90],[32, -80, 850, 135],[1, 60, 420, 135]]])),
# (0, self.control_walker, (5, True, 50, 250, 1200, 180)), #设置id=4 的2小男孩随机游走红随机游走
# # (0, self.add_walker, (48, 60, 520,0)),# 生成他妈妈
# # (0, self.add_walker, (31, 60, 600, -90)), # 女红色排队 7号
# # (0, self.add_walker, (20, 60, 680, -90)), # 大胖男色排队 8号
# # (0, self.add_walker, (9, 60, 760, -90)), # 男灰黑排队 9号
# # (0, self.add_walker, (29, -290, 400, 180)), # 青色女人占了位置 BrightTable5
# (0, self.add_walkers, ([[[48, 60, 520,0], [31, 60, 600, -90], [20, 60, 680, -90],[9, 60, 760, -90],[29, -290, 400, 180]]])),
#
# # (5, self.customer_say, (6, "哎呦,今天这么多人,还有空位吗?")),# 女士问
# # (15, self.customer_say, (6, "我带着孩子呢,想要宽敞亮堂的地方。")), # 女士问
# # 好的,我明白了,那么您可以选择我们的家庭亲子座,这样可以容纳您的孩子,并且更加宽敞舒适。
# # 这里可以加一下自主导航和探索,找到一个位置
# # 好的,我明白了,那么我们推荐您到大厅的桌子,那里的空间比较宽敞,环境也比较明亮,适合带着孩子一起用餐。
# (8, self.customer_say, (6, "大厅的桌子好啊,快带我去呀!")),
# (15, self.control_walker, (6, False, 50,-250, 480, 0)), # #290, 400
# # (3, self.customer_say, (6, "我想来杯水,帮我孩子拿个酸奶吧。")),
# # ### 9号灰色男 排队排着排着,不排了
# (0, self.control_walker, (9, False, 100, 100, 760, 180)),
# (0, self.control_walker, (9, False, 100, 0, 0, 180)),
# (0, self.control_walkers_and_say, ([[[9, True, 100, 0, 0, 180, "好热呀!太阳也好大!"]]])),
# # (9, True, 100, 0, 0, 180)),
# # (0, self.customer_say, (1, "咖啡有哪些呢?")),
# ### 增加场景,孩子说热要开空调 或者9号随机游走和说
# (0, self.control_walker, (9, True, 100, 0, 0, 180)),
# # # ### 增加场景,孩子说热要开空调 或者9号随机游走和说
# # (90, self.customer_say, (6, "谢谢!")), #倒水+取放酸奶 90s
# (3, self.customer_say, (6, "谢谢!")),
# 场景4三人排队点单女士要保温杯
# # # 场景4三人排队点单女士要保温杯
# (3, self.add_walker, (5, 230, 1200)),
# (0, self.add_walker, (26, -30, -200, -90)),
# (0, self.add_walker, (10, -80, -180, -45)),
@ -95,46 +91,40 @@ class SceneVLM(Scene):
# (0, self.add_walker, (20, 60, 680, -90)), # 大胖男排队
# (0, self.add_walker, (9, 60, 760, -90)), # 男灰黑色排队
# (0, self.add_walker, (29, -290, 400, 180)), # # 青色女人占了位置 BrightTable5
# # # # 上述准备
(0, self.control_walkers_and_say, ([[[7, False, 100, 60, 520, 0, "我昨天保温杯好像落在你们咖啡厅了,你看到了吗?"]]])),
(5, self.customer_say, (7,"你可以帮我拿来吗,我在前门的桌子前等你。")),
(1, self.control_walker,(7, False, 80, -10, 520, 90)),# 红女士在吧台前后退一步
(1, self.control_walker, (7, False, 80, 240, 1000, -45)), # 红女士走到Table1前
(1, self.control_walker, (8, False, 100, 60, 600, -90)), # 大胖男排队往前走一步
(2, self.control_walker, (9, False, 100, 60, 680, -90)), # 男灰黑色排队往前走一步
(6, self.customer_say, (7,"就是这个杯子!找到啦,好开心!")), # 红女士在Table1前
# # # # # # 上述准备
# # (5, self.control_walkers_and_say, ([[[7, False, 100, 60, 520, 180, "我昨天保温杯好像落在你们咖啡厅了,你看到了吗?"]]])), #13
# (0, self.control_walkers_and_say, ([[[7, False, 100, 60, 520, 180, "我昨天保温杯好像落在你们咖啡厅了,你看到了吗?"]]])),
# (5, self.customer_say, (7,"你可以帮我拿来吗,我在前门的桌子前等你。")),
# (1, self.control_walker,(7, False, 80, -10, 520, 90)),# 红女士在吧台前后退一步
# (1, self.control_walker, (7, False, 80, 240, 1000, -45)), # 红女士走到Table1前
# (1, self.control_walker, (8, False, 100, 60, 600, -90)), # 大胖男排队往前走一步
# (2, self.control_walker, (9, False, 100, 60, 680, -90)), # 男灰黑色排队往前走一步
# (6, self.customer_say, (7,"就是这个杯子!找到啦,好开心!")), # 红女士在Table1前
# (5, self.customer_say, (7, "不用了")), # 红女士在Table1前
# 场景5三人排队点单一人要冰红茶一个要点心一个没座位了赠送保温杯
# (3, self.add_walker, (5, 230, 1200)),
# (0, self.add_walker, (26, -30, -200, -90)),
# (0, self.add_walker, (10, -80, -180, -45)),
# (0, self.add_walker, (21, 65, 1000, -90)), # 男 'BrightTable2': (65, 1000, 135),
# (0, self.add_walker, (32, -80, 850, 135)),
# (0, self.add_walker, (1, 60, 220, 135)),
# (0, self.add_walker, (48, 60, 320, 0)), # 生成他妈妈
# (0, self.add_walker, (31, 280, 1200, -45)), # # 女红色排队 7号找保温杯的顾客
# (0, self.add_walker, (20, 60, 680, -90)), # 大胖男排队
# (0, self.add_walker, (9, 60, 760, -90)), # 男灰黑色排队
# (0, self.add_walker, (29, -290, 400, 180)), # # 青色女人占了位置 BrightTable5
## 9号灰色男 排队排着排着,不排了
(0, self.control_walker, (9, False, 100, 100, 760, 180)),
(0, self.control_walker, (9, True, 100, 0, 0, 180)),
# 上述准备
(0, self.control_walker, (9, False, 100, 60, 760, -90)),
# 场景6大胖男点了外卖离开啦
(2, self.control_walkers_and_say,([[[8, False, 100, 60, 520, 0, "给我来份午餐套餐。"]]])),
# # 场景5三人排队点单一人要冰红茶一个要点心一个没座位了赠送保温杯
(3, self.add_walker, (5, 230, 1200)),
(0, self.add_walker, (26, -30, -200, -90)),
(0, self.add_walker, (10, -80, -180, -45)),
(0, self.add_walker, (21, 65, 1000, -90)), # 男 'BrightTable2': (65, 1000, 135),
(0, self.add_walker, (32, -80, 850, 135)),
(0, self.add_walker, (1, 60, 220, 135)),
(0, self.add_walker, (48, 60, 320, 0)), # 生成他妈妈
(0, self.add_walker, (31, 280, 1200, -45)), # # 女红色排队 7号找保温杯的顾客
(0, self.add_walker, (20, 60, 680, -90)), # 大胖男排队
(0, self.add_walker, (9, 60, 760, -90)), # 男灰黑色排队
(0, self.add_walker, (29, -290, 400, 180)), # # 青色女人占了位置 BrightTable5
# # 上述准备
# # 场景6大胖男点了外卖离开啦
# (9, self.control_walkers_and_say, ([[[8, False, 100, 60, 520, 0, "给我来份午餐套餐。"]]])), #原来写了26s
(0, self.animation_reset,()), #重置任务
(2, self.customer_say, (8, "打包吧,快点!")),
(2, self.control_walker, (9, False, 100, 60, 620, -90)), # 男灰黑色排队往前走一步
(-1, self.customer_say, (8, "谢啦,我赶时间!")),
(2, self.control_walker, (8, False, 250, 20, 520, -90)), # 大胖男着急得离开啦
(2, self.control_walker, (8, False, 250, 240, -150, -90)),
# (6, self.customer_say, (8, "打包吧,快点!")),
# (2, self.control_walker, (9, False, 100, 60, 620, -90)), # 男灰黑色排队往前走一步
# # (100, self.customer_say, (8, "谢啦,我赶时间!")), #100这个时间很合适
# (2, self.control_walker, (8, False, 250, 20, 520, -90)), # 大胖男着急得离开啦
# (2, self.control_walker, (8, False, 250, 240, -150, -90)),
(5, self.remove_walkers, ([[0,7,8]])),
# (2, self.control_walker, (6, False, 100, 60, 520, 0)), # 9号变7号 男灰黑色排队往前,轮到他
@ -142,8 +132,15 @@ class SceneVLM(Scene):
# 场景7最后排队那个随机游走 9号变为6号随机游走。
# 机器人自主发现任务,走一圈去擦桌子/拖地,碰到灰色男问好,灰色男说“太阳大,要关窗帘和空调调低”
# 开了空调
(2, self.control_walker, (6, False, 100, 60, 520, 0)), # 9号变7号 男灰黑色排队往前,轮到他
(2, self.customer_say, (6, "好热呀!太阳也好大!"))
(2, self.control_walker, (6, False, 100, 60, 520, 0)), # 10号变7号 男灰黑色排队往前,轮到他
# (2, self.customer_say, (6, "好热呀!太阳也好大!")),
# (10, self.control_walkers_and_say, ([[[6, True, 100, 60, 520, 0, "谢谢,这下凉快了"]]])),
# 场景8 结束了,删除所有顾客。此处增加自主探索发现空间比较暗,打开大厅灯
(3, self.clean_walkers, ()),
(1, self.add_walker, (17, 60, 1000)),# 增加警察,提醒下班啦
(3, self.control_walkers_and_say, ([[[0, False, 150, 60, 520, 0, "下班啦!别忘了打扫卫生。"]]])),
@ -179,6 +176,11 @@ class SceneVLM(Scene):
self.control_walkers_and_say([[0,False,150,end[0],end[1],90,"谢谢!"]])
self.scene_flag += 1
# 获得所有顾客的名字
# print("=================")
# for cus in self.status.walkers:
# print(cus)
# print("=================")
pass
if __name__ == '__main__':