├── w.txt
├── env
├── __init__.py
├── data
│ ├── room_mapping.json
│ ├── semantic_map_tags.json
│ ├── room_sampling_points.json
│ ├── map_room_data.json
│ ├── npc_data.json
│ └── map_receptacle_data.json
├── map_process.py
└── socket_server.py
├── unity
└── start.sh
├── robot
├── example.jpg
├── llm_process.py
├── object_detection.py
├── PRS_Robot.urdf
└── baseline.py
├── clean_port.sh
├── prs_requirements.txt
├── task_evaluation.py
├── prs_demo.py
├── test_demo.ipynb
├── README.md
├── task
└── eval.py
└── document
└── api.md
/w.txt:
--------------------------------------------------------------------------------
1 | sdad
--------------------------------------------------------------------------------
/env/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) PRS. All Rights Reserved
--------------------------------------------------------------------------------
/unity/start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Start the Unity .x86_64 executable
4 | ./PRS.x86_64
5 |
--------------------------------------------------------------------------------
/robot/example.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PRS-Organization/prs-delivery/HEAD/robot/example.jpg
--------------------------------------------------------------------------------
/clean_port.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Find processes with port 8000 and kill them
4 | netstat -ap | grep 8000 | awk '{print $7}' | awk -F '/' '{print $1}' | while read -r pid; do
5 | echo "Killing process with PID: $pid"
6 | kill -9 "$pid"
7 | done
8 |
--------------------------------------------------------------------------------
/prs_requirements.txt:
--------------------------------------------------------------------------------
1 | ansitable==0.9.10
2 | asyncio==3.4.3
3 | cfgv==3.4.0
4 | colored==1.4.4
5 | contourpy==1.2.0
6 | cycler==0.12.1
7 | DateTime==5.5
8 | distlib==0.3.8
9 | filelock==3.13.3
10 | fonttools==4.50.0
11 | identify==2.5.35
12 | kiwisolver==1.4.5
13 | matplotlib==3.8.3
14 | nodeenv==1.8.0
15 | numpy==1.26.4
16 | openai==1.30.5
17 | opencv-python==4.9.0.80
18 | packaging==24.0
19 | pgraph-python==0.6.2
20 | pillow==10.2.0
21 | platformdirs==4.2.0
22 | pre-commit==3.7.0
23 | progress==1.6
24 | pygame==2.5.2
25 | pyparsing==3.1.2
26 | python-dateutil==2.9.0.post0
27 | pytz==2024.1
28 | PyYAML==6.0.1
29 | roboticstoolbox-python==1.1.0
30 | rtb-data==1.0.1
31 | scikit-fmm==2023.4.2
32 | scipy==1.11.1
33 | six==1.16.0
34 | spatialgeometry==1.1.0
35 | spatialmath-python==1.1.9
36 | swift-sim==1.1.0
37 | transformers==4.40.2
38 | typing_extensions==4.10.0
39 | virtualenv==20.25.1
40 | websockets==12.0
41 | zope.interface==6.2
42 |
--------------------------------------------------------------------------------
/task_evaluation.py:
--------------------------------------------------------------------------------
1 | import time
2 |
3 | from env.socket_server import *
4 | import os
5 | from robot.baseline import *
6 |
7 | # Environment initialization
8 | prs = PrsEnv(is_print=1, rendering=1, start_up_mode=1)
9 |
10 | with open(os.path.join('task', 'dataset', 'deliver_task_test_set.json'), 'r') as file:
11 | task_data = json.load(file)
12 | tasks = list(task_data.keys())
13 | print('task:', len(tasks))
14 | for task_i, task_id in enumerate(tasks):
15 | task = task_data[task_id]
16 | task_npc_id = task['npc_id']
17 | start_time = time.time()
18 | instruction, npc_information, data = prs.delivery_task_import(task)
19 | # ------------ robot execution method -----------------
20 | # delivery_execution(prs, instruction, npc_information)
21 |
22 | # ------------ robot execution method -----------------
23 | time.sleep(0.5)
24 | result = prs.delivery_task_evaluate(task, score=1, save=0)
25 | print(result['task_score'])
26 |
27 | # ====== if you want to save the result as json file to submission on Eval AI ==========
28 | # result_save = prs.delivery_task_evaluate(task, score=0, save=1)
29 | # task_results[task_id] = result_save
30 | # with open('task/result/deliver_task_result.json', 'w') as file:
31 | # json.dump(task_results, file, indent=4)
32 | # ---------------------------------------------------------------------------------------
33 | time.sleep(1)
34 | prs.finish_env()
--------------------------------------------------------------------------------
/env/data/room_mapping.json:
--------------------------------------------------------------------------------
1 | {
2 | "0": {
3 | "room0": "storage room 1",
4 | "room1": "energy room",
5 | "room2": "storage room 2",
6 | "room3": "conveyor room"
7 | },
8 | "1": {
9 | "room0": "hall room 2",
10 | "room1": "hall room 1",
11 | "room2": "warm room",
12 | "room3": "lab room 2",
13 | "room4": "lab room 1",
14 | "room5": "medical room 3",
15 | "room6": "server room",
16 | "room7": "storage room",
17 | "room8": "medical room 2",
18 | "room9": "lab room 3",
19 | "room10": "hall room 3",
20 | "room11": "medical room 1",
21 | "room12": "rest room"
22 | },
23 | "2": {
24 | "room0": "bed room 4",
25 | "room1": "bed room 10",
26 | "room2": "bed room 8",
27 | "room3": "bed room 2",
28 | "room4": "bed room 11",
29 | "room5": "bed room 5",
30 | "room6": "bed room 6",
31 | "room7": "kitchen room",
32 | "room8": "bed room 7",
33 | "room9": "bed room 9",
34 | "room10": "bed room 3",
35 | "room11": "bed room 1",
36 | "room12": "bed room 0",
37 | "room13": "hall room 1",
38 | "room14": "gym room",
39 | "room15": "office room 1",
40 | "room16": "hall room 3",
41 | "room17": "office room 2",
42 | "room18": "rest room",
43 | "room19": "office space",
44 | "room20": "storage room",
45 | "room21": "hall room 2",
46 | "room22": "living room",
47 | "room23": "conference room"
48 | }
49 | }
--------------------------------------------------------------------------------
/prs_demo.py:
--------------------------------------------------------------------------------
1 | from env.socket_server import *
2 | import matplotlib.pyplot as plt
3 | # from env.socket_server import server
4 | # import sys
5 |
6 | if __name__ == '__main__':
7 | # Environment initialization
8 | prs = PrsEnv(is_print=1, rendering=1, start_up_mode=1)
9 | prs.npc_start(5)
10 | # How many NPCs are there
11 | prs.agent.initial_pose()
12 | prs.agent.go_to_destination(tar_location='kitchen')
13 | prs.agent.rotate_right(degree=-30)
14 | # prs.agent.direction_adjust(position=(0, 0, 0))
15 | # print(prs.agent.query_near_objects())
16 | # print(len(prs.agent.get_room_area('kitchen room')))
17 | # print(prs.agent.get_receptacles_within_room(room_name='kitchen room'))
18 | # prs.agent.goto_receptacle(room='kitchen room', recepacle=0, random=0)
19 | # print(prs.agent.object_information_query(obj_id=0))
20 |
21 | # rgb = prs.agent.head_camera_look_at()
22 | # rgb = prs.agent.observation(degree=0, camera=0)
23 | # view = prs.agent.site_view(pos=(0, 0, 0))
24 | # depth = prs.agent.get_depth()
25 | arr, tags = prs.agent.get_segmentation(camera_type=0, decode=1)
26 | print(tags)
27 | plt.imshow(arr)
28 | plt.show()
29 |
30 | marked_arr = np.zeros_like(arr)
31 | for tag in tags:
32 | if 'apple' in tags[tag].lower():
33 | aaa = tag
34 | break
35 | marked_arr[arr == aaa] = 1
36 | prs.agent.object_interaction(marked_arr, manipulaton=1)
37 | prs.agent.goto_target_goal((2, 130, 120), position_mode=1)
38 | # robot navigate to floor3 point (130, 120)
39 | map_room = prs.server.maps.floor3
40 |
41 | time.sleep(20)
42 | # ------------ end ------------
43 | prs.finish_env()
--------------------------------------------------------------------------------
/test_demo.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "id": "417071ec",
7 | "metadata": {},
8 | "outputs": [
9 | {
10 | "name": "stdout",
11 | "output_type": "stream",
12 | "text": [
13 | "pygame 2.5.2 (SDL 2.28.3, Python 3.11.5)\n",
14 | "Hello from the pygame community. https://www.pygame.org/contribute.html\n",
15 | "PRS environment beta is starting without interaction\n",
16 | "Please open the Unity program (start.sh)\n",
17 | "PRS challenge task and benchmark come soon!\n"
18 | ]
19 | }
20 | ],
21 | "source": [
22 | "from socket_server import *\n",
23 | "# Environment initialization\n",
24 | "prs = PrsEnv(is_print=0, not_test_mode=0)"
25 | ]
26 | },
27 | {
28 | "cell_type": "code",
29 | "execution_count": null,
30 | "id": "19a9dd9f",
31 | "metadata": {},
32 | "outputs": [],
33 | "source": [
34 | "# npc behavior\n",
35 | "prs.npc_start(5)"
36 | ]
37 | },
38 | {
39 | "cell_type": "code",
40 | "execution_count": null,
41 | "id": "7d358a1a",
42 | "metadata": {},
43 | "outputs": [],
44 | "source": [
45 | "# action sequence of robot\n"
46 | ]
47 | },
48 | {
49 | "cell_type": "code",
50 | "execution_count": null,
51 | "id": "d2f268f3",
52 | "metadata": {},
53 | "outputs": [],
54 | "source": [
55 | "prs.finish_env()"
56 | ]
57 | },
58 | {
59 | "cell_type": "code",
60 | "execution_count": null,
61 | "id": "bed19f72",
62 | "metadata": {},
63 | "outputs": [],
64 | "source": []
65 | }
66 | ],
67 | "metadata": {
68 | "kernelspec": {
69 | "display_name": "Python 3 (ipykernel)",
70 | "language": "python",
71 | "name": "python3"
72 | },
73 | "language_info": {
74 | "codemirror_mode": {
75 | "name": "ipython",
76 | "version": 3
77 | },
78 | "file_extension": ".py",
79 | "mimetype": "text/x-python",
80 | "name": "python",
81 | "nbconvert_exporter": "python",
82 | "pygments_lexer": "ipython3",
83 | "version": "3.11.5"
84 | }
85 | },
86 | "nbformat": 4,
87 | "nbformat_minor": 5
88 | }
89 |
--------------------------------------------------------------------------------
/robot/llm_process.py:
--------------------------------------------------------------------------------
1 | # import openai
2 | from matplotlib import pyplot as plt
3 | from openai import OpenAI
4 | # from zhipuai import ZhipuAI
5 | import cv2
6 | import base64
7 | import io
8 | from PIL import Image, ImageDraw
9 | from robot.object_detection import *
10 |
11 |
12 | client = OpenAI(
13 | # api_key=os.environ.get("OPENAI_API_KEY")
14 | )
15 | grounding_dino = GroundingDino()
16 |
17 |
18 | def object_detect_module(image, text='the human'):
19 | if text[-1] != '.':
20 | text = text + '.'
21 | result = grounding_dino.predict(image, text)
22 | return result
23 |
24 |
25 | def lmm_interaction(content, image):
26 | image = Image.fromarray(image)
27 | image_file = io.BytesIO()
28 | image.save(image_file, format='PNG')
29 | encoded_string = base64.b64encode(image_file.getvalue()).decode()
30 | response = client.chat.completions.create(
31 | model="gpt-4o", # Fill in the name of the model that needs to be called
32 | messages=[
33 | {
34 | "role": "user",
35 | "content": [
36 | {
37 | "type": "text",
38 | "text": content
39 | },
40 | {
41 | "type": "image_url",
42 | "image_url": {
43 | "url": f"data:image/jpeg;base64,{encoded_string}"
44 | }
45 | }
46 | ]
47 | }
48 | ],
49 | max_tokens=300
50 | )
51 | res = response.choices[0].message.content
52 | return res
53 |
54 |
55 | def llm_interaction(content='Hello World!', temperature=0.9):
56 | response = client.chat.completions.create(
57 | model="gpt-4-turbo", # gpt-3.5-turbo-0125
58 | messages=[
59 | {"role": "user", "content": content}
60 | ],
61 | )
62 | res = response.choices[0].message.content
63 | return res
64 |
65 |
66 | if __name__ == '__main__':
67 | im = cv2.imread('example.jpg')
68 | # print(im.shape)
69 | mat = object_detect_module(im, 'the water bottle.')
70 | plt.imshow(mat)
71 | plt.show()
--------------------------------------------------------------------------------
/robot/object_detection.py:
--------------------------------------------------------------------------------
1 | from matplotlib import pyplot as plt
2 | from transformers import AutoProcessor, GroundingDinoForObjectDetection
3 | from PIL import Image
4 | import requests
5 | import torch
6 | import numpy as np
7 | import cv2
8 |
9 |
10 | class GroundingDino(object):
11 | def __init__(self):
12 | self.processor = AutoProcessor.from_pretrained("IDEA-Research/grounding-dino-tiny")
13 | self.model = GroundingDinoForObjectDetection.from_pretrained("IDEA-Research/grounding-dino-tiny")
14 |
15 | def predict(self, rgb_image, text):
16 | image = Image.fromarray(rgb_image)
17 | inputs = self.processor(images=image, text=text, return_tensors="pt")
18 | outputs = self.model(**inputs)
19 | # convert outputs (bounding boxes and class logits) to COCO API
20 | target_sizes = torch.tensor([image.size[::-1]])
21 | results = self.processor.image_processor.post_process_object_detection(
22 | outputs, threshold=0.35, target_sizes=target_sizes
23 | )[0]
24 | item, score_max = None, 0
25 | for score, label, box in zip(results["scores"], results["labels"], results["boxes"]):
26 | box = [round(i, 2) for i in box.tolist()]
27 | # print(f"Detected {label.item()} with confidence " f"{round(score.item(), 3)} at location {box}")
28 | if round(score.item(), 3) > score_max:
29 | score_max = round(score.item(), 3)
30 | item = box
31 | if item is None:
32 | return None
33 | h, w = rgb_image.shape[0], rgb_image.shape[1]
34 | box = item
35 | top_left = (round(box[0]), round(box[1]))
36 | bottom_right = (round(box[2]), round(box[3]))
37 | # print(bottom_right, top_left, h, w)
38 | cv2.rectangle(rgb_image, top_left, bottom_right, (255, 0, 0), 2)
39 | mat = np.zeros((h, w))
40 | mat[top_left[1]:bottom_right[1] + 1, top_left[0]:bottom_right[0] + 1] = 1
41 | return mat
42 |
43 |
44 | if __name__ == "__main__":
45 | grounding_dino = GroundingDino()
46 | url = "http://images.cocodataset.org/val2017/000000039769.jpg"
47 | pil_image = Image.open(requests.get(url, stream=True).raw)
48 | image = np.array(pil_image)
49 | res = grounding_dino.predict(image, 'cat.')
50 | plt.imshow(res)
51 | plt.show()
52 | print(np.sum(res) / (480 * 640))
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [//]: # (# PRS-Test)
2 | # Human-centered In-building Embodied Delivery Benchmark
3 | ## [PRS Challenge](https://prsorg.github.io/challenge) hosted on [CVPR 2024 Embodied AI Workshop](https://embodied-ai.org/)
4 |
5 | ## Quick Start & Installation
6 |
7 | Follow these steps to quickly set up and run the PRS delivery task version:
8 |
9 | 1. Clone the PRS delivery repository:
10 | ```
11 | git clone https://github.com/PRS-Organization/prs-delivery.git
12 | ```
13 | 2. Ensure you have a Python virtual environment (Python version >= 3.9) activated.
14 |
15 | ```
16 | conda create -n prs python=3.9
17 | conda activate mvp
18 | ```
19 |
20 | 3. Install the required Python packages:
21 | ```
22 | pip install -r prs_requirements.txt
23 | ```
24 | 4. Download the Unity executable file (for Ubuntu, Windows, and Mac) from [PRS executable program](https://docs.google.com/forms/d/e/1FAIpQLScrk25iSnnmOH8cj4eqD8lcALcj1Cx1bSiiTsw9q9DzvWnCig/viewform?usp=sf_link). If you are using the macOS or Windows version, you need to modify some of the environment data paths in ```StreamingAssets``` folder and executable application paths.
25 |
26 | 5. Extract the `PRS_Ubuntu_x.x.x.zip` file into the `unity` folder:
27 | ```
28 | cd unity
29 | unzip PRS_Ubuntu_0.3.0.zip
30 | ```
31 | Note that the contents after unzipping should be placed in `unity` folder, and give `unity` folder file permissions:
32 | ```
33 | sudo chmod 777 -R unity
34 | ```
35 | 6. Start running the demo:
36 | ```
37 | python prs_demo.py
38 | ```
39 | or start with only unity application:
40 | ```
41 | bash ./unity/start.sh
42 | ```
43 | 7. If you encounter a port occupation error, clean up occupied ports:
44 | ```
45 | bash clean_port.sh
46 | ```
47 | 8. Manual start: class initialization parameter is ```PrsEnv(start_up_mode=0)```, after running the Python script, you can open another terminal and execute ```unity/start.sh``` or directly run `unity/PRS.x86_64`.
48 |
49 | 9. Runing on the headless server without rendering initialization ```PrsEnv(rendering=0)```.
50 |
51 | 10. Wait a few seconds for Unity to render the graphics. In Unity, you can control the camera movement using the keyboard keys W, A, S, D, Q, and E. Robot control using the keyboard keys I R, F J, O P, K L, G H, N M, Z X, V B. Switch perspectives using C, accelerate time using numeric keypad 123456789.
52 |
53 | 11. To close the demo, first close the Unity program (or press Esc), then stop the Python program (Ctrl+C or Ctrl+Z), and finally run:
54 | ```
55 | bash clean_port.sh
56 | ```
57 | Note: Or use ```prs.finish_env()``` to end PRS environment in Python script.
58 |
59 | 12. To get started with the Delivery Task Dataset, simply run the following command in your terminal:
60 |
61 | ```
62 | python task_evaluation.py
63 | ```
64 | This will initiate the evaluation process using delivery task dataset.
65 |
66 | ## Baseline Method
67 |
68 | If you want to run baseline method, please install ```transformers==4.40.2 ```, ```torch==2.0.1```, ```openai==1.30.5```. And fill in the API-key in the ```robot\llm_process.py```.
69 | We utilize [Grounding DINO](https://github.com/IDEA-Research/GroundingDINO) to achieve zero-shot object detection with text prompt, you can replace it with others, e.g. [Grounded SAM](https://github.com/IDEA-Research/Grounded-Segment-Anything).
70 |
71 | Make```delivery_execution(prs, instruction, npc_information)``` available in ```task_evaluation.py``` on line 20.
72 |
73 | The main process of the baseline method is in ```./robot/baseline.py```, ```./robot/object_detection.py``` is visual detection, and ```./robot/llm_process.py``` is the LMM and LLM application.
74 |
75 | Save the result and submit the ```result.json``` to [Eval AI leaderboard](https://eval.ai/web/challenges/challenge-page/2313/overview).
76 |
77 | ## More API Guidance
78 | [PRS Platform API](document/api.md)
79 |
80 |
81 |
82 | [//]: # (input your API key for LLM service)
83 |
84 | [//]: # (download vision model for object detect)
85 |
86 | [//]: # (python task evaluation py)
87 |
88 | [//]: # (save the result (save=1))
89 |
90 | [//]: # (submit the json to Eval AI leaderboard)
91 |
92 | [//]: # (cite us contact us project homepage)
93 |
94 | [//]: # (long term leaderboard for delivery)
95 |
--------------------------------------------------------------------------------
/robot/PRS_Robot.urdf:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
--------------------------------------------------------------------------------
/task/eval.py:
--------------------------------------------------------------------------------
1 | import random
2 | import datetime
3 | import numpy as np
4 | import json
5 | import math
6 |
7 |
8 | def calculate_distance(point1, point2):
9 | # NumPy array
10 | try:
11 | point1_array = np.array([point1['x'], point1['y'], point1['z']], dtype=float)
12 | except:
13 | point1_array = np.array([point1[0], point1[1], point1[2]], dtype=float)
14 | try:
15 | point2_array = np.array([point2['x'], point2['y'], point2['z']], dtype=float)
16 | except:
17 | point2_array = np.array([point2[0], point2[1], point2[2]], dtype=float)
18 | try:
19 | # distance = np.linalg.norm(point2_array - point1_array)
20 | distance = math.sqrt(sum((a - b) ** 2 for a, b in zip(point1_array, point2_array)))
21 | except:
22 | distance = 99999
23 | return distance
24 |
25 |
26 | def delivery_task_score(result_data, task_id=0):
27 | task_res, res_grasp, res_find, human_find, res_deliver = 0, 0, 0, 0, 0
28 | start_t = datetime.datetime.fromisoformat(result_data['start_time'])
29 | end_t = datetime.datetime.fromisoformat(result_data['end_time'])
30 | time_cost = end_t - start_t
31 | seconds_cost = (end_t - start_t).total_seconds()
32 | minutes_cost = time_cost.total_seconds() / 60
33 | # 1. target find, 2. grasp target, 3. target object dis, 4. deliver
34 | if result_data['agent_object_name'] is not None:
35 | if result_data['tar_object_name'] == result_data['agent_object_name']:
36 | res_grasp = 1
37 | else:
38 | if result_data['target_object_type'] in result_data['agent_object_name']:
39 | res_grasp = 0.5
40 | hr_dis = calculate_distance(result_data['npc_position'], result_data['agent_position'])
41 | if hr_dis < 3:
42 | human_find = 1
43 | elif hr_dis < 5:
44 | human_find = 0.5
45 | res_deliver = human_find * res_grasp
46 | task_res = res_grasp + res_find + res_deliver + human_find
47 | task_result = {'sub_result': {'grasp': res_grasp, 'object_find': res_find,
48 | 'deliver': res_deliver, 'human_find': human_find},
49 | 'result': task_res, 'time': minutes_cost}
50 | return task_result
51 |
52 |
53 | def evaluate(test_annotation_file, user_submission_file, phase_codename, **kwargs):
54 | print("Starting Evaluation.....")
55 | """
56 | Evaluates the submission for a particular challenge phase and returns score
57 | Arguments:
58 |
59 | `test_annotations_file`: Path to test_annotation_file on the server
60 | `user_submission_file`: Path to file submitted by the user
61 | `phase_codename`: Phase to which submission is made
62 |
63 | `**kwargs`: keyword arguments that contains additional submission
64 | metadata that challenge hosts can use to send slack notification.
65 | You can access the submission metadata
66 | with kwargs['submission_metadata']
67 |
68 | Example: A sample submission metadata can be accessed like this:
69 | >>> print(kwargs['submission_metadata'])
70 | {
71 | 'status': u'running',
72 | 'when_made_public': None,
73 | 'participant_team': 5,
74 | 'input_file': 'https://abc.xyz/path/to/submission/file.json',
75 | 'execution_time': u'123',
76 | 'publication_url': u'ABC',
77 | 'challenge_phase': 1,
78 | 'created_by': u'ABC',
79 | 'stdout_file': 'https://abc.xyz/path/to/stdout/file.json',
80 | 'method_name': u'Test',
81 | 'stderr_file': 'https://abc.xyz/path/to/stderr/file.json',
82 | 'participant_team_name': u'Test Team',
83 | 'project_url': u'http://foo.bar',
84 | 'method_description': u'ABC',
85 | 'is_public': False,
86 | 'submission_result_file': 'https://abc.xyz/path/result/file.json',
87 | 'id': 123,
88 | 'submitted_at': u'2017-03-20T19:22:03.880652Z'
89 | }
90 | """
91 | with open(test_annotation_file, 'r') as file:
92 | task_data = json.load(file)
93 | with open(user_submission_file, 'r') as file:
94 | task_submission = json.load(file)
95 | task_r, grasp_r, human_r, time_used = 0, 0, 0, 0
96 | number, tasks = len(list(task_data)), []
97 | for task_id, task in task_submission.items():
98 | print(task_id)
99 | if task_id in tasks:
100 | continue
101 | else:
102 | tasks.append(task)
103 | task_result = delivery_task_score(task)
104 | # task_result = {'sub_result': {'grasp': res_grasp, 'object_find': res_find,
105 | # 'deliver': res_deliver, 'human_find': human_find},
106 | # 'result': task_res, 'time': minutes_cost}
107 | if task_result['time'] > 10:
108 | continue
109 | task_r += int(task_result['result']/4)
110 | grasp_r += task_result['sub_result']['grasp']
111 | human_r += task_result['sub_result']['human_find']
112 | time_used += task_result['time']
113 | print(number, len(tasks))
114 | task_r = task_r / float(number)
115 | grasp_r = grasp_r / float(number)
116 | human_r = human_r / float(number)
117 | time_used = time_used / float(len(tasks))
118 |
119 | output = {}
120 | if phase_codename == "dev":
121 | # print("Evaluating for Dev Phase")
122 | # ["Task SR", "Object Manipulation SR", "Human Search SR", "Time Used"]
123 | output["result"] = [
124 | {
125 | "Delivery_dataset": {
126 | "Task SR": task_r,
127 | "Object Manipulation SR": grasp_r,
128 | "Human Search SR": human_r,
129 | "Time Used": time_used
130 | }
131 | }
132 | ]
133 | # To display the results in the result file
134 | output["submission_result"] = output["result"][0]["Delivery_dataset"]
135 | print("Completed evaluation for Dev Phase")
136 | elif phase_codename == "test":
137 | # print("Evaluating for Test Phase")
138 | output["result"] = [
139 | {
140 | "Delivery_dataset": {
141 | "Task SR": task_r,
142 | "Object Manipulation SR": grasp_r,
143 | "Human Search SR": human_r,
144 | "Time Used": time_used
145 | }
146 | }
147 | ]
148 | # To display the results in the result file
149 | output["submission_result"] = output["result"][0]["Delivery_dataset"]
150 | print("Completed evaluation for Test Phase")
151 | return output
152 |
153 |
154 | if __name__ == "__main__":
155 | res = evaluate('dataset/deliver_task_test_set.json',
156 | 'D:\\code\\prs_develop\\prs_system_git_push_version\\task\\result\\deliver_task_5_19_result.json'
157 | , 'test')
158 | print(res)
--------------------------------------------------------------------------------
/document/api.md:
--------------------------------------------------------------------------------
1 | # PRS API
2 | We provide **API** that includes various functions:
3 | - [Environment API](#environment-api)
4 | - [Task API](#task-api)
5 | - [Robot API](#robot-api)
6 | - [Map API](#map-and-position-api)
7 | - [NPC API](#npc-api)
8 |
9 | ## Environment API
10 | Operations: Accelerate, Terminate, Initiate
11 |
12 | Instantiate environment class
13 | ```
14 | prs = PrsEnv()
15 | ```
16 | Start autonomous activities for NPCs, specifying the number of activated NPCs
17 | ```
18 | prs.npc_start(3)
19 | ```
20 | Accelerate the scene simulation by specifying the speed multiplier
21 | ```
22 | prs.sim_speed(2)
23 | ```
24 | set environment time
25 | ```
26 | prs.env_time.set_time(2024, 6, 1, 9, 0)
27 | ```
28 | Terminate the environment and end the process
29 | ```
30 | prs.finish_env()
31 | ```
32 |
33 | ## Task API
34 |
35 | Initialize the task program, "task" stands for JSON content of a delivery task
36 | ```
37 | prs.delivery_task_import(task)
38 | ```
39 | Evaluate the task result: score=1 represents result calculation, and save = 1 will return the result dict for saving the JSON file
40 | ```
41 | prs.delivery_task_evaluate(task, score=1, save=0)
42 | ```
43 | ## Robot API
44 |
45 | Retrieve vision data, specifying the camera type (0 for head, 1 for hand)
46 | ```
47 | prs.agent.observation_camera(camera_type=0)
48 | ```
49 | Move the robot to a target location, specifying the position mode (0 for world, 1 for grid map)
50 | ```
51 | prs.agent.goto_target_goal((2, 130, 120), position_mode=1)
52 | ```
53 | Retrieve robot position information, returning position (pos) and detailed information (info)
54 | ```
55 | prs.agent.pos_query()
56 | ```
57 | Rotate the robot, specifying the degree of rotation (positive for right, negative for left)
58 | ```
59 | prs.agent.rotate_right(degree=30)
60 | ```
61 | Control robot joints, specifying the joint ID and target
62 | ```
63 | prs.agent.joint_control(joint_id=1, target=20)
64 | ```
65 | Adjust robot direction alignment based on input coordinates
66 | ```
67 | prs.agent.direction_adjust(position=(22.38, 0.1, -0.17))
68 | ```
69 | Perform inverse kinematics (IK) for the robot, specifying relative coordinates
70 | ```
71 | prs.agent.ik_process(x=0, y=1, z=0.1)
72 | ```
73 | Calculate 6 Degrees of Freedom (6-DoF) IK for the robot, specifying the target coordinates and rotation matrix (yaw, pitch, roll)
74 | ```
75 | prs.agent.input_pos(prs.agent.robot, x=0.2, y=0, z=0.75, phi=0, theta=1.25, psi=0, plot=0)
76 | ```
77 | Move the robot forward by specifying the distance
78 | ```
79 | prs.agent.move_forward(dis=1.0)
80 | ```
81 | Navigate to a specific destination, specifying the location name
82 | ```
83 | prs.agent.go_to_destination('kitchen')
84 | ```
85 | Retrieve the latest map
86 | ```
87 | prs.agent.get_all_map()
88 | ```
89 | Calculate IK for relative coordinates and target values, specifying world coordinates
90 | ```
91 | prs.agent.ik_calculation((-10.1, 0.1, 1.6))
92 | ```
93 | Calculate IK target, specifying relative coordinates
94 | ```
95 | prs.agent.ik_process(0.25, 0.1, 0.79)
96 | ```
97 | Control robot arms, specifying joint target values
98 | ```
99 | prs.agent.arm_control([0, 0, 0, 0, 0])
100 | ```
101 | Grab an object, specifying the object's ID
102 | ```
103 | prs.agent.grasp_object(17)
104 | ```
105 | Move towards the vicinity of an object, specifying the object ID or functional feature
106 | ```
107 | prs.agent.go_to_target_object(feature='Seat')
108 | ```
109 | Walk towards and grab the target object
110 | ```
111 | prs.agent.goto_and_grasp('apple')
112 | ```
113 | Release the held object
114 | ```
115 | depth_m = prs.agent.get_depth(0)
116 | ```
117 | Retrieve depth information, specifying mode (0 for head camera, 1 for hand camera)
118 | ```
119 | prs.agent.get_depth()
120 | ```
121 | Retrieve camera semantic segmentation, specifying mode (0 for head camera, 1 for hand camera), tags contain object information
122 | ```
123 | seg, tags = prs.agent.get_segmentation(0)
124 | ```
125 | Head camera twisted downwards
126 | ```
127 | prs.agent.joint_control(joint_id=4, target=20)
128 | ```
129 | Using the camera to observe the surroundings with the given angle
130 | ```
131 | prs.agent.observation(degree=0, camera=0, up_down=30)
132 | ```
133 |
134 | "Request Visual Interaction"
135 |
136 | ```
137 | prs.agent.object_interaction(input_matrix=array, manipulaton=1, type=0)
138 | ```
139 | [This function requests an interaction with the visual system.
140 | Input: A two-dimensional matrix marking the target and the operation type:
141 | 0: recognize
142 | 1: grasp
143 | 2: approach target
144 | 3, etc.]
145 |
146 | [//]: # (prs.agent.request_interaction())
147 | [//]: # (prs.agent.interaction())
148 |
149 | Robot pose adjustment
150 | ```
151 | prs.agent.initial_pose()
152 | ```
153 |
154 | Go to receptacle of the room
155 | ```
156 | prs.agent.goto_receptacle(room='office', recepacle='table', random=1)
157 | ```
158 |
159 | Look at somewhere (head camera)
160 | ```
161 | prs.agent.head_camera_look_at((1, 122, 54))
162 | ```
163 |
164 | Estimating distance through mask
165 | ```
166 | tar_distance, view_angle = prs.agent.depth_estimation(target_mask, depth_m, field_of_view=90)
167 | ```
168 |
169 | Calculate accessible locations based on target distance and observation angle
170 | ```
171 | position = prs.agent.target_direction(degree=camera_degree, distance=tar_distance, target_degree_view=view_angle)
172 | ```
173 |
174 | [//]: # (```)
175 |
176 | [//]: # (prs.agent.head_camera_look_at)
177 |
178 | [//]: # (```)
179 | ## Map and Position API
180 |
181 | Determine the area based on world coordinates, returning the room or None
182 | ```
183 | prs.objs_data.point_determine((15.7, -5.1, -19.5))
184 | ```
185 | Retrieve information from the 2D grid map, specifying world coordinates [-10.1, 0.1, -6.1], output includes floor, map_i, map_j, and obstacle status
186 | ```
187 | prs.server.maps.get_point_info({'x': -10.1, 'y': 0.1, 'z': -6.1})
188 | ```
189 | Retrieve world position based on floor, map_i, and map_j coordinates
190 | ```
191 | prs.server.maps.get_world_position(1, 89, 108)
192 | ```
193 | Retrieve 2D grid maps for floors 1, 2, and 3
194 | ```
195 | map1, map2, map3 = prs.server.maps.floor1, prs.server.maps.floor2, prs.server.maps.floor3
196 | ```
197 | Retrieve the latest map
198 | ```
199 | prs.agent.get_all_map()
200 | ```
201 | Parse object information based on instructions, querying a specific object
202 | ```
203 | obj_list = prs.objs_data.object_parsing(instruction, ['apple'])
204 | ```
205 | Global query for an object's ID, specifying the object's name
206 | ```
207 | obj_list = prs.objs_data.object_query(['apple'])
208 | ```
209 | Query object information based on ID
210 | ```
211 | prs.object_query(obj_id=100)
212 | ```
213 |
214 | ## NPC API
215 |
216 | Execute actions for NPCs based on action IDs, including looping actions, interactive actions, and performance actions
217 | ```
218 | prs.npcs[0].npc_action(tar_action='stand')
219 | ```
220 | Retrieve photos around the NPC, from the camera perspective above the head
221 | ```
222 | prs.npcs[0].observation_surrounding()
223 | ```
224 | Retrieve the current NPC's position, returning position and detailed NPC information
225 | ```
226 | prs.npcs[0].where_npc()
227 | ```
228 | NPC move to a specific place based on preset location lists
229 | ```
230 | prs.npcs[0].go_to_place()
231 | ```
232 | Retrieve detailed information about the NPC, including position and other information
233 | ```
234 | pos, npc_info = prs.npcs[0].query_information()
235 | ```
236 | Move towards the vicinity of an object, specifying the distance range to the target
237 | ```
238 | res, obj = prs.npcs[0].go_to_object('Seat')
239 | ```
--------------------------------------------------------------------------------
/env/data/semantic_map_tags.json:
--------------------------------------------------------------------------------
1 | {
2 | "0": {
3 | "0": "obstacles",
4 | "1": "accessible area",
5 | "4": [
6 | "room0"
7 | ],
8 | "5": [
9 | "room1"
10 | ],
11 | "6": [
12 | "room2"
13 | ],
14 | "7": [
15 | "room3"
16 | ]
17 | },
18 | "1": {
19 | "0": "obstacles",
20 | "1": "accessible area",
21 | "4": [
22 | "room10",
23 | "reception counter"
24 | ],
25 | "5": [
26 | "room10",
27 | "table"
28 | ],
29 | "6": [
30 | "room10",
31 | "table"
32 | ],
33 | "7": [
34 | "room10",
35 | "table"
36 | ],
37 | "8": [
38 | "room10",
39 | "table"
40 | ],
41 | "9": [
42 | "room0",
43 | "table"
44 | ],
45 | "10": [
46 | "room0",
47 | "table"
48 | ],
49 | "11": [
50 | "room1",
51 | "polygon table"
52 | ],
53 | "12": [
54 | "room5",
55 | "desk"
56 | ],
57 | "13": [
58 | "room0"
59 | ],
60 | "14": [
61 | "room1"
62 | ],
63 | "15": [
64 | "room2"
65 | ],
66 | "16": [
67 | "room3"
68 | ],
69 | "17": [
70 | "room4"
71 | ],
72 | "18": [
73 | "room5"
74 | ],
75 | "19": [
76 | "room6"
77 | ],
78 | "20": [
79 | "room7"
80 | ],
81 | "21": [
82 | "room8"
83 | ],
84 | "22": [
85 | "room9"
86 | ],
87 | "23": [
88 | "room10"
89 | ],
90 | "24": [
91 | "room11"
92 | ],
93 | "25": [
94 | "room12"
95 | ]
96 | },
97 | "2": {
98 | "0": "obstacles",
99 | "1": "accessible area",
100 | "4": [
101 | "room0",
102 | "table"
103 | ],
104 | "5": [
105 | "room0",
106 | "bed"
107 | ],
108 | "6": [
109 | "room1",
110 | "table"
111 | ],
112 | "7": [
113 | "room1",
114 | "bed"
115 | ],
116 | "8": [
117 | "room2",
118 | "table"
119 | ],
120 | "9": [
121 | "room2",
122 | "bed"
123 | ],
124 | "10": [
125 | "room3",
126 | "table"
127 | ],
128 | "11": [
129 | "room3",
130 | "bed"
131 | ],
132 | "12": [
133 | "room15",
134 | "desk"
135 | ],
136 | "13": [
137 | "room16",
138 | "table"
139 | ],
140 | "14": [
141 | "room16",
142 | "table"
143 | ],
144 | "15": [
145 | "room16",
146 | "table"
147 | ],
148 | "16": [
149 | "room16",
150 | "reception counter"
151 | ],
152 | "17": [
153 | "room16",
154 | "table"
155 | ],
156 | "18": [
157 | "room19",
158 | "side table"
159 | ],
160 | "19": [
161 | "room19",
162 | "desk"
163 | ],
164 | "20": [
165 | "room19",
166 | "desk"
167 | ],
168 | "21": [
169 | "room19",
170 | "desk"
171 | ],
172 | "22": [
173 | "room19",
174 | "desk"
175 | ],
176 | "23": [
177 | "room19",
178 | "desk"
179 | ],
180 | "24": [
181 | "room19",
182 | "desk"
183 | ],
184 | "25": [
185 | "room19",
186 | "desk"
187 | ],
188 | "26": [
189 | "room19",
190 | "desk"
191 | ],
192 | "27": [
193 | "room22",
194 | "dinner counter"
195 | ],
196 | "28": [
197 | "room22",
198 | "coffee table"
199 | ],
200 | "29": [
201 | "room4",
202 | "table"
203 | ],
204 | "30": [
205 | "room4",
206 | "bed"
207 | ],
208 | "31": [
209 | "room5",
210 | "table"
211 | ],
212 | "32": [
213 | "room5",
214 | "bed"
215 | ],
216 | "33": [
217 | "room17",
218 | "desk"
219 | ],
220 | "34": [
221 | "room6",
222 | "table"
223 | ],
224 | "35": [
225 | "room6",
226 | "bed"
227 | ],
228 | "36": [
229 | "room7",
230 | "small table"
231 | ],
232 | "37": [
233 | "room7",
234 | "table"
235 | ],
236 | "38": [
237 | "room7",
238 | "kitchen counter"
239 | ],
240 | "39": [
241 | "room7",
242 | "kitchen wardrobe"
243 | ],
244 | "40": [
245 | "room7",
246 | "dinner counter"
247 | ],
248 | "41": [
249 | "room21",
250 | "table"
251 | ],
252 | "42": [
253 | "room21",
254 | "table"
255 | ],
256 | "43": [
257 | "room8",
258 | "table"
259 | ],
260 | "44": [
261 | "room8",
262 | "bed"
263 | ],
264 | "45": [
265 | "room23",
266 | "meeting table large"
267 | ],
268 | "46": [
269 | "room9",
270 | "table"
271 | ],
272 | "47": [
273 | "room9",
274 | "bed"
275 | ],
276 | "48": [
277 | "room14",
278 | "furnituregymdesk"
279 | ],
280 | "49": [
281 | "room10",
282 | "table"
283 | ],
284 | "50": [
285 | "room10",
286 | "bed"
287 | ],
288 | "51": [
289 | "room11",
290 | "table"
291 | ],
292 | "52": [
293 | "room11",
294 | "bed"
295 | ],
296 | "53": [
297 | "room13",
298 | "polygon table"
299 | ],
300 | "54": [
301 | "room12",
302 | "table"
303 | ],
304 | "55": [
305 | "room12",
306 | "bed"
307 | ],
308 | "56": [
309 | "room0"
310 | ],
311 | "57": [
312 | "room1"
313 | ],
314 | "58": [
315 | "room2"
316 | ],
317 | "59": [
318 | "room3"
319 | ],
320 | "60": [
321 | "room4"
322 | ],
323 | "61": [
324 | "room5"
325 | ],
326 | "62": [
327 | "room6"
328 | ],
329 | "63": [
330 | "room7"
331 | ],
332 | "64": [
333 | "room8"
334 | ],
335 | "65": [
336 | "room9"
337 | ],
338 | "66": [
339 | "room10"
340 | ],
341 | "67": [
342 | "room11"
343 | ],
344 | "68": [
345 | "room12"
346 | ],
347 | "69": [
348 | "room13"
349 | ],
350 | "70": [
351 | "room14"
352 | ],
353 | "71": [
354 | "room15"
355 | ],
356 | "72": [
357 | "room16"
358 | ],
359 | "73": [
360 | "room17"
361 | ],
362 | "74": [
363 | "room18"
364 | ],
365 | "75": [
366 | "room19"
367 | ],
368 | "76": [
369 | "room20"
370 | ],
371 | "77": [
372 | "room21"
373 | ],
374 | "78": [
375 | "room22"
376 | ],
377 | "79": [
378 | "room23"
379 | ]
380 | }
381 | }
--------------------------------------------------------------------------------
/env/data/room_sampling_points.json:
--------------------------------------------------------------------------------
1 | {
2 | "0_storage room 1": [
3 | [
4 | 0,
5 | 5,
6 | 69
7 | ],
8 | [
9 | 0,
10 | 42,
11 | 36
12 | ]
13 | ],
14 | "0_energy room": [
15 | [
16 | 0,
17 | 0,
18 | 0
19 | ],
20 | [
21 | 0,
22 | 138,
23 | 72
24 | ]
25 | ],
26 | "0_storage room 2": [
27 | [
28 | 0,
29 | 5,
30 | 140
31 | ],
32 | [
33 | 0,
34 | 42,
35 | 108
36 | ]
37 | ],
38 | "0_conveyor room": [
39 | [
40 | 0,
41 | 67,
42 | 201
43 | ],
44 | [
45 | 0,
46 | 80,
47 | 208
48 | ]
49 | ],
50 | "1_hall room 2": [
51 | [
52 | 1,
53 | 141,
54 | 187
55 | ],
56 | [
57 | 1,
58 | 152,
59 | 178
60 | ]
61 | ],
62 | "1_hall room 1": [
63 | [
64 | 1,
65 | 104,
66 | 190
67 | ],
68 | [
69 | 1,
70 | 111,
71 | 179
72 | ]
73 | ],
74 | "1_warm room": [
75 | [
76 | 1,
77 | 122,
78 | 134
79 | ],
80 | [
81 | 1,
82 | 112,
83 | 132
84 | ]
85 | ],
86 | "1_lab room 2": [
87 | [
88 | 1,
89 | 82,
90 | 207
91 | ],
92 | [
93 | 1,
94 | 83,
95 | 217
96 | ]
97 | ],
98 | "1_lab room 1": [
99 | [
100 | 1,
101 | 114,
102 | 207
103 | ],
104 | [
105 | 1,
106 | 116,
107 | 217
108 | ]
109 | ],
110 | "1_medical room 3": [
111 | [
112 | 1,
113 | 26,
114 | 189
115 | ],
116 | [
117 | 1,
118 | 25,
119 | 178
120 | ]
121 | ],
122 | "1_server room": [
123 | [
124 | 1,
125 | 122,
126 | 159
127 | ],
128 | [
129 | 1,
130 | 112,
131 | 158
132 | ]
133 | ],
134 | "1_storage room": [
135 | [
136 | 1,
137 | 0,
138 | 0
139 | ],
140 | [
141 | 1,
142 | 29,
143 | 219
144 | ]
145 | ],
146 | "1_medical room 2": [
147 | [
148 | 1,
149 | 51,
150 | 189
151 | ],
152 | [
153 | 1,
154 | 50,
155 | 178
156 | ]
157 | ],
158 | "1_lab room 3": [
159 | [
160 | 1,
161 | 51,
162 | 207
163 | ],
164 | [
165 | 1,
166 | 50,
167 | 217
168 | ]
169 | ],
170 | "1_hall room 3": [
171 | [
172 | 1,
173 | 141,
174 | 208
175 | ],
176 | [
177 | 1,
178 | 148,
179 | 218
180 | ]
181 | ],
182 | "1_medical room 1": [
183 | [
184 | 1,
185 | 82,
186 | 189
187 | ],
188 | [
189 | 1,
190 | 84,
191 | 178
192 | ]
193 | ],
194 | "1_rest room": [
195 | [
196 | 1,
197 | 0,
198 | 0
199 | ],
200 | [
201 | 1,
202 | 12,
203 | 222
204 | ]
205 | ],
206 | "2_bed room 4": [
207 | [
208 | 2,
209 | 141,
210 | 108
211 | ],
212 | [
213 | 2,
214 | 152,
215 | 103
216 | ]
217 | ],
218 | "2_bed room 10": [
219 | [
220 | 2,
221 | 141,
222 | 31
223 | ],
224 | [
225 | 2,
226 | 152,
227 | 26
228 | ]
229 | ],
230 | "2_bed room 8": [
231 | [
232 | 2,
233 | 123,
234 | 46
235 | ],
236 | [
237 | 2,
238 | 112,
239 | 52
240 | ]
241 | ],
242 | "2_bed room 2": [
243 | [
244 | 2,
245 | 123,
246 | 72
247 | ],
248 | [
249 | 2,
250 | 112,
251 | 77
252 | ]
253 | ],
254 | "2_bed room 11": [
255 | [
256 | 2,
257 | 141,
258 | 83
259 | ],
260 | [
261 | 2,
262 | 152,
263 | 77
264 | ]
265 | ],
266 | "2_bed room 5": [
267 | [
268 | 2,
269 | 123,
270 | 98
271 | ],
272 | [
273 | 2,
274 | 112,
275 | 102
276 | ]
277 | ],
278 | "2_bed room 6": [
279 | [
280 | 2,
281 | 123,
282 | 149
283 | ],
284 | [
285 | 2,
286 | 112,
287 | 154
288 | ]
289 | ],
290 | "2_kitchen room": [
291 | [
292 | 2,
293 | 19,
294 | 190
295 | ],
296 | [
297 | 2,
298 | 16,
299 | 180
300 | ]
301 | ],
302 | "2_bed room 7": [
303 | [
304 | 2,
305 | 141,
306 | 57
307 | ],
308 | [
309 | 2,
310 | 152,
311 | 52
312 | ]
313 | ],
314 | "2_bed room 9": [
315 | [
316 | 2,
317 | 141,
318 | 134
319 | ],
320 | [
321 | 2,
322 | 152,
323 | 128
324 | ]
325 | ],
326 | "2_bed room 3": [
327 | [
328 | 2,
329 | 141,
330 | 160
331 | ],
332 | [
333 | 2,
334 | 152,
335 | 154
336 | ]
337 | ],
338 | "2_bed room 1": [
339 | [
340 | 2,
341 | 123,
342 | 123
343 | ],
344 | [
345 | 2,
346 | 112,
347 | 128
348 | ]
349 | ],
350 | "2_bed room 0": [
351 | [
352 | 2,
353 | 123,
354 | 21
355 | ],
356 | [
357 | 2,
358 | 112,
359 | 26
360 | ]
361 | ],
362 | "2_hall room 1": [
363 | [
364 | 2,
365 | 104,
366 | 190
367 | ],
368 | [
369 | 2,
370 | 111,
371 | 179
372 | ]
373 | ],
374 | "2_gym room": [
375 | [
376 | 2,
377 | 114,
378 | 207
379 | ],
380 | [
381 | 2,
382 | 116,
383 | 217
384 | ]
385 | ],
386 | "2_office room 1": [
387 | [
388 | 2,
389 | 58,
390 | 190
391 | ],
392 | [
393 | 2,
394 | 58,
395 | 179
396 | ]
397 | ],
398 | "2_hall room 3": [
399 | [
400 | 2,
401 | 141,
402 | 208
403 | ],
404 | [
405 | 2,
406 | 148,
407 | 218
408 | ]
409 | ],
410 | "2_office room 2": [
411 | [
412 | 2,
413 | 43,
414 | 190
415 | ],
416 | [
417 | 2,
418 | 42,
419 | 179
420 | ]
421 | ],
422 | "2_rest room": [
423 | [
424 | 2,
425 | 0,
426 | 0
427 | ],
428 | [
429 | 2,
430 | 12,
431 | 222
432 | ]
433 | ],
434 | "2_office space": [
435 | [
436 | 2,
437 | 82,
438 | 207
439 | ],
440 | [
441 | 2,
442 | 83,
443 | 217
444 | ]
445 | ],
446 | "2_storage room": [
447 | [
448 | 2,
449 | 0,
450 | 0
451 | ],
452 | [
453 | 2,
454 | 29,
455 | 219
456 | ]
457 | ],
458 | "2_hall room 2": [
459 | [
460 | 2,
461 | 141,
462 | 187
463 | ],
464 | [
465 | 2,
466 | 152,
467 | 178
468 | ]
469 | ],
470 | "2_living room": [
471 | [
472 | 2,
473 | 51,
474 | 207
475 | ],
476 | [
477 | 2,
478 | 50,
479 | 217
480 | ]
481 | ],
482 | "2_conference room": [
483 | [
484 | 2,
485 | 82,
486 | 189
487 | ],
488 | [
489 | 2,
490 | 83,
491 | 178
492 | ]
493 | ]
494 | }
--------------------------------------------------------------------------------
/env/data/map_room_data.json:
--------------------------------------------------------------------------------
1 | {
2 | "0": {
3 | "room0": {
4 | "x": [
5 | 2,
6 | 83
7 | ],
8 | "y": [
9 | 4,
10 | 69
11 | ]
12 | },
13 | "room1": {
14 | "x": [
15 | 118,
16 | 159
17 | ],
18 | "y": [
19 | 39,
20 | 105
21 | ]
22 | },
23 | "room2": {
24 | "x": [
25 | 2,
26 | 83
27 | ],
28 | "y": [
29 | 75,
30 | 140
31 | ]
32 | },
33 | "room3": {
34 | "x": [
35 | 62,
36 | 98
37 | ],
38 | "y": [
39 | 188,
40 | 228
41 | ]
42 | }
43 | },
44 | "1": {
45 | "room0": {
46 | "x": [
47 | 141,
48 | 163
49 | ],
50 | "y": [
51 | 168,
52 | 187
53 | ]
54 | },
55 | "room1": {
56 | "x": [
57 | 100,
58 | 122
59 | ],
60 | "y": [
61 | 168,
62 | 190
63 | ]
64 | },
65 | "room2": {
66 | "x": [
67 | 101,
68 | 122
69 | ],
70 | "y": [
71 | 116,
72 | 148
73 | ]
74 | },
75 | "room3": {
76 | "x": [
77 | 68,
78 | 98
79 | ],
80 | "y": [
81 | 207,
82 | 227
83 | ]
84 | },
85 | "room4": {
86 | "x": [
87 | 100,
88 | 131
89 | ],
90 | "y": [
91 | 207,
92 | 227
93 | ]
94 | },
95 | "room5": {
96 | "x": [
97 | 17,
98 | 33
99 | ],
100 | "y": [
101 | 168,
102 | 189
103 | ]
104 | },
105 | "room6": {
106 | "x": [
107 | 101,
108 | 122
109 | ],
110 | "y": [
111 | 150,
112 | 166
113 | ]
114 | },
115 | "room7": {
116 | "x": [
117 | 25,
118 | 33
119 | ],
120 | "y": [
121 | 211,
122 | 227
123 | ]
124 | },
125 | "room8": {
126 | "x": [
127 | 33,
128 | 67
129 | ],
130 | "y": [
131 | 168,
132 | 189
133 | ]
134 | },
135 | "room9": {
136 | "x": [
137 | 35,
138 | 65
139 | ],
140 | "y": [
141 | 207,
142 | 227
143 | ]
144 | },
145 | "room10": {
146 | "x": [
147 | 133,
148 | 162
149 | ],
150 | "y": [
151 | 208,
152 | 227
153 | ]
154 | },
155 | "room11": {
156 | "x": [
157 | 68,
158 | 100
159 | ],
160 | "y": [
161 | 168,
162 | 189
163 | ]
164 | },
165 | "room12": {
166 | "x": [
167 | 0,
168 | 24
169 | ],
170 | "y": [
171 | 216,
172 | 227
173 | ]
174 | }
175 | },
176 | "2": {
177 | "room0": {
178 | "x": [
179 | 141,
180 | 163
181 | ],
182 | "y": [
183 | 91,
184 | 115
185 | ]
186 | },
187 | "room1": {
188 | "x": [
189 | 141,
190 | 163
191 | ],
192 | "y": [
193 | 14,
194 | 38
195 | ]
196 | },
197 | "room2": {
198 | "x": [
199 | 101,
200 | 123
201 | ],
202 | "y": [
203 | 40,
204 | 63
205 | ]
206 | },
207 | "room3": {
208 | "x": [
209 | 101,
210 | 123
211 | ],
212 | "y": [
213 | 65,
214 | 89
215 | ]
216 | },
217 | "room4": {
218 | "x": [
219 | 141,
220 | 163
221 | ],
222 | "y": [
223 | 65,
224 | 89
225 | ]
226 | },
227 | "room5": {
228 | "x": [
229 | 101,
230 | 123
231 | ],
232 | "y": [
233 | 91,
234 | 114
235 | ]
236 | },
237 | "room6": {
238 | "x": [
239 | 101,
240 | 123
241 | ],
242 | "y": [
243 | 142,
244 | 166
245 | ]
246 | },
247 | "room7": {
248 | "x": [
249 | 0,
250 | 33
251 | ],
252 | "y": [
253 | 169,
254 | 190
255 | ]
256 | },
257 | "room8": {
258 | "x": [
259 | 141,
260 | 163
261 | ],
262 | "y": [
263 | 40,
264 | 63
265 | ]
266 | },
267 | "room9": {
268 | "x": [
269 | 141,
270 | 163
271 | ],
272 | "y": [
273 | 117,
274 | 140
275 | ]
276 | },
277 | "room10": {
278 | "x": [
279 | 141,
280 | 163
281 | ],
282 | "y": [
283 | 142,
284 | 166
285 | ]
286 | },
287 | "room11": {
288 | "x": [
289 | 101,
290 | 123
291 | ],
292 | "y": [
293 | 117,
294 | 140
295 | ]
296 | },
297 | "room12": {
298 | "x": [
299 | 101,
300 | 123
301 | ],
302 | "y": [
303 | 14,
304 | 38
305 | ]
306 | },
307 | "room13": {
308 | "x": [
309 | 100,
310 | 122
311 | ],
312 | "y": [
313 | 168,
314 | 190
315 | ]
316 | },
317 | "room14": {
318 | "x": [
319 | 101,
320 | 131
321 | ],
322 | "y": [
323 | 207,
324 | 227
325 | ]
326 | },
327 | "room15": {
328 | "x": [
329 | 50,
330 | 65
331 | ],
332 | "y": [
333 | 168,
334 | 190
335 | ]
336 | },
337 | "room16": {
338 | "x": [
339 | 133,
340 | 162
341 | ],
342 | "y": [
343 | 208,
344 | 227
345 | ]
346 | },
347 | "room17": {
348 | "x": [
349 | 35,
350 | 50
351 | ],
352 | "y": [
353 | 168,
354 | 190
355 | ]
356 | },
357 | "room18": {
358 | "x": [
359 | 0,
360 | 24
361 | ],
362 | "y": [
363 | 216,
364 | 227
365 | ]
366 | },
367 | "room19": {
368 | "x": [
369 | 68,
370 | 98
371 | ],
372 | "y": [
373 | 207,
374 | 227
375 | ]
376 | },
377 | "room20": {
378 | "x": [
379 | 25,
380 | 33
381 | ],
382 | "y": [
383 | 211,
384 | 227
385 | ]
386 | },
387 | "room21": {
388 | "x": [
389 | 141,
390 | 163
391 | ],
392 | "y": [
393 | 168,
394 | 187
395 | ]
396 | },
397 | "room22": {
398 | "x": [
399 | 36,
400 | 65
401 | ],
402 | "y": [
403 | 207,
404 | 227
405 | ]
406 | },
407 | "room23": {
408 | "x": [
409 | 68,
410 | 98
411 | ],
412 | "y": [
413 | 168,
414 | 189
415 | ]
416 | }
417 | }
418 | }
--------------------------------------------------------------------------------
/env/map_process.py:
--------------------------------------------------------------------------------
1 | import json
2 | import matplotlib.pyplot as plt
3 | import numpy as np
4 | import copy
5 | import skfmm
6 |
7 |
8 | class RoomMap(object):
9 |
10 | def __init__(self):
11 | self.floor1 = None
12 | self.floor2 = None
13 | self.floor3 = None
14 | # F1, f2, f3 = -16.69344711303711, -5.217403411865234, -0.0499998964369297
15 | self.height_floor1 = -16.693447
16 | self.height_floor2 = -5.2174
17 | self.height_floor3 = -0.0499999
18 | self.floor1_x0, self.floor1_y0, self.floor1_z0 = None, None, None
19 | self.maps_info = [
20 | {'x0': None, 'y0': None, 'z0': None, 'scale': None, 'width': None, 'height': None, 'grid': None},
21 | {'x0': None, 'y0': None, 'z0': None, 'scale': None, 'width': None, 'height': None, 'grid': None},
22 | {'x0': None, 'y0': None, 'z0': None, 'scale': None, 'width': None, 'height': None, 'grid': None}
23 | ]
24 | self.floors = [self.height_floor1, self.height_floor2, self.height_floor3]
25 |
26 | def get_world_position(self, n, i, j):
27 | x0, y0 = self.maps_info[n]['x0'], self.maps_info[n]['z0']
28 | scale, width, height = self.maps_info[n]['scale'], self.maps_info[n]['width'], self.maps_info[n]['height']
29 | x, y = x0 + i * scale, y0 + j * scale
30 | return x, self.floors[n], y
31 |
32 | def get_grid_position(self, n, x, y):
33 | x0, y0 = self.maps_info[n]['x0'], self.maps_info[n]['z0']
34 | scale, width, height = self.maps_info[n]['scale'], self.maps_info[n]['width'], self.maps_info[n]['height']
35 | # x, y = x0 + i * scale, y0 + j * scale
36 | i, j = (x - x0) / scale, (y - y0) / scale
37 | return round(i), round(j)
38 |
39 | def get_point_info(self, point):
40 | try:
41 | x, y, z = point['x'], point['y'], point['z']
42 | except:
43 | x, y, z = point[0], point[1], point[2]
44 |
45 | ind, value = min(enumerate(self.floors), key=lambda lis: abs(y - lis[1]))
46 | point_i, point_j = self.get_grid_position(ind, x, z)
47 | try:
48 | return ind, point_i, point_j, self.maps_info[ind]['grid'][point_i][point_j]
49 | except:
50 | i_max, j_max = np.array(self.maps_info[ind]['grid']).shape[0], np.array(self.maps_info[ind]['grid']).shape[
51 | 1]
52 | p_i, p_j = min(point_i, i_max - 1), min(point_j, j_max - 1)
53 | return ind, p_i, p_j, self.maps_info[ind]['grid'][p_i][p_j]
54 |
55 | def get_an_aligned_world_coordinate_randomly(self, floor, x, y, random=1):
56 | point_i, floor_layer, point_j = self.get_world_position(floor, x, y)
57 | accuracy = self.maps_info[floor]['scale']
58 | random_x_i = np.random.uniform(point_i, point_i + accuracy)
59 | random_y_j = np.random.uniform(point_j, point_j + accuracy)
60 | return random_x_i, random_y_j
61 |
62 | def get_an_accessible_area(self, x, y, z, radius_meter=1.5, mode=0, sort=1, inflation=0, dis=0):
63 | # mode 0 represent the world position, 1 is the matrix map(x=floor_n, y=map_i, z=map_j)
64 | if not mode:
65 | floor, map_i, map_j, is_obstacle = self.get_point_info([x, y, z])
66 | else:
67 | floor, map_i, map_j = round(x), round(y), round(z)
68 | is_obstacle = self.maps_info[floor]['grid'][map_i][map_j]
69 | map_array = np.array(self.maps_info[floor]['grid'])
70 | radius = radius_meter / self.maps_info[floor]['scale']
71 | # Determine the scope of the query domain
72 | min_i, max_i = round(max(0, map_i - radius)), round(min(map_array.shape[0] - 1, map_i + radius))
73 | min_j, max_j = round(max(0, map_j - radius)), round(min(map_array.shape[1] - 1, map_j + radius))
74 | # Find feasible points within the specified radius
75 | valid_points = []
76 | # exclude points with a distance of 1 from obstacles
77 | valid_points = []
78 | for i in range(min_i, max_i + 1):
79 | for j in range(min_j, max_j + 1):
80 | if map_array[i, j] != 0 and ((i - map_i) ** 2 + (j - map_j) ** 2) <= radius ** 2:
81 | too_close_to_obstacle = False
82 | if inflation:
83 | for ii in range(max(0, i - 1), min(map_array.shape[0], i + 2)):
84 | for jj in range(max(0, j - 1), min(map_array.shape[1], j + 2)):
85 | if map_array[ii, jj] == 0:
86 | too_close_to_obstacle = True
87 | if not too_close_to_obstacle:
88 | valid_points.append((i, j))
89 | if dis != 0:
90 | distances = [abs(np.sqrt((i - map_i) ** 2 + (j - map_j) ** 2) - dis) for i, j in valid_points]
91 | sorted_valid_points = [point for _, point in sorted(zip(distances, valid_points))]
92 | return floor, sorted_valid_points
93 | if sort:
94 | # Calculate the distance from each feasible point to a given point
95 | distances = [np.sqrt((i - map_i) ** 2 + (j - map_j) ** 2) for i, j in valid_points]
96 | # Sort feasible points in ascending order of distance
97 | sorted_valid_points = [point for _, point in sorted(zip(distances, valid_points))]
98 | # print('here: ', len(sorted_valid_points), ' in radius ', radius_meter, ', scale', self.maps_info[floor]['scale'])
99 | return floor, sorted_valid_points
100 | else:
101 | return floor, valid_points
102 |
103 | def add_room(self, json_data):
104 | # parsing map information
105 | map_id = json_data['mapId']
106 | floor = json_data['mapName']
107 | width = json_data['width']
108 | height = json_data['height']
109 | points = json_data['points']
110 | scale = json_data['accuracy']
111 | positions = json_data['minPoint']
112 | n_length = scale
113 | x, y = 0, 0
114 | # Create a 2D matrix map
115 | # Analyze points and add point information to the map matrix
116 | n = 0
117 | map_data = []
118 | xx, yy = [], []
119 | # json_m = {"mapId": 1, "mapName": "F3", "width": 51, "height": 68, "accuracy": 1.0, "points": []}
120 | po = eval(points)
121 | for point in points:
122 | # point_data = json.loads(point)
123 | map_data.append(1)
124 | matrix = [[0 for _ in range(height)] for _ in range(width)]
125 | navMapPoints = [[None for _ in range(height)] for _ in range(width)]
126 | for i in range(width):
127 | for j in range(height):
128 | index = i * height + j
129 | matrix[i][j] = map_data[index]
130 | navMapPoints[i][j] = {"x": x + i * n_length, "y": y + j * n_length, "data": map_data[index]}
131 | flag = None
132 | if floor == 'F1':
133 | self.floor1 = po
134 | flag = 0
135 | elif floor == 'F2':
136 | self.floor2 = po
137 | flag = 1
138 | elif floor == 'F3':
139 | self.floor3 = po
140 | flag = 2
141 | # plt.show()
142 | self.maps_info[flag]['scale'] = scale
143 | self.maps_info[flag]['width'] = width
144 | self.maps_info[flag]['height'] = height
145 | self.maps_info[flag]['grid'] = po
146 | self.maps_info[flag]['x0'] = positions['x']
147 | self.maps_info[flag]['y0'] = positions['z']
148 | self.maps_info[flag]['z0'] = positions['z']
149 | self.floors[flag] = positions['y']
150 | # matrix_map = np.array(map_data).reshape((width, height))
151 | # Convert all values uniformly to values greater than or equal to 0
152 | # Create and initialize matrix
153 | # matrix = [[0 for _ in range(max_y)] for _ in range(max_x)]
154 |
155 | def draw(self, i, n, j):
156 | if isinstance(n, int) and isinstance(i, int) and isinstance(j, int):
157 | pass
158 | else:
159 | n, i, j, is_obstacle = self.get_point_info((i, n, j))
160 | mat = copy.deepcopy(self.maps_info[n]['grid'])
161 | mat[i][j] = 5
162 | plt.imshow(mat, cmap='gray')
163 | plt.title('Floor{}'.format(n))
164 | plt.show()
165 |
166 | def plot_map(self):
167 | map = self.floor3
168 | plt.imshow(map, cmap='gray')
169 | plt.title('Room Map')
170 | plt.grid(False)
171 | plt.axis('off')
172 | plt.xticks([])
173 | plt.yticks([])
174 | plt.show()
175 |
176 | def dis_matrix(self, mappp, target_position):
177 | map = np.array(mappp)
178 | map_copy = copy.deepcopy(map)
179 | # mask = np.logical_and(abs(X) < 0.1, abs(Y) < 0.5)
180 | # phi = np.ma.MaskedArray(phi, mask)
181 | tar_map = np.ones_like(map)
182 | tar_map[target_position[0]][target_position[1]] = 0
183 | obstacle_map = np.ones_like(map)
184 | obstacle_map[map == 1] = 0
185 | bool_map = np.array(obstacle_map, dtype=bool)
186 | bool_map = np.ma.MaskedArray(tar_map, bool_map)
187 | return skfmm.distance(bool_map)
188 |
189 | def search_route(self, map, current_position, target_position):
190 | target_x, target_y = 1, 1
191 | map_show = copy.deepcopy(map)
192 | dis_matrix = self.dis_matrix(map, target_position)
193 | # plt.imshow(map)
194 | # plt.show()
195 | arrive = 0
196 | while not arrive:
197 | map_show[current_position[0]][current_position[1]] = -50
198 | xx, yy = current_position[0], current_position[1]
199 | if dis_matrix[xx][yy] == 0:
200 | break
201 | min_value, next_x, next_y = 100000, 0, 0
202 | for i in range(xx-1, xx+2):
203 | for j in range(yy-1, yy+2):
204 | if min_value > dis_matrix[i][j]:
205 | min_value, next_x, next_y = dis_matrix[i][j], i, j
206 | current_position = (next_x, next_y)
207 | # break
208 | plt.imshow(map_show)
209 | plt.axis('off')
210 | plt.show()
211 |
212 | '''
213 | points:["{\"viability\":false,\"position\":{\"x\":-19.94000244140625,\"y\":-0.0499998964369297,\"z\":-59.400001525878909}}"]
214 | points:[[0/1,x,y,z],[0/1,-19.94000,-0.04999,-59.4000],[0/1,x,y,z]]
215 | '''
216 |
217 | if __name__ == '__main__':
218 | # read Map.json
219 | file_name = "map/map4.json"
220 | with open(file_name, 'r') as file:
221 | json_data = json.load(file)
222 | map = RoomMap()
223 | map.add_room(json_data)
--------------------------------------------------------------------------------
/robot/baseline.py:
--------------------------------------------------------------------------------
1 | import time
2 | import re
3 | import difflib
4 | import os
5 | import matplotlib.pyplot as plt
6 | # from env.socket_server import *
7 | # from llm_process import *
8 | from robot.llm_process import *
9 | # Notice the relative path of the main script
10 |
11 |
12 | def instruction_parsing_res(prs, instruction, resume):
13 | task_planning = instruction_parsing(instruction, resume)
14 | # task_planning = ['white bagged cake', 'marble dinner counter', 'living room', 'man with white coat', 'bed room']
15 | object_room, human_room = room_filter(prs, task_planning[2])[0], room_filter(prs, task_planning[4])[0]
16 | possible_receptacles, receptacles_index = approach_landmark(prs, task_planning[1], object_room)
17 | result_data = {'target_object': task_planning[0], 'target_object_receptacle': possible_receptacles,
18 | 'target_object_room': (object_room, task_planning[2]), 'target_human': task_planning[3],
19 | 'target_human_room': (human_room, task_planning[4])}
20 | return result_data
21 |
22 |
23 | def calculate_similarity(a, b):
24 | len_a, len_b = len(a), len(b)
25 | dp = [[0] * (len_b + 1) for _ in range(len_a + 1)]
26 | for i in range(1, len_a + 1):
27 | for j in range(1, len_b + 1):
28 | if a[i - 1] == b[j - 1]:
29 | dp[i][j] = dp[i - 1][j - 1] + 1
30 | else:
31 | dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
32 | lcs_length = dp[len_a][len_b]
33 | similarity = 2.0 * lcs_length / (len_a + len_b)
34 | if similarity > 0.5:
35 | return True
36 | else:
37 | return False
38 |
39 |
40 | def delivery_execution(prs, instruction, resume):
41 | '''
42 | 1. Analyze language instructions to determine the target
43 | 2. Locate/proceed to the room where the target item is located
44 | 3. Find the container based on the semantic map
45 | 4. Identify the target item using camera information (or explore if not found)
46 | 5. Grasp the target item based on segmentation information
47 | 6. After grasping, proceed to the room based on the information from step 1
48 | 7. Locate and recognize the target person
49 | '''
50 | # prs.agent.initial_pose()
51 | task_planning = instruction_parsing(instruction, resume)
52 | # task_planning = ['white bagged cake', 'marble dinner counter', 'living room', 'man with white coat', 'bed room']
53 | # print(task_planning)
54 | object_room, human_room = room_filter(prs, task_planning[2])[0], room_filter(prs, task_planning[4])[0]
55 | # print(object_room, human_room)
56 | speed_time, camera_pitch = 3, 20
57 | prs.sim_speed(speed_time)
58 | # Unity rendering and runtime acceleration, notice the possibility of logical errors caused by fast rendering speed
59 | go_to_location(prs, object_room)
60 | prs.sim_speed(1)
61 | camera_rgb, camera_degree = scene_understanding(prs, task_planning[0], task_planning[1], pitch=camera_pitch, mode=1)
62 | possible_receptacles, receptacles_index = approach_landmark(prs, task_planning[1], object_room)
63 | for r_index, rec in enumerate(possible_receptacles):
64 | if camera_rgb is not None: break
65 | for time_i in range(2):
66 | prs.sim_speed(speed_time)
67 | prs.agent.goto_receptacle(room=object_room, recepacle=receptacles_index[r_index], random=1)
68 | prs.sim_speed(1)
69 | camera_rgb, camera_degree = scene_understanding(prs, task_planning[0], task_planning[1], pitch=camera_pitch, mode=1)
70 | if camera_rgb is not None: break
71 | if camera_rgb is None: pass
72 | # exploration of environment
73 | else:
74 | break
75 | if camera_rgb is not None:
76 | # Operate items and identify, determine room
77 | prs.sim_speed(1)
78 | manipulate_target(prs, task_planning[0], camera_degree, pitch=camera_pitch)
79 | time.sleep(1)
80 | prs.sim_speed(speed_time)
81 | go_to_location(prs, human_room)
82 | prs.sim_speed(1)
83 | camera_rgb, camera_degree = scene_understanding(prs, task_planning[3], pitch=camera_pitch, mode=1)
84 | search_result = 0
85 | if camera_rgb is not None:
86 | search_result = approach_target(camera_rgb, camera_degree, task_planning[3], 3)
87 | if not search_result:
88 | for room_i in prs.objs_data.room_area:
89 | if room_i['name'] == human_room:
90 | room_info = room_i
91 | break
92 | if room_info is None: return None
93 | receptacles_info = room_info['receptacles_list']
94 | # Locate possible receptacles in the room
95 | for r_index, rec in enumerate(receptacles_info):
96 | if camera_rgb is not None: break
97 | prs.sim_speed(speed_time)
98 | prs.agent.goto_receptacle(room=human_room, recepacle=r_index, random=1)
99 | prs.sim_speed(1)
100 | camera_rgb, camera_degree = scene_understanding(prs, task_planning[3], pitch=camera_pitch,
101 | mode=1)
102 | if camera_rgb is None:
103 | pass
104 | else:
105 | search_result = approach_target(camera_rgb, camera_degree, task_planning[3], 3)
106 | break
107 | return 1
108 |
109 |
110 | def target_matching(target, options=['room']):
111 | best_match, matches_with_similarity = None, []
112 | target_preprocess = re.sub(r'[^a-zA-Z0-9]', '', target).lower()
113 | for location in options:
114 | similarity = difflib.SequenceMatcher(None, target_preprocess, location.lower()).ratio()
115 | matches_with_similarity.append((similarity, location))
116 | matches_with_similarity.sort(key=lambda x: x[0], reverse=True)
117 | sorted_matches = [match[1] for match in matches_with_similarity]
118 | # Sort by similarity
119 | return sorted_matches
120 |
121 |
122 | def instruction_parsing(task_instruction, description=None):
123 | background = 'Now you are a robotic assistant tasked with assisting in executing a human-centred item delivery mission. Please deduce the necessary execution actions and objectives based on the following task instructions:'
124 | npc_info = 'Introduction to the target person for the transportation mission: ' + description
125 | requirement = 'The following information needs to be extracted from the task: the target item, the container that holds the target item, the room where the target item is located, the visual characteristics of the target person (excluding the name but including gender for identification, such as a woman in a white dress), and the room where the target person is located (including the room number such as bedroom 1, with only the room name information and excluding ambiguous location descriptions, for example, outputting office 1). Only the inference results are required, the format is as follows:'
126 | reference = ''
127 | prompt = background + task_instruction + npc_info + requirement + reference
128 | task_parameter = None
129 | for i in range(3):
130 | reasoning_result = llm_interaction(prompt)
131 | # reasoning_result = ''
132 | # print(reasoning_result)
133 | try:
134 | cleaned_string = reasoning_result.strip('<>').strip()
135 | items = cleaned_string.split(',')
136 | task_parameter = [item.strip() for item in items]
137 | break
138 | except Exception as e:
139 | continue
140 | # decoded_str = s.encode('utf-8').decode('unicode-escape')
141 | return task_parameter
142 |
143 |
144 | def go_to_location(prs, destination='bed room 1'):
145 | # go to the target room through global map
146 | if destination is not None:
147 | # prs.agent.goto_target_goal((-8.4, 0.1, 7.9), radius=1.5, position_mode=1)
148 | position = None
149 | for room in prs.objs_data.room_sampling_points:
150 | if room.split('_')[1] == destination:
151 | position = prs.objs_data.room_sampling_points[room]
152 | if position is None: return 0
153 | target = position[0]
154 | prs.agent.goto_target_goal(target, 1.25, position_mode=1)
155 | # Facing the center position of the room space
156 | prs.agent.head_camera_look_at(position[1], accuracy=0)
157 |
158 |
159 | def room_filter(prs, destination, floor=2):
160 | rooms = prs.objs_data.room_area
161 | locations = [roo['name'] for roo in rooms]
162 | # locations = prs.objs_data.buliding_rooms[floor]
163 | best_match_rooms = target_matching(destination, locations)
164 | return best_match_rooms
165 |
166 |
167 | def approach_landmark(prs, landmark, room):
168 | # Determine which one in the list has a higher similarity to the destination.
169 | # For 'bed room 1', it is desired to output 'bedroom1' instead of 'bedroom'
170 | room_info = None
171 | for room_i in prs.objs_data.room_area:
172 | if room_i['name'] == room:
173 | room_info = room_i
174 | break
175 | if room_info is None: return None
176 | landmarks, original_index = room_info['receptacles_list'], []
177 | potential_receptacles = target_matching(landmark, landmarks)
178 | for rec in potential_receptacles:
179 | original_index.append(landmarks.index(rec))
180 | return potential_receptacles, original_index
181 | # Selecting potential containers through semantic matching
182 |
183 |
184 | def scene_understanding(prs, target, surrounding=None, pitch=20, mode=0):
185 | # The angle of horizontal X-axis rotation, equivalent to the pitch angle, whether to segment
186 | observation_views = [0, -60, 60]
187 | for degree in observation_views:
188 | if surrounding is not None:
189 | target = target + ' or ' + surrounding
190 | context1 = 'Please answer yes or no. If there is '
191 | context2 = ', or there may be similar objects or content. Only answer yes or no!'
192 | detect_prompt = context1 + target + context2
193 | head_camera_rgb = prs.agent.observation(degree=degree, camera=0, up_down=pitch)
194 | if mode:
195 | recognition_result = lmm_interaction(detect_prompt, head_camera_rgb)
196 | if 'yes' in recognition_result.lower():
197 | return head_camera_rgb, degree
198 | else:
199 | if surrounding is not None:
200 | target = target + '. ' + surrounding
201 | seg = object_detect_module(head_camera_rgb, target)
202 | if seg is not None:
203 | return head_camera_rgb, degree
204 | prs.agent.joint_control(joint_id=14, target=0)
205 | # Adjust the camera to its original degree 0 (look straight ahead)
206 | return None, None
207 |
208 |
209 | def approach_target(ego_view, camera_degree, target, distance=2):
210 | target_mask = object_detect_module(ego_view, target)
211 | res = 0
212 | if target_mask is not None:
213 | depth_m = prs.agent.get_depth(0)
214 | tar_distance, view_angle = prs.agent.depth_estimation(target_mask, depth_m, field_of_view=90)
215 | if tar_distance > distance:
216 | point = prs.agent.target_direction(degree=camera_degree, distance=tar_distance, target_degree_view=view_angle)
217 | res = prs.agent.goto_target_goal(point, radius=2.5, position_mode=1, inflation=1)
218 | prs.agent.direction_adjust(point, pos_input=1)
219 | else:
220 | res = 1
221 | return res
222 |
223 |
224 | def manipulate_target(prs, target_obj, degree, pitch=20):
225 | s_now = prs.agent.observation(degree, up_down=pitch)
226 | seg, result = object_detect_module(s_now, target_obj), None
227 | if seg is not None:
228 | result = prs.agent.object_interaction(input_matrix=seg, manipulaton=1, type=0)
229 | return result
230 |
231 |
232 | if __name__ == "__main__":
233 | # Environment initialization
234 | prs = PrsEnv(is_print=1, rendering=1, start_up_mode=1)
235 |
236 | with open(os.path.join('task', 'dataset', 'deliver_task_test_set.json'), 'r') as file:
237 | task_data = json.load(file)
238 | tasks = list(task_data.keys())
239 | errors, error_num, task_results = [], 0, dict()
240 | for task_i, task_id in enumerate(tasks):
241 | print('task:', task_id)
242 | task = task_data[task_id]
243 | task_npc_id = task['npc_id']
244 | start_time = time.time()
245 | instruction, npc_information, data = prs.delivery_task_import(task)
246 | now = prs.env_time.current_date.strftime("%d %H:%M:%S")
247 | try:
248 | # ------------ baseline method -----------------
249 | time.sleep(0.5)
250 | delivery_execution(prs, instruction, npc_information)
251 | except Exception as e:
252 | print(e, 'error')
253 | break
254 | result = prs.delivery_task_evaluate(task, score=1, save=0)
255 | print(result['task_score'])
256 | # ====== if you want to save the result as json file to submission on Eval AI ==========
257 | # result_save = prs.delivery_task_evaluate(task, score=0, save=1)
258 | # task_results[task_id] = result_save
259 | # with open('task/result/deliver_task_result.json', 'w') as file:
260 | # json.dump(task_results, file, indent=4)
261 | # ---------------------------------------------------------------------------------------
262 | time.sleep(3)
263 | prs.finish_env()
--------------------------------------------------------------------------------
/env/data/npc_data.json:
--------------------------------------------------------------------------------
1 | {
2 | "npc": [
3 | {
4 | "description": "I'm {name} from europe, a computer engineer based in a co-working space. My favorite attire includes light-colored jackets. I often work late into the night and occasionally participate in meetings during the afternoon. Besides working, eating, and attending meetings, I usually stay in Room 0.",
5 | "feature": "I'm {name}, a man with light-colored jackets.",
6 | "character": "a man with light-colored jackets.",
7 | "information": {
8 | "id": 0,
9 | "name": null,
10 | "age": 31,
11 | "gender": 0,
12 | "room": "F3_Bedroom_0",
13 | "office": "F3_OfficeSpaceRoom",
14 | "job": "IT",
15 | "npc_name": "Npc_CasualMale",
16 | "schedule": null
17 | }
18 | },
19 | {
20 | "description": "I'm {name}, a scientific advisor at a polar research station. My room number is 1 and my office is located in office 1, next to the conference room. I lead a regular life and often spend some time in the hall in the evenings. My fashion preferences include blue shirts and black glasses.",
21 | "feature": "I'm {name}, a woman, and my outfit includes blue shirt and black glasses.",
22 | "character": "a woman with blue shirt and black glasses",
23 | "information": {
24 | "id": 1,
25 | "name": null,
26 | "age": 48,
27 | "gender": 1,
28 | "room": "F3_Bedroom_1",
29 | "office": "F3_OfficeRoom01",
30 | "job": "Advisor",
31 | "npc_name": "Npc_BusinessFemale",
32 | "schedule": null
33 | }
34 | },
35 | {
36 | "description": " I'm {name}, a supervisor who's often busy with meetings and office work. However, I'm also a fitness enthusiast. My office is in Office 2, and Room 2 is where I stay. If you see a middle-aged man in a white shirt, that's me.",
37 | "feature": "I'm {name}, a middle-aged man in a white shirt.",
38 | "character": "a middle-aged man in a white shirt ",
39 | "information": {
40 | "id": 2,
41 | "name": null,
42 | "age": 52,
43 | "gender": 0,
44 | "room": "F3_Bedroom_2",
45 | "office": "F3_OfficeRoom02",
46 | "job": "Supervisor",
47 | "npc_name": "Npc_BusinessMale",
48 | "schedule": null
49 | }
50 | },
51 | {
52 | "description": "I'm {name}, an intern from Asia. You can find me in the shared office, and my room number is 3. Besides attending afternoon meetings and evening workouts, I spend most of my time in the office studying and handling data. I have some trendy hats and hoodies.",
53 | "feature": "I'm {name} and have trendy hat and hoody, a young lady.",
54 | "character": "a young lady with trendy hat and hoody",
55 | "information": {
56 | "id": 3,
57 | "name": null,
58 | "age": 24,
59 | "gender": 1,
60 | "room": "F3_Bedroom_3",
61 | "office": "F3_OfficeSpaceRoom",
62 | "job": "Internship",
63 | "npc_name": "Npc_CasualFemale",
64 | "schedule": null
65 | }
66 | },
67 | {
68 | "description": "I am designer {name}. I reside in Room 4 and work in the shared workspace opposite the conference room. During my lunch break and evenings, you might find me seeking inspiration on the couch in the living room. I'm often spotted in a black jacket.",
69 | "feature": "I am designer {name} and spotted in a black jacket, a gentleman.",
70 | "character": "a gentleman with black jacket",
71 | "information": {
72 | "id": 4,
73 | "name": null,
74 | "age": 37,
75 | "gender": 0,
76 | "room": "F3_Bedroom_4",
77 | "office": "F3_OfficeSpaceRoom",
78 | "job": "Designer",
79 | "npc_name": "Npc_CasualMale",
80 | "schedule": null
81 | }
82 | },
83 | {
84 | "description": "I'm doctor {name}. I can usually be found in the medical room on the second floor. During mealtimes, I sometimes have a light meal at the tables in the hall or kitchen. I typically wear a white lab coat and reside in Room 5.",
85 | "feature": "I'm doctor {name} and wear a white lab coat, a woman.",
86 | "character": "a woman with white lab coat",
87 | "information": {
88 | "id": 5,
89 | "name": null,
90 | "age": 45,
91 | "gender": 1,
92 | "room": "F3_Bedroom_5",
93 | "office": "F2_MedicalRoom03",
94 | "job": "Doctor",
95 | "npc_name": "Npc_UniformFemale",
96 | "schedule": null
97 | }
98 | },
99 | {
100 | "description": "I'm {name}, a researcher at a polar research station, specializing in biological experiments. Currently, I'm working in the shared office area to process experimental data. Sometimes, I take a break in the living room for a drink. My room number is 6, and I often wear a white lab coat.",
101 | "feature": "I'm {name} and wear a white lab coat, a lady.",
102 | "character": "a lady with white lab coat",
103 | "information": {
104 | "id": 6,
105 | "name": null,
106 | "age": 29,
107 | "gender": 1,
108 | "room": "F3_Bedroom_6",
109 | "office": "F3_OfficeSpaceRoom",
110 | "job": "Laboratory",
111 | "npc_name": "Npc_UniformFemale",
112 | "schedule": null
113 | }
114 | },
115 | {
116 | "description": "I'm {name}, a facility maintenance technician. I oversee the equipment on the first floor and reside in Room 7. While I spend most of my time with the equipment, apart from meals in the third-floor dining area, I also take breaks in the living room. You can easily spot me in my signature blue work uniform.",
117 | "feature": "I'm {name} with my blue work uniform, a man.",
118 | "character": "a man with blue work uniform",
119 | "information": {
120 | "id": 7,
121 | "name": null,
122 | "age": 40,
123 | "gender": 0,
124 | "room": "F3_Bedroom_7",
125 | "office": "F1_ConveyorRoom",
126 | "job": "Equipment",
127 | "npc_name": "Npc_UniformMale",
128 | "schedule": null
129 | }
130 | },
131 | {
132 | "description": " I'm {name}, a worker here. My room is number 8, and I usually wear an orange vest. My daily routine is quite regular. I spend my days handling cargo on the first floor and having meals in the kitchen. In the evenings, I retreat to my room to rest.",
133 | "feature": "I'm {name} and wear an orange vest, a man.",
134 | "character": "a man with orange vest",
135 | "information": {
136 | "id": 8,
137 | "name": null,
138 | "age": 42,
139 | "gender": 0,
140 | "room": "F3_Bedroom_8",
141 | "office": "F1_EnergyRoom",
142 | "job": "Worker",
143 | "npc_name": "Npc_UniformMale",
144 | "schedule": null
145 | }
146 | },
147 | {
148 | "description": "I'm an experimental researcher {name}. I conduct intricate biological and chemical experiments in the second-floor laboratory. I reside in Room 9 on the third floor, identifiable by my white lab coat and yellow hair. I often cook for myself in the kitchen and enjoy my meals at the table in the main hall.",
149 | "feature": "I'm {name}, a gentleman, identifiable by my white lab coat and yellow hair.",
150 | "character": "a gentleman with white lab coat and yellow hair",
151 | "information": {
152 | "id": 9,
153 | "name": null,
154 | "age": 31,
155 | "gender": 0,
156 | "room": "F3_Bedroom_9",
157 | "office": "F2_LabRoom03",
158 | "job": "Medical",
159 | "npc_name": "Npc_UniformMale",
160 | "schedule": null
161 | }
162 | }
163 | ],
164 | "names": {
165 | "0": [
166 | "Jack",
167 | "Peter",
168 | "Michael",
169 | "James",
170 | "David",
171 | "Robert",
172 | "John",
173 | "William",
174 | "Richard",
175 | "Charles",
176 | "Joseph",
177 | "Thomas",
178 | "Christopher",
179 | "Daniel",
180 | "Matthew",
181 | "Anthony",
182 | "Andrew",
183 | "Paul",
184 | "Stephen",
185 | "Edward",
186 | "Jonathan",
187 | "Kevin",
188 | "Justin",
189 | "Henry",
190 | "Adam",
191 | "Joshua",
192 | "Nicholas",
193 | "Ryan",
194 | "Brian",
195 | "Samuel",
196 | "Eric",
197 | "Jason",
198 | "Mark",
199 | "George",
200 | "Timothy",
201 | "Jeffrey",
202 | "Alexander",
203 | "Joseph",
204 | "Adam",
205 | "Jacob",
206 | "Noah",
207 | "Ethan",
208 | "William",
209 | "Michael",
210 | "Alexander",
211 | "James",
212 | "Benjamin",
213 | "Oliver",
214 | "Matthew",
215 | "David",
216 | "Daniel",
217 | "Joseph",
218 | "Jackson",
219 | "Lucas",
220 | "Logan",
221 | "Nathan",
222 | "Elijah",
223 | "Christian",
224 | "Gabriel",
225 | "Owen",
226 | "Aiden",
227 | "Isaac",
228 | "Sebastian",
229 | "Lucas",
230 | "Jack",
231 | "Hunter",
232 | "Jayden",
233 | "Andrew",
234 | "Dylan",
235 | "Wyatt",
236 | "Liam",
237 | "Caleb",
238 | "Evan",
239 | "Charles",
240 | "Leo",
241 | "Maxwell",
242 | "Adam",
243 | "Aaron",
244 | "Abraham",
245 | "Adam",
246 | "Adrian",
247 | "Alan",
248 | "Albert",
249 | "Alec",
250 | "Alex",
251 | "Alexander",
252 | "Alfred",
253 | "Ali",
254 | "Allen",
255 | "Alvin",
256 | "Andre",
257 | "Andrew",
258 | "Andy",
259 | "Anthony",
260 | "Antonio",
261 | "Archer",
262 | "Ari",
263 | "Arthur",
264 | "Asher",
265 | "Austin",
266 | "Axel",
267 | "Barry",
268 | "Ben",
269 | "Benjamin",
270 | "Blake",
271 | "Bradley",
272 | "Brandon",
273 | "Brayden",
274 | "Brendan",
275 | "Brian",
276 | "Bruce",
277 | "Bryan",
278 | "Caleb",
279 | "Calvin",
280 | "Cameron",
281 | "Carl",
282 | "Carlos",
283 | "Carter",
284 | "Charles",
285 | "Charlie",
286 | "Chase",
287 | "Chris",
288 | "Christian",
289 | "Christopher",
290 | "Clarence",
291 | "Clark",
292 | "Cody",
293 | "Cole",
294 | "Colin",
295 | "Collin",
296 | "Connor",
297 | "Cooper",
298 | "Craig",
299 | "Curtis",
300 | "Cyrus",
301 | "Dale",
302 | "Dalton",
303 | "Damian",
304 | "Daniel",
305 | "Danny",
306 | "Darius",
307 | "Darren",
308 | "David",
309 | "Dean",
310 | "Dennis",
311 | "Derek",
312 | "Derrick",
313 | "Devin",
314 | "Diego",
315 | "Dominic",
316 | "Donald",
317 | "Douglas",
318 | "Dylan",
319 | "Eddie",
320 | "Edward",
321 | "Edwin",
322 | "Eli",
323 | "Elijah",
324 | "Elliot",
325 | "Elliott",
326 | "Emmanuel",
327 | "Eric",
328 | "Ethan",
329 | "Evan",
330 | "Everett",
331 | "Ezra",
332 | "Felix",
333 | "Fernando",
334 | "Francis",
335 | "Frank",
336 | "Franklin",
337 | "Frederick",
338 | "Gabriel",
339 | "Gavin",
340 | "George",
341 | "Gerald",
342 | "Gilbert",
343 | "Giovanni",
344 | "Graham",
345 | "Grant",
346 | "Gregory",
347 | "Harrison",
348 | "Harry",
349 | "Hayden",
350 | "Henry",
351 | "Hudson",
352 | "Hugh",
353 | "Hunter",
354 | "Ian",
355 | "Isaac",
356 | "Isaiah",
357 | "Ivan",
358 | "Jack",
359 | "Jackson",
360 | "Jacob",
361 | "Jake",
362 | "James",
363 | "Jamie",
364 | "Jared",
365 | "Jason",
366 | "Jaxon",
367 | "Jay",
368 | "Jayden",
369 | "Jeff",
370 | "Jeffrey",
371 | "Jeremiah",
372 | "Jeremy",
373 | "Jerome",
374 | "Jerry",
375 | "Jesse",
376 | "Jesus",
377 | "Jim",
378 | "Jimmy",
379 | "Joe",
380 | "Joel",
381 | "John",
382 | "Johnny",
383 | "Jonah",
384 | "Jonathan",
385 | "Jordan",
386 | "Joseph",
387 | "Joshua",
388 | "Josiah",
389 | "Juan",
390 | "Julian",
391 | "Justin",
392 | "Kai",
393 | "Kaleb",
394 | "Kameron",
395 | "Karl",
396 | "Keith",
397 | "Kenneth",
398 | "Kevin",
399 | "Kieran",
400 | "Kyle",
401 | "Landon",
402 | "Larry",
403 | "Lawrence",
404 | "Lee",
405 | "Leo",
406 | "Leon",
407 | "Leonard",
408 | "Liam",
409 | "Lincoln",
410 | "Logan",
411 | "Louis",
412 | "Lucas",
413 | "Luke",
414 | "Malachi",
415 | "Malcolm",
416 | "Marcus",
417 | "Mario",
418 | "Mark",
419 | "Marshall",
420 | "Martin",
421 | "Mason",
422 | "Mathew",
423 | "Matthew",
424 | "Max",
425 | "Maxwell",
426 | "Miles",
427 | "Mitchell",
428 | "Nathan",
429 | "Nathaniel",
430 | "Neil",
431 | "Nicholas",
432 | "Noah",
433 | "Nolan",
434 | "Oliver",
435 | "Oscar",
436 | "Owen",
437 | "Patrick",
438 | "Paul",
439 | "Peter",
440 | "Philip",
441 | "Preston",
442 | "Quentin",
443 | "Ralph",
444 | "Randall",
445 | "Randy",
446 | "Raymond",
447 | "Reid",
448 | "Richard",
449 | "Rick",
450 | "Riley",
451 | "Robert",
452 | "Robin",
453 | "Rodney",
454 | "Roger",
455 | "Ronald",
456 | "Ross",
457 | "Roy",
458 | "Russell",
459 | "Ryan",
460 | "Sam",
461 | "Samuel",
462 | "Scott",
463 | "Sean",
464 | "Sebastian",
465 | "Seth",
466 | "Shane",
467 | "Shaun",
468 | "Shawn",
469 | "Sidney",
470 | "Simon",
471 | "Spencer",
472 | "Stanley",
473 | "Stephen",
474 | "Steve",
475 | "Steven",
476 | "Stuart",
477 | "Taylor",
478 | "Ted",
479 | "Terrence",
480 | "Terry",
481 | "Theodore",
482 | "Thomas",
483 | "Timothy",
484 | "Todd",
485 | "Tommy",
486 | "Tony",
487 | "Travis",
488 | "Trevor",
489 | "Troy",
490 | "Tyler",
491 | "Victor",
492 | "Vincent",
493 | "Walter",
494 | "Warren",
495 | "Wayne",
496 | "Wesley",
497 | "William",
498 | "Willie",
499 | "Wyatt",
500 | "Xavier",
501 | "Zachary",
502 | "Zane"
503 | ],
504 | "1": [
505 | "Emily",
506 | "Olivia",
507 | "Sophia",
508 | "Isabella",
509 | "Ava",
510 | "Mia",
511 | "Charlotte",
512 | "Amelia",
513 | "Harper",
514 | "Abigail",
515 | "Elizabeth",
516 | "Sofia",
517 | "Chloe",
518 | "Ella",
519 | "Zoe",
520 | "Samantha",
521 | "Grace",
522 | "Emily",
523 | "Emma",
524 | "Madison",
525 | "Lily",
526 | "Anna",
527 | "Aubrey",
528 | "Hannah",
529 | "Addison",
530 | "Kayla",
531 | "Alyssa",
532 | "Ashley",
533 | "Bella",
534 | "Natalie",
535 | "Victoria",
536 | "Sarah",
537 | "Kaitlyn",
538 | "Layla",
539 | "Alexa",
540 | "Olivia",
541 | "Savannah",
542 | "Sydney",
543 | "Taylor",
544 | "Kimberly",
545 | "Morgan",
546 | "Jasmine",
547 | "Eva",
548 | "Riley",
549 | "Quinn",
550 | "Jasmine",
551 | "Gabriella",
552 | "Aria",
553 | "Elena",
554 | "Isabel",
555 | "Nora",
556 | "Maya",
557 | "Lillian",
558 | "Stella",
559 | "Gabrielle",
560 | "Lauren",
561 | "Skylar",
562 | "Natalia",
563 | "Katherine",
564 | "Alexa",
565 | "Camila",
566 | "Makayla",
567 | "Kylie",
568 | "Brooklyn",
569 | "Audrey",
570 | "Ivy",
571 | "Eleanor",
572 | "Adriana",
573 | "Leah",
574 | "Mia",
575 | "Caroline",
576 | "Kennedy",
577 | "Piper",
578 | "Maria",
579 | "Lilyana",
580 | "Julia",
581 | "Isla",
582 | "Evelyn",
583 | "Genesis",
584 | "Melanie",
585 | "Scarlett",
586 | "Hayley",
587 | "Serena",
588 | "Valentina",
589 | "Angelina",
590 | "Claire",
591 | "Maya",
592 | "Abigail",
593 | "Ada",
594 | "Adela",
595 | "Adriana",
596 | "Agnes",
597 | "Aisha",
598 | "Alana",
599 | "Alejandra",
600 | "Alexa",
601 | "Alexandra",
602 | "Alice",
603 | "Alina",
604 | "Alisa",
605 | "Alisha",
606 | "Alivia",
607 | "Alyssa",
608 | "Amalia",
609 | "Amanda",
610 | "Amara",
611 | "Amaya",
612 | "Amelia",
613 | "Amira",
614 | "Amy",
615 | "Ana",
616 | "Anastasia",
617 | "Andrea",
618 | "Angela",
619 | "Angelica",
620 | "Angelina",
621 | "Angie",
622 | "Anika",
623 | "Anita",
624 | "Anna",
625 | "Annabelle",
626 | "Anne",
627 | "Annie",
628 | "April",
629 | "Aria",
630 | "Ariana",
631 | "Arianna",
632 | "Ariel",
633 | "Arabella",
634 | "Aria",
635 | "Ashley",
636 | "Aspen",
637 | "Athena",
638 | "Aubree",
639 | "Aubrey",
640 | "Audrey",
641 | "Aurora",
642 | "Autumn",
643 | "Ava",
644 | "Avery",
645 | "Ayla",
646 | "Bailey",
647 | "Barbara",
648 | "Beatrice",
649 | "Bella",
650 | "Bernadette",
651 | "Bethany",
652 | "Bianca",
653 | "Blake",
654 | "Brenda",
655 | "Briana",
656 | "Brianna",
657 | "Bridget",
658 | "Brinley",
659 | "Britney",
660 | "Brooke",
661 | "Brynn",
662 | "Caitlin",
663 | "Caitlyn",
664 | "Camila",
665 | "Candice",
666 | "Carla",
667 | "Carmen",
668 | "Caroline",
669 | "Carolyn",
670 | "Casey",
671 | "Cassandra",
672 | "Catherine",
673 | "Cecilia",
674 | "Celeste",
675 | "Celia",
676 | "Charlotte",
677 | "Chelsea",
678 | "Cheyenne",
679 | "Chloe",
680 | "Christina",
681 | "Christine",
682 | "Cindy",
683 | "Claire",
684 | "Clara",
685 | "Clarissa",
686 | "Claudia",
687 | "Colette",
688 | "Colleen",
689 | "Constance",
690 | "Cora",
691 | "Corinne",
692 | "Courtney",
693 | "Crystal",
694 | "Cynthia",
695 | "Daisy",
696 | "Dakota",
697 | "Dana",
698 | "Daniela",
699 | "Danielle",
700 | "Daphne",
701 | "Darlene",
702 | "Delaney",
703 | "Delilah",
704 | "Denise",
705 | "Desiree",
706 | "Destiny",
707 | "Diana",
708 | "Dina",
709 | "Dora",
710 | "Dorothy",
711 | "Eden",
712 | "Eleanor",
713 | "Elena",
714 | "Eliana",
715 | "Eliza",
716 | "Elizabeth",
717 | "Ella",
718 | "Ellie",
719 | "Eloise",
720 | "Elsa",
721 | "Emerson",
722 | "Emery",
723 | "Emilia",
724 | "Emily",
725 | "Emma",
726 | "Emmy",
727 | "Erica",
728 | "Erika",
729 | "Erin",
730 | "Esmeralda",
731 | "Estelle",
732 | "Esther",
733 | "Eva",
734 | "Evangeline",
735 | "Eve",
736 | "Evelyn",
737 | "Faith",
738 | "Fatima",
739 | "Fiona",
740 | "Francesca",
741 | "Gabriela",
742 | "Gabriella",
743 | "Gabrielle",
744 | "Gemma",
745 | "Genesis",
746 | "Genevieve",
747 | "Georgia",
748 | "Gianna",
749 | "Giselle",
750 | "Gloria",
751 | "Grace",
752 | "Gracie",
753 | "Gwendolyn",
754 | "Hadley",
755 | "Hailey",
756 | "Haley",
757 | "Hanna",
758 | "Hannah",
759 | "Harmony",
760 | "Harper",
761 | "Hazel",
762 | "Heidi",
763 | "Helena",
764 | "Hope",
765 | "Imani",
766 | "India",
767 | "Iris",
768 | "Isabel",
769 | "Isabella",
770 | "Isabelle",
771 | "Ivy",
772 | "Jacqueline",
773 | "Jade",
774 | "Jasmine",
775 | "Jayla",
776 | "Jenna",
777 | "Jennifer",
778 | "Jessica",
779 | "Jillian",
780 | "Jocelyn",
781 | "Joelle",
782 | "Josephine",
783 | "Josie",
784 | "Joy",
785 | "Julia",
786 | "Juliana",
787 | "Julianna",
788 | "Julie",
789 | "Juliet",
790 | "June",
791 | "Kaia",
792 | "Kaitlyn",
793 | "Kara",
794 | "Karen",
795 | "Karina",
796 | "Katelyn",
797 | "Katherine",
798 | "Kathleen",
799 | "Katie",
800 | "Kayla",
801 | "Kaylee",
802 | "Keira",
803 | "Kelly",
804 | "Kelsey",
805 | "Kendall",
806 | "Kennedy",
807 | "Khloe",
808 | "Kimberly",
809 | "Kinsley",
810 | "Kira",
811 | "Kylie",
812 | "Laila",
813 | "Lana",
814 | "Lara",
815 | "Laura",
816 | "Lauren",
817 | "Layla",
818 | "Leah",
819 | "Leila",
820 | "Lena",
821 | "Leona",
822 | "Leslie",
823 | "Lila",
824 | "Liliana",
825 | "Lillian",
826 | "Lily",
827 | "Linda",
828 | "London",
829 | "Lorelei",
830 | "Lucia",
831 | "Lucy",
832 | "Luna",
833 | "Lydia",
834 | "Lyla",
835 | "Lyric",
836 | "Mackenzie",
837 | "Macy",
838 | "Madeline",
839 | "Madelyn",
840 | "Madison",
841 | "Maeve",
842 | "Maggie",
843 | "Makayla",
844 | "Makenzie",
845 | "Malaysia",
846 | "Malia",
847 | "Mallory",
848 | "Mara",
849 | "Margaret",
850 | "Maria",
851 | "Mariah",
852 | "Marina",
853 | "Marissa",
854 | "Marjorie",
855 | "Marley",
856 | "Mary",
857 | "Maya",
858 | "Mckenna",
859 | "Megan",
860 | "Melanie",
861 | "Melissa",
862 | "Melody",
863 | "Meredith",
864 | "Mia",
865 | "Michaela",
866 | "Michelle",
867 | "Mikayla",
868 | "Mila",
869 | "Miley",
870 | "Miranda",
871 | "Miriam",
872 | "Molly",
873 | "Monica",
874 | "Morgan",
875 | "Mya",
876 | "Nadia",
877 | "Naomi",
878 | "Natalia",
879 | "Natalie",
880 | "Natasha",
881 | "Naya",
882 | "Nevaeh",
883 | "Nicole",
884 | "Nina",
885 | "Noelle",
886 | "Norah",
887 | "Nora",
888 | "Nova",
889 | "Olivia",
890 | "Ophelia",
891 | "Paige",
892 | "Paisley",
893 | "Payton",
894 | "Penelope",
895 | "Phoebe",
896 | "Piper",
897 | "Presley",
898 | "Priscilla",
899 | "Rachel",
900 | "Raegan",
901 | "Raina",
902 | "Rebecca",
903 | "Reese",
904 | "Regina",
905 | "Riley",
906 | "Rosa",
907 | "Rose",
908 | "Rosie",
909 | "Ruby",
910 | "Ruth",
911 | "Sabrina",
912 | "Sadie",
913 | "Samantha",
914 | "Samara",
915 | "Sandra",
916 | "Sara",
917 | "Sarah",
918 | "Savannah",
919 | "Scarlet",
920 | "Serena",
921 | "Shelby",
922 | "Sienna",
923 | "Sierra",
924 | "Simone",
925 | "Skye",
926 | "Skylar",
927 | "Sofia",
928 | "Sophia",
929 | "Sophie",
930 | "Stella",
931 | "Stephanie",
932 | "Summer",
933 | "Sydney",
934 | "Sylvia",
935 | "Talia",
936 | "Tatiana",
937 | "Teresa",
938 | "Tessa",
939 | "Theresa",
940 | "Tiffany",
941 | "Valentina",
942 | "Valeria",
943 | "Valerie",
944 | "Vanessa",
945 | "Vera",
946 | "Veronica",
947 | "Victoria",
948 | "Violet",
949 | "Vivian",
950 | "Wendy",
951 | "Whitney",
952 | "Willow",
953 | "Winter",
954 | "Yara",
955 | "Zara",
956 | "Zoe",
957 | "Zoey"
958 | ]
959 | }
960 | }
--------------------------------------------------------------------------------
/env/data/map_receptacle_data.json:
--------------------------------------------------------------------------------
1 | {
2 | "0": {},
3 | "1": {
4 | "room10": {
5 | "receptacles": [
6 | {
7 | "name": "table",
8 | "x": [
9 | 152,
10 | 154
11 | ],
12 | "y": [
13 | 213,
14 | 215
15 | ],
16 | "position": [
17 | 153,
18 | 214
19 | ],
20 | "floor": 1
21 | },
22 | {
23 | "name": "table",
24 | "x": [
25 | 160,
26 | 162
27 | ],
28 | "y": [
29 | 212,
30 | 214
31 | ],
32 | "position": [
33 | 161,
34 | 213
35 | ],
36 | "floor": 1
37 | },
38 | {
39 | "name": "reception counter",
40 | "x": [
41 | 136,
42 | 139
43 | ],
44 | "y": [
45 | 208,
46 | 225
47 | ],
48 | "position": [
49 | 138,
50 | 216
51 | ],
52 | "floor": 1
53 | },
54 | {
55 | "name": "table",
56 | "x": [
57 | 160,
58 | 162
59 | ],
60 | "y": [
61 | 220,
62 | 222
63 | ],
64 | "position": [
65 | 161,
66 | 221
67 | ],
68 | "floor": 1
69 | },
70 | {
71 | "name": "table",
72 | "x": [
73 | 156,
74 | 158
75 | ],
76 | "y": [
77 | 215,
78 | 219
79 | ],
80 | "position": [
81 | 157,
82 | 217
83 | ],
84 | "floor": 1
85 | }
86 | ],
87 | "receptacle_names": [
88 | "table",
89 | "table",
90 | "reception counter",
91 | "table",
92 | "table"
93 | ]
94 | },
95 | "room0": {
96 | "receptacles": [
97 | {
98 | "name": "table",
99 | "x": [
100 | 153,
101 | 159
102 | ],
103 | "y": [
104 | 179,
105 | 182
106 | ],
107 | "position": [
108 | 156,
109 | 180
110 | ],
111 | "floor": 1
112 | },
113 | {
114 | "name": "table",
115 | "x": [
116 | 153,
117 | 159
118 | ],
119 | "y": [
120 | 171,
121 | 174
122 | ],
123 | "position": [
124 | 156,
125 | 172
126 | ],
127 | "floor": 1
128 | }
129 | ],
130 | "receptacle_names": [
131 | "table",
132 | "table"
133 | ]
134 | },
135 | "room1": {
136 | "receptacles": [
137 | {
138 | "name": "polygon table",
139 | "x": [
140 | 107,
141 | 111
142 | ],
143 | "y": [
144 | 176,
145 | 183
146 | ],
147 | "position": [
148 | 109,
149 | 180
150 | ],
151 | "floor": 1
152 | }
153 | ],
154 | "receptacle_names": [
155 | "polygon table"
156 | ]
157 | },
158 | "room5": {
159 | "receptacles": [
160 | {
161 | "name": "desk",
162 | "x": [
163 | 18,
164 | 26
165 | ],
166 | "y": [
167 | 171,
168 | 179
169 | ],
170 | "position": [
171 | 22,
172 | 175
173 | ],
174 | "floor": 1
175 | }
176 | ],
177 | "receptacle_names": [
178 | "desk"
179 | ]
180 | }
181 | },
182 | "2": {
183 | "room19": {
184 | "receptacles": [
185 | {
186 | "name": "desk",
187 | "x": [
188 | 71,
189 | 74
190 | ],
191 | "y": [
192 | 207,
193 | 214
194 | ],
195 | "position": [
196 | 72,
197 | 210
198 | ],
199 | "floor": 2
200 | },
201 | {
202 | "name": "desk",
203 | "x": [
204 | 88,
205 | 91
206 | ],
207 | "y": [
208 | 220,
209 | 227
210 | ],
211 | "position": [
212 | 90,
213 | 224
214 | ],
215 | "floor": 2
216 | },
217 | {
218 | "name": "desk",
219 | "x": [
220 | 71,
221 | 74
222 | ],
223 | "y": [
224 | 220,
225 | 227
226 | ],
227 | "position": [
228 | 72,
229 | 224
230 | ],
231 | "floor": 2
232 | },
233 | {
234 | "name": "desk",
235 | "x": [
236 | 91,
237 | 95
238 | ],
239 | "y": [
240 | 207,
241 | 214
242 | ],
243 | "position": [
244 | 93,
245 | 210
246 | ],
247 | "floor": 2
248 | },
249 | {
250 | "name": "desk",
251 | "x": [
252 | 74,
253 | 78
254 | ],
255 | "y": [
256 | 207,
257 | 214
258 | ],
259 | "position": [
260 | 76,
261 | 210
262 | ],
263 | "floor": 2
264 | },
265 | {
266 | "name": "desk",
267 | "x": [
268 | 74,
269 | 78
270 | ],
271 | "y": [
272 | 220,
273 | 227
274 | ],
275 | "position": [
276 | 76,
277 | 224
278 | ],
279 | "floor": 2
280 | },
281 | {
282 | "name": "desk",
283 | "x": [
284 | 91,
285 | 95
286 | ],
287 | "y": [
288 | 220,
289 | 227
290 | ],
291 | "position": [
292 | 93,
293 | 224
294 | ],
295 | "floor": 2
296 | },
297 | {
298 | "name": "desk",
299 | "x": [
300 | 88,
301 | 91
302 | ],
303 | "y": [
304 | 207,
305 | 214
306 | ],
307 | "position": [
308 | 90,
309 | 210
310 | ],
311 | "floor": 2
312 | },
313 | {
314 | "name": "side table",
315 | "x": [
316 | 81,
317 | 84
318 | ],
319 | "y": [
320 | 212,
321 | 223
322 | ],
323 | "position": [
324 | 82,
325 | 218
326 | ],
327 | "floor": 2
328 | }
329 | ],
330 | "receptacle_names": [
331 | "desk",
332 | "desk",
333 | "desk",
334 | "desk",
335 | "desk",
336 | "desk",
337 | "desk",
338 | "desk",
339 | "side table"
340 | ]
341 | },
342 | "room17": {
343 | "receptacles": [
344 | {
345 | "name": "desk",
346 | "x": [
347 | 40,
348 | 50
349 | ],
350 | "y": [
351 | 172,
352 | 180
353 | ],
354 | "position": [
355 | 45,
356 | 176
357 | ],
358 | "floor": 2
359 | }
360 | ],
361 | "receptacle_names": [
362 | "desk"
363 | ]
364 | },
365 | "room0": {
366 | "receptacles": [
367 | {
368 | "name": "table",
369 | "x": [
370 | 103,
371 | 111
372 | ],
373 | "y": [
374 | 92,
375 | 93
376 | ],
377 | "position": [
378 | 107,
379 | 92
380 | ],
381 | "floor": 2
382 | },
383 | {
384 | "name": "bed",
385 | "x": [
386 | 112,
387 | 119
388 | ],
389 | "y": [
390 | 100,
391 | 107
392 | ],
393 | "position": [
394 | 116,
395 | 104
396 | ],
397 | "floor": 2
398 | }
399 | ],
400 | "receptacle_names": [
401 | "table",
402 | "bed"
403 | ]
404 | },
405 | "room1": {
406 | "receptacles": [
407 | {
408 | "name": "table",
409 | "x": [
410 | 153,
411 | 161
412 | ],
413 | "y": [
414 | 112,
415 | 114
416 | ],
417 | "position": [
418 | 157,
419 | 113
420 | ],
421 | "floor": 2
422 | },
423 | {
424 | "name": "bed",
425 | "x": [
426 | 145,
427 | 152
428 | ],
429 | "y": [
430 | 98,
431 | 106
432 | ],
433 | "position": [
434 | 148,
435 | 102
436 | ],
437 | "floor": 2
438 | }
439 | ],
440 | "receptacle_names": [
441 | "table",
442 | "bed"
443 | ]
444 | },
445 | "room2": {
446 | "receptacles": [
447 | {
448 | "name": "table",
449 | "x": [
450 | 103,
451 | 111
452 | ],
453 | "y": [
454 | 66,
455 | 68
456 | ],
457 | "position": [
458 | 107,
459 | 67
460 | ],
461 | "floor": 2
462 | },
463 | {
464 | "name": "bed",
465 | "x": [
466 | 112,
467 | 119
468 | ],
469 | "y": [
470 | 74,
471 | 82
472 | ],
473 | "position": [
474 | 116,
475 | 78
476 | ],
477 | "floor": 2
478 | }
479 | ],
480 | "receptacle_names": [
481 | "table",
482 | "bed"
483 | ]
484 | },
485 | "room3": {
486 | "receptacles": [
487 | {
488 | "name": "table",
489 | "x": [
490 | 153,
491 | 161
492 | ],
493 | "y": [
494 | 163,
495 | 165
496 | ],
497 | "position": [
498 | 157,
499 | 164
500 | ],
501 | "floor": 2
502 | },
503 | {
504 | "name": "bed",
505 | "x": [
506 | 145,
507 | 152
508 | ],
509 | "y": [
510 | 149,
511 | 157
512 | ],
513 | "position": [
514 | 148,
515 | 153
516 | ],
517 | "floor": 2
518 | }
519 | ],
520 | "receptacle_names": [
521 | "table",
522 | "bed"
523 | ]
524 | },
525 | "room4": {
526 | "receptacles": [
527 | {
528 | "name": "table",
529 | "x": [
530 | 103,
531 | 111
532 | ],
533 | "y": [
534 | 117,
535 | 119
536 | ],
537 | "position": [
538 | 107,
539 | 118
540 | ],
541 | "floor": 2
542 | },
543 | {
544 | "name": "bed",
545 | "x": [
546 | 112,
547 | 119
548 | ],
549 | "y": [
550 | 126,
551 | 133
552 | ],
553 | "position": [
554 | 116,
555 | 130
556 | ],
557 | "floor": 2
558 | }
559 | ],
560 | "receptacle_names": [
561 | "table",
562 | "bed"
563 | ]
564 | },
565 | "room16": {
566 | "receptacles": [
567 | {
568 | "name": "table",
569 | "x": [
570 | 160,
571 | 162
572 | ],
573 | "y": [
574 | 212,
575 | 214
576 | ],
577 | "position": [
578 | 161,
579 | 213
580 | ],
581 | "floor": 2
582 | },
583 | {
584 | "name": "table",
585 | "x": [
586 | 152,
587 | 154
588 | ],
589 | "y": [
590 | 213,
591 | 215
592 | ],
593 | "position": [
594 | 153,
595 | 214
596 | ],
597 | "floor": 2
598 | },
599 | {
600 | "name": "reception counter",
601 | "x": [
602 | 136,
603 | 139
604 | ],
605 | "y": [
606 | 208,
607 | 225
608 | ],
609 | "position": [
610 | 138,
611 | 216
612 | ],
613 | "floor": 2
614 | },
615 | {
616 | "name": "table",
617 | "x": [
618 | 156,
619 | 158
620 | ],
621 | "y": [
622 | 215,
623 | 219
624 | ],
625 | "position": [
626 | 157,
627 | 217
628 | ],
629 | "floor": 2
630 | },
631 | {
632 | "name": "table",
633 | "x": [
634 | 160,
635 | 162
636 | ],
637 | "y": [
638 | 220,
639 | 222
640 | ],
641 | "position": [
642 | 161,
643 | 221
644 | ],
645 | "floor": 2
646 | }
647 | ],
648 | "receptacle_names": [
649 | "table",
650 | "table",
651 | "reception counter",
652 | "table",
653 | "table"
654 | ]
655 | },
656 | "room5": {
657 | "receptacles": [
658 | {
659 | "name": "table",
660 | "x": [
661 | 153,
662 | 161
663 | ],
664 | "y": [
665 | 61,
666 | 63
667 | ],
668 | "position": [
669 | 157,
670 | 62
671 | ],
672 | "floor": 2
673 | },
674 | {
675 | "name": "bed",
676 | "x": [
677 | 145,
678 | 152
679 | ],
680 | "y": [
681 | 47,
682 | 54
683 | ],
684 | "position": [
685 | 148,
686 | 50
687 | ],
688 | "floor": 2
689 | }
690 | ],
691 | "receptacle_names": [
692 | "table",
693 | "bed"
694 | ]
695 | },
696 | "room15": {
697 | "receptacles": [
698 | {
699 | "name": "desk",
700 | "x": [
701 | 50,
702 | 59
703 | ],
704 | "y": [
705 | 171,
706 | 179
707 | ],
708 | "position": [
709 | 54,
710 | 175
711 | ],
712 | "floor": 2
713 | }
714 | ],
715 | "receptacle_names": [
716 | "desk"
717 | ]
718 | },
719 | "room6": {
720 | "receptacles": [
721 | {
722 | "name": "table",
723 | "x": [
724 | 103,
725 | 111
726 | ],
727 | "y": [
728 | 15,
729 | 17
730 | ],
731 | "position": [
732 | 107,
733 | 16
734 | ],
735 | "floor": 2
736 | },
737 | {
738 | "name": "bed",
739 | "x": [
740 | 112,
741 | 119
742 | ],
743 | "y": [
744 | 23,
745 | 30
746 | ],
747 | "position": [
748 | 116,
749 | 26
750 | ],
751 | "floor": 2
752 | }
753 | ],
754 | "receptacle_names": [
755 | "table",
756 | "bed"
757 | ]
758 | },
759 | "room7": {
760 | "receptacles": [
761 | {
762 | "name": "table",
763 | "x": [
764 | 153,
765 | 161
766 | ],
767 | "y": [
768 | 86,
769 | 88
770 | ],
771 | "position": [
772 | 157,
773 | 87
774 | ],
775 | "floor": 2
776 | },
777 | {
778 | "name": "bed",
779 | "x": [
780 | 145,
781 | 152
782 | ],
783 | "y": [
784 | 73,
785 | 80
786 | ],
787 | "position": [
788 | 148,
789 | 76
790 | ],
791 | "floor": 2
792 | }
793 | ],
794 | "receptacle_names": [
795 | "table",
796 | "bed"
797 | ]
798 | },
799 | "room8": {
800 | "receptacles": [
801 | {
802 | "name": "table",
803 | "x": [
804 | 153,
805 | 161
806 | ],
807 | "y": [
808 | 138,
809 | 140
810 | ],
811 | "position": [
812 | 157,
813 | 139
814 | ],
815 | "floor": 2
816 | },
817 | {
818 | "name": "bed",
819 | "x": [
820 | 145,
821 | 152
822 | ],
823 | "y": [
824 | 124,
825 | 131
826 | ],
827 | "position": [
828 | 148,
829 | 128
830 | ],
831 | "floor": 2
832 | }
833 | ],
834 | "receptacle_names": [
835 | "table",
836 | "bed"
837 | ]
838 | },
839 | "room9": {
840 | "receptacles": [
841 | {
842 | "name": "table",
843 | "x": [
844 | 103,
845 | 111
846 | ],
847 | "y": [
848 | 40,
849 | 42
850 | ],
851 | "position": [
852 | 107,
853 | 41
854 | ],
855 | "floor": 2
856 | },
857 | {
858 | "name": "bed",
859 | "x": [
860 | 112,
861 | 119
862 | ],
863 | "y": [
864 | 49,
865 | 56
866 | ],
867 | "position": [
868 | 116,
869 | 52
870 | ],
871 | "floor": 2
872 | }
873 | ],
874 | "receptacle_names": [
875 | "table",
876 | "bed"
877 | ]
878 | },
879 | "room22": {
880 | "receptacles": [
881 | {
882 | "name": "coffee table",
883 | "x": [
884 | 42,
885 | 45
886 | ],
887 | "y": [
888 | 216,
889 | 221
890 | ],
891 | "position": [
892 | 44,
893 | 218
894 | ],
895 | "floor": 2
896 | },
897 | {
898 | "name": "dinner counter",
899 | "x": [
900 | 56,
901 | 59
902 | ],
903 | "y": [
904 | 212,
905 | 223
906 | ],
907 | "position": [
908 | 58,
909 | 218
910 | ],
911 | "floor": 2
912 | }
913 | ],
914 | "receptacle_names": [
915 | "coffee table",
916 | "dinner counter"
917 | ]
918 | },
919 | "room10": {
920 | "receptacles": [
921 | {
922 | "name": "table",
923 | "x": [
924 | 153,
925 | 161
926 | ],
927 | "y": [
928 | 35,
929 | 37
930 | ],
931 | "position": [
932 | 157,
933 | 36
934 | ],
935 | "floor": 2
936 | },
937 | {
938 | "name": "bed",
939 | "x": [
940 | 145,
941 | 152
942 | ],
943 | "y": [
944 | 21,
945 | 29
946 | ],
947 | "position": [
948 | 148,
949 | 25
950 | ],
951 | "floor": 2
952 | }
953 | ],
954 | "receptacle_names": [
955 | "table",
956 | "bed"
957 | ]
958 | },
959 | "room23": {
960 | "receptacles": [
961 | {
962 | "name": "meeting table large",
963 | "x": [
964 | 74,
965 | 92
966 | ],
967 | "y": [
968 | 176,
969 | 181
970 | ],
971 | "position": [
972 | 83,
973 | 178
974 | ],
975 | "floor": 2
976 | }
977 | ],
978 | "receptacle_names": [
979 | "meeting table large"
980 | ]
981 | },
982 | "room11": {
983 | "receptacles": [
984 | {
985 | "name": "small table",
986 | "x": [
987 | 14,
988 | 16
989 | ],
990 | "y": [
991 | 169,
992 | 171
993 | ],
994 | "position": [
995 | 15,
996 | 170
997 | ],
998 | "floor": 2
999 | },
1000 | {
1001 | "name": "table",
1002 | "x": [
1003 | 9,
1004 | 17
1005 | ],
1006 | "y": [
1007 | 180,
1008 | 183
1009 | ],
1010 | "position": [
1011 | 13,
1012 | 182
1013 | ],
1014 | "floor": 2
1015 | },
1016 | {
1017 | "name": "kitchen counter",
1018 | "x": [
1019 | 30,
1020 | 33
1021 | ],
1022 | "y": [
1023 | 177,
1024 | 187
1025 | ],
1026 | "position": [
1027 | 32,
1028 | 182
1029 | ],
1030 | "floor": 2
1031 | },
1032 | {
1033 | "name": "kitchen wardrobe",
1034 | "x": [
1035 | 30,
1036 | 32
1037 | ],
1038 | "y": [
1039 | 175,
1040 | 177
1041 | ],
1042 | "position": [
1043 | 31,
1044 | 176
1045 | ],
1046 | "floor": 2
1047 | },
1048 | {
1049 | "name": "dinner counter",
1050 | "x": [
1051 | 21,
1052 | 24
1053 | ],
1054 | "y": [
1055 | 172,
1056 | 183
1057 | ],
1058 | "position": [
1059 | 22,
1060 | 178
1061 | ],
1062 | "floor": 2
1063 | }
1064 | ],
1065 | "receptacle_names": [
1066 | "small table",
1067 | "table",
1068 | "kitchen counter",
1069 | "kitchen wardrobe",
1070 | "dinner counter"
1071 | ]
1072 | },
1073 | "room21": {
1074 | "receptacles": [
1075 | {
1076 | "name": "table",
1077 | "x": [
1078 | 153,
1079 | 159
1080 | ],
1081 | "y": [
1082 | 171,
1083 | 174
1084 | ],
1085 | "position": [
1086 | 156,
1087 | 172
1088 | ],
1089 | "floor": 2
1090 | },
1091 | {
1092 | "name": "table",
1093 | "x": [
1094 | 153,
1095 | 159
1096 | ],
1097 | "y": [
1098 | 179,
1099 | 182
1100 | ],
1101 | "position": [
1102 | 156,
1103 | 180
1104 | ],
1105 | "floor": 2
1106 | }
1107 | ],
1108 | "receptacle_names": [
1109 | "table",
1110 | "table"
1111 | ]
1112 | },
1113 | "room13": {
1114 | "receptacles": [
1115 | {
1116 | "name": "polygon table",
1117 | "x": [
1118 | 107,
1119 | 111
1120 | ],
1121 | "y": [
1122 | 176,
1123 | 183
1124 | ],
1125 | "position": [
1126 | 109,
1127 | 180
1128 | ],
1129 | "floor": 2
1130 | }
1131 | ],
1132 | "receptacle_names": [
1133 | "polygon table"
1134 | ]
1135 | },
1136 | "room14": {
1137 | "receptacles": [
1138 | {
1139 | "name": "furnituregymdesk",
1140 | "x": [
1141 | 100,
1142 | 103
1143 | ],
1144 | "y": [
1145 | 207,
1146 | 210
1147 | ],
1148 | "position": [
1149 | 102,
1150 | 208
1151 | ],
1152 | "floor": 2
1153 | }
1154 | ],
1155 | "receptacle_names": [
1156 | "furnituregymdesk"
1157 | ]
1158 | },
1159 | "room12": {
1160 | "receptacles": [
1161 | {
1162 | "name": "table",
1163 | "x": [
1164 | 103,
1165 | 111
1166 | ],
1167 | "y": [
1168 | 143,
1169 | 145
1170 | ],
1171 | "position": [
1172 | 107,
1173 | 144
1174 | ],
1175 | "floor": 2
1176 | },
1177 | {
1178 | "name": "bed",
1179 | "x": [
1180 | 112,
1181 | 119
1182 | ],
1183 | "y": [
1184 | 151,
1185 | 159
1186 | ],
1187 | "position": [
1188 | 116,
1189 | 155
1190 | ],
1191 | "floor": 2
1192 | }
1193 | ],
1194 | "receptacle_names": [
1195 | "table",
1196 | "bed"
1197 | ]
1198 | }
1199 | }
1200 | }
--------------------------------------------------------------------------------
/env/socket_server.py:
--------------------------------------------------------------------------------
1 | import copy
2 | import sys
3 | import time
4 | import subprocess
5 | # import atexit
6 | from socket import *
7 | import threading
8 | import json
9 | import struct
10 | from enum import Enum
11 | # from game_demo import *
12 | import ast
13 | from env.map_process import RoomMap
14 | from env.npc_control import Npc, Agent
15 | import datetime
16 | import numpy as np
17 |
18 |
19 | class EnvTime(object):
20 | def __init__(self, speed=120, year=2025, month=3, day=12, hour=6, minute=50, second=0, end=2050):
21 | # Define start date. At a rate of speed(120) times
22 | self.start_date = datetime.datetime(year, month, day, hour, minute, second)
23 | # Define time multiplier
24 | self.time_multiplier = speed
25 | self.running = 1
26 | self.end = end
27 | # Simulation time
28 | self.current_date = self.start_date
29 | self.start_time = self.start_date
30 | # self.current_date.isoweekday()
31 | self.week = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
32 |
33 | def set_time(self, year=2025, month=3, day=12, hour=6, minute=50, second=0, end=2050):
34 | self.current_date = datetime.datetime(year, month, day, hour, minute, second)
35 | print(self.current_date)
36 |
37 | def time_simulation(self, stop_event):
38 | while True:
39 | # print(stop_event.is_set())
40 | if not self.running or stop_event.is_set():
41 | break
42 | # print("Current Date:", self.current_date)
43 | # Accelerate at 120 times the speed
44 | time_delta = datetime.timedelta(seconds=1) # Add one more day
45 | self.current_date += time_delta * self.time_multiplier
46 | # Control simulation speed
47 | time.sleep(1) # Update every second
48 | # Termination conditions can be added, such as stopping simulation when a specific date is reached
49 | if self.current_date.year > self.end:
50 | break
51 |
52 | def time_difference(self):
53 | time_diff = self.current_date - self.start_time
54 | hours = time_diff.total_seconds() // 3600
55 | # print("The time difference is% d hours" % hours)
56 | return time_diff.days
57 |
58 | def weekday_now(self):
59 | return self.week[self.current_date.weekday()]
60 |
61 | def simulation_start(self):
62 | self.start_time = self.current_date
63 |
64 |
65 | # message define
66 | class MsgCmd(Enum):
67 | # 0 disconnects, 1 server sends behavior instructions, 2 servers send status requests, 3 clients reply with behavior callbacks,
68 | # 4 clients reply with target status, 5 instructions to robots, 6 requests/feedback about robot clients
69 | EXIT = 0
70 | Instruction = 1
71 | Request = 2
72 | Result = 3
73 | State = 4
74 | Control = 5
75 | Information = 6
76 | Server_Update_Config = 7
77 | Server_Device_Create_Request = 8
78 | Server_Device_Inform_Request = 9
79 | Server_Device_Status_Request = 10
80 | Client_Device_Status_Response = 11
81 | Server_Config_Inform = 12
82 | Client_Config_Response = 13
83 |
84 |
85 | class Server(object):
86 | def __init__(self, stop_event):
87 | self.stop_event = stop_event
88 | self.state = 1
89 | self.clients = []
90 | self.messages = []
91 | self.information = ''
92 | # 1.Create a socket
93 | self.sock = socket(AF_INET, SOCK_STREAM)
94 | # 2. Prepare to connect to the server and establish a connection
95 | serve_ip = 'localhost'
96 | serve_port = 8000 # search for available port starting from 8000
97 | # tcp_socket.connect((serve_ip,serve_port))
98 | # Connect to the server, establish a connection, with parameters in tuple form
99 | tcp_address = ('localhost', serve_port)
100 | # Provide a mechanism for checking ports
101 | sock_result = 0
102 | while not sock_result:
103 | try:
104 | self.sock.bind(tcp_address)
105 | sock_result = 1
106 | except:
107 | serve_port += 1
108 | tcp_address = ('localhost', serve_port)
109 | with open('unity/PRS_Data/StreamingAssets/config.json', 'r') as file:
110 | env_data = json.load(file)
111 | env_data["serverConnectionPort"] = serve_port
112 | with open('unity/PRS_Data/StreamingAssets/config.json', 'w') as file:
113 | json.dump(env_data, file)
114 | print('server started: ', str(tcp_address))
115 | MAX_CONNECTION = 100
116 | # Start listening for connections
117 | self.sock.listen(MAX_CONNECTION)
118 | self.headerSize = 12
119 | self.count = 0
120 | # self.robot = PRS_IK()
121 | # robot ik algorithm
122 | self.maps = RoomMap()
123 | self.notes = {}
124 | self.byte_stream = bytes()
125 | self.header_length = 0
126 | self.sock.settimeout(10)
127 |
128 | def wait_for_connection(self):
129 | while True:
130 | try:
131 | now_client, addr = self.sock.accept()
132 | print('Connected by', now_client)
133 | self.state = 2
134 | now_client.settimeout(300)
135 | self.clients.append([addr, now_client])
136 | except: pass
137 | for index_client, n_client in enumerate(self.clients):
138 | # result = self.sock.connect_ex(n_client)
139 | try:
140 | result = n_client[1].getsockname()
141 | r = n_client[1].getpeername()
142 | # print('===========perfect connection============')
143 | except Exception as e:
144 | print(e, n_client[0], 'Connected Closed Now')
145 | try:
146 | self.clients.remove(n_client)
147 | if len(self.clients) == 0 and self.state == 2:
148 | self.state = 0
149 | self.stop_event.set()
150 | except:
151 | pass
152 | if not self.state or self.stop_event.is_set():
153 | print(self.state, 'No waiting for connection')
154 | self.sock.close()
155 | break
156 | if len(self.clients):
157 | time.sleep(0.5)
158 | else:
159 | time.sleep(0.01)
160 |
161 | def check_connection(self):
162 | pass
163 | # for index_client, n_client in enumerate(self.clients):
164 | # # result = self.sock.connect_ex(n_client)
165 | # rrr = n_client[1].recv(1024)
166 | # result = n_client[1].getsockname()
167 | # r = n_client[1].getpeername()
168 |
169 | def handle_data(self, n_client):
170 | # receive message from client -> information process
171 | data = n_client.recv(10240000)
172 | if not data:
173 | return 0
174 | else:
175 | self.messages.append(data)
176 | # print('---------------------------------', 'Received: msg')
177 | # ------------------parsing info from unity---------------------
178 | # self.send_back({'result': 1})
179 | return 1
180 |
181 | def message_process(self):
182 | while True:
183 | if not self.state or self.stop_event.is_set():
184 | self.state = 0
185 | print(self.state, 'Processing Completed')
186 | break
187 | if len(self.messages) > 0:
188 | for msg_i, msg in enumerate(self.messages):
189 | try:
190 | self.unpack(msg)
191 | except Exception as e:
192 | print('.........parsing error............', e, type(msg))
193 | self.state = 0
194 | finally:
195 | del self.messages[msg_i]
196 | else:
197 | time.sleep(0.005)
198 |
199 | def receive_data(self):
200 | while True:
201 | # self.check_connection()
202 | for n_client in self.clients:
203 | try:
204 | # Processing received message
205 | res = self.handle_data(n_client[1])
206 | except Exception as e:
207 | print(e, n_client[0], 'Connected closed')
208 | try:
209 | self.clients.remove(n_client)
210 | if len(self.clients) == 0 and self.state == 2:
211 | self.state = 0
212 | self.stop_event.set()
213 | except:
214 | pass
215 | time.sleep(0.005)
216 | if not self.state or self.stop_event.is_set():
217 | print(self.state, 'Connection closed')
218 | self.sock.close()
219 | break
220 |
221 | def send_data(self, cmd=1, data={"requestIndex":10,"npcId":0,"actionId":0,"actionPara":""}, recv=0):
222 | send_finish = 0
223 | while not send_finish:
224 | if len(self.clients)==0: break
225 | for n_client in self.clients:
226 | self.check_connection()
227 | try:
228 | if cmd < 15:
229 | data['requestIndex'] = self.count
230 | self.count = self.count + 1
231 | elif cmd == 0:
232 | self.state = 0
233 | msg, msg_data = self.pack(cmd, data, recv)
234 | n_client[1].send(msg)
235 | send_finish = 1
236 | return data['requestIndex']
237 | break
238 | except Exception as e:
239 | # print(e, n_client[0])
240 | try:
241 | self.clients.remove(n_client)
242 | if len(self.clients) == 0:
243 | self.state = 0
244 | except: pass
245 | return False
246 |
247 | def send_back(self, response={'result': 0}):
248 | f = 0
249 | while not f:
250 | for n_client in self.clients:
251 | self.check_connection()
252 | try:
253 | info = json.dumps(response)
254 | n_client[1].send(info.encode("utf8"))
255 | print('Sent: ', info.encode("utf8"))
256 | f = 1
257 | return 1
258 | except Exception as e:
259 | print(e, n_client[0])
260 | try:
261 | self.clients.remove(n_client)
262 | except: pass
263 |
264 | def pack(self, cmd, _body, _recv=0):
265 | body = json.dumps(_body)
266 | # Convert the message body to Json format and convert it to byte encoding
267 | header = [body.__len__(), cmd, _recv]
268 | # Form a list of message headers in order
269 | headPack= struct.pack("3I", *header)
270 | # Use struct to package message headers and obtain byte encoding
271 | sendData = headPack+body.encode("utf8")
272 | # Combine message header bytes and message body bytes together
273 | return sendData, body
274 |
275 | def handle_msg(self, headPack ,body):
276 | """Classify and process received message strings"""
277 | # data processing
278 | cmd= 'ad'
279 | try:
280 | cmd = MsgCmd(headPack[1]).name # Get the value of Code\
281 | except Exception as e:
282 | print(headPack[1])
283 | # print('python get================cmd is', cmd)
284 | is_recv = headPack[2]
285 | # print("Received 1 packet->bodySize:{}, cmd:{}, recv:{}".format(headPack[0], cmd, is_recv))
286 | body = body.replace("false", "False")
287 | body = body.replace("true", "True")
288 | body = body.replace("none", "None")
289 | p = json.loads(body) # Decode and deserialize strings into JSON objects
290 | dict_data = ast.literal_eval(p)
291 | # self.information += str(cmd) + str(body)
292 | # Check the message type
293 | dict_d = copy.deepcopy(dict_data)
294 | del dict_d['requestIndex']
295 | self.notes[dict_data['requestIndex']] = dict_d
296 | if cmd == "EXIT":
297 | self.state = 0
298 | print('0. Env is over, exit!')
299 | return
300 | elif cmd == "Result": pass
301 | # print('3、Execution results from Unity', dict_data)
302 | elif cmd == "State": pass
303 | # Storing parameter information
304 | # print('4、Detailed information obtained id: {}'.format(dict_data['requestIndex']))
305 | elif cmd == "Control": pass
306 | # IK is here
307 | elif cmd == "Information": pass
308 | # print("6、This is robot information", dict_data['requestIndex'], ', length- ', len(dict_data),)
309 | else: pass
310 | # print("\nUnknown cmd: {0}".format(cmd))
311 | # Continue receiving messages
312 | #self._recv_bytes()
313 |
314 | def unpack(self, data):
315 | headPack = struct.unpack('3I', bytearray(data[:self.headerSize]))
316 | bodySize = headPack[0]
317 | body = data[self.headerSize:self.headerSize + bodySize]
318 | try:
319 | self.handle_msg(headPack, body.decode("utf8"))
320 | except ValueError:
321 | if not self.header_length or len(self.byte_stream) == 0:
322 | self.header_length = headPack
323 | self.byte_stream += body
324 | else:
325 | self.byte_stream += data
326 | if len(self.byte_stream) >= self.header_length[0]:
327 | # data_byte = self.byte_stream.decode("utf8")
328 | self.handle_msg(self.header_length, self.byte_stream.decode())
329 | self.byte_stream = bytes()
330 | self.header_length = 0
331 | return 1
332 |
333 | def unpack_pro(self, data, msgHandler):
334 | dataBuffer = bytes()
335 | if data:
336 | self.dataBuffer += data
337 | while True:
338 | # Jump out of the function to continue receiving data when there is insufficient data in the message header
339 | if len(self.dataBuffer) < self.headerSize:
340 | # print("Packet (% s Byte) is smaller than the length of the message header, causing a small loop to break out" % len(self.dataBuffer))
341 | break
342 | # struct: represent Network order,3I represents 3个unsigned int
343 | # msg_length = struct.unpack("I", bytearray(msg[:4]))[0]
344 | # Obtain information length
345 | headPack = struct.unpack('3I', bytearray(self.dataBuffer[:self.headerSize]))
346 | # Decode the message header
347 | # Get message body length
348 | bodySize = headPack[0]
349 | # Handling subcontracting situations, jumping out of the function to continue receiving data
350 | if len(self.dataBuffer) < self.headerSize + bodySize:
351 | # print("Packet (% s Byte) incomplete (total of% s Bytes), skipping small loop“ % (len(self.dataBuffer), self.headerSize + bodySize))
352 | break
353 | # Read the content of the message body
354 | body = self.dataBuffer[self.headerSize:self.headerSize + bodySize]
355 | self.handle_msg(headPack, body.decode("utf8"))
356 | # Handling of packet sticking and obtaining the next part of the data packet
357 | self.dataBuffer = self.dataBuffer[self.headerSize + bodySize:]
358 | if len(self.dataBuffer) != 0:
359 | return True # Continue receiving messages
360 | else:
361 | return False # No longer receiving messages
362 | else:
363 | return False # No longer receiving messages
364 |
365 | def wait_for_respond(self, id, times=60):
366 | info = None
367 | for ii in range(int(times)):
368 | time.sleep(0.1)
369 | try:
370 | info = self.notes[id]
371 | break
372 | except Exception as e:
373 | pass
374 | return info
375 |
376 | def object_query(self, obj_id=0):
377 | for i in range(5):
378 | instruction = {"requestIndex": 0, "targetType": 1, "targetId": obj_id}
379 | r_id = self.send_data(2, instruction, 1)
380 | object_info = self.wait_for_respond(r_id, 60)
381 | if object_info is not None:
382 | break
383 | time.sleep(0.1)
384 | if object_info:
385 | object_info = eval(object_info['statusDetail'])
386 | return object_info
387 |
388 | def object_nearby_detect(self, obj_id=0):
389 | instruction = {"requestIndex": 1, "targetType": 20, "targetId": obj_id}
390 | r_id = self.send_data(2, instruction, 1)
391 | object_info = self.wait_for_respond(r_id, 60)
392 | if object_info:
393 | object_info = eval(object_info['statusDetail'])
394 | return object_info['touchedIds']
395 | if object_info:
396 | object_info = eval(object_info['statusDetail'])
397 | try:
398 | return object_info['touchedIds']
399 | except:
400 | return None
401 | return None
402 |
403 | def object_transform(self, obj_type=0, target_id=4, pos=(0, 0, 0), rotation=0):
404 | # obj_type = 0: npc, obj_type = 1: items in the env
405 | try:
406 | position = {"x": pos[0], "y": pos[1], "z": pos[2]}
407 | except:
408 | position = {"x": pos['x'], "y": pos['y'], "z": pos['z']}
409 | instruction = {"requestIndex": 1, "objectTransformHandles": []}
410 | para = {"objectType": obj_type, "objectId": target_id, "objectPos": position, "objectDir":
411 | {"x": 0, "y": 90, "z": 0}}
412 | instruction['objectTransformHandles'].append(para)
413 | r_id = self.send_data(12, instruction, 1)
414 | object_info = self.wait_for_respond(r_id, 60)
415 | time.sleep(0.2)
416 | return object_info
417 |
418 | def env_finish(self, process, npcs):
419 | if process:
420 | process.terminate()
421 | # Waiting for the process to end (optional, but recommended)
422 | process.wait()
423 | self.send_data(0, {"requestIndex": 10, "actionId": 1}, 0)
424 | # movement demo
425 | self.state = 0
426 | for npc in npcs:
427 | npc.running = 0
428 | self.stop_event.set()
429 | self.sock.close()
430 | # print(self.state, type(self.state))
431 | print(threading.active_count(), ' ------ env is ready to end')
432 | time.sleep(3)
433 | print(threading.active_count(), ' ------ thank you for using')
434 |
435 |
436 | class ObjectsData(object):
437 | def __init__(self):
438 | with open('unity/PRS_Data/StreamingAssets/itemInfo.json', 'r') as file:
439 | json_data = json.load(file)
440 | with open('env/data/map_room_data.json', 'r') as file:
441 | room_data = json.load(file)
442 | with open('env/data/map_receptacle_data.json', 'r') as file:
443 | receptacles = json.load(file)
444 | with open('env/data/npc_data.json', 'r') as file:
445 | json_npc = json.load(file)
446 | with open('env/data/room_mapping.json', 'r') as file:
447 | room_names = json.load(file)
448 | with open('env/data/room_sampling_points.json', 'r') as file:
449 | self.room_sampling_points = json.load(file)
450 | # decode JSON
451 |
452 | env_objects = []
453 | for json_i in json_data['statusDetails']:
454 | data = json.loads(json_i)
455 | env_objects.append(data)
456 | env_rooms = []
457 | for floor_i in list(room_data.keys()):
458 | for identifier, r_data in room_data[floor_i].items():
459 | room_information = dict()
460 | room_name = room_names[floor_i][identifier]
461 | room_information['name'] = room_name
462 | room_information['floor'] = int(floor_i)
463 | x, y = (r_data['x'][1] + r_data['x'][0]) / 2, (r_data['y'][1] + r_data['y'][0])/2
464 | room_information['position'] = (int(floor_i), round(x), round(y))
465 | room_information['x'], room_information['y'] = r_data['x'], r_data['y']
466 | room_information['id'] = identifier
467 | room_information['semantic_name'] = floor_i + '_' + room_name
468 | try:
469 | room_information['receptacles'] = receptacles[floor_i][identifier]['receptacles']
470 | room_information['receptacles_list'] = receptacles[floor_i][identifier]['receptacle_names']
471 | except:
472 | room_information['receptacles'] = dict()
473 | room_information['receptacles_list'] = []
474 | env_rooms.append(room_information)
475 |
476 | self.objects = env_objects
477 | self.room_area = env_rooms
478 | self.room_receptacles = receptacles
479 | self.characters = json_npc['npc']
480 | self.room_receptacles = None
481 | map0 = np.loadtxt('env/data/semantic_map_0.txt', dtype=int, delimiter='\t')
482 | map1 = np.loadtxt('env/data/semantic_map_1.txt', dtype=int, delimiter='\t')
483 | map2 = np.loadtxt('env/data/semantic_map_2.txt', dtype=int, delimiter='\t')
484 | self.sematic_map = [map0, map1, map2]
485 | with open('env/data/semantic_map_tags.json', 'r') as file:
486 | self.semantic_tags = json.load(file)
487 |
488 | def point_determine(self, pos):
489 | # position not world coordinates, pos: [x, y, z], z is floor
490 | point_P = dict()
491 | try:
492 | point_P['x'], point_P['y'], point_P['z'] = pos['x'], pos['y'], pos['z']
493 | except:
494 | point_P['x'], point_P['y'], point_P['z'] = pos[0], pos[1], pos[2]
495 | res = None
496 | for room_i in self.room_area:
497 | if round(point_P['z']) != round(room_i['floor']):
498 | continue
499 | if (room_i['x'][0] <= point_P['x'] <= room_i['x'][1]) and (
500 | room_i['y'][0] <= point_P['y'] <= room_i['y'][1]):
501 | if abs(point_P['z']-room_i['floor']) < 1:
502 | res = room_i['semantic_name']
503 | return res
504 |
505 | def segment(self):
506 | with open('unity/PRS_Data/StreamingAssets\segmentationTagColorInfo.json', 'r') as file:
507 | seg_tag_data = json.load(file)
508 | seg_data = []
509 | rgb_id = dict()
510 | for index_tag, item_tag in enumerate(seg_tag_data['TagColors']):
511 | # data_i = json.loads(item_tag)
512 | seg_data.append(item_tag)
513 | r_n, g_n, b_n = float(item_tag['color']['r']), float(item_tag['color']['g']), float(item_tag['color']['b'])
514 | r_n, g_n, b_n = '{:.2f}'.format(r_n), '{:.2f}'.format(g_n), '{:.2f}'.format(b_n)
515 | rgb = (r_n, g_n, b_n)
516 | rgb_id[rgb] = index_tag
517 | if item_tag['tag'] == "UnTagged" or item_tag['tag'].lower() == "untagged":
518 | self.background = rgb
519 | self.segment_tag = seg_data
520 | self.rgb_to_id = rgb_id
521 |
522 | def object_parsing(self, ins, target=['Chair','Stool']):
523 | datas = eval(ins['statusDetail'])
524 | obj_closed = datas['closeRangeItemIds']
525 | object = None
526 | for i, obj in enumerate(obj_closed):
527 | name = self.objects[obj]['itemName']
528 | for ttt in target:
529 | if ttt.lower() in name.lower():
530 | print("The target: ", name, obj, self.objects[obj])
531 | return obj
532 | # print('There is no {}'.format(target))
533 | return object
534 | # return None
535 |
536 | def object_query(self, target=['Chair', 'Stool']):
537 | tar = []
538 | for i, obj in enumerate(self.objects):
539 | obj_i = obj['itemId']
540 | obj_full_name = obj['itemName']
541 | obj_now = ''.join([char for char in obj_full_name if not char.isdigit()])
542 | for name in target:
543 | if name.lower() == obj_now.lower():
544 | tar.append(obj_i)
545 | return tar
546 |
547 | def get_object_name(self, object_id=1):
548 | name = None
549 | for obj in self.objects:
550 | id = obj['itemId']
551 | if id == object_id:
552 | name = obj['itemName']
553 | return name
554 |
555 | def get_info_from_name(self, object_name):
556 | result = None
557 | for obj in self.objects:
558 | na = obj['itemName']
559 | if na == object_name:
560 | result = obj
561 | return result
562 |
563 | def check_feedback(self, server, id):
564 | time.sleep(0.1)
565 | info = None
566 | for i in range(30):
567 | try:
568 | info = server.notes[id]
569 | break
570 | except Exception as e:
571 | print(len(server.notes))
572 | time.sleep(0.1)
573 | return info
574 |
575 |
576 | def cleanup_function(stop_event):
577 | stop_event.set()
578 | # stop the loop
579 |
580 |
581 | class DevNull:
582 | def write(self, msg):
583 | pass
584 |
585 |
586 | class PrsEnv(object):
587 | def __init__(self, is_print=1, rendering=1, start_up_mode=0):
588 | # is_print: 0 without print, 1 print information to screen;
589 | # rendering=1 with unity render, 0 is headless mode; start_up_mode: 0 manual, 1 automatic
590 | print("PRS environment beta is starting without interaction")
591 | print('More PRS challenge task and benchmark come soon!')
592 | self.original_stdout = sys.stdout
593 | if not is_print:
594 | dev_null = DevNull()
595 | sys.stdout = dev_null
596 | self.stop_event = threading.Event()
597 | self.server = Server(self.stop_event)
598 | self.npc_running, self.time_running, self.agent_running = 0, 0, 0
599 | connection_thread = threading.Thread(target=self.server.wait_for_connection, args=())
600 | receive_thread = threading.Thread(target=self.server.receive_data, args=())
601 | parsing_thread = threading.Thread(target=self.server.message_process, args=())
602 | connection_thread.start()
603 | receive_thread.start()
604 | parsing_thread.start()
605 | # ---------------server begin-------------------
606 | self.env_time = EnvTime()
607 | # ---------------time system ready-------------------
608 | self.process = 0
609 | # executable_path = 'start.sh'
610 | executable_path = './unity/PRS.x86_64'
611 | if rendering:
612 | command_args = [executable_path]
613 | else:
614 | command_args = [executable_path, '-batchmode']
615 | try:
616 | if start_up_mode:
617 | # Start the Shell script using subprocess.Popen and capture stdout and stderr
618 | self.process = subprocess.Popen(command_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
619 | print("Starting Unity process...")
620 | # If needed, you can add more processing logic here, such as waiting for the process to finish, etc.
621 | else:
622 | print('Please open the Unity program (unity/start.sh)')
623 | except Exception as e:
624 | # Catch any exceptions that occur during startup and print the error message
625 | print(f"An error occurred during beginning: {e}")
626 | # --- unity exe start ---
627 | while True:
628 | time.sleep(0.3)
629 | state = self.server.state
630 | if state == 2 : break
631 | self.objs_data = ObjectsData()
632 | # --------------agent begin---------------
633 | self.agent = Agent(self.server, self.env_time, self.objs_data)
634 | # agent_thread = threading.Thread(target=agent_plan, args=(self.server, self.agent))
635 | self.agent.get_all_map()
636 | # agent_thread.start()
637 | self.objs_data.segment()
638 | # ----------------------- npc coming----------------------
639 | npc_0 = Npc(0, self.server, self.env_time, self.objs_data)
640 | npc_1 = Npc(1, self.server, self.env_time, self.objs_data)
641 | npc_2 = Npc(2, self.server, self.env_time, self.objs_data)
642 | npc_3 = Npc(3, self.server, self.env_time, self.objs_data)
643 | npc_4 = Npc(4, self.server, self.env_time, self.objs_data)
644 | npc_5 = Npc(5, self.server, self.env_time, self.objs_data)
645 | npc_6 = Npc(6, self.server, self.env_time, self.objs_data)
646 | npc_7 = Npc(7, self.server, self.env_time, self.objs_data)
647 | npc_8 = Npc(8, self.server, self.env_time, self.objs_data)
648 | npc_9 = Npc(9, self.server, self.env_time, self.objs_data)
649 |
650 | print('start')
651 | self.task = {'type': None, 'npc': None, 'object': None, 'target': None, 'state': 0, 'result': None}
652 | self.npcs = [npc_0, npc_1, npc_2, npc_3, npc_4, npc_5, npc_6, npc_7, npc_8, npc_9]
653 | self.agent.npcs = self.npcs
654 | # self.receptacle_mark()
655 | with open('env/data/npc_data.json', 'r') as file:
656 | npc_data = json.load(file)
657 | self.npc_data = npc_data
658 | time.sleep(0.1)
659 |
660 | # # --------------------------robot ----------------------
661 |
662 | def npc_start(self, number=1):
663 | if not self.time_running:
664 | time_thread = threading.Thread(target=self.env_time.time_simulation, args=(self.stop_event,))
665 | time_thread.start()
666 | self.time_running = 1
667 | if not self.npc_running:
668 | for npc_i, npc in enumerate(self.npcs):
669 | if npc_i == number:
670 | break
671 | # running_thread = threading.Thread(target=npc.continuous_simulation, args=())
672 | running_thread = threading.Thread(target=npc.random_walk, args=())
673 | running_thread.start()
674 | time.sleep(2)
675 | self.npc_running = 1
676 |
677 | def finish_env(self):
678 | print('========== Env end ==========')
679 | self.stop_event.set()
680 | self.agent.running = 0
681 | self.server.env_finish(self.process, self.npcs)
682 | sys.stdout = self.original_stdout
683 | exit(0)
684 |
685 | def sim_speed(self, speed):
686 | instruction = {"requestIndex": 1, "timeScale": speed}
687 | action_id = self.server.send_data(12, instruction, 0)
688 | # print(self.env_time.time_multiplier, speed)
689 | res = self.server.wait_for_respond(action_id, 10)
690 | self.env_time.time_multiplier = speed
691 | return self.env_time.time_multiplier
692 |
693 | def object_query(self, obj_id=0):
694 | instruction = {"requestIndex": 0, "targetType": 1, "targetId": obj_id}
695 | r_id = self.server.send_data(2, instruction, 1)
696 | object_info = self.agent.wait_for_respond(r_id, 60)
697 | if object_info:
698 | object_info = eval(object_info['statusDetail'])
699 | return object_info
700 |
701 | def receptacle_mark(self):
702 | # maps_0 = copy.deepcopy(self.server.maps.maps_info[0]['grid'])
703 | # maps_1 = copy.deepcopy(self.server.maps.maps_info[1]['grid'])
704 | for floor_i in range(3):
705 | maps_2 = copy.deepcopy(self.server.maps.maps_info[floor_i]['grid'])
706 | record = dict()
707 | for rece in self.objs_data.receptacles:
708 | # {'name': name, 'id': id, 'x_max': x_max,'x_min': x_min, 'z_max': z_max, 'z_min': z_min}
709 | x_max, x_min, z_max, z_min, y = rece['x_max'], rece['x_min'], rece['z_max'], rece['z_min'], rece['y']
710 | floor, map_i1, map_j1, iso = self.server.maps.get_point_info((x_max, y, z_max))
711 | floor, map_i2, map_j2, iso = self.server.maps.get_point_info((x_min, y, z_min))
712 | map_i_min, map_i_max = min(map_i1, map_i2), max(map_i1, map_i2)
713 | map_j_min, map_j_max = min(map_j1, map_j2), max(map_j1, map_j2)
714 | for ii in range(map_i_min, map_i_max + 1):
715 | for jj in range(map_j_min, map_j_max + 1):
716 | if maps_2[ii][jj] == 0:
717 | maps_2[ii][jj] = 2
718 | loc = self.objs_data.point_determine((x_min, floor, z_max))
719 | rece['location'], rece['floor'] = loc, floor
720 | rece['map_i_min'], rece['map_i_max'] = map_i_min, map_i_max
721 | rece['map_j_min'], rece['map_j_max'] = map_j_min, map_j_max
722 | try:
723 | record[loc]['num'] += 1
724 | record[loc]['receptacles'].append(rece)
725 | except:
726 | record[loc] = {'num': 1}
727 | record[loc]['receptacles'] = [rece]
728 | self.objs_data.room_receptacles = record
729 | self.objs_data.sematic_map[floor_i] = maps_2
730 |
731 | # ---------------- delivery task - ------------------------
732 |
733 | def delivery_task_import(self, task_setup):
734 | target_npc_id = task_setup['npc_id']
735 | if self.time_running == 0:
736 | self.env_time.time_multiplier = 1
737 | time_thread = threading.Thread(target=self.env_time.time_simulation, args=(self.stop_event,))
738 | time_thread.start()
739 | # self.sim_speed(1)
740 | self.time_running = 1
741 | if self.npc_running:
742 | return False
743 | else:
744 | for npc_i, npc in enumerate(self.npcs):
745 | if npc_i == target_npc_id:
746 | continue
747 | # npc.random_behavior(task_setup['npc_location'], 1)
748 | self.npcs[target_npc_id].directive_following(task_setup)
749 | basic_information, name_dict = self.npc_data["npc"][target_npc_id]["description"], {
750 | 'name': task_setup['npc_name']}
751 | npc_information = basic_information.format_map(name_dict)
752 | try:
753 | instruction = task_setup['directive'][4]
754 | except:
755 | instruction = task_setup['directive'][0] + task_setup['directive'][1]
756 | data = task_setup
757 | return instruction, npc_information, data
758 |
759 | def delivery_task_evaluate(self, task_data, score=0, save=0):
760 | now_time = self.env_time.current_date.isoformat()
761 | time.sleep(0.3)
762 | tar_npc_id, tar_obj = task_data['npc_id'], task_data['target_object_name']
763 | tar_obj_inf = self.objs_data.get_info_from_name(tar_obj)
764 | tar_obj_id = tar_obj_inf['itemId']
765 | npc_pos, npc_info = self.npcs[tar_npc_id].query_information()
766 | obj_info = self.server.object_query(tar_obj_id)
767 | try:
768 | obj_pos = obj_info['position']
769 | except Exception as e:
770 | print(tar_obj_inf)
771 | print(e, tar_obj_id, obj_info)
772 | obj_pos = obj_info['position']
773 | agent_pos, agent_info = self.agent.pos_query()
774 | agent_obj_id = self.agent.is_grasp
775 | if agent_obj_id is not None:
776 | agent_obj_info = self.server.object_query(agent_obj_id)
777 | agent_obj_pos = agent_obj_info['position']
778 | agent_obj_name = agent_obj_info['itemName']
779 | else:
780 | agent_obj_pos, agent_obj_name = None, None
781 | result = {'task_id': task_data['task_id'], 'tar_object_position': obj_pos, 'tar_object_name': tar_obj,
782 | 'target_object_type': task_data['target_object_type'],
783 | 'agent_object_name': agent_obj_name, 'agent_object_position': agent_obj_pos,
784 | 'npc_position': npc_pos, 'npc_id': tar_npc_id, 'agent_position': agent_pos,
785 | 'start_time': task_data['time'], 'end_time': now_time}
786 | if agent_obj_id is not None:
787 | self.agent.release_object()
788 | pos_original = self.objs_data.objects[agent_obj_id]['position']
789 | self.server.object_transform(obj_type=1, target_id=agent_obj_id, pos=pos_original)
790 | if save:
791 | return result
792 | if score:
793 | grade = self.delivery_task_score(result)
794 | result['task_score'] = grade
795 | return result
796 | return result
797 |
798 | def delivery_task_score(self, result_data, task_id=0):
799 | task_res, res_grasp, res_find, human_find, res_deliver = 0, 0, 0, 0, 0
800 | start_t = datetime.datetime.fromisoformat(result_data['start_time'])
801 | end_t = datetime.datetime.fromisoformat(result_data['end_time'])
802 | time_cost = end_t - start_t
803 | seconds_cost = (end_t - start_t).total_seconds()
804 | minutes_cost = time_cost.total_seconds() / 60
805 | # 1. target find, 2. grasp target, 3. target object dis, 4. deliver
806 | if result_data['agent_object_name'] is not None:
807 | if result_data['tar_object_name'] == result_data['agent_object_name']:
808 | res_grasp, res_find = 1, 1
809 | else:
810 | if result_data['target_object_type'] in result_data['agent_object_name']:
811 | res_find = 0.5
812 | hr_dis = self.agent.env.calculate_distance(result_data['npc_position'], result_data['agent_position'])
813 | if hr_dis < 3:
814 | human_find = 1
815 | elif hr_dis < 5:
816 | human_find = 0.5
817 | res_deliver = human_find * res_grasp
818 | # Calculate distance, determine items in hand, and calculate time
819 | task_res = res_grasp + res_find + res_deliver + human_find
820 | task_result = {'sub_result': {'grasp': res_grasp, 'object_find': res_find,
821 | 'deliver': res_deliver, 'human_find': human_find},
822 | 'result': task_res, 'time': minutes_cost}
823 | # task_result = {'sub_result': [res_grasp, res_find, res_deliver, human_find],
824 | # 'result': task_res, 'time': minutes_cost}
825 | return task_result
826 |
827 |
828 | if __name__ == '__main__': # pragma nocover
829 | server = Server()
830 |
831 |
832 |
833 | '''
834 | -> Unity: {"requestIndex":10,"npcId":0,"actionId":0,"actionPara":""}
835 | -> Get : {"requestIndex":11, "result":1}
836 |
837 |
838 | -> Unity: {"requestIndex":10,"npcId":0,"actionId":0,"actionPara":""}
839 | -> Get : {"result":1}
840 | '''
841 |
--------------------------------------------------------------------------------