diff --git a/Algorithms/.gitignore b/Algorithms/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..5f2c97937124264fdebf3602664c58bc39290ee6 --- /dev/null +++ b/Algorithms/.gitignore @@ -0,0 +1,30 @@ +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf +.idea/ + +# Generated files +.idea/**/contentModel.xml + +.DS_Store +__pycache__/ + + +# Extra +./build +./obj +./Logs +./Library +./Temp +./ProjectSettings + + +# algorithms +*.tour +*.par +*.tsp + + diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/EnvChannel.py b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/EnvChannel.py new file mode 100644 index 0000000000000000000000000000000000000000..89909eccb160d3bebb15087e72541ddbdd4ce2fd --- /dev/null +++ b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/EnvChannel.py @@ -0,0 +1,45 @@ +import json +from mlagents_envs.side_channel.side_channel import ( + SideChannel, + IncomingMessage, + OutgoingMessage, +) +import uuid + +from EnvironmentData import EnvironmentData + +""" +class that processes information from SideChannel EnvChannel +""" + +class EnvChannel(SideChannel): + + def __init__(self) -> None: + super().__init__(uuid.UUID("621f0a70-4f87-11ea-a6bf-784f4387d1f7")) #must coincide with ChannelId set in c# + self.EnvData = EnvironmentData() # object that stores info on environment + + def on_message_received(self, msg: IncomingMessage) -> None: + # We simply read a string from the message and print it. + data = msg.read_string() + environment_info = json.loads(data) + + self.EnvData.matrix = environment_info["matrixLayout"] + self.EnvData.rotation = environment_info["rotationRobot"] + self.EnvData.action_size = environment_info["sizeOfAction"] + self.EnvData.observation_size = environment_info["sizeOfObservation"] + self.EnvData.number_of_robots = environment_info["numberOfRobotsInEnv"] + self.EnvData.number_of_current_tasks = environment_info["numberOfCurrentTasks"] + self.EnvData.can_go_backwards = environment_info["backwards"] + self.EnvData.random_tasks = environment_info["tasksGeneratedRandomly"] + self.EnvData.instance_ids = environment_info["instanceIDSRobots"] + + self.EnvData.set_initial_nodes_dictionary(environment_info["initialNodesOfRobots"]) + self.EnvData.set_tasks_to_be_assigned(environment_info["currentTasks"]) + self.EnvData.set_assigned_tasks() + + def send_string(self, data: str) -> None: + # Add the string to an OutgoingMessage + msg = OutgoingMessage() + msg.write_string(data) + # We call this method to queue the data we want to send + super().queue_message_to_send(msg) \ No newline at end of file diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/EnvironmentData.py b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/EnvironmentData.py new file mode 100644 index 0000000000000000000000000000000000000000..5156f445b07ce2351c4b0dcd5ea506e3135bf990 --- /dev/null +++ b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/EnvironmentData.py @@ -0,0 +1,92 @@ +# stores data on environment +# initialized when initial data is being sent through EnvChannel +import json +import numpy as np + +from Node import Node + +import ta_task +from ta_state import Location + + +class EnvironmentData: + + def __init__(self): + self.matrix = None + self.rotation = None + self.action_size = None + self.observation_size = None + self.number_of_robots = None + self.number_of_current_tasks = None + self.can_go_backwards = None + self.random_tasks = None # if set to true random tasks will be send whenever a task has been completed, + # otherwise all tasks self.tasks_to_be_assigned + + self.instance_ids = [] + self.current_nodes_dictionary = {} # dictionary instance_id -> current node + self.tasks_to_be_assigned = [] # tasks that are still to be assigned + self.assigned_tasks_dictionary = {} # dictionary instance_id -> assigned task + + self.task_side_channel = None + + ######################################### + ## methods used by EnvChannel to initialize attributes: + ######################################### + + # set_initial_nodes_dictionary + # set_tasks_to_be_assigned + # set_assigned_tasks + + # given a correct string containing array of nodes + def set_initial_nodes_dictionary(self, initial_nodes): + for i in range(self.number_of_robots): + self.current_nodes_dictionary[self.instance_ids[i]] = Node(initial_nodes[i]["GridPosition"]["Row"], + initial_nodes[i]["GridPosition"]["Column"], + initial_nodes[i]["Degrees"]) + + # given a correct json_string containing array of tasks + def set_tasks_to_be_assigned(self, tasks): + for i in range(self.number_of_current_tasks): + pickup = Location(tasks[i]["PickUp"]["Column"], + tasks[i]["PickUp"]["Row"], 0) + delivery = Location( + tasks[i]["Delivery"]["Column"], tasks[i]["Delivery"]["Row"], 0) + releaseTime = tasks[i]["ReleaseTime"] + new_task = ta_task.Task(ta_task.CURRENT_TASK_ID, releaseTime, + pickup, delivery, None) + ta_task.CURRENT_TASK_ID += 1 + self.tasks_to_be_assigned.append(new_task) + + # initialize dictionary robot instance_id -> task (None) + def set_assigned_tasks(self): + for i in range(self.number_of_robots): + self.assigned_tasks_dictionary[self.instance_ids[i]] = None + + ######################################### + ## methods used to update environment info + ######################################### + + # when a task is assigned to a robot, it has to be added to self.assigned_tasks + # and removed from self.tasks_to_be_assigned + # info has to be sent to unity via the correct channel + def assign_task(self, robot_instanceID, task): + self.assigned_tasks_dictionary[robot_instanceID] = task + self.tasks_to_be_assigned.remove(task) + taskDict = {"Task": { + "PickUp": {"Column": str(task.pickup_endpoint.col), "Row": str(task.pickup_endpoint.row)}, + "Delivery": {"Column": str(task.delivery_endpoint.col), "Row": str(task.delivery_endpoint.row)}, + "ReleaseTime": str(task.release_time)}, + "InstanceID": int(robot_instanceID)} + + self.task_side_channel.send_string(json.dumps(taskDict)) + + # when a new task is available it is added to tasks_to_be_assigned + # a check is made whether there are still tasks that can be added, but this should not be happening (diagnostical) + def add_task_to_tasks_to_be_assigned(self, task): + if len(self.tasks_to_be_assigned) == self.number_of_current_tasks: + raise Exception("cannot add more tasks") + self.tasks_to_be_assigned.append(task) + + # when a robot has finished his task it has to be removed from assigned_tasks + def task_done(self, instance_id): + self.assigned_tasks_dictionary[instance_id] = None diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/DOC/LKH-2_USER_GUIDE.pdf b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/DOC/LKH-2_USER_GUIDE.pdf new file mode 100644 index 0000000000000000000000000000000000000000..5b6edc40d0d640399ffdb78307263c7c0707b534 Binary files /dev/null and b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/DOC/LKH-2_USER_GUIDE.pdf differ diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/DOC/LKH-3_PARAMETERS.pdf b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/DOC/LKH-3_PARAMETERS.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7642480b7ccc43f184818f62829ad0dd75c2f6cd Binary files /dev/null and b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/DOC/LKH-3_PARAMETERS.pdf differ diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/DOC/LKH-3_REPORT.pdf b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/DOC/LKH-3_REPORT.pdf new file mode 100644 index 0000000000000000000000000000000000000000..cf04bb69d91ea29d79a7ba8880cd3d3899747dd1 Binary files /dev/null and b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/DOC/LKH-3_REPORT.pdf differ diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/DOC/LKH_Genetic.pdf b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/DOC/LKH_Genetic.pdf new file mode 100644 index 0000000000000000000000000000000000000000..db5d376fdd3ce0725a2905312762e8f5ae416fb1 Binary files /dev/null and b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/DOC/LKH_Genetic.pdf differ diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/DOC/LKH_REPORT.pdf b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/DOC/LKH_REPORT.pdf new file mode 100644 index 0000000000000000000000000000000000000000..333e254a7f1a76a951240626f1ba8fc830bdd99e Binary files /dev/null and b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/DOC/LKH_REPORT.pdf differ diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/DOC/POPMUSIC_REPORT.pdf b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/DOC/POPMUSIC_REPORT.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c957427ad8c7ddac33947df6d525f39226d2574c Binary files /dev/null and b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/DOC/POPMUSIC_REPORT.pdf differ diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/DOC/TSPLIB_DOC.pdf b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/DOC/TSPLIB_DOC.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c109b3a0ea7c35ea91f59eccb9e034202a6238a9 Binary files /dev/null and b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/DOC/TSPLIB_DOC.pdf differ diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/LKH-3.exe b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/LKH-3.exe new file mode 100644 index 0000000000000000000000000000000000000000..132733fbc6ddd5fbfaec3b2fc792f8404e1b4fd6 Binary files /dev/null and b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/LKH-3.exe differ diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/LKHWin-3.0.6-WinChanges.zip b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/LKHWin-3.0.6-WinChanges.zip new file mode 100644 index 0000000000000000000000000000000000000000..4d8fdea33ef7ea8799b4f8abcd1e82276180bd25 Binary files /dev/null and b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/LKHWin-3.0.6-WinChanges.zip differ diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/LKH_linux b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/LKH_linux new file mode 100644 index 0000000000000000000000000000000000000000..8a9ab0d5394332e166a8332d956afb089a077bfa Binary files /dev/null and b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/LKH_linux differ diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/Makefile b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..4849d972907664b17c5bd9310455084e203789cd --- /dev/null +++ b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/Makefile @@ -0,0 +1,4 @@ +all: + make -C SRC +clean: + make -C SRC clean diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/README.txt b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..30c5f622fa2b23276bac3aa5d21169249fc738d5 --- /dev/null +++ b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/README.txt @@ -0,0 +1,146 @@ +LKH is an implementation of the Lin-Kernighan traveling salesman heuristic. + +The code is distributed for research use. The author reserves all rights to +the code. + + +INSTRUCTIONS FOR INSTALLATION: (Version 3.0.3 - July 2018) +----------------------------- + +The software is available in gzipped tar format: + + LKH-3.0.3.tgz (approximately 2.3 MB) + +Download the software and execute the following UNIX commands: + + tar xvfz LKH-3.0.3.tgz + cd LKH-3.0.3 + make + +An executable file called LKH will now be available in the directory LKH-3.0.3. + +To test the installation run the program by typing ./LKH pr2392.par. +Then press return. The program should now solve a TSP instance with 2392 nodes. + +For testing the installation on an mTSP problem, type ./LKH whizzkids96.par. +Then press return. + +A two-level tree is used as the default tour representation. +A three-level tree representation may be used instead by compiling the +source code with the compiler option + + -DTHREE_LEVEL_TREE + +Just edit the first line in SRC/Makefile and execute the commands + + make clean + make + +CHANGES IN VERSION 3.0.3: +------------------------- + +Candidate sets may now be created by means of POPMUSIC by giving the following +specification in the parameter file for LKH: + + CANDIDATE_SET_TYPE = POPMUSIC + +The value of the parameter MAX_CANDIDATES is used to trim the candidate set. +There are, however, some other POPMUSIC related parameters. If not specified, +they will take their default values. These parameters are: + + POPMUSIC_SAMPLE_SIZE = <int>  + Sample size. + Default: 10. + + POPMUSIC_SOLUTIONS = <int> + Number of solutions to generate. + Default: 50. + + POPMUSIC_MAX_NEIGHBORS = <int> + Maximum number of nearest neighbors used as candidates in iterated 3-opt for + POPMUSIC. + Default: 5. + + POPMUSIC_TRIALS = <int> + Number of trials used in iterated 3-opt for POPMUSIC. + If the value is zero, the number of trials is the size of the subpath + to be optimized. + Default: 1. + + POPMUSIC_INITIAL_TOUR = { YES | NO } + Specifies whether the first generated POPMUSIC tour is used as + initial tour for Lin-Kernighan. + Default: NO. + +CHANGES IN VERSION 3.0.2: +------------------------- + +Tours may now be recombined by GPX2 (Generalized Partition Crossover 2) +instead of IPT (Iterative Partial Transcription). + +GPX2 is used by giving the following specification in the parameter file: + + RECOMBINATION = GPX2 + +The possible settings are: + + RECOMBINATION = { IPT | GPX2 } + +IPT is default. + + +CHANGES IN VERSION 3.0.1: +------------------------- + + New problem type: TSPDL (traveling salesman with draft limits) + +NEW IN VERSION 3.0: +------------------- + +New parameter keywords: + + BWTSP = <integer> <integer> [ <integer> ] + DEPOT = <integer> + MAKESPAN = { YES | NO } MTSP_MIN_SIZE = <integer> + MTSP_MAX_SIZE = <integer> + MTSP_OBJECTIVE = [ MINMAX | MINMAX_SIZE | MINSUM ] + MTSP_RESULT_FILE = <string> + SINTEF_RESULT_FILE = <string> + SALESMEN = <integer> + SCALE = <integer> + VEHICLES : <integer> + + New initial tour algorithms: + CVRPR + MTSP + SOP + +New TSPLIB format keywords: + +The specification part: + + CAPACITY : <integer> + DEMAND_DIMENSION : <integer> + DISTANCE : <real> + GRID_SIZE : <real> + RISK_THRESHOLD : <integer> + SALESMEN : <integer> + SCALE : <integer> + SERVICE_TIME_SECTION + VEHICLES : <integer> + + New edge weight types: + EXACT_2D + EXACT_3D + FLOOR_2D + FLOOR_3D + TOR_2D + TOR_3D + +The data part: + + BACKHAUL_SECTION + DEMAND_SECTION + DEPOT_SECTION + PICKUP_AND_DELIVERY_SECTION + TIME_WINDOW_SECTION diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/SRC.zip b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/SRC.zip new file mode 100644 index 0000000000000000000000000000000000000000..4dd16c6a5d327c5bac3f7b15a7a7888013e22a2e Binary files /dev/null and b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/SRC.zip differ diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/Node.py b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/Node.py new file mode 100644 index 0000000000000000000000000000000000000000..a2bb07c8fdf941ab68a8e8c87e8478b6d2e79aba --- /dev/null +++ b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/Node.py @@ -0,0 +1,39 @@ +# Class Node represent nodes in the graph. Every node contains a +# position (x,y) in the grid +# and a rotation in degree where +# 0 = North +# 90 = East +# 280 = South +# 270 = West +# all degrees must be between 0 and 360 + +# attributes are set to private such that they cannot be overwritten and there is no problem with the hash + +class Node: + def __init__(self,x,y,g): + self._x = x + self._y = y + self._g = g + + @property + def x(self): + return self._x + + @property + def y(self): + return self._y + + @property + def g(self): + return self._g + + + def __eq__(self, other): + return self.__class__ == other.__class__ and self.x == other.x and self.y == other.y and self.g == other.g + + + def __hash__(self): + return (((self.x * 397) ** self.y) * 397) **self.g + + def __str__(self): + return "[(" + str(self.x) + ", " + str(self.y) + ")" + "," + str(self.g) + "]" diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/PickupAndDeliveryChannel.py b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/PickupAndDeliveryChannel.py new file mode 100644 index 0000000000000000000000000000000000000000..c7b40e6db4ea21d3a9eb72b29558fe4b9260ddfb --- /dev/null +++ b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/PickupAndDeliveryChannel.py @@ -0,0 +1,36 @@ +import json +from mlagents_envs.side_channel.side_channel import ( + SideChannel, + IncomingMessage, + OutgoingMessage, +) +import uuid + +""" +class that processes information from SideChannel EnvChannel +""" + +NEW_TASKS = [] + + +# Create the StringLogChannel class +class PaDChannel(SideChannel): + + def __init__(self) -> None: + # must coincide with ChannelId set in c# + super().__init__(uuid.UUID("621f0a70-4f87-11ea-a6bf-784f4387d1f8")) + + def on_message_received(self, msg: IncomingMessage) -> None: + # We simply read a string from the message and print it. + data = msg.read_string() + print(f"Received info from side channel: {data}") + args = data.split(" ") + NEW_TASKS.append(args[1:]) + print(f"New Task({args[1]}, {args[2]}, {args[3]})") + + def send_string(self, data: str) -> None: + # Add the string to an OutgoingMessage + msg = OutgoingMessage() + msg.write_string(data) + # We call this method to queue the data we want to send + super().queue_message_to_send(msg) diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/Pipfile b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/Pipfile new file mode 100644 index 0000000000000000000000000000000000000000..9b2afe2db3b43b974e3fc2244ddb1076119118dc --- /dev/null +++ b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/Pipfile @@ -0,0 +1,15 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +networkx = "==2.5" +mlagents = "==0.23.0" +mlagents-envs = "==0.23.0" +numpy = "*" + +[dev-packages] + +[requires] +python_version = "3.6" diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/Pipfile.lock b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/Pipfile.lock new file mode 100644 index 0000000000000000000000000000000000000000..b182fb88a1831f2730b6e59774e840f5498a278a --- /dev/null +++ b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/Pipfile.lock @@ -0,0 +1,528 @@ +{ + "_meta": { + "hash": { + "sha256": "7d5bfdeb402549418fd529d32756528fb1c7c6815d55687f16e3784120edf6c8" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.6" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "absl-py": { + "hashes": [ + "sha256:62bd4e248ddb19d81aec8f9446b407ff37c8175c2ba88266a7afa9b4ce4a333b", + "sha256:6953272383486044699fd0e9f00aad167a27e08ce19aae66c6c4b10e7e767793" + ], + "version": "==0.13.0" + }, + "attrs": { + "hashes": [ + "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1", + "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==21.2.0" + }, + "cached-property": { + "hashes": [ + "sha256:9fa5755838eecbb2d234c3aa390bd80fbd3ac6b6869109bfc1b499f7bd89a130", + "sha256:df4f613cf7ad9a588cc381aaf4a512d26265ecebd5eb9e1ba12f1319eb85a6a0" + ], + "markers": "python_version < '3.8'", + "version": "==1.5.2" + }, + "cachetools": { + "hashes": [ + "sha256:2cc0b89715337ab6dbba85b5b50effe2b0c74e035d83ee8ed637cf52f12ae001", + "sha256:61b5ed1e22a0924aed1d23b478f37e8d52549ff8a961de2909c69bf950020cff" + ], + "markers": "python_version ~= '3.5'", + "version": "==4.2.2" + }, + "cattrs": { + "hashes": [ + "sha256:616972ae3dfa6e623a40ad3cb845420e64942989152774ab055e5c2b2f89f997", + "sha256:b7ab5cf8ad127c42eefd01410c1c6e28569a45a255ea80ed968511873c433c7a" + ], + "version": "==1.0.0" + }, + "certifi": { + "hashes": [ + "sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee", + "sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8" + ], + "version": "==2021.5.30" + }, + "chardet": { + "hashes": [ + "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa", + "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==4.0.0" + }, + "cloudpickle": { + "hashes": [ + "sha256:3a32d0eb0bc6f4d0c57fbc4f3e3780f7a81e6fee0fa935072884d58ae8e1cc7c", + "sha256:9bc994f9e9447593bd0a45371f0e7ac7333710fcf64a4eb9834bf149f4ef2f32" + ], + "markers": "python_version >= '3.5'", + "version": "==1.6.0" + }, + "dataclasses": { + "hashes": [ + "sha256:0201d89fa866f68c8ebd9d08ee6ff50c0b255f8ec63a71c16fda7af82bb887bf", + "sha256:8479067f342acf957dc82ec415d355ab5edb7e7646b90dc6e2fd1d96ad084c97" + ], + "markers": "python_version < '3.7'", + "version": "==0.8" + }, + "decorator": { + "hashes": [ + "sha256:6e5c199c16f7a9f0e3a61a4a54b3d27e7dad0dbdde92b944426cb20914376323", + "sha256:72ecfba4320a893c53f9706bebb2d55c270c1e51a28789361aa93e4a21319ed5" + ], + "markers": "python_version >= '3.5'", + "version": "==5.0.9" + }, + "google-auth": { + "hashes": [ + "sha256:9266252e11393943410354cf14a77bcca24dd2ccd9c4e1aef23034fe0fbae630", + "sha256:c7c215c74348ef24faef2f7b62f6d8e6b38824fe08b1e7b7b09a02d397eda7b3" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", + "version": "==1.32.1" + }, + "google-auth-oauthlib": { + "hashes": [ + "sha256:09832c6e75032f93818edf1affe4746121d640c625a5bef9b5c96af676e98eee", + "sha256:0e92aacacfb94978de3b7972cf4b0f204c3cd206f74ddd0dc0b31e91164e6317" + ], + "markers": "python_version >= '3.6'", + "version": "==0.4.4" + }, + "grpcio": { + "hashes": [ + "sha256:0e193feaf4ebc72f6af57d7b8a08c0b8e43ebbd76f81c6f1e55d013557602dfd", + "sha256:118479436bda25b369e2dc1cd0921790fbfaea1ec663e4ee7095c4c325694495", + "sha256:1f79d8a24261e3c12ec3a6c25945ff799ae09874fd24815bc17c2dc37715ef6c", + "sha256:26af85ae0a7ff8e8f8f550255bf85551df86a89883c11721c0756b71bc1019be", + "sha256:278e131bfbc57bab112359b98930b0fdbf81aa0ba2cdfc6555c7a5119d7e2117", + "sha256:2a179b2565fa85a134933acc7845f9d4c12e742c802b4f50bf2fd208bf8b741e", + "sha256:3a25e1a46f51c80d06b66223f61938b9ffda37f2824ca65749c49b758137fac2", + "sha256:3db0680fee9e55022677abda186e73e3c019c59ed83e1550519250dc97cf6793", + "sha256:3e85bba6f0e0c454a90b8fea16b59db9c6d19ddf9cc95052b2d4ca77b22d46d6", + "sha256:3eb960c2f9e031f0643b53bab67733a9544d82f42d0714338183d14993d2a23c", + "sha256:419af4f577a3d5d9f386aeacf4c4992f90016f84cbceb11ecd832101b1f7f9c9", + "sha256:44efa41ac36f6bcbf4f64d6479b3031cceea28cf6892a77f15bd1c22611bff9d", + "sha256:4bc60f8372c3ab06f41279163c5d558bf95195bb3f68e35ed19f95d4fbd53d71", + "sha256:4c19578b35715e110c324b27c18ab54a56fccc4c41b8f651b1d1da5a64e0d605", + "sha256:532ab738351aad2cdad80f4355123652e08b207281f3923ce51fb2b58692dd4c", + "sha256:549beb5646137b78534a312a3b80b2b8b1ea01058b38a711d42d6b54b20b6c2b", + "sha256:59f5fb4ba219a11fdc1c23e17c93ca3090480a8cde4370c980908546ffc091e6", + "sha256:5efa68fc3fe0c439e2858215f2224bfb7242c35079538d58063f68a0d5d5ec33", + "sha256:5ff4802d9b3704e680454289587e1cc146bb0d953cf3c9296e2d96441a6a8e88", + "sha256:6a225440015db88ec4625a2a41c21582a50cce7ffbe38dcbbb416c7180352516", + "sha256:6d898441ada374f76e0b5354d7e240e1c0e905a1ebcb1e95d9ffd99c88f63700", + "sha256:6e137d014cf4162e5a796777012452516d92547717c1b4914fb71ce4e41817b5", + "sha256:6edf68d4305e08f6f8c45bfaa9dc04d527ab5a1562aaf0c452fa921fbe90eb23", + "sha256:72e8358c751da9ab4f8653a3b67b2a3bb7e330ee57cb26439c6af358d6eac032", + "sha256:77054f24d46498d9696c809da7810b67bccf6153f9848ea48331708841926d82", + "sha256:7adfbd4e22647f880c9ed86b2be7f6d7a7dbbb8adc09395808cc7a4d021bc328", + "sha256:87b4b1977b52d5e0873a5e396340d2443640ba760f4fa23e93a38997ecfbcd5b", + "sha256:889518ce7c2a0609a3cffb7b667669a39b3410e869ff38e087bf7eeadad62e5d", + "sha256:89af675d38bf490384dae85151768b8434e997cece98e5d1eb6fcb3c16d6af12", + "sha256:8ab27a6626c2038e13c1b250c5cd22da578f182364134620ec298b4ccfc85722", + "sha256:8ccde1df51eeaddf5515edc41bde2ea43a834a288914eae9ce4287399be108f5", + "sha256:947bdba3ebcd93a7cef537d6405bc5667d1caf818fa8bbd2e2cc952ec8f97e09", + "sha256:96d78d9edf3070770cefd1822bc220d8cccad049b818a70a3c630052e9f15490", + "sha256:a433d3740a9ef7bc34a18e2b12bf72b25e618facdfd09871167b30fd8e955fed", + "sha256:a77d1f47e5e82504c531bc9dd22c093ff093b6706ec8bcdad228464ef3a5dd54", + "sha256:b1624123710fa701988a8a43994de78416e5010ac1508f64ed41e2577358604a", + "sha256:b16e1967709392a0ec4b10b4374a72eb062c47c168a189606c9a7ea7b36593a8", + "sha256:b5ea9902fc2990af993b74862282b49ae0b8de8a64ca3b4a8dda26a3163c3bb4", + "sha256:c323265a4f18f586e8de84fda12b48eb3bd48395294aa2b8c05307ac1680299d", + "sha256:c83481501533824fe341c17d297bbec1ec584ec46b352f98ce12bf16740615c4", + "sha256:cd7ddb5b6ffcbd3691990df20f260a888c8bd770d57480a97da1b756fb1be5c0", + "sha256:cddd61bff66e42ef334f8cb9e719951e479b5ad2cb75c00338aac8de28e17484", + "sha256:cf6c3bfa403e055380fe90844beb4fe8e9448edab5d2bf40d37d208dbb2f768c", + "sha256:d4179d96b0ce27602756185c1a00d088c9c1feb0cc17a36f8a66eec6ddddbc0c", + "sha256:d49f250c3ffbe83ba2d03e3500e03505576a985f7c5f77172a9531058347aa68", + "sha256:dcfcb147c18272a22a592251a49830b3c7abc82385ffff34916c2534175d885e", + "sha256:ddd33c90b0c95eca737c9f6db7e969a48d23aed72cecb23f3b8aac009ca2cfb4", + "sha256:e4a8a371ad02bf31576bcd99093cea3849e19ca1e9eb63fc0b2c0f1db1132f7d", + "sha256:e891b0936aab73550d673dd3bbf89fa9577b3db1a61baecea480afd36fdb1852", + "sha256:e90cda2ccd4bdb89a3cd5dc11771c3b8394817d5caaa1ae36042bc96a428c10e", + "sha256:ff9ebc416e815161d89d2fd22d1a91acf3b810ef800dae38c402d19d203590bf" + ], + "version": "==1.38.1" + }, + "h5py": { + "hashes": [ + "sha256:02c391fdb980762a1cc03a4bcaecd03dc463994a9a63a02264830114a96e111f", + "sha256:1cd367f89a5441236bdbb795e9fb9a9e3424929c00b4a54254ca760437f83d69", + "sha256:1cdfd1c5449ca1329d152f0b66830e93226ebce4f5e07dd8dc16bfc2b1a49d7b", + "sha256:1e2516f190652beedcb8c7acfa1c6fa92d99b42331cbef5e5c7ec2d65b0fc3c2", + "sha256:236ac8d943be30b617ab615c3d4a4bf4a438add2be87e54af3687ab721a18fac", + "sha256:2e37352ddfcf9d77a2a47f7c8f7e125c6d20cc06c2995edeb7be222d4e152636", + "sha256:80c623be10479e81b64fa713b7ed4c0bbe9f02e8e7d2a2e5382336087b615ce4", + "sha256:ba71f6229d2013fbb606476ecc29c6223fc16b244d35fcd8566ad9dbaf910857", + "sha256:cb74df83709d6d03d11e60b9480812f58da34f194beafa8c8314dbbeeedfe0a6", + "sha256:dccb89358bc84abcd711363c3e138f9f4eccfdf866f2139a8e72308328765b2c", + "sha256:e33f61d3eb862614c0f273a1f993a64dc2f093e1a3094932c50ada9d2db2170f", + "sha256:f89a3dae38843ffa49d17a31a3509a8129e9b46ece602a0138e1ed79e685c361", + "sha256:fea05349f63625a8fb808e57e42bb4c76930cf5d50ac58b678c52f913a48a89b" + ], + "markers": "python_version >= '3.6'", + "version": "==3.1.0" + }, + "idna": { + "hashes": [ + "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6", + "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.10" + }, + "importlib-metadata": { + "hashes": [ + "sha256:079ada16b7fc30dfbb5d13399a5113110dab1aa7c2bc62f66af75f0b717c8cac", + "sha256:9f55f560e116f8643ecf2922d9cd3e1c7e8d52e683178fecd9d08f6aa357e11e" + ], + "markers": "python_version < '3.8'", + "version": "==4.6.1" + }, + "markdown": { + "hashes": [ + "sha256:31b5b491868dcc87d6c24b7e3d19a0d730d59d3e46f4eea6430a321bed387a49", + "sha256:96c3ba1261de2f7547b46a00ea8463832c921d3f9d6aba3f255a6f71386db20c" + ], + "markers": "python_version >= '3.6'", + "version": "==3.3.4" + }, + "mlagents": { + "hashes": [ + "sha256:06e7b7d4b5ae46213d6bf52be9b17770ba305b58138423630070dee4acbe9406", + "sha256:1103dfcaa4b08b5705b59b03bf893aa79d1ccc08bc2eac0bbe77154d353f8f14" + ], + "index": "pypi", + "version": "==0.23.0" + }, + "mlagents-envs": { + "hashes": [ + "sha256:0bd06c704c3cc384c6852138dc865fd5cfb4f0fddd69a8ccee28c457cd80bdfb", + "sha256:472adf39a6fb66750749e619077e3d8ce51afa8b90d00f93960c18d467ed40ef" + ], + "index": "pypi", + "version": "==0.23.0" + }, + "networkx": { + "hashes": [ + "sha256:7978955423fbc9639c10498878be59caf99b44dc304c2286162fd24b458c1602", + "sha256:8c5812e9f798d37c50570d15c4a69d5710a18d77bafc903ee9c5fba7454c616c" + ], + "index": "pypi", + "version": "==2.5" + }, + "numpy": { + "hashes": [ + "sha256:0172304e7d8d40e9e49553901903dc5f5a49a703363ed756796f5808a06fc233", + "sha256:34e96e9dae65c4839bd80012023aadd6ee2ccb73ce7fdf3074c62f301e63120b", + "sha256:3676abe3d621fc467c4c1469ee11e395c82b2d6b5463a9454e37fe9da07cd0d7", + "sha256:3dd6823d3e04b5f223e3e265b4a1eae15f104f4366edd409e5a5e413a98f911f", + "sha256:4064f53d4cce69e9ac613256dc2162e56f20a4e2d2086b1956dd2fcf77b7fac5", + "sha256:4674f7d27a6c1c52a4d1aa5f0881f1eff840d2206989bae6acb1c7668c02ebfb", + "sha256:7d42ab8cedd175b5ebcb39b5208b25ba104842489ed59fbb29356f671ac93583", + "sha256:965df25449305092b23d5145b9bdaeb0149b6e41a77a7d728b1644b3c99277c1", + "sha256:9c9d6531bc1886454f44aa8f809268bc481295cf9740827254f53c30104f074a", + "sha256:a78e438db8ec26d5d9d0e584b27ef25c7afa5a182d1bf4d05e313d2d6d515271", + "sha256:a7acefddf994af1aeba05bbbafe4ba983a187079f125146dc5859e6d817df824", + "sha256:a87f59508c2b7ceb8631c20630118cc546f1f815e034193dc72390db038a5cb3", + "sha256:ac792b385d81151bae2a5a8adb2b88261ceb4976dbfaaad9ce3a200e036753dc", + "sha256:b03b2c0badeb606d1232e5f78852c102c0a7989d3a534b3129e7856a52f3d161", + "sha256:b39321f1a74d1f9183bf1638a745b4fd6fe80efbb1f6b32b932a588b4bc7695f", + "sha256:cae14a01a159b1ed91a324722d746523ec757357260c6804d11d6147a9e53e3f", + "sha256:cd49930af1d1e49a812d987c2620ee63965b619257bd76eaaa95870ca08837cf", + "sha256:e15b382603c58f24265c9c931c9a45eebf44fe2e6b4eaedbb0d025ab3255228b", + "sha256:e91d31b34fc7c2c8f756b4e902f901f856ae53a93399368d9a0dc7be17ed2ca0", + "sha256:ef627986941b5edd1ed74ba89ca43196ed197f1a206a3f18cc9faf2fb84fd675", + "sha256:f718a7949d1c4f622ff548c572e0c03440b49b9531ff00e4ed5738b459f011e8" + ], + "index": "pypi", + "version": "==1.18.5" + }, + "oauthlib": { + "hashes": [ + "sha256:42bf6354c2ed8c6acb54d971fce6f88193d97297e18602a3a886603f9d7730cc", + "sha256:8f0215fcc533dd8dd1bee6f4c412d4f0cd7297307d43ac61666389e3bc3198a3" + ], + "markers": "python_version >= '3.6'", + "version": "==3.1.1" + }, + "pillow": { + "hashes": [ + "sha256:063d17a02a0170c2f880fbd373b2738b089c6adcbd1f7418667bc9e97524c11b", + "sha256:1037288a22cc8ec9d2918a24ded733a1cc4342fd7f21d15d37e6bbe5fb4a7306", + "sha256:25f6564df21d15bcac142b4ed92b6c02e53557539f535f31c1f3bcc985484753", + "sha256:28f184c0a65be098af412f78b0b6f3bbafd1614e1dc896e810d8357342a794b7", + "sha256:3251557c53c1ed0c345559afc02d2b0a0aa5788042e161366ed90b27bc322d3d", + "sha256:331f8321418682386e4f0d0e6369f732053f95abddd2af4e1b1ef74a9537ef37", + "sha256:333313bcc53a8a7359e98d5458dfe37bfa301da2fd0e0dc41f585ae0cede9181", + "sha256:34ce3d993cb4ca840b1e31165b38cb19c64f64f822a8bc5565bde084baff3bdb", + "sha256:490c9236ef4762733b6c2e1f1fcb37793cb9c57d860aa84d6994c990461882e5", + "sha256:519b3b24dedc81876d893475bade1b92c4ce7c24b9b82224f0bd8daae682e039", + "sha256:53f6e4b73b3899015ac4aa95d99da0f48ea18a6d7c8db672e8bead3fb9570ef5", + "sha256:561339ed7c324bbcb29b5e4f4705c97df950785394b3ac181f5bf6a08088a672", + "sha256:6f7517a220aca8b822e25b08b0df9546701a606a328da5bc057e5f32a3f9b07c", + "sha256:713b762892efa8cd5d8dac24d16ac2d2dbf981963ed1b3297e79755f03f8cbb8", + "sha256:72858a27dd7bd1c40f91c4f85db3b9f121c8412fd66573121febb00d074d0530", + "sha256:778a819c2d194e08d39d67ddb15ef0d32eba17bf7d0c2773e97bd221b2613a3e", + "sha256:803606e206f3e366eea46b1e7ab4dac74cfac770d04de9c35319814e11e47c46", + "sha256:856fcbc3201a6cabf0478daa0c0a1a8a175af7e5173e2084ddb91cc707a09dd1", + "sha256:8f65d2a98f198e904dbe89ecb10862d5f0511367d823689039e17c4d011de11e", + "sha256:94db5ea640330de0945b41dc77fb4847b4ab6e87149126c71b36b112e8400898", + "sha256:950e873ceefbd283cbe7bc5b648b832d1dcf89eeded6726ebec42bc7d67966c0", + "sha256:a7beda44f177ee602aa27e0a297da1657d9572679522c8fb8b336b734653516e", + "sha256:aef0838f28328523e9e5f2c1852dd96fb85768deb0eb8f908c54dad0f44d2f6f", + "sha256:b42ea77f4e7374a67e1f27aaa9c62627dff681f67890e5b8f0c1e21b1500d9d2", + "sha256:bccd0d604d814e9494f3bf3f077a23835580ed1743c5175581882e7dd1f178c3", + "sha256:c2d78c8230bda5fc9f6b1d457c7f8f3432f4fe85bed86f80ba3ed73d59775a88", + "sha256:c3529fb98a40f89269175442c5ff4ef81d22e91b2bdcbd33833a350709b5130c", + "sha256:cc8e926d6ffa65d0dddb871b7afe117f17bc045951e66afde60eb0eba923db9e", + "sha256:ce90aad0a3dc0f13a9ff0ab1f43bcbea436089b83c3fadbe37c6f1733b938bf1", + "sha256:cec702974f162026bf8de47f6f4b7ce9584a63c50002b38f195ee797165fea77", + "sha256:d9ef8119ce44f90d2f8ac7c58f7da480ada5151f217dc8da03681b73fc91dec3", + "sha256:eccaefbd646022b5313ca4b0c5f1ae6e0d3a52ef66de64970ecf3f9b2a1be751", + "sha256:fb91deb5121b6dde88599bcb3db3fdad9cf33ff3d4ccc5329ee1fe9655a2f7ff", + "sha256:fc25d59ecf23ea19571065306806a29c43c67f830f0e8a121303916ba257f484" + ], + "markers": "python_version >= '3.6'", + "version": "==8.3.0" + }, + "protobuf": { + "hashes": [ + "sha256:13ee7be3c2d9a5d2b42a1030976f760f28755fcf5863c55b1460fd205e6cd637", + "sha256:145ce0af55c4259ca74993ddab3479c78af064002ec8227beb3d944405123c71", + "sha256:14c1c9377a7ffbeaccd4722ab0aa900091f52b516ad89c4b0c3bb0a4af903ba5", + "sha256:1556a1049ccec58c7855a78d27e5c6e70e95103b32de9142bae0576e9200a1b0", + "sha256:26010f693b675ff5a1d0e1bdb17689b8b716a18709113288fead438703d45539", + "sha256:2ae692bb6d1992afb6b74348e7bb648a75bb0d3565a3f5eea5bec8f62bd06d87", + "sha256:2bfb815216a9cd9faec52b16fd2bfa68437a44b67c56bee59bc3926522ecb04e", + "sha256:4ffbd23640bb7403574f7aff8368e2aeb2ec9a5c6306580be48ac59a6bac8bde", + "sha256:59e5cf6b737c3a376932fbfb869043415f7c16a0cf176ab30a5bbc419cd709c1", + "sha256:6902a1e4b7a319ec611a7345ff81b6b004b36b0d2196ce7a748b3493da3d226d", + "sha256:6ce4d8bf0321e7b2d4395e253f8002a1a5ffbcfd7bcc0a6ba46712c07d47d0b4", + "sha256:6d847c59963c03fd7a0cd7c488cadfa10cda4fff34d8bc8cba92935a91b7a037", + "sha256:72804ea5eaa9c22a090d2803813e280fb273b62d5ae497aaf3553d141c4fdd7b", + "sha256:7a4c97961e9e5b03a56f9a6c82742ed55375c4a25f2692b625d4087d02ed31b9", + "sha256:85d6303e4adade2827e43c2b54114d9a6ea547b671cb63fafd5011dc47d0e13d", + "sha256:8727ee027157516e2c311f218ebf2260a18088ffb2d29473e82add217d196b1c", + "sha256:99938f2a2d7ca6563c0ade0c5ca8982264c484fdecf418bd68e880a7ab5730b1", + "sha256:9b7a5c1022e0fa0dbde7fd03682d07d14624ad870ae52054849d8960f04bc764", + "sha256:a22b3a0dbac6544dacbafd4c5f6a29e389a50e3b193e2c70dae6bbf7930f651d", + "sha256:a38bac25f51c93e4be4092c88b2568b9f407c27217d3dd23c7a57fa522a17554", + "sha256:a981222367fb4210a10a929ad5983ae93bd5a050a0824fc35d6371c07b78caf6", + "sha256:ab6bb0e270c6c58e7ff4345b3a803cc59dbee19ddf77a4719c5b635f1d547aa8", + "sha256:c56c050a947186ba51de4f94ab441d7f04fcd44c56df6e922369cc2e1a92d683", + "sha256:e76d9686e088fece2450dbc7ee905f9be904e427341d289acbe9ad00b78ebd47", + "sha256:ebcb546f10069b56dc2e3da35e003a02076aaa377caf8530fe9789570984a8d2", + "sha256:f0e59430ee953184a703a324b8ec52f571c6c4259d496a19d1cabcdc19dabc62", + "sha256:ffea251f5cd3c0b9b43c7a7a912777e0bc86263436a87c2555242a348817221b" + ], + "version": "==3.17.3" + }, + "pyasn1": { + "hashes": [ + "sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359", + "sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576", + "sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf", + "sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7", + "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d", + "sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00", + "sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8", + "sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86", + "sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12", + "sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776", + "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba", + "sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2", + "sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3" + ], + "version": "==0.4.8" + }, + "pyasn1-modules": { + "hashes": [ + "sha256:0845a5582f6a02bb3e1bde9ecfc4bfcae6ec3210dd270522fee602365430c3f8", + "sha256:0fe1b68d1e486a1ed5473f1302bd991c1611d319bba158e98b106ff86e1d7199", + "sha256:15b7c67fabc7fc240d87fb9aabf999cf82311a6d6fb2c70d00d3d0604878c811", + "sha256:426edb7a5e8879f1ec54a1864f16b882c2837bfd06eee62f2c982315ee2473ed", + "sha256:65cebbaffc913f4fe9e4808735c95ea22d7a7775646ab690518c056784bc21b4", + "sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e", + "sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74", + "sha256:a99324196732f53093a84c4369c996713eb8c89d360a496b599fb1a9c47fc3eb", + "sha256:b80486a6c77252ea3a3e9b1e360bc9cf28eaac41263d173c032581ad2f20fe45", + "sha256:c29a5e5cc7a3f05926aff34e097e84f8589cd790ce0ed41b67aed6857b26aafd", + "sha256:cbac4bc38d117f2a49aeedec4407d23e8866ea4ac27ff2cf7fb3e5b570df19e0", + "sha256:f39edd8c4ecaa4556e989147ebf219227e2cd2e8a43c7e7fcb1f1c18c5fd6a3d", + "sha256:fe0644d9ab041506b62782e92b06b8c68cca799e1a9636ec398675459e031405" + ], + "version": "==0.2.8" + }, + "pyyaml": { + "hashes": [ + "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf", + "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696", + "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393", + "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77", + "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922", + "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5", + "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8", + "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10", + "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc", + "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018", + "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e", + "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253", + "sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347", + "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183", + "sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541", + "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb", + "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185", + "sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc", + "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db", + "sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa", + "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46", + "sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122", + "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b", + "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63", + "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df", + "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc", + "sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247", + "sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6", + "sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", + "version": "==5.4.1" + }, + "requests": { + "hashes": [ + "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804", + "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==2.25.1" + }, + "requests-oauthlib": { + "hashes": [ + "sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d", + "sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a", + "sha256:fa6c47b933f01060936d87ae9327fead68768b69c6c9ea2109c48be30f2d4dbc" + ], + "version": "==1.3.0" + }, + "rsa": { + "hashes": [ + "sha256:78f9a9bf4e7be0c5ded4583326e7461e3a3c5aae24073648b4bdfa797d78c9d2", + "sha256:9d689e6ca1b3038bc82bf8d23e944b6b6037bc02301a574935b2dd946e0353b9" + ], + "markers": "python_version >= '3.6'", + "version": "==4.7.2" + }, + "six": { + "hashes": [ + "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", + "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.16.0" + }, + "tensorboard": { + "hashes": [ + "sha256:e167460085b6528956b33bab1c970c989cdce47a6616273880733f5e7bde452e" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.5.0" + }, + "tensorboard-data-server": { + "hashes": [ + "sha256:809fe9887682d35c1f7d1f54f0f40f98bb1f771b14265b453ca051e2ce58fca7", + "sha256:d8237580755e58eff68d1f3abefb5b1e39ae5c8b127cc40920f9c4fb33f4b98a", + "sha256:fa8cef9be4fcae2f2363c88176638baf2da19c5ec90addb49b1cde05c95c88ee" + ], + "markers": "python_version >= '3.6'", + "version": "==0.6.1" + }, + "tensorboard-plugin-wit": { + "hashes": [ + "sha256:2a80d1c551d741e99b2f197bb915d8a133e24adb8da1732b840041860f91183a" + ], + "version": "==1.8.0" + }, + "torch": { + "hashes": [ + "sha256:2e49cac969976be63117004ee00d0a3e3dd4ea662ad77383f671b8992825de1a", + "sha256:38d67f4fb189a92a977b2c0a38e4f6dd413e0bf55aa6d40004696df7e40a71ff", + "sha256:422e64e98d0e100c360993819d0307e5d56e9517b26135808ad68984d577d75a", + "sha256:5d76c255a41484c1d41a9ff570b9c9f36cb85df9428aa15a58ae16ac7cfc2ea6", + "sha256:6652a767a0572ae0feb74ad128758e507afd3b8396b6e7f147e438ba8d4c6f63", + "sha256:a3793dcceb12b1e2281290cca1277c5ce86ddfd5bf044f654285a4d69057aea7", + "sha256:af464a6f4314a875035e0c4c2b07517599704b214634f4ed3ad2e748c5ef291f", + "sha256:d241c3f1c4d563e4ba86f84769c23e12606db167ee6f674eedff6d02901462e3", + "sha256:dd2fc6880c95e836960d86efbbc7f63d3287f2e1893c51d31f96dbfe02f0d73e", + "sha256:de84b4166e3f7335eb868b51d3bbd909ec33828af27290b4171bce832a55be3c", + "sha256:e000b94be3aa58ad7f61e7d07cf379ea9366cf6c6874e68bd58ad0bdc537b3a7", + "sha256:f0aaf657145533824b15f2fd8fde8f8c67fe6c6281088ef588091f03fad90243" + ], + "markers": "platform_system != 'Windows'", + "version": "==1.7.1" + }, + "typing-extensions": { + "hashes": [ + "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497", + "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342", + "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84" + ], + "markers": "python_version < '3.8'", + "version": "==3.10.0.0" + }, + "urllib3": { + "hashes": [ + "sha256:39fb8672126159acb139a7718dd10806104dec1e2f0f6c88aab05d17df10c8d4", + "sha256:f57b4c16c62fa2760b7e3d97c35b255512fb6b59a259730f36ba32ce9f8e342f" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", + "version": "==1.26.6" + }, + "werkzeug": { + "hashes": [ + "sha256:1de1db30d010ff1af14a009224ec49ab2329ad2cde454c8a708130642d579c42", + "sha256:6c1ec500dcdba0baa27600f6a22f6333d8b662d22027ff9f6202e3367413caa8" + ], + "markers": "python_version >= '3.6'", + "version": "==2.0.1" + }, + "wheel": { + "hashes": [ + "sha256:78b5b185f0e5763c26ca1e324373aadd49182ca90e825f7853f4b2509215dc0e", + "sha256:e11eefd162658ea59a60a0f6c7d493a7190ea4b9a85e335b33489d9f17e0245e" + ], + "markers": "python_version >= '3'", + "version": "==0.36.2" + }, + "zipp": { + "hashes": [ + "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3", + "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4" + ], + "markers": "python_version >= '3.6'", + "version": "==3.5.0" + } + }, + "develop": {} +} diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/Readme.md b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/Readme.md new file mode 100644 index 0000000000000000000000000000000000000000..27b0b6a9b6d66f7bb0a3362c55c262f091326e68 --- /dev/null +++ b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/Readme.md @@ -0,0 +1,94 @@ +# Task-Allocation and Prioritized pathplanning (TA-Prioritized) + +The Task-Allocation and Prioritized pathplanning (TA-Prioritized) algorithm is a centralized algorithm for the offline variant of the MAPD problem. + +In the offline variant of the MAPD problem the following is supported: +- Using tasks from a taskslist with releaseTimes +- Tested from 1 agent up untill 50 agents (significant lag for larger amount of agents) + +Not supported: +- Randomly generated tasks (randomTasks = True) +- Tasklists without releaseTimes + +## Running the algorithm + +1. Install the virtual environment + - 'pipenv install' +2. Setup the LKH-3 TSP solver (see "LKH-3 TSP Solver" section) +3. Setup lkh.config (see below) +4. Run the "centralized_decisionmaker_shortest_path.py" file +4. Start the game inside the Unity editor + +## Working of the algorithm + +This implementation is a modified version of the implementation available at: https://github.com/Pieter-Cawood/M-TA-Prioritized-MAPD + +This implementation is based on the "Task and Path Planning for Multi-Agent Pickup and Delivery" paper (http://idm-lab.org/bib/abstracts/papers/aamas19a.pdf). +An explanation of the algorithm is available at: + - Section 3 and 4 of the "Task and Path Planning for Multi-Agent Pickup and Delivery" paper + - Section 2.2.2 of the paper provided in the "paper" + +General working of the algorithm: + - The algorithm uses the LKH-3 TSP Solver to generate task sequences for the agents: + * Each agent gets an ordered list of tasks (or no tasks at all) + * The agent needs to execute these tasks in the provided order + - The algorithm plans 1 path for each agent to execute its whole task set: + * Each agent gets one path that allows it to execute all its tasks in the correct order + => In order to minimize the amount of timesteps needed to solve the problem the algorithm uses the Prioritized Pathplanning method to always plan longer paths first + => This is done to avoid making the longer paths even longer by waiting to avoid collisions (see papers for a more detailed explanation) + - Once all the agents have their path they start following that path + * In each timestep each agent moves one step following its path + +## (IMPORTANT) LKH-3 TSP Solver + +- This algorithm uses a modified version of the original LKH-3 TSP solver (original: http://akira.ruc.dk/~keld/research/LKH-3/) to generate task sequences. The source code (and an executable for Linux and Windows) can be found in the LKH3 directory. A visual studio project for Windows is added as LKHwin-3.0.6-WinChanges. +- By default the algorithm computes new task sequences using the LKH-3 solver every time the algorithm is ran +- The algorithm supports using pre-computed task sequences (as this process can be slow for larger task sets) (see "Generating pre-computed task sequences" section) + +### Setup of LKH-3 TSP Solver + +- The source code (and an executable for Linux and Windows) are provided in the LKH-3 directory +- If the provided executable is not supported by your machine (error when trying to run the LKH-3 executable) you can compile a new executable on a Unix/Linux machine using the following commands: + * cd LKH3 + * make +- On Windows machines you need to create an .exe file using the visual studio project provided in the LKH3/SRC directory + +### Running algorithm without using pre-computed task sequences +- Set the lkh.conf file as follows: + * tourFile = None + * path = specify path to LKH3 solver (can found in directory LKH3, Linux: LKH_linux, Windows: LKH-3.exe) + * lkhMaxTime = The maximum time (in seconds) that should be used by the LKH-3 TSP solver to compute task sequences (default: 500) +- Run the main file centralized_decisionmaker_shortest_path.py directly. + +### Running algorithm using pre-computed task sequences +- Set the lkh.conf file as follows: + * tourFile = None. + * path = specify path to LKH3 solver (can found in directory LKH3, Linux: LKH_linux, Windows: LKH-3.exe) + * lkhMaxTime = The maximum time (in seconds) that should be used by the LKH-3 TSP solver to compute task sequences (default: 500) +- Compute tour file using generate_tour_file.py + * Add the path to the problem file (config file warehouse) and the file containing the tasks in generate_tour_file.py. + * run generate_tour_file.py, a tour file will have been generated and added in LKH3/TOUR. Each tour file created will have a unique name. +- Set the lkh.conf file as follows: + * tourFile = path to tour file computed in previous step. + * path = path to LKH3 solver (Linux: LKH_linux, Windows: LKH-3.exe) + * lkhMaxTime = The maximum time (in seconds) that should be used by the LKH-3 TSP solver to compute task sequences (default: 500) +- Run the main file centralized_decisionmaker_shortest_path.py + +## Overview of the provided files + +Main file: +- centralized_decisionmaker_shortest_path.py: Main file that runs the algorithm + +Task Allocation and Prioritized Pathplanning: +- ta_agent.py: Agent that are executing tasks +- ta_system.py: System allocates tasks and plans paths for agents +- ta_task.py: Pickup and delivery tasks +- ta_world.py: Class that reads and stores the warehouse environment + +A-star: +- ta_astar.py: A-Star algorithm +- ta_state.py: Contains Location and state classes used for the path planning + +LKH-3: +- lkh.py: Class that computes task sequences using the LKH-3 TSP solver +- lkh.conf: Configuration file for the LKH-3 TSP solver \ No newline at end of file diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/TaskSideChannel.py b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/TaskSideChannel.py new file mode 100644 index 0000000000000000000000000000000000000000..3e86f1a0f43763e5ee775f1063422926c5a64297 --- /dev/null +++ b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/TaskSideChannel.py @@ -0,0 +1,41 @@ +import json +from mlagents_envs.side_channel.side_channel import ( + SideChannel, + IncomingMessage, + OutgoingMessage, +) +import uuid + +import ta_task +from ta_state import Location + + +class TaskSideChannel(SideChannel): + + def __init__(self) -> None: + super().__init__(uuid.UUID("c11ab982-82b8-4194-b387-3bd0fe9ebdc7")) #must coincide with ChannelId set in c# + self.environment_data = None #info on the environment + + # channel receives new tasks that have to be assigned + def on_message_received(self, msg: IncomingMessage) -> None: + data = msg.read_string() + new_task = json.loads(data) + new_task = new_task["task"] + task_to_add = ta_task.Task(ta_task.CURRENT_TASK_ID, + Location(new_task["PickUp"]["Column"], + new_task["PickUp"]["Row"], 0), + Location(new_task["Delivery"]["Column"], new_task["Delivery"]["Row"], 0), + new_task["ReleaseTime"], + None) + ta_task.CURRENT_TASK_ID += 1 + # add task to task to be assigned + self.environment_data.add_task_to_tasks_to_be_assigned(task_to_add) + + # channel sends information when a task has been assigned (to which robot) + def send_string(self, data: str) -> None: + + # Add the string to an OutgoingMessage + msg = OutgoingMessage() + msg.write_string(data) + # We call this method to queue the data we want to send + super().queue_message_to_send(msg) diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/centralized_decisionmaker_shortest_path.py b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/centralized_decisionmaker_shortest_path.py new file mode 100644 index 0000000000000000000000000000000000000000..2cc18a3d799b06749b833e0bd27ddaf0a71dda98 --- /dev/null +++ b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/centralized_decisionmaker_shortest_path.py @@ -0,0 +1,209 @@ +from mlagents_envs.environment import ActionTuple, UnityEnvironment +import EnvChannel +import TaskSideChannel +import PickupAndDeliveryChannel as PADEC +import numpy as np +import os +import time + +from Node import Node + +import configparser + +from lkh import LKH + +# from pickup_and_delivery.task import Task +from ta_system import System as TA_System +from ta_state import Location +from ta_agent import Agent + +# as long as simulation_going is true, new actions will be generated +simulation_going = True + +# Load the side channels and Unity environment. +envChannel = EnvChannel.EnvChannel() +taskChannel = TaskSideChannel.TaskSideChannel() +# Open unity and press play to execute +env = UnityEnvironment(file_name=None, side_channels=[ + envChannel, taskChannel]) +env.reset() # reset the environment + +# Specify the used behaviour name for steering the agent +behavior_names = list(env.behavior_specs.keys()) +behavior_name = behavior_names[0] + +# info obtained from environment +environment_info = envChannel.EnvData +# set up links between task side channel and environment info +environment_info.task_side_channel = taskChannel +taskChannel.environment_data = environment_info + +##--------## +## Agents ## +##--------## + +# Create all the agents +agentsList = [] +for robot_id, start_node in environment_info.current_nodes_dictionary.items(): + # Convert the Node that represents the agent's starting position to a Location + robot_position = Location(start_node.y, start_node.x, start_node.g) + # Create agent + agentsList.append(Agent(robot_id, robot_position)) + +##-------## +## Tasks ## +##-------## + +# Retrieve all tasks +tasksList = environment_info.tasks_to_be_assigned + +##-----------------------------## +## LKH3-Solver: Task sequences ## +##-----------------------------## + +## Create the LKH class so that the problem (and parameter) files for the LKH3 solver can be generated +lkh = LKH(environment_info.matrix, tasksList, agentsList) +# File that contains all the task sequences: can either be pre-computed or can be computed on the fly +lkhFile = lkh.get_task_sequences() + +##--------## +## System ## +##--------## + +# Initialize system +system = TA_System(environment_info.matrix, environment_info.rotation, agentsList, tasksList, lkhFile) + +##---------------## +## Path Planning ## +##---------------## + +# Retrieve all agents from the system +agents_list = system.world.agents +# Retrieve all paths from the system +agent_paths = system.get_paths() + +##-------------## +## Follow Path ## +##-------------## + +# Keep track of current timestep +actions_requested_in_timestep = 0 +timestep = 0 + +# Keep track of tasks that need to be assigned in Unity +to_assign_tasks = [] + +# Assign all agents to their first task in Unity +for a_id, agent in agents_list.items(): + # Agent has at least one task + if len(agent.taskSet) > 0: + # Get the agent's first task + next_task = agent.taskSet[0] + # Assign the first task to the agent in Unity + environment_info.assign_task( + a_id, system.tasks[next_task.id]) + +while simulation_going: + # Get information on the agents that request an action + decision_steps, terminal_steps = env.get_steps(behavior_name) + agents = decision_steps.agent_id + observation = decision_steps.obs[0][0] + + # Actions that will be sent to Unity + actions = [] + action_tuple = ActionTuple() # actions to send to unity + + # Assign tasks in Unity for agents that are waiting for a new task assignment + for agent_tuple in to_assign_tasks: + # Extract the needed information from the tupple + agent_id = agent_tuple[0] + task = agent_tuple[1] + # Assign the task to the agent in Unity + environment_info.assign_task(agent_id, task) + # Remove the task from the tupple list to avoid assigning the same task to the same agent more than once + to_assign_tasks.remove(agent_tuple) + + ##--------------## + ## Observations ## + ##--------------## + + # get observations per robot and store in dictionary observations[instance_id] -> observation + observations = {} + for i in range(environment_info.number_of_robots): + observation_i = observation[i * environment_info.observation_size: + i * environment_info.observation_size + environment_info.observation_size] + observations[observation_i[0]] = observation_i[1:] + + # Create an action for all agents that request an action + for robot_id_unity in observations: + + ##--------------## + ## OBSERVATIONS ## + ##--------------## + + # robot_id_unity = list(agents_list.keys())[i] + # Collect agent's observations + observation = observations[robot_id_unity] + + # Extract observations + # robot_id_unity = observation[0] # robot id in unity used to get correct precomputed path + robot_pos_x = observation[1] + robot_pos_y = observation[0] + robot_rot = observation[2] + # Convert coordinates to position + robot_position = Location(robot_pos_x, robot_pos_y, robot_rot) + + ##-------------## + ## FOLLOW PATH ## + ##-------------## + + # Get the pre-computed path of the agent + path = agent_paths[robot_id_unity] + + next_pos = None + + # Check if agent still needs to move + if timestep <= agents_list[robot_id_unity].final_action: + # Agent has not yet reached the end of its path: get the next position of the agent + next_pos = path[timestep] + else: + # Agent has reached the end of its path: stay parked at its parking location + next_pos = Location(robot_pos_x, robot_pos_y, robot_rot) + + # Convert Position to Node + next_action = Node(next_pos.row, next_pos.col, next_pos.rotation) + + # Check whether agent needs to pickup/deliver + pickup_action = 0 + delivery_action = 0 + if next_pos.to_pickup: + # Agent has to pick up his task + pickup_action = 1 + elif next_pos.to_deliver: + # Agent has to deliver his task + delivery_action = 1 + # Remove the task that was delivered from the taskSet + agents_list[robot_id_unity].taskSet = agents_list[robot_id_unity].taskSet[1:] + # Get the task set of the agent + tasks = agents_list[robot_id_unity].taskSet + # If there are remaining tasks assign the next one to the agent: + if (len(tasks) > 0): + # Get the agent's next task + next_task = tasks[0] + # Do not assign the task directly as the agent has not yet delivered it's task, add it to a list so that it will be assigned in the next timestep + to_assign_tasks.append((robot_id_unity, system.tasks[next_task.id])) + + # Send action to agent in Unity + actions.extend([robot_id_unity, next_action.x, next_action.y, next_action.g, pickup_action, delivery_action]) + + timestep += 1 + + # Send actions to Unity + actions = np.array(actions) + actions.resize(1, environment_info.number_of_robots * environment_info.action_size) + action_tuple.add_discrete(actions) + + env.set_actions(behavior_name, action_tuple) + env.step() + + diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/generate_tour_file.py b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/generate_tour_file.py new file mode 100644 index 0000000000000000000000000000000000000000..7d0ea098ee7a2035f446ce5d87daab0b52cf063b --- /dev/null +++ b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/generate_tour_file.py @@ -0,0 +1,65 @@ +import os +import json +import numpy as np + +from lkh import Agent, LKH +from ta_world import Location +from ta_task import Task + +#problemFile = "C:/Users/Marjon/Documents/Toolbox_MAS/pick-up-and-delivery/PickUpandDelivery/ConfigurationFiles/Offline_Centralized/warehousejson.txt" +#tasksFile = "C:/Users/Marjon/Documents/Toolbox_MAS/pick-up-and-delivery/PickUpandDelivery/ConfigurationFiles/Offline_Centralized/tasks_releasetime.txt" + +problemFile ="../../../PickUpandDelivery/ConfigurationFiles/Offline_Centralized/warehousejson.txt" +tasksFile = "../../../PickUpandDelivery/ConfigurationFiles/Offline_Centralized/tasks_releasetime.txt" + + +print(os.path.isfile(problemFile)) +print(os.path.isfile(tasksFile)) + +environment = None +agentsList = [] +tasksList = [] + +with open(problemFile) as envFile: + envData = json.load(envFile) + + environment = np.array(envData["Matrix"]) + + agents = envData["InitialNodes"] + + for a in agents: + col = a["GridPosition"]["Column"] + row = a["GridPosition"]["Row"] + rot = a["Degrees"] + + loc = Location(col, row, rot) + + agentsList.append(Agent(loc)) + +with open(tasksFile) as tasksFile: + + tasksData = json.load(tasksFile) + + taskID = 1 + + for task in tasksData: + + pickup = Location(task['PickUp']["Column"], + task['PickUp']["Row"], + 0) + + delivery = Location(task['Delivery']["Column"], + task['Delivery']["Row"], + 0) + + releaseTime = task['ReleaseTime'] + + tasksList.append(Task(taskID, releaseTime, pickup, delivery, None)) + + taskID += 1 + +lkh = LKH(environment, tasksList, agentsList) + +lkhFile = lkh.get_task_sequences() + +print(f"Computed task sequences saved: {lkhFile}") \ No newline at end of file diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/lkh.conf b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/lkh.conf new file mode 100644 index 0000000000000000000000000000000000000000..0fc64fae722c355ffd40ecd05ec99f5f2c091b3e --- /dev/null +++ b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/lkh.conf @@ -0,0 +1,6 @@ +[lkh] +#tourFile=None +path=C:/Users/Marjon/Documents/Toolbox_MAS/pick-up-and-delivery/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/LKH-3.exe +lkhMaxTime=500 + +tourFile=LKH3/TOUR/LKH_2021_08_12-12_29_43.tour \ No newline at end of file diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/lkh.py b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/lkh.py new file mode 100644 index 0000000000000000000000000000000000000000..33bc318348a49021335998965a55aff962976cd1 --- /dev/null +++ b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/lkh.py @@ -0,0 +1,262 @@ +import numpy as np +import configparser +import os +import time +import sys +import json + +from ta_task import Task +# from position import Position, dist +from ta_world import Location + +def dist(loc1, loc2): + return abs(loc1.col - loc2.col) + abs(loc1.row - loc2.row) + +##-----------## +## CONSTANTS ## +##-----------## + +# Dummy agents only used to calculate the distances in the graph +class Agent: + def __init__(self, pos): + # Dummy agents only have a position + self.parking_location = pos + +##--------## +## System ## +##--------## + +class LKH: + def __init__(self, environment, tasks, agentsList): + # Keep track of the agents and the amount of agents + self.agents = agentsList + + # Keep track of all endpoints in the environment + self.task_endpoints = dict() + # Initialize environment + self.init_env(environment) + + # Keep track of tasks in the task set + self.tasks = tasks + # Initialize tasks + self.load_tasks() + + def init_env(self, env): + # Keep track of task endpoints + n_endpoints = 0 + for y in range(len(env)): + for x in range(len(env[0])): + if env[y][x] == 3: + self.task_endpoints[(x, y)] = n_endpoints + n_endpoints += 1 + + ##-------## + ## TASKS ## + ##-------## + + def load_tasks(self): + for task in self.tasks: + pickup_id = self.task_endpoints[( + task.pickup_endpoint.col, task.pickup_endpoint.row)] + task.pickup_id = pickup_id + delivery_id = self.task_endpoints[( + task.delivery_endpoint.col, task.delivery_endpoint.row)] + task.delivery_id = delivery_id + + ##-------## + ## LKH-3 ## + ##-------## + + def get_task_sequences(self): + + ##----------------## + ## Initialization ## + ##----------------## + + print(f"Current directory: {os.getcwd()}") + + # Create a configParser to read the config file + config = configparser.ConfigParser() + # Read the config file + config.read("lkh.conf") + + # Extract information needed from config file + # Path to pre-computed .tour file OR None (default: None) + tour_file_path = config["lkh"]["tourFile"] + lkh_path = config["lkh"]["path"] # Path to the LKH solver (default: /LKH3/LKH) + # Maximum time (in seconds) that is going to be used by the LKH3 solver to compute task sequences (default: 500) + lkh_time = config["lkh"]["lkhMaxTime"] + + if tour_file_path != "None": + # Use a pre-computed .tour file (contains pre-computed task sequences) + return tour_file_path + + # First compute the task sequences using the LKH3 solver, then return the created .tour file + + ## Generate a unique filename for the generated problem, parameter and .tour files + timestr = time.strftime("%Y_%m_%d-%H_%M_%S") + lkh_filename = "LKH_" + timestr + + ## Create problem and parameter files + self.generate_problem_files(lkh_filename) + + ##------------## + ## Run solver ## + ##------------## + + ## Run the LKH-3 algorithm to generate .tour file + print("\n\n[LKH3] Generating task sequences:\n") + os.system(lkh_path + " " + "LKH3/PROBLEM/" + lkh_filename + ".par") + print("\n\n[LKH3] Task sequences generated") + + ##---------------## + ## Return result ## + ##---------------## + + # Save the path of the newly created .tour file + lkhFile = "LKH3/TOUR/" + lkh_filename + ".tour" + return lkhFile + + + + def generate_problem_files(self, lkhFileName): + + ##-------------------------------------## + ## Create graph to calculate sequences ## + ##-------------------------------------## + + n_tasks = len(self.tasks) + n_agents = len(self.agents) + n_nodes = n_tasks + n_agents + edge_weights = np.zeros((n_nodes, n_nodes)) + + # Edge + for k in range(n_agents): + for i in range(n_tasks): + task = self.tasks[i] + agent = self.agents[k] + # Edges from tasks to agents + edge_weights[n_agents + + i][k] = dist(task.pickup_endpoint, task.delivery_endpoint) + # Edges from agents to tasks + edge_weights[k][n_agents+i] = max( + dist(agent.parking_location, task.pickup_endpoint), task.release_time) + + for i in range(n_tasks): + for j in range(n_tasks): + if (i != j): + taski = self.tasks[i] + taskj = self.tasks[j] + # Edges between tasks + d = dist(taski.pickup_endpoint, taski.delivery_endpoint) + \ + dist(taski.delivery_endpoint, taskj.pickup_endpoint) + edge_weights[n_agents+i][n_agents+j] = d + + #---------------------# + # Create problem file # + #---------------------# + + problemFileName = "LKH3/PROBLEM/" + lkhFileName + ".tsp" + problemFile = open(problemFileName, "w") + problemFile.write("NAME: MAPD\n") + problemFile.write("TYPE: TSPTW\n") + problemFile.write(f"DIMENSION: {n_nodes}\n") + problemFile.write("EDGE_WEIGHT_TYPE: EXPLICIT\n") + problemFile.write("DISPLAY_DATA_TYPE: NO_DISPLAY\n") + problemFile.write("EDGE_WEIGHT_FORMAT: FULL_MATRIX\n") + problemFile.write("EDGE_WEIGHT_SECTION\n") + for i in range(n_nodes): + for j in range(n_nodes): + problemFile.write(f"{str(int(edge_weights[i][j]))} ") + problemFile.write("\n") + problemFile.write("TIME_WINDOW_SECTION\n") + for i in range(n_agents): + problemFile.write(f"{i+1} -1 {10000} 0 0 0\n") + for i in range(n_tasks): + task = self.tasks[i] + problemFile.write( + f"{i+1+n_agents} {task.release_time} {10000} {dist(task.pickup_endpoint, task.delivery_endpoint)} {task.pickup_id} {task.delivery_id}\n") + + #-----------------------# + # Create parameter file # + #-----------------------# + + parameterFileName = "LKH3/PROBLEM/" + lkhFileName + ".par" + parFile = open(parameterFileName, "w") + parFile.write("SPECIAL\n") + parFile.write("PROBLEM_FILE = " + problemFileName + "\n") + parFile.write("MAX_TRIALS = 100000\nTIME_LIMIT = 1000\n") + parFile.write("RUNS = 1\n") + parFile.write("TRACE_LEVEL = 1\n") + parFile.write("TOUR_FILE = LKH3/TOUR/" + lkhFileName + ".tour\n") + parFile.write("MAKESPAN = YES\n") + +# environmentFile = None +# tasksFile = None + +#TODO: remove commented code + +# if __name__ == '__main__': +# +# if (len(sys.argv) != 3): +# print("Incorrect number of arguments: 'python lkh.py <problemFile> <tasksFile>'") +# problemFile = "C:/Users/Marjon/Documents/Toolbox_MAS/pick-up-and-delivery/PickUpandDelivery/ConfigurationFiles/Offline_Centralized/warehousejson.txt" +# tasksFile = "C:/Users/Marjon/Documents/Toolbox_MAS/pick-up-and-delivery/PickUpandDelivery/ConfigurationFiles/Offline_Centralized/tasks_releasetime.txt" +# else: +# problemFile = str(sys.argv[1]) +# tasksFile = str(sys.argv[2]) +# +# print(f"Problem file: {problemFile}") +# print(f"Tasks file: {tasksFile}") +# +# environment = None +# agentsList = [] +# tasksList = [] +# +# with open(problemFile) as envFile: +# envData = json.load(envFile) +# +# environment = np.array(envData["Matrix"]) +# +# agents = envData["InitialNodes"] +# +# for a in agents: +# col = a["GridPosition"]["Column"] +# row = a["GridPosition"]["Row"] +# rot = a["Degrees"] +# +# loc = Location(col, row, rot) +# +# agentsList.append(Agent(loc)) +# +# with open(tasksFile) as tasksFile: +# +# tasksData = json.load(tasksFile) +# +# taskID = 1 +# +# for task in tasksData: +# +# pickup = Location(task['PickUp']["Column"], +# task['PickUp']["Row"], +# 0) +# +# delivery = Location(task['Delivery']["Column"], +# task['Delivery']["Row"], +# 0) +# +# releaseTime = task['ReleaseTime'] +# +# tasksList.append(Task(taskID, releaseTime, pickup, delivery, None)) +# +# taskID += 1 +# +# lkh = LKH(environment, tasksList, agentsList) +# +# lkhFile = lkh.get_task_sequences() +# +# print(f"Computed task sequences saved: {lkhFile}") + + + + diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/paper/Bachelorthesis.pdf b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/paper/Bachelorthesis.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e9bf4fce9fccb3903a7f502782e4292f8c59e23d Binary files /dev/null and b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/paper/Bachelorthesis.pdf differ diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/ta_agent.py b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/ta_agent.py new file mode 100644 index 0000000000000000000000000000000000000000..2203d79e507a49fa2b88204e085a6ee591d4a4a2 --- /dev/null +++ b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/ta_agent.py @@ -0,0 +1,27 @@ +""" +Created on Sat Apr 18 11:45:41 2020 + +@author: Pieter Cawood + +""" + +GLOBAL_MAX_AGENT_TIME = 2500 + +class Agent(object): + def __init__(self, _id, parking_location): + self.id = _id + self.parking_location = parking_location + self.path = {} + self.max_time = GLOBAL_MAX_AGENT_TIME + self.pos = parking_location + self.next_endpoint = None + self.time_at_goal = 0 + + self.final_action = 0 + + self.taskSet = [] + + self.tasksPlanning = [] + + + diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/ta_astar.py b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/ta_astar.py new file mode 100644 index 0000000000000000000000000000000000000000..c15b674e09b720dae7cb101a40699b6b8b0bf74c --- /dev/null +++ b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/ta_astar.py @@ -0,0 +1,154 @@ +""" +Created on Wed Apr 22 07:43:03 2020 + +@author: Pieter Cawood + +""" +from heapq import * +from ta_state import * +from ta_world import MAPNODETYPES + +def rotation_steps(rotation, start_rotation, end_rotation): + n_rotations = int(360/rotation) + return int(abs(end_rotation-start_rotation)/rotation) + + + +def get_heuristic(start_location, goal_location, rotation): + # Admissible heuristic - manhattan distance + return abs(start_location.col - goal_location.col) + abs(start_location.row - goal_location.row) + rotation_steps(rotation, start_location.rotation, goal_location.rotation) + +def get_old_heuristic(start_location, goal_location): + # Admissible heuristic - manhattan distance + return abs(start_location.col - goal_location.col) + abs(start_location.row - goal_location.row) + + +class AStar: + def __init__(self, world, _rotation): + self.dim_x = world.width + self.dim_y = world.height + self.obstacles = {} + self.other_agent_paths = [] + + self.rotation = _rotation + + def state_possible(self, current_state, new_state): + # Check not parking or wall + not_obstacle = False + if (new_state.location.col, new_state.location.row) not in self.obstacles: + not_obstacle = True + return 0 <= new_state.location.col < self.dim_x and 0 <= new_state.location.row < self.dim_y \ + and not_obstacle and not self.is_collision(current_state, new_state) + + def is_collision(self, current_state, new_state): + for other_agent_path in self.other_agent_paths: + # Vertex collision + if new_state.time in other_agent_path: + if other_agent_path[new_state.time].row == new_state.location.row and other_agent_path[new_state.time].col == new_state.location.col: + return True + # Edge collision + if new_state.time in other_agent_path and current_state.time in other_agent_path: + if other_agent_path[new_state.time].row == current_state.location.row and \ + other_agent_path[new_state.time].col == current_state.location.col and \ + other_agent_path[current_state.time].row == new_state.location.row and \ + other_agent_path[current_state.time].col == new_state.location.col: + return True + return False + + def get_neighbours(self, current_state): + neighbours = [] + neighbour_time_step = current_state.time + 1 + # Wait in state + new_state = State(neighbour_time_step, Location(current_state.location.col, current_state.location.row, current_state.location.rotation)) + if self.state_possible(current_state, new_state): + neighbours.append(new_state) + + # Add rotation + new_state = State(neighbour_time_step, Location(current_state.location.col, current_state.location.row, (current_state.location.rotation+self.rotation) % 360)) + if self.state_possible(current_state, new_state): + neighbours.append(new_state) + # Remove rotation + new_state = State(neighbour_time_step, Location(current_state.location.col, current_state.location.row, (current_state.location.rotation-self.rotation) % 360)) + if self.state_possible(current_state, new_state): + neighbours.append(new_state) + + ## Move in specific directions + if current_state.location.rotation == 0: + # Move down + new_state = State(neighbour_time_step, Location(current_state.location.col, current_state.location.row - 1, current_state.location.rotation)) + if self.state_possible(current_state, new_state): + neighbours.append(new_state) + elif current_state.location.rotation == 90: + # Move right + new_state = State(neighbour_time_step, Location(current_state.location.col + 1, current_state.location.row, current_state.location.rotation)) + if self.state_possible(current_state, new_state): + neighbours.append(new_state) + elif current_state.location.rotation == 180: + # Move up + new_state = State(neighbour_time_step, Location(current_state.location.col, current_state.location.row + 1, current_state.location.rotation)) + if self.state_possible(current_state, new_state): + neighbours.append(new_state) + elif current_state.location.rotation == 270: + new_state = State(neighbour_time_step, Location(current_state.location.col - 1, current_state.location.row, current_state.location.rotation)) + if self.state_possible(current_state, new_state): + neighbours.append(new_state) + + return neighbours + + def create_obstacles(self, world, other_agent_paths, remaining_parking, timestep): + # Map blocked cells + for element in world: + if world[element] == MAPNODETYPES.WALL: + self.obstacles[(element[0], element[1])] = True + + # Other agents' parking locations + for location in remaining_parking: + self.obstacles[(location.col, location.row)] = True + + short_paths = [] + t = timestep + for path in other_agent_paths: + new_path = dict() + t = timestep + while t in path: + new_path[t] = path[t] + t += 1 + short_paths.append(new_path) + self.other_agent_paths = short_paths + + def search(self, time_step, start_location, goal_location, other_agent_paths, world, parking_locations, agent, + release_time=0, find_step = 0): + self.create_obstacles(world, other_agent_paths, parking_locations, time_step) + initial_state = State(time_step, start_location) + came_from = {} + open_list = [initial_state] + closed_set = set() + initial_state.g_score = 0 + # initial_state.f_score = get_heuristic(start_location, goal_location, self.rotation) + initial_state.f_score = get_old_heuristic(start_location, goal_location) + while open_list: + current = heappop(open_list) + # If agent is at the goal location + if current.location == goal_location: + # Agent cannot move during pickup/delivery, needs at least 2 timesteps at the goal location + if current in came_from and came_from[current].location == goal_location: + # If not yet release time hold and run search + if not current.time < release_time: + new_path = [current] + while current in came_from: + current = came_from[current] + new_path.append(current) + return new_path[::-1] + # Continue looking for the goal location + closed_set |= {current} + neighbours = self.get_neighbours(current) + neighbour: State + for neighbour in neighbours: + # Only explore new states + if (neighbour not in closed_set) and (neighbour not in open_list): + came_from[neighbour] = current + neighbour.g = current.g + 1 + # neighbour.f = neighbour.g + get_heuristic(neighbour.location, goal_location, self.rotation) + neighbour.f = neighbour.g + get_old_heuristic(neighbour.location, goal_location) + heappush(open_list, neighbour) + return False diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/ta_state.py b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/ta_state.py new file mode 100644 index 0000000000000000000000000000000000000000..5ad98faed2d5c8a149f7671e2ce84702c0db5604 --- /dev/null +++ b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/ta_state.py @@ -0,0 +1,56 @@ +""" +Created on Sat Apr 18 10:45:11 2020 + +@author: Pieter Cawood + +""" + +def h(pos1, pos2): + return abs(pos1.col - pos2.col) + abs(pos1.row - pos2.row) + +class Location(object): + def __init__(self, col, row, rotation): + self.col = col + self.row = row + self.rotation = rotation + + # Relevant information for pickup and delivery actions + self.task_id = None + self.to_pickup = False + self.to_deliver = False + + def __eq__(self, other): + return self.col == other.col and self.row == other.row and self.rotation == other.rotation + + def __hash__(self): + return hash(str(self.col) + "_" + str(self.row) + "_" + str(self.rotation)) + + def __str__(self): + return str((self.col, self.row, self.rotation)) + + # Better information for debugging + def __repr__(self): + return f"Location({self.col}, {self.row}, {self.rotation})" + + +class State(object): + def __init__(self, time, location): + self.time = time + self.location = location + self.g = 0 + self.f = 0 + + def __eq__(self, other): + return self.time == other.time and self.location == other.location + + def __hash__(self): + return hash(str(self.time) + str(self.location.col) + str(self.location.row)) + + def __str__(self): + return str((self.time, self.location.col, self.location.row)) + + def __lt__(self, other): + if self.f < other.f: + return True + else: + return False diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/ta_system.py b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/ta_system.py new file mode 100644 index 0000000000000000000000000000000000000000..e36ec78cd4c83668bdbb577597cc9509120962e0 --- /dev/null +++ b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/ta_system.py @@ -0,0 +1,261 @@ +""" +Created on Sat Apr 18 11:11:10 2020 + +@author: Pieter Cawood +""" +import time +from ta_world import * +from ta_task import * +from ta_astar import AStar +from queue import Queue +from itertools import combinations +import concurrent.futures + +GLOBAL_MAX_AGENT_TIME = 2500 + +def plan_path(world, rotation, agent, time_step, release_time=0, find_step=0): + a_star = AStar(world, rotation) + other_agent_paths = [] + parking_locations = [] + + # Add other agent paths + for agent_id in world.agents: + if agent_id != agent.id: + other_agent_paths.append(world.agents[agent_id].path) + parking_locations.append(world.agents[agent_id].parking_location) + start_location = agent.path[time_step] + goal_location = agent.next_endpoint + + # Non dummy path, add release time to hold pickup + new_path = a_star.search(time_step, start_location, goal_location, other_agent_paths, world, parking_locations, + agent, release_time, find_step) + # Could not find path + if not new_path: + return False + + # Update agent path + for state in new_path: + world.agents[agent.id].path[state.time] = state.location + + world.agents[agent.id].time_at_goal = time_step + len(new_path) - 1 + return world.agents[agent.id].time_at_goal + +def copy_queue(queue): + result = Queue() + for entry in queue.queue: + result.put(entry) + return result + +def calculate_execution_time(world, rotation, agent_id, tsp_seqs): + # print(f"Calculating execution time of agent: {agent_id}") + time_step = 0 + new_start_step = -1 + while True: + new_start_step += 1 + time_step = new_start_step + if agent_id not in tsp_seqs: + tsp_seqs[agent_id] = Queue() + seq = copy_queue(tsp_seqs[agent_id]) + path_failed = False + for seq_task in range(seq.qsize()): + task = seq.get() + # To pickup position + world.agents[agent_id].next_endpoint = task.pickup_endpoint + time_step = plan_path(world, rotation, world.agents[agent_id], time_step, task.release_time, 1) + if not time_step: + path_failed = True + break + # To delivery position + world.agents[agent_id].next_endpoint = task.delivery_endpoint + time_step = plan_path(world, rotation, world.agents[agent_id], time_step, 0, 2) + if not time_step: + path_failed = True + break + if not path_failed: + break + # Move agent path back to parking position + for t_step in range(GLOBAL_MAX_AGENT_TIME): + world.agents[agent_id].path[t_step] = world.agents[agent_id].parking_location + return time_step + +class System: + def __init__(self, env, rotation, agentsList, taskList, sequence_file_path): + self.env = env + self.rotation = rotation + self.agentsList = agentsList + self.taskList = taskList + self.sequence_file_path = sequence_file_path + + self.world = None + self.tasks = None + + self.paths = dict() + + self.makespan = 0 + + self.main() + + + def load_files(self): + world = World(self.env, self.agentsList) + self.world = world + tasks = TaskDict(self.taskList, world) + self.tasks = tasks + agent_tour_dict = TourDict( + self.sequence_file_path, self.agentsList, tasks) + return world, tasks, agent_tour_dict + + + def find_agent_path(self, world, rotation, agent, time_step, release_time=0, find_step=0): + a_star = AStar(world, rotation) + other_agent_paths = [] + parking_locations = [] + + # Add other agent paths + for agent_id in world.agents: + if agent_id != agent.id: + other_agent_paths.append(world.agents[agent_id].path) + parking_locations.append(world.agents[agent_id].parking_location) + start_location = agent.path[time_step] + goal_location = agent.next_endpoint + + # Non dummy path, add release time to hold pickup + new_path = a_star.search(time_step, start_location, goal_location, other_agent_paths, world, parking_locations, + agent, release_time, find_step) + # Could not find path + if not new_path: + return False + + # Update agent path + for state in new_path: + world.agents[agent.id].path[state.time] = state.location + + world.agents[agent.id].time_at_goal = time_step + len(new_path) - 1 + return world.agents[agent.id].time_at_goal + + + def test_paths(self, world): + for agent_1, agent_2 in combinations(world.agents, 2): + for time_step in world.agents[agent_1].path: + if time_step > max(world.agents[agent_2].path): + break + # Vertex collision between any two agents + if world.agents[agent_1].path[time_step] == world.agents[agent_2].path[time_step]: + print("Agent #" + str(agent_1) + ",#" + str(agent_2) + " vertex collision at " + + str(world.agents[agent_1].path[time_step]) + " t:" + str(time_step)) + return False + # Edge collision between any two agents + elif (time_step + 1 in world.agents[agent_1].path) and (time_step + 1 in world.agents[agent_2].path): + if (world.agents[agent_1].path[time_step] == world.agents[agent_2].path[time_step + 1]) and \ + (world.agents[agent_2].path[time_step] == world.agents[agent_1].path[time_step + 1]): + print("Agent #" + str(agent_1) + ",#" + str(agent_2) + " edge collision at " + + str(world.agents[agent_1].path[time_step]) + "-" + + str(world.agents[agent_2].path[time_step]) + " t:" + str(time_step)) + return False + return True + + + + def main(self): + world, tasks, tsp_seqs = self.load_files() + make_span = 0 + last_sim_step = 0 + closed_list = {} + time_start = time.perf_counter() + for next_agent in world.agents: + time_agent_start = time.perf_counter() + max_len = 0 + priority_id = -1 + print(f"Determining execution times for remaining agents: ", end='') + ''' + Calculate agents execution time for their paths + Initialise path to parking position once complete + ''' + estimated_times = [] + threads = [] + remainingAgents = [] + + for agent_id in world.agents: + if agent_id not in closed_list: + remainingAgents.append(agent_id) + + if len(remainingAgents) > 1: + with concurrent.futures.ThreadPoolExecutor() as executor: + for agent_id in remainingAgents: + print(agent_id, end=',') + future = executor.submit(calculate_execution_time, world, self.rotation, agent_id, tsp_seqs) + threads.append((future, agent_id)) + print("") + + for threadTuple in threads: + timestep = threadTuple[0].result() + estimated_times.append((timestep, threadTuple[1])) + largest_exec = max(estimated_times, key=lambda t: t[0]) + max_len = largest_exec[0] + priority_id = largest_exec[1] + else: + priority_id = remainingAgents[0] + # print(f"Calculating actual for {priority_id}") + # Expand _id: highest execution time + closed_list[priority_id] = True + # print(f"Agent {priority_id} is now in closed list") + ''' + Calculate actual prioritized agent path + ''' + new_start_step = -1 + while True: + new_start_step += 1 + time_step = new_start_step + seq = copy_queue(tsp_seqs[priority_id]) + path_failed = False + for next_task in range(tsp_seqs[priority_id].qsize()): + task = seq.get() + # To pickup position + world.agents[priority_id].next_endpoint = task.pickup_endpoint + time_step = self.find_agent_path(world, self.rotation, world.agents[priority_id], time_step, task.release_time, 3) + world.agents[priority_id].path[time_step].task_id = task.id + world.agents[priority_id].path[time_step].to_pickup = True + if not time_step: + path_failed = True + break + # To delivery position + world.agents[priority_id].next_endpoint = task.delivery_endpoint + time_step = self.find_agent_path(world, self.rotation, world.agents[priority_id], time_step, 0, 4) + world.agents[priority_id].path[time_step].task_id = task.id + world.agents[priority_id].path[time_step].to_deliver = True + if not time_step: + path_failed = True + break + task.delivered = time_step + world.agents[priority_id].taskSet.append(task) + if not path_failed: + break + # Record make_span before parking travel + make_span = max(make_span, world.agents[priority_id].time_at_goal) + time_agent_stop = time.perf_counter() + print("\t* Agent #" + str(priority_id) + " execution time: " + str( + world.agents[priority_id].time_at_goal) + " (calc :" + str( + round(((time_agent_stop - time_agent_start) / 60), 1)) + " mins)") + # End - Travel back to parking + world.agents[priority_id].next_endpoint = world.agents[priority_id].parking_location + self.find_agent_path(world, self.rotation, world.agents[priority_id], time_step) + last_sim_step = max(last_sim_step, world.agents[priority_id].time_at_goal) + world.agents[priority_id].final_action = last_sim_step + + time_stop = time.perf_counter() + print("Make_span of :" + str(make_span)) + self.makespan = make_span + print("Runtime of :" + str(round(((time_stop - time_start) / 60), 1)) + " minutes") + for a_id, a in world.agents.items(): + self.paths[a_id] = a.path + + def get_paths(self): + return self.paths + + def get_parking_locations(self): + agents = self.world.agents + parking_locations = dict() + for a_id, agent in agents.items(): + parking_pos = agent.parking_location + parking_locations[parking_pos] = a_id + return parking_locations diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/ta_task.py b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/ta_task.py new file mode 100644 index 0000000000000000000000000000000000000000..87abad263c228fe56cb021979dbe4bf4d2d39226 --- /dev/null +++ b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/ta_task.py @@ -0,0 +1,100 @@ +""" +Created on Sat Apr 18 12:51:32 2020 + +@author: Pieter Cawood +""" +from queue import Queue +import os + +CURRENT_TASK_ID = 0 + + +class Task(object): + def __init__(self, task_id, release_time, endpoint_pickup, endpoint_delivery, world): + self.id = task_id + self.assigned_agent = None + self.release_time = release_time + self.pickup_endpoint = endpoint_pickup + self.delivery_endpoint = endpoint_delivery + + self.delivered = None + + self.pickup_id = None + self.delivery_id = None + + def service_time(self): + if self.delivered is not None: + return (self.delivered - self.release_time) + else: + return None + + +# With key of task_id to pair with TaskSequence +class TaskDict(dict): + def __init__(self, taskList, world): + self.load_tasks(taskList, world) + + def load_tasks(self, taskList, world): + + for t in taskList: + self[t.id] = t + + + # task_id = 0 + # for t in taskList: + # task_releaseTime = t[0] + # task_pickup = t[1] + # task_delivery = t[2] + + # self[task_id] = Task(task_id, task_releaseTime, task_pickup, task_delivery, world) + # task_id += 1 + print(f"(2/3) Tasks loaded") + + +# With key of seq id (max is agent count) to load all tasks +# Seq_id is initially agent listed in tour file +class TourDict(dict): + def __init__(self, tour_file_path, agent_count, tasks_dict): + self.load_file(tour_file_path, agent_count, tasks_dict) + + def load_file(self, tour_file_path, agentsList, tasks_dict): + agent_count = len(agentsList) + file = open(tour_file_path, "r") +# file = open("C:/Users/Marjon/Documents/Toolbox_MAS/mvpwarehouse/Algorithm_TA_Prioritized/LKH3/TOUR/LKH_2021_07_08-15_00_44.tour", "r") + if not file.mode == 'r': + print("Could not open " + tour_file_path) + else: + tour_data = file.readlines() + tour_section = False + agent_sequence = None + agent_number = 1 + ez = 0 + for line in tour_data: + if "-1" in line: # end of data + if agent_sequence.qsize(): + agent = agentsList[agent_number-1] + a_id = agent.id + self[a_id] = agent_sequence + tour_section = False + if tour_section: + line_val = int(line) + if line_val <= agent_count: # line listed an agent number + # print(f"Reading sequence of agent: {ez} / {agent_count}") + if agent_sequence.qsize(): # Store previous agent queue + # print(f"Saved sequence for agent {agent_number} with size {agent_sequence.qsize()}") + agent = agentsList[agent_number-1] + a_id = agent.id + self[a_id] = agent_sequence + agent_sequence = Queue() # Create new agent queue + agent_number = line_val + ez += 1 + else: + # Line listed as task number, subtract agent count + task_id = line_val - agent_count - 1 + agent_sequence.put(tasks_dict[task_id]) + # Set initial agent to tsp seq + tasks_dict[task_id].seq_id = agent_number + if "TOUR_SECTION" in line: # start of data next line + tour_section = True + agent_sequence = Queue() + print(f"(3/3) Sequences loaded") diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/ta_world.py b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/ta_world.py new file mode 100644 index 0000000000000000000000000000000000000000..bb39f9cc548bfacb46aefb85c9b4e91cf5ee52a4 --- /dev/null +++ b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/ta_world.py @@ -0,0 +1,67 @@ +""" +Created on Sat Apr 18 10:49:17 2020 + +@author: Pieter Cawood + +""" +from enum import Enum +from ta_agent import * +from ta_state import * + + +class MAPNODETYPES(Enum): + PARKING = 0 + PATH = 1 + WALL = 2 + TASK_ENDPOINT = 3 + + +# Loads map. parking and endpoints are numbered in sequence loaded. +# Task endpoints numbered from agent_number + 1 +class World(dict): + def __init__(self, env, agentsList): + self.agents = dict() + self.endpoints = dict() + self.parking_locations = dict() + self.width = 0 # Map width + self.height = 0 # Map height + self.load_map(env) + self.load_agents(env, agentsList) + + def load_agents(self, env, agentsList): + for agent in agentsList: + agent_col = agent.parking_location.col + agent_row = agent.parking_location.row + if env[agent_row][agent_col] != 2: + raise Exception('Agent {} has an invalid parking location: {}'.format(agent.id, agent.parking_location)) + self.agents[agent.id] = agent + agent.path[0] = agent.parking_location + self.parking_locations[agent.id] = agent.parking_location + + def load_map(self, env): + parking_count = 1 + endpoint_count = 0 + for row in range(len(env)): + for col in range(len(env[0])): + node = None + if env[row][col] == 0: + # Node is a path + node = MAPNODETYPES.PATH + elif env[row][col] == 2: + # Node is a parking location (non-task endpoint) + node = MAPNODETYPES.PARKING + elif env[row][col] == 1: + # Node is a wall + node = MAPNODETYPES.WALL + elif env[row][col] == 3: + # Node is a pickup/delivery location (task endpoint) + node = MAPNODETYPES.TASK_ENDPOINT + self.endpoints[endpoint_count] = Location(col, row, 0) + endpoint_count += 1 + if node is not None: + # Add node to this collection + self[col, row] = node + self.width = len(env[0]) + self.height = len(env) + print(f"(1/3) Map loaded") + print(f"Created {parking_count} agents") diff --git a/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/test.py b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/test.py new file mode 100644 index 0000000000000000000000000000000000000000..5afca52772df1cee7078faa5fac96a39cd7a9421 --- /dev/null +++ b/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/test.py @@ -0,0 +1,15 @@ +import os + +#total = "C:/Users/Marjon/Documents/Toolbox_MAS/pick-up-and-delivery/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized/LKH3/TOUR/LKH_2021_08_11-16_23_20.tour" +#start = "C:/Users/Marjon/Documents/Toolbox_MAS/pick-up-and-delivery/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized" + +total = "C:/Users/Marjon/Documents/Toolbox_MAS/pick-up-and-delivery/PickUpandDelivery/ConfigurationFiles/Offline_Centralized/warehousejson.txt" +start = "C:/Users/Marjon/Documents/Toolbox_MAS/pick-up-and-delivery/Algorithms/Offline_Centralized/Algorithm_TA_Prioritized" + +#print(os.path.relpath(total, start)) + +test = "../../../PickUpandDelivery/ConfigurationFiles/Offline_Centralized/warehousejson.txt" + +print(os.path.isfile(test)) + +print(os.path.isfile("LKH3/LKH-3.exe")) \ No newline at end of file diff --git a/Algorithms/Offline_Centralized/Algorithm_test_toyexample_offline_centralized/EnvChannel.py b/Algorithms/Offline_Centralized/Algorithm_test_toyexample_offline_centralized/EnvChannel.py new file mode 100644 index 0000000000000000000000000000000000000000..64ab52f3d9eba835313576996a986084d4dc6233 --- /dev/null +++ b/Algorithms/Offline_Centralized/Algorithm_test_toyexample_offline_centralized/EnvChannel.py @@ -0,0 +1,61 @@ +""" + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +""" +import json +from mlagents_envs.side_channel.side_channel import ( + SideChannel, + IncomingMessage, + OutgoingMessage, +) +import uuid + +from EnvironmentData import EnvironmentData + +""" +class that processes information from SideChannel EnvChannel: stores all incoming information +in an instance of class EnvironmentData +""" + +class EnvChannel(SideChannel): + + def __init__(self) -> None: + super().__init__(uuid.UUID("621f0a70-4f87-11ea-a6bf-784f4387d1f7")) #must coincide with ChannelId set in c# + self.envData = EnvironmentData() # object that stores info on environment + + def on_message_received(self, msg: IncomingMessage) -> None: + # We simply read a string from the message and print it. + data = msg.read_string() + environment_info = json.loads(data) + + self.envData.matrix = environment_info["matrixLayout"] + self.envData.rotation = environment_info["rotationRobot"] + self.envData.size_of_action = environment_info["sizeOfAction"] + self.envData.size_of_observation = environment_info["sizeOfObservation"] + self.envData.number_of_robots = environment_info["numberOfRobotsInEnv"] + self.envData.number_of_current_tasks = environment_info["numberOfCurrentTasks"] + self.envData.can_go_backwards = environment_info["backwards"] + self.envData.random_tasks = environment_info["tasksGeneratedRandomly"] + self.envData.instance_ids = environment_info["instanceIDSRobots"] + + self.envData.set_initial_nodes_dictionary(environment_info["initialNodesOfRobots"]) + self.envData.set_tasks_to_be_assigned(environment_info["currentTasks"]) + self.envData.set_assigned_tasks() + + def send_string(self, data: str) -> None: + # Add the string to an OutgoingMessage + msg = OutgoingMessage() + msg.write_string(data) + # We call this method to queue the data we want to send + super().queue_message_to_send(msg) \ No newline at end of file diff --git a/Algorithms/Offline_Centralized/Algorithm_test_toyexample_offline_centralized/EnvironmentData.py b/Algorithms/Offline_Centralized/Algorithm_test_toyexample_offline_centralized/EnvironmentData.py new file mode 100644 index 0000000000000000000000000000000000000000..0e8e71e36be0c96182a7480803290e2edbaccb2f --- /dev/null +++ b/Algorithms/Offline_Centralized/Algorithm_test_toyexample_offline_centralized/EnvironmentData.py @@ -0,0 +1,99 @@ +""" + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +""" + +""" +stores data on environment +instance methods that initialize environment (used by EnvChannel) +- set_initial_nodes_dictionary(initial_nodes): initializes current_nodes_dictionary +containing current(next) nodes for each of the robots +- set_tasks_to_be_assigned(tasks): initialize tasks_to_be_assigned: tasks that have to be assigned +- set_assigned_tasks(): initialize assigned_tasks_dictionary containing + for every robot the current assigned task + +instance methods that update environment info +- assign_task(robot_instanceID, task): assign task to a given robot +- add_task_to_tasks_to_be_assigned(task): append a new task to tasks_to_be_assigned +- task_done(instance_id): remove task from robot that was assigned this task +""" + + +from Node import Node +from Task import Position, Task + + +class EnvironmentData: + + def __init__(self): + self.matrix = None + self.rotation = None + self.size_of_action = None + self.size_of_observation = None + self.number_of_robots = None + self.number_of_current_tasks = None + self.can_go_backwards = None + self.random_tasks = None # if set to true random tasks will be send whenever a task has been completed, + # otherwise all tasks self.tasks_to_be_assigned + + self.instance_ids = [] + self.current_nodes_dictionary = {} # dictionary instance_id -> current node + self.tasks_to_be_assigned = [] # tasks that are still to be assigned + self.assigned_tasks_dictionary = {} # dictionary instance_id -> assigned task + + + ######################################### + ## methods used by EnvChannel to initialize attributes: + ######################################### + + # given a correct string containing array of nodes + def set_initial_nodes_dictionary(self, initial_nodes): + for i in range(self.number_of_robots): + self.current_nodes_dictionary[self.instance_ids[i]] = Node(initial_nodes[i]["GridPosition"]["Row"], + initial_nodes[i]["GridPosition"]["Column"], + initial_nodes[i]["Degrees"]) + + # given a correct json_string containing array of tasks + def set_tasks_to_be_assigned(self, tasks): + for i in range(self.number_of_current_tasks): + pickup = Position(tasks[i]["PickUp"]["Row"], tasks[i]["PickUp"]["Column"]) + delivery = Position(tasks[i]["Delivery"]["Row"], tasks[i]["Delivery"]["Column"]) + release = tasks[i]["ReleaseTime"] + self.tasks_to_be_assigned.append(Task(pickup, delivery, release)) + + # initialize dictionary robot instance_id -> task (None) + def set_assigned_tasks(self): + for i in range(self.number_of_robots): + self.assigned_tasks_dictionary[self.instance_ids[i]] = None + + ######################################### + ## methods used to update environment info + ######################################### + + # when a task is assigned to a robot, it has to be added to self.assigned_tasks + # and removed from self.tasks_to_be_assigned + def assign_task(self, robot_instanceID, task): + self.assigned_tasks_dictionary[robot_instanceID] = task + self.tasks_to_be_assigned.remove(task) + + # when a new task is available it is added to tasks_to_be_assigned + # a check is made whether there are still tasks that can be added, but this should not be happening (diagnostical) + def add_task_to_tasks_to_be_assigned(self, task): + if len(self.tasks_to_be_assigned) == self.number_of_current_tasks: + raise Exception("cannot add more tasks") + self.tasks_to_be_assigned.append(task) + + # when a robot has finished his task it has to be removed from assigned_tasks + def task_done(self, instance_id): + self.assigned_tasks_dictionary[instance_id] = None diff --git a/Algorithms/Offline_Centralized/Algorithm_test_toyexample_offline_centralized/EnvironmentManager.py b/Algorithms/Offline_Centralized/Algorithm_test_toyexample_offline_centralized/EnvironmentManager.py new file mode 100644 index 0000000000000000000000000000000000000000..d830bee18b18943dfe19075de04c1083c021f727 --- /dev/null +++ b/Algorithms/Offline_Centralized/Algorithm_test_toyexample_offline_centralized/EnvironmentManager.py @@ -0,0 +1,203 @@ +""" + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +""" + +"""' +Class that contains and manages the information on the environment. +- Initializes and holds information on the environment (EnvData). +- Contains a reference to the sidechannel (EnvChannel). +- Contains a reference to the sidechannel (TaskChannel). +- Contains a reference to the unity environment (UnityEnv). +Has instance methods +- reset() which resets the environment. +- step() which assigns tasks, computes a new action based on observation from the unity environment + and sends actions back to unity, updates info environment when a task has finished +- close() which closes the environment/ + +Has also some auxilary instance methods: +- assign_new_task() which finds a new task and a robot that is free, then calls +assign_task_to_robot(robot_instanceID, task) +- compute_path(current_node, task) which computes paths starting in current_node completing a certain task +- initialize_shortest_paths() which initializes a dictionary containing the paths robots are following +- assign_task_to_robot(robot_instanceID, task) which assigns task to a robot with given instance ID, +updates EnvData and sends information on assignment back to Unity + +Note that this a toy example. No checks are done on collisions. +""" + + +import json + +from mlagents_envs.base_env import ActionTuple + +from Graph import Graph +from Node import Node + +import numpy as np + + +class EnvironmentManager: + + def __init__(self, envData, unityEnv, envChannel, taskChannel): + self.envData = envData + self.unityEnv = unityEnv + self.envChannel = envChannel + self.taskChannel = taskChannel + + # IMPORTANT: sends info through envChannel, to be called before setting up connection envData an taskChannel + self.reset() + + # taskChannel needs info on envData + self.taskChannel.environment_data = envData + + # behavior name for agent + self.behavior_name = list(unityEnv.behavior_specs.keys())[0] + + # graph that is used for computing paths + self.graph = Graph(envData.matrix, envData.rotation, envData.can_go_backwards) + + # for every robot with instanceID id shortest_paths[id] gives the shortest path to + # its currently assigned task + self.shortest_paths = {} + + self.initialize_shortest_paths() + + # step in the environment + # 1) checks if new tasks can be assigned + # 2) collect observations + # 3) compute new actions + # 4) send actions back to Unity + def step(self): + self.assign_new_task() + + # get information from the agent that requests an action + decision_steps, terminal_steps = self.unityEnv.get_steps(self.behavior_name) + + # decision_steps.obs is a list of numpy arrays, first dimension corresponds to the number of agents that has requested + # a decision (here 1), the observation of the agent is the first element + observation = decision_steps.obs[0][0] + + print("----------------------------------------") + + + actions = [] # long list of all actions + action_tuple = ActionTuple() # actions to send to unity + + # get observations per robot and store in dictionary observations[instance_id] -> observation + observations = {} + for i in range(self.envData.number_of_robots): + observation_i = observation[i * self.envData.size_of_observation: + i * self.envData.size_of_observation + self.envData.size_of_observation] + observations[observation_i[0]] = observation_i[1:] + + # create an action for all robots and send at once to unity + for robot_id_unity in observations: + + obs = observations[robot_id_unity] + print("robot " + str(robot_id_unity) + " at node [(" + str(obs[0]) + "," + str(obs[1]) + ")," + str( + obs[2]) + "]") + + path = self.shortest_paths[robot_id_unity] + # if path is empty, then robot should stay at same node + if len(path) == 0: + actions.extend([robot_id_unity, obs[0], obs[1], obs[2], 0, 0]) + # if path is not empty we get next action from shortest path + else: + next_action = path[0] # is node or "pickup" or "deliver" + if next_action == "pickup": + actions.extend([robot_id_unity, obs[0], obs[1], obs[2], 1, 0]) + elif next_action == "deliver": + actions.extend([robot_id_unity, obs[0], obs[1], obs[2], 0, 1]) + self.envData.assigned_tasks_dictionary[robot_id_unity] = None + else: + actions.extend([robot_id_unity, next_action.x, next_action.y, next_action.g, 0, 0]) + # update current node + self.envData.current_nodes_dictionary[robot_id_unity] = Node(next_action.x, next_action.y, + next_action.g) + # update path + self.shortest_paths[robot_id_unity] = path[1:] + + # add action to action_tuple and set the actions + actions = np.array(actions) + actions.resize(1, self.envData.size_of_action * self.envData.number_of_robots) + action_tuple.add_discrete(actions) + + self.unityEnv.set_actions(self.behavior_name, action_tuple) + self.unityEnv.step() # send actions to unity and wait until a new decision is requested + + + + + # reset the environment + def reset(self): + self.unityEnv.reset() + + # close the environment + def close(self): + self.close() + + # assigns the next available task to an idle robot, if possible + def assign_new_task(self): + # check if there are tasks that have to be assigned + # if this is the case, get first task and assign to available robot + if len(self.envData.tasks_to_be_assigned) != 0: + task = self.envData.tasks_to_be_assigned[0] + # get available robot + for robot_id in self.envData.instance_ids: + if self.envData.assigned_tasks_dictionary[robot_id] is None: + # robot is free: assign task to robot and break out of for loop + self.assign_task_to_robot(robot_id, task) + break + + + # compute path from current_node that finishes given task + # for test purposes pick up and delivery need to have rotation 0 + # at pick up delivery robot stays at same node + # returns a sequence of nodes and pick up/delivery actions + def compute_path(self, current_node, task): + path1 = self.graph.computeShortestPath(current_node, + Node(task.PickUp.Row, task.PickUp.Column, 0)) + path1 = path1[1:] + path2 = self.graph.computeShortestPath(Node(task.PickUp.Row, task.PickUp.Column, 0), + Node(task.Delivery.Row, task.Delivery.Column, 0)) + path2 = path2[1:] + + return path1 + ["pickup"] + path2 + ["deliver"] + + + # for every robot initially there is an empty path to be followed + def initialize_shortest_paths(self): + for robot_id in self.envData.instance_ids: + self.shortest_paths[robot_id] = [] + + def assign_task_to_robot(self, robot_instanceID, task): + # update envData + self.envData.assign_task(robot_instanceID, task) + # compute path for robot + self.shortest_paths[robot_instanceID] = \ + self.compute_path(self.envData.current_nodes_dictionary[robot_instanceID],task) + # send info to unity + taskDict = {"Task": { + "PickUp": {"Row": task.PickUp.Row, "Column": task.PickUp.Column}, + "Delivery": {"Row": task.Delivery.Row, "Column": task.Delivery.Column}, + "ReleaseTime": task.ReleaseTime}, + "InstanceID": robot_instanceID} + self.taskChannel.send_string(json.dumps(taskDict)) + + + + + + diff --git a/Algorithms/Offline_Centralized/Algorithm_test_toyexample_offline_centralized/Graph.py b/Algorithms/Offline_Centralized/Algorithm_test_toyexample_offline_centralized/Graph.py new file mode 100644 index 0000000000000000000000000000000000000000..69e03b997172dae6855dca7f06890606239e7063 --- /dev/null +++ b/Algorithms/Offline_Centralized/Algorithm_test_toyexample_offline_centralized/Graph.py @@ -0,0 +1,126 @@ +""" + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +""" + +from networkx import DiGraph, shortest_path +from Node import Node + +""" +Class Graph creates a graph based on matrix, deviation (unit of rotation) and whether robots can move backwards). +Its nodes contain position in the grid and orientation wrt north (see class <c>Node</c>). +Networkx package as underlying data structure. +""" + +class Graph: + def __init__(self, matrix, deviation, cangobackwards): + self.matrix = matrix + self.number_of_rows = len(matrix) + self.number_of_columns = len(matrix[0]) + self.deviation = deviation + self.cangobackwards = cangobackwards + self.graph = DiGraph() + + for i in range(self.number_of_rows): + for j in range(self.number_of_columns): + # we have to add nodes to the graph when we encounter a number different than 1 + if matrix[i][j] != 1: + self.addEdgesByRotation(i, j) + self.addEdgesByMovingForward(i,j) + + def addEdgesByRotation(self, row, column): + degree = 0 + while degree < 360: + newnode = Node(row, column, degree) + + # add all edges from newnode staying at the same position (row, number), i.e. rotation + + # rotate left + rotateLeftNode = Node(row, column, get_degree_in_range_0_360(degree - self.deviation)) + self.graph.add_edge(newnode, rotateLeftNode) + + # rotate right + rotateRightNode = Node(row, column, get_degree_in_range_0_360(degree + self.deviation)) + self.graph.add_edge(newnode, rotateRightNode) + + degree += self.deviation + + def addEdgesByMovingForward(self, row, column): + # check left + if column > 0 and self.matrix[row][column-1] != 1: + # we can move forward if we have degree 270 + currentnode = Node(row, column, 270) + neighbourleft = Node(row, column-1, 270) + self.graph.add_edge(currentnode, neighbourleft) + # we can move backward if we have degree 90 + if self.cangobackwards: + currentnode = Node(row, column, 90) + neighbourleft = Node(row, column-1, 90) + self.graph.add_edge(currentnode, neighbourleft) + + # check right + if column < self.number_of_columns -1 and self.matrix[row][column+1] != 1: + # we can move forward if we have degree 90 + currentnode = Node(row, column, 90) + neighbourright = Node(row, column+1, 90) + self.graph.add_edge(currentnode, neighbourright) + # we can move backward if we have degree 270 + if self.cangobackwards: + currentnode = Node(row, column, 270) + neighbourright = Node(row, column+1, 270) + self.graph.add_edge(currentnode, neighbourright) + + # check up + if row > 0 and self.matrix[row-1][column] != 1: + # we can move forward if we have degree 0 + currentnode = Node(row, column, 0) + neighbourup = Node(row-1, column, 0) + self.graph.add_edge(currentnode, neighbourup) + # we can move backward if we have degree 180 + if self.cangobackwards: + currentnode = Node(row, column, 180) + neighbourup = Node(row-1, column, 180) + self.graph.add_edge(currentnode, neighbourup) + + # check down + if row < self.number_of_rows-1 and self.matrix[row+1][column] != 1: + # we can move forward if we have degree 180 + currentnode = Node(row, column, 180) + neighbourdown = Node(row+1, column, 180) + self.graph.add_edge(currentnode, neighbourdown) + # we can move backward if we have degree 0 + if self.cangobackwards: + currentnode = Node(row, column, 0) + neighbourdown = Node(row+1, column, 0) + self.graph.add_edge(currentnode, neighbourdown) + + def computeShortestPath(self, start_node, end_node): + #compute shortest path from start_node to end_node: return a list + return shortest_path(self.graph, start_node, end_node) + +def get_degree_in_range_0_360(degree): + rest = degree % 360 + if rest < 0: + return rest + 360 + return rest + + + + + + + + + + diff --git a/Algorithms/Offline_Centralized/Algorithm_test_toyexample_offline_centralized/Node.py b/Algorithms/Offline_Centralized/Algorithm_test_toyexample_offline_centralized/Node.py new file mode 100644 index 0000000000000000000000000000000000000000..126684f885f63b51edcd2b6684d26d7a847c51af --- /dev/null +++ b/Algorithms/Offline_Centralized/Algorithm_test_toyexample_offline_centralized/Node.py @@ -0,0 +1,57 @@ +""" + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +""" + +""" +Class Node represent nodes in the graph. Every node contains a +position (x,y) in the grid +and a rotation in degree where +0 = North +90 = East +280 = South +270 = West +all degrees must be between 0 and 360 + +attributes are set to private such that they cannot be overwritten and there is no problem with the hash +""" + +class Node: + def __init__(self,x,y,g): + self._x = x + self._y = y + self._g = g + + @property + def x(self): + return self._x + + @property + def y(self): + return self._y + + @property + def g(self): + return self._g + + + def __eq__(self, other): + return self.__class__ == other.__class__ and self.x == other.x and self.y == other.y and self.g == other.g + + + def __hash__(self): + return (((self.x * 397) ** self.y) * 397) **self.g + + def __str__(self): + return "[(" + str(self.x) + ", " + str(self.y) + ")" + "," + str(self.g) + "]" diff --git a/Algorithms/Offline_Centralized/Algorithm_test_toyexample_offline_centralized/Pipfile b/Algorithms/Offline_Centralized/Algorithm_test_toyexample_offline_centralized/Pipfile new file mode 100644 index 0000000000000000000000000000000000000000..2cf8108a7836978e89ef3320e61b72d3c4eb3be6 --- /dev/null +++ b/Algorithms/Offline_Centralized/Algorithm_test_toyexample_offline_centralized/Pipfile @@ -0,0 +1,14 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +networkx = "==2.5" +mlagents = "==0.23.0" +mlagents-envs = "==0.23.0" + +[dev-packages] + +[requires] +python_version = "3.6" diff --git a/Algorithms/Offline_Centralized/Algorithm_test_toyexample_offline_centralized/Task.py b/Algorithms/Offline_Centralized/Algorithm_test_toyexample_offline_centralized/Task.py new file mode 100644 index 0000000000000000000000000000000000000000..23aa3d5b09f76858f524061f0050f39d9e914fe0 --- /dev/null +++ b/Algorithms/Offline_Centralized/Algorithm_test_toyexample_offline_centralized/Task.py @@ -0,0 +1,51 @@ +""" + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +""" + +""" +Class Task represents tasks which consist of 2 positions: a pickup and a delivery position and a release time. +""" +class Task: + def __init__(self, pos1, pos2, release): + self.PickUp = pos1 + self.Delivery = pos2 + self.ReleaseTime = release + + def __eq__(self, other): + return self.__class__ == other.__class__ and self.PickUp == other.PickUp and\ + self.Delivery == other.Delivery and self.ReleaseTime == other.ReleaseTime + + def __hash__(self): + hash_code = hash(self.PickUp) + hash_code = (hash_code * 397) ** hash(self.Delivery) + hash_code = (hash_code * 397) ** hash(self.ReleaseTime) + return hash_code + + def __str__(self): + return "[" + str(self.PickUp) + ", " + str(self.Delivery) + "]" + str(self.ReleaseTime) + +class Position: + def __init__(self, x, y): + self.Row = x + self.Column = y + + def __eq__(self, other): + return self.__class__ == other.__class__ and self.Row == other.Row and self.Column == other.Column + + def __hash__(self): + return ((self.Row * 397) ** self.Column) * 397 + + def __str__(self): + return "(" + str(self.Row) + ", " + str(self.Column) + ")" diff --git a/Algorithms/Offline_Centralized/Algorithm_test_toyexample_offline_centralized/TaskSideChannel.py b/Algorithms/Offline_Centralized/Algorithm_test_toyexample_offline_centralized/TaskSideChannel.py new file mode 100644 index 0000000000000000000000000000000000000000..6b5d1fba25f4def24a809c0552ee719bd7bef553 --- /dev/null +++ b/Algorithms/Offline_Centralized/Algorithm_test_toyexample_offline_centralized/TaskSideChannel.py @@ -0,0 +1,50 @@ +""" + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +""" + +from mlagents_envs.side_channel.side_channel import ( + SideChannel, + IncomingMessage, + OutgoingMessage, +) +import uuid + +from Task import Task, Position + +""" +Class that processes info from the TaskSideChannel. +- sends assignment of tasks to robots +""" + + +class TaskSideChannel(SideChannel): + + def __init__(self) -> None: + super().__init__(uuid.UUID("c11ab982-82b8-4194-b387-3bd0fe9ebdc7")) #must coincide with ChannelId set in c# + self.environment_data = None #info on the environment + + # channel receives new tasks that have to be assigned + def on_message_received(self, msg: IncomingMessage) -> None: + # We simply read a string from the message and print it. + print(msg.read_string()) + + # channel sends information when a task has been assigned (to which robot) + def send_string(self, data: str) -> None: + + # Add the string to an OutgoingMessage + msg = OutgoingMessage() + msg.write_string(data) + # We call this method to queue the data we want to send + super().queue_message_to_send(msg) \ No newline at end of file diff --git a/Algorithms/Offline_Centralized/Algorithm_test_toyexample_offline_centralized/main.py b/Algorithms/Offline_Centralized/Algorithm_test_toyexample_offline_centralized/main.py new file mode 100644 index 0000000000000000000000000000000000000000..bf0312bb53a914f0169c5b6fb6d78efb87298b3c --- /dev/null +++ b/Algorithms/Offline_Centralized/Algorithm_test_toyexample_offline_centralized/main.py @@ -0,0 +1,44 @@ +""" + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +""" + +""" +Main file that controls and decision making +This is a toy example! +Uses EnvironmentManager who assigns tasks in order to available agents +and then computes shortest paths, no check on collisions. +""" + +from mlagents_envs.environment import UnityEnvironment +import EnvChannel, TaskSideChannel +import EnvironmentManager + +# as long as simulation_going is true, new actions will be generated + +simulation_going = True + +# setup side channels and unity environment +envChannel = EnvChannel.EnvChannel() +taskChannel = TaskSideChannel.TaskSideChannel() +env = UnityEnvironment(file_name=None, side_channels=[envChannel, taskChannel]) + +# set up environment manager +envManager = EnvironmentManager.EnvironmentManager(envChannel.envData, env, envChannel, taskChannel) + + +while simulation_going: + envManager.step() + +envManager.close() diff --git a/Algorithms/Offline_Decentralized/Algorithm_test_toyexample_offline_decentralized/EnvChannel.py b/Algorithms/Offline_Decentralized/Algorithm_test_toyexample_offline_decentralized/EnvChannel.py new file mode 100644 index 0000000000000000000000000000000000000000..b6d62add37419b9cfe1ddb9b07a70b150a07a6d7 --- /dev/null +++ b/Algorithms/Offline_Decentralized/Algorithm_test_toyexample_offline_decentralized/EnvChannel.py @@ -0,0 +1,63 @@ +""" + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +""" + +import json +from mlagents_envs.side_channel.side_channel import ( + SideChannel, + IncomingMessage, + OutgoingMessage, +) +import uuid + +from EnvironmentData import EnvironmentData + +""" +class that processes information from SideChannel EnvChannel: stores all incoming information +in an instance of class EnvironmentData +""" + + +class EnvChannel(SideChannel): + + def __init__(self) -> None: + super().__init__(uuid.UUID("621f0a70-4f87-11ea-a6bf-784f4387d1f7")) #must coincide with ChannelId set in c# + self.envData = EnvironmentData() # object that stores info on environment + + def on_message_received(self, msg: IncomingMessage) -> None: + # We simply read a string from the message and print it. + data = msg.read_string() + environment_info = json.loads(data) + + self.envData.matrix = environment_info["matrixLayout"] + self.envData.rotation = environment_info["rotationRobot"] + self.envData.size_of_action = environment_info["sizeOfAction"] + self.envData.size_of_observation = environment_info["sizeOfObservation"] + self.envData.number_of_robots = environment_info["numberOfRobotsInEnv"] + self.envData.number_of_current_tasks = environment_info["numberOfCurrentTasks"] + self.envData.can_go_backwards = environment_info["backwards"] + self.envData.random_tasks = environment_info["tasksGeneratedRandomly"] + self.envData.instance_ids = environment_info["instanceIDSRobots"] + + self.envData.set_initial_nodes_dictionary(environment_info["initialNodesOfRobots"]) + self.envData.set_tasks_to_be_assigned(environment_info["currentTasks"]) + self.envData.set_assigned_tasks() + + def send_string(self, data: str) -> None: + # Add the string to an OutgoingMessage + msg = OutgoingMessage() + msg.write_string(data) + # We call this method to queue the data we want to send + super().queue_message_to_send(msg) \ No newline at end of file diff --git a/Algorithms/Offline_Decentralized/Algorithm_test_toyexample_offline_decentralized/EnvironmentData.py b/Algorithms/Offline_Decentralized/Algorithm_test_toyexample_offline_decentralized/EnvironmentData.py new file mode 100644 index 0000000000000000000000000000000000000000..be6a9c1e66b598ea49fd5fba407962fc81bc9581 --- /dev/null +++ b/Algorithms/Offline_Decentralized/Algorithm_test_toyexample_offline_decentralized/EnvironmentData.py @@ -0,0 +1,102 @@ +""" + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +""" + +""" +stores data on environment +instance methods that initialize environment (used by EnvChannel) +- set_initial_nodes_dictionary(initial_nodes): initializes current_nodes_dictionary +containing current(next) nodes for each of the robots +- set_tasks_to_be_assigned(tasks): initialize tasks_to_be_assigned: tasks that have to be assigned +- set_assigned_tasks(): initialize assigned_tasks_dictionary containing + for every robot the current assigned task + +instance methods that update environment info +- assign_task(robot_instanceID, task): assign task to a given robot +- add_task_to_tasks_to_be_assigned(task): append a new task to tasks_to_be_assigned +- task_done(instance_id): remove task from robot that was assigned this task +""" + + +import json + +from Node import Node +from Task import Position, Task + + +class EnvironmentData: + + def __init__(self): + self.matrix = None + self.rotation = None + self.size_of_action = None + self.size_of_observation = None + self.number_of_robots = None + self.number_of_current_tasks = None + self.can_go_backwards = None + self.random_tasks = None # if set to true random tasks will be send whenever a task has been completed, + # otherwise all tasks self.tasks_to_be_assigned + + self.instance_ids = [] + self.current_nodes_dictionary = {} # dictionary instance_id -> current node + self.tasks_to_be_assigned = [] # tasks that are still to be assigned + self.assigned_tasks_dictionary = {} # dictionary instance_id -> assigned task + + + ######################################### + ## methods used by EnvChannel to initialize attributes: + ######################################### + + # given a correct string containing array of nodes + def set_initial_nodes_dictionary(self, initial_nodes): + for i in range(self.number_of_robots): + self.current_nodes_dictionary[self.instance_ids[i]] = Node(initial_nodes[i]["GridPosition"]["Row"], + initial_nodes[i]["GridPosition"]["Column"], + initial_nodes[i]["Degrees"]) + + # given a correct json_string containing array of tasks + def set_tasks_to_be_assigned(self, tasks): + for i in range(self.number_of_current_tasks): + pickup = Position(tasks[i]["PickUp"]["Row"], tasks[i]["PickUp"]["Column"]) + delivery = Position(tasks[i]["Delivery"]["Row"], tasks[i]["Delivery"]["Column"]) + release = tasks[i]["ReleaseTime"] + self.tasks_to_be_assigned.append(Task(pickup, delivery, release)) + + # initialize dictionary robot instance_id -> task (None) + def set_assigned_tasks(self): + for i in range(self.number_of_robots): + self.assigned_tasks_dictionary[self.instance_ids[i]] = None + + ######################################### + ## methods used to update environment info + ######################################### + + # when a task is assigned to a robot, it has to be added to self.assigned_tasks + # and removed from self.tasks_to_be_assigned + # info has to be sent to unity via the correct channel + def assign_task(self, robot_instanceID, task): + self.assigned_tasks_dictionary[robot_instanceID] = task + self.tasks_to_be_assigned.remove(task) + + # when a new task is available it is added to tasks_to_be_assigned + # a check is made whether there are still tasks that can be added, but this should not be happening (diagnostical) + def add_task_to_tasks_to_be_assigned(self, task): + if len(self.tasks_to_be_assigned) == self.number_of_current_tasks: + raise Exception("cannot add more tasks") + self.tasks_to_be_assigned.append(task) + + # when a robot has finished his task it has to be removed from assigned_tasks + def task_done(self, instance_id): + self.assigned_tasks_dictionary[instance_id] = None diff --git a/Algorithms/Offline_Decentralized/Algorithm_test_toyexample_offline_decentralized/EnvironmentManager.py b/Algorithms/Offline_Decentralized/Algorithm_test_toyexample_offline_decentralized/EnvironmentManager.py new file mode 100644 index 0000000000000000000000000000000000000000..910a3108999159afa39573e29a13b95d94465168 --- /dev/null +++ b/Algorithms/Offline_Decentralized/Algorithm_test_toyexample_offline_decentralized/EnvironmentManager.py @@ -0,0 +1,196 @@ +""" + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +""" + +"""' +Class that contains and manages the information on the environment. +- Initializes and holds information on the environment (EnvData). +- Contains a reference to the sidechannel (EnvChannel). +- Contains a reference to the sidechannel (TaskChannel). +- Contains a reference to the unity environment (UnityEnv). +Has instance methods +- reset() which resets the environment. +- step() which assigns tasks, computes a new action based on observation from the unity environment + and sends actions back to unity, updates info environment when a task has finished +- close() which closes the environment/ + +Has also some auxiliary instance methods: +- assign_new_task() which finds a new task and a robot that is free, then calls +assign_task_to_robot(robot_instanceID, task) +- compute_path(current_node, task) which computes paths starting in current_node completing a certain task +- initialize_shortest_paths() which initializes a dictionary containing the paths robots are following +- assign_task_to_robot(robot_instanceID, task) which assigns task to a robot with given instance ID, +updates EnvData and sends information on assignment back to Unity + +Note that this a toy example. No checks are done on collisions. +""" + +import json + +from mlagents_envs.base_env import ActionTuple + +from Graph import Graph +from Node import Node + +import numpy as np + + +class EnvironmentManager: + + def __init__(self, envData, unityEnv, envChannel, taskChannel): + self.envData = envData + self.unityEnv = unityEnv + self.envChannel = envChannel + self.taskChannel = taskChannel + + # IMPORTANT: sends info through envChannel, to be called before setting up connection envData an taskChannel + self.reset() + + # taskChannel needs info on envData + self.taskChannel.environment_data = envData + + # behavior name for agent + self.behavior_name = list(unityEnv.behavior_specs.keys())[0] + + # graph that is used for computing paths + self.graph = Graph(envData.matrix, envData.rotation, envData.can_go_backwards) + + # for every robot with instanceID id shortest_paths[id] gives the shortest path to + # its currently assigned task + self.shortest_paths = {} + + self.initialize_shortest_paths() + + # step in the environment + # 1) checks if new tasks can be assigned + # 2) collect observations + # 3) compute new actions + # 4) send actions back to Unity + def step(self): + self.assign_new_task() + + # get information from the agent that requests an action + decision_steps, terminal_steps = self.unityEnv.get_steps(self.behavior_name) + + print("request is being made by") + agents = decision_steps.agent_id + print(str(len(agents)) + " agents") + + # decision_steps.obs is a list of numpy arrays, first dimension corresponds to the number of agents that has requested + # a decision (here len(agents)) + observations = decision_steps.obs + + print("----------------------------------------") + + + actions = [] # long list of all actions + action_tuple = ActionTuple() # actions to send to unity + + # create an action for all agents that request an action + for i in range(len(agents)): + observation = observations[0][i] # observation of current agent + robot_id_unity = observation[0] + row = observation[1] + column = observation[2] + degrees = observation[3] + + print("robot " + str(robot_id_unity) + " at node [(" + str(row) + "," + str(column) + ")," + str( + degrees) + "]") + + path = self.shortest_paths[robot_id_unity] + + # if path is empty, then robot should stay at same node + if len(path) == 0: + actions.extend([row, column, degrees, 0, 0]) + # if path is not empty we get next action from shortest path + else: + next_action = path[0] # is a node or "pickup" or "deliver" + if next_action == "pickup": + actions.extend([row, column, degrees, 1, 0]) + elif next_action == "deliver": + actions.extend([row, column, degrees, 0, 1]) + self.envData.assigned_tasks_dictionary[robot_id_unity] = None + else: + actions.extend([next_action.x, next_action.y, next_action.g, 0, 0]) + # update current node + self.envData.current_nodes_dictionary[robot_id_unity] = Node(next_action.x, next_action.y, + next_action.g) + # update path + self.shortest_paths[robot_id_unity] = path[1:] + + # add action to action_tuple and set the actions + actions = np.array(actions) + actions.resize(len(agents), self.envData.size_of_action) + action_tuple.add_discrete(actions) + + self.unityEnv.set_actions(self.behavior_name, action_tuple) + self.unityEnv.step() # send actions to unity and wait until a new decision is requested + + # reset the environment + def reset(self): + self.unityEnv.reset() + + # close the environment + def close(self): + self.close() + + # assigns the next available task to an idle robot, if possible + def assign_new_task(self): + # check if there are tasks that have to be assigned + # if this is the case, get first task and assign to available robot + if len(self.envData.tasks_to_be_assigned) != 0: + task = self.envData.tasks_to_be_assigned[0] + # get available robot + for robot_id in self.envData.instance_ids: + if self.envData.assigned_tasks_dictionary[robot_id] is None: + # robot is free: assign task to robot and break out of for loop + self.assign_task_to_robot(robot_id, task) + break + + + # compute path from current_node that finishes given task + # for test purposes pick up and delivery need to have rotation 0 + # at pick up delivery robot stays at same node + # returns a sequence of nodes and pick up/delivery actions + def compute_path(self, current_node, task): + path1 = self.graph.computeShortestPath(current_node, + Node(task.PickUp.Row, task.PickUp.Column, 0)) + path1 = path1[1:] + path2 = self.graph.computeShortestPath(Node(task.PickUp.Row, task.PickUp.Column, 0), + Node(task.Delivery.Row, task.Delivery.Column, 0)) + path2 = path2[1:] + + return path1 + ["pickup"] + path2 + ["deliver"] + + + # for every robot initially there is an empty path to be followed + def initialize_shortest_paths(self): + for robot_id in self.envData.instance_ids: + self.shortest_paths[robot_id] = [] + + def assign_task_to_robot(self, robot_instanceID, task): + # update envData + self.envData.assign_task(robot_instanceID, task) + # compute path for robot + self.shortest_paths[robot_instanceID] = \ + self.compute_path(self.envData.current_nodes_dictionary[robot_instanceID],task) + # send info to unity + taskDict = {"Task": { + "PickUp": {"Row": task.PickUp.Row, "Column": task.PickUp.Column}, + "Delivery": {"Row": task.Delivery.Row, "Column": task.Delivery.Column}, + "ReleaseTime": task.ReleaseTime}, + "InstanceID": robot_instanceID} + self.taskChannel.send_string(json.dumps(taskDict)) + diff --git a/Algorithms/Offline_Decentralized/Algorithm_test_toyexample_offline_decentralized/Graph.py b/Algorithms/Offline_Decentralized/Algorithm_test_toyexample_offline_decentralized/Graph.py new file mode 100644 index 0000000000000000000000000000000000000000..69e03b997172dae6855dca7f06890606239e7063 --- /dev/null +++ b/Algorithms/Offline_Decentralized/Algorithm_test_toyexample_offline_decentralized/Graph.py @@ -0,0 +1,126 @@ +""" + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +""" + +from networkx import DiGraph, shortest_path +from Node import Node + +""" +Class Graph creates a graph based on matrix, deviation (unit of rotation) and whether robots can move backwards). +Its nodes contain position in the grid and orientation wrt north (see class <c>Node</c>). +Networkx package as underlying data structure. +""" + +class Graph: + def __init__(self, matrix, deviation, cangobackwards): + self.matrix = matrix + self.number_of_rows = len(matrix) + self.number_of_columns = len(matrix[0]) + self.deviation = deviation + self.cangobackwards = cangobackwards + self.graph = DiGraph() + + for i in range(self.number_of_rows): + for j in range(self.number_of_columns): + # we have to add nodes to the graph when we encounter a number different than 1 + if matrix[i][j] != 1: + self.addEdgesByRotation(i, j) + self.addEdgesByMovingForward(i,j) + + def addEdgesByRotation(self, row, column): + degree = 0 + while degree < 360: + newnode = Node(row, column, degree) + + # add all edges from newnode staying at the same position (row, number), i.e. rotation + + # rotate left + rotateLeftNode = Node(row, column, get_degree_in_range_0_360(degree - self.deviation)) + self.graph.add_edge(newnode, rotateLeftNode) + + # rotate right + rotateRightNode = Node(row, column, get_degree_in_range_0_360(degree + self.deviation)) + self.graph.add_edge(newnode, rotateRightNode) + + degree += self.deviation + + def addEdgesByMovingForward(self, row, column): + # check left + if column > 0 and self.matrix[row][column-1] != 1: + # we can move forward if we have degree 270 + currentnode = Node(row, column, 270) + neighbourleft = Node(row, column-1, 270) + self.graph.add_edge(currentnode, neighbourleft) + # we can move backward if we have degree 90 + if self.cangobackwards: + currentnode = Node(row, column, 90) + neighbourleft = Node(row, column-1, 90) + self.graph.add_edge(currentnode, neighbourleft) + + # check right + if column < self.number_of_columns -1 and self.matrix[row][column+1] != 1: + # we can move forward if we have degree 90 + currentnode = Node(row, column, 90) + neighbourright = Node(row, column+1, 90) + self.graph.add_edge(currentnode, neighbourright) + # we can move backward if we have degree 270 + if self.cangobackwards: + currentnode = Node(row, column, 270) + neighbourright = Node(row, column+1, 270) + self.graph.add_edge(currentnode, neighbourright) + + # check up + if row > 0 and self.matrix[row-1][column] != 1: + # we can move forward if we have degree 0 + currentnode = Node(row, column, 0) + neighbourup = Node(row-1, column, 0) + self.graph.add_edge(currentnode, neighbourup) + # we can move backward if we have degree 180 + if self.cangobackwards: + currentnode = Node(row, column, 180) + neighbourup = Node(row-1, column, 180) + self.graph.add_edge(currentnode, neighbourup) + + # check down + if row < self.number_of_rows-1 and self.matrix[row+1][column] != 1: + # we can move forward if we have degree 180 + currentnode = Node(row, column, 180) + neighbourdown = Node(row+1, column, 180) + self.graph.add_edge(currentnode, neighbourdown) + # we can move backward if we have degree 0 + if self.cangobackwards: + currentnode = Node(row, column, 0) + neighbourdown = Node(row+1, column, 0) + self.graph.add_edge(currentnode, neighbourdown) + + def computeShortestPath(self, start_node, end_node): + #compute shortest path from start_node to end_node: return a list + return shortest_path(self.graph, start_node, end_node) + +def get_degree_in_range_0_360(degree): + rest = degree % 360 + if rest < 0: + return rest + 360 + return rest + + + + + + + + + + diff --git a/Algorithms/Offline_Decentralized/Algorithm_test_toyexample_offline_decentralized/Node.py b/Algorithms/Offline_Decentralized/Algorithm_test_toyexample_offline_decentralized/Node.py new file mode 100644 index 0000000000000000000000000000000000000000..126684f885f63b51edcd2b6684d26d7a847c51af --- /dev/null +++ b/Algorithms/Offline_Decentralized/Algorithm_test_toyexample_offline_decentralized/Node.py @@ -0,0 +1,57 @@ +""" + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +""" + +""" +Class Node represent nodes in the graph. Every node contains a +position (x,y) in the grid +and a rotation in degree where +0 = North +90 = East +280 = South +270 = West +all degrees must be between 0 and 360 + +attributes are set to private such that they cannot be overwritten and there is no problem with the hash +""" + +class Node: + def __init__(self,x,y,g): + self._x = x + self._y = y + self._g = g + + @property + def x(self): + return self._x + + @property + def y(self): + return self._y + + @property + def g(self): + return self._g + + + def __eq__(self, other): + return self.__class__ == other.__class__ and self.x == other.x and self.y == other.y and self.g == other.g + + + def __hash__(self): + return (((self.x * 397) ** self.y) * 397) **self.g + + def __str__(self): + return "[(" + str(self.x) + ", " + str(self.y) + ")" + "," + str(self.g) + "]" diff --git a/Algorithms/Offline_Decentralized/Algorithm_test_toyexample_offline_decentralized/Pipfile b/Algorithms/Offline_Decentralized/Algorithm_test_toyexample_offline_decentralized/Pipfile new file mode 100644 index 0000000000000000000000000000000000000000..2cf8108a7836978e89ef3320e61b72d3c4eb3be6 --- /dev/null +++ b/Algorithms/Offline_Decentralized/Algorithm_test_toyexample_offline_decentralized/Pipfile @@ -0,0 +1,14 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +networkx = "==2.5" +mlagents = "==0.23.0" +mlagents-envs = "==0.23.0" + +[dev-packages] + +[requires] +python_version = "3.6" diff --git a/Algorithms/Offline_Decentralized/Algorithm_test_toyexample_offline_decentralized/Task.py b/Algorithms/Offline_Decentralized/Algorithm_test_toyexample_offline_decentralized/Task.py new file mode 100644 index 0000000000000000000000000000000000000000..6ed7c37501e17a97a2a21349c34d6220720ad380 --- /dev/null +++ b/Algorithms/Offline_Decentralized/Algorithm_test_toyexample_offline_decentralized/Task.py @@ -0,0 +1,53 @@ +""" + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +""" + +""" +Class Task represents tasks which consist of 2 positions: a pickup and a delivery position and a release time. +""" + +class Task: + def __init__(self, pos1, pos2, release): + self.PickUp = pos1 + self.Delivery = pos2 + self.ReleaseTime = release + + def __eq__(self, other): + return self.__class__ == other.__class__ and self.PickUp == other.PickUp and\ + self.Delivery == other.Delivery and self.ReleaseTime == other.ReleaseTime + + def __hash__(self): + hash_code = hash(self.PickUp) + hash_code = (hash_code * 397) ** hash(self.Delivery) + hash_code = (hash_code * 397) ** hash(self.ReleaseTime) + return hash_code + + def __str__(self): + return "[" + str(self.PickUp) + ", " + str(self.Delivery) + "]" + str(self.ReleaseTime) + + +class Position: + def __init__(self, x, y): + self.Row = x + self.Column = y + + def __eq__(self, other): + return self.__class__ == other.__class__ and self.Row == other.Row and self.Column == other.Column + + def __hash__(self): + return ((self.Row * 397) ** self.Column) * 397 + + def __str__(self): + return "(" + str(self.Row) + ", " + str(self.Column) + ")" diff --git a/Algorithms/Offline_Decentralized/Algorithm_test_toyexample_offline_decentralized/TaskSideChannel.py b/Algorithms/Offline_Decentralized/Algorithm_test_toyexample_offline_decentralized/TaskSideChannel.py new file mode 100644 index 0000000000000000000000000000000000000000..5f75664d7780ae5804ed869bebeac4a7815903e5 --- /dev/null +++ b/Algorithms/Offline_Decentralized/Algorithm_test_toyexample_offline_decentralized/TaskSideChannel.py @@ -0,0 +1,48 @@ +""" + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +""" + +from mlagents_envs.side_channel.side_channel import ( + SideChannel, + IncomingMessage, + OutgoingMessage, +) +import uuid + + +""" +Class that processes info from the TaskSideChannel. +- sends assignment of tasks to robots +""" + + +class TaskSideChannel(SideChannel): + + def __init__(self) -> None: + super().__init__(uuid.UUID("c11ab982-82b8-4194-b387-3bd0fe9ebdc7")) #must coincide with ChannelId set in c# + self.environment_data = None #info on the environment + + def on_message_received(self, msg: IncomingMessage) -> None: + # We simply read a string from the message and print it. + print(msg.read_string()) + + # channel sends information when a task has been assigned (to which robot) + def send_string(self, data: str) -> None: + + # Add the string to an OutgoingMessage + msg = OutgoingMessage() + msg.write_string(data) + # We call this method to queue the data we want to send + super().queue_message_to_send(msg) \ No newline at end of file diff --git a/Algorithms/Offline_Decentralized/Algorithm_test_toyexample_offline_decentralized/main.py b/Algorithms/Offline_Decentralized/Algorithm_test_toyexample_offline_decentralized/main.py new file mode 100644 index 0000000000000000000000000000000000000000..8ac383f4edcaad078ae265e9a4a795e8d9f0810b --- /dev/null +++ b/Algorithms/Offline_Decentralized/Algorithm_test_toyexample_offline_decentralized/main.py @@ -0,0 +1,44 @@ +""" + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +""" + +""" +Main file that controls decision making for the Offline Decentralized Pick Up and Delivery problem. +This is a toy example! +Uses EnvironmentManager who assigns tasks in order to available agents +and then computes shortest paths, no check on collisions. +""" + +from mlagents_envs.environment import UnityEnvironment +import EnvChannel, TaskSideChannel +import EnvironmentManager + +# as long as simulation_going is true, new actions will be generated + +simulation_going = True + +# setup side channels and unity environment +envChannel = EnvChannel.EnvChannel() +taskChannel = TaskSideChannel.TaskSideChannel() +env = UnityEnvironment(file_name=None, side_channels=[envChannel, taskChannel]) + +# set up environment manager +envManager = EnvironmentManager.EnvironmentManager(envChannel.envData, env, envChannel, taskChannel) + + +while simulation_going: + envManager.step() + +envManager.close() diff --git a/Algorithms/Online_Centralized/Algorithm_test_toyexample_online_centralized/EnvChannel.py b/Algorithms/Online_Centralized/Algorithm_test_toyexample_online_centralized/EnvChannel.py new file mode 100644 index 0000000000000000000000000000000000000000..142cf2c27d8f9fa7d090c79496901190bb8bf2f3 --- /dev/null +++ b/Algorithms/Online_Centralized/Algorithm_test_toyexample_online_centralized/EnvChannel.py @@ -0,0 +1,46 @@ +import json +from mlagents_envs.side_channel.side_channel import ( + SideChannel, + IncomingMessage, + OutgoingMessage, +) +import uuid + +from EnvironmentData import EnvironmentData + +""" +class that processes information from SideChannel EnvChannel: stores all incoming information +in an instance of class EnvironmentData +""" + +class EnvChannel(SideChannel): + + def __init__(self) -> None: + super().__init__(uuid.UUID("621f0a70-4f87-11ea-a6bf-784f4387d1f7")) #must coincide with ChannelId set in c# + self.envData = EnvironmentData() # object that stores info on environment + + def on_message_received(self, msg: IncomingMessage) -> None: + # We simply read a string from the message and print it. + data = msg.read_string() + environment_info = json.loads(data) + + self.envData.matrix = environment_info["matrixLayout"] + self.envData.rotation = environment_info["rotationRobot"] + self.envData.size_of_action = environment_info["sizeOfAction"] + self.envData.size_of_observation = environment_info["sizeOfObservation"] + self.envData.number_of_robots = environment_info["numberOfRobotsInEnv"] + self.envData.number_of_current_tasks = environment_info["numberOfCurrentTasks"] + self.envData.can_go_backwards = environment_info["backwards"] + self.envData.random_tasks = environment_info["tasksGeneratedRandomly"] + self.envData.instance_ids = environment_info["instanceIDSRobots"] + + self.envData.set_initial_nodes_dictionary(environment_info["initialNodesOfRobots"]) + self.envData.set_tasks_to_be_assigned(environment_info["currentTasks"]) + self.envData.set_assigned_tasks() + + def send_string(self, data: str) -> None: + # Add the string to an OutgoingMessage + msg = OutgoingMessage() + msg.write_string(data) + # We call this method to queue the data we want to send + super().queue_message_to_send(msg) \ No newline at end of file diff --git a/Algorithms/Online_Centralized/Algorithm_test_toyexample_online_centralized/EnvironmentData.py b/Algorithms/Online_Centralized/Algorithm_test_toyexample_online_centralized/EnvironmentData.py new file mode 100644 index 0000000000000000000000000000000000000000..bac66852ffcfdfe8f738b1e24f91b339772fb042 --- /dev/null +++ b/Algorithms/Online_Centralized/Algorithm_test_toyexample_online_centralized/EnvironmentData.py @@ -0,0 +1,82 @@ +""" +stores data on environment +instance methods that initialize environment (used by EnvChannel) +- set_initial_nodes_dictionary(initial_nodes): initializes current_nodes_dictionary +containing current(next) nodes for each of the robots +- set_tasks_to_be_assigned(tasks): initialize tasks_to_be_assigned: tasks that have to be assigned +- set_assigned_tasks(): initialize assigned_tasks_dictionary containing + for every robot the current assigned task + +instance methods that update environment info +- assign_task(robot_instanceID, task): assign task to a given robot +- add_task_to_tasks_to_be_assigned(task): append a new task to tasks_to_be_assigned +- task_done(instance_id): remove task from robot that was assigned this task +""" + + +from Node import Node +from Task import Position, Task + + +class EnvironmentData: + + def __init__(self): + self.matrix = None + self.rotation = None + self.size_of_action = None + self.size_of_observation = None + self.number_of_robots = None + self.number_of_current_tasks = None + self.can_go_backwards = None + self.random_tasks = None # if set to true random tasks will be send whenever a task has been completed, + # otherwise all tasks self.tasks_to_be_assigned + + self.instance_ids = [] + self.current_nodes_dictionary = {} # dictionary instance_id -> current node + self.tasks_to_be_assigned = [] # tasks that are still to be assigned + self.assigned_tasks_dictionary = {} # dictionary instance_id -> assigned task + + + ######################################### + ## methods used by EnvChannel to initialize attributes: + ######################################### + + # given a correct string containing array of nodes + def set_initial_nodes_dictionary(self, initial_nodes): + for i in range(self.number_of_robots): + self.current_nodes_dictionary[self.instance_ids[i]] = Node(initial_nodes[i]["GridPosition"]["Row"], + initial_nodes[i]["GridPosition"]["Column"], + initial_nodes[i]["Degrees"]) + + # given a correct json_string containing array of tasks + def set_tasks_to_be_assigned(self, tasks): + for i in range(self.number_of_current_tasks): + pickup = Position(tasks[i]["PickUp"]["Row"], tasks[i]["PickUp"]["Column"]) + delivery = Position(tasks[i]["Delivery"]["Row"], tasks[i]["Delivery"]["Column"]) + self.tasks_to_be_assigned.append(Task(pickup, delivery)) + + # initialize dictionary robot instance_id -> task (None) + def set_assigned_tasks(self): + for i in range(self.number_of_robots): + self.assigned_tasks_dictionary[self.instance_ids[i]] = None + + ######################################### + ## methods used to update environment info + ######################################### + + # when a task is assigned to a robot, it has to be added to self.assigned_tasks + # and removed from self.tasks_to_be_assigned + def assign_task(self, robot_instanceID, task): + self.assigned_tasks_dictionary[robot_instanceID] = task + self.tasks_to_be_assigned.remove(task) + + # when a new task is available it is added to tasks_to_be_assigned + # a check is made whether there are still tasks that can be added, but this should not be happening (diagnostical) + def add_task_to_tasks_to_be_assigned(self, task): + if len(self.tasks_to_be_assigned) == self.number_of_current_tasks: + raise Exception("cannot add more tasks") + self.tasks_to_be_assigned.append(task) + + # when a robot has finished his task it has to be removed from assigned_tasks + def task_done(self, instance_id): + self.assigned_tasks_dictionary[instance_id] = None diff --git a/Algorithms/Online_Centralized/Algorithm_test_toyexample_online_centralized/EnvironmentManager.py b/Algorithms/Online_Centralized/Algorithm_test_toyexample_online_centralized/EnvironmentManager.py new file mode 100644 index 0000000000000000000000000000000000000000..dab5fa9450b32f7f6029c56449f7c3641ab1ea56 --- /dev/null +++ b/Algorithms/Online_Centralized/Algorithm_test_toyexample_online_centralized/EnvironmentManager.py @@ -0,0 +1,186 @@ +"""' +Class that contains and manages the information on the environment. +- Initializes and holds information on the environment (EnvData). +- Contains a reference to the sidechannel (EnvChannel). +- Contains a reference to the sidechannel (TaskChannel). +- Contains a reference to the unity environment (UnityEnv). +Has instance methods +- reset() which resets the environment. +- step() which assigns tasks, computes a new action based on observation from the unity environment + and sends actions back to unity, updates info environment when a task has finished +- close() which closes the environment/ + +Has also some auxilary instance methods: +- assign_new_task() which finds a new task and a robot that is free, then calls +assign_task_to_robot(robot_instanceID, task) +- compute_path(current_node, task) which computes paths starting in current_node completing a certain task +- initialize_shortest_paths() which initializes a dictionary containing the paths robots are following +- assign_task_to_robot(robot_instanceID, task) which assigns task to a robot with given instance ID, +updates EnvData and sends information on assignment back to Unity + +Note that this a toy example. No checks are done on collisions. +""" + + +import json + +from mlagents_envs.base_env import ActionTuple + +from Graph import Graph +from Node import Node + +import numpy as np + + +class EnvironmentManager: + + def __init__(self, envData, unityEnv, envChannel, taskChannel): + self.envData = envData + self.unityEnv = unityEnv + self.envChannel = envChannel + self.taskChannel = taskChannel + + # IMPORTANT: sends info through envChannel, to be called before setting up connection envData an taskChannel + self.reset() + + # taskChannel needs info on envData + self.taskChannel.environment_data = envData + + # behavior name for agent + self.behavior_name = list(unityEnv.behavior_specs.keys())[0] + + # graph that is used for computing paths + self.graph = Graph(envData.matrix, envData.rotation, envData.can_go_backwards) + + # for every robot with instanceID id shortest_paths[id] gives the shortest path to + # its currently assigned task + self.shortest_paths = {} + + self.initialize_shortest_paths() + + # step in the environment + # 1) checks if new tasks can be assigned + # 2) collect observations + # 3) compute new actions + # 4) send actions back to Unity + def step(self): + self.assign_new_task() + + # get information from the agent that requests an action + decision_steps, terminal_steps = self.unityEnv.get_steps(self.behavior_name) + + # decision_steps.obs is a list of numpy arrays, first dimension corresponds to the number of agents that has requested + # a decision (here 1), the observation of the agent is the first element + observation = decision_steps.obs[0][0] + + print("----------------------------------------") + + + actions = [] # long list of all actions + action_tuple = ActionTuple() # actions to send to unity + + # get observations per robot and store in dictionary observations[instance_id] -> observation + observations = {} + for i in range(self.envData.number_of_robots): + observation_i = observation[i * self.envData.size_of_observation: + i * self.envData.size_of_observation + self.envData.size_of_observation] + observations[observation_i[0]] = observation_i[1:] + + # create an action for all robots and send at once to unity + for robot_id_unity in observations: + + obs = observations[robot_id_unity] + print("robot " + str(robot_id_unity) + " at node [(" + str(obs[0]) + "," + str(obs[1]) + ")," + str( + obs[2]) + "]") + + path = self.shortest_paths[robot_id_unity] + # if path is empty, then robot should stay at same node + if len(path) == 0: + actions.extend([robot_id_unity, obs[0], obs[1], obs[2], 0, 0]) + # if path is not empty we get next action from shortest path + else: + next_action = path[0] # is node or "pickup" or "deliver" + if next_action == "pickup": + actions.extend([robot_id_unity, obs[0], obs[1], obs[2], 1, 0]) + elif next_action == "deliver": + actions.extend([robot_id_unity, obs[0], obs[1], obs[2], 0, 1]) + self.envData.assigned_tasks_dictionary[robot_id_unity] = None + else: + actions.extend([robot_id_unity, next_action.x, next_action.y, next_action.g, 0, 0]) + # update current node + self.envData.current_nodes_dictionary[robot_id_unity] = Node(next_action.x, next_action.y, + next_action.g) + # update path + self.shortest_paths[robot_id_unity] = path[1:] + + # add action to action_tuple and set the actions + actions = np.array(actions) + actions.resize(1, self.envData.size_of_action * self.envData.number_of_robots) + action_tuple.add_discrete(actions) + + self.unityEnv.set_actions(self.behavior_name, action_tuple) + self.unityEnv.step() # send actions to unity and wait until a new decision is requested + + + + + # reset the environment + def reset(self): + self.unityEnv.reset() + + # close the environment + def close(self): + self.close() + + # assigns the next available task to an idle robot, if possible + def assign_new_task(self): + # check if there are tasks that have to be assigned + # if this is the case, get first task and assign to available robot + if len(self.envData.tasks_to_be_assigned) != 0: + task = self.envData.tasks_to_be_assigned[0] + # get available robot + for robot_id in self.envData.instance_ids: + if self.envData.assigned_tasks_dictionary[robot_id] is None: + # robot is free: assign task to robot and break out of for loop + self.assign_task_to_robot(robot_id, task) + break + + + # compute path from current_node that finishes given task + # for test purposes pick up and delivery need to have rotation 0 + # at pick up delivery robot stays at same node + # returns a sequence of nodes and pick up/delivery actions + def compute_path(self, current_node, task): + path1 = self.graph.computeShortestPath(current_node, + Node(task.PickUp.Row, task.PickUp.Column, 0)) + path1 = path1[1:] + path2 = self.graph.computeShortestPath(Node(task.PickUp.Row, task.PickUp.Column, 0), + Node(task.Delivery.Row, task.Delivery.Column, 0)) + path2 = path2[1:] + + return path1 + ["pickup"] + path2 + ["deliver"] + + + # for every robot initially there is an empty path to be followed + def initialize_shortest_paths(self): + for robot_id in self.envData.instance_ids: + self.shortest_paths[robot_id] = [] + + def assign_task_to_robot(self, robot_instanceID, task): + # update envData + self.envData.assign_task(robot_instanceID, task) + # compute path for robot + self.shortest_paths[robot_instanceID] = \ + self.compute_path(self.envData.current_nodes_dictionary[robot_instanceID],task) + # send info to unity + taskDict = {"Task": { + "PickUp": {"Row": task.PickUp.Row, "Column": task.PickUp.Column}, + "Delivery": {"Row": task.Delivery.Row, "Column": task.Delivery.Column}}, + "InstanceID": robot_instanceID} + self.taskChannel.send_string(json.dumps(taskDict)) + + + + + + diff --git a/Algorithms/Online_Centralized/Algorithm_test_toyexample_online_centralized/Graph.py b/Algorithms/Online_Centralized/Algorithm_test_toyexample_online_centralized/Graph.py new file mode 100644 index 0000000000000000000000000000000000000000..c877def1fe99a2f5d82697167084c1a40dd0a30e --- /dev/null +++ b/Algorithms/Online_Centralized/Algorithm_test_toyexample_online_centralized/Graph.py @@ -0,0 +1,110 @@ +from networkx import DiGraph, shortest_path +from Node import Node + +""" +Class Graph creates a graph based on matrix, deviation (unit of rotation) and whether robots can move backwards). +Its nodes contain position in the grid and orientation wrt north (see class <c>Node</c>). +Networkx package as underlying data structure. +""" + +class Graph: + def __init__(self, matrix, deviation, cangobackwards): + self.matrix = matrix + self.number_of_rows = len(matrix) + self.number_of_columns = len(matrix[0]) + self.deviation = deviation + self.cangobackwards = cangobackwards + self.graph = DiGraph() + + for i in range(self.number_of_rows): + for j in range(self.number_of_columns): + # we have to add nodes to the graph when we encounter a number different than 1 + if matrix[i][j] != 1: + self.addEdgesByRotation(i, j) + self.addEdgesByMovingForward(i,j) + + def addEdgesByRotation(self, row, column): + degree = 0 + while degree < 360: + newnode = Node(row, column, degree) + + # add all edges from newnode staying at the same position (row, number), i.e. rotation + + # rotate left + rotateLeftNode = Node(row, column, get_degree_in_range_0_360(degree - self.deviation)) + self.graph.add_edge(newnode, rotateLeftNode) + + # rotate right + rotateRightNode = Node(row, column, get_degree_in_range_0_360(degree + self.deviation)) + self.graph.add_edge(newnode, rotateRightNode) + + degree += self.deviation + + def addEdgesByMovingForward(self, row, column): + # check left + if column > 0 and self.matrix[row][column-1] != 1: + # we can move forward if we have degree 270 + currentnode = Node(row, column, 270) + neighbourleft = Node(row, column-1, 270) + self.graph.add_edge(currentnode, neighbourleft) + # we can move backward if we have degree 90 + if self.cangobackwards: + currentnode = Node(row, column, 90) + neighbourleft = Node(row, column-1, 90) + self.graph.add_edge(currentnode, neighbourleft) + + # check right + if column < self.number_of_columns -1 and self.matrix[row][column+1] != 1: + # we can move forward if we have degree 90 + currentnode = Node(row, column, 90) + neighbourright = Node(row, column+1, 90) + self.graph.add_edge(currentnode, neighbourright) + # we can move backward if we have degree 270 + if self.cangobackwards: + currentnode = Node(row, column, 270) + neighbourright = Node(row, column+1, 270) + self.graph.add_edge(currentnode, neighbourright) + + # check up + if row > 0 and self.matrix[row-1][column] != 1: + # we can move forward if we have degree 0 + currentnode = Node(row, column, 0) + neighbourup = Node(row-1, column, 0) + self.graph.add_edge(currentnode, neighbourup) + # we can move backward if we have degree 180 + if self.cangobackwards: + currentnode = Node(row, column, 180) + neighbourup = Node(row-1, column, 180) + self.graph.add_edge(currentnode, neighbourup) + + # check down + if row < self.number_of_rows-1 and self.matrix[row+1][column] != 1: + # we can move forward if we have degree 180 + currentnode = Node(row, column, 180) + neighbourdown = Node(row+1, column, 180) + self.graph.add_edge(currentnode, neighbourdown) + # we can move backward if we have degree 0 + if self.cangobackwards: + currentnode = Node(row, column, 0) + neighbourdown = Node(row+1, column, 0) + self.graph.add_edge(currentnode, neighbourdown) + + def computeShortestPath(self, start_node, end_node): + #compute shortest path from start_node to end_node: return a list + return shortest_path(self.graph, start_node, end_node) + +def get_degree_in_range_0_360(degree): + rest = degree % 360 + if rest < 0: + return rest + 360 + return rest + + + + + + + + + + diff --git a/Algorithms/Online_Centralized/Algorithm_test_toyexample_online_centralized/Node.py b/Algorithms/Online_Centralized/Algorithm_test_toyexample_online_centralized/Node.py new file mode 100644 index 0000000000000000000000000000000000000000..e7dc823be7e503837647d38290413521b04c1512 --- /dev/null +++ b/Algorithms/Online_Centralized/Algorithm_test_toyexample_online_centralized/Node.py @@ -0,0 +1,41 @@ +""" +Class Node represent nodes in the graph. Every node contains a +position (x,y) in the grid +and a rotation in degree where +0 = North +90 = East +280 = South +270 = West +all degrees must be between 0 and 360 + +attributes are set to private such that they cannot be overwritten and there is no problem with the hash +""" + +class Node: + def __init__(self,x,y,g): + self._x = x + self._y = y + self._g = g + + @property + def x(self): + return self._x + + @property + def y(self): + return self._y + + @property + def g(self): + return self._g + + + def __eq__(self, other): + return self.__class__ == other.__class__ and self.x == other.x and self.y == other.y and self.g == other.g + + + def __hash__(self): + return (((self.x * 397) ** self.y) * 397) **self.g + + def __str__(self): + return "[(" + str(self.x) + ", " + str(self.y) + ")" + "," + str(self.g) + "]" diff --git a/Algorithms/Online_Centralized/Algorithm_test_toyexample_online_centralized/Pipfile b/Algorithms/Online_Centralized/Algorithm_test_toyexample_online_centralized/Pipfile new file mode 100644 index 0000000000000000000000000000000000000000..2cf8108a7836978e89ef3320e61b72d3c4eb3be6 --- /dev/null +++ b/Algorithms/Online_Centralized/Algorithm_test_toyexample_online_centralized/Pipfile @@ -0,0 +1,14 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +networkx = "==2.5" +mlagents = "==0.23.0" +mlagents-envs = "==0.23.0" + +[dev-packages] + +[requires] +python_version = "3.6" diff --git a/Algorithms/Online_Centralized/Algorithm_test_toyexample_online_centralized/Task.py b/Algorithms/Online_Centralized/Algorithm_test_toyexample_online_centralized/Task.py new file mode 100644 index 0000000000000000000000000000000000000000..286d0d8254452110b0f491296120de590b9a642c --- /dev/null +++ b/Algorithms/Online_Centralized/Algorithm_test_toyexample_online_centralized/Task.py @@ -0,0 +1,31 @@ +""" +Class Task represents tasks which consist of 2 positions: a pickup and a delivery position. +""" +class Task: + def __init__(self, pos1, pos2): + self.PickUp = pos1 + self.Delivery = pos2 + + def __eq__(self, other): + return self.__class__ == other.__class__ and self.PickUp == other.PickUp and self.Delivery == other.Delivery + + def __hash__(self): + return ((hash(self.PickUp) * 397) ** hash(self.Delivery)) * 397 + + def __str__(self): + return "[" + str(self.PickUp) + ", " + str(self.Delivery) + "]" + + +class Position: + def __init__(self, x, y): + self.Row = x + self.Column = y + + def __eq__(self, other): + return self.__class__ == other.__class__ and self.Row == other.Row and self.Column == other.Column + + def __hash__(self): + return ((self.Row * 397) ** self.Column) * 397 + + def __str__(self): + return "(" + str(self.Row) + ", " + str(self.Column) + ")" diff --git a/Algorithms/Online_Centralized/Algorithm_test_toyexample_online_centralized/TaskSideChannel.py b/Algorithms/Online_Centralized/Algorithm_test_toyexample_online_centralized/TaskSideChannel.py new file mode 100644 index 0000000000000000000000000000000000000000..a541d459d56aec589f8e20b09cd7f5485b92dcd4 --- /dev/null +++ b/Algorithms/Online_Centralized/Algorithm_test_toyexample_online_centralized/TaskSideChannel.py @@ -0,0 +1,41 @@ +import json +from mlagents_envs.side_channel.side_channel import ( + SideChannel, + IncomingMessage, + OutgoingMessage, +) +import uuid + +from Task import Task, Position + +""" +Class that processes info from the TaskSideChannel. +- receives new tasks that have to assigned to robots +- sends assignment of tasks to robots +""" + + +class TaskSideChannel(SideChannel): + + def __init__(self) -> None: + super().__init__(uuid.UUID("c11ab982-82b8-4194-b387-3bd0fe9ebdc7")) #must coincide with ChannelId set in c# + self.environment_data = None #info on the environment + + # channel receives new tasks that have to be assigned + def on_message_received(self, msg: IncomingMessage) -> None: + data = msg.read_string() + new_task = json.loads(data) + new_task = new_task["task"] + task_to_add = Task(Position(new_task["PickUp"]["Row"], new_task["PickUp"]["Column"]), + Position(new_task["Delivery"]["Row"], new_task["Delivery"]["Column"])) + # add task to tasks to be assigned + self.environment_data.add_task_to_tasks_to_be_assigned(task_to_add) + + # channel sends information when a task has been assigned (to which robot) + def send_string(self, data: str) -> None: + + # Add the string to an OutgoingMessage + msg = OutgoingMessage() + msg.write_string(data) + # We call this method to queue the data we want to send + super().queue_message_to_send(msg) \ No newline at end of file diff --git a/Algorithms/Online_Centralized/Algorithm_test_toyexample_online_centralized/main.py b/Algorithms/Online_Centralized/Algorithm_test_toyexample_online_centralized/main.py new file mode 100644 index 0000000000000000000000000000000000000000..3768c19ce07c27f85c2ab1aad60ff2c707e0dfce --- /dev/null +++ b/Algorithms/Online_Centralized/Algorithm_test_toyexample_online_centralized/main.py @@ -0,0 +1,28 @@ +""" +Main file that controls and decision making +This is a toy example! +Uses EnvironmentManager who assigns tasks in order to available agents +and then computes shortest paths, no check on collisions. +""" + +from mlagents_envs.environment import UnityEnvironment +import EnvChannel, TaskSideChannel +import EnvironmentManager + +# as long as simulation_going is true, new actions will be generated + +simulation_going = True + +# setup side channels and unity environment +envChannel = EnvChannel.EnvChannel() +taskChannel = TaskSideChannel.TaskSideChannel() +env = UnityEnvironment(file_name=None, side_channels=[envChannel, taskChannel]) + +# set up environment manager +envManager = EnvironmentManager.EnvironmentManager(envChannel.envData, env, envChannel, taskChannel) + + +while simulation_going: + envManager.step() + +envManager.close() diff --git a/Algorithms/Online_Decentralized/Algorithm_Token_Passing/EnvChannel.py b/Algorithms/Online_Decentralized/Algorithm_Token_Passing/EnvChannel.py new file mode 100644 index 0000000000000000000000000000000000000000..89909eccb160d3bebb15087e72541ddbdd4ce2fd --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_Token_Passing/EnvChannel.py @@ -0,0 +1,45 @@ +import json +from mlagents_envs.side_channel.side_channel import ( + SideChannel, + IncomingMessage, + OutgoingMessage, +) +import uuid + +from EnvironmentData import EnvironmentData + +""" +class that processes information from SideChannel EnvChannel +""" + +class EnvChannel(SideChannel): + + def __init__(self) -> None: + super().__init__(uuid.UUID("621f0a70-4f87-11ea-a6bf-784f4387d1f7")) #must coincide with ChannelId set in c# + self.EnvData = EnvironmentData() # object that stores info on environment + + def on_message_received(self, msg: IncomingMessage) -> None: + # We simply read a string from the message and print it. + data = msg.read_string() + environment_info = json.loads(data) + + self.EnvData.matrix = environment_info["matrixLayout"] + self.EnvData.rotation = environment_info["rotationRobot"] + self.EnvData.action_size = environment_info["sizeOfAction"] + self.EnvData.observation_size = environment_info["sizeOfObservation"] + self.EnvData.number_of_robots = environment_info["numberOfRobotsInEnv"] + self.EnvData.number_of_current_tasks = environment_info["numberOfCurrentTasks"] + self.EnvData.can_go_backwards = environment_info["backwards"] + self.EnvData.random_tasks = environment_info["tasksGeneratedRandomly"] + self.EnvData.instance_ids = environment_info["instanceIDSRobots"] + + self.EnvData.set_initial_nodes_dictionary(environment_info["initialNodesOfRobots"]) + self.EnvData.set_tasks_to_be_assigned(environment_info["currentTasks"]) + self.EnvData.set_assigned_tasks() + + def send_string(self, data: str) -> None: + # Add the string to an OutgoingMessage + msg = OutgoingMessage() + msg.write_string(data) + # We call this method to queue the data we want to send + super().queue_message_to_send(msg) \ No newline at end of file diff --git a/Algorithms/Online_Decentralized/Algorithm_Token_Passing/EnvironmentData.py b/Algorithms/Online_Decentralized/Algorithm_Token_Passing/EnvironmentData.py new file mode 100644 index 0000000000000000000000000000000000000000..82b6b1b7ee71726bd23a94aedbfea83657c7e988 --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_Token_Passing/EnvironmentData.py @@ -0,0 +1,91 @@ +# stores data on environment +# initialized when initial data is being sent through EnvChannel +import json + +from Node import Node +from ta_state import Location +import tp_task + + +class EnvironmentData: + + def __init__(self): + self.matrix = None + self.rotation = None + self.action_size = None + self.observation_size = None + self.number_of_robots = None + self.number_of_current_tasks = None + self.can_go_backwards = None + self.random_tasks = None # if set to true random tasks will be send whenever a task has been completed, + # otherwise all tasks self.tasks_to_be_assigned + + self.instance_ids = [] + self.current_nodes_dictionary = {} # dictionary instance_id -> current node + self.tasks_to_be_assigned = [] # tasks that are still to be assigned + self.assigned_tasks_dictionary = {} # dictionary instance_id -> assigned task + + self.task_side_channel = None + + self.tasksCreated = 0 + + ######################################### + ## methods used by EnvChannel to initialize attributes: + ######################################### + + # set_initial_nodes_dictionary + # set_tasks_to_be_assigned + # set_assigned_tasks + + # given a correct string containing array of nodes + def set_initial_nodes_dictionary(self, initial_nodes): + for i in range(self.number_of_robots): + self.current_nodes_dictionary[self.instance_ids[i]] = Node(initial_nodes[i]["GridPosition"]["Row"], + initial_nodes[i]["GridPosition"]["Column"], + initial_nodes[i]["Degrees"]) + + # given a correct json_string containing array of tasks + def set_tasks_to_be_assigned(self, tasks): + + for i in range(self.number_of_current_tasks): + pickup = Location(tasks[i]["PickUp"]["Column"], tasks[i]["PickUp"]["Row"], 0) + delivery = Location(tasks[i]["Delivery"]["Column"], tasks[i]["Delivery"]["Row"], 0) + releaseTime = tasks[i]["ReleaseTime"] + task = tp_task.Task(tp_task.CURRENT_TASK_ID, pickup, delivery, releaseTime=releaseTime) + self.tasks_to_be_assigned.append(task) + + tp_task.CURRENT_TASK_ID += 1 + + # initialize dictionary robot instance_id -> task (None) + def set_assigned_tasks(self): + for i in range(self.number_of_robots): + self.assigned_tasks_dictionary[self.instance_ids[i]] = None + + ######################################### + ## methods used to update environment info + ######################################### + + # when a task is assigned to a robot, it has to be added to self.assigned_tasks + # and removed from self.tasks_to_be_assigned + # info has to be sent to unity via the correct channel + def assign_task(self, robot_instanceID, task): + self.assigned_tasks_dictionary[robot_instanceID] = task + # self.tasks_to_be_assigned.remove(task) + taskDict = {"Task": { + "PickUp": {"Column": str(task.pickup.col), "Row": str(task.pickup.row)}, + "Delivery": {"Column": str(task.delivery.col), "Row": str(task.delivery.row)}, + "ReleaseTime": str(task.releaseTime)}, + "InstanceID": str(robot_instanceID)} + + self.task_side_channel.send_string(json.dumps(taskDict)) + + # when a new task is available it is added to tasks_to_be_assigned + # a check is made whether there are still tasks that can be added, but this should not be happening (diagnostical) + def add_task_to_tasks_to_be_assigned(self, task): + if len(self.tasks_to_be_assigned) == self.number_of_current_tasks: + raise Exception("cannot add more tasks") + self.tasks_to_be_assigned.append(task) + + # when a robot has finished his task it has to be removed from assigned_tasks + def task_done(self, instance_id): + self.assigned_tasks_dictionary[instance_id] = None diff --git a/Algorithms/Online_Decentralized/Algorithm_Token_Passing/Node.py b/Algorithms/Online_Decentralized/Algorithm_Token_Passing/Node.py new file mode 100644 index 0000000000000000000000000000000000000000..a2bb07c8fdf941ab68a8e8c87e8478b6d2e79aba --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_Token_Passing/Node.py @@ -0,0 +1,39 @@ +# Class Node represent nodes in the graph. Every node contains a +# position (x,y) in the grid +# and a rotation in degree where +# 0 = North +# 90 = East +# 280 = South +# 270 = West +# all degrees must be between 0 and 360 + +# attributes are set to private such that they cannot be overwritten and there is no problem with the hash + +class Node: + def __init__(self,x,y,g): + self._x = x + self._y = y + self._g = g + + @property + def x(self): + return self._x + + @property + def y(self): + return self._y + + @property + def g(self): + return self._g + + + def __eq__(self, other): + return self.__class__ == other.__class__ and self.x == other.x and self.y == other.y and self.g == other.g + + + def __hash__(self): + return (((self.x * 397) ** self.y) * 397) **self.g + + def __str__(self): + return "[(" + str(self.x) + ", " + str(self.y) + ")" + "," + str(self.g) + "]" diff --git a/Algorithms/Online_Decentralized/Algorithm_Token_Passing/Pipfile b/Algorithms/Online_Decentralized/Algorithm_Token_Passing/Pipfile new file mode 100644 index 0000000000000000000000000000000000000000..2cf8108a7836978e89ef3320e61b72d3c4eb3be6 --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_Token_Passing/Pipfile @@ -0,0 +1,14 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +networkx = "==2.5" +mlagents = "==0.23.0" +mlagents-envs = "==0.23.0" + +[dev-packages] + +[requires] +python_version = "3.6" diff --git a/Algorithms/Online_Decentralized/Algorithm_Token_Passing/Readme.md b/Algorithms/Online_Decentralized/Algorithm_Token_Passing/Readme.md new file mode 100644 index 0000000000000000000000000000000000000000..3c6b638256050c47eaa46819580e4985de7064d6 --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_Token_Passing/Readme.md @@ -0,0 +1,52 @@ +# Token Passing (TP) + +The Token-Passing (TP) algorithm is a decentralized algorithm for the online variant of the MAPD problem. + +In the online variant of the MAPD problem the following is supported: +- Using randomly generated tasks (randomtasks = True) +- Using tasks from a taskslist (bv. ../config/tasks.txt) + -> When using a taskslist with releaseTimes: releaseTimes are ignored (only used in offline variant) +- Tested from 1 agent up untill 50 agents (significant lag for larger amount of agents) + +## Running the algorithm + +1. Install the virtual environment + - pipenv install +2. Run the "decentralized_decisionmaker_shortest_path.py" file + - pipenv run python decentralized_decisionmaker_shortest_path.py +3. Start the game inside the Unity editor + +## Working of the algorithm + +This implementation is based on the "Lifelong Multi-Agent Path Finding for Online Pickup and Delivery Tasks" paper (https://arxiv.org/pdf/1705.10868.pdf). +An explanation of the algorithm is available at: + - Section 4.1 of the "Lifelong Multi-Agent Path Finding for Online Pickup and Delivery Tasks" paper + - Section 2.2.1 of the paper provided in the "paper" directory + +General overview of working: + - Token contains: + * Paths of all agents + * Taskset + * Assignments of tasks of all agents + - In each timestep each agent moves one step following its path in the token + - When an agent reaches the end of its path (= free agent) it looks for a task: + - Task found: + * Plan path to execute task and update token + * Remove the selected task from the task set + - No task found: + * Plan path to safe location and update token + +## Overview of the provided files + +Main file: +- decentralized_decisionmaker_shortest_path.py: Main file that runs the algorithm + +Token Passing: +- tp_agent.py: Agent that are executing tasks +- tp_system: System manages the agents and tasks +- tp_task: Pickup and delivery tasks +- tp_token: Token that is used for communicating global information between the agents + +A-star: +- ta_astar.py: A-Star algorithm +- ta_state.py: Contains Location and state classes used for the path planning \ No newline at end of file diff --git a/Algorithms/Online_Decentralized/Algorithm_Token_Passing/TaskSideChannel.py b/Algorithms/Online_Decentralized/Algorithm_Token_Passing/TaskSideChannel.py new file mode 100644 index 0000000000000000000000000000000000000000..4f03f1fbc3e78a07d30314469a72777623e13e7f --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_Token_Passing/TaskSideChannel.py @@ -0,0 +1,39 @@ +import json +from mlagents_envs.side_channel.side_channel import ( + SideChannel, + IncomingMessage, + OutgoingMessage, +) +import uuid + +import tp_task +from ta_state import Location + + +class TaskSideChannel(SideChannel): + + def __init__(self) -> None: + super().__init__(uuid.UUID("c11ab982-82b8-4194-b387-3bd0fe9ebdc7")) #must coincide with ChannelId set in c# + self.environment_data = None #info on the environment + + # channel receives new tasks that have to be assigned + def on_message_received(self, msg: IncomingMessage) -> None: + data = msg.read_string() + new_task = json.loads(data) + new_task = new_task["task"] + task_to_add = tp_task.Task(tp_task.CURRENT_TASK_ID, + Location(new_task["PickUp"]["Column"], new_task["PickUp"]["Row"], 0), + Location(new_task["Delivery"]["Column"], new_task["Delivery"]["Row"], 0), + new_task["ReleaseTime"]) + tp_task.CURRENT_TASK_ID += 1 + # add task to task to be assigned + self.environment_data.add_task_to_tasks_to_be_assigned(task_to_add) + + # channel sends information when a task has been assigned (to which robot) + def send_string(self, data: str) -> None: + + # Add the string to an OutgoingMessage + msg = OutgoingMessage() + msg.write_string(data) + # We call this method to queue the data we want to send + super().queue_message_to_send(msg) diff --git a/Algorithms/Online_Decentralized/Algorithm_Token_Passing/decentralized_decisionmaker_shortest_path.py b/Algorithms/Online_Decentralized/Algorithm_Token_Passing/decentralized_decisionmaker_shortest_path.py new file mode 100644 index 0000000000000000000000000000000000000000..dc5f1b5513a0f597bd3a231eb5629d0944afe9df --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_Token_Passing/decentralized_decisionmaker_shortest_path.py @@ -0,0 +1,163 @@ +##------------------## +## Python libraries ## +##------------------## + +import sys +import numpy as np + +##-----------## +## ML-agents ## +##-----------## + +from mlagents_envs.environment import ActionTuple, UnityEnvironment +import EnvChannel +import TaskSideChannel +from Node import Node + +##----## +## TP ## +##----## + +from tp_system import System as TP_System +from ta_state import Location +from tp_task import Task + + + +simulation_going = True + +# Load the side channels and Unity environment. +envChannel = EnvChannel.EnvChannel() +taskChannel = TaskSideChannel.TaskSideChannel() +env = UnityEnvironment(file_name=None, side_channels=[envChannel, taskChannel]) # Open unity and press play to execute +env.reset() # reset the environment and get info about environment through envChannel + +# Specify the used behaviour name for steering the agent +behavior_names = list(env.behavior_specs.keys()) +behavior_name = behavior_names[0] + +# info obtained from environment +environment_info = envChannel.EnvData +# set up links between task side channel and environment info +environment_info.task_side_channel = taskChannel +taskChannel.environment_data = environment_info + +# Retrieve information from environment +matrix = environment_info.matrix +number_of_robots = environment_info.number_of_robots +rotation = environment_info.rotation +observation_size = environment_info.observation_size +action_size = environment_info.action_size +robot_can_go_backwards = environment_info.can_go_backwards + +# Initialize system +system = TP_System(matrix, rotation) + +# Callback called when an agent assigns itself a task +def on_task_assigned(agent_id, task_id): + environment_info.assign_task(agent_id, system.get_task(task_id)) + +##----------------## +## Robot Creation ## +##----------------## + +# Number of agents in the configuration file +n_agents = len(environment_info.instance_ids) + +# Create all the agents +for robot_id, start_node in environment_info.current_nodes_dictionary.items(): + # Convert the Node that represents the agent's location to a Location + robot_position = Location(start_node.y, start_node.x, start_node.g) + # Create agent + system.add_agent(robot_id, robot_position, on_task_assigned) + +# Each agent requests 1 action in each timestep +# next timestep starts when all agents have requested an action in this timestep +actions_requested_in_timestep = 0 +# Keep track of current timestep +timestep = 0 + +while simulation_going: + # If there are new tasks that need to be assigned add them to the task set + if len(environment_info.tasks_to_be_assigned) != 0: + for task in environment_info.tasks_to_be_assigned: + # Add task to task set + system.add_task(task) + # Task is already in task set, remove it from this list to avoid duplicates in task set + environment_info.tasks_to_be_assigned.remove(task) + + # Get information on the agents that request an action + decision_steps, terminal_steps = env.get_steps(behavior_name) + agents = decision_steps.agent_id + observations = decision_steps.obs + + # Actions that will be sent back to Unity + actions = [] + action_tuple = ActionTuple() # actions to send to unity + + # Create an action for all agents that request an action + for i in range(len(agents)): + + ##--------------## + ## OBSERVATIONS ## + ##--------------## + + # Keep track of how many agents have requested an action in this timestep + actions_requested_in_timestep += 1 + + # Collect agent's observations + observation = observations[0][i] + # Extract observations + robot_id_unity = observation[0] # robot id in unity used to get correct precomputed path + robot_pos_x = observation[2] + robot_pos_y = observation[1] + robot_rot = observation[3] + # Convert coordinates to the agent's current position + robot_position = Location(robot_pos_x, robot_pos_y, robot_rot) + + # Get Python Agent that represents robot + robot = system.get_agent(int(robot_id_unity)) + + ##-------------## + ## FOLLOW PATH ## + ##-------------## + + # Follow previously computed path or plan new path when at the end of path + next_position = robot.move(system.token, timestep) + # Convert Location to Node + next_action = Node(next_position.row, next_position.col, next_position.rotation) + # Check if a task needs to be picked up / delivered + pickup_action = 0 + delivery_action = 0 + if next_position.to_pickup: + # Agent has to pick up his task + pickup_action = 1 + elif next_position.to_deliver: + # Agent has to deliver his task + delivery_action = 1 + # Agent has no task assigned anymore as the task is delivered + system.token.assignments[robot_id_unity] = None + + # Send action to agent in Unity + actions.extend([next_action.x, next_action.y, next_action.g, pickup_action, delivery_action]) + + # When all agents have moved in this timestep update the timestep + if (actions_requested_in_timestep == n_agents): + # Update the timestep + timestep += 1 + # Reset the number of agents that have requested a timestep in this timestep + actions_requested_in_timestep = 0 + + # Send actions to Unity + actions = np.array(actions) + actions.resize(len(agents), action_size) + action_tuple.add_discrete(actions) + + env.set_actions(behavior_name, action_tuple) + env.step() + + + + + + diff --git a/Algorithms/Online_Decentralized/Algorithm_Token_Passing/paper/Bachelorthesis.pdf b/Algorithms/Online_Decentralized/Algorithm_Token_Passing/paper/Bachelorthesis.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e9bf4fce9fccb3903a7f502782e4292f8c59e23d Binary files /dev/null and b/Algorithms/Online_Decentralized/Algorithm_Token_Passing/paper/Bachelorthesis.pdf differ diff --git a/Algorithms/Online_Decentralized/Algorithm_Token_Passing/ta_astar.py b/Algorithms/Online_Decentralized/Algorithm_Token_Passing/ta_astar.py new file mode 100644 index 0000000000000000000000000000000000000000..975ff6a58ab1b48d69e3704354ce14919b0c315e --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_Token_Passing/ta_astar.py @@ -0,0 +1,164 @@ +""" +Created on Wed Apr 22 07:43:03 2020 + +@author: Pieter Cawood + +""" +from heapq import * +from ta_state import * + +def get_heuristic(start_location, goal_location, rotation): + # Admissible heuristic - manhattan distance + return abs(start_location.col - goal_location.col) + abs(start_location.row - goal_location.row) + +class AStar: + def __init__(self, world, rotation): + self.rotation = rotation + self.world = world + self.dim_x = len(world[0]) + self.dim_y = len(world) + self.obstacles = {} + self.path_ends = dict() + self.other_agent_paths = [] + + def state_possible(self, current_state, new_state): + # Check if wall + not_obstacle = False + if new_state.location not in self.obstacles: + not_obstacle = True + # Check if location is in dimensions of grid and does not collide with another location/wall + return 0 <= new_state.location.col < self.dim_x and 0 <= new_state.location.row < self.dim_y \ + and not_obstacle and not self.is_collision(current_state, new_state) + + def is_collision(self, current_state, new_state): + for other_agent_path in self.other_agent_paths: + # Vertex collision + if new_state.time in other_agent_path: + if other_agent_path[new_state.time].row == new_state.location.row and other_agent_path[new_state.time].col == new_state.location.col: + return True + # Edge collision + if new_state.time in other_agent_path and current_state.time in other_agent_path: + if other_agent_path[new_state.time].row == current_state.location.row and \ + other_agent_path[new_state.time].col == current_state.location.col and \ + other_agent_path[current_state.time].row == new_state.location.row and \ + other_agent_path[current_state.time].col == new_state.location.col: + return True + # Last position of agent is his parking location + if new_state.location in self.path_ends: + busy_time = self.path_ends[new_state.location] + if new_state.time >= busy_time: + return True + return False + + def get_neighbours(self, current_state): + neighbours = [] + neighbour_time_step = current_state.time + 1 + # Wait in state + new_state = State(neighbour_time_step, Location(current_state.location.col, current_state.location.row, current_state.location.rotation)) + if self.state_possible(current_state, new_state): + neighbours.append(new_state) + # Add rotation + new_state = State(neighbour_time_step, Location(current_state.location.col, current_state.location.row, (current_state.location.rotation+self.rotation) % 360)) + if self.state_possible(current_state, new_state): + neighbours.append(new_state) + # Remove rotation + new_state = State(neighbour_time_step, Location(current_state.location.col, current_state.location.row, (current_state.location.rotation-self.rotation) % 360)) + if self.state_possible(current_state, new_state): + neighbours.append(new_state) + if current_state.location.rotation == 0: + # Move down + new_state = State(neighbour_time_step, Location(current_state.location.col, current_state.location.row - 1, current_state.location.rotation)) + if self.state_possible(current_state, new_state): + neighbours.append(new_state) + elif current_state.location.rotation == 90: + # Move right + new_state = State(neighbour_time_step, Location(current_state.location.col + 1, current_state.location.row, current_state.location.rotation)) + if self.state_possible(current_state, new_state): + neighbours.append(new_state) + elif current_state.location.rotation == 180: + # Move up + new_state = State(neighbour_time_step, Location(current_state.location.col, current_state.location.row + 1, current_state.location.rotation)) + if self.state_possible(current_state, new_state): + neighbours.append(new_state) + elif current_state.location.rotation == 270: + # Move left + new_state = State(neighbour_time_step, Location(current_state.location.col - 1, current_state.location.row, current_state.location.rotation)) + if self.state_possible(current_state, new_state): + neighbours.append(new_state) + return neighbours + + def create_obstacles(self, other_agent_paths): + n_rotations = int(360/self.rotation) + # Keep track of all walls in the environment + for y in range(self.dim_y): + for x in range(self.dim_x): + # 1 represent a wall in the environment + if self.world[y][x] == 1: + # A wall is always a collision, no matter the rotation + for i in range(n_rotations): + rot = i * self.rotation + self.obstacles[Location(x, y, rot)] = True + # Keep track of where the paths of the other agents end + self.path_ends = dict() + for path in other_agent_paths: + # Get the last timestep in the path of the agent + last_time = list(path)[-1] + # Get the last location in the path of the agent + last_pos = path[last_time] + # Two agents always collide when they share the same location, no matter the rotation + for i in range(n_rotations): + rot = i * self.rotation + self.path_ends[Location(last_pos.col, last_pos.row, rot)] = last_time + # Keep track of the other paths of agents to detect collisions + self.other_agent_paths = other_agent_paths + + # Returns the latest timestep at which a specific location will be used + def find_lastest_use(self, location): + # Keep track of all the uses of that location + uses = [] + # Check in the path of each agent if that agent uses that location, if yes, add it to the list + for agent_path in self.other_agent_paths: + for t, loc in agent_path.items(): + if loc.col == location.col and loc.row == location.row: + uses.append(t) + # If the location is used at least once, return the maximum + if uses: + return max(uses) + # If the location is never used, return 0 + else: + return 0 + + + def search(self, time_step, start_location, goal_location, other_agent_paths, + release_time=0, find_step = 0): + self.create_obstacles(other_agent_paths) + initial_state = State(time_step, start_location) + # Find the lastest use of the goal location to avoid parking on a location that is still going to be used + lastest_use = self.find_lastest_use(goal_location) + came_from = {} + open_list = [initial_state] + closed_set = set() + initial_state.g_score = 0 + initial_state.f_score = get_heuristic(start_location, goal_location, self.rotation) + while open_list: + current = heappop(open_list) + if current.location == goal_location: + if current in came_from and came_from[current].location == goal_location: + if current.time > lastest_use: + new_path = [current] + while current in came_from: + current = came_from[current] + new_path.append(current) + # Reverse path + return new_path[::-1] + closed_set |= {current} + neighbours = self.get_neighbours(current) + neighbour: State + for neighbour in neighbours: + # Only explore new states + if (neighbour not in closed_set) and (neighbour not in open_list): + came_from[neighbour] = current + neighbour.g = current.g + 1 + neighbour.f = neighbour.g + get_heuristic(neighbour.location, goal_location, self.rotation) + heappush(open_list, neighbour) + return False diff --git a/Algorithms/Online_Decentralized/Algorithm_Token_Passing/ta_state.py b/Algorithms/Online_Decentralized/Algorithm_Token_Passing/ta_state.py new file mode 100644 index 0000000000000000000000000000000000000000..a6269547d945284d4fcff1503617d8a2e44b8ff4 --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_Token_Passing/ta_state.py @@ -0,0 +1,60 @@ +""" +Created on Sat Apr 18 10:45:11 2020 + +@author: Pieter Cawood + +""" + +def h(pos1, pos2): + return abs(pos1.col - pos2.col) + abs(pos1.row - pos2.row) + +class Location(object): + def __init__(self, col, row, rotation): + self.col = col + self.row = row + self.rotation = rotation + + # Relevant information for pickup and delivery actions + self.task_id = None + self.to_pickup = False + self.to_deliver = False + + def __eq__(self, other): + return self.col == other.col and self.row == other.row and self.rotation == other.rotation + + def __hash__(self): + return hash(str(self.col) + "_" + str(self.row) + "_" + str(self.rotation)) + + def __str__(self): + return str((self.col, self.row, self.rotation, self.to_pickup, self.to_deliver)) + + # Better information for debugging + def __repr__(self): + return f"Location({self.col}, {self.row}, {self.rotation}, {self.to_pickup}, {self.to_deliver})" + + +class State(object): + def __init__(self, time, location): + self.time = time + self.location = location + self.g = 0 + self.f = 0 + + def __eq__(self, other): + return self.time == other.time and self.location == other.location + + def __hash__(self): + return hash(str(self.time) + str(self.location.col) + str(self.location.row)) + + def __str__(self): + return str((self.time, self.location.col, self.location.row)) + + def __lt__(self, other): + if self.f < other.f: + return True + else: + return False + + # Better information for debugging + def __repr__(self): + return f"State(Time: {self.time}, Location(x: {self.location.col}, y: {self.location.row}, r: {self.location.rotation}))" diff --git a/Algorithms/Online_Decentralized/Algorithm_Token_Passing/tp_agent.py b/Algorithms/Online_Decentralized/Algorithm_Token_Passing/tp_agent.py new file mode 100644 index 0000000000000000000000000000000000000000..092eb890db6d8d7decf3c9f8bf046c5cc60dcc09 --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_Token_Passing/tp_agent.py @@ -0,0 +1,161 @@ +# Python modules +import sys +import numpy as np +# Pathfinding modules +from ta_astar import AStar +from ta_state import Location, h + + +class Agent: + def __init__(self, id, initialLocation, system, environment, rotation, on_task_assigned): + self.id = id + # Position + self.pos = initialLocation + # Plan paths + self.a_star = AStar(environment, rotation) + # Used to request token when looking for a task + self.system = system + + self.on_task_assigned = on_task_assigned + + def look_for_task(self, token, timestep): + availableTasks = [] # List of all the tasks that are available to the agent + + ##-- Check if pickup/delivery is not end of path of any other agent --## + # Get last locations of all paths in token + pathEnds = token.get_pathends(self.id) + # If pickup/delivery is not in pathEnds it's an available task + for t in token.taskSet: + if t.pickup not in pathEnds and t.delivery not in pathEnds: + availableTasks.append(t) + # If there is no available task plan a path to a location where the agent can wait + if len(availableTasks) == 0: + self.path2(token, timestep) + # There is at least one task the agent can execute + else: + # Find the "best" task (best = minimum h-value) + h_scores = np.array(map(lambda t: h(self.pos, t.pickup), availableTasks)) + min_task = availableTasks[np.argmin(h_scores)] + # Plan path for that task + self.path1(token, min_task, timestep) + + + def path1(self, token, task, timestep): + """[summary] + Args: + token (Token): The global token provided by the system + task (Task): The task for which a path needs to be planned + timestep (int): Current timestep + """ + + # All needed locations for the pathplanning + current_location = Location(self.pos.col, self.pos.row, self.pos.rotation) + pickup_location = Location(task.pickup.col, task.pickup.row, task.pickup.rotation) + delivery_location = Location(task.delivery.col, task.delivery.row, task.delivery.rotation) + + ##----------------## + ## Path to pickup ## + ##----------------## + + # Get the paths of all the other agents + other_agent_paths = token.get_other_agents_paths(timestep, self.id) + # Plan a path from the current location of the agent to the pickup location of the task + pickup_path = self.a_star.search(timestep, current_location, pickup_location, other_agent_paths) + # There should always be a path if the problem is well formed + if not pickup_path: + raise ValueError("[TP] No path to pickup location - Problem not well formed") + # Add newly planned path to the agent's path in the token + for state in pickup_path: + token.paths[self.id][state.time] = state.location + old_timestep = timestep + + # Update the timestep to the timestep at the end of the planned path + timestep = timestep + len(pickup_path) - 1 + + timestep_at_pickup = timestep + + ##------------------## + ## Path to delivery ## + ##------------------## + + # Get the paths of all the other agents + other_agent_paths = token.get_other_agents_paths(timestep, self.id) + # Plan a path from the pickup location of the task to the delivery location of the task + delivery_path = self.a_star.search(timestep, pickup_location, delivery_location, other_agent_paths) + # There should always be a path if the problem is well formed + if not delivery_path: + raise ValueError("[TP] No path to delivery location - Problem not well formed") + # Add newly planned path to the agent's path in the token + for state in delivery_path: + token.paths[self.id][state.time] = state.location + + timestep = timestep + len(delivery_path) - 1 + + ##---------------------------## + ## Pickup / Delivery actions ## + ##---------------------------## + + # Register in the last location of the path to the pickup location that the agent needs to pickup a task and register the task ID + token.paths[self.id][timestep_at_pickup].to_pickup = True + token.paths[self.id][timestep_at_pickup].task_id = task.id + + # Register in the last location of the path to the delivery location that the agent needs to pickup a task and register the task ID + token.paths[self.id][timestep].to_deliver = True + token.paths[self.id][timestep].task_id = task.id + + # Assign task to agent + token.assignments[self.id] = task.id + # Remove the task from the taskset + token.taskSet.remove(task) + + def path2(self, token, timestep): + ##-- Check if current location is not delivery location of any task in taskSet --## + # Indicates whether agent needs to move + needToMove = False + for t in token.taskSet: + # If the agent is parked on the delivery location of a task he needs to move + if t.delivery == self.pos: + needToMove = True + if not needToMove: + # Agent doesn't need to move, update the path with a trivial path to current position + token.paths[self.id][timestep] = Location(self.pos.col, self.pos.row, self.pos.rotation) + else: + ##-- Find a free endpoint to move to --## + endpoints = self.system.get_free_endpoints() + # Select the best endpoint (best = smallest h-score) + h_scores = list(map(lambda e: h(self.pos, e), endpoints)) + chosen_endpoint = endpoints[np.argmin(h_scores)] + + ##-- Plan path to free endpoint --## + # Make sure planned path doesn't collide with already planned paths + current_location = Location(self.pos.col, self.pos.row, self.pos.rotation) + endpoint_location = Location(chosen_endpoint.col, chosen_endpoint.row, chosen_endpoint.rotation) + # Get the paths of all the other agents + other_agent_paths = token.get_other_agents_paths(timestep, self.id) + # Plan a path from the agent's current location to the chosen endpoint + path_to_endpoint = self.a_star.search(timestep, current_location, endpoint_location, other_agent_paths) + # There should always be a path if the problem is well formed + if not path_to_endpoint: + raise ValueError("[TP] No path to chosen endpoint - Problem not well formed") + # Add newly planned path to the agent's path in the token + for state in path_to_endpoint: + token.paths[self.id][state.time] = state.location + + def move(self, token, timestep): + # Get the current path of the agent + path = token.paths[self.id] + # Check if the agent has already planned a move for this timestep + if timestep not in path: + # If agent has not yet planned a move for this timestep it requests the token and looks for a task + # Start looking for a new task + self.look_for_task(token, timestep) + # Check if the agent has assigned a task to itself and notify Unity if that is the case (using callback) + if token.assignments[self.id] is not None: + self.on_task_assigned(self.id, token.assignments[self.id]) + + # Select the move of the agent in this timestep + next_move = token.paths[self.id][timestep] + # Update the agent's position + self.pos = next_move + # Return the agent's next position + return next_move diff --git a/Algorithms/Online_Decentralized/Algorithm_Token_Passing/tp_system.py b/Algorithms/Online_Decentralized/Algorithm_Token_Passing/tp_system.py new file mode 100644 index 0000000000000000000000000000000000000000..121ce15369f3709c23c5101f0b56231b78fd3334 --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_Token_Passing/tp_system.py @@ -0,0 +1,104 @@ +# Python modules +import sys +import numpy as np +# Pathfinding modules +from ta_state import Location +# Own modules +from tp_agent import Agent +from tp_token import Token + +# System manages the token +class System: + def __init__(self, env, rotation): + # Keep track of the warehouse setup + self.environment = env + # Keep track of rotation + self.rotation = rotation + + # Keep track of all agents in the system + self.agents = dict() + # Keep track of all tasks + self.tasks = dict() + # Token setup + self.token = Token() + # Keep track of all the non-task/task endpoints + self.task_endpoints = [] + self.non_task_endpoints = [] + # Get all the endpoints from the environment + self.init_endpoints() + + # Find all the task and non-task endpoints in the environment + def init_endpoints(self): + # Get the dimensions of the environment + dim_y = len(self.environment) + dim_x = len(self.environment[0]) + for y in range(dim_y): + for x in range(dim_x): + # Non-task endpoints (parking locations) are represented by 2 + if self.environment[y][x] == 2: + self.non_task_endpoints.append(Location(x, y, 0)) + # Task endpoints (pickup/delivery locations) are represented by 3 + elif self.environment[y][x] == 3: + self.task_endpoints.append(Location(x, y, 0)) + + ##---------## + ## Getters ## + ##---------## + + def get_agent(self, a_id): + return self.agents[a_id] + + def get_task(self, task_id): + return self.tasks[task_id] + + def get_endpoints(self): + return np.concatenate((self.non_task_endpoints, self.task_endpoints)) + + def get_non_task_endpoints(self): + return self.non_task_endpoints + + def get_free_endpoints(self): + # List of all the endpoints + all_endpoints = self.get_endpoints() + free_endpoints = [] + # Get a list of the last positions of each agent's path + endPaths = self.token.get_pathends() + # Generate a list of all the delivery locations of the tasks in the taskSet + deliveryLocations = [] + for t in self.token.taskSet: + deliveryLocations.append(t.delivery) + for e in all_endpoints: + # If endpoint is not the end of the path of any agent + # or is not the delivery location of any task it's free + if e not in endPaths and e not in deliveryLocations: + free_endpoints.append(e) + return free_endpoints + + ##---------------------## + ## Adding new elements ## + ##---------------------## + + def add_task(self, task): + self.token.add_task(task) + self.tasks[task.id] = task + return True + + def add_agent(self, agent_id, agent_pos, on_task_assigned): + agent = Agent(agent_id, agent_pos, self, self.environment, self.rotation, on_task_assigned) + self.agents[agent_id] = agent + self.token.add_agent(agent) + + ##-------------------## + ## Utilitary methods ## + ##-------------------## + + def request_token(self): + return self.token + + def is_endpoint(self, pos): + if pos in self.non_task_endpoints or pos in self.task_endpoints: + return True + else: + return False + + diff --git a/Algorithms/Online_Decentralized/Algorithm_Token_Passing/tp_task.py b/Algorithms/Online_Decentralized/Algorithm_Token_Passing/tp_task.py new file mode 100644 index 0000000000000000000000000000000000000000..105c02eabdb1cc0c4828f5b811455118e4e3bd22 --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_Token_Passing/tp_task.py @@ -0,0 +1,43 @@ +CURRENT_TASK_ID = 0 + +class Task: + """ Represents a task in the pickup & delivery problem + + Attributes: + id: int + Identifier of the task + pickupLocation: Position + The location where the task needs to be picked up + deliveryLocation: Position + The location where the task needs to be delivered + """ + def __init__(self, id, pickupLocation, deliveryLocation, releaseTime=0): + self.id = id + + self.pickup = pickupLocation + self.delivery = deliveryLocation + + self.releaseTime = releaseTime + + # Keep track timestep when task enters the taskset and when it's executed => calculating service time + self.entered = None + self.delivered = None + + def service_time(self): + if self.entered is not None and self.delivered is not None: + return self.delivered - self.entered + else: + return None + + def __eq__(self, other): + return self.pickup == other.pickup and self.delivery == other.delivery + + def __hash__(self): + return ((hash(self.pickup) * 397) ** hash(self.delivery)) * 397 + + # Better information for debugging + def __repr__(self): + return f"Task({self.id},Pickup({self.pickup}), Delivery({self.delivery}))" + + def __str__(self): + return f"Task({self.id},Pickup({self.pickup}), Delivery({self.delivery}))" diff --git a/Algorithms/Online_Decentralized/Algorithm_Token_Passing/tp_token.py b/Algorithms/Online_Decentralized/Algorithm_Token_Passing/tp_token.py new file mode 100644 index 0000000000000000000000000000000000000000..f804b8d9dbe0dfc553d22065e9d17d8681b9c32a --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_Token_Passing/tp_token.py @@ -0,0 +1,63 @@ +class Token: + def __init__(self): + # Keep track of the paths of all the agents + self.paths = dict() + # Keep track of which agent is executing which task + self.assignments = dict() + # Keep track of the remaining tasks + self.taskSet = [] + + ##---------## + ## Getters ## + ##---------## + + # Returns the last location on the path of each agent + def get_pathends(self, given_id=None): + pathEnds = [] + for a_id, k in self.paths.items(): + if given_id is None or a_id != given_id: + pathEnds.append(k[list(k)[-1]]) + return pathEnds + + # Get the paths of all agents except the path of agent with ID = own_id + def get_other_agents_paths(self, timestep, own_id): + other_agent_paths = [] + for a_id, path in self.paths.items(): + if a_id != own_id: + other_agent_paths.append(path) + return other_agent_paths + + ##------------------## + ## Add new elements ## + ##------------------## + + # Adds a new agent to the system + def add_agent(self, agent): + a_id = agent.id + self.paths[a_id] = dict() + self.paths[a_id][0] = agent.pos + self.assignments[a_id] = None + + # Adds a new task to the system + def add_task(self, task): + self.taskSet.append(task) + + ##-------------------## + ## Utilitary methods ## + ##-------------------## + + # Restores the token with an old state of the token + def restore(self, old_token): + self.paths = old_token.paths + self.assignments = old_token.assignments + self.taskSet = old_token.taskSet + + # Generates a copy of this token + def copy(self): + new_token = Token() + new_token.paths = self.paths + new_token.assignments = self.assignments + new_token.taskSet = self.taskSet + return new_token + + diff --git a/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/EnvChannel.py b/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/EnvChannel.py new file mode 100644 index 0000000000000000000000000000000000000000..89909eccb160d3bebb15087e72541ddbdd4ce2fd --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/EnvChannel.py @@ -0,0 +1,45 @@ +import json +from mlagents_envs.side_channel.side_channel import ( + SideChannel, + IncomingMessage, + OutgoingMessage, +) +import uuid + +from EnvironmentData import EnvironmentData + +""" +class that processes information from SideChannel EnvChannel +""" + +class EnvChannel(SideChannel): + + def __init__(self) -> None: + super().__init__(uuid.UUID("621f0a70-4f87-11ea-a6bf-784f4387d1f7")) #must coincide with ChannelId set in c# + self.EnvData = EnvironmentData() # object that stores info on environment + + def on_message_received(self, msg: IncomingMessage) -> None: + # We simply read a string from the message and print it. + data = msg.read_string() + environment_info = json.loads(data) + + self.EnvData.matrix = environment_info["matrixLayout"] + self.EnvData.rotation = environment_info["rotationRobot"] + self.EnvData.action_size = environment_info["sizeOfAction"] + self.EnvData.observation_size = environment_info["sizeOfObservation"] + self.EnvData.number_of_robots = environment_info["numberOfRobotsInEnv"] + self.EnvData.number_of_current_tasks = environment_info["numberOfCurrentTasks"] + self.EnvData.can_go_backwards = environment_info["backwards"] + self.EnvData.random_tasks = environment_info["tasksGeneratedRandomly"] + self.EnvData.instance_ids = environment_info["instanceIDSRobots"] + + self.EnvData.set_initial_nodes_dictionary(environment_info["initialNodesOfRobots"]) + self.EnvData.set_tasks_to_be_assigned(environment_info["currentTasks"]) + self.EnvData.set_assigned_tasks() + + def send_string(self, data: str) -> None: + # Add the string to an OutgoingMessage + msg = OutgoingMessage() + msg.write_string(data) + # We call this method to queue the data we want to send + super().queue_message_to_send(msg) \ No newline at end of file diff --git a/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/EnvironmentData.py b/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/EnvironmentData.py new file mode 100644 index 0000000000000000000000000000000000000000..ea3e19ffeee3dfbe56ad9e5cddeab3af61bcbfaf --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/EnvironmentData.py @@ -0,0 +1,86 @@ +# stores data on environment +# initialized when initial data is being sent through EnvChannel +import json + +from Node import Node +from ta_state import Location +import tpts_task + + +class EnvironmentData: + + def __init__(self): + self.matrix = None + self.rotation = None + self.action_size = None + self.observation_size = None + self.number_of_robots = None + self.number_of_current_tasks = None + self.can_go_backwards = None + self.random_tasks = None # if set to true random tasks will be send whenever a task has been completed, + # otherwise all tasks self.tasks_to_be_assigned + + self.instance_ids = [] + self.current_nodes_dictionary = {} # dictionary instance_id -> current node + self.tasks_to_be_assigned = [] # tasks that are still to be assigned + self.assigned_tasks_dictionary = {} # dictionary instance_id -> assigned task + + self.task_side_channel = None + + self.tasksCreated = 0 + + ######################################### + ## methods used by EnvChannel to initialize attributes: + ######################################### + + # set_initial_nodes_dictionary + # set_tasks_to_be_assigned + # set_assigned_tasks + + # given a correct string containing array of nodes + def set_initial_nodes_dictionary(self, initial_nodes): + for i in range(self.number_of_robots): + self.current_nodes_dictionary[self.instance_ids[i]] = Node(initial_nodes[i]["GridPosition"]["Row"], + initial_nodes[i]["GridPosition"]["Column"], + initial_nodes[i]["Degrees"]) + + # given a correct json_string containing array of tasks + def set_tasks_to_be_assigned(self, tasks): + for i in range(self.number_of_current_tasks): + pickup = Location(tasks[i]["PickUp"]["Column"], tasks[i]["PickUp"]["Row"], 0) + delivery = Location(tasks[i]["Delivery"]["Column"], tasks[i]["Delivery"]["Row"], 0) + self.tasks_to_be_assigned.append(tpts_task.Task(tpts_task.CURRENT_TASK_ID, pickup, delivery)) + tpts_task.CURRENT_TASK_ID += 1 + + # initialize dictionary robot instance_id -> task (None) + def set_assigned_tasks(self): + for i in range(self.number_of_robots): + self.assigned_tasks_dictionary[self.instance_ids[i]] = None + + ######################################### + ## methods used to update environment info + ######################################### + + # when a task is assigned to a robot, it has to be added to self.assigned_tasks + # and removed from self.tasks_to_be_assigned + # info has to be sent to unity via the correct channel + def assign_task(self, robot_instanceID, task): + self.assigned_tasks_dictionary[robot_instanceID] = task + # self.tasks_to_be_assigned.remove(task) + taskDict = {"Task": { + "PickUp": {"Column": str(task.pickup.col), "Row": str(task.pickup.row)}, + "Delivery": {"Column": str(task.delivery.col), "Row": str(task.delivery.row)}}, + "InstanceID": str(robot_instanceID)} + + self.task_side_channel.send_string(json.dumps(taskDict)) + + # when a new task is available it is added to tasks_to_be_assigned + # a check is made whether there are still tasks that can be added, but this should not be happening (diagnostical) + def add_task_to_tasks_to_be_assigned(self, task): + if len(self.tasks_to_be_assigned) == self.number_of_current_tasks: + raise Exception("cannot add more tasks") + self.tasks_to_be_assigned.append(task) + + # when a robot has finished his task it has to be removed from assigned_tasks + def task_done(self, instance_id): + self.assigned_tasks_dictionary[instance_id] = None diff --git a/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/Node.py b/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/Node.py new file mode 100644 index 0000000000000000000000000000000000000000..a2bb07c8fdf941ab68a8e8c87e8478b6d2e79aba --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/Node.py @@ -0,0 +1,39 @@ +# Class Node represent nodes in the graph. Every node contains a +# position (x,y) in the grid +# and a rotation in degree where +# 0 = North +# 90 = East +# 280 = South +# 270 = West +# all degrees must be between 0 and 360 + +# attributes are set to private such that they cannot be overwritten and there is no problem with the hash + +class Node: + def __init__(self,x,y,g): + self._x = x + self._y = y + self._g = g + + @property + def x(self): + return self._x + + @property + def y(self): + return self._y + + @property + def g(self): + return self._g + + + def __eq__(self, other): + return self.__class__ == other.__class__ and self.x == other.x and self.y == other.y and self.g == other.g + + + def __hash__(self): + return (((self.x * 397) ** self.y) * 397) **self.g + + def __str__(self): + return "[(" + str(self.x) + ", " + str(self.y) + ")" + "," + str(self.g) + "]" diff --git a/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/Pipfile b/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/Pipfile new file mode 100644 index 0000000000000000000000000000000000000000..2cf8108a7836978e89ef3320e61b72d3c4eb3be6 --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/Pipfile @@ -0,0 +1,14 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +networkx = "==2.5" +mlagents = "==0.23.0" +mlagents-envs = "==0.23.0" + +[dev-packages] + +[requires] +python_version = "3.6" diff --git a/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/Readme.md b/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/Readme.md new file mode 100644 index 0000000000000000000000000000000000000000..d354f1ceb2311e731e56be3a148b0fb0cc535666 --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/Readme.md @@ -0,0 +1,59 @@ +# Token Passing with Task Swaps (TPTS) + +The Token-Passing with Task Swaps (TPTS) algorithm is a decentralized algorithm for the online variant of the MAPD problem. + +In the online variant of the MAPD problem the following is supported: +- Using randomly generated tasks (randomtasks = True) +- Using tasks from a taskslist (bv. ../config/tasks.txt) + -> When using a taskslist with releaseTimes: releaseTimes are ignored (only used in offline variant) +- Tested from 1 agent up untill 50 agents (significant lag for larger amount of agents) + +## Running the algorithm + +1. Install the virtual environment + - pipenv install +2. Run the "decentralized_decisionmaker_shortest_path.py" file + - pipenv run python decentralized_decisionmaker_shortest_path.py +3. Start the game inside the Unity editor + +## Working of the algorithm + +This implementation is based on the "Lifelong Multi-Agent Path Finding for Online Pickup and Delivery Tasks" paper (https://arxiv.org/pdf/1705.10868.pdf). +An explanation of the algorithm is available at: + - Section 4.2 of the "Lifelong Multi-Agent Path Finding for Online Pickup and Delivery Tasks" paper + - Section 2.2.2 of the paper provided in the "paper" directory + +General overview of working: + - Token contains: + * Paths of all agents + * Taskset + * Assignments of tasks of all agents + - In each timestep each agent moves one step following its path in the token + - When an agent reaches the pickup location of its task: + * Remove the task from the task set + - When an agent reaches the end of its path (= free agent) it looks for a task: + - Task found: + * Plan path to execute task and update token + - No task found: + * Plan path to safe location and update token + +Differece with Token Passing (TP): + - Availability tasks in token + * In the TP algorithm tasks are removed from the taskset as soon as an agent assigns that task to itself + * In the TPTS algorithm tasks are only removed when an agent reaches the pickup location of the task + => This allows agents to select tasks that are already assigned to other agents if they can execute the task more efficiently (= task swapping) + +## Overview of the provided files + +Main file: +- decentralized_decisionmaker_shortest_path.py: Main file that runs the algorithm + +Token Passing with Task Swaps: +- tpts_agent.py: Agent that are executing tasks +- tpts_system: System manages the agents and tasks +- tpts_task: Pickup and delivery tasks +- tpts_token: Token that is used for communicating global information between the agents + +A-star: +- ta_astar.py: A-Star algorithm +- ta_state.py: Contains Location and state classes used for the path planning \ No newline at end of file diff --git a/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/TaskSideChannel.py b/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/TaskSideChannel.py new file mode 100644 index 0000000000000000000000000000000000000000..5905a60a0e4d906da492398691ce59c60764791a --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/TaskSideChannel.py @@ -0,0 +1,38 @@ +import json +from mlagents_envs.side_channel.side_channel import ( + SideChannel, + IncomingMessage, + OutgoingMessage, +) +import uuid + +import tpts_task +from ta_state import Location + + +class TaskSideChannel(SideChannel): + + def __init__(self) -> None: + super().__init__(uuid.UUID("c11ab982-82b8-4194-b387-3bd0fe9ebdc7")) #must coincide with ChannelId set in c# + self.environment_data = None #info on the environment + + # channel receives new tasks that have to be assigned + def on_message_received(self, msg: IncomingMessage) -> None: + data = msg.read_string() + new_task = json.loads(data) + new_task = new_task["task"] + task_to_add = tpts_task.Task(tpts_task.CURRENT_TASK_ID, + Location(new_task["PickUp"]["Column"], new_task["PickUp"]["Row"], 0), + Location(new_task["Delivery"]["Column"], new_task["Delivery"]["Row"], 0)) + tpts_task.CURRENT_TASK_ID += 1 + # add task to task to be assigned + self.environment_data.add_task_to_tasks_to_be_assigned(task_to_add) + + # channel sends information when a task has been assigned (to which robot) + def send_string(self, data: str) -> None: + + # Add the string to an OutgoingMessage + msg = OutgoingMessage() + msg.write_string(data) + # We call this method to queue the data we want to send + super().queue_message_to_send(msg) \ No newline at end of file diff --git a/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/decentralized_decisionmaker_shortest_path.py b/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/decentralized_decisionmaker_shortest_path.py new file mode 100644 index 0000000000000000000000000000000000000000..9dba440c4b19d672bd25c54c07d8c4579d97a82a --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/decentralized_decisionmaker_shortest_path.py @@ -0,0 +1,165 @@ +##------------------## +## Python libraries ## +##------------------## + +import sys +import numpy as np + +##-----------## +## ML-agents ## +##-----------## + +from mlagents_envs.environment import ActionTuple, UnityEnvironment +import EnvChannel +import TaskSideChannel +from Node import Node + +##------## +## TPTS ## +##------## + +from tpts_system import System as TPTS_System +from ta_state import Location +import tpts_task + +simulation_going = True + +# Load the side channels and Unity environment. +envChannel = EnvChannel.EnvChannel() +taskChannel = TaskSideChannel.TaskSideChannel() +env = UnityEnvironment(file_name=None, side_channels=[envChannel, taskChannel]) # Open unity and press play to execute +env.reset() # reset the environment and get info about environment through envChannel + +# Specify the used behaviour name for steering the agent +behavior_names = list(env.behavior_specs.keys()) +behavior_name = behavior_names[0] + +# info obtained from environment +environment_info = envChannel.EnvData +# set up links between task side channel and environment info +environment_info.task_side_channel = taskChannel +taskChannel.environment_data = environment_info + +# Retrieve information from environment +matrix = environment_info.matrix +number_of_robots = environment_info.number_of_robots +rotation = environment_info.rotation +observation_size = environment_info.observation_size +action_size = environment_info.action_size +robot_can_go_backwards = environment_info.can_go_backwards + +# Initialize system +system = TPTS_System(matrix, rotation) + +# Callback called when an agent assigns itself a task +def on_task_assigned(agent_id, task_id): + environment_info.assign_task(agent_id, system.get_task(task_id)) + +##----------------## +## Robot Creation ## +##----------------## + +# Number of agents in the configuration file +n_agents = len(environment_info.instance_ids) + +# Create all the agents +for robot_id, start_node in environment_info.current_nodes_dictionary.items(): + # Convert the Node that represents the agent's location to a Location + robot_position = Location(start_node.y, start_node.x, start_node.g) + # Create agent + system.add_agent(robot_id, robot_position, on_task_assigned) + +# Each agent requests 1 action in each timestep +# next timestep starts when all agents have requested an action in this timestep +actions_requested_in_timestep = 0 +# Keep track of current timestep +timestep = 0 + +while simulation_going: + # If there are new tasks that need to be assigned add them to the task set + if len(environment_info.tasks_to_be_assigned) != 0: + for task in environment_info.tasks_to_be_assigned: + # Add task to task set + system.add_task(task) + # Task is already in task set, remove it from this list to avoid duplicates in task set + environment_info.tasks_to_be_assigned.remove(task) + + # Get information on the agents that request an action + decision_steps, terminal_steps = env.get_steps(behavior_name) + agents = decision_steps.agent_id + observations = decision_steps.obs + + # Actions that will be sent back to Unity + actions = [] + action_tuple = ActionTuple() # actions to send to unity + + # Create an action for all agents that request an action + for i in range(len(agents)): + + ##--------------## + ## OBSERVATIONS ## + ##--------------## + + # Keep track of how many agents have requested an action in this timestep + actions_requested_in_timestep += 1 + + # Collect agent's observations + observation = observations[0][i] + # Extract observations + robot_id_unity = observation[0] # robot id in unity used to get correct precomputed path + robot_pos_x = observation[2] + robot_pos_y = observation[1] + robot_rot = observation[3] + # Convert coordinates to position + robot_position = Location(robot_pos_x, robot_pos_y, robot_rot) + + # Get Python Agent that represents robot + robot = system.get_agent(int(robot_id_unity)) + + ##-------------## + ## FOLLOW PATH ## + ##-------------## + + # Follow previously computed path or plan new path when at the end of path + next_position = robot.move(system.token, timestep) + # Convert Position to Node + next_action = Node(next_position.row, next_position.col, next_position.rotation) + # Check if a task needs to be picked up / delivered + pickup_action = 0 + delivery_action = 0 + if next_position.to_pickup: + # Agent has to pick up his task + pickup_action = 1 + # Agent has picked up the task, no agent can swap from now on, remove it from the taskSet + to_remove = system.get_task(next_position.task_id) + system.token.taskSet.remove(to_remove) + elif next_position.to_deliver: + # Agent has to deliver his task + delivery_action = 1 + # Agent has no task assigned anymore as the task is delivered + system.token.assignments[robot_id_unity] = None + + # Send action to agent in Unity + actions.extend([next_action.x, next_action.y, next_action.g, pickup_action, delivery_action]) + + + # When all agents have moved in this timestep update the timestep + if (actions_requested_in_timestep == n_agents): + # Update the timestep + timestep += 1 + # Reset the number of agents that have requested a timestep in this timestep + actions_requested_in_timestep = 0 + + # Send actions to Unity + actions = np.array(actions) + actions.resize(len(agents), action_size) + action_tuple.add_discrete(actions) + + env.set_actions(behavior_name, action_tuple) + env.step() + + + + + + diff --git a/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/paper/Bachelorthesis.pdf b/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/paper/Bachelorthesis.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e9bf4fce9fccb3903a7f502782e4292f8c59e23d Binary files /dev/null and b/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/paper/Bachelorthesis.pdf differ diff --git a/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/ta_astar.py b/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/ta_astar.py new file mode 100644 index 0000000000000000000000000000000000000000..c936ffdaffbb6872143e2fd42caaa7ab35656dc1 --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/ta_astar.py @@ -0,0 +1,163 @@ +""" +Created on Wed Apr 22 07:43:03 2020 + +@author: Pieter Cawood + +""" +from heapq import * +from ta_state import * + +def get_heuristic(start_location, goal_location, rotation): + # Admissible heuristic - manhattan distance + return abs(start_location.col - goal_location.col) + abs(start_location.row - goal_location.row) + +class AStar: + def __init__(self, world, rotation): + self.rotation = rotation + self.world = world + self.dim_x = len(world[0]) + self.dim_y = len(world) + self.obstacles = {} + self.path_ends = dict() + self.other_agent_paths = [] + + def state_possible(self, current_state, new_state): + # Check if wall + not_obstacle = False + if new_state.location not in self.obstacles: + not_obstacle = True + return 0 <= new_state.location.col < self.dim_x and 0 <= new_state.location.row < self.dim_y \ + and not_obstacle and not self.is_collision(current_state, new_state) + + def is_collision(self, current_state, new_state): + for other_agent_path in self.other_agent_paths: + # Vertex collision + if new_state.time in other_agent_path: + if other_agent_path[new_state.time].row == new_state.location.row and other_agent_path[new_state.time].col == new_state.location.col: + return True + # Edge collision + if new_state.time in other_agent_path and current_state.time in other_agent_path: + if other_agent_path[new_state.time].row == current_state.location.row and \ + other_agent_path[new_state.time].col == current_state.location.col and \ + other_agent_path[current_state.time].row == new_state.location.row and \ + other_agent_path[current_state.time].col == new_state.location.col: + return True + # Last position of agent is his parking location + if new_state.location in self.path_ends: + busy_time = self.path_ends[new_state.location] + if new_state.time >= busy_time: + return True + return False + + def get_neighbours(self, current_state): + neighbours = [] + neighbour_time_step = current_state.time + 1 + # Wait in state + new_state = State(neighbour_time_step, Location(current_state.location.col, current_state.location.row, current_state.location.rotation)) + if self.state_possible(current_state, new_state): + neighbours.append(new_state) + # Add rotation + new_state = State(neighbour_time_step, Location(current_state.location.col, current_state.location.row, (current_state.location.rotation+self.rotation) % 360)) + if self.state_possible(current_state, new_state): + neighbours.append(new_state) + # Remove rotation + new_state = State(neighbour_time_step, Location(current_state.location.col, current_state.location.row, (current_state.location.rotation-self.rotation) % 360)) + if self.state_possible(current_state, new_state): + neighbours.append(new_state) + if current_state.location.rotation == 0: + # Move down + new_state = State(neighbour_time_step, Location(current_state.location.col, current_state.location.row - 1, current_state.location.rotation)) + if self.state_possible(current_state, new_state): + neighbours.append(new_state) + elif current_state.location.rotation == 90: + # Move right + new_state = State(neighbour_time_step, Location(current_state.location.col + 1, current_state.location.row, current_state.location.rotation)) + if self.state_possible(current_state, new_state): + neighbours.append(new_state) + elif current_state.location.rotation == 180: + # Move up + new_state = State(neighbour_time_step, Location(current_state.location.col, current_state.location.row + 1, current_state.location.rotation)) + if self.state_possible(current_state, new_state): + neighbours.append(new_state) + elif current_state.location.rotation == 270: + # Move left + new_state = State(neighbour_time_step, Location(current_state.location.col - 1, current_state.location.row, current_state.location.rotation)) + if self.state_possible(current_state, new_state): + neighbours.append(new_state) + return neighbours + + def create_obstacles(self, other_agent_paths): + n_rotations = int(360/self.rotation) + # Keep track of all walls in the environment + for y in range(self.dim_y): + for x in range(self.dim_x): + # 1 represent a wall in the environment + if self.world[y][x] == 1: + # A wall is always a collision, no matter the rotation + for i in range(n_rotations): + rot = i * self.rotation + self.obstacles[Location(x, y, rot)] = True + # Keep track of where the paths of the other agents end + self.path_ends = dict() + for path in other_agent_paths: + # Get the last timestep in the path of the agent + last_time = list(path)[-1] + # Get the last location in the path of the agent + last_pos = path[last_time] + # Two agents always collide when they share the same location, no matter the rotation + for i in range(n_rotations): + rot = i * self.rotation + self.path_ends[Location(last_pos.col, last_pos.row, rot)] = last_time + # Keep track of the other paths of agents to detect collisions + self.other_agent_paths = other_agent_paths + + # Returns the latest timestep at which a specific location will be used + def find_lastest_use(self, location): + # Keep track of all the uses of that location + uses = [] + # Check in the path of each agent if that agent uses that location, if yes, add it to the list + for agent_path in self.other_agent_paths: + for t, loc in agent_path.items(): + if loc.col == location.col and loc.row == location.row: + uses.append(t) + # If the location is used at least once, return the maximum + if uses: + return max(uses) + # If the location is never used, return 0 + else: + return 0 + + + def search(self, time_step, start_location, goal_location, other_agent_paths, + release_time=0, find_step = 0): + self.create_obstacles(other_agent_paths) + initial_state = State(time_step, start_location) + # Find the lastest use of the goal location to avoid parking on a location that is still going to be used + lastest_use = self.find_lastest_use(goal_location) + came_from = {} + open_list = [initial_state] + closed_set = set() + initial_state.g_score = 0 + initial_state.f_score = get_heuristic(start_location, goal_location, self.rotation) + while open_list: + current = heappop(open_list) + if current.location == goal_location: + if current in came_from and came_from[current].location == goal_location: + if current.time > lastest_use: + new_path = [current] + while current in came_from: + current = came_from[current] + new_path.append(current) + # Reverse path + return new_path[::-1] + closed_set |= {current} + neighbours = self.get_neighbours(current) + neighbour: State + for neighbour in neighbours: + # Only explore new states + if (neighbour not in closed_set) and (neighbour not in open_list): + came_from[neighbour] = current + neighbour.g = current.g + 1 + neighbour.f = neighbour.g + get_heuristic(neighbour.location, goal_location, self.rotation) + heappush(open_list, neighbour) + return False diff --git a/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/ta_state.py b/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/ta_state.py new file mode 100644 index 0000000000000000000000000000000000000000..a6269547d945284d4fcff1503617d8a2e44b8ff4 --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/ta_state.py @@ -0,0 +1,60 @@ +""" +Created on Sat Apr 18 10:45:11 2020 + +@author: Pieter Cawood + +""" + +def h(pos1, pos2): + return abs(pos1.col - pos2.col) + abs(pos1.row - pos2.row) + +class Location(object): + def __init__(self, col, row, rotation): + self.col = col + self.row = row + self.rotation = rotation + + # Relevant information for pickup and delivery actions + self.task_id = None + self.to_pickup = False + self.to_deliver = False + + def __eq__(self, other): + return self.col == other.col and self.row == other.row and self.rotation == other.rotation + + def __hash__(self): + return hash(str(self.col) + "_" + str(self.row) + "_" + str(self.rotation)) + + def __str__(self): + return str((self.col, self.row, self.rotation, self.to_pickup, self.to_deliver)) + + # Better information for debugging + def __repr__(self): + return f"Location({self.col}, {self.row}, {self.rotation}, {self.to_pickup}, {self.to_deliver})" + + +class State(object): + def __init__(self, time, location): + self.time = time + self.location = location + self.g = 0 + self.f = 0 + + def __eq__(self, other): + return self.time == other.time and self.location == other.location + + def __hash__(self): + return hash(str(self.time) + str(self.location.col) + str(self.location.row)) + + def __str__(self): + return str((self.time, self.location.col, self.location.row)) + + def __lt__(self, other): + if self.f < other.f: + return True + else: + return False + + # Better information for debugging + def __repr__(self): + return f"State(Time: {self.time}, Location(x: {self.location.col}, y: {self.location.row}, r: {self.location.rotation}))" diff --git a/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/tpts_agent.py b/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/tpts_agent.py new file mode 100644 index 0000000000000000000000000000000000000000..c274323e921b25304f7b3c82e81deef100d88206 --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/tpts_agent.py @@ -0,0 +1,248 @@ +# Python modules +import sys +import numpy as np +# Pathfinding modules +from ta_astar import AStar +from ta_state import Location, h +# Own modules + +class Agent: + def __init__(self, id, initial_position, system, environment, rotation, on_task_assigned): + # Identifier used to identify this agent + self.id = id + # Position of the agent + self.pos = initial_position + # Keep track of the parking location of the agent + self.parkingLocation = initial_position + # AStar planner used to compute path + self.a_star = AStar(environment, rotation) + # System is used to request token to look for tasks + self.system = system + # Indicates whether agent is currently carying a package + self.carrying = False + # Callback called when agent assigns a task to itself + self.on_task_assigned = on_task_assigned + + # Delete path of an agent from the token + def delete_path(self, token, agent, start_timestep): + del token.paths[agent.id] + + # Method that the agent calls to look for a new task and plan a path + def look_for_task(self, token, timestep): + # When look_for_task is called by another agent that tries to swap tasks agent might not be on an endpoint + if not self.system.is_endpoint(self.pos): + # Agent is not on an endpoint so planning a path to an endpoint might fail + found = self.path2(token, timestep) + if found: + # Agent can safely move to an endpoint -> Allow swapping + return True + else: + # Agent can not safely move to an endpoint -> Do not allow swapping + return False + + availableTasks = [] # List of all the tasks that are available to the agent + + ##-- Check if pickup/delivery is not end of path of any other agent --## + # Get last locations of all paths in token + pathEndsWithID = token.get_pathends(self.id) + # Only keep the locations, ID's are not needed here + pathEnds = list(map(lambda x: x[0], pathEndsWithID)) + # If pickup/delivery is not in pathEnds it's an available task + for t in token.taskSet: + # Task is available if it's delivery location is not the end of the path of any agent + if t.pickup not in pathEnds: + availableTasks.append(t) + + # While there is still at least one task + while len(availableTasks) > 0: + # Find the "best" task (best = minimum h-value) + h_scores = np.array(map(lambda t: h(self.pos, t.pickup), availableTasks)) + min_task = availableTasks[np.argmin(h_scores)] + # Remove task from available tasks + availableTasks.remove(min_task) + + # Check if task has already been assigned + other_id = None + for a_id, t_id in token.assignments.items(): + # If another agent has already assigned this task to itself, keep track of the agent + if t_id == min_task.id: + other_id = a_id + if other_id is None: + # No other agent has already reserved this task + + # Check if the path of any agent ends in the delivery location of the task: means that it can rest there forever, look for another task + if min_task.delivery in pathEnds: + continue + # No agent is assigned to task + # Assign the task to this agent + token.assignments[self.id] = min_task.id + # Plan a path to execute the task + self.path1(min_task, token, timestep) + # Call the callback to notify Unity that the agent has a new task assignment + self.on_task_assigned(self.id, min_task.id) + # Agent was able to find a task and plan a path, return True + return True + else: + # Task is already assigned to another agent: check if this agent can reach the pickup location more efficiently + other_agent = self.system.get_agent(other_id) + # Check if the path of any other agent is the delivery location of the task: means that it can rest there forever, look for another task + if min_task.delivery in pathEnds and (min_task.delivery, other_id) not in pathEndsWithID: + continue + # Check if other agent is already at the pickup location of the task: if yes, look for another task + if other_agent.pos == min_task.pickup: + continue + # Make a copy of the token to restore it in case swapping is not allowed + token_copy = token.copy() + # Unassign the task from the other agent + token.assignments[other_id] = None + # Assign this task to this agent + token.assignments[self.id] = min_task.id + # Delete the path of the other agent from the token + self.delete_path(token, other_agent, timestep) + # Plan a path to execute this task + self.path1(min_task, token, timestep) + # Calculate how many steps this agent needs to reach the pickup location + selfReached = timestep + while(token.paths[self.id][selfReached] != min_task.pickup): + selfReached += 1 + # Calculate how many steps the other agent needs to reach the pickup location + otherReached = timestep + while(token_copy.paths[other_id][otherReached] != min_task.pickup): + otherReached += 1 + # Check which agent reaches the pickup location of the task more efficiently + if (selfReached < otherReached): + # This agent can reach the pickup location more efficiently, check if other agent can find another task or find a path to a safe location + success = other_agent.look_for_task(token, timestep) + if success: + # Other agent was able to plan a path to another task or to a safe location -> Notify Unity that this agent has a new task assigned + self.on_task_assigned(self.id, min_task.id) + # Agent was able to find a task and plan a path, return True + return True + # Task Swapping is not allowed or this agent can not reach the pickup location more efficiently, restore the token + token.restore(token_copy) + # Agent was not able to find a task, plan a path to a safe location + + # Keep track of all the delivery locations of the tasks in the taskSet + delivery_locations = [] + for task in token.taskSet: + delivery_locations.append(task.delivery) + # If the current position of the agent is not a delivery location the agent can rest at it's current position + if Location(self.pos.col, self.pos.row, 0) not in delivery_locations: + # Check if agent already has a path in the token (might have been deleted by other agent): create a path if there is none + if self.id not in token.paths: + token.paths[self.id] = dict() + # Register the trivial path to the agent's current location in its path: will try to look for a path in the next timestep + token.paths[self.id][timestep] = Location(self.pos.col, self.pos.row, self.pos.rotation) + else: + # Agent has to move as it's current location is a delivery location, plan a collision-free path to a safe location + self.path2(token, timestep) + # Agent was not able to find a task, but was able to plan a collision-free path to a safe location + return True + + + def path1(self, task, token, timestep): + # Plans a path from the current location of the agent to the pickup location and a path from pickup location to delivery location + + # All needed locations for the pathplanning + current_location = Location(self.pos.col, self.pos.row, self.pos.rotation) + pickup_location = Location(task.pickup.col, task.pickup.row, task.pickup.rotation) + delivery_location = Location(task.delivery.col, task.delivery.row, task.delivery.rotation) + + ##----------------## + ## Path to pickup ## + ##----------------## + + # Get the paths of all the other agents + other_agent_paths = token.get_other_agents_paths(timestep, self.id) + # Plan a path from the current location of the agent to the pickup location of the task + pickup_path = self.a_star.search(timestep, current_location, pickup_location, other_agent_paths) + # There should always be a path if the problem is well formed + if not pickup_path: + raise ValueError("[TPTS] No path to pickup location - Problem not well formed") + + # Add newly planned path to the agent's path in the token + for state in pickup_path: + # Check if agent already has a path in the token (might have been deleted by other agent): create a path if there is none + if self.id not in token.paths: + token.paths[self.id] = dict() + token.paths[self.id][state.time] = state.location + # Update the timestep to the timestep at the end of the planned path + timestep = timestep + len(pickup_path) - 1 + + # Keep track of the timestep when the agent reaches the pickup location + timestep_at_pickup = timestep + + ##------------------## + ## Path to delivery ## + ##------------------## + + # Get the paths of all the other agents + other_agent_paths = token.get_other_agents_paths(timestep, self.id) + # Plan a path from the pickup location of the task to the delivery location of the task + delivery_path = self.a_star.search(timestep, pickup_location, delivery_location, other_agent_paths) + # There should always be a path if the problem is well formed + if not delivery_path: + raise ValueError("[TP] No path to delivery location - Problem not well formed") + # Add newly planned path to the agent's path in the token + for state in delivery_path: + token.paths[self.id][state.time] = state.location + + # Keep track of the timestep at which the agent reaches the delivery location + timestep = timestep + len(delivery_path) - 1 + + ##---------------------------## + ## Pickup / Delivery actions ## + ##---------------------------## + + # Register in the last location of the path to the pickup location that the agent needs to pickup a task and register the task ID + token.paths[self.id][timestep_at_pickup].to_pickup = True + token.paths[self.id][timestep_at_pickup].task_id = task.id + + # Register in the last location of the path to the delivery location that the agent needs to pickup a task and register the task ID + token.paths[self.id][timestep].to_deliver = True + token.paths[self.id][timestep].task_id = task.id + + """ Path2 plans a path from the agent's current location + to the closest free endpoint + """ + def path2(self, token, timestep): + # Agent is not at an endpoint, path planning might fail + ##-- Find free endpoints to move to --## + endpoints = self.system.get_free_endpoints() + # Select the best endpoint (best = smallest h-score) + h_scores = list(map(lambda e: h(self.pos, e), endpoints)) + chosen_endpoint = endpoints[np.argmin(h_scores)] + + ##-- Plan path to free endpoint --## + # Make sure planned path doesn't collide with already planned paths + current_location = Location(self.pos.col, self.pos.row, self.pos.rotation) + endpoint_location = Location(chosen_endpoint.col, chosen_endpoint.row, chosen_endpoint.rotation) + # Get the paths of all the other agents + other_agent_paths = token.get_other_agents_paths(timestep, self.id) + # Plan a path from the agent's current location to the chosen endpoint + path_to_endpoint = self.a_star.search(timestep, current_location, endpoint_location, other_agent_paths) + # If agent is not currently at an endpoint, there might be no possible path, return False + if not path_to_endpoint: + return False + # Add newly planned path to the agent's path in the token + for state in path_to_endpoint: + # Check if agent already has a path in the token (might have been deleted by other agent): create a path if there is none + if self.id not in token.paths: + token.paths[self.id] = dict() + token.paths[self.id][state.time] = state.location + return True + + def move(self, token, timestep): + # Get the current path of the agent + path = token.paths[self.id] + # Check if the agent has already planned a move for this timestep + if timestep not in path: + # If agent has not yet planned a move for this timestep it requests the token and looks for a task + token = self.system.request_token() + self.look_for_task(token, timestep) + # Select the move of the agent in this timestep + next_move = token.paths[self.id][timestep] + # Update the agent's position + self.pos = next_move + # Return the agent's next position + return next_move diff --git a/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/tpts_system.py b/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/tpts_system.py new file mode 100644 index 0000000000000000000000000000000000000000..d5c22f40302601435063882364577e7bd16da96c --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/tpts_system.py @@ -0,0 +1,104 @@ +# Python modules +import sys +import numpy as np +# Pathfinding modules +from ta_state import Location +# Own modules +from tpts_token import Token +from tpts_agent import Agent + +class System: + def __init__(self, environment, rotation): + # Keep track of the warehouse setup + self.environment = environment + # Keep track of rotation + self.rotation = rotation + + # Keep track of all agents in the system + self.agents = dict() + # Keep track of all tasks + self.tasks = dict() + # Token setup + self.token = Token() + + # Keep track of all the non-task/task endpoints + self.task_endpoints = [] + self.non_task_endpoints = [] + # Get all the endpoints from the environment + self.init_endpoints() + + # Find all the task and non-task endpoints in the environment + def init_endpoints(self): + # Get the dimensions of the environment + dim_y = len(self.environment) + dim_x = len(self.environment[0]) + for y in range(dim_y): + for x in range(dim_x): + # Non-task endpoints (parking locations) are represented by 2 + if self.environment[y][x] == 2: + self.non_task_endpoints.append(Location(x, y, 0)) + # Task endpoints (pickup/delivery locations) are represented by 3 + elif self.environment[y][x] == 3: + self.task_endpoints.append(Location(x, y, 0)) + + ##---------## + ## Getters ## + ##---------## + + def get_agent(self, agent_id): + return self.agents[agent_id] + + def get_task(self, task_id): + return self.tasks[task_id] + + def get_endpoints(self): + return np.concatenate((self.non_task_endpoints, self.task_endpoints)) + + def get_free_endpoints(self): + # List of all the endpoints + all_endpoints = self.get_endpoints() + free_endpoints = [] + # Get a list of the last positions of each agent's path + endPathsWithID = self.token.get_pathends() + endPaths = list(map(lambda x: x[0], endPathsWithID)) + # Generate a list of all the delivery locations of the tasks in the taskSet + deliveryLocations = [] + for t in self.token.taskSet: + deliveryLocations.append(t.delivery) + for e in all_endpoints: + # If endpoint is not the end of the path of any agent + # or is not the delivery location of any task it's free + if e not in endPaths and e not in deliveryLocations: + free_endpoints.append(e) + return free_endpoints + + def get_non_task_endpoints(self): + return self.non_task_endpoints + + ##---------------------## + ## Adding new elements ## + ##---------------------## + + def add_agent(self, agent_id, agent_pos, on_task_assigned): + agent = Agent(agent_id, agent_pos, self, self.environment, + self.rotation, on_task_assigned) + self.agents[agent.id] = agent + self.token.add_agent(agent) + + def add_task(self, task): + self.token.add_task(task) + self.tasks[task.id] = task + + ##-------------------## + ## Utilitary methods ## + ##-------------------## + + def request_token(self): + return self.token + + def is_endpoint(self, endpoint): + endpoint_loc = Location(endpoint.col, endpoint.row, 0) + if endpoint_loc in self.non_task_endpoints or endpoint_loc in self.task_endpoints: + return True + else: + return False diff --git a/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/tpts_task.py b/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/tpts_task.py new file mode 100644 index 0000000000000000000000000000000000000000..03e2b01468fb260764e4733a86d8571643c48b16 --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/tpts_task.py @@ -0,0 +1,35 @@ +CURRENT_TASK_ID = 0 + +class Task: + """ Represents a task in the pickup & delivery problem + + Attributes: + id: int + Identifier of the task + pickupLocation: Position + The location where the task needs to be picked up + deliveryLocation: Position + The location where the task needs to be delivered + """ + def __init__(self, id, pickupLocation, deliveryLocation): + self.id = id + + self.pickup = pickupLocation + self.delivery = deliveryLocation + + # Keep track timestep when task enters the taskset and when it's executed => calculating service time + self.entered = None + self.delivered = None + + def service_time(self): + if self.entered is not None and self.delivered is not None: + return self.delivered - self.entered + else: + return None + + # Better information for debugging + def __repr__(self): + return f"Task({self.id},Pickup({self.pickup}), Delivery({self.delivery}))" + + def __str__(self): + return f"Task({self.id},Pickup({self.pickup}), Delivery({self.delivery}))" diff --git a/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/tpts_token.py b/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/tpts_token.py new file mode 100644 index 0000000000000000000000000000000000000000..7e42d8ffd46c51fdebcea3639f91cab0c9e5e311 --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_Token_Passing_with_Task_Swapping/tpts_token.py @@ -0,0 +1,75 @@ +from ta_state import Location + +class Token: + def __init__(self): + # Keep track of the paths of all the agents + self.paths = dict() + # Keep track of which agent is executing which task + self.assignments = dict() + # Keep track of the remaining tasks + self.taskSet = [] + + ##---------## + ## Getters ## + ##---------## + + # Returns the last location on the path of each agent + def get_pathends(self, given_id=None): + pathEnds = [] + for a_id, k in self.paths.items(): + if given_id is None or a_id != given_id: + loc = k[list(k)[-1]] + pathEnds.append((Location(loc.col, loc.row, 0), a_id)) + return pathEnds + + # Get the paths of all agents except the path of agent with ID = own_id + def get_other_agents_paths(self, timestep, own_id): + other_agent_paths = [] + for a_id, path in self.paths.items(): + if a_id != own_id: + other_agent_paths.append(path) + return other_agent_paths + + ##------------------## + ## Add new elements ## + ##------------------## + + # Adds a new agent to the system + def add_agent(self, agent): + a_id = agent.id + self.paths[a_id] = dict() + self.paths[a_id][0] = agent.pos + self.assignments[a_id] = None + + # Adds a new task to the system + def add_task(self, task): + self.taskSet.append(task) + + ##-------------------## + ## Utilitary methods ## + ##-------------------## + + # Restores the token with an old state of the token + def restore(self, old_token): + self.paths = old_token.paths + self.assignments = old_token.assignments + self.taskSet = old_token.taskSet + + # Generates a copy of this token + def copy(self): + new_token = Token() + # Copy paths + new_token.paths = dict() + for a_id, path in self.paths.items(): + new_token.paths[a_id] = dict() + for t, loc in path.items(): + new_token.paths[a_id][t] = loc + # Copy assignments + new_token.assignments = dict() + for a_id, t_id in self.assignments.items(): + new_token.assignments[a_id] = t_id + # Copy tasks + new_token.taskSet = [] + for task in self.taskSet: + new_token.taskSet.append(task) + return new_token diff --git a/Algorithms/Online_Decentralized/Algorithm_test_toyexample_online_decentralized/EnvChannel.py b/Algorithms/Online_Decentralized/Algorithm_test_toyexample_online_decentralized/EnvChannel.py new file mode 100644 index 0000000000000000000000000000000000000000..b6d62add37419b9cfe1ddb9b07a70b150a07a6d7 --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_test_toyexample_online_decentralized/EnvChannel.py @@ -0,0 +1,63 @@ +""" + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +""" + +import json +from mlagents_envs.side_channel.side_channel import ( + SideChannel, + IncomingMessage, + OutgoingMessage, +) +import uuid + +from EnvironmentData import EnvironmentData + +""" +class that processes information from SideChannel EnvChannel: stores all incoming information +in an instance of class EnvironmentData +""" + + +class EnvChannel(SideChannel): + + def __init__(self) -> None: + super().__init__(uuid.UUID("621f0a70-4f87-11ea-a6bf-784f4387d1f7")) #must coincide with ChannelId set in c# + self.envData = EnvironmentData() # object that stores info on environment + + def on_message_received(self, msg: IncomingMessage) -> None: + # We simply read a string from the message and print it. + data = msg.read_string() + environment_info = json.loads(data) + + self.envData.matrix = environment_info["matrixLayout"] + self.envData.rotation = environment_info["rotationRobot"] + self.envData.size_of_action = environment_info["sizeOfAction"] + self.envData.size_of_observation = environment_info["sizeOfObservation"] + self.envData.number_of_robots = environment_info["numberOfRobotsInEnv"] + self.envData.number_of_current_tasks = environment_info["numberOfCurrentTasks"] + self.envData.can_go_backwards = environment_info["backwards"] + self.envData.random_tasks = environment_info["tasksGeneratedRandomly"] + self.envData.instance_ids = environment_info["instanceIDSRobots"] + + self.envData.set_initial_nodes_dictionary(environment_info["initialNodesOfRobots"]) + self.envData.set_tasks_to_be_assigned(environment_info["currentTasks"]) + self.envData.set_assigned_tasks() + + def send_string(self, data: str) -> None: + # Add the string to an OutgoingMessage + msg = OutgoingMessage() + msg.write_string(data) + # We call this method to queue the data we want to send + super().queue_message_to_send(msg) \ No newline at end of file diff --git a/Algorithms/Online_Decentralized/Algorithm_test_toyexample_online_decentralized/EnvironmentData.py b/Algorithms/Online_Decentralized/Algorithm_test_toyexample_online_decentralized/EnvironmentData.py new file mode 100644 index 0000000000000000000000000000000000000000..ddc7bc4ddf6d4e8de2c6a5143287a3809f728196 --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_test_toyexample_online_decentralized/EnvironmentData.py @@ -0,0 +1,101 @@ +""" + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +""" + +""" +stores data on environment +instance methods that initialize environment (used by EnvChannel) +- set_initial_nodes_dictionary(initial_nodes): initializes current_nodes_dictionary +containing current(next) nodes for each of the robots +- set_tasks_to_be_assigned(tasks): initialize tasks_to_be_assigned: tasks that have to be assigned +- set_assigned_tasks(): initialize assigned_tasks_dictionary containing + for every robot the current assigned task + +instance methods that update environment info +- assign_task(robot_instanceID, task): assign task to a given robot +- add_task_to_tasks_to_be_assigned(task): append a new task to tasks_to_be_assigned +- task_done(instance_id): remove task from robot that was assigned this task +""" + + +import json + +from Node import Node +from Task import Position, Task + + +class EnvironmentData: + + def __init__(self): + self.matrix = None + self.rotation = None + self.size_of_action = None + self.size_of_observation = None + self.number_of_robots = None + self.number_of_current_tasks = None + self.can_go_backwards = None + self.random_tasks = None # if set to true random tasks will be send whenever a task has been completed, + # otherwise all tasks self.tasks_to_be_assigned + + self.instance_ids = [] + self.current_nodes_dictionary = {} # dictionary instance_id -> current node + self.tasks_to_be_assigned = [] # tasks that are still to be assigned + self.assigned_tasks_dictionary = {} # dictionary instance_id -> assigned task + + + ######################################### + ## methods used by EnvChannel to initialize attributes: + ######################################### + + # given a correct string containing array of nodes + def set_initial_nodes_dictionary(self, initial_nodes): + for i in range(self.number_of_robots): + self.current_nodes_dictionary[self.instance_ids[i]] = Node(initial_nodes[i]["GridPosition"]["Row"], + initial_nodes[i]["GridPosition"]["Column"], + initial_nodes[i]["Degrees"]) + + # given a correct json_string containing array of tasks + def set_tasks_to_be_assigned(self, tasks): + for i in range(self.number_of_current_tasks): + pickup = Position(tasks[i]["PickUp"]["Row"], tasks[i]["PickUp"]["Column"]) + delivery = Position(tasks[i]["Delivery"]["Row"], tasks[i]["Delivery"]["Column"]) + self.tasks_to_be_assigned.append(Task(pickup, delivery)) + + # initialize dictionary robot instance_id -> task (None) + def set_assigned_tasks(self): + for i in range(self.number_of_robots): + self.assigned_tasks_dictionary[self.instance_ids[i]] = None + + ######################################### + ## methods used to update environment info + ######################################### + + # when a task is assigned to a robot, it has to be added to self.assigned_tasks + # and removed from self.tasks_to_be_assigned + # info has to be sent to unity via the correct channel + def assign_task(self, robot_instanceID, task): + self.assigned_tasks_dictionary[robot_instanceID] = task + self.tasks_to_be_assigned.remove(task) + + # when a new task is available it is added to tasks_to_be_assigned + # a check is made whether there are still tasks that can be added, but this should not be happening (diagnostical) + def add_task_to_tasks_to_be_assigned(self, task): + if len(self.tasks_to_be_assigned) == self.number_of_current_tasks: + raise Exception("cannot add more tasks") + self.tasks_to_be_assigned.append(task) + + # when a robot has finished his task it has to be removed from assigned_tasks + def task_done(self, instance_id): + self.assigned_tasks_dictionary[instance_id] = None diff --git a/Algorithms/Online_Decentralized/Algorithm_test_toyexample_online_decentralized/EnvironmentManager.py b/Algorithms/Online_Decentralized/Algorithm_test_toyexample_online_decentralized/EnvironmentManager.py new file mode 100644 index 0000000000000000000000000000000000000000..d839fb86c4c64858daad064023e5293d8de187fb --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_test_toyexample_online_decentralized/EnvironmentManager.py @@ -0,0 +1,195 @@ +""" + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +""" + +"""' +Class that contains and manages the information on the environment. +- Initializes and holds information on the environment (EnvData). +- Contains a reference to the sidechannel (EnvChannel). +- Contains a reference to the sidechannel (TaskChannel). +- Contains a reference to the unity environment (UnityEnv). +Has instance methods +- reset() which resets the environment. +- step() which assigns tasks, computes a new action based on observation from the unity environment + and sends actions back to unity, updates info environment when a task has finished +- close() which closes the environment/ + +Has also some auxiliary instance methods: +- assign_new_task() which finds a new task and a robot that is free, then calls +assign_task_to_robot(robot_instanceID, task) +- compute_path(current_node, task) which computes paths starting in current_node completing a certain task +- initialize_shortest_paths() which initializes a dictionary containing the paths robots are following +- assign_task_to_robot(robot_instanceID, task) which assigns task to a robot with given instance ID, +updates EnvData and sends information on assignment back to Unity + +Note that this a toy example. No checks are done on collisions. +""" + +import json + +from mlagents_envs.base_env import ActionTuple + +from Graph import Graph +from Node import Node + +import numpy as np + + +class EnvironmentManager: + + def __init__(self, envData, unityEnv, envChannel, taskChannel): + self.envData = envData + self.unityEnv = unityEnv + self.envChannel = envChannel + self.taskChannel = taskChannel + + # IMPORTANT: sends info through envChannel, to be called before setting up connection envData an taskChannel + self.reset() + + # taskChannel needs info on envData + self.taskChannel.environment_data = envData + + # behavior name for agent + self.behavior_name = list(unityEnv.behavior_specs.keys())[0] + + # graph that is used for computing paths + self.graph = Graph(envData.matrix, envData.rotation, envData.can_go_backwards) + + # for every robot with instanceID id shortest_paths[id] gives the shortest path to + # its currently assigned task + self.shortest_paths = {} + + self.initialize_shortest_paths() + + # step in the environment + # 1) checks if new tasks can be assigned + # 2) collect observations + # 3) compute new actions + # 4) send actions back to Unity + def step(self): + self.assign_new_task() + + # get information from the agent that requests an action + decision_steps, terminal_steps = self.unityEnv.get_steps(self.behavior_name) + + print("request is being made by") + agents = decision_steps.agent_id + print(str(len(agents)) + " agents") + + # decision_steps.obs is a list of numpy arrays, first dimension corresponds to the number of agents that has requested + # a decision (here len(agents)) + observations = decision_steps.obs + + print("----------------------------------------") + + + actions = [] # long list of all actions + action_tuple = ActionTuple() # actions to send to unity + + # create an action for all agents that request an action + for i in range(len(agents)): + observation = observations[0][i] # observation of current agent + robot_id_unity = observation[0] + row = observation[1] + column = observation[2] + degrees = observation[3] + + print("robot " + str(robot_id_unity) + " at node [(" + str(row) + "," + str(column) + ")," + str( + degrees) + "]") + + path = self.shortest_paths[robot_id_unity] + + # if path is empty, then robot should stay at same node + if len(path) == 0: + actions.extend([row, column, degrees, 0, 0]) + # if path is not empty we get next action from shortest path + else: + next_action = path[0] # is a node or "pickup" or "deliver" + if next_action == "pickup": + actions.extend([row, column, degrees, 1, 0]) + elif next_action == "deliver": + actions.extend([row, column, degrees, 0, 1]) + self.envData.assigned_tasks_dictionary[robot_id_unity] = None + else: + actions.extend([next_action.x, next_action.y, next_action.g, 0, 0]) + # update current node + self.envData.current_nodes_dictionary[robot_id_unity] = Node(next_action.x, next_action.y, + next_action.g) + # update path + self.shortest_paths[robot_id_unity] = path[1:] + + # add action to action_tuple and set the actions + actions = np.array(actions) + actions.resize(len(agents), self.envData.size_of_action) + action_tuple.add_discrete(actions) + + self.unityEnv.set_actions(self.behavior_name, action_tuple) + self.unityEnv.step() # send actions to unity and wait until a new decision is requested + + # reset the environment + def reset(self): + self.unityEnv.reset() + + # close the environment + def close(self): + self.close() + + # assigns the next available task to an idle robot, if possible + def assign_new_task(self): + # check if there are tasks that have to be assigned + # if this is the case, get first task and assign to available robot + if len(self.envData.tasks_to_be_assigned) != 0: + task = self.envData.tasks_to_be_assigned[0] + # get available robot + for robot_id in self.envData.instance_ids: + if self.envData.assigned_tasks_dictionary[robot_id] is None: + # robot is free: assign task to robot and break out of for loop + self.assign_task_to_robot(robot_id, task) + break + + + # compute path from current_node that finishes given task + # for test purposes pick up and delivery need to have rotation 0 + # at pick up delivery robot stays at same node + # returns a sequence of nodes and pick up/delivery actions + def compute_path(self, current_node, task): + path1 = self.graph.computeShortestPath(current_node, + Node(task.PickUp.Row, task.PickUp.Column, 0)) + path1 = path1[1:] + path2 = self.graph.computeShortestPath(Node(task.PickUp.Row, task.PickUp.Column, 0), + Node(task.Delivery.Row, task.Delivery.Column, 0)) + path2 = path2[1:] + + return path1 + ["pickup"] + path2 + ["deliver"] + + + # for every robot initially there is an empty path to be followed + def initialize_shortest_paths(self): + for robot_id in self.envData.instance_ids: + self.shortest_paths[robot_id] = [] + + def assign_task_to_robot(self, robot_instanceID, task): + # update envData + self.envData.assign_task(robot_instanceID, task) + # compute path for robot + self.shortest_paths[robot_instanceID] = \ + self.compute_path(self.envData.current_nodes_dictionary[robot_instanceID],task) + # send info to unity + taskDict = {"Task": { + "PickUp": {"Row": task.PickUp.Row, "Column": task.PickUp.Column}, + "Delivery": {"Row": task.Delivery.Row, "Column": task.Delivery.Column}}, + "InstanceID": robot_instanceID} + self.taskChannel.send_string(json.dumps(taskDict)) + diff --git a/Algorithms/Online_Decentralized/Algorithm_test_toyexample_online_decentralized/Graph.py b/Algorithms/Online_Decentralized/Algorithm_test_toyexample_online_decentralized/Graph.py new file mode 100644 index 0000000000000000000000000000000000000000..69e03b997172dae6855dca7f06890606239e7063 --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_test_toyexample_online_decentralized/Graph.py @@ -0,0 +1,126 @@ +""" + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +""" + +from networkx import DiGraph, shortest_path +from Node import Node + +""" +Class Graph creates a graph based on matrix, deviation (unit of rotation) and whether robots can move backwards). +Its nodes contain position in the grid and orientation wrt north (see class <c>Node</c>). +Networkx package as underlying data structure. +""" + +class Graph: + def __init__(self, matrix, deviation, cangobackwards): + self.matrix = matrix + self.number_of_rows = len(matrix) + self.number_of_columns = len(matrix[0]) + self.deviation = deviation + self.cangobackwards = cangobackwards + self.graph = DiGraph() + + for i in range(self.number_of_rows): + for j in range(self.number_of_columns): + # we have to add nodes to the graph when we encounter a number different than 1 + if matrix[i][j] != 1: + self.addEdgesByRotation(i, j) + self.addEdgesByMovingForward(i,j) + + def addEdgesByRotation(self, row, column): + degree = 0 + while degree < 360: + newnode = Node(row, column, degree) + + # add all edges from newnode staying at the same position (row, number), i.e. rotation + + # rotate left + rotateLeftNode = Node(row, column, get_degree_in_range_0_360(degree - self.deviation)) + self.graph.add_edge(newnode, rotateLeftNode) + + # rotate right + rotateRightNode = Node(row, column, get_degree_in_range_0_360(degree + self.deviation)) + self.graph.add_edge(newnode, rotateRightNode) + + degree += self.deviation + + def addEdgesByMovingForward(self, row, column): + # check left + if column > 0 and self.matrix[row][column-1] != 1: + # we can move forward if we have degree 270 + currentnode = Node(row, column, 270) + neighbourleft = Node(row, column-1, 270) + self.graph.add_edge(currentnode, neighbourleft) + # we can move backward if we have degree 90 + if self.cangobackwards: + currentnode = Node(row, column, 90) + neighbourleft = Node(row, column-1, 90) + self.graph.add_edge(currentnode, neighbourleft) + + # check right + if column < self.number_of_columns -1 and self.matrix[row][column+1] != 1: + # we can move forward if we have degree 90 + currentnode = Node(row, column, 90) + neighbourright = Node(row, column+1, 90) + self.graph.add_edge(currentnode, neighbourright) + # we can move backward if we have degree 270 + if self.cangobackwards: + currentnode = Node(row, column, 270) + neighbourright = Node(row, column+1, 270) + self.graph.add_edge(currentnode, neighbourright) + + # check up + if row > 0 and self.matrix[row-1][column] != 1: + # we can move forward if we have degree 0 + currentnode = Node(row, column, 0) + neighbourup = Node(row-1, column, 0) + self.graph.add_edge(currentnode, neighbourup) + # we can move backward if we have degree 180 + if self.cangobackwards: + currentnode = Node(row, column, 180) + neighbourup = Node(row-1, column, 180) + self.graph.add_edge(currentnode, neighbourup) + + # check down + if row < self.number_of_rows-1 and self.matrix[row+1][column] != 1: + # we can move forward if we have degree 180 + currentnode = Node(row, column, 180) + neighbourdown = Node(row+1, column, 180) + self.graph.add_edge(currentnode, neighbourdown) + # we can move backward if we have degree 0 + if self.cangobackwards: + currentnode = Node(row, column, 0) + neighbourdown = Node(row+1, column, 0) + self.graph.add_edge(currentnode, neighbourdown) + + def computeShortestPath(self, start_node, end_node): + #compute shortest path from start_node to end_node: return a list + return shortest_path(self.graph, start_node, end_node) + +def get_degree_in_range_0_360(degree): + rest = degree % 360 + if rest < 0: + return rest + 360 + return rest + + + + + + + + + + diff --git a/Algorithms/Online_Decentralized/Algorithm_test_toyexample_online_decentralized/Node.py b/Algorithms/Online_Decentralized/Algorithm_test_toyexample_online_decentralized/Node.py new file mode 100644 index 0000000000000000000000000000000000000000..126684f885f63b51edcd2b6684d26d7a847c51af --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_test_toyexample_online_decentralized/Node.py @@ -0,0 +1,57 @@ +""" + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +""" + +""" +Class Node represent nodes in the graph. Every node contains a +position (x,y) in the grid +and a rotation in degree where +0 = North +90 = East +280 = South +270 = West +all degrees must be between 0 and 360 + +attributes are set to private such that they cannot be overwritten and there is no problem with the hash +""" + +class Node: + def __init__(self,x,y,g): + self._x = x + self._y = y + self._g = g + + @property + def x(self): + return self._x + + @property + def y(self): + return self._y + + @property + def g(self): + return self._g + + + def __eq__(self, other): + return self.__class__ == other.__class__ and self.x == other.x and self.y == other.y and self.g == other.g + + + def __hash__(self): + return (((self.x * 397) ** self.y) * 397) **self.g + + def __str__(self): + return "[(" + str(self.x) + ", " + str(self.y) + ")" + "," + str(self.g) + "]" diff --git a/Algorithms/Online_Decentralized/Algorithm_test_toyexample_online_decentralized/Pipfile b/Algorithms/Online_Decentralized/Algorithm_test_toyexample_online_decentralized/Pipfile new file mode 100644 index 0000000000000000000000000000000000000000..2cf8108a7836978e89ef3320e61b72d3c4eb3be6 --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_test_toyexample_online_decentralized/Pipfile @@ -0,0 +1,14 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +networkx = "==2.5" +mlagents = "==0.23.0" +mlagents-envs = "==0.23.0" + +[dev-packages] + +[requires] +python_version = "3.6" diff --git a/Algorithms/Online_Decentralized/Algorithm_test_toyexample_online_decentralized/Task.py b/Algorithms/Online_Decentralized/Algorithm_test_toyexample_online_decentralized/Task.py new file mode 100644 index 0000000000000000000000000000000000000000..16dd163021e1d3fb53b5ea42052621255e9a7e79 --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_test_toyexample_online_decentralized/Task.py @@ -0,0 +1,50 @@ +""" + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +""" + +""" +Class Task represents tasks which consist of 2 positions: a pickup and a delivery position. +""" + +class Task: + def __init__(self, pos1, pos2): + self.PickUp = pos1 + self.Delivery = pos2 + + def __eq__(self, other): + return self.__class__ == other.__class__ and self.PickUp == other.PickUp and self.Delivery == other.Delivery + + def __hash__(self): + hash_code = hash(self.PickUp) + hash_code = (hash_code * 397) ** hash(self.Delivery) + return hash_code + + def __str__(self): + return "[" + str(self.PickUp) + ", " + str(self.Delivery) + "]" + + +class Position: + def __init__(self, x, y): + self.Row = x + self.Column = y + + def __eq__(self, other): + return self.__class__ == other.__class__ and self.Row == other.Row and self.Column == other.Column + + def __hash__(self): + return ((self.Row * 397) ** self.Column) * 397 + + def __str__(self): + return "(" + str(self.Row) + ", " + str(self.Column) + ")" diff --git a/Algorithms/Online_Decentralized/Algorithm_test_toyexample_online_decentralized/TaskSideChannel.py b/Algorithms/Online_Decentralized/Algorithm_test_toyexample_online_decentralized/TaskSideChannel.py new file mode 100644 index 0000000000000000000000000000000000000000..dd99877185ec3103f5ccda97c5352856e9745634 --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_test_toyexample_online_decentralized/TaskSideChannel.py @@ -0,0 +1,58 @@ +""" + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +""" + +import json +from mlagents_envs.side_channel.side_channel import ( + SideChannel, + IncomingMessage, + OutgoingMessage, +) +import uuid + +from Task import Task, Position + + +""" +Class that processes info from the TaskSideChannel. +- receives new tasks that have to assigned to robots +- sends assignment of tasks to robots +""" + + +class TaskSideChannel(SideChannel): + + def __init__(self) -> None: + super().__init__(uuid.UUID("c11ab982-82b8-4194-b387-3bd0fe9ebdc7")) #must coincide with ChannelId set in c# + self.environment_data = None #info on the environment + + # channel receives new tasks that have to be assigned + def on_message_received(self, msg: IncomingMessage) -> None: + data = msg.read_string() + new_task = json.loads(data) + new_task = new_task["task"] + task_to_add = Task(Position(new_task["PickUp"]["Row"], new_task["PickUp"]["Column"]), + Position(new_task["Delivery"]["Row"], new_task["Delivery"]["Column"])) + # add task to task to be assigned + self.environment_data.add_task_to_tasks_to_be_assigned(task_to_add) + + # channel sends information when a task has been assigned (to which robot) + def send_string(self, data: str) -> None: + + # Add the string to an OutgoingMessage + msg = OutgoingMessage() + msg.write_string(data) + # We call this method to queue the data we want to send + super().queue_message_to_send(msg) \ No newline at end of file diff --git a/Algorithms/Online_Decentralized/Algorithm_test_toyexample_online_decentralized/main.py b/Algorithms/Online_Decentralized/Algorithm_test_toyexample_online_decentralized/main.py new file mode 100644 index 0000000000000000000000000000000000000000..130dda386a5fd019fb5c84e3c36d457a2493b824 --- /dev/null +++ b/Algorithms/Online_Decentralized/Algorithm_test_toyexample_online_decentralized/main.py @@ -0,0 +1,44 @@ +""" + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +""" + +""" +Main file that controls decision making for the Online Centralized Pick Up and Delivery Problem +This is a toy example! +Uses EnvironmentManager who assigns tasks in order to available agents +and then computes shortest paths, no check on collisions. +""" + +from mlagents_envs.environment import UnityEnvironment +import EnvChannel, TaskSideChannel +import EnvironmentManager + +# as long as simulation_going is true, new actions will be generated + +simulation_going = True + +# setup side channels and unity environment +envChannel = EnvChannel.EnvChannel() +taskChannel = TaskSideChannel.TaskSideChannel() +env = UnityEnvironment(file_name=None, side_channels=[envChannel, taskChannel]) + +# set up environment manager +envManager = EnvironmentManager.EnvironmentManager(envChannel.envData, env, envChannel, taskChannel) + + +while simulation_going: + envManager.step() + +envManager.close() diff --git a/PickUpandDelivery/.gitignore b/PickUpandDelivery/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..8c31b4fb7a402827dadeb8e1f7881f6b62b25528 --- /dev/null +++ b/PickUpandDelivery/.gitignore @@ -0,0 +1,98 @@ +# This .gitignore file should be placed at the root of your Unity project directory +# +# Get latest from https://github.com/github/gitignore/blob/master/Unity.gitignore +# +/[Ll]ibrary/ +/[Tt]emp/ +/[Oo]bj/ +/[Bb]uild/ +/[Bb]uilds/ +/[Ll]ogs/ +/[Uu]ser[Ss]ettings/ + +# MemoryCaptures can get excessive in size. +# They also could contain extremely sensitive data +/[Mm]emoryCaptures/ + +# Asset meta data should only be ignored when the corresponding asset is also ignored +!/[Aa]ssets/**/*.meta + +# Uncomment this line if you wish to ignore the asset store tools plugin +# /[Aa]ssets/AssetStoreTools* + +# Autogenerated Jetbrains Rider plugin +/[Aa]ssets/Plugins/Editor/JetBrains* + +# Visual Studio cache directory +.vs/ + +# Gradle cache directory +.gradle/ + +# Autogenerated VS/MD/Consulo solution and project files +ExportedObj/ +.consulo/ +*.csproj +*.unityproj +*.sln +*.suo +*.tmp +*.user +*.userprefs +*.pidb +*.booproj +*.svd +*.pdb +*.mdb +*.opendb +*.VC.db + +# Unity3D generated meta files +*.pidb.meta +*.pdb.meta +*.mdb.meta + +# Unity3D generated file on crash reports +sysinfo.txt + +# Builds +*.apk +*.aab +*.unitypackage + +# Crashlytics generated file +crashlytics-build.properties + +# Packed Addressables +/[Aa]ssets/[Aa]ddressable[Aa]ssets[Dd]ata/*/*.bin* + +# Temporary auto-generated Android Assets +/[Aa]ssets/[Ss]treamingAssets/aa.meta +/[Aa]ssets/[Ss]treamingAssets/aa/* + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf +.idea/ + +# Generated files +.idea/**/contentModel.xml + +.DS_Store +__pycache__/ + + +# Extra +./build +./obj +./Logs +./Library +./Temp +./ProjectSettings + +#ML agents +/Assets/ML-Agents/Timers* + diff --git a/PickUpandDelivery/Assembly-CSharp.csproj.DotSettings b/PickUpandDelivery/Assembly-CSharp.csproj.DotSettings new file mode 100644 index 0000000000000000000000000000000000000000..b5b235a96cba87306e02eb00fa185c185f99c22f --- /dev/null +++ b/PickUpandDelivery/Assembly-CSharp.csproj.DotSettings @@ -0,0 +1,2 @@ +<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> + <s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">Default</s:String></wpf:ResourceDictionary> \ No newline at end of file diff --git a/PickUpandDelivery/Assets/Fonts.meta b/PickUpandDelivery/Assets/Fonts.meta new file mode 100644 index 0000000000000000000000000000000000000000..b21a2be7e93069be1414f4e55f2281efe2bbf640 --- /dev/null +++ b/PickUpandDelivery/Assets/Fonts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7c67c373f3538ef46bc6cad48b8fc69f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Fonts/ArialCE.ttf b/PickUpandDelivery/Assets/Fonts/ArialCE.ttf new file mode 100644 index 0000000000000000000000000000000000000000..a53879583c273432b10231e109677f10a30ee290 Binary files /dev/null and b/PickUpandDelivery/Assets/Fonts/ArialCE.ttf differ diff --git a/PickUpandDelivery/Assets/Fonts/ArialCE.ttf.meta b/PickUpandDelivery/Assets/Fonts/ArialCE.ttf.meta new file mode 100644 index 0000000000000000000000000000000000000000..b5465334c10b78ec9c2f289eb7b4e28ebb8dc6fb --- /dev/null +++ b/PickUpandDelivery/Assets/Fonts/ArialCE.ttf.meta @@ -0,0 +1,22 @@ +fileFormatVersion: 2 +guid: 424c8962f52026a4c96be91a0f9cc09d +TrueTypeFontImporter: + externalObjects: {} + serializedVersion: 4 + fontSize: 16 + forceTextureCase: -2 + characterSpacing: 0 + characterPadding: 1 + includeFontData: 1 + fontName: Arial CE + fontNames: + - Arial CE + fallbackFontReferences: [] + customCharacters: + fontRenderingMode: 0 + ascentCalculationMode: 1 + useLegacyBoundsCalculation: 0 + shouldRoundAdvanceValue: 1 + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/ML-Agents.meta b/PickUpandDelivery/Assets/ML-Agents.meta new file mode 100644 index 0000000000000000000000000000000000000000..cc6931f55431e3405539c60d283f04e4f66e768c --- /dev/null +++ b/PickUpandDelivery/Assets/ML-Agents.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1c329b599f3585243a8ef689890c9264 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Materials.meta b/PickUpandDelivery/Assets/Materials.meta new file mode 100644 index 0000000000000000000000000000000000000000..56af04ecde68ef744e07dadbee36551a03e67c20 --- /dev/null +++ b/PickUpandDelivery/Assets/Materials.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 81ccf87ab9c53bf4193803e5daa4485b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Materials/AgentBlue.mat b/PickUpandDelivery/Assets/Materials/AgentBlue.mat new file mode 100644 index 0000000000000000000000000000000000000000..98afe276c85991a80022bc840443e213ce8898c9 --- /dev/null +++ b/PickUpandDelivery/Assets/Materials/AgentBlue.mat @@ -0,0 +1,80 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: AgentBlue + m_Shader: {fileID: 47, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: _GLOSSYREFLECTIONS_OFF _SPECULARHIGHLIGHTS_OFF + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SpecGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 0 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 0 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 0.12941177, g: 0.5882353, b: 0.9529412, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/PickUpandDelivery/Assets/Materials/AgentBlue.mat.meta b/PickUpandDelivery/Assets/Materials/AgentBlue.mat.meta new file mode 100644 index 0000000000000000000000000000000000000000..8869d32d9f6cba37e1949e2cedc800dcf82623cc --- /dev/null +++ b/PickUpandDelivery/Assets/Materials/AgentBlue.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 65c786e6f7696492e9956e3b8eac5564 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Materials/Eye.mat b/PickUpandDelivery/Assets/Materials/Eye.mat new file mode 100644 index 0000000000000000000000000000000000000000..703bddeb2b720271b3f10738fb6345fe61da8e16 --- /dev/null +++ b/PickUpandDelivery/Assets/Materials/Eye.mat @@ -0,0 +1,77 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: Eye + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: _ALPHATEST_ON _GLOSSYREFLECTIONS_OFF _SPECULARHIGHLIGHTS_OFF + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: 2450 + stringTagMap: + RenderType: TransparentCutout + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 10912, guid: 0000000000000000f000000000000000, type: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 0 + - _Metallic: 0 + - _Mode: 1 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 0 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 0.058823526, g: 0.058823526, b: 0.058823526, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/PickUpandDelivery/Assets/Materials/Eye.mat.meta b/PickUpandDelivery/Assets/Materials/Eye.mat.meta new file mode 100644 index 0000000000000000000000000000000000000000..5188e4a58bd34b2e232fc93e254a36e254880ec4 --- /dev/null +++ b/PickUpandDelivery/Assets/Materials/Eye.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4ed73faac93ee4f8dbaaf5edf7376682 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Materials/Headband.mat b/PickUpandDelivery/Assets/Materials/Headband.mat new file mode 100644 index 0000000000000000000000000000000000000000..13b5854401121e714a66c0cfcac42cd501591113 --- /dev/null +++ b/PickUpandDelivery/Assets/Materials/Headband.mat @@ -0,0 +1,76 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: Headband + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 1 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 0.98039216, g: 0.6509804, b: 0.16078432, a: 1} + - _EmissionColor: {r: 0.98039216, g: 0.6509804, b: 0.16078432, a: 1} diff --git a/PickUpandDelivery/Assets/Materials/Headband.mat.meta b/PickUpandDelivery/Assets/Materials/Headband.mat.meta new file mode 100644 index 0000000000000000000000000000000000000000..59b630f9eb3a46e059d66e63e03fbd7cde324c34 --- /dev/null +++ b/PickUpandDelivery/Assets/Materials/Headband.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 651c8f7b5f94e4712bb6738769a27fed +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Materials/TextMaterial.mat b/PickUpandDelivery/Assets/Materials/TextMaterial.mat new file mode 100644 index 0000000000000000000000000000000000000000..141085a5d0bd7efa26d10945931f26118f17b6e3 --- /dev/null +++ b/PickUpandDelivery/Assets/Materials/TextMaterial.mat @@ -0,0 +1,77 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: TextMaterial + m_Shader: {fileID: 4800000, guid: 3b25d06e715175541a7601ed730df7c6, type: 3} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 2800000, guid: 424c8962f52026a4c96be91a0f9cc09d, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/PickUpandDelivery/Assets/Materials/TextMaterial.mat.meta b/PickUpandDelivery/Assets/Materials/TextMaterial.mat.meta new file mode 100644 index 0000000000000000000000000000000000000000..3d91073f2c3dc0a376f6e2c51e2c8d66b64cc80b --- /dev/null +++ b/PickUpandDelivery/Assets/Materials/TextMaterial.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9a31293b7f33d9e41811a9f5e33f80fa +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Materials/Tile.mat b/PickUpandDelivery/Assets/Materials/Tile.mat new file mode 100644 index 0000000000000000000000000000000000000000..7576715697f26ba96eb94fba81ec11eb5fc9dcd8 --- /dev/null +++ b/PickUpandDelivery/Assets/Materials/Tile.mat @@ -0,0 +1,77 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Tile + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 0.6698113, g: 0.6698113, b: 0.6698113, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/PickUpandDelivery/Assets/Materials/Tile.mat.meta b/PickUpandDelivery/Assets/Materials/Tile.mat.meta new file mode 100644 index 0000000000000000000000000000000000000000..5e00a1df9721debafcf7bd5d5c8f266f497b3d6c --- /dev/null +++ b/PickUpandDelivery/Assets/Materials/Tile.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 015f80b5c4ae946a88dafd7feae278d9 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Materials/X.mat b/PickUpandDelivery/Assets/Materials/X.mat new file mode 100644 index 0000000000000000000000000000000000000000..10e6ba7d3ebbcd4e2520fa52d84650e92128ab12 --- /dev/null +++ b/PickUpandDelivery/Assets/Materials/X.mat @@ -0,0 +1,77 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: X + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 1 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/PickUpandDelivery/Assets/Materials/X.mat.meta b/PickUpandDelivery/Assets/Materials/X.mat.meta new file mode 100644 index 0000000000000000000000000000000000000000..f56645adfdbdb4cfd6879e6f833a779b420e17a4 --- /dev/null +++ b/PickUpandDelivery/Assets/Materials/X.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c491227f9c123ab4f82f045383d91485 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Plugins.meta b/PickUpandDelivery/Assets/Plugins.meta new file mode 100644 index 0000000000000000000000000000000000000000..80031e8149bfecaf25cfecef19acec476490068f --- /dev/null +++ b/PickUpandDelivery/Assets/Plugins.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f401d27e12cbd6548b27de328ce5b37b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Plugins/Newtonsoft.Json.dll b/PickUpandDelivery/Assets/Plugins/Newtonsoft.Json.dll new file mode 100644 index 0000000000000000000000000000000000000000..3772590130fa624f93bc2ca75cbc56be2b2b00c8 Binary files /dev/null and b/PickUpandDelivery/Assets/Plugins/Newtonsoft.Json.dll differ diff --git a/PickUpandDelivery/Assets/Plugins/Newtonsoft.Json.dll.meta b/PickUpandDelivery/Assets/Plugins/Newtonsoft.Json.dll.meta new file mode 100644 index 0000000000000000000000000000000000000000..c372e408ffafd1cda11683f8d08271146e433d1d --- /dev/null +++ b/PickUpandDelivery/Assets/Plugins/Newtonsoft.Json.dll.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: b0827a2f804d24c789672af19d1683f2 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Prefabs.meta b/PickUpandDelivery/Assets/Prefabs.meta new file mode 100644 index 0000000000000000000000000000000000000000..cf19c1e3537c6f81f393e2d943b0ebfab4a0bfbd --- /dev/null +++ b/PickUpandDelivery/Assets/Prefabs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 702e69246a5bf1f4abf39e9514807a2b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Prefabs/EndPoint.prefab b/PickUpandDelivery/Assets/Prefabs/EndPoint.prefab new file mode 100644 index 0000000000000000000000000000000000000000..d8810959d79d88f1ff11372d5ebff5916a62d8d5 --- /dev/null +++ b/PickUpandDelivery/Assets/Prefabs/EndPoint.prefab @@ -0,0 +1,392 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &784985611624235947 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 357068018734814567} + - component: {fileID: 990189179575991127} + - component: {fileID: 2675203881973562991} + - component: {fileID: 6721500656427338880} + m_Layer: 0 + m_Name: x1 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &357068018734814567 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 784985611624235947} + m_LocalRotation: {x: 0, y: 0.38268343, z: 0, w: 0.92387956} + m_LocalPosition: {x: 0, y: 0.51, z: 0} + m_LocalScale: {x: 0.08, y: 0.08, z: 0.02} + m_Children: [] + m_Father: {fileID: 7903164002163363415} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 45, z: 0} +--- !u!33 &990189179575991127 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 784985611624235947} + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &2675203881973562991 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 784985611624235947} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: c491227f9c123ab4f82f045383d91485, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!64 &6721500656427338880 +MeshCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 784985611624235947} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 4 + m_Convex: 0 + m_CookingOptions: 30 + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &3537248152627339076 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2017623479251953269} + - component: {fileID: 6124382143263498424} + - component: {fileID: 8765626904929566005} + - component: {fileID: 7556388547506331738} + m_Layer: 0 + m_Name: x2 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2017623479251953269 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3537248152627339076} + m_LocalRotation: {x: 0, y: -0.38268343, z: 0, w: 0.92387956} + m_LocalPosition: {x: 0, y: 0.51, z: 0} + m_LocalScale: {x: 0.08, y: 0.08, z: 0.02} + m_Children: [] + m_Father: {fileID: 7903164002163363415} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: -45, z: 0} +--- !u!33 &6124382143263498424 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3537248152627339076} + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &8765626904929566005 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3537248152627339076} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: c491227f9c123ab4f82f045383d91485, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!64 &7556388547506331738 +MeshCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3537248152627339076} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 4 + m_Convex: 0 + m_CookingOptions: 30 + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &6314994090778056550 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7903164002163363415} + - component: {fileID: 5447487630165351505} + - component: {fileID: 4185037264137122964} + - component: {fileID: 7916022369362927641} + - component: {fileID: 6937335721257966020} + m_Layer: 0 + m_Name: EndPoint + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &7903164002163363415 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6314994090778056550} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 357068018734814567} + - {fileID: 2017623479251953269} + - {fileID: 7126322845514153872} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &5447487630165351505 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6314994090778056550} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &4185037264137122964 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6314994090778056550} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 015f80b5c4ae946a88dafd7feae278d9, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!65 &7916022369362927641 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6314994090778056550} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!114 &6937335721257966020 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6314994090778056550} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f3dcff173f5992d4db93b38be21d0d1d, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &6412298205908224070 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7126322845514153872} + - component: {fileID: 8849749889804757716} + - component: {fileID: 4644426937966420123} + m_Layer: 0 + m_Name: text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &7126322845514153872 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6412298205908224070} + m_LocalRotation: {x: 0.5, y: -0.5, z: 0.5, w: 0.5} + m_LocalPosition: {x: 0, y: 0.51, z: 0} + m_LocalScale: {x: 0.1, y: 0.1, z: 0.02} + m_Children: [] + m_Father: {fileID: 7903164002163363415} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 90, y: -90, z: 0} +--- !u!23 &8849749889804757716 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6412298205908224070} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 9a31293b7f33d9e41811a9f5e33f80fa, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!102 &4644426937966420123 +TextMesh: + serializedVersion: 3 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6412298205908224070} + m_Text: 1000 + m_OffsetZ: 0 + m_CharacterSize: 4 + m_LineSpacing: 1 + m_Anchor: 4 + m_Alignment: 1 + m_TabSize: 4 + m_FontSize: 15 + m_FontStyle: 1 + m_RichText: 1 + m_Font: {fileID: 12800000, guid: 424c8962f52026a4c96be91a0f9cc09d, type: 3} + m_Color: + serializedVersion: 2 + rgba: 4283710242 diff --git a/PickUpandDelivery/Assets/Prefabs/EndPoint.prefab.meta b/PickUpandDelivery/Assets/Prefabs/EndPoint.prefab.meta new file mode 100644 index 0000000000000000000000000000000000000000..a3492ec921a75ca5f4db1a6c81bfd3f873a0b19d --- /dev/null +++ b/PickUpandDelivery/Assets/Prefabs/EndPoint.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 8ddb9b3dc215c2b4e97741bad9ced662 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Prefabs/RobotOfflineCentralizedPrefab.prefab b/PickUpandDelivery/Assets/Prefabs/RobotOfflineCentralizedPrefab.prefab new file mode 100644 index 0000000000000000000000000000000000000000..f3b7aa72e014706001e371713d860b2286fc94f6 --- /dev/null +++ b/PickUpandDelivery/Assets/Prefabs/RobotOfflineCentralizedPrefab.prefab @@ -0,0 +1,637 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &1218265376493012 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4082575947564308} + - component: {fileID: 33986757750372936} + - component: {fileID: 23248495933290848} + m_Layer: 0 + m_Name: eye + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4082575947564308 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1218265376493012} + m_LocalRotation: {x: -0, y: 1, z: -0, w: 0} + m_LocalPosition: {x: 0.29999995, y: 0.07399994, z: 0.50040054} + m_LocalScale: {x: 0.29457998, y: 0.29457998, z: 0.29457998} + m_Children: [] + m_Father: {fileID: 4294419716796784} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0} +--- !u!33 &33986757750372936 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1218265376493012} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &23248495933290848 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1218265376493012} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 4ed73faac93ee4f8dbaaf5edf7376682, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!1 &1321468028730240 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4679453577574622} + - component: {fileID: 5294701982035410442} + m_Layer: 0 + m_Name: RobotOfflineCentralizedPrefab + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4679453577574622 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1321468028730240} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 5} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 4780098186595842} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &5294701982035410442 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1321468028730240} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 54b9a4088e4329849b24b0da23b5d39d, type: 3} + m_Name: + m_EditorClassIdentifier: + idleColor: {fileID: 2100000, guid: 65c786e6f7696492e9956e3b8eac5564, type: 2} +--- !u!1 &1424713891854676 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4780098186595842} + m_Layer: 0 + m_Name: Agent + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4780098186595842 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1424713891854676} + m_LocalRotation: {x: 0, y: 0.7071068, z: 0, w: 0.7071068} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 4294419716796784} + m_Father: {fileID: 4679453577574622} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 90, z: 0} +--- !u!1 &1619100162539582 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4425897039098228} + - component: {fileID: 33259119028337980} + - component: {fileID: 23108868206887546} + m_Layer: 0 + m_Name: mouth + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4425897039098228 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1619100162539582} + m_LocalRotation: {x: -0, y: 1, z: -0, w: 0} + m_LocalPosition: {x: 0, y: -0.18299997, z: 0.50040054} + m_LocalScale: {x: 0.27602, y: 0.042489994, z: 0.13891} + m_Children: [] + m_Father: {fileID: 4294419716796784} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0} +--- !u!33 &33259119028337980 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1619100162539582} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &23108868206887546 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1619100162539582} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 4ed73faac93ee4f8dbaaf5edf7376682, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!1 &1854695166504686 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4300192163442926} + - component: {fileID: 33165976320323760} + - component: {fileID: 23468552506669568} + m_Layer: 0 + m_Name: Headband + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4300192163442926 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1854695166504686} + m_LocalRotation: {x: -0, y: -0, z: 0.016506119, w: 0.9998638} + m_LocalPosition: {x: 0, y: 0.341, z: 0} + m_LocalScale: {x: 1.0441425, y: 0.19278127, z: 1.0441422} + m_Children: [] + m_Father: {fileID: 4294419716796784} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: -179.99998, z: 1.8920001} +--- !u!33 &33165976320323760 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1854695166504686} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &23468552506669568 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1854695166504686} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 651c8f7b5f94e4712bb6738769a27fed, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!1 &1859240399150782 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4294419716796784} + - component: {fileID: 33973749152356522} + - component: {fileID: 23340305563606254} + m_Layer: 0 + m_Name: AgentCube_Blue + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4294419716796784 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1859240399150782} + m_LocalRotation: {x: 0, y: 1, z: 0, w: 0} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 4082575947564308} + - {fileID: 4144856465265480} + - {fileID: 4425897039098228} + - {fileID: 4300192163442926} + - {fileID: 8910510863212595550} + - {fileID: 5852217119192457300} + m_Father: {fileID: 4780098186595842} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0} +--- !u!33 &33973749152356522 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1859240399150782} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &23340305563606254 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1859240399150782} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 65c786e6f7696492e9956e3b8eac5564, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!1 &1999020414315134 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4144856465265480} + - component: {fileID: 33069174244444078} + - component: {fileID: 23048386147321498} + m_Layer: 0 + m_Name: eye + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4144856465265480 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1999020414315134} + m_LocalRotation: {x: -0, y: 1, z: -0, w: 0} + m_LocalPosition: {x: -0.29999995, y: 0.07399994, z: 0.50040054} + m_LocalScale: {x: 0.29457998, y: 0.29457998, z: 0.29457998} + m_Children: [] + m_Father: {fileID: 4294419716796784} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0} +--- !u!33 &33069174244444078 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1999020414315134} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &23048386147321498 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1999020414315134} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 4ed73faac93ee4f8dbaaf5edf7376682, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!1 &5885360301775037259 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5852217119192457300} + - component: {fileID: 1187121205107757005} + - component: {fileID: 3213252032395258356} + m_Layer: 0 + m_Name: x2 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &5852217119192457300 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5885360301775037259} + m_LocalRotation: {x: -0, y: -0.38268346, z: -0, w: -0.9238795} + m_LocalPosition: {x: 0, y: 0.51, z: 0} + m_LocalScale: {x: 0.07999999, y: 0.08, z: 0.019999998} + m_Children: [] + m_Father: {fileID: 4294419716796784} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: -45, z: 0} +--- !u!33 &1187121205107757005 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5885360301775037259} + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &3213252032395258356 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5885360301775037259} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 65c786e6f7696492e9956e3b8eac5564, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!1 &6501887724070931806 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8910510863212595550} + - component: {fileID: 1257352226056678973} + - component: {fileID: 3406077584688725003} + m_Layer: 0 + m_Name: x1 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8910510863212595550 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6501887724070931806} + m_LocalRotation: {x: -0, y: -0.9238795, z: -0, w: -0.38268346} + m_LocalPosition: {x: 0, y: 0.51, z: 0} + m_LocalScale: {x: 0.08, y: 0.08, z: 0.02} + m_Children: [] + m_Father: {fileID: 4294419716796784} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 45, z: 0} +--- !u!33 &1257352226056678973 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6501887724070931806} + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &3406077584688725003 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6501887724070931806} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 65c786e6f7696492e9956e3b8eac5564, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 diff --git a/PickUpandDelivery/Assets/Prefabs/RobotOfflineCentralizedPrefab.prefab.meta b/PickUpandDelivery/Assets/Prefabs/RobotOfflineCentralizedPrefab.prefab.meta new file mode 100644 index 0000000000000000000000000000000000000000..6ee54b59b9beede9bbe751dc8012125e8b2838f6 --- /dev/null +++ b/PickUpandDelivery/Assets/Prefabs/RobotOfflineCentralizedPrefab.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: eaded20e79e164040a7073677ba44c47 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Prefabs/RobotOfflineDecentralizedPrefab.prefab b/PickUpandDelivery/Assets/Prefabs/RobotOfflineDecentralizedPrefab.prefab new file mode 100644 index 0000000000000000000000000000000000000000..b8f041d4a5ac648ed652f62045ab68bf6bc2a7ac --- /dev/null +++ b/PickUpandDelivery/Assets/Prefabs/RobotOfflineDecentralizedPrefab.prefab @@ -0,0 +1,672 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &1218265376493012 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4082575947564308} + - component: {fileID: 33986757750372936} + - component: {fileID: 23248495933290848} + m_Layer: 0 + m_Name: eye + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4082575947564308 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1218265376493012} + m_LocalRotation: {x: -0, y: 1, z: -0, w: 0} + m_LocalPosition: {x: 0.29999995, y: 0.07399994, z: 0.50040054} + m_LocalScale: {x: 0.29457998, y: 0.29457998, z: 0.29457998} + m_Children: [] + m_Father: {fileID: 4294419716796784} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0} +--- !u!33 &33986757750372936 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1218265376493012} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &23248495933290848 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1218265376493012} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 4ed73faac93ee4f8dbaaf5edf7376682, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!1 &1321468028730240 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4679453577574622} + - component: {fileID: 163425050273668575} + - component: {fileID: -4965312288568279513} + m_Layer: 0 + m_Name: RobotOfflineDecentralizedPrefab + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4679453577574622 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1321468028730240} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 5} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 4780098186595842} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &163425050273668575 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1321468028730240} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e224beeb8f8781f479c65279d3e07a01, type: 3} + m_Name: + m_EditorClassIdentifier: + agentParameters: + maxStep: 0 + hasUpgradedFromAgentParameters: 1 + MaxStep: 0 + idleColor: {fileID: 2100000, guid: 65c786e6f7696492e9956e3b8eac5564, type: 2} +--- !u!114 &-4965312288568279513 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1321468028730240} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5d1c4e0b1822b495aa52bc52839ecb30, type: 3} + m_Name: + m_EditorClassIdentifier: + m_BrainParameters: + VectorObservationSize: 4 + NumStackedVectorObservations: 1 + m_ActionSpec: + m_NumContinuousActions: 0 + BranchSizes: 0000000000000000000000000000000000000000 + VectorActionSize: 0000000000000000000000000000000000000000 + VectorActionDescriptions: [] + VectorActionSpaceType: 0 + hasUpgradedBrainParametersWithActionSpec: 1 + m_Model: {fileID: 0} + m_InferenceDevice: 0 + m_BehaviorType: 0 + m_BehaviorName: RobotBehavior + TeamId: 0 + m_UseChildSensors: 1 + m_UseChildActuators: 1 + m_ObservableAttributeHandling: 0 +--- !u!1 &1424713891854676 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4780098186595842} + m_Layer: 0 + m_Name: Agent + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4780098186595842 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1424713891854676} + m_LocalRotation: {x: 0, y: 0.7071068, z: 0, w: 0.7071068} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 4294419716796784} + m_Father: {fileID: 4679453577574622} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 90, z: 0} +--- !u!1 &1619100162539582 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4425897039098228} + - component: {fileID: 33259119028337980} + - component: {fileID: 23108868206887546} + m_Layer: 0 + m_Name: mouth + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4425897039098228 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1619100162539582} + m_LocalRotation: {x: -0, y: 1, z: -0, w: 0} + m_LocalPosition: {x: 0, y: -0.18299997, z: 0.50040054} + m_LocalScale: {x: 0.27602, y: 0.042489994, z: 0.13891} + m_Children: [] + m_Father: {fileID: 4294419716796784} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0} +--- !u!33 &33259119028337980 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1619100162539582} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &23108868206887546 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1619100162539582} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 4ed73faac93ee4f8dbaaf5edf7376682, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!1 &1854695166504686 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4300192163442926} + - component: {fileID: 33165976320323760} + - component: {fileID: 23468552506669568} + m_Layer: 0 + m_Name: Headband + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4300192163442926 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1854695166504686} + m_LocalRotation: {x: -0, y: -0, z: 0.016506119, w: 0.9998638} + m_LocalPosition: {x: 0, y: 0.341, z: 0} + m_LocalScale: {x: 1.0441425, y: 0.19278127, z: 1.0441422} + m_Children: [] + m_Father: {fileID: 4294419716796784} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: -179.99998, z: 1.8920001} +--- !u!33 &33165976320323760 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1854695166504686} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &23468552506669568 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1854695166504686} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 651c8f7b5f94e4712bb6738769a27fed, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!1 &1859240399150782 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4294419716796784} + - component: {fileID: 33973749152356522} + - component: {fileID: 23340305563606254} + m_Layer: 0 + m_Name: AgentCube_Blue + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4294419716796784 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1859240399150782} + m_LocalRotation: {x: 0, y: 1, z: 0, w: 0} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 4082575947564308} + - {fileID: 4144856465265480} + - {fileID: 4425897039098228} + - {fileID: 4300192163442926} + - {fileID: 8910510863212595550} + - {fileID: 5852217119192457300} + m_Father: {fileID: 4780098186595842} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0} +--- !u!33 &33973749152356522 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1859240399150782} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &23340305563606254 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1859240399150782} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 65c786e6f7696492e9956e3b8eac5564, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!1 &1999020414315134 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4144856465265480} + - component: {fileID: 33069174244444078} + - component: {fileID: 23048386147321498} + m_Layer: 0 + m_Name: eye + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4144856465265480 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1999020414315134} + m_LocalRotation: {x: -0, y: 1, z: -0, w: 0} + m_LocalPosition: {x: -0.29999995, y: 0.07399994, z: 0.50040054} + m_LocalScale: {x: 0.29457998, y: 0.29457998, z: 0.29457998} + m_Children: [] + m_Father: {fileID: 4294419716796784} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0} +--- !u!33 &33069174244444078 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1999020414315134} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &23048386147321498 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1999020414315134} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 4ed73faac93ee4f8dbaaf5edf7376682, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!1 &5885360301775037259 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5852217119192457300} + - component: {fileID: 1187121205107757005} + - component: {fileID: 3213252032395258356} + m_Layer: 0 + m_Name: x2 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &5852217119192457300 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5885360301775037259} + m_LocalRotation: {x: -0, y: -0.38268346, z: -0, w: -0.9238795} + m_LocalPosition: {x: 0, y: 0.51, z: 0} + m_LocalScale: {x: 0.07999999, y: 0.08, z: 0.019999998} + m_Children: [] + m_Father: {fileID: 4294419716796784} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: -45, z: 0} +--- !u!33 &1187121205107757005 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5885360301775037259} + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &3213252032395258356 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5885360301775037259} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 65c786e6f7696492e9956e3b8eac5564, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!1 &6501887724070931806 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8910510863212595550} + - component: {fileID: 1257352226056678973} + - component: {fileID: 3406077584688725003} + m_Layer: 0 + m_Name: x1 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8910510863212595550 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6501887724070931806} + m_LocalRotation: {x: -0, y: -0.9238795, z: -0, w: -0.38268346} + m_LocalPosition: {x: 0, y: 0.51, z: 0} + m_LocalScale: {x: 0.08, y: 0.08, z: 0.02} + m_Children: [] + m_Father: {fileID: 4294419716796784} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 45, z: 0} +--- !u!33 &1257352226056678973 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6501887724070931806} + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &3406077584688725003 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6501887724070931806} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 65c786e6f7696492e9956e3b8eac5564, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 diff --git a/PickUpandDelivery/Assets/Prefabs/RobotOfflineDecentralizedPrefab.prefab.meta b/PickUpandDelivery/Assets/Prefabs/RobotOfflineDecentralizedPrefab.prefab.meta new file mode 100644 index 0000000000000000000000000000000000000000..c50e4611c0e30c7c613e0ea95ba3435560b38619 --- /dev/null +++ b/PickUpandDelivery/Assets/Prefabs/RobotOfflineDecentralizedPrefab.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 832f1310dfa5fd24dac021345a803d31 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Prefabs/RobotOnlineCentralizedPrefab.prefab b/PickUpandDelivery/Assets/Prefabs/RobotOnlineCentralizedPrefab.prefab new file mode 100644 index 0000000000000000000000000000000000000000..4f0a711db9f2324f9eb9c2503987ea4ef129d856 --- /dev/null +++ b/PickUpandDelivery/Assets/Prefabs/RobotOnlineCentralizedPrefab.prefab @@ -0,0 +1,637 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &1218265376493012 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4082575947564308} + - component: {fileID: 33986757750372936} + - component: {fileID: 23248495933290848} + m_Layer: 0 + m_Name: eye + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4082575947564308 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1218265376493012} + m_LocalRotation: {x: -0, y: 1, z: -0, w: 0} + m_LocalPosition: {x: 0.29999995, y: 0.07399994, z: 0.50040054} + m_LocalScale: {x: 0.29457998, y: 0.29457998, z: 0.29457998} + m_Children: [] + m_Father: {fileID: 4294419716796784} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0} +--- !u!33 &33986757750372936 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1218265376493012} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &23248495933290848 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1218265376493012} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 4ed73faac93ee4f8dbaaf5edf7376682, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!1 &1321468028730240 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4679453577574622} + - component: {fileID: -6752361495951348029} + m_Layer: 0 + m_Name: RobotOnlineCentralizedPrefab + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4679453577574622 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1321468028730240} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 5} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 4780098186595842} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &-6752361495951348029 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1321468028730240} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0ee9f4e10c142784c91290b59532cb09, type: 3} + m_Name: + m_EditorClassIdentifier: + idleColor: {fileID: 2100000, guid: 65c786e6f7696492e9956e3b8eac5564, type: 2} +--- !u!1 &1424713891854676 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4780098186595842} + m_Layer: 0 + m_Name: Agent + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4780098186595842 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1424713891854676} + m_LocalRotation: {x: 0, y: 0.7071068, z: 0, w: 0.7071068} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 4294419716796784} + m_Father: {fileID: 4679453577574622} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 90, z: 0} +--- !u!1 &1619100162539582 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4425897039098228} + - component: {fileID: 33259119028337980} + - component: {fileID: 23108868206887546} + m_Layer: 0 + m_Name: mouth + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4425897039098228 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1619100162539582} + m_LocalRotation: {x: -0, y: 1, z: -0, w: 0} + m_LocalPosition: {x: 0, y: -0.18299997, z: 0.50040054} + m_LocalScale: {x: 0.27602, y: 0.042489994, z: 0.13891} + m_Children: [] + m_Father: {fileID: 4294419716796784} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0} +--- !u!33 &33259119028337980 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1619100162539582} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &23108868206887546 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1619100162539582} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 4ed73faac93ee4f8dbaaf5edf7376682, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!1 &1854695166504686 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4300192163442926} + - component: {fileID: 33165976320323760} + - component: {fileID: 23468552506669568} + m_Layer: 0 + m_Name: Headband + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4300192163442926 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1854695166504686} + m_LocalRotation: {x: -0, y: -0, z: 0.016506119, w: 0.9998638} + m_LocalPosition: {x: 0, y: 0.341, z: 0} + m_LocalScale: {x: 1.0441425, y: 0.19278127, z: 1.0441422} + m_Children: [] + m_Father: {fileID: 4294419716796784} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: -179.99998, z: 1.8920001} +--- !u!33 &33165976320323760 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1854695166504686} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &23468552506669568 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1854695166504686} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 651c8f7b5f94e4712bb6738769a27fed, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!1 &1859240399150782 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4294419716796784} + - component: {fileID: 33973749152356522} + - component: {fileID: 23340305563606254} + m_Layer: 0 + m_Name: AgentCube_Blue + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4294419716796784 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1859240399150782} + m_LocalRotation: {x: 0, y: 1, z: 0, w: 0} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 4082575947564308} + - {fileID: 4144856465265480} + - {fileID: 4425897039098228} + - {fileID: 4300192163442926} + - {fileID: 8910510863212595550} + - {fileID: 5852217119192457300} + m_Father: {fileID: 4780098186595842} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0} +--- !u!33 &33973749152356522 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1859240399150782} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &23340305563606254 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1859240399150782} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 65c786e6f7696492e9956e3b8eac5564, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!1 &1999020414315134 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4144856465265480} + - component: {fileID: 33069174244444078} + - component: {fileID: 23048386147321498} + m_Layer: 0 + m_Name: eye + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4144856465265480 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1999020414315134} + m_LocalRotation: {x: -0, y: 1, z: -0, w: 0} + m_LocalPosition: {x: -0.29999995, y: 0.07399994, z: 0.50040054} + m_LocalScale: {x: 0.29457998, y: 0.29457998, z: 0.29457998} + m_Children: [] + m_Father: {fileID: 4294419716796784} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0} +--- !u!33 &33069174244444078 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1999020414315134} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &23048386147321498 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1999020414315134} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 4ed73faac93ee4f8dbaaf5edf7376682, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!1 &5885360301775037259 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5852217119192457300} + - component: {fileID: 1187121205107757005} + - component: {fileID: 3213252032395258356} + m_Layer: 0 + m_Name: x2 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &5852217119192457300 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5885360301775037259} + m_LocalRotation: {x: -0, y: -0.38268346, z: -0, w: -0.9238795} + m_LocalPosition: {x: 0, y: 0.51, z: 0} + m_LocalScale: {x: 0.07999999, y: 0.08, z: 0.019999998} + m_Children: [] + m_Father: {fileID: 4294419716796784} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: -45, z: 0} +--- !u!33 &1187121205107757005 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5885360301775037259} + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &3213252032395258356 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5885360301775037259} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 65c786e6f7696492e9956e3b8eac5564, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!1 &6501887724070931806 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8910510863212595550} + - component: {fileID: 1257352226056678973} + - component: {fileID: 3406077584688725003} + m_Layer: 0 + m_Name: x1 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8910510863212595550 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6501887724070931806} + m_LocalRotation: {x: -0, y: -0.9238795, z: -0, w: -0.38268346} + m_LocalPosition: {x: 0, y: 0.51, z: 0} + m_LocalScale: {x: 0.08, y: 0.08, z: 0.02} + m_Children: [] + m_Father: {fileID: 4294419716796784} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 45, z: 0} +--- !u!33 &1257352226056678973 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6501887724070931806} + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &3406077584688725003 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6501887724070931806} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 65c786e6f7696492e9956e3b8eac5564, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 diff --git a/PickUpandDelivery/Assets/Prefabs/RobotOnlineCentralizedPrefab.prefab.meta b/PickUpandDelivery/Assets/Prefabs/RobotOnlineCentralizedPrefab.prefab.meta new file mode 100644 index 0000000000000000000000000000000000000000..c2b861d943c47cc4fef5534d555c69ebf93ca3df --- /dev/null +++ b/PickUpandDelivery/Assets/Prefabs/RobotOnlineCentralizedPrefab.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 189960379d04e524eb29a18f9c0de39d +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Prefabs/RobotOnlineDecentralizedPrefab.prefab b/PickUpandDelivery/Assets/Prefabs/RobotOnlineDecentralizedPrefab.prefab new file mode 100644 index 0000000000000000000000000000000000000000..f625865c56f7df353343eb26f3cf8c4bf0ceecb7 --- /dev/null +++ b/PickUpandDelivery/Assets/Prefabs/RobotOnlineDecentralizedPrefab.prefab @@ -0,0 +1,673 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &1218265376493012 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4082575947564308} + - component: {fileID: 33986757750372936} + - component: {fileID: 23248495933290848} + m_Layer: 0 + m_Name: eye + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4082575947564308 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1218265376493012} + m_LocalRotation: {x: -0, y: 1, z: -0, w: 0} + m_LocalPosition: {x: 0.29999995, y: 0.07399994, z: 0.50040054} + m_LocalScale: {x: 0.29457998, y: 0.29457998, z: 0.29457998} + m_Children: [] + m_Father: {fileID: 4294419716796784} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0} +--- !u!33 &33986757750372936 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1218265376493012} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &23248495933290848 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1218265376493012} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 4ed73faac93ee4f8dbaaf5edf7376682, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!1 &1321468028730240 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4679453577574622} + - component: {fileID: 6178260321861954731} + - component: {fileID: -4965312288568279513} + m_Layer: 0 + m_Name: 3DBall + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4679453577574622 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1321468028730240} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 5} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 4780098186595842} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &6178260321861954731 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1321468028730240} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 388587dedc7732c449a7c4461107ddc3, type: 3} + m_Name: + m_EditorClassIdentifier: + agentParameters: + maxStep: 0 + hasUpgradedFromAgentParameters: 1 + MaxStep: 0 + simulationManager: {fileID: 0} + idleColor: {fileID: 2100000, guid: 65c786e6f7696492e9956e3b8eac5564, type: 2} +--- !u!114 &-4965312288568279513 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1321468028730240} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5d1c4e0b1822b495aa52bc52839ecb30, type: 3} + m_Name: + m_EditorClassIdentifier: + m_BrainParameters: + VectorObservationSize: 4 + NumStackedVectorObservations: 1 + m_ActionSpec: + m_NumContinuousActions: 0 + BranchSizes: 0000000000000000000000000000000000000000 + VectorActionSize: 0000000000000000000000000000000000000000 + VectorActionDescriptions: [] + VectorActionSpaceType: 0 + hasUpgradedBrainParametersWithActionSpec: 1 + m_Model: {fileID: 0} + m_InferenceDevice: 0 + m_BehaviorType: 0 + m_BehaviorName: RobotBehavior + TeamId: 0 + m_UseChildSensors: 1 + m_UseChildActuators: 1 + m_ObservableAttributeHandling: 0 +--- !u!1 &1424713891854676 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4780098186595842} + m_Layer: 0 + m_Name: Agent + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4780098186595842 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1424713891854676} + m_LocalRotation: {x: 0, y: 0.7071068, z: 0, w: 0.7071068} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 4294419716796784} + m_Father: {fileID: 4679453577574622} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 90, z: 0} +--- !u!1 &1619100162539582 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4425897039098228} + - component: {fileID: 33259119028337980} + - component: {fileID: 23108868206887546} + m_Layer: 0 + m_Name: mouth + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4425897039098228 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1619100162539582} + m_LocalRotation: {x: -0, y: 1, z: -0, w: 0} + m_LocalPosition: {x: 0, y: -0.18299997, z: 0.50040054} + m_LocalScale: {x: 0.27602, y: 0.042489994, z: 0.13891} + m_Children: [] + m_Father: {fileID: 4294419716796784} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0} +--- !u!33 &33259119028337980 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1619100162539582} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &23108868206887546 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1619100162539582} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 4ed73faac93ee4f8dbaaf5edf7376682, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!1 &1854695166504686 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4300192163442926} + - component: {fileID: 33165976320323760} + - component: {fileID: 23468552506669568} + m_Layer: 0 + m_Name: Headband + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4300192163442926 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1854695166504686} + m_LocalRotation: {x: -0, y: -0, z: 0.016506119, w: 0.9998638} + m_LocalPosition: {x: 0, y: 0.341, z: 0} + m_LocalScale: {x: 1.0441425, y: 0.19278127, z: 1.0441422} + m_Children: [] + m_Father: {fileID: 4294419716796784} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: -179.99998, z: 1.8920001} +--- !u!33 &33165976320323760 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1854695166504686} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &23468552506669568 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1854695166504686} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 651c8f7b5f94e4712bb6738769a27fed, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!1 &1859240399150782 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4294419716796784} + - component: {fileID: 33973749152356522} + - component: {fileID: 23340305563606254} + m_Layer: 0 + m_Name: AgentCube_Blue + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4294419716796784 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1859240399150782} + m_LocalRotation: {x: 0, y: 1, z: 0, w: 0} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 4082575947564308} + - {fileID: 4144856465265480} + - {fileID: 4425897039098228} + - {fileID: 4300192163442926} + - {fileID: 8910510863212595550} + - {fileID: 5852217119192457300} + m_Father: {fileID: 4780098186595842} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0} +--- !u!33 &33973749152356522 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1859240399150782} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &23340305563606254 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1859240399150782} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 65c786e6f7696492e9956e3b8eac5564, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!1 &1999020414315134 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4144856465265480} + - component: {fileID: 33069174244444078} + - component: {fileID: 23048386147321498} + m_Layer: 0 + m_Name: eye + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4144856465265480 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1999020414315134} + m_LocalRotation: {x: -0, y: 1, z: -0, w: 0} + m_LocalPosition: {x: -0.29999995, y: 0.07399994, z: 0.50040054} + m_LocalScale: {x: 0.29457998, y: 0.29457998, z: 0.29457998} + m_Children: [] + m_Father: {fileID: 4294419716796784} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0} +--- !u!33 &33069174244444078 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1999020414315134} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &23048386147321498 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1999020414315134} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 4ed73faac93ee4f8dbaaf5edf7376682, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!1 &5885360301775037259 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5852217119192457300} + - component: {fileID: 1187121205107757005} + - component: {fileID: 3213252032395258356} + m_Layer: 0 + m_Name: x2 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &5852217119192457300 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5885360301775037259} + m_LocalRotation: {x: -0, y: -0.38268346, z: -0, w: -0.9238795} + m_LocalPosition: {x: 0, y: 0.51, z: 0} + m_LocalScale: {x: 0.07999999, y: 0.08, z: 0.019999998} + m_Children: [] + m_Father: {fileID: 4294419716796784} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: -45, z: 0} +--- !u!33 &1187121205107757005 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5885360301775037259} + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &3213252032395258356 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5885360301775037259} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 65c786e6f7696492e9956e3b8eac5564, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!1 &6501887724070931806 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8910510863212595550} + - component: {fileID: 1257352226056678973} + - component: {fileID: 3406077584688725003} + m_Layer: 0 + m_Name: x1 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8910510863212595550 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6501887724070931806} + m_LocalRotation: {x: -0, y: -0.9238795, z: -0, w: -0.38268346} + m_LocalPosition: {x: 0, y: 0.51, z: 0} + m_LocalScale: {x: 0.08, y: 0.08, z: 0.02} + m_Children: [] + m_Father: {fileID: 4294419716796784} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 45, z: 0} +--- !u!33 &1257352226056678973 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6501887724070931806} + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &3406077584688725003 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6501887724070931806} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 65c786e6f7696492e9956e3b8eac5564, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 diff --git a/PickUpandDelivery/Assets/Prefabs/RobotOnlineDecentralizedPrefab.prefab.meta b/PickUpandDelivery/Assets/Prefabs/RobotOnlineDecentralizedPrefab.prefab.meta new file mode 100644 index 0000000000000000000000000000000000000000..08858463e7adb58ab8c97e8463e9a81004cb8539 --- /dev/null +++ b/PickUpandDelivery/Assets/Prefabs/RobotOnlineDecentralizedPrefab.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 5b62ae8d6539a4637bba603a6015fe86 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Prefabs/TileWall.prefab b/PickUpandDelivery/Assets/Prefabs/TileWall.prefab new file mode 100644 index 0000000000000000000000000000000000000000..8d74658f79515f356361820ff32ef19466def618 --- /dev/null +++ b/PickUpandDelivery/Assets/Prefabs/TileWall.prefab @@ -0,0 +1,95 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &7692220640868168301 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5136915043093844274} + - component: {fileID: 639462588314027066} + - component: {fileID: 1131881454912184682} + - component: {fileID: 6436653372698916071} + m_Layer: 0 + m_Name: TileWall + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &5136915043093844274 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7692220640868168301} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 4.369123, y: -0.5599309, z: 6.53695} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &639462588314027066 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7692220640868168301} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &1131881454912184682 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7692220640868168301} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 015f80b5c4ae946a88dafd7feae278d9, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!65 &6436653372698916071 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7692220640868168301} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} diff --git a/PickUpandDelivery/Assets/Prefabs/TileWall.prefab.meta b/PickUpandDelivery/Assets/Prefabs/TileWall.prefab.meta new file mode 100644 index 0000000000000000000000000000000000000000..c7c7cddf35081d2524be13daaef24e85b0d3e1f3 --- /dev/null +++ b/PickUpandDelivery/Assets/Prefabs/TileWall.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: de70788c970f16940b9f517cf39194b0 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scenes.meta b/PickUpandDelivery/Assets/Scenes.meta new file mode 100644 index 0000000000000000000000000000000000000000..4a2d7e549e1b886de946a48bcefcb5ee594909de --- /dev/null +++ b/PickUpandDelivery/Assets/Scenes.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 45802cab3f0230a4aac55237b4131b37 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scenes/Offline_Centralized.unity b/PickUpandDelivery/Assets/Scenes/Offline_Centralized.unity new file mode 100644 index 0000000000000000000000000000000000000000..88af974c39cab3b2fccd16b2f6187492ebd3c23b --- /dev/null +++ b/PickUpandDelivery/Assets/Scenes/Offline_Centralized.unity @@ -0,0 +1,442 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 705507994} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 500 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 2 + m_PVRDenoiserTypeDirect: 0 + m_PVRDenoiserTypeIndirect: 0 + m_PVRDenoiserTypeAO: 0 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 1 +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &93153075 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 93153076} + - component: {fileID: 93153077} + - component: {fileID: 93153078} + m_Layer: 0 + m_Name: SimulationController + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &93153076 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 93153075} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &93153077 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 93153075} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: ec6a5fb578df5504186ba78f15f70a56, type: 3} + m_Name: + m_EditorClassIdentifier: + agentParameters: + maxStep: 0 + hasUpgradedFromAgentParameters: 1 + MaxStep: 0 + robotPrefab: {fileID: 1321468028730240, guid: eaded20e79e164040a7073677ba44c47, + type: 3} +--- !u!114 &93153078 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 93153075} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5d1c4e0b1822b495aa52bc52839ecb30, type: 3} + m_Name: + m_EditorClassIdentifier: + m_BrainParameters: + VectorObservationSize: 1 + NumStackedVectorObservations: 1 + m_ActionSpec: + m_NumContinuousActions: 0 + BranchSizes: 01000000 + VectorActionSize: 01000000 + VectorActionDescriptions: [] + VectorActionSpaceType: 0 + hasUpgradedBrainParametersWithActionSpec: 1 + m_Model: {fileID: 0} + m_InferenceDevice: 0 + m_BehaviorType: 0 + m_BehaviorName: My Behavior + TeamId: 0 + m_UseChildSensors: 1 + m_UseChildActuators: 1 + m_ObservableAttributeHandling: 0 +--- !u!1 &225044881 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 225044882} + - component: {fileID: 225044883} + m_Layer: 0 + m_Name: Floor + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &225044882 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 225044881} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &225044883 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 225044881} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a74be3508dbe36342858e20cec768f98, type: 3} + m_Name: + m_EditorClassIdentifier: + tileWallPrefab: {fileID: 7692220640868168301, guid: de70788c970f16940b9f517cf39194b0, + type: 3} + endPointPrefab: {fileID: 6314994090778056550, guid: 8ddb9b3dc215c2b4e97741bad9ced662, + type: 3} + mainCamera: {fileID: 963194227} + SimulationController: {fileID: 93153077} +--- !u!1 &705507993 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 705507995} + - component: {fileID: 705507994} + m_Layer: 0 + m_Name: Directional Light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &705507994 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 705507993} + m_Enabled: 1 + serializedVersion: 10 + m_Type: 1 + m_Shape: 0 + m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} + m_Intensity: 1 + m_Range: 10 + m_SpotAngle: 30 + m_InnerSpotAngle: 21.80208 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 1 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &705507995 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 705507993} + m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} + m_LocalPosition: {x: 0, y: 3, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} +--- !u!1 &963194225 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 963194228} + - component: {fileID: 963194227} + - component: {fileID: 963194226} + - component: {fileID: 963194229} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &963194226 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 963194225} + m_Enabled: 1 +--- !u!20 &963194227 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 963194225} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &963194228 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 963194225} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &963194229 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 963194225} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 208230689b9953844af11c709edefaea, type: 3} + m_Name: + m_EditorClassIdentifier: + speed: 0.5 + sensitivity: 1 diff --git a/PickUpandDelivery/Assets/Scenes/Offline_Centralized.unity.meta b/PickUpandDelivery/Assets/Scenes/Offline_Centralized.unity.meta new file mode 100644 index 0000000000000000000000000000000000000000..851ee36aca9bd0405c1a655119551adcaf2c0e2d --- /dev/null +++ b/PickUpandDelivery/Assets/Scenes/Offline_Centralized.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 767a15f082bfafb48aa82817daae4814 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scenes/Offline_Decentralized.unity b/PickUpandDelivery/Assets/Scenes/Offline_Decentralized.unity new file mode 100644 index 0000000000000000000000000000000000000000..915201ed05470990b51451e7e5e6d692b321ca06 --- /dev/null +++ b/PickUpandDelivery/Assets/Scenes/Offline_Decentralized.unity @@ -0,0 +1,407 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 705507994} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 500 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 2 + m_PVRDenoiserTypeDirect: 0 + m_PVRDenoiserTypeIndirect: 0 + m_PVRDenoiserTypeAO: 0 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 1 +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &93153075 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 93153076} + - component: {fileID: 93153077} + m_Layer: 0 + m_Name: SimulationController + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &93153076 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 93153075} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &93153077 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 93153075} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 00bf636c107a31d489dc615292930654, type: 3} + m_Name: + m_EditorClassIdentifier: + robotPrefab: {fileID: 1321468028730240, guid: 832f1310dfa5fd24dac021345a803d31, + type: 3} +--- !u!1 &225044881 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 225044882} + - component: {fileID: 225044883} + m_Layer: 0 + m_Name: Floor + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &225044882 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 225044881} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &225044883 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 225044881} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a74be3508dbe36342858e20cec768f98, type: 3} + m_Name: + m_EditorClassIdentifier: + tileWallPrefab: {fileID: 7692220640868168301, guid: de70788c970f16940b9f517cf39194b0, + type: 3} + endPointPrefab: {fileID: 6314994090778056550, guid: 8ddb9b3dc215c2b4e97741bad9ced662, + type: 3} + mainCamera: {fileID: 963194227} + SimulationController: {fileID: 93153077} +--- !u!1 &705507993 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 705507995} + - component: {fileID: 705507994} + m_Layer: 0 + m_Name: Directional Light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &705507994 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 705507993} + m_Enabled: 1 + serializedVersion: 10 + m_Type: 1 + m_Shape: 0 + m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} + m_Intensity: 1 + m_Range: 10 + m_SpotAngle: 30 + m_InnerSpotAngle: 21.80208 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 1 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &705507995 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 705507993} + m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} + m_LocalPosition: {x: 0, y: 3, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} +--- !u!1 &963194225 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 963194228} + - component: {fileID: 963194227} + - component: {fileID: 963194226} + - component: {fileID: 963194229} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &963194226 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 963194225} + m_Enabled: 1 +--- !u!20 &963194227 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 963194225} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &963194228 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 963194225} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &963194229 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 963194225} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 208230689b9953844af11c709edefaea, type: 3} + m_Name: + m_EditorClassIdentifier: + speed: 0.5 + sensitivity: 1 diff --git a/PickUpandDelivery/Assets/Scenes/Offline_Decentralized.unity.meta b/PickUpandDelivery/Assets/Scenes/Offline_Decentralized.unity.meta new file mode 100644 index 0000000000000000000000000000000000000000..b06ed74695c8997d984daefe1b020d57f50b511d --- /dev/null +++ b/PickUpandDelivery/Assets/Scenes/Offline_Decentralized.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 4d6a107688c48a745813862826c4aed6 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scenes/Online_Centralized.unity b/PickUpandDelivery/Assets/Scenes/Online_Centralized.unity new file mode 100644 index 0000000000000000000000000000000000000000..9f265bb5b0a1beaa578f17a12abb7a06d2710d03 --- /dev/null +++ b/PickUpandDelivery/Assets/Scenes/Online_Centralized.unity @@ -0,0 +1,442 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 705507994} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 500 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 2 + m_PVRDenoiserTypeDirect: 0 + m_PVRDenoiserTypeIndirect: 0 + m_PVRDenoiserTypeAO: 0 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 1 +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &93153075 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 93153076} + - component: {fileID: 93153077} + - component: {fileID: 93153078} + m_Layer: 0 + m_Name: SimulationController + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &93153076 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 93153075} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &93153077 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 93153075} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e6bf74ca92d023a4dadefd09723b6558, type: 3} + m_Name: + m_EditorClassIdentifier: + agentParameters: + maxStep: 0 + hasUpgradedFromAgentParameters: 1 + MaxStep: 0 + robotPrefab: {fileID: 1321468028730240, guid: 189960379d04e524eb29a18f9c0de39d, + type: 3} +--- !u!114 &93153078 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 93153075} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5d1c4e0b1822b495aa52bc52839ecb30, type: 3} + m_Name: + m_EditorClassIdentifier: + m_BrainParameters: + VectorObservationSize: 1 + NumStackedVectorObservations: 1 + m_ActionSpec: + m_NumContinuousActions: 0 + BranchSizes: 01000000 + VectorActionSize: 01000000 + VectorActionDescriptions: [] + VectorActionSpaceType: 0 + hasUpgradedBrainParametersWithActionSpec: 1 + m_Model: {fileID: 0} + m_InferenceDevice: 0 + m_BehaviorType: 0 + m_BehaviorName: My Behavior + TeamId: 0 + m_UseChildSensors: 1 + m_UseChildActuators: 1 + m_ObservableAttributeHandling: 0 +--- !u!1 &225044881 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 225044882} + - component: {fileID: 225044883} + m_Layer: 0 + m_Name: Floor + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &225044882 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 225044881} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &225044883 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 225044881} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a74be3508dbe36342858e20cec768f98, type: 3} + m_Name: + m_EditorClassIdentifier: + tileWallPrefab: {fileID: 7692220640868168301, guid: de70788c970f16940b9f517cf39194b0, + type: 3} + endPointPrefab: {fileID: 6314994090778056550, guid: 8ddb9b3dc215c2b4e97741bad9ced662, + type: 3} + mainCamera: {fileID: 963194227} + SimulationController: {fileID: 93153077} +--- !u!1 &705507993 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 705507995} + - component: {fileID: 705507994} + m_Layer: 0 + m_Name: Directional Light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &705507994 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 705507993} + m_Enabled: 1 + serializedVersion: 10 + m_Type: 1 + m_Shape: 0 + m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} + m_Intensity: 1 + m_Range: 10 + m_SpotAngle: 30 + m_InnerSpotAngle: 21.80208 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 1 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &705507995 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 705507993} + m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} + m_LocalPosition: {x: 0, y: 3, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} +--- !u!1 &963194225 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 963194228} + - component: {fileID: 963194227} + - component: {fileID: 963194226} + - component: {fileID: 963194229} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &963194226 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 963194225} + m_Enabled: 1 +--- !u!20 &963194227 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 963194225} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &963194228 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 963194225} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &963194229 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 963194225} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 208230689b9953844af11c709edefaea, type: 3} + m_Name: + m_EditorClassIdentifier: + speed: 0.5 + sensitivity: 1 diff --git a/PickUpandDelivery/Assets/Scenes/Online_Centralized.unity.meta b/PickUpandDelivery/Assets/Scenes/Online_Centralized.unity.meta new file mode 100644 index 0000000000000000000000000000000000000000..149175f1f35c979cdb54888a570415ea75cf6b23 --- /dev/null +++ b/PickUpandDelivery/Assets/Scenes/Online_Centralized.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: c22ac62bd8f63044a827178aa567b823 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scenes/Online_Decentralized.unity b/PickUpandDelivery/Assets/Scenes/Online_Decentralized.unity new file mode 100644 index 0000000000000000000000000000000000000000..64deb18a4961b32fcff61046487b206d12de7d29 --- /dev/null +++ b/PickUpandDelivery/Assets/Scenes/Online_Decentralized.unity @@ -0,0 +1,407 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 705507994} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 500 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 2 + m_PVRDenoiserTypeDirect: 0 + m_PVRDenoiserTypeIndirect: 0 + m_PVRDenoiserTypeAO: 0 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 1 +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &93153075 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 93153076} + - component: {fileID: 93153077} + m_Layer: 0 + m_Name: SimulationController + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &93153076 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 93153075} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &93153077 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 93153075} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a6033bfb5a3a1f747b8a528a445711a6, type: 3} + m_Name: + m_EditorClassIdentifier: + robotPrefab: {fileID: 1321468028730240, guid: 5b62ae8d6539a4637bba603a6015fe86, + type: 3} +--- !u!1 &225044881 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 225044882} + - component: {fileID: 225044883} + m_Layer: 0 + m_Name: Floor + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &225044882 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 225044881} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &225044883 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 225044881} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a74be3508dbe36342858e20cec768f98, type: 3} + m_Name: + m_EditorClassIdentifier: + tileWallPrefab: {fileID: 7692220640868168301, guid: de70788c970f16940b9f517cf39194b0, + type: 3} + endPointPrefab: {fileID: 6314994090778056550, guid: 8ddb9b3dc215c2b4e97741bad9ced662, + type: 3} + mainCamera: {fileID: 963194227} + SimulationController: {fileID: 93153077} +--- !u!1 &705507993 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 705507995} + - component: {fileID: 705507994} + m_Layer: 0 + m_Name: Directional Light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &705507994 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 705507993} + m_Enabled: 1 + serializedVersion: 10 + m_Type: 1 + m_Shape: 0 + m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} + m_Intensity: 1 + m_Range: 10 + m_SpotAngle: 30 + m_InnerSpotAngle: 21.80208 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 1 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &705507995 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 705507993} + m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} + m_LocalPosition: {x: 0, y: 3, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} +--- !u!1 &963194225 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 963194228} + - component: {fileID: 963194227} + - component: {fileID: 963194226} + - component: {fileID: 963194229} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &963194226 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 963194225} + m_Enabled: 1 +--- !u!20 &963194227 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 963194225} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &963194228 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 963194225} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &963194229 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 963194225} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 208230689b9953844af11c709edefaea, type: 3} + m_Name: + m_EditorClassIdentifier: + speed: 0.5 + sensitivity: 1 diff --git a/PickUpandDelivery/Assets/Scenes/Online_Decentralized.unity.meta b/PickUpandDelivery/Assets/Scenes/Online_Decentralized.unity.meta new file mode 100644 index 0000000000000000000000000000000000000000..952bd1e9e110583d94b471a30ff4ddd69f4aee7d --- /dev/null +++ b/PickUpandDelivery/Assets/Scenes/Online_Decentralized.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 9fc0d4010bbf28b4594072e72b8655ab +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scripts.meta b/PickUpandDelivery/Assets/Scripts.meta new file mode 100644 index 0000000000000000000000000000000000000000..976748fdba857f0df5545bc22656f99324c1c1c1 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: eeec7c13660dbba42b8a8df0a27ca542 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scripts/Common.meta b/PickUpandDelivery/Assets/Scripts/Common.meta new file mode 100644 index 0000000000000000000000000000000000000000..420236084e42050a641b19f7fb22c5fbc4f369f8 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bb96f31e5d7da9e4d9750f484538c33b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scripts/Common/Robot.meta b/PickUpandDelivery/Assets/Scripts/Common/Robot.meta new file mode 100644 index 0000000000000000000000000000000000000000..c31fb5ac36f8ae0c17fb802fe7e098b3c460fc47 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/Robot.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 961c621f85b64a8cbdfc0f1130b7735d +timeCreated: 1628838762 \ No newline at end of file diff --git a/PickUpandDelivery/Assets/Scripts/Common/Robot/IRobot.cs b/PickUpandDelivery/Assets/Scripts/Common/Robot/IRobot.cs new file mode 100644 index 0000000000000000000000000000000000000000..eaa09010e417ae65c6e35fe66df8e5bc87ff03be --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/Robot/IRobot.cs @@ -0,0 +1,18 @@ +using Common.SimulationManager; +using Common.Warehouse; +using UnityEngine; + +namespace Common.Robot +{ + public interface IRobot + { + ISimulationManager simulationManager { get; set; } + Task assignedTask { get; set; } + + //METHODS + MonoBehaviour GetMonoBehaviour(); + void AssignTask(Task task); + void PickUp(); + Task Deliver(); + } +} \ No newline at end of file diff --git a/PickUpandDelivery/Assets/Scripts/Common/Robot/IRobot.cs.meta b/PickUpandDelivery/Assets/Scripts/Common/Robot/IRobot.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..7c04a5f287b558ba7d72f9cb9873793b2adfe09f --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/Robot/IRobot.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5ab51108ccb54e19a3721df3d82ce8f3 +timeCreated: 1628601434 \ No newline at end of file diff --git a/PickUpandDelivery/Assets/Scripts/Common/Robot/RobotMethods.cs b/PickUpandDelivery/Assets/Scripts/Common/Robot/RobotMethods.cs new file mode 100644 index 0000000000000000000000000000000000000000..1f4c95db81bad6863742785680ed82b081ae6308 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/Robot/RobotMethods.cs @@ -0,0 +1,255 @@ +/* + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +using System; +using System.Linq; +using Common.Warehouse; +using Unity.MLAgents.Actuators; +using Unity.MLAgents.Sensors; +using UnityEngine; + +namespace Common.Robot +{ + /// <summary> + /// Static class <c> RobotMethods </c> contains methods used by classes implementing the <c> IRobot </c> interface. + /// - InitializeRobotAtStart(IRobot robot) draws robot using initial nodes and sets parameters for collision detection + /// - UpdatePosition(IRobot robot): updates position and rotation for robot + /// - CollisionEvent(IRobot robot): determines what happens when a robot collides + /// - AssignTask(IRobot robot, Task task): assign task to robot, color robot in task color + /// - PickUp(IRobot robot): pick up: add cross on top of robot + /// - Deliver(IRobot robot): deliver task: remove cross, reset color of robot + /// - CollectObservations(IRobot robot, VectorSensor sensor): collect observations when robot is agent + /// - OnActionReceived(IRobot robot, ActionBuffers actionBuffers, Color defaultColor): do action when robot is agent + /// + /// Private methods: + /// - RemoveTask(IRobot robot, Color defaultColor): removes tasks for robot, resets color and removes cross + /// - ActivateCross(IRobot robot, Task assignedTask): activate cross on robot using complementary color of task + /// - DeactivateCross(IRobot robot): deactivate cross + /// </summary> + public static class RobotMethods + { + /// <summary> + /// Draw robot at start. + /// </summary> + /// <param name="robot"></param> + public static void InitializeRobotAtStart(IRobot robot) + { + MonoBehaviour robotMB = robot.GetMonoBehaviour(); + // draw robot + robotMB.transform.localScale = robot.simulationManager.SIZE * robot.simulationManager.SCALEROBOT * Vector3.one; + robotMB.transform.localPosition = new Vector3( + robot.simulationManager.GetCurrentNode(robotMB.gameObject.GetInstanceID()).GridPosition.Row * robot.simulationManager.SIZE, + robotMB.transform.localScale.y / 2 + robot.simulationManager.YROBOTFLOATING, // put on tile + floating + robot.simulationManager.GetCurrentNode(robotMB.gameObject.GetInstanceID()).GridPosition.Column * robot.simulationManager.SIZE); + robotMB.transform.eulerAngles = + new Vector3(0, robot.simulationManager.GetCurrentNode(robotMB.gameObject.GetInstanceID()).Degrees, 0); + + // add rigidbody and collider for collision detection + // change size of boxcollider otherwise there is a collision when + robotMB.gameObject.AddComponent<Rigidbody>(); + robotMB.gameObject.GetComponent<Rigidbody>().useGravity = false; + robotMB.gameObject.GetComponent<Rigidbody>().isKinematic = false; + robotMB.gameObject.AddComponent<BoxCollider>().isTrigger = true; + + // deactivate cross on top of robot + DeactivateCross(robot); + } + + /// <summary> + /// Update robot position and rotation. + /// </summary> + /// <param name="robot"></param> + public static void UpdatePosition(IRobot robot) + { + MonoBehaviour robotMB = robot.GetMonoBehaviour(); + // only update positions robot if there haven't been detected any collisions + if (!robot.simulationManager.collisions) + { + var maxDistance = robot.simulationManager.SIZE * Time.fixedDeltaTime; + var maxDegs = robot.simulationManager.parameters.Rotation * Time.fixedDeltaTime; + + robotMB.transform.localPosition = Vector3.MoveTowards( + robotMB.transform.localPosition, + new Vector3( + robot.simulationManager.GetCurrentNode(robotMB.gameObject.GetInstanceID()).GridPosition.Row * + robot.simulationManager.SIZE, + robotMB.transform.localPosition.y, + robot.simulationManager.GetCurrentNode(robotMB.gameObject.GetInstanceID()).GridPosition.Column * + robot.simulationManager.SIZE), + maxDistance + ); + + robotMB.transform.rotation = Quaternion.RotateTowards( + robotMB.transform.rotation, + Quaternion.Euler(0, robot.simulationManager.GetCurrentNode(robotMB.gameObject.GetInstanceID()).Degrees, 0), + maxDegs + ); + } + } + + /// <summary> + /// Method used when robot is decision maker. + /// Collect observations and add to sensor. + /// An observation for one robot consists of a row, a column and a number of degrees. + /// </summary> + /// <param name="robot"></param> + /// <param name="sensor"></param> + public static void CollectObservations(IRobot robot, VectorSensor sensor) + { + MonoBehaviour robotMB = robot.GetMonoBehaviour(); + sensor.AddObservation(robotMB.gameObject.GetInstanceID()); + var node = robot.simulationManager.GetCurrentNode(robotMB.gameObject.GetInstanceID()); + sensor.AddObservation(node.GridPosition.Row); + sensor.AddObservation(node.GridPosition.Column); + sensor.AddObservation(node.Degrees); + } + + /// <summary> + /// Method used when Robot is decision maker. + /// When an action is received the position and location of the robot is updated and if applicable + /// pickup or delivery action is invoked. + /// </summary> + /// <param name="robot"></param> + /// <param name="actionBuffers"></param> + public static void OnActionReceived(IRobot robot, ActionBuffers actionBuffers, Color defaultColor) + { + MonoBehaviour robotMB = robot.GetMonoBehaviour(); + var individualActions = actionBuffers.DiscreteActions.ToArray(); + var row = individualActions[0]; + var column = individualActions[1]; + var degrees = individualActions[2]; + var pickup = individualActions[3]; + var deliver = individualActions[4]; + Debug.Log(String.Format("Robot {0} received action [{1}, {2}, {3}, {4}, {5}]", + robotMB.gameObject.GetInstanceID(), row, column, degrees, pickup, deliver)); + robot.simulationManager.currentNodes[robotMB.gameObject.GetInstanceID()] = new Node(new Position(row, column), degrees); + + if (pickup == 1) + { + PickUp(robot); + } + + if (deliver == 1) + { + // remove task in simulation manager + robot.simulationManager.RemoveTask(robot.assignedTask); + + // remove task for robot + Deliver(robot, defaultColor); + + // create new task + robot.simulationManager.AddNewTask(); + } + } + + /// <summary> + /// After an collision event, simulationManager has to be notified. + /// </summary> + /// <param name="robot"></param> + public static void CollisionEvent(IRobot robot) + { + robot.simulationManager.collisions = true; + } + + /// <summary> + /// Assign task to robot. Color robot using task color. + /// </summary> + /// <param name="task"> a Task object</param> + public static void AssignTask(IRobot robot, Task task) + { + MonoBehaviour robotMB = robot.GetMonoBehaviour(); + robot.assignedTask = task; + robotMB.transform.Find("Agent").Find("AgentCube_Blue").GetComponent<Renderer>().material.color = + robot.simulationManager.currentTasks[task]; + } + + /// <summary> + /// Remove assigned task for robot. Reset color to default and deactivate cross. + /// </summary> + private static void RemoveTask(IRobot robot, Color defaultColor) + { + MonoBehaviour robotMB = robot.GetMonoBehaviour(); + robot.assignedTask = null; + robotMB.transform.Find("Agent").Find("AgentCube_Blue").GetComponent<Renderer>().material.color = defaultColor; + + // deactivate cross on top of robot + DeactivateCross(robot); + } + + /// <summary> + /// After pick up, a cross is added on top of the agent. We use the complementary color of the task color. + /// </summary> + /// <exception cref="Exception"> if robot is not at the pick up position</exception> + public static void PickUp(IRobot robot) + { + MonoBehaviour robotMB = robot.GetMonoBehaviour(); + if (! robot.assignedTask.PickUp.Equals(robot.simulationManager.currentNodes[robotMB.gameObject.GetInstanceID()].GridPosition)) + { + throw new Exception("robot " + robotMB.gameObject.GetInstanceID() + "pickup incorrect position: " + + robot.simulationManager.currentNodes[robotMB.gameObject.GetInstanceID()].GridPosition); + } + + // activate cross on top of robot + ActivateCross(robot, robot.assignedTask); + } + + /// <summary> + /// After delivering a task, the assigned task must be removed and the robot's color has to be resetted to defaultcolor + /// and the cross has to be removed. + /// </summary> + /// <param name="robot"></param> + /// <param name="defaultColor"></param> + /// <returns></returns> + /// <exception cref="Exception">if robot is not at the delivery position</exception> + public static Task Deliver(IRobot robot, Color defaultColor) + { + MonoBehaviour robotMB = robot.GetMonoBehaviour(); + if (! robot.assignedTask.Delivery.Equals(robot.simulationManager.currentNodes[robotMB.gameObject.GetInstanceID()].GridPosition)) + { + throw new Exception("robot " + robotMB.gameObject.GetInstanceID() + "delivery incorrect position: " + + robot.simulationManager.currentNodes[robotMB.gameObject.GetInstanceID()].GridPosition); + } + + var taskToReturn = robot.assignedTask; + RemoveTask(robot, defaultColor); + return taskToReturn; + } + + /// <summary> + /// Deactivate cross on top of robot. + /// </summary> + /// <param name="robot"></param> + private static void DeactivateCross(IRobot robot) + { + MonoBehaviour robotMB = robot.GetMonoBehaviour(); + robotMB.transform.Find("Agent").Find("AgentCube_Blue").Find("x1").gameObject.SetActive(false); + robotMB.transform.Find("Agent").Find("AgentCube_Blue").Find("x2").gameObject.SetActive(false); + } + + /// <summary> + /// Activate cross on top of robot and color robot in complementary color of assigned task color. + /// </summary> + private static void ActivateCross(IRobot robot, Task assignedTask) + { + MonoBehaviour robotMB = robot.GetMonoBehaviour(); + robotMB.transform.Find("Agent").Find("AgentCube_Blue").Find("x1").gameObject.SetActive(true); + robotMB.transform.Find("Agent").Find("AgentCube_Blue").Find("x2").gameObject.SetActive(true); + Color negativeColor = UtilityMethods.GetNegativeColor(robot.simulationManager.currentTasks[assignedTask]); + robotMB.transform.Find("Agent").Find("AgentCube_Blue").Find("x1").GetComponent<Renderer>().material.color = negativeColor; + robotMB.transform.Find("Agent").Find("AgentCube_Blue").Find("x2").GetComponent<Renderer>().material.color = negativeColor; + } + } +} diff --git a/PickUpandDelivery/Assets/Scripts/Common/Robot/RobotMethods.cs.meta b/PickUpandDelivery/Assets/Scripts/Common/Robot/RobotMethods.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..e93eb39c778b1a53d5e604321ad00f3a33e9e6ad --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/Robot/RobotMethods.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 94d94501e73f4450bbb36cfedaeb7ec8 +timeCreated: 1628838963 \ No newline at end of file diff --git a/PickUpandDelivery/Assets/Scripts/Common/Scripts.meta b/PickUpandDelivery/Assets/Scripts/Common/Scripts.meta new file mode 100644 index 0000000000000000000000000000000000000000..e5ce89abb67f1d5865e70e9a3c5562bd3f722eff --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/Scripts.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7f30b9cb10964db1bf69c766b3bd9a94 +timeCreated: 1628838540 \ No newline at end of file diff --git a/PickUpandDelivery/Assets/Scripts/Common/Scripts/CameraMoveScript.cs b/PickUpandDelivery/Assets/Scripts/Common/Scripts/CameraMoveScript.cs new file mode 100644 index 0000000000000000000000000000000000000000..dceecb4d57b02b61de703c0e1c938d7e7348a5d7 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/Scripts/CameraMoveScript.cs @@ -0,0 +1,66 @@ +/* + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +using UnityEngine; + +namespace Common.Scripts +{ + public class CameraMoveScript: MonoBehaviour + { + [SerializeField] float speed = 0.5f; + [SerializeField] float sensitivity = 1.0f; + + Camera cam; + Vector3 anchorPoint; + Quaternion anchorRot; + + private void Awake() + { + cam = GetComponent<Camera>(); + } + + void FixedUpdate() + { + Vector3 move = Vector3.zero; + if (Input.GetKey(KeyCode.W)) + move += Vector3.forward * speed; + if (Input.GetKey(KeyCode.S)) + move -= Vector3.forward * speed; + if (Input.GetKey(KeyCode.D)) + move += Vector3.right * speed; + if (Input.GetKey(KeyCode.A)) + move -= Vector3.right * speed; + if (Input.GetKey(KeyCode.E)) + move += Vector3.up * speed; + if (Input.GetKey(KeyCode.Q)) + move -= Vector3.up * speed; + transform.Translate(move); + + if (Input.GetMouseButtonDown(1)) + { + anchorPoint = new Vector3(Input.mousePosition.y, -Input.mousePosition.x); + anchorRot = transform.rotation; + } + if (Input.GetMouseButton(1)) + { + Quaternion rot = anchorRot; + Vector3 dif = anchorPoint - new Vector3(Input.mousePosition.y, -Input.mousePosition.x); + rot.eulerAngles += dif * sensitivity; + transform.rotation = rot; + } + } + } +} \ No newline at end of file diff --git a/PickUpandDelivery/Assets/Scripts/Common/Scripts/CameraMoveScript.cs.meta b/PickUpandDelivery/Assets/Scripts/Common/Scripts/CameraMoveScript.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..532e4d444ac4a2869182d28986df5e30ec4fe2ca --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/Scripts/CameraMoveScript.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 208230689b9953844af11c709edefaea +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scripts/Common/Scripts/EndPoint.cs b/PickUpandDelivery/Assets/Scripts/Common/Scripts/EndPoint.cs new file mode 100644 index 0000000000000000000000000000000000000000..01952c7d4970b942935ac255d76afe0640ec20d2 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/Scripts/EndPoint.cs @@ -0,0 +1,72 @@ +/* + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +using Common.SimulationManager; +using Common.Warehouse; +using UnityEngine; + +namespace Common.Scripts +{ + /// <summary> + /// Script <c> EndPoint </c> takes care of coloring the endpoints and contains methods + /// - ResetColors(): changes color back to default, removes cross on top + /// - SetAsPickUp(Color taskColor): changes color to taskColor, removes cross on top + /// - SetAsDelivery(Color taskColor): changes color to taskColor, adds cross on top in complementary color of taskColor + /// </summary> + + public class EndPoint : MonoBehaviour + { + public ISimulationManager simulationManager; + + // endpoint as default (not pickup, not delivery) + public void ResetColors() + { + gameObject.GetComponent<Renderer>().material.color = simulationManager.colorEndPoint; + transform.Find("x1").gameObject.SetActive(false); + transform.Find("x2").gameObject.SetActive(false); + transform.Find("text").gameObject.SetActive(false); + } + + //set as pick up point for a certain task (color and release time) + public void SetAsPickUp(Task task) + { + Color taskColor = simulationManager.currentTasks[task]; + gameObject.GetComponent<Renderer>().material.color = taskColor; + transform.Find("x1").gameObject.SetActive(false); + transform.Find("x2").gameObject.SetActive(false); + if (task.ReleaseTime != 0) + { + transform.Find("text").gameObject.SetActive(true); + transform.Find("text").gameObject.GetComponent<TextMesh>().text = task.ReleaseTime.ToString(); + transform.Find("text").gameObject.GetComponent<MeshRenderer>().material.color = + UtilityMethods.GetNegativeColor(taskColor); + } + } + + // set as delivery point for a certain task (color): there will be an x drawn on top + public void SetAsDelivery(Task task) + { + Color taskColor = simulationManager.currentTasks[task]; + gameObject.GetComponent<Renderer>().material.color = taskColor; + transform.Find("x1").gameObject.SetActive(true); + transform.Find("x2").gameObject.SetActive(true); + transform.Find("text").gameObject.SetActive(false); + transform.Find("x1").GetComponent<Renderer>().material.color = UtilityMethods.GetNegativeColor(taskColor); + transform.Find("x2").GetComponent<Renderer>().material.color = UtilityMethods.GetNegativeColor(taskColor); + } + + } +} diff --git a/PickUpandDelivery/Assets/Scripts/Common/Scripts/EndPoint.cs.meta b/PickUpandDelivery/Assets/Scripts/Common/Scripts/EndPoint.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..1f523e30802ecd593c4dbc9e8c5bccd0f6bcb03e --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/Scripts/EndPoint.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f3dcff173f5992d4db93b38be21d0d1d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scripts/Common/Scripts/Floor.cs b/PickUpandDelivery/Assets/Scripts/Common/Scripts/Floor.cs new file mode 100644 index 0000000000000000000000000000000000000000..f42f783961dc28d5c8678fa41534c878444e0cb5 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/Scripts/Floor.cs @@ -0,0 +1,154 @@ +/* + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +using System; +using Common.SimulationManager; +using Common.Warehouse; +using UnityEngine; + +namespace Common.Scripts +{ + /// <summary> + /// Script <c> Floor </c> sets up the floor + /// - draws tiles, walls, endpoints, parking + /// - draws initial tasks (pick up and delivery) + /// and sets up the camera + /// </summary> + + public class Floor : MonoBehaviour + { + [SerializeField] + private GameObject tileWallPrefab = default; // prefab for tiles and walls + [SerializeField] + private GameObject endPointPrefab = default; // prefab for endPoints + [SerializeField] + private Camera mainCamera = default; + [SerializeField] + private MonoBehaviour SimulationController = default;// add gameobject SimulationController in editor + + private ISimulationManager simulationManager; + + // Start is called before the first frame update + void Start() + { + simulationManager = SimulationController as ISimulationManager; + + // draw tiles and walls (initial status, no tasks) + for (var row = 0; row < simulationManager.parameters.Matrix.Length; row++) + { + for (var column = 0; column < simulationManager.parameters.Matrix[0].Length; column++) + { + GameObject cube; + + if (simulationManager.parameters.Matrix[row][column] == simulationManager.parameters.CodeWall) //wall + { + cube = Instantiate(tileWallPrefab); + cube.GetComponent<Renderer>().material.color = simulationManager.colorWall; + } + + else if (simulationManager.parameters.Matrix[row][column] == simulationManager.parameters.CodeTile) // normal tile + { + cube = Instantiate(tileWallPrefab); + cube.GetComponent<Renderer>().material.color = simulationManager.colorTile; + } + + else if (simulationManager.parameters.Matrix[row][column] == simulationManager.parameters.CodeEndPoint) // end point + { + cube = Instantiate(endPointPrefab); + cube.GetComponent<EndPoint>().simulationManager = simulationManager; + cube.GetComponent<EndPoint>().ResetColors(); + simulationManager.endPoints[new Position(row, column)] = cube; + } + else //parking + { + cube = Instantiate(tileWallPrefab); + cube.GetComponent<Renderer>().material.color = simulationManager.colorParking; + } + + // we want to detect collisions between robots and walls + cube.GetComponent<BoxCollider>().enabled = + simulationManager.parameters.Matrix[row][column] == simulationManager.parameters.CodeWall; + cube.GetComponent<BoxCollider>().isTrigger = + simulationManager.parameters.Matrix[row][column] == simulationManager.parameters.CodeWall; + + // add size tile/wall + cube.transform.localScale = new Vector3(simulationManager.SIZE, + simulationManager.parameters.Matrix[row][column] == simulationManager.parameters.CodeWall ? simulationManager.SIZE : 0.2f, + simulationManager.SIZE); + + cube.transform.position = new Vector3(row*simulationManager.SIZE, + 0, column*simulationManager.SIZE); + + cube.transform.parent = gameObject.transform; + } + } + // add colors to current tasks + //TODO: what with tasks from list? -> they might overlap + foreach (var task in simulationManager.currentTasks) + { + var pickUp = task.Key.PickUp; + var delivery = task.Key.Delivery; + + simulationManager.endPoints[pickUp].GetComponent<EndPoint>().SetAsPickUp(task.Key); + simulationManager.endPoints[delivery].GetComponent<EndPoint>().SetAsDelivery(task.Key); + } + + SetCamera(); + } + + private void SetCamera() + { + var maxbound = Math.Max(simulationManager.parameters.Matrix.Length, simulationManager.parameters.Matrix[0].Length); + mainCamera.gameObject.transform.position = + new Vector3(simulationManager.SIZE * maxbound + simulationManager.SIZE, + simulationManager.SIZE * maxbound, - simulationManager.SIZE); + mainCamera.gameObject.transform.LookAt(gameObject.GetBoundsWithChildren().center); + } + } + + public static class UnityExtensions + { + public static Bounds GetBoundsWithChildren(this GameObject gameObject) + { + // GetComponentsInChildren() also returns components on gameobject which you call it on + // you don't need to get component specially on gameObject + Renderer[] renderers = gameObject.GetComponentsInChildren<Renderer>(); + + // If renderers.Length = 0, you'll get OutOfRangeException + Bounds bounds = renderers.Length > 0 ? renderers[0].bounds : new Bounds(); + + // Start from 1 because we've already encapsulated renderers[0] + for (int i = 1; i < renderers.Length; i++) + { + if (renderers[i].enabled) + { + bounds.Encapsulate(renderers[i].bounds); + } + } + + return bounds; + } + + public static void FocusOn(this Camera camera, GameObject focusedObject, float marginPercentage) + { + Bounds bounds = focusedObject.GetBoundsWithChildren(); + float maxExtent = bounds.extents.magnitude; + float minDistance = (maxExtent * marginPercentage) / Mathf.Sin(Mathf.Deg2Rad * camera.fieldOfView / 2f); + camera.transform.position = focusedObject.transform.position - Vector3.forward * minDistance; + camera.nearClipPlane = minDistance - maxExtent; + } + } +} \ No newline at end of file diff --git a/PickUpandDelivery/Assets/Scripts/Common/Scripts/Floor.cs.meta b/PickUpandDelivery/Assets/Scripts/Common/Scripts/Floor.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..b0c33767854c37e49af831d753810e7981dd87c3 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/Scripts/Floor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a74be3508dbe36342858e20cec768f98 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scripts/Common/SideChannels.meta b/PickUpandDelivery/Assets/Scripts/Common/SideChannels.meta new file mode 100644 index 0000000000000000000000000000000000000000..fe09df17e6f2a481f6867d37b24c0acaefde0dae --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/SideChannels.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f0be1d97d4954270a69446174d8b05e2 +timeCreated: 1628838678 \ No newline at end of file diff --git a/PickUpandDelivery/Assets/Scripts/Common/SideChannels/EnvSideChannel.cs b/PickUpandDelivery/Assets/Scripts/Common/SideChannels/EnvSideChannel.cs new file mode 100644 index 0000000000000000000000000000000000000000..dfbd17e817abffaef70f4ba6783981a6801d30a2 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/SideChannels/EnvSideChannel.cs @@ -0,0 +1,49 @@ +/* + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +using System; +using Unity.MLAgents.SideChannels; + +namespace Common.SideChannels +{ + /// <summary> + /// SideChannel used for sending initial information on environment to Python client. + /// </summary> + + public class EnvSideChannel : SideChannel + { + public EnvSideChannel() + { + ChannelId = new Guid("621f0a70-4f87-11ea-a6bf-784f4387d1f7"); + } + + protected override void OnMessageReceived(IncomingMessage msg) + { + //var receivedString = msg.ReadString(); + //Debug.LogError("From Python : " + receivedString); + } + + public void SendEnv(string message) + { + var stringToSend = message; + using (var msgOut = new OutgoingMessage()) + { + msgOut.WriteString(stringToSend); + QueueMessageToSend(msgOut); + } + } + } +} \ No newline at end of file diff --git a/PickUpandDelivery/Assets/Scripts/Common/SideChannels/EnvSideChannel.cs.meta b/PickUpandDelivery/Assets/Scripts/Common/SideChannels/EnvSideChannel.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..7524541d0ada964c61a8bb7166de5742f326606b --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/SideChannels/EnvSideChannel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 30ce75aad8425a644b59307793a9af24 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scripts/Common/SideChannels/TaskSideChannel.cs b/PickUpandDelivery/Assets/Scripts/Common/SideChannels/TaskSideChannel.cs new file mode 100644 index 0000000000000000000000000000000000000000..067346e475ab7a23e0c537e7f5b60f003d06c7cc --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/SideChannels/TaskSideChannel.cs @@ -0,0 +1,68 @@ +/* + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +using System; +using Common.SimulationManager; +using Common.Warehouse; +using Newtonsoft.Json; +using Unity.MLAgents.SideChannels; +using UnityEngine; + +namespace Common.SideChannels +{ + /// <summary> + /// SideChannel used for sending and receiving information on tasks. + /// - sends initial information on tasks (initial tasks) + /// - receives information on assigned tasks + /// </summary> + + public class TaskSideChannel : SideChannel + { + private class TaskAssignment + { + public Task Task = null; + public int InstanceId = 0; + } + + public ISimulationManager SimulationManager; + + public TaskSideChannel() + { + ChannelId = new Guid("c11ab982-82b8-4194-b387-3bd0fe9ebdc7"); + } + + protected override void OnMessageReceived(IncomingMessage msg) + { + var receivedString = msg.ReadString(); + Debug.Log("message received"); + var newTask = JsonConvert.DeserializeObject<TaskAssignment>(receivedString); + if (newTask != null) + { + SimulationManager.AssignTask(newTask.Task, newTask.InstanceId); + } + } + + public void SendEnv(string message) + { + var stringToSend = message; + using (var msgOut = new OutgoingMessage()) + { + msgOut.WriteString(stringToSend); + QueueMessageToSend(msgOut); + } + } + } +} diff --git a/PickUpandDelivery/Assets/Scripts/Common/SideChannels/TaskSideChannel.cs.meta b/PickUpandDelivery/Assets/Scripts/Common/SideChannels/TaskSideChannel.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..607eb97952f2026887a605686f0e9d79ff05ee69 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/SideChannels/TaskSideChannel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 15225950aa7307b4086f7d0a544ca3c1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scripts/Common/SimulationManager.meta b/PickUpandDelivery/Assets/Scripts/Common/SimulationManager.meta new file mode 100644 index 0000000000000000000000000000000000000000..21f8c0cbd4b13a7977cf237a1d1b69f3f1198b50 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/SimulationManager.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e59645e254214d8995295041954a75cf +timeCreated: 1628838787 \ No newline at end of file diff --git a/PickUpandDelivery/Assets/Scripts/Common/SimulationManager/ISimulationManager.cs b/PickUpandDelivery/Assets/Scripts/Common/SimulationManager/ISimulationManager.cs new file mode 100644 index 0000000000000000000000000000000000000000..b2b6b7c410feedcc0003d2a2124240357226e9c7 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/SimulationManager/ISimulationManager.cs @@ -0,0 +1,89 @@ +/* + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +using System.Collections.Generic; +using Common.SideChannels; +using Common.Warehouse; +using UnityEngine; + +namespace Common.SimulationManager +{ + public interface ISimulationManager + { + // PARAMETERS + // parameters of warehouse + WarehouseParameters parameters { get; set; } + // offline or online + bool online { get; } + // input warehouse and tasks + string warehouseConfigFile { get; } + string tasksListFile { get; } + + // COLORS + // colors for tiles and walls + Color colorWall { get; } + Color colorTile { get; } + Color colorEndPoint { get; } + Color colorParking { get; } + + // colors used for tasks and the robots that have been assigned these tasks: initially colors will be created + // and stored in notAssignedColors, when assigned to a task, color will be moved to assignedColors + HashSet<Color> assignedColors { get; set; } + HashSet<Color> notAssignedColors { get; set; } + + // ENDPOINTS + // dictionary containing all endpoints + // every endpointposition points to a gameobject, gameobject will be setup by the Floor script + Dictionary<Position, GameObject> endPoints { get; set; } + + // TASKS + // at every timestep there will be max numberOfTasks tasks that have to be assigned (by the python code) + // current available tasks and their assigned colors: these are the tasks to remain to be assigned to robots + Dictionary<Task, Color> currentTasks { get; set; } + // when using a predefined set of tasks, the tasks that are not yet in currentTasks are sstored in remainingTasks + Task[] remainingTasks { get; set; } + + // ROBOTS + // For every robot the current node where he is going, i.e. the next action + Dictionary<int, Node> currentNodes { get; } + // unity instance ID and corresponding game object + Dictionary<int, GameObject> robotGameObjects { get; set; } + + // ENVIRONMENT VARIABLES + // check for collisions + bool collisions { get; set; } + // observation- and actionsize + int observationSize { get; } + int actionSize { get; } + // environment variables for drawing + float SIZE { get; } // Size of square/tile, this is kept constant to avoid having to change camera perspective + float SCALEROBOT { get; } // Ratio robot to tile, for drawing robot + float YROBOTFLOATING { get; } // Floating y value robot, for drawing robot + + //SIDE CHANNELS + EnvSideChannel envChannel { get; set; } + TaskSideChannel taskChannel { get; set; } + + + //METHODS + Node GetCurrentNode(int instanceID); + void RemoveTask(Task task); + void AddNewTask(); + void AssignTask(Task task, int instanceID); + MonoBehaviour GetMonoBehaviour(); + } +} + diff --git a/PickUpandDelivery/Assets/Scripts/Common/SimulationManager/ISimulationManager.cs.meta b/PickUpandDelivery/Assets/Scripts/Common/SimulationManager/ISimulationManager.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..c921a4853f3f02bbaf6ade3d8564793494197b64 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/SimulationManager/ISimulationManager.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: b03b437f56df4d82a29a944ac1b111ae +timeCreated: 1628603152 \ No newline at end of file diff --git a/PickUpandDelivery/Assets/Scripts/Common/SimulationManager/SimulationManagerMethods.cs b/PickUpandDelivery/Assets/Scripts/Common/SimulationManager/SimulationManagerMethods.cs new file mode 100644 index 0000000000000000000000000000000000000000..a178dbd9b5fab9a5b93c45ad0c28508ef10c64cb --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/SimulationManager/SimulationManagerMethods.cs @@ -0,0 +1,484 @@ +/* + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +using System; +using System.Collections.Generic; +using System.Linq; +using Common.Robot; +using Common.Scripts; +using Common.SideChannels; +using Common.Warehouse; +using Newtonsoft.Json; +using Unity.MLAgents.Actuators; +using Unity.MLAgents.Policies; +using Unity.MLAgents.Sensors; +using Unity.MLAgents.SideChannels; +using Random = System.Random; +using UnityEngine; + +namespace Common.SimulationManager +{ + /// <summary> + /// Static class <c> SimulationManagerMethods </c> contains methods used by + /// classes implementing the <c> ISimulationManager </c> interface. + /// - SetUpWarehouse<T>(ISimulationManager simulationManager, GameObject robotPrefab, bool isDecisionMaker): setup warehouse, tasks, + /// side channels, behavior component + /// - GetCurrentNode(ISimulationManager simulationManager, int instanceID): get next node for robot with given id + /// - AssignTask<T>(ISimulationManager simulationManager, Task task, int instanceID): assign a task to a robot with given instanceID + /// - AddNewTask(ISimulationManager simulationManager): add a new task to <c> simulationManager.currentTasks </c> if there are + /// still tasks available + /// - RemoveTask(ISimulationManager simulationManager, Task task): remove a task from <c> simulationManager.currentTasks </c> + /// - CollectObservations(ISimulationManager simulationManager, VectorSensor sensor): collect observations for all robots and + /// add to sensor + /// - ShowCollisionMessage(ISimulationManager simulationManager): show message collision + /// + /// private methods: + /// - ReadInput(ISimulationManager simulationManager): set parameters and tasks from input + /// - SetUpRobots<T>(ISimulationManager simulationManager, GameObject robotPrefab): initialize and set up robots + /// - SetUpSideChannels(ISimulationManager simulationManager): set up side channels + /// - SetUpBehaviorParameters(ISimulationManager simulationManager): set up behavior parameters + /// - CreateColors(ISimulationManager simulationManager): create as many colors as there are tasks available at every point in time + /// and store in set <c> simulationManager.notAssignedColors </c> + /// - SetUpEndPoints(ISimulationManager simulationManager): store positions for all endpoints in dictionary <c> simulationManager.endPoints </c> + /// - InitializeCurrentTasks(ISimulationManager simulationManager): store first tasks in <c> + /// - GetNewTask(ISimulationManager simulationManager): get next task to be added to <c> simulationManager.currentTasks </c> + /// </summary> + public static class SimulationManagerMethods + { + + /// <summary> + /// Sets up warehouse: reads input, creates colors for tasks, sets up tasks, sets up endpoints, sets up robots + /// using the prefab, sets up side channels. If applicable sets up a behavior component. + /// </summary> + /// <param name="simulationManager"></param> + /// <param name="robotPrefab"></param> + /// <param name="isDecisionMaker"></param> + /// <typeparam name="T"></typeparam> + public static void SetUpWarehouse<T>(ISimulationManager simulationManager, GameObject robotPrefab, bool isDecisionMaker) where T:IRobot + { + // read input and set up parameters + ReadInput(simulationManager); + + // setup colors + CreateColors(simulationManager); + + // setup endpoints + SetUpEndPoints(simulationManager); + + // setup tasks: + InitializeCurrentTasks(simulationManager); + + // setup robots + SetUpRobots<T>(simulationManager, robotPrefab); + + // set up side channels + SetUpSideChannels(simulationManager); + + // set up behavior parameters + if (isDecisionMaker) + { + SetUpBehaviorParameters(simulationManager); + } + } + + /// <summary> + /// Returns current node, i.e. the next node to go to, for a robot with a given instance ID. + /// </summary> + /// <param name="simulationManager"></param> + /// <param name="instanceID"></param> + /// <returns>current node</returns> + public static Node GetCurrentNode(ISimulationManager simulationManager, int instanceID) + { + return simulationManager.currentNodes[instanceID]; + } + + /// <summary> + /// Assign a task to a robot with a given instanceID. + /// </summary> + /// <param name="simulationManager"></param> + /// <param name="task"></param> + /// <param name="instanceID"></param> + /// <typeparam name="T"> the corresponding robot type </typeparam> + public static void AssignTask<T>(ISimulationManager simulationManager, Task task, int instanceID) where T:IRobot + { + simulationManager.robotGameObjects[instanceID].GetComponent<T>().AssignTask(task); + } + + /// <summary> + /// Add a task to <c> simulationManager.currentTasks </c> if there are still tasks available. + /// Assign a color and send information to python code. + /// </summary> + /// <exception cref="Exception">thrown when currentTasks has already reached capacity</exception> + public static void AddNewTask(ISimulationManager simulationManager) + { + if (simulationManager.currentTasks.Count == simulationManager.parameters.NumberOfTasks) + { + throw new Exception("currentTasks is full"); + } + + if (simulationManager.notAssignedColors.Count == 0) + { + throw new Exception("no colors left"); + } + + var newTask = GetNewTask(simulationManager); + + // newTask can be null if there are no tasks left + if (newTask != null) + { + // get color from notAssignedColors (will not be empty, we can always take element at index 0) and move to assignedColors + var color = simulationManager.notAssignedColors.ElementAt(0); + simulationManager.notAssignedColors.Remove(color); + simulationManager.assignedColors.Add(color); + + // add task to currentTasks + simulationManager.currentTasks.Add(newTask, color); + + // color pickup/deliver + simulationManager.endPoints[newTask.PickUp].GetComponent<EndPoint>().SetAsPickUp(newTask); + simulationManager.endPoints[newTask.Delivery].GetComponent<EndPoint>().SetAsDelivery(newTask); + + // use task sidechannel + var jsonTask = JsonConvert.SerializeObject( + new + { + task = newTask + }); + simulationManager.taskChannel.SendEnv(jsonTask); + } + } + + /// <summary> + /// Remove a task from <c> simulationManager.currentTasks </c> that was assigned to a robot. + /// </summary> + /// <param name="simulationManager"></param> + /// <param name="task"></param> + /// <exception cref="Exception"></exception> + public static void RemoveTask(ISimulationManager simulationManager, Task task) + { + if (!simulationManager.currentTasks.ContainsKey(task)) + { + throw new Exception("task was not assigned and cannot be removed: " + task); + } + + var colorOfTask = simulationManager.currentTasks[task]; + + // reset color of pickup/deliver endpoints + simulationManager.endPoints[task.PickUp].GetComponent<EndPoint>().ResetColors(); + simulationManager.endPoints[task.Delivery].GetComponent<EndPoint>().ResetColors(); + + // move color to notAssignedColors + simulationManager.assignedColors.Remove(colorOfTask); + simulationManager.notAssignedColors.Add(colorOfTask); + + // remove from currentTasks + simulationManager.currentTasks.Remove(task); + } + + /// <summary> + /// Method used when simulationManager is decision maker. + /// Collect observations for each robot and add to sensor. + /// An observation for one robot consists of an instance id, a row, a column and a number of degrees. + /// </summary> + /// <param name="simulationManager"></param> + /// <param name="sensor"></param> + public static void CollectObservations(ISimulationManager simulationManager, VectorSensor sensor) + { + foreach (var node in simulationManager.currentNodes) + { + sensor.AddObservation(node.Key); + sensor.AddObservation(node.Value.GridPosition.Row); + sensor.AddObservation(node.Value.GridPosition.Column); + sensor.AddObservation(node.Value.Degrees); + } + } + + /// <summary> + /// When actions are received, do actions. Update position robots, and if applicable pickup or deliver. + /// </summary> + /// <param name="simulationManager"></param> + /// <param name="actionBuffers"></param> + /// <typeparam name="T"></typeparam> + public static void OnActionReceived<T>(ISimulationManager simulationManager, ActionBuffers actionBuffers) where T:IRobot + { + for (var i = 0; i < simulationManager.parameters.NumberOfRobots; i++) + { + var individualActions + = actionBuffers.DiscreteActions.Skip(i * simulationManager.actionSize).Take(simulationManager.actionSize).ToArray(); + var instanceID = individualActions[0]; + var row = individualActions[1]; + var column = individualActions[2]; + var degrees = individualActions[3]; + var pickup = individualActions[4]; + var deliver = individualActions[5]; + Debug.Log(String.Format("Robot {0} received action [{1}, {2}, {3}, {4}, {5}]", + instanceID, row, column, degrees, pickup, deliver)); + simulationManager.currentNodes[instanceID] = new Node(new Position(row, column), degrees); + + if (pickup == 1) + { + simulationManager.robotGameObjects[instanceID].gameObject.GetComponent<T>().PickUp(); + } + + if (deliver == 1) + { + // remove task for robot + var deliveredTask + = simulationManager.robotGameObjects[instanceID].gameObject.GetComponent<T>().Deliver(); + + // remove task in simulationmanager + RemoveTask(simulationManager,deliveredTask); + + // add new task + AddNewTask(simulationManager); + } + } + } + + /// <summary> + /// Read input and set parameters and if applicable preset tasks. + /// </summary> + /// <param name="simulationManager"></param> + private static void ReadInput(ISimulationManager simulationManager) + { + simulationManager.parameters = new ReadConfig(simulationManager.warehouseConfigFile).Parameters; + + //offline: check whether randomTasks is set to false + if (!simulationManager.online && simulationManager.parameters.RandomTasks) + { + throw new ArgumentException("In offline setting random tasks should be set to false"); + } + + // if tasks are not generated randomly they are taken from a preset list of tasks + if (! simulationManager.parameters.RandomTasks) + { + // release time allowed (online -> false, offline -> true) + simulationManager.remainingTasks = + new ReadTasks(simulationManager.tasksListFile, simulationManager.parameters.Matrix, + simulationManager.parameters.CodeEndPoint, ! simulationManager.online).ListOfTasks; + // in any case there should be at least simulationManager.parameters.NumberOfTasks in preset list of tasks + if (simulationManager.remainingTasks.Length < simulationManager.parameters.NumberOfTasks) + { + throw new ArgumentException("given predefined set of tasks should contain at least " + + "the given number of tasks"); + } + // in offline setting simulationManager.parameters.NumberOfTasks in preset list of tasks must be exactly + // equal to the length of the list of tasks + if (!simulationManager.online && simulationManager.remainingTasks.Length != + simulationManager.parameters.NumberOfTasks) + { + throw new ArgumentException("given predefined set of tasks should contain " + + "the given number of tasks"); + } + } + } + + public static void ShowCollisionMessage(ISimulationManager simulationManager) + { + GUI.Box(new Rect(50, 50, 100, 25), "Collision!"); + } + + /// <summary> + /// Set up robots using a prefab. Save the gameobject together with its instance id in <c> simulationManager.robotGameObjects </c> + /// and add th current node together with its istance id to <c> simulationManager.currentNodes </c>. + /// </summary> + /// <param name="simulationManager"></param> + /// <param name="robotPrefab"></param> + /// <typeparam name="T"></typeparam> + private static void SetUpRobots<T>(ISimulationManager simulationManager, GameObject robotPrefab) where T:IRobot + { + for (var i = 0; i < simulationManager.parameters.NumberOfRobots; i++) + { + var robot = MonoBehaviour.Instantiate(robotPrefab); + robot.GetComponent<T>().simulationManager = simulationManager; + simulationManager.robotGameObjects.Add(robot.GetInstanceID(), robot); + simulationManager.currentNodes.Add(robot.GetInstanceID(), simulationManager.parameters.InitialNodes[i]); + } + } + + /// <summary> + /// Set up side channels and send initial information on warehouse to Python code. + /// </summary> + /// <param name="simulationManager"></param> + private static void SetUpSideChannels(ISimulationManager simulationManager) + { + // create side channel for communication on the environment + simulationManager.envChannel = new EnvSideChannel(); + // The channel must be registered with the SideChannelManager class + SideChannelManager.RegisterSideChannel(simulationManager.envChannel); + // communicate info on environment to Python code through the SideChannel + var json = JsonConvert.SerializeObject( + new + { + matrixLayout = simulationManager.parameters.Matrix, + rotationRobot = simulationManager.parameters.Rotation, + sizeOfAction = simulationManager.actionSize, + sizeOfObservation = simulationManager.observationSize, + numberOfRobotsInEnv = simulationManager.parameters.NumberOfRobots, + initialNodesOfRobots = simulationManager.parameters.InitialNodes, + currentTasks = simulationManager.currentTasks.Keys, + numberOfCurrentTasks = simulationManager.parameters.NumberOfTasks, + backwards = simulationManager.parameters.CanGoBackWards, + instanceIDSRobots = simulationManager.robotGameObjects.Keys, + tasksGeneratedRandomly = simulationManager.parameters.RandomTasks + }); + simulationManager.envChannel.SendEnv(json); + + // create side channel for communication on tasks + simulationManager.taskChannel = new TaskSideChannel(); + SideChannelManager.RegisterSideChannel(simulationManager.taskChannel); + simulationManager.taskChannel.SimulationManager = simulationManager; + } + + /// <summary> + /// Set up behaviorparameters. + /// </summary> + /// <param name="simulationManager"></param> + private static void SetUpBehaviorParameters(ISimulationManager simulationManager) + { + MonoBehaviour simulationManagerMB = simulationManager.GetMonoBehaviour(); + var component = simulationManagerMB.GetComponent<BehaviorParameters>(); + // Set up the parameters of the behavioral component. + component.BrainParameters.VectorObservationSize + = simulationManager.parameters.NumberOfRobots*simulationManager.observationSize; + component.BrainParameters.ActionSpec + = ActionSpec.MakeDiscrete(new int [simulationManager.parameters.NumberOfRobots*simulationManager.actionSize]); + } + + /// <summary> + /// Create random colors as many as there are available tasks (at any point in time). They should be all different + /// and also not equal to the default tile/wall/endpoint/parking colors. + /// </summary> + /// <param name="simulationManager"></param> + private static void CreateColors(ISimulationManager simulationManager) + { + simulationManager.notAssignedColors = new HashSet<Color>(); + + var rand = new Random(); + while (simulationManager.notAssignedColors.Count < simulationManager.parameters.NumberOfTasks) + { + var randomColor = new Color( + (float) rand.NextDouble(), + (float) rand.NextDouble(), + (float) rand.NextDouble(), + 1 + ); + + if (!randomColor.Equals(simulationManager.colorWall) && !randomColor.Equals(simulationManager.colorTile) + && !randomColor.Equals(simulationManager.colorEndPoint) && + !randomColor.Equals(simulationManager.colorParking)) + { + simulationManager.notAssignedColors + .Add(randomColor); // if randomColor is already in notAssignedColors it will not be added + } + } + } + + /// <summary> + /// Setup Endpoints dictionary. Gameobjects will be created and added by the <c>Floor</c> script. + /// </summary> + /// <param name="simulationManager"></param> + private static void SetUpEndPoints(ISimulationManager simulationManager) + { + simulationManager.endPoints = new Dictionary<Position, GameObject>(); + + for (var row = 0; row < simulationManager.parameters.Matrix.Length; row++) + { + for (var column = 0; column < simulationManager.parameters.Matrix[0].Length; column++) + { + if (simulationManager.parameters.Matrix[row][column] == simulationManager.parameters.CodeEndPoint) + { + simulationManager.endPoints.Add(new Position(row, column), null); + } + } + } + } + + /// <summary> + /// Setup CurrentTasks: add tasks to <c> simulationManager.currentTasks </c> until we have + /// <c> simulationManager.parameters.NumberOfTaskss </c> tasks. Assign a color to each task. Initialize + /// <c> simulationManager.assignedColor </c> to keep track of assigned colors. + /// Initial coloring is done by the <c>Floor</c> script. + /// </summary> + /// <param name="simulationManager"></param> + private static void InitializeCurrentTasks(ISimulationManager simulationManager) + { + simulationManager.currentTasks = new Dictionary<Task, Color>(); + simulationManager.assignedColors = new HashSet<Color>(); + + while (simulationManager.currentTasks.Count < simulationManager.parameters.NumberOfTasks) + { + // get new task (this will not be null by the restriction that remainingTasks should have at least numberOfTasks elements) + var newTask = GetNewTask(simulationManager); + + // get color from notAssignedColors (will not be empty, we can always take element at index 0) and move to assignedColors + var color = simulationManager.notAssignedColors.ElementAt(0); + simulationManager.notAssignedColors.Remove(color); + simulationManager.assignedColors.Add(color); + + // add to currentTasks + simulationManager.currentTasks.Add(newTask, color); + } + } + + /// <summary> + /// Get a new task. + /// - If randomTasks == true, we create a new task that is not in currentTasks. + /// - If randomTasks == false, we get the next task from remainingTasks, if there are no tasks left return null. + /// </summary> + /// <param name="simulationManager"></param> + /// <returns>A new task</returns> + private static Task GetNewTask(ISimulationManager simulationManager) + { + //random task generation + if (simulationManager.parameters.RandomTasks) + { + var random = new Random(); + // get random endpoint as candidate for next pick up + var randomPickUp = simulationManager.endPoints.Keys.ElementAt(random.Next(0, simulationManager.endPoints.Count)); + // update randomPickUp until is not an endpoint in currentTasks + while (simulationManager.currentTasks.Any(task => task.Key.HasEndPoint(randomPickUp))) + { + randomPickUp = simulationManager.endPoints.Keys.ElementAt(random.Next(0, simulationManager.endPoints.Count)); + } + // get random endpoint as candidate for next delivery + var randomDelivery = simulationManager.endPoints.Keys.ElementAt(random.Next(0, simulationManager.endPoints.Count)); + //update randomDelivery until is not an endpoint in currentTasks and different from randomPickUp + while (simulationManager.currentTasks.Any(task => task.Key.HasEndPoint(randomDelivery)) + || randomDelivery.Equals(randomPickUp)) + { + randomDelivery = simulationManager.endPoints.Keys.ElementAt(random.Next(0, simulationManager.endPoints.Count)); + } + + return new Task(randomPickUp, randomDelivery,0); + } + + // non random task generation: we get next task from remainingTasks and update remainingTasks + + // there are no remaining tasks left + if (simulationManager.remainingTasks.Length == 0) + { + return null; + } + + // there are remaining tasks left + var newTask = simulationManager.remainingTasks[0]; + simulationManager.remainingTasks = simulationManager.remainingTasks.Skip(1).ToArray(); + return newTask; + } + + } +} \ No newline at end of file diff --git a/PickUpandDelivery/Assets/Scripts/Common/SimulationManager/SimulationManagerMethods.cs.meta b/PickUpandDelivery/Assets/Scripts/Common/SimulationManager/SimulationManagerMethods.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..b85ef31b92a6040395056edf8759a1ceace1266d --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/SimulationManager/SimulationManagerMethods.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: cd8f59650b1a42caa417c3842ef8806c +timeCreated: 1628858423 \ No newline at end of file diff --git a/PickUpandDelivery/Assets/Scripts/Common/UtilityMethods.meta b/PickUpandDelivery/Assets/Scripts/Common/UtilityMethods.meta new file mode 100644 index 0000000000000000000000000000000000000000..60296f45b4f36ed92b0fda5e4a1922d1984feafb --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/UtilityMethods.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ddc2bac031dc4237900a0faec627a6fd +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scripts/Common/Warehouse.meta b/PickUpandDelivery/Assets/Scripts/Common/Warehouse.meta new file mode 100644 index 0000000000000000000000000000000000000000..05f2a350aae902853017b79884c3d1db2ec82ac6 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/Warehouse.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 911a6d88db034382a0c812352f12439e +timeCreated: 1628838833 \ No newline at end of file diff --git a/PickUpandDelivery/Assets/Scripts/Common/Warehouse/Node.cs b/PickUpandDelivery/Assets/Scripts/Common/Warehouse/Node.cs new file mode 100644 index 0000000000000000000000000000000000000000..e2dabd56b9ee0682341efaf71745569b58a0005c --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/Warehouse/Node.cs @@ -0,0 +1,67 @@ +/* + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + + +namespace Common.Warehouse +{ + /// <summary> + /// Class <c> Node </c> represents the nodes in the graph. Every node contains + /// - a position (x,y) in the grid + /// - the difference in degrees with the direction north: + /// - 0 = North + /// - 90 = East + /// - 180 = South + /// - 270 = West + /// </summary> + + public class Node + { + public Position GridPosition { get; set; } + public int Degrees { get; } + + public Node(Position pos, int degrees) + { + GridPosition = pos; + Degrees = degrees; + } + + protected bool Equals(Node other) + { + return Equals(GridPosition, other.GridPosition) && Degrees == other.Degrees; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != this.GetType()) return false; + return Equals((Node) obj); + } + + public override int GetHashCode() + { + unchecked + { + return ((GridPosition != null ? GridPosition.GetHashCode() : 0) * 397) ^ Degrees; + } + } + + public override string ToString() + { + return "(" + GridPosition.Row + "," + GridPosition.Column + ")" + " " + Degrees; + } + } +} diff --git a/PickUpandDelivery/Assets/Scripts/Common/Warehouse/Node.cs.meta b/PickUpandDelivery/Assets/Scripts/Common/Warehouse/Node.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..c1332fd67db4a07ac8df46efb8df6ae36a0c26a2 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/Warehouse/Node.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 192efae1e20ced443998b710269bfeee +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scripts/Common/Warehouse/Position.cs b/PickUpandDelivery/Assets/Scripts/Common/Warehouse/Position.cs new file mode 100644 index 0000000000000000000000000000000000000000..69973cb6e99f53800fd3d68d121a1a5edec1e8cf --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/Warehouse/Position.cs @@ -0,0 +1,63 @@ +/* + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +namespace Common.Warehouse +{ + /// <summary> + /// A position in the grid is described by two integers Row and Column,e.g. + /// for a grid with dimensions 2 rows and 3 columns we have following positions + /// (0,0) (0,1) (0,2) + /// (1,0) (1,1) (1,2) + /// </summary> + + public class Position + { + public int Row { get; set; } + public int Column { get; set; } + + public Position(int row, int column) + { + Row = row; + Column = column; + } + + protected bool Equals(Position other) + { + return Row == other.Row && Column == other.Column; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != this.GetType()) return false; + return Equals((Position) obj); + } + + public override int GetHashCode() + { + unchecked + { + return (Row * 397) ^ Column; + } + } + + public override string ToString() + { + return "(" + Row + "," + Column + ")"; + } + } +} \ No newline at end of file diff --git a/PickUpandDelivery/Assets/Scripts/Common/Warehouse/Position.cs.meta b/PickUpandDelivery/Assets/Scripts/Common/Warehouse/Position.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..fd9da1efbff63704ba48101e50d5423fcd20af34 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/Warehouse/Position.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 31b30aafb0088be4aab3311716cb5315 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scripts/Common/Warehouse/ReadConfig.cs b/PickUpandDelivery/Assets/Scripts/Common/Warehouse/ReadConfig.cs new file mode 100644 index 0000000000000000000000000000000000000000..826b1aa592e2d79293c6df58418d71a3e5bfbc36 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/Warehouse/ReadConfig.cs @@ -0,0 +1,171 @@ +/* + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +using System; +using System.IO; +using Newtonsoft.Json; + +namespace Common.Warehouse +{ + /// <summary> + /// Class reads a json string and converting it to an object of the class WarehouseParameters. + /// does multiple checks on the resulting object + /// - CheckMatrix(): checks dimensions of the matrix and the values of the entries + /// - CheckRotation(): checks whether the unit of rotation is a divisor of 90 + /// - CheckNumberOfRobots(): checks whether for each robot exactly 1 initial node is given + /// - CheckValidityNodes(): checks whether the given initial nodes are valid nodes (the position should + /// correspond to a parking location in the matrix and the rotation should be a divisor of the unit of rotation) + /// - CheckNumberOfTasks(): checks whether there no more current tasks than the available endpoints can accomodate + /// </summary> + + public class ReadConfig + { + public WarehouseParameters Parameters { get; } + private int numberOfEndpoints; + + public ReadConfig(string pathToFile) + { + var jsonString = File.ReadAllText(pathToFile); + Parameters = JsonConvert.DeserializeObject<WarehouseParameters>(jsonString); + CheckMatrix(); + CheckRotation(); + CheckNumberOfRobots(); + CheckValidityNodes(); + CheckNumberOfTasks(); + } + + /// <summary> + /// Checks validity of rotation. + /// </summary> + /// <exception cref="ArgumentException"> thrown when the rotation is not a divisor of 90.</exception> + private void CheckRotation() + { + if (90 % Parameters.Rotation != 0) + { + throw new ArgumentException("Invalid rotation in config file"); + } + } + + /// <summary> + /// Checks number of initial nodes. + /// </summary> + /// <exception cref="ArgumentException"> thrown when number of initial nodes does not coincide + /// with given number of robots.</exception> + private void CheckNumberOfRobots() + { + if (Parameters.NumberOfRobots != Parameters.InitialNodes.Length) + { + throw new ArgumentException("Invalid number of robots in config file"); + } + } + + /// <summary> + /// Checks validity of initial nodes. + /// </summary> + /// <exception cref="ArgumentException"> thrown when an initial node is not a parking node + /// or an allowed rotation. </exception> + private void CheckValidityNodes() + { + for (var i = 0; i < Parameters.NumberOfRobots; i++) + { + var initialNode = Parameters.InitialNodes[i]; + if (Parameters.Matrix[initialNode.GridPosition.Row][initialNode.GridPosition.Column] != Parameters.CodeParking + || IsInvalidNodeRotation(initialNode.Degrees)) + { + throw new ArgumentException("Invalid initial node in config file: " + initialNode); + } + } + } + + /// <summary> + /// Checks shape of matrix and entries. Counts number of endpoints. + /// </summary> + /// <exception cref="ArgumentException"> thrown when matrix does not have correct shape or when entries are not valid</exception> + private void CheckMatrix() + { + var numberOfRows = Parameters.Matrix.Length; + if (numberOfRows == 0) + { + throw new ArgumentException("Matrix has length 0"); + } + + var numberOfColumns = Parameters.Matrix[0].Length; + + for (var row = 0; row < numberOfRows; row++) + { + // check shape + if (Parameters.Matrix[row].Length != numberOfColumns) + { + throw new ArgumentException("Matrix has incorrect shape"); + } + + for (var column = 0; column < numberOfColumns; column++) + { + if (IsInvalidCode(Parameters.Matrix[row][column])) + { + throw new ArgumentException("Matrix contains unaccepted value at position " + + "(" + row + "," + column + ")"); + } + + if (Parameters.Matrix[row][column] == Parameters.CodeEndPoint) + { + numberOfEndpoints++; + } + } + } + } + + /// <summary> + /// Checks whether the rotation is valid for nodes. + /// </summary> + /// <param name="rotation"> an int </param> + /// <returns> true when the unit of rotation is not a divisor of rotation</returns> + private bool IsInvalidNodeRotation(int rotation) + { + return rotation % Parameters.Rotation != 0; + } + + /// <summary> + /// Checks whether it is a valid code. + /// </summary> + /// <param name="code"></param> + /// <returns> true when the given code is not valid.</returns> + private bool IsInvalidCode(int code) + { + return code != Parameters.CodeWall + && code != Parameters.CodeTile + && code != Parameters.CodeParking + && code != Parameters.CodeEndPoint; + } + + /// <summary> + /// Checks whether the number of tasks is not more than the endpoints can accomodate, i.e. endpoints/2. + /// Do not call this method before CheckMatrix(). + /// </summary> + /// <exception cref="ArgumentException"> thrown when there are no endpoints or when there are too many tasks</exception> + private void CheckNumberOfTasks() + { + if (numberOfEndpoints == 0) + { + throw new ArgumentException("There are no endpoints. Did you run Checkmatrix()?"); + } + if (Parameters.NumberOfTasks > numberOfEndpoints / 2) + { + throw new ArgumentException("Invalid number of tasks, not enough endpoints"); + } + } + } +} diff --git a/PickUpandDelivery/Assets/Scripts/Common/Warehouse/ReadConfig.cs.meta b/PickUpandDelivery/Assets/Scripts/Common/Warehouse/ReadConfig.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..d90c1b489f0716c655e49760feb09a2af960a648 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/Warehouse/ReadConfig.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 12faaaf5e8d363f4b8d5a75aafc56fe2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scripts/Common/Warehouse/ReadTasks.cs b/PickUpandDelivery/Assets/Scripts/Common/Warehouse/ReadTasks.cs new file mode 100644 index 0000000000000000000000000000000000000000..4c0c2b22d1b04fd90d71694fe70c7caa9ef617a2 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/Warehouse/ReadTasks.cs @@ -0,0 +1,70 @@ +/* + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + + +using System; +using System.IO; +using Newtonsoft.Json; + +namespace Common.Warehouse +{ + /// <summary> + /// Class <c> ReadTasks </c> is used to read a preset list of tasks (json format). It converts the list to + /// an instance of Task[] and will only be called in the offline problem setting. + /// Does multiple checks on the resulting object: + /// - every tasks has to be a valid endpoint and has to correspond to the correct code in the config matrix + /// - whether release time is allowed or not + /// </summary> + public class ReadTasks + { + public Task[] ListOfTasks; + private int[][] Matrix; + private int EndPointCode; + private bool ReleaseTimeAllowed; + + public ReadTasks(string pathToFile, int[][] matrix, int endPointCode, bool releaseTimeAllowed) + { + Matrix = matrix; + var jsonString = File.ReadAllText(pathToFile); + ListOfTasks = JsonConvert.DeserializeObject<Task[]>(jsonString); + EndPointCode = endPointCode; + ReleaseTimeAllowed = releaseTimeAllowed; + CheckInput(); + } + + // check whether pickup and delivery correspond to the correct number in the matrix + private void CheckInput() + { + foreach(var task in ListOfTasks) + { + if (Matrix[task.PickUp.Row][task.PickUp.Column] != EndPointCode) + { + throw new ArgumentException("Invalid task pickup " + task.PickUp); + } + if (Matrix[task.Delivery.Row][task.Delivery.Column] != EndPointCode) + { + throw new ArgumentException("Invalid task deliver " + task.Delivery); + } + + if (!ReleaseTimeAllowed && task.ReleaseTime != 0) + { + throw new ArgumentException("Releasetime task cannot be equal to zero " + task.PickUp + " " + + task.Delivery); + } + } + } + } +} diff --git a/PickUpandDelivery/Assets/Scripts/Common/Warehouse/ReadTasks.cs.meta b/PickUpandDelivery/Assets/Scripts/Common/Warehouse/ReadTasks.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..2f1bf911cc1f3bf5b117c7ad9eee104a42e5dd8a --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/Warehouse/ReadTasks.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 50ade04715a988d4d8eac455082416b2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scripts/Common/Warehouse/Task.cs b/PickUpandDelivery/Assets/Scripts/Common/Warehouse/Task.cs new file mode 100644 index 0000000000000000000000000000000000000000..d90ffb3b2b881c05189a8a5fcad82a1c92696ffa --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/Warehouse/Task.cs @@ -0,0 +1,76 @@ +/* + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +using System.ComponentModel; +using Newtonsoft.Json; + +namespace Common.Warehouse +{ + /// <summary> + /// Class <c> Task </c> represents a task. A task consists of 2 positions: a pick up and a delivery position and a release time. + /// Default release time equals 0. + /// + /// contains instance method + /// - HasEndPoint(Position pos): checks whether pos is an endpoint (pick up or delivery) of the task + /// </summary> + public class Task + { + public Position PickUp { get; set; } + public Position Delivery { get; set; } + + [DefaultValue(0)] + [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)] + public int ReleaseTime { get; set; } + + public Task(Position pickUp, Position delivery, int releaseTime) + { + PickUp = pickUp; + Delivery = delivery; + ReleaseTime = releaseTime; + } + + // check whether a position is an endpoint of a task + public bool HasEndPoint(Position pos) + { + return pos.Equals(PickUp) || pos.Equals(Delivery); + } + + protected bool Equals(Task other) + { + return Equals(PickUp, other.PickUp) && Equals(Delivery, other.Delivery) && ReleaseTime == other.ReleaseTime; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != this.GetType()) return false; + return Equals((Task) obj); + } + + public override int GetHashCode() + { + unchecked + { + var hashCode = (PickUp != null ? PickUp.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (Delivery != null ? Delivery.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ ReleaseTime; + return hashCode; + } + } + + } +} diff --git a/PickUpandDelivery/Assets/Scripts/Common/Warehouse/Task.cs.meta b/PickUpandDelivery/Assets/Scripts/Common/Warehouse/Task.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..ad3b93b8ac7e92d8013bba97bad2b1cabf056426 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/Warehouse/Task.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8bbe96fcd2953ed4b9c3fdee2b6ccc1d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scripts/Common/Warehouse/UtilityMethods.cs b/PickUpandDelivery/Assets/Scripts/Common/Warehouse/UtilityMethods.cs new file mode 100644 index 0000000000000000000000000000000000000000..06adb2fe93e9a97a63b90189f80e7113dc5579e4 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/Warehouse/UtilityMethods.cs @@ -0,0 +1,40 @@ +/* + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +using UnityEngine; + +namespace Common.Warehouse +{ + /// <summary> + /// Static class <c> UtilityMethods </c> contains static helper methods. + /// </summary> + + public static class UtilityMethods + { + /// <summary> + /// Returns complementary color. + /// </summary> + /// <param name="color"></param> + /// <returns>the complementary color</returns> + public static Color GetNegativeColor(Color color) + { + Color.RGBToHSV(color, out float H, out float S, out float V); + float negativeH = (H + 0.5f) % 1f; + return Color.HSVToRGB(negativeH, S, V); + } + } + +} \ No newline at end of file diff --git a/PickUpandDelivery/Assets/Scripts/Common/Warehouse/UtilityMethods.cs.meta b/PickUpandDelivery/Assets/Scripts/Common/Warehouse/UtilityMethods.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..4daac6d5cd73cf85b3440f6134fd85e22d2bb0e2 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/Warehouse/UtilityMethods.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: fc3d6a786841450292dc559c0be8cb2f +timeCreated: 1628848095 \ No newline at end of file diff --git a/PickUpandDelivery/Assets/Scripts/Common/Warehouse/WarehouseParameters.cs b/PickUpandDelivery/Assets/Scripts/Common/Warehouse/WarehouseParameters.cs new file mode 100644 index 0000000000000000000000000000000000000000..135953c6d534a5af7872869b4ba5ccc97c4495b9 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/Warehouse/WarehouseParameters.cs @@ -0,0 +1,46 @@ +/* + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + + +namespace Common.Warehouse +{ + /// <summary> + /// Class <c> WarehouseParameters </c> contains all parameters needed to set up the warehouse. + /// </summary> + + public class WarehouseParameters + { + public int[][] Matrix { get; set; } // 1 is wall, 0 is tile, 2 is endpoint (pick up or delivery), 3 is parking + + public int Rotation { get; set; } // unit of rotation + public int TimeRobotPerTile { get; set; } // time needed to traverse one tile + + public int NumberOfRobots { get; set; } + public Node[] InitialNodes { get; set; } + + public int NumberOfTasks { get; set; } // at all times there will be this number of tasks to be done + + public bool CanGoBackWards { get; set; } // robot can go backwards + + public bool RandomTasks { get; set; } // whether tasks are created random or taken from list + + // codes for matrix entries + public readonly int CodeWall = 1; + public readonly int CodeTile = 0; + public readonly int CodeEndPoint = 3; + public readonly int CodeParking = 2; + } +} diff --git a/PickUpandDelivery/Assets/Scripts/Common/Warehouse/WarehouseParameters.cs.meta b/PickUpandDelivery/Assets/Scripts/Common/Warehouse/WarehouseParameters.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..4596e3b46bb250696629a500ee8d5dda622240d5 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Common/Warehouse/WarehouseParameters.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 810902285cb122d4cb8ceec8fa99aa9f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scripts/Offline_Centralized.meta b/PickUpandDelivery/Assets/Scripts/Offline_Centralized.meta new file mode 100644 index 0000000000000000000000000000000000000000..7bbad8183aa6465f04c21a4f444efddab7c31ff6 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Offline_Centralized.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 125388dc41b974b4f9620a18d4842943 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scripts/Offline_Centralized/RobotOfflineCentralized.cs b/PickUpandDelivery/Assets/Scripts/Offline_Centralized/RobotOfflineCentralized.cs new file mode 100644 index 0000000000000000000000000000000000000000..7dddb615cbf73f83d3235ff66e61eb14cc5afc52 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Offline_Centralized/RobotOfflineCentralized.cs @@ -0,0 +1,90 @@ +/* + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + + +using Common.Robot; +using Common.SimulationManager; +using Common.Warehouse; +using UnityEngine; + +/// <summary> +/// Script <c> RobotOnlineDecentralized </c> +/// has public instance methods: +/// - GetMonoBehaviour(): return instance as Monobehaviour +/// - AssignTask(Task task): assign a task to robot and update color of robot accordingly +/// - PickUp(): after picking up, a cross is drawn on top of the robot using the complementary color of the task +/// - Deliver(): calls RemoveTask() and returns delivered task +/// has private instance methods: +/// - OnTriggerEnter(Collider other) for collision detection +/// </summary> +public class RobotOfflineCentralized : MonoBehaviour, IRobot +{ + public ISimulationManager simulationManager { get; set; } + + public Task assignedTask { get; set; } = null; // the task a robot is assigned, mainly used for coloring + [SerializeField] private Material idleColor = default; // color when no task assigned + + void Start() + { + RobotMethods.InitializeRobotAtStart(this); + } + + void FixedUpdate() + { + RobotMethods.UpdatePosition(this); + } + + /// <summary> + /// Return this as MonoBehaviour. + /// </summary> + /// <returns></returns> + public MonoBehaviour GetMonoBehaviour() + { + return this; + } + + // collision handling + private void OnTriggerEnter(Collider other) + { + RobotMethods.CollisionEvent(this); + } + + /// <summary> + /// Assign task to robot. + /// </summary> + /// <param name="task"> a Task object</param> + public void AssignTask(Task task) + { + RobotMethods.AssignTask(this, task); + } + + /// <summary> + /// Pick up. + /// </summary> + public void PickUp() + { + RobotMethods.PickUp(this); + } + + /// <summary> + /// Delivery. + /// </summary> + /// <returns>the delivered task</returns> + public Task Deliver() + { + return RobotMethods.Deliver(this, idleColor.color); + } +} \ No newline at end of file diff --git a/PickUpandDelivery/Assets/Scripts/Offline_Centralized/RobotOfflineCentralized.cs.meta b/PickUpandDelivery/Assets/Scripts/Offline_Centralized/RobotOfflineCentralized.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..504752fbabf7d90204f43f2609538c60f5de30aa --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Offline_Centralized/RobotOfflineCentralized.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 54b9a4088e4329849b24b0da23b5d39d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scripts/Offline_Centralized/SimulationManagerOfflineCentralized.cs b/PickUpandDelivery/Assets/Scripts/Offline_Centralized/SimulationManagerOfflineCentralized.cs new file mode 100644 index 0000000000000000000000000000000000000000..8e35665fabe9fb3b281bb4e53f5f5f33d2496b35 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Offline_Centralized/SimulationManagerOfflineCentralized.cs @@ -0,0 +1,219 @@ +/* + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +using System.Collections.Generic; +using System; +using System.IO; +using UnityEngine; +using Unity.MLAgents.SideChannels; +using Newtonsoft.Json; +using System.Linq; +using Common.Scripts; +using Common.SideChannels; +using Common.SimulationManager; +using Common.Warehouse; +using Unity.MLAgents; +using Unity.MLAgents.Actuators; +using Unity.MLAgents.Policies; +using Unity.MLAgents.Sensors; +using Random = System.Random; + +/// <summary> +/// Class <c> SimulationManagerOfflineCentralized </c> controls the simulation for the Offline Centralized Pick Up and +/// Delivery problem. +/// +/// The only fields that should be altered here is warehouseConfigFile, the path to the txt file containing +/// the configurable parameters of the simulation and the path to the preset tasks. +/// +/// Has instance methods: +/// - GetMonoBehaviour(): return object as monobehaviour +/// - GetCurrentNode(int instanceID): get current node for a robot with given instance ID +/// - RemoveTask(Task task): remove a tasks from current tasks +/// - AddNewTask(): add a new task to current tasks +/// - AssignTask(Task task, int instanceID): assign a task to a robot with given instance ID +/// </summary>. + + +public class SimulationManagerOfflineCentralized : Agent, ISimulationManager +{ + public string warehouseConfigFile { get; } = "ConfigurationFiles/Offline_Centralized/warehousejson.txt"; + public string tasksListFile { get; }= "ConfigurationFiles/Offline_Centralized/tasks_releasetime.txt"; + + // online or offline + public bool online { get; } = false; + + private int counter; // Count time in ms (used in advance method), to make sure every timeRobotPerTile a new action or node is given + + // colors + // colors for walls, tiles and prefabs + public Color colorWall { get; } = Color.black; + public Color colorTile { get; } = Color.white; + public Color colorEndPoint { get; }= new Color(0.5f, 0.5f, 1f); // blue-ish + public Color colorParking { get; } = Color.gray; + + // colors for tasks and the robots that have been assigned these tasks + public HashSet<Color> assignedColors { get; set; } = new HashSet<Color>(); + public HashSet<Color> notAssignedColors { get; set; } = new HashSet<Color>(); + + // endpoints + // dictionary containing all endpoints + // every endpoint will point to a gameobject, this will be setup by the Floor script + public Dictionary<Position, GameObject> endPoints { get; set; }= new Dictionary<Position, GameObject>(); + + // parameters of warehouse + public WarehouseParameters parameters { get; set; } + + // tasks + // at every timestep there will be max numberOfTasks tasks that have to be assigned (by the python code), in + // the offline setting this has to be same as the number of preset tasks + // current available tasks and their assigned colors: these are the tasks to remain to be assigned to robots + public Dictionary<Task, Color> currentTasks { get; set; } = new Dictionary<Task, Color>(); + // all remaining tasks, used to store tasks read from file + public Task[] remainingTasks { get; set; } + + // robots + [SerializeField] private GameObject robotPrefab = default; // GameObject prefab used for the robot + + // For every robot the current node where he is going, i.e. the next action + public Dictionary<int, Node> currentNodes { get; } = new Dictionary<int, Node>(); + + // For every robot the corresponding gameobject + public Dictionary<int, GameObject> robotGameObjects { get; set; } = new Dictionary<int, GameObject>(); + + // environment variables + // check for collisions + public bool collisions { get; set; } + + // observations and actions + public int observationSize { get; }= 4; // id,x,y,rotation + public int actionSize { get; } = 6; // id,x,y,rotation,pick up, delivery + + // environment variables for drawing + public float + SIZE { get; } = 1; // Size of square/tile, this is kept constant to avoid having to change camera perspective + + public float SCALEROBOT { get; } = 0.49f; // Ratio robot to tile, for drawing robot + public float YROBOTFLOATING { get; }= 0.2f; // Floating y value robot, for drawing robot + + // sidechannels + public EnvSideChannel envChannel { get; set; } // SideChannel for communication initial environment parameters + public TaskSideChannel taskChannel { get; set; } // SideChannel for communication on tasks + + void Awake() + { + SimulationManagerMethods.SetUpWarehouse<RobotOfflineCentralized>(this, robotPrefab, true); + } + + /// <summary> + /// Return this as MonoBehaviour. + /// </summary> + /// <returns></returns> + public MonoBehaviour GetMonoBehaviour() + { + return this; + } + + /// <summary> + /// Every timeRobotPerTile a new decision is requested: observations are collected (<c>CollectObservations</c>) and actions are received + /// (<c>OnActionReceived</c>) + /// </summary> + public void FixedUpdate() + { + counter += 20; // FixedUpdate is called every 20ms, add 20ms to counter + // if counter has passed timeRobotPerTile and there is a python client listening new actions are requested + // if a collisions has been detected no new requests are made + if (counter >= parameters.TimeRobotPerTile && Academy.Instance.IsCommunicatorOn) + { + if (!collisions) + { + RequestDecision(); // manually request a decision + } + + counter = 0; // reset counter + } + } + + /// <summary> + /// Collect observations, will be executed when requested. + /// Note that the number of observations per robot should be equal to <c>ObservationSize</c>. + /// </summary> + /// <param name="sensor"></param> + public override void CollectObservations(VectorSensor sensor) + { + SimulationManagerMethods.CollectObservations(this, sensor); + } + + /// <summary> + /// Receive actions, will be executed when requested. + /// Note that the number of actions per robot should be equal to <c>ActionSize</c>. + /// </summary> + public override void OnActionReceived(ActionBuffers actionBuffers) + { + SimulationManagerMethods.OnActionReceived<RobotOfflineCentralized>(this,actionBuffers); + } + + /// <summary> + /// Show message when a collision has occured. + /// </summary> + private void OnGUI() + { + if (collisions) + { + SimulationManagerMethods.ShowCollisionMessage(this); + } + } + + /// <summary> + /// Returns current node, i.e. the next node to go to, for a robot with a given instance ID. + /// </summary> + /// <param name="instanceID"> an int</param> + /// <returns> A node corresponding to the current node.</returns> + public Node GetCurrentNode(int instanceID) + { + return SimulationManagerMethods.GetCurrentNode(this,instanceID); + } + + /// <summary> + /// Remove a task from CurrentTasks. Reset color of pick up and delivery endpoints. + /// Make color available. + /// </summary> + /// <param name="task"></param> + /// <exception cref="Exception">thrown if it was not assigned to a robot</exception> + public void RemoveTask(Task task) + { + SimulationManagerMethods.RemoveTask(this, task); + } + + /// <summary> + /// Add a task to currentTasks if there are still tasks available. Assign a color and send information to python code. + /// </summary> + /// <exception cref="Exception">thrown when currentTasks has already reached capacity</exception> + public void AddNewTask() + { + SimulationManagerMethods.AddNewTask(this); + } + + /// <summary> + /// Assign a task to a robot with a given instanceID. + /// </summary> + /// <param name="task"></param> + /// <param name="instanceID"></param> + public void AssignTask(Task task, int instanceID) + { + SimulationManagerMethods.AssignTask<RobotOfflineCentralized>(this, task, instanceID); + } +} + diff --git a/PickUpandDelivery/Assets/Scripts/Offline_Centralized/SimulationManagerOfflineCentralized.cs.meta b/PickUpandDelivery/Assets/Scripts/Offline_Centralized/SimulationManagerOfflineCentralized.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..6d05e96b6804a89d5eb6bd7683ef73f7189e1009 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Offline_Centralized/SimulationManagerOfflineCentralized.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ec6a5fb578df5504186ba78f15f70a56 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scripts/Offline_Decentralized.meta b/PickUpandDelivery/Assets/Scripts/Offline_Decentralized.meta new file mode 100644 index 0000000000000000000000000000000000000000..9eb4f284b983de8ee07f3f68b610a085b5768b39 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Offline_Decentralized.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c819bbdde6c1a9143a5866dbd9669aa0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scripts/Offline_Decentralized/RobotOfflineDecentralized.cs b/PickUpandDelivery/Assets/Scripts/Offline_Decentralized/RobotOfflineDecentralized.cs new file mode 100644 index 0000000000000000000000000000000000000000..fe2a58e17db8ddab215ed704284098f418058054 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Offline_Decentralized/RobotOfflineDecentralized.cs @@ -0,0 +1,135 @@ +/* + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + + +using System; +using System.Linq; +using Common.Robot; +using Common.SimulationManager; +using Common.Warehouse; +using Unity.MLAgents; +using Unity.MLAgents.Actuators; +using Unity.MLAgents.Sensors; +using UnityEngine; + +/// <summary> +/// Script <c> RobotOfflineDecentralized </c> +/// has public instance methods: +/// - GetMonoBehaviour(): return instance as Monobehaviour +/// - AssignTask(Task task): assign a task to robot and update color of robot accordingly +/// - CollectObservations(VectorSensor sensor): collect an observation +/// - OnActionReceived(ActionBuffers actionBuffers): do action +/// - Pickup() and Delivery(): unused methods from interface IRobot +/// has private instance methods: +/// - OnTriggerEnter(Collider other) for collision detection +/// </summary> +public class RobotOfflineDecentralized : Agent, IRobot +{ + public ISimulationManager simulationManager { get; set; } + + private int + counter; // Count time in ms (used in advance method), to make sure every timeRobotPerTile a new action or node is given + + public Task assignedTask { get; set; } = null; // the task a robot is assigned, mainly used for coloring + [SerializeField] private Material idleColor = default; // color when no task assigned + + void Start() + { + RobotMethods.InitializeRobotAtStart(this); + } + + + /// <summary> + /// Every timeRobotPerTile a new decision is requested: observations are collected (<c>CollectObservations</c>) and actions are received + /// (<c>OnActionReceived</c>). + /// </summary> + void FixedUpdate() + { + counter += 20; // FixedUpdate is called every 20ms, add 20ms to counter + // if counter has passed timeRobotPerTile and there is a python client listening new actions are requested + // if a collisions has been detected no new requests are made + if (counter >= simulationManager.parameters.TimeRobotPerTile && Academy.Instance.IsCommunicatorOn) + { + if (!simulationManager.collisions) + { + Debug.Log("request by " + gameObject.GetInstanceID()); + RequestDecision(); // manually request a decision + } + + counter = 0; // reset counter + } + RobotMethods.UpdatePosition(this); + } + + /// <summary> + /// Return this as MonoBehaviour. + /// </summary> + /// <returns></returns> + public MonoBehaviour GetMonoBehaviour() + { + return this; + } + + /// <summary> + /// Collect observation, will be executed when requested. + /// </summary> + /// <param name="sensor"></param> + public override void CollectObservations(VectorSensor sensor) + { + RobotMethods.CollectObservations(this,sensor); + } + + /// <summary> + /// Do action when received, will be executed when requested. + /// </summary> + /// <param name="actionBuffers"></param> + public override void OnActionReceived(ActionBuffers actionBuffers) + { + RobotMethods.OnActionReceived(this, actionBuffers, idleColor.color); + } + + // collision handling + private void OnTriggerEnter(Collider other) + { + RobotMethods.CollisionEvent(this); + } + + /// <summary> + /// Assign task to robot. + /// </summary> + /// <param name="task"> a Task object</param> + public void AssignTask(Task task) + { + RobotMethods.AssignTask(this, task); + } + + /// <summary> + /// Pick up. + /// </summary> + public void PickUp() + { + RobotMethods.PickUp(this); + } + + /// <summary> + /// Delivery. + /// </summary> + /// <returns>the delivered task</returns> + public Task Deliver() + { + return RobotMethods.Deliver(this, idleColor.color); + } +} diff --git a/PickUpandDelivery/Assets/Scripts/Offline_Decentralized/RobotOfflineDecentralized.cs.meta b/PickUpandDelivery/Assets/Scripts/Offline_Decentralized/RobotOfflineDecentralized.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..fe499e5080631e0c05cd4d65b0fc146b4fec55ae --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Offline_Decentralized/RobotOfflineDecentralized.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e224beeb8f8781f479c65279d3e07a01 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scripts/Offline_Decentralized/SimulationManagerOfflineDecentralized.cs b/PickUpandDelivery/Assets/Scripts/Offline_Decentralized/SimulationManagerOfflineDecentralized.cs new file mode 100644 index 0000000000000000000000000000000000000000..c6f0d22e7530e21a350006dfa2548fddb2bb281e --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Offline_Decentralized/SimulationManagerOfflineDecentralized.cs @@ -0,0 +1,173 @@ +/* + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +using System.Collections.Generic; +using System; +using System.IO; +using UnityEngine; +using Unity.MLAgents.SideChannels; +using Newtonsoft.Json; +using System.Linq; +using Common.Scripts; +using Common.SideChannels; +using Common.SimulationManager; +using Common.Warehouse; +using Random = System.Random; + +/// <summary> +/// Class <c> SimulationManagerOfflineDecentralized </c> controls the simulation for the Offline Decentralized Pick Up and +/// Delivery problem. +/// +/// The only fields that should be altered here is warehouseConfigFile, the path to the txt file containing +/// the configurable parameters of the simulation and the path to the preset tasks. +/// +/// Has instance methods: +/// - GetMonoBehaviour(): return object as monobehavior +/// - GetCurrentNode(int instanceID): get current node for a robot with given instance ID +/// - RemoveTask(Task task): remove a tasks from current tasks +/// - AddNewTask(): add a new task to current tasks +/// - AssignTask(Task task, int instanceID): assign a task to a robot with given instance ID +/// </summary> + + +public class SimulationManagerOfflineDecentralized : MonoBehaviour, ISimulationManager +{ + public string warehouseConfigFile { get; }= "ConfigurationFiles/Offline_Decentralized/warehousejson.txt"; + public string tasksListFile { get; }= "ConfigurationFiles/Offline_Decentralized/tasks_releasetime.txt"; + + // online or offline + public bool online { get; } = false; + + // colors + // colors for walls, tiles and prefabs + public Color colorWall { get; } = Color.black; + public Color colorTile { get; } = Color.white; + public Color colorEndPoint { get; }= new Color(0.5f, 0.5f, 1f); // blue-ish + public Color colorParking { get; } = Color.gray; + + // colors for tasks and the robots that have been assigned these tasks + public HashSet<Color> assignedColors { get; set; } = new HashSet<Color>(); + public HashSet<Color> notAssignedColors { get; set; } = new HashSet<Color>(); + + // endpoints + // dictionary containing all endpoints + // every endpoint will point to a gameobject, this will be setup by the Floor script + public Dictionary<Position, GameObject> endPoints { get; set; }= new Dictionary<Position, GameObject>(); + + // parameters of warehouse + public WarehouseParameters parameters { get; set; } + + // tasks + // at every timestep there will be max numberOfTasks tasks that have to be assigned (by the python code), in + // the offline setting this has to be same as the number of preset tasks + // current available tasks and their assigned colors: these are the tasks to remain to be assigned to robots + public Dictionary<Task, Color> currentTasks { get; set; } = new Dictionary<Task, Color>(); + // all remaining tasks, used to store tasks read from file + public Task[] remainingTasks { get; set; } + + // robots + [SerializeField] private GameObject robotPrefab = default; // GameObject prefab used for the robot + + // For every robot the current node where he is going, i.e. the next action + public Dictionary<int, Node> currentNodes { get; } = new Dictionary<int, Node>(); + + // For every robot the corresponding gameobject + public Dictionary<int, GameObject> robotGameObjects { get; set; } = new Dictionary<int, GameObject>(); + + // environment variables + // check for collisions + public bool collisions { get; set; } + + // observations and actions + public int observationSize { get; }= 4; //id,x,y,rotation + public int actionSize { get; } = 5; //x,y,rotation,pick up, delivery + + // environment variables for drawing + public float + SIZE { get; } = 1; // Size of square/tile, this is kept constant to avoid having to change camera perspective + + public float SCALEROBOT { get; } = 0.49f; // Ratio robot to tile, for drawing robot + public float YROBOTFLOATING { get; }= 0.2f; // Floating y value robot, for drawing robot + + // sidechannels + public EnvSideChannel envChannel { get; set; } // SideChannel for communication initial environment parameters + public TaskSideChannel taskChannel { get; set; } // SideChannel for communication on tasks + + void Awake() + { + SimulationManagerMethods.SetUpWarehouse<RobotOfflineDecentralized>(this, robotPrefab, false); + } + + /// <summary> + /// Return this as MonoBehaviour. + /// </summary> + /// <returns></returns> + public MonoBehaviour GetMonoBehaviour() + { + return this; + } + + /// <summary> + /// Show message when a collision has occured. + /// </summary> + public void OnGUI() + { + if (collisions) + { + SimulationManagerMethods.ShowCollisionMessage(this); + } + } + + /// <summary> + /// Returns current node, i.e. the next node to go to, for a robot with a given instance ID. + /// </summary> + /// <param name="instanceID"> an int</param> + /// <returns> A node corresponding to the current node.</returns> + public Node GetCurrentNode(int instanceID) + { + return SimulationManagerMethods.GetCurrentNode(this,instanceID); + } + + /// <summary> + /// Remove a task from CurrentTasks that was assigned to a robot. + /// </summary> + /// <param name="task"></param> + /// <exception cref="Exception">thrown if it was not assigned to a robot</exception> + public void RemoveTask(Task task) + { + SimulationManagerMethods.RemoveTask(this, task); + } + + /// <summary> + /// Add a task to currentTasks if there are still tasks available. Assign a color and send information to python code. + /// </summary> + /// <exception cref="Exception">thrown when currentTasks has already reached capacity</exception> + public void AddNewTask() + { + SimulationManagerMethods.AddNewTask(this); + } + + /// <summary> + /// Assign a task to a robot with a given instanceID. + /// </summary> + /// <param name="task"></param> + /// <param name="instanceID"></param> + public void AssignTask(Task task, int instanceID) + { + SimulationManagerMethods.AssignTask<RobotOfflineDecentralized>(this, task, instanceID); + } +} + diff --git a/PickUpandDelivery/Assets/Scripts/Offline_Decentralized/SimulationManagerOfflineDecentralized.cs.meta b/PickUpandDelivery/Assets/Scripts/Offline_Decentralized/SimulationManagerOfflineDecentralized.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..9b690ed9a0c7b40954dc07699918f57f0881d7f9 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Offline_Decentralized/SimulationManagerOfflineDecentralized.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 00bf636c107a31d489dc615292930654 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scripts/Online_Centralized.meta b/PickUpandDelivery/Assets/Scripts/Online_Centralized.meta new file mode 100644 index 0000000000000000000000000000000000000000..d22a27c7180498ecd4b764b76c6c574b1fff08a2 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Online_Centralized.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 16849455029256649b94eab199627f93 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scripts/Online_Centralized/RobotOnlineCentralized.cs b/PickUpandDelivery/Assets/Scripts/Online_Centralized/RobotOnlineCentralized.cs new file mode 100644 index 0000000000000000000000000000000000000000..2803a4333c420edb2c16900c9b1d8c730d1c1c13 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Online_Centralized/RobotOnlineCentralized.cs @@ -0,0 +1,90 @@ +/* + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +using Common.Robot; +using Common.SimulationManager; +using Common.Warehouse; +using UnityEngine; + +/// <summary> +/// Script <c> RobotOnlineCentralized </c> +/// has public instance methods: +/// - GetMonoBehaviour(): return instance as Monobehaviour +/// - AssignTask(Task task): assign a task to robot and update color of robot accordingly +/// - PickUp(): after picking up, a cross is drawn on top of the robot using the complementary color of the task +/// - Deliver(): calls RemoveTask() and returns delivered task +/// has private instance methods: +/// - OnTriggerEnter(Collider other) for collision detection +/// </summary> + +public class RobotOnlineCentralized : MonoBehaviour, IRobot +{ + public ISimulationManager simulationManager { get; set; } + + public Task assignedTask { get; set; } = null; // the task a robot is assigned, mainly used for coloring + [SerializeField] private Material idleColor = default; // color when no task assigned + + void Start() + { + RobotMethods.InitializeRobotAtStart(this); + } + + void FixedUpdate() + { + RobotMethods.UpdatePosition(this); + } + + /// <summary> + /// Return this as MonoBehaviour. + /// </summary> + /// <returns></returns> + public MonoBehaviour GetMonoBehaviour() + { + return this; + } + + // collision handling + private void OnTriggerEnter(Collider other) + { + RobotMethods.CollisionEvent(this); + } + + /// <summary> + /// Assign task to robot. + /// </summary> + /// <param name="task"> a Task object</param> + public void AssignTask(Task task) + { + RobotMethods.AssignTask(this, task); + } + + /// <summary> + /// Pick up. + /// </summary> + public void PickUp() + { + RobotMethods.PickUp(this); + } + + /// <summary> + /// Delivery. + /// </summary> + /// <returns>the delivered task</returns> + public Task Deliver() + { + return RobotMethods.Deliver(this, idleColor.color); + } +} diff --git a/PickUpandDelivery/Assets/Scripts/Online_Centralized/RobotOnlineCentralized.cs.meta b/PickUpandDelivery/Assets/Scripts/Online_Centralized/RobotOnlineCentralized.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..1814ac0aed389c9765ca48f8cfc78d1f1ea498e7 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Online_Centralized/RobotOnlineCentralized.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0ee9f4e10c142784c91290b59532cb09 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scripts/Online_Centralized/SimulationManagerOnlineCentralized.cs b/PickUpandDelivery/Assets/Scripts/Online_Centralized/SimulationManagerOnlineCentralized.cs new file mode 100644 index 0000000000000000000000000000000000000000..9cb299d077f184010af2d1195a4a79c9624d5ec9 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Online_Centralized/SimulationManagerOnlineCentralized.cs @@ -0,0 +1,211 @@ +/* + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +using System.Collections.Generic; +using System; +using UnityEngine; +using Common.SideChannels; +using Common.SimulationManager; +using Common.Warehouse; +using Unity.MLAgents; +using Unity.MLAgents.Actuators; +using Unity.MLAgents.Sensors; + +/// <summary> +/// Class <c> SimulationManagerOnlineCentralized </c> controls the simulation for the Online Centralized Pick Up and +/// Delivery problem. +/// +/// The only field that should be altered here is warehouseConfigFile, the path to the txt file containing +/// the configurable parameters of the simulation. Optionally a preset set of tasks. +/// +/// Has instance methods: +/// - GetMonoBehaviour(): return object as monobehaviour +/// - GetCurrentNode(int instanceID): get current node for a robot with given instance ID +/// - RemoveTask(Task task): remove a tasks from current tasks +/// - AddNewTask(): add a new task to current tasks +/// - AssignTask(Task task, int instanceID): assign a task to a robot with given instance ID +/// </summary> + + +public class SimulationManagerOnlineCentralized : Agent, ISimulationManager +{ + //public string warehouseConfigFile {get;} = "ConfigurationFiles/Online_Centralized/warehousejson_random.txt"; + public string warehouseConfigFile { get; } = "ConfigurationFiles/Online_Centralized/warehousejson_not_random.txt"; + public string tasksListFile { get; }= "ConfigurationFiles/Online_Centralized/tasks.txt"; + + // online or offline + public bool online { get; } = true; + + private int counter; // Count time in ms (used in advance method), to make sure every timeRobotPerTile a new action or node is given + + // colors + // colors for walls, tiles and prefabs + public Color colorWall { get; } = Color.black; + public Color colorTile { get; } = Color.white; + public Color colorEndPoint { get; }= new Color(0.5f, 0.5f, 1f); // blue-ish + public Color colorParking { get; } = Color.gray; + + // colors for tasks and the robots that have been assigned these tasks + public HashSet<Color> assignedColors { get; set; } = new HashSet<Color>(); + public HashSet<Color> notAssignedColors { get; set; } = new HashSet<Color>(); + + // endpoints + // dictionary containing all endpoints + // every endpoint will point to a gameobject, this will be setup by the Floor script + public Dictionary<Position, GameObject> endPoints { get; set; }= new Dictionary<Position, GameObject>(); + + // parameters of warehouse + public WarehouseParameters parameters { get; set; } + + // tasks + // at every timestep there will be max numberOfTasks tasks that have to be assigned (by the python code) + // current available tasks and their assigned colors: these are the tasks to remain to be assigned to robots + public Dictionary<Task, Color> currentTasks { get; set; } = new Dictionary<Task, Color>(); + // all remaining tasks, not yet in currentTasks, if not generated randomly and taken from predefined list + public Task[] remainingTasks { get; set; } + + // robots + [SerializeField] private GameObject robotPrefab = default; // GameObject prefab used for the robot + + // For every robot the current node where he is going, i.e. the next action + public Dictionary<int, Node> currentNodes { get; } = new Dictionary<int, Node>(); + + // For every robot the corresponding gameobject + public Dictionary<int, GameObject> robotGameObjects { get; set; }= new Dictionary<int, GameObject>(); + + // environment variables + // check for collisions + public bool collisions { get; set; } + + // observations and actions + public int observationSize { get; }= 4; // id,x,y,rotation + public int actionSize { get; }= 6; // id,x,y,rotation,pick up, delivery + + // environment variables for drawing + public float + SIZE { get; } = 1; // Size of square/tile, this is kept constant to avoid having to change camera perspective + + public float SCALEROBOT { get; } = 0.49f; // Ratio robot to tile, for drawing robot + public float YROBOTFLOATING { get; }= 0.2f; // Floating y value robot, for drawing robot + + // sidechannels + public EnvSideChannel envChannel { get; set; } // SideChannel for communication initial environment parameters + public TaskSideChannel taskChannel { get; set; } // SideChannel for communication on tasks + + void Awake() + { + SimulationManagerMethods.SetUpWarehouse<RobotOnlineCentralized>(this, robotPrefab, true); + } + + /// <summary> + /// Every timeRobotPerTile a new decision is requested: observations are collected (<c>CollectObservations</c>) and actions are received + /// (<c>OnActionReceived</c>) + /// </summary> + public void FixedUpdate() + { + counter += 20; // FixedUpdate is called every 20ms, add 20ms to counter + // if counter has passed timeRobotPerTile and there is a python client listening new actions are requested + // if a collisions has been detected no new requests are made + if (counter >= parameters.TimeRobotPerTile && Academy.Instance.IsCommunicatorOn) + { + if (!collisions) + { + RequestDecision(); // manually request a decision + } + + counter = 0; // reset counter + } + } + + /// <summary> + /// Return this as MonoBehaviour. + /// </summary> + /// <returns></returns> + public MonoBehaviour GetMonoBehaviour() + { + return this; + } + + /// <summary> + /// Collect observations, will be executed when requested. + /// </summary> + /// <param name="sensor"></param> + public override void CollectObservations(VectorSensor sensor) + { + SimulationManagerMethods.CollectObservations(this, sensor); + } + + /// <summary> + /// Receive actions, will be executed when requested. + /// Note that the number of actions per robot should be equal to <c>ActionSize</c>. + /// </summary> + public override void OnActionReceived(ActionBuffers actionBuffers) + { + SimulationManagerMethods.OnActionReceived<RobotOnlineCentralized>(this,actionBuffers); + } + + /// <summary> + /// Show message when a collision has occured. + /// </summary> + private void OnGUI() + { + if (collisions) + { + SimulationManagerMethods.ShowCollisionMessage(this); + } + } + + /// <summary> + /// Returns current node, i.e. the next node to go to, for a robot with a given instance ID. + /// </summary> + /// <param name="instanceID"> an int</param> + /// <returns> A node corresponding to the current node.</returns> + public Node GetCurrentNode(int instanceID) + { + return SimulationManagerMethods.GetCurrentNode(this,instanceID); + } + + /// <summary> + /// Remove a task from CurrentTasks. Reset color of pick up and delivery endpoints. + /// Make color available. + /// </summary> + /// <param name="task"></param> + /// <exception cref="Exception">thrown if it was not assigned to a robot</exception> + public void RemoveTask(Task task) + { + SimulationManagerMethods.RemoveTask(this, task); + } + + /// <summary> + /// Add a task to currentTasks if there are still tasks available. Assign a color and send information to python code. + /// </summary> + /// <exception cref="Exception">thrown when currentTasks has already reached capacity</exception> + public void AddNewTask() + { + SimulationManagerMethods.AddNewTask(this); + } + + /// <summary> + /// Assign a task to a robot with a given instanceID. + /// </summary> + /// <param name="task"></param> + /// <param name="instanceID"></param> + public void AssignTask(Task task, int instanceID) + { + SimulationManagerMethods.AssignTask<RobotOnlineCentralized>(this, task, instanceID); + } +} + diff --git a/PickUpandDelivery/Assets/Scripts/Online_Centralized/SimulationManagerOnlineCentralized.cs.meta b/PickUpandDelivery/Assets/Scripts/Online_Centralized/SimulationManagerOnlineCentralized.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..876b08d111b677caa17052cc901d7c751de0d1c9 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Online_Centralized/SimulationManagerOnlineCentralized.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e6bf74ca92d023a4dadefd09723b6558 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scripts/Online_Decentralized.meta b/PickUpandDelivery/Assets/Scripts/Online_Decentralized.meta new file mode 100644 index 0000000000000000000000000000000000000000..ac4f46d805fc3096aadf4406370e4e259f8ba1fd --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Online_Decentralized.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d36c6186b86728445b8ce6bc5a7c8180 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scripts/Online_Decentralized/RobotOnlineDecentralized.cs b/PickUpandDelivery/Assets/Scripts/Online_Decentralized/RobotOnlineDecentralized.cs new file mode 100644 index 0000000000000000000000000000000000000000..9b866a5270c0553dbd9129fad783340836197b78 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Online_Decentralized/RobotOnlineDecentralized.cs @@ -0,0 +1,129 @@ +/* + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + + +using Common.Robot; +using Common.SimulationManager; +using Common.Warehouse; +using Unity.MLAgents; +using Unity.MLAgents.Actuators; +using Unity.MLAgents.Sensors; +using UnityEngine; + +/// <summary> +/// Script <c> RobotOnlineDecentralized </c> +/// has public instance methods: +/// - GetMonoBehaviour(): return instance as Monobehaviour +/// - AssignTask(Task task): assign a task to robot and update color of robot accordingly +/// - CollectObservations(VectorSensor sensor): collect an observation +/// - OnActionReceived(ActionBuffers actionBuffers): do action +/// - Pickup() and Delivery(): unused methods from interface IRobot +/// has private instance methods: +/// - OnTriggerEnter(Collider other) for collision detection +/// </summary> +public class RobotOnlineDecentralized : Agent, IRobot +{ + public ISimulationManager simulationManager { get; set; } + + private int + counter; // Count time in ms (used in advance method), to make sure every timeRobotPerTile a new action or node is given + + public Task assignedTask { get; set; }= null; // the task a robot is assigned, mainly used for coloring + [SerializeField] private Material idleColor = default; // color when no task assigned + + void Start() + { + RobotMethods.InitializeRobotAtStart(this); + } + + void FixedUpdate() + { + counter += 20; // FixedUpdate is called every 20ms, add 20ms to counter + // if counter has passed timeRobotPerTile and there is a python client listening new actions are requested + // if a collisions has been detected no new requests are made + if (counter >= simulationManager.parameters.TimeRobotPerTile && Academy.Instance.IsCommunicatorOn) + { + if (!simulationManager.collisions) + { + Debug.Log("request by " + gameObject.GetInstanceID()); + RequestDecision(); // manually request a decision + } + + counter = 0; // reset counter + } + + RobotMethods.UpdatePosition(this); + } + + /// <summary> + /// Return this as MonoBehaviour. + /// </summary> + /// <returns></returns> + public MonoBehaviour GetMonoBehaviour() + { + return this; + } + + /// <summary> + /// Collect observation, will be executed when requested. + /// </summary> + /// <param name="sensor"></param> + public override void CollectObservations(VectorSensor sensor) + { + RobotMethods.CollectObservations(this,sensor); + } + + /// <summary> + /// Do action when received, will be executed when requested. + /// </summary> + /// <param name="actionBuffers"></param> + public override void OnActionReceived(ActionBuffers actionBuffers) + { + RobotMethods.OnActionReceived(this, actionBuffers, idleColor.color); + } + + // collision handling + private void OnTriggerEnter(Collider other) + { + RobotMethods.CollisionEvent(this); + } + + /// <summary> + /// Assign task to robot. + /// </summary> + /// <param name="task"> a Task object</param> + public void AssignTask(Task task) + { + RobotMethods.AssignTask(this, task); + } + + /// <summary> + /// Pick up. + /// </summary> + public void PickUp() + { + RobotMethods.PickUp(this); + } + + /// <summary> + /// Delivery. + /// </summary> + /// <returns>the delivered task</returns> + public Task Deliver() + { + return RobotMethods.Deliver(this, idleColor.color); + } +} diff --git a/PickUpandDelivery/Assets/Scripts/Online_Decentralized/RobotOnlineDecentralized.cs.meta b/PickUpandDelivery/Assets/Scripts/Online_Decentralized/RobotOnlineDecentralized.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..f93b82ae59289b27f28d39db8d38f1405187ea88 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Online_Decentralized/RobotOnlineDecentralized.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 388587dedc7732c449a7c4461107ddc3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Scripts/Online_Decentralized/SimulationManagerOnlineDecentralized.cs b/PickUpandDelivery/Assets/Scripts/Online_Decentralized/SimulationManagerOnlineDecentralized.cs new file mode 100644 index 0000000000000000000000000000000000000000..eb396aba5055ea2c556f8dd00f6c1ec8d40aed04 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Online_Decentralized/SimulationManagerOnlineDecentralized.cs @@ -0,0 +1,167 @@ +/* + Copyright (c) 2021. AI Lab, Vrije Universiteit Brussel. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +using System.Collections.Generic; +using System; +using UnityEngine; +using Common.SideChannels; +using Common.SimulationManager; +using Common.Warehouse; + +/// <summary> +/// Class <c> SimulationManagerOnlineDecentralized </c> controls the simulation for the Online Decentralized Pick Up and +/// Delivery problem. +/// +/// The only field that should be altered here is warehouseConfigFile, the path to the txt file containing +/// the configurable parameters of the simulation. Optionally a preset set of tasks. +/// +/// Has instance methods: +/// - GetMonoBehaviour(): return object as monobehavior +/// - GetCurrentNode(int instanceID): get current node for a robot with given instance ID +/// - RemoveTask(Task task): remove a tasks from current tasks +/// - AddNewTask(): add a new task to current tasks +/// - AssignTask(Task task, int instanceID): assign a task to a robot with given instance ID +/// </summary> + + +public class SimulationManagerOnlineDecentralized : MonoBehaviour, ISimulationManager +{ + //public string warehouseConfigFile { get; } = "ConfigurationFiles/Online_Decentralized/warehousejson_not_random.txt"; + public string warehouseConfigFile {get;} = "ConfigurationFiles/Online_Centralized/warehousejson_random.txt"; + public string tasksListFile { get; } = "ConfigurationFiles/Online_Decentralized/tasks.txt"; + + // online or offline + public bool online { get; } = true; + + // colors + // colors for walls, tiles and prefabs + public Color colorWall { get; } = Color.black; + public Color colorTile { get; } = Color.white; + public Color colorEndPoint { get; }= new Color(0.5f, 0.5f, 1f); // blue-ish + public Color colorParking { get; } = Color.gray; + + // colors for tasks and the robots that have been assigned these tasks + public HashSet<Color> assignedColors { get; set; } + public HashSet<Color> notAssignedColors { get; set; } + + // endpoints + // dictionary containing all endpoints + // every endpoint will point to a gameobject, this will be setup by the Floor script + public Dictionary<Position, GameObject> endPoints { get; set; } + + // parameters of warehouse + public WarehouseParameters parameters { get; set; } + + // tasks + // at every timestep there will be max numberOfTasks tasks that have to be assigned (by the python code) + // current available tasks and their assigned colors: these are the tasks to remain to be assigned to robots + public Dictionary<Task, Color> currentTasks { get; set; } + // all remaining tasks, not yet in currentTasks, if not generated randomly and taken from predefined list + public Task[] remainingTasks { get; set; } + + // robots + [SerializeField] private GameObject robotPrefab = default; // GameObject prefab used for the robot + + // For every robot the current node where he is going, i.e. the next action + public Dictionary<int, Node> currentNodes { get; } = new Dictionary<int, Node>(); + + // For every robot the corresponding gameobject + public Dictionary<int, GameObject> robotGameObjects { get; set; }= new Dictionary<int, GameObject>(); + + // environment variables + // check for collisions + public bool collisions { get; set; } + + // observations and actions + public int observationSize { get; } = 4; //id,x,y,rotation + public int actionSize { get; } = 5; //x,y,rotation,pick up, delivery + + // environment variables for drawing + public float + SIZE { get; } = 1; // Size of square/tile, this is kept constant to avoid having to change camera perspective + + public float SCALEROBOT { get; } = 0.49f; // Ratio robot to tile, for drawing robot + public float YROBOTFLOATING { get; }= 0.2f; // Floating y value robot, for drawing robot + + // sidechannels + public EnvSideChannel envChannel { get; set; } // SideChannel for communication initial environment parameters + public TaskSideChannel taskChannel { get; set; } // SideChannel for communication on tasks + + void Awake() + { + SimulationManagerMethods.SetUpWarehouse<RobotOnlineDecentralized>(this, robotPrefab, false); + } + + /// <summary> + /// Return this as MonoBehaviour. + /// </summary> + /// <returns></returns> + public MonoBehaviour GetMonoBehaviour() + { + return this; + } + + /// <summary> + /// Show message when a collision has occured. + /// </summary> + public void OnGUI() + { + if (collisions) + { + SimulationManagerMethods.ShowCollisionMessage(this); + } + } + + /// <summary> + /// Returns current node, i.e. the next node to go to, for a robot with a given instance ID. + /// </summary> + /// <param name="instanceID"> an int</param> + /// <returns> A node corresponding to the current node.</returns> + public Node GetCurrentNode(int instanceID) + { + return SimulationManagerMethods.GetCurrentNode(this,instanceID); + } + + /// <summary> + /// Remove a task from CurrentTasks that was assigned to a robot. + /// </summary> + /// <param name="task"></param> + /// <exception cref="Exception">thrown if it was not assigned to a robot</exception> + public void RemoveTask(Task task) + { + SimulationManagerMethods.RemoveTask(this, task); + } + + /// <summary> + /// Add a task to currentTasks if there are still tasks available. Assign a color and send information to python code. + /// </summary> + /// <exception cref="Exception">thrown when currentTasks has already reached capacity</exception> + public void AddNewTask() + { + SimulationManagerMethods.AddNewTask(this); + } + + /// <summary> + /// Assign a task to a robot with a given instanceID. + /// </summary> + /// <param name="task"></param> + /// <param name="instanceID"></param> + public void AssignTask(Task task, int instanceID) + { + SimulationManagerMethods.AssignTask<RobotOnlineDecentralized>(this, task, instanceID); + } +} + diff --git a/PickUpandDelivery/Assets/Scripts/Online_Decentralized/SimulationManagerOnlineDecentralized.cs.meta b/PickUpandDelivery/Assets/Scripts/Online_Decentralized/SimulationManagerOnlineDecentralized.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..7e69fb08dd730ea41b154b9fe5213a4e28948a23 --- /dev/null +++ b/PickUpandDelivery/Assets/Scripts/Online_Decentralized/SimulationManagerOnlineDecentralized.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a6033bfb5a3a1f747b8a528a445711a6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Shaders.meta b/PickUpandDelivery/Assets/Shaders.meta new file mode 100644 index 0000000000000000000000000000000000000000..58b6c1ad82bc6cf9bb3caeb3afcaf71c00f3d8de --- /dev/null +++ b/PickUpandDelivery/Assets/Shaders.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c5ae9f1e9e172db45b8fcd2ac5c729b3 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/Assets/Shaders/TextShader.shader b/PickUpandDelivery/Assets/Shaders/TextShader.shader new file mode 100644 index 0000000000000000000000000000000000000000..4f433e4bda5c6c2d7ec7ae61ba06f6bff7e0b456 --- /dev/null +++ b/PickUpandDelivery/Assets/Shaders/TextShader.shader @@ -0,0 +1,18 @@ +Shader "GUI/3D Text Shader - Cull Back" { + Properties { + _MainTex ("Font Texture", 2D) = "white" {} + _Color ("Text Color", Color) = (1,1,1,1) + } + + SubShader { + Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } + Lighting Off Cull Back ZWrite Off Fog { Mode Off } + Blend SrcAlpha OneMinusSrcAlpha + Pass { + Color [_Color] + SetTexture [_MainTex] { + combine primary, texture * primary + } + } + } +} \ No newline at end of file diff --git a/PickUpandDelivery/Assets/Shaders/TextShader.shader.meta b/PickUpandDelivery/Assets/Shaders/TextShader.shader.meta new file mode 100644 index 0000000000000000000000000000000000000000..dcd31128c12e19e8cb61854841daf86ab4c86e42 --- /dev/null +++ b/PickUpandDelivery/Assets/Shaders/TextShader.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 3b25d06e715175541a7601ed730df7c6 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/PickUpandDelivery/ConfigurationFiles/Offline_Centralized/tasks.txt b/PickUpandDelivery/ConfigurationFiles/Offline_Centralized/tasks.txt new file mode 100644 index 0000000000000000000000000000000000000000..7f62b76ad2e3d4b861325ef0b7eb42389ca6e419 --- /dev/null +++ b/PickUpandDelivery/ConfigurationFiles/Offline_Centralized/tasks.txt @@ -0,0 +1,52 @@ +[ + { + "PickUp": { + "Row": 2, + "Column": 0 + }, + "Delivery": { + "Row": 3, + "Column": 2 + } + }, + { + "PickUp": { + "Row": 2, + "Column": 9 + }, + "Delivery": { + "Row": 3, + "Column": 9 + } + }, + { + "PickUp": { + "Row": 3, + "Column": 4 + }, + "Delivery": { + "Row": 5, + "Column": 7 + } + }, + { + "PickUp": { + "Row": 6, + "Column": 0 + }, + "Delivery": { + "Row": 7, + "Column": 3 + } + }, + { + "PickUp": { + "Row": 7, + "Column": 5 + }, + "Delivery": { + "Row": 9, + "Column": 6 + } + } +] diff --git a/PickUpandDelivery/ConfigurationFiles/Offline_Centralized/tasks_releasetime.txt b/PickUpandDelivery/ConfigurationFiles/Offline_Centralized/tasks_releasetime.txt new file mode 100644 index 0000000000000000000000000000000000000000..81ed04c0bf18e033fe7179b97919ff63f696d922 --- /dev/null +++ b/PickUpandDelivery/ConfigurationFiles/Offline_Centralized/tasks_releasetime.txt @@ -0,0 +1,57 @@ +[ + { + "PickUp": { + "Row": 2, + "Column": 0 + }, + "Delivery": { + "Row": 3, + "Column": 2 + }, + "ReleaseTime": 5 + }, + { + "PickUp": { + "Row": 2, + "Column": 9 + }, + "Delivery": { + "Row": 3, + "Column": 9 + }, + "ReleaseTime": 9 + }, + { + "PickUp": { + "Row": 3, + "Column": 4 + }, + "Delivery": { + "Row": 5, + "Column": 7 + }, + "ReleaseTime": 10 + }, + { + "PickUp": { + "Row": 6, + "Column": 0 + }, + "Delivery": { + "Row": 7, + "Column": 3 + }, + "ReleaseTime": 2 + }, + { + "PickUp": { + "Row": 7, + "Column": 5 + }, + "Delivery": { + "Row": 9, + "Column": 6 + }, + "ReleaseTime": 2 + } +] diff --git a/PickUpandDelivery/ConfigurationFiles/Offline_Centralized/warehousejson.txt b/PickUpandDelivery/ConfigurationFiles/Offline_Centralized/warehousejson.txt new file mode 100644 index 0000000000000000000000000000000000000000..6c208ca746adf0f3fed6cefc87bc3e5a9b104892 --- /dev/null +++ b/PickUpandDelivery/ConfigurationFiles/Offline_Centralized/warehousejson.txt @@ -0,0 +1,26 @@ +{ + "Matrix": [ + [2,2,2,2,2,2,2,2,2,2], + [2,2,2,2,2,2,2,2,2,2], + [3,0,0,0,0,0,0,0,0,3], + [3,0,3,3,3,3,3,3,0,3], + [3,0,1,1,1,1,1,1,0,3], + [3,0,3,3,3,3,3,3,0,3], + [3,0,0,0,0,0,0,0,0,3], + [3,0,3,3,3,3,3,3,0,3], + [3,0,1,1,1,1,1,1,0,3], + [3,0,3,3,3,3,3,3,0,3], + [3,0,0,0,0,0,0,0,0,3] + ], + "Rotation": 45, + "TimeRobotPerTile": 1000, + "NumberOfRobots": 3, + "InitialNodes" : [ + {"GridPosition":{"Row":0,"Column":0},"Degrees":0}, + {"GridPosition":{"Row":1,"Column":4},"Degrees":270}, + {"GridPosition":{"Row":0,"Column":9},"Degrees":270} + ], + "NumberOfTasks": 5, + "CanGoBackWards": false, + "RandomTasks": false +} diff --git a/PickUpandDelivery/ConfigurationFiles/Offline_Decentralized/tasks.txt b/PickUpandDelivery/ConfigurationFiles/Offline_Decentralized/tasks.txt new file mode 100644 index 0000000000000000000000000000000000000000..7f62b76ad2e3d4b861325ef0b7eb42389ca6e419 --- /dev/null +++ b/PickUpandDelivery/ConfigurationFiles/Offline_Decentralized/tasks.txt @@ -0,0 +1,52 @@ +[ + { + "PickUp": { + "Row": 2, + "Column": 0 + }, + "Delivery": { + "Row": 3, + "Column": 2 + } + }, + { + "PickUp": { + "Row": 2, + "Column": 9 + }, + "Delivery": { + "Row": 3, + "Column": 9 + } + }, + { + "PickUp": { + "Row": 3, + "Column": 4 + }, + "Delivery": { + "Row": 5, + "Column": 7 + } + }, + { + "PickUp": { + "Row": 6, + "Column": 0 + }, + "Delivery": { + "Row": 7, + "Column": 3 + } + }, + { + "PickUp": { + "Row": 7, + "Column": 5 + }, + "Delivery": { + "Row": 9, + "Column": 6 + } + } +] diff --git a/PickUpandDelivery/ConfigurationFiles/Offline_Decentralized/tasks_releasetime.txt b/PickUpandDelivery/ConfigurationFiles/Offline_Decentralized/tasks_releasetime.txt new file mode 100644 index 0000000000000000000000000000000000000000..81ed04c0bf18e033fe7179b97919ff63f696d922 --- /dev/null +++ b/PickUpandDelivery/ConfigurationFiles/Offline_Decentralized/tasks_releasetime.txt @@ -0,0 +1,57 @@ +[ + { + "PickUp": { + "Row": 2, + "Column": 0 + }, + "Delivery": { + "Row": 3, + "Column": 2 + }, + "ReleaseTime": 5 + }, + { + "PickUp": { + "Row": 2, + "Column": 9 + }, + "Delivery": { + "Row": 3, + "Column": 9 + }, + "ReleaseTime": 9 + }, + { + "PickUp": { + "Row": 3, + "Column": 4 + }, + "Delivery": { + "Row": 5, + "Column": 7 + }, + "ReleaseTime": 10 + }, + { + "PickUp": { + "Row": 6, + "Column": 0 + }, + "Delivery": { + "Row": 7, + "Column": 3 + }, + "ReleaseTime": 2 + }, + { + "PickUp": { + "Row": 7, + "Column": 5 + }, + "Delivery": { + "Row": 9, + "Column": 6 + }, + "ReleaseTime": 2 + } +] diff --git a/PickUpandDelivery/ConfigurationFiles/Offline_Decentralized/warehousejson.txt b/PickUpandDelivery/ConfigurationFiles/Offline_Decentralized/warehousejson.txt new file mode 100644 index 0000000000000000000000000000000000000000..6c208ca746adf0f3fed6cefc87bc3e5a9b104892 --- /dev/null +++ b/PickUpandDelivery/ConfigurationFiles/Offline_Decentralized/warehousejson.txt @@ -0,0 +1,26 @@ +{ + "Matrix": [ + [2,2,2,2,2,2,2,2,2,2], + [2,2,2,2,2,2,2,2,2,2], + [3,0,0,0,0,0,0,0,0,3], + [3,0,3,3,3,3,3,3,0,3], + [3,0,1,1,1,1,1,1,0,3], + [3,0,3,3,3,3,3,3,0,3], + [3,0,0,0,0,0,0,0,0,3], + [3,0,3,3,3,3,3,3,0,3], + [3,0,1,1,1,1,1,1,0,3], + [3,0,3,3,3,3,3,3,0,3], + [3,0,0,0,0,0,0,0,0,3] + ], + "Rotation": 45, + "TimeRobotPerTile": 1000, + "NumberOfRobots": 3, + "InitialNodes" : [ + {"GridPosition":{"Row":0,"Column":0},"Degrees":0}, + {"GridPosition":{"Row":1,"Column":4},"Degrees":270}, + {"GridPosition":{"Row":0,"Column":9},"Degrees":270} + ], + "NumberOfTasks": 5, + "CanGoBackWards": false, + "RandomTasks": false +} diff --git a/PickUpandDelivery/ConfigurationFiles/Online_Centralized/tasks.txt b/PickUpandDelivery/ConfigurationFiles/Online_Centralized/tasks.txt new file mode 100644 index 0000000000000000000000000000000000000000..7f62b76ad2e3d4b861325ef0b7eb42389ca6e419 --- /dev/null +++ b/PickUpandDelivery/ConfigurationFiles/Online_Centralized/tasks.txt @@ -0,0 +1,52 @@ +[ + { + "PickUp": { + "Row": 2, + "Column": 0 + }, + "Delivery": { + "Row": 3, + "Column": 2 + } + }, + { + "PickUp": { + "Row": 2, + "Column": 9 + }, + "Delivery": { + "Row": 3, + "Column": 9 + } + }, + { + "PickUp": { + "Row": 3, + "Column": 4 + }, + "Delivery": { + "Row": 5, + "Column": 7 + } + }, + { + "PickUp": { + "Row": 6, + "Column": 0 + }, + "Delivery": { + "Row": 7, + "Column": 3 + } + }, + { + "PickUp": { + "Row": 7, + "Column": 5 + }, + "Delivery": { + "Row": 9, + "Column": 6 + } + } +] diff --git a/PickUpandDelivery/ConfigurationFiles/Online_Centralized/warehousejson_not_random.txt b/PickUpandDelivery/ConfigurationFiles/Online_Centralized/warehousejson_not_random.txt new file mode 100644 index 0000000000000000000000000000000000000000..ac87e23386d1b4c8fcefd1f55f4c6596aa0e5abe --- /dev/null +++ b/PickUpandDelivery/ConfigurationFiles/Online_Centralized/warehousejson_not_random.txt @@ -0,0 +1,26 @@ +{ + "Matrix": [ + [2,2,2,2,2,2,2,2,2,2], + [2,2,2,2,2,2,2,2,2,2], + [3,0,0,0,0,0,0,0,0,3], + [3,0,3,3,3,3,3,3,0,3], + [3,0,1,1,1,1,1,1,0,3], + [3,0,3,3,3,3,3,3,0,3], + [3,0,0,0,0,0,0,0,0,3], + [3,0,3,3,3,3,3,3,0,3], + [3,0,1,1,1,1,1,1,0,3], + [3,0,3,3,3,3,3,3,0,3], + [3,0,0,0,0,0,0,0,0,3] + ], + "Rotation": 45, + "TimeRobotPerTile": 1000, + "NumberOfRobots": 3, + "InitialNodes" : [ + {"GridPosition":{"Row":0,"Column":0},"Degrees":0}, + {"GridPosition":{"Row":1,"Column":4},"Degrees":270}, + {"GridPosition":{"Row":0,"Column":9},"Degrees":270} + ], + "NumberOfTasks": 3, + "CanGoBackWards": false, + "RandomTasks": false +} diff --git a/PickUpandDelivery/ConfigurationFiles/Online_Centralized/warehousejson_random.txt b/PickUpandDelivery/ConfigurationFiles/Online_Centralized/warehousejson_random.txt new file mode 100644 index 0000000000000000000000000000000000000000..985e2f98b15dc780fe819ea29221f566ad395764 --- /dev/null +++ b/PickUpandDelivery/ConfigurationFiles/Online_Centralized/warehousejson_random.txt @@ -0,0 +1,26 @@ +{ + "Matrix": [ + [2,2,2,2,2,2,2,2,2,2], + [2,2,2,2,2,2,2,2,2,2], + [3,0,0,0,0,0,0,0,0,3], + [3,0,3,3,3,3,3,3,0,3], + [3,0,1,1,1,1,1,1,0,3], + [3,0,3,3,3,3,3,3,0,3], + [3,0,0,0,0,0,0,0,0,3], + [3,0,3,3,3,3,3,3,0,3], + [3,0,1,1,1,1,1,1,0,3], + [3,0,3,3,3,3,3,3,0,3], + [3,0,0,0,0,0,0,0,0,3] + ], + "Rotation": 45, + "TimeRobotPerTile": 1000, + "NumberOfRobots": 3, + "InitialNodes" : [ + {"GridPosition":{"Row":0,"Column":0},"Degrees":0}, + {"GridPosition":{"Row":1,"Column":4},"Degrees":270}, + {"GridPosition":{"Row":0,"Column":9},"Degrees":270} + ], + "NumberOfTasks": 3, + "CanGoBackWards": false, + "RandomTasks": true +} diff --git a/PickUpandDelivery/ConfigurationFiles/Online_Decentralized/tasks.txt b/PickUpandDelivery/ConfigurationFiles/Online_Decentralized/tasks.txt new file mode 100644 index 0000000000000000000000000000000000000000..7f62b76ad2e3d4b861325ef0b7eb42389ca6e419 --- /dev/null +++ b/PickUpandDelivery/ConfigurationFiles/Online_Decentralized/tasks.txt @@ -0,0 +1,52 @@ +[ + { + "PickUp": { + "Row": 2, + "Column": 0 + }, + "Delivery": { + "Row": 3, + "Column": 2 + } + }, + { + "PickUp": { + "Row": 2, + "Column": 9 + }, + "Delivery": { + "Row": 3, + "Column": 9 + } + }, + { + "PickUp": { + "Row": 3, + "Column": 4 + }, + "Delivery": { + "Row": 5, + "Column": 7 + } + }, + { + "PickUp": { + "Row": 6, + "Column": 0 + }, + "Delivery": { + "Row": 7, + "Column": 3 + } + }, + { + "PickUp": { + "Row": 7, + "Column": 5 + }, + "Delivery": { + "Row": 9, + "Column": 6 + } + } +] diff --git a/PickUpandDelivery/ConfigurationFiles/Online_Decentralized/warehousejson_not_random.txt b/PickUpandDelivery/ConfigurationFiles/Online_Decentralized/warehousejson_not_random.txt new file mode 100644 index 0000000000000000000000000000000000000000..ac87e23386d1b4c8fcefd1f55f4c6596aa0e5abe --- /dev/null +++ b/PickUpandDelivery/ConfigurationFiles/Online_Decentralized/warehousejson_not_random.txt @@ -0,0 +1,26 @@ +{ + "Matrix": [ + [2,2,2,2,2,2,2,2,2,2], + [2,2,2,2,2,2,2,2,2,2], + [3,0,0,0,0,0,0,0,0,3], + [3,0,3,3,3,3,3,3,0,3], + [3,0,1,1,1,1,1,1,0,3], + [3,0,3,3,3,3,3,3,0,3], + [3,0,0,0,0,0,0,0,0,3], + [3,0,3,3,3,3,3,3,0,3], + [3,0,1,1,1,1,1,1,0,3], + [3,0,3,3,3,3,3,3,0,3], + [3,0,0,0,0,0,0,0,0,3] + ], + "Rotation": 45, + "TimeRobotPerTile": 1000, + "NumberOfRobots": 3, + "InitialNodes" : [ + {"GridPosition":{"Row":0,"Column":0},"Degrees":0}, + {"GridPosition":{"Row":1,"Column":4},"Degrees":270}, + {"GridPosition":{"Row":0,"Column":9},"Degrees":270} + ], + "NumberOfTasks": 3, + "CanGoBackWards": false, + "RandomTasks": false +} diff --git a/PickUpandDelivery/ConfigurationFiles/Online_Decentralized/warehousejson_random.txt b/PickUpandDelivery/ConfigurationFiles/Online_Decentralized/warehousejson_random.txt new file mode 100644 index 0000000000000000000000000000000000000000..985e2f98b15dc780fe819ea29221f566ad395764 --- /dev/null +++ b/PickUpandDelivery/ConfigurationFiles/Online_Decentralized/warehousejson_random.txt @@ -0,0 +1,26 @@ +{ + "Matrix": [ + [2,2,2,2,2,2,2,2,2,2], + [2,2,2,2,2,2,2,2,2,2], + [3,0,0,0,0,0,0,0,0,3], + [3,0,3,3,3,3,3,3,0,3], + [3,0,1,1,1,1,1,1,0,3], + [3,0,3,3,3,3,3,3,0,3], + [3,0,0,0,0,0,0,0,0,3], + [3,0,3,3,3,3,3,3,0,3], + [3,0,1,1,1,1,1,1,0,3], + [3,0,3,3,3,3,3,3,0,3], + [3,0,0,0,0,0,0,0,0,3] + ], + "Rotation": 45, + "TimeRobotPerTile": 1000, + "NumberOfRobots": 3, + "InitialNodes" : [ + {"GridPosition":{"Row":0,"Column":0},"Degrees":0}, + {"GridPosition":{"Row":1,"Column":4},"Degrees":270}, + {"GridPosition":{"Row":0,"Column":9},"Degrees":270} + ], + "NumberOfTasks": 3, + "CanGoBackWards": false, + "RandomTasks": true +} diff --git a/PickUpandDelivery/Packages/manifest.json b/PickUpandDelivery/Packages/manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..e9d691a6c4a01ff2d6d7575d39ad268b1aec2145 --- /dev/null +++ b/PickUpandDelivery/Packages/manifest.json @@ -0,0 +1,43 @@ +{ + "dependencies": { + "com.unity.collab-proxy": "1.2.16", + "com.unity.ide.rider": "1.1.4", + "com.unity.ide.vscode": "1.2.1", + "com.unity.ml-agents": "1.7.2-preview", + "com.unity.test-framework": "1.1.16", + "com.unity.textmeshpro": "2.1.1", + "com.unity.timeline": "1.2.17", + "com.unity.ugui": "1.0.0", + "com.unity.modules.ai": "1.0.0", + "com.unity.modules.androidjni": "1.0.0", + "com.unity.modules.animation": "1.0.0", + "com.unity.modules.assetbundle": "1.0.0", + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.cloth": "1.0.0", + "com.unity.modules.director": "1.0.0", + "com.unity.modules.imageconversion": "1.0.0", + "com.unity.modules.imgui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.particlesystem": "1.0.0", + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.physics2d": "1.0.0", + "com.unity.modules.screencapture": "1.0.0", + "com.unity.modules.terrain": "1.0.0", + "com.unity.modules.terrainphysics": "1.0.0", + "com.unity.modules.tilemap": "1.0.0", + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.uielements": "1.0.0", + "com.unity.modules.umbra": "1.0.0", + "com.unity.modules.unityanalytics": "1.0.0", + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.unitywebrequestassetbundle": "1.0.0", + "com.unity.modules.unitywebrequestaudio": "1.0.0", + "com.unity.modules.unitywebrequesttexture": "1.0.0", + "com.unity.modules.unitywebrequestwww": "1.0.0", + "com.unity.modules.vehicles": "1.0.0", + "com.unity.modules.video": "1.0.0", + "com.unity.modules.vr": "1.0.0", + "com.unity.modules.wind": "1.0.0", + "com.unity.modules.xr": "1.0.0" + } +} diff --git a/PickUpandDelivery/Packages/packages-lock.json b/PickUpandDelivery/Packages/packages-lock.json new file mode 100644 index 0000000000000000000000000000000000000000..2eb734f3c1e7fd77fd7d0e096bd6fec7e0b1407b --- /dev/null +++ b/PickUpandDelivery/Packages/packages-lock.json @@ -0,0 +1,353 @@ +{ + "dependencies": { + "com.unity.barracuda": { + "version": "1.2.1-preview", + "depth": 1, + "source": "registry", + "dependencies": { + "com.unity.burst": "1.3.4", + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.imageconversion": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.burst": { + "version": "1.3.4", + "depth": 2, + "source": "registry", + "dependencies": { + "com.unity.mathematics": "1.2.1" + }, + "url": "https://packages.unity.com" + }, + "com.unity.collab-proxy": { + "version": "1.2.16", + "depth": 0, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.ext.nunit": { + "version": "1.0.0", + "depth": 1, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.ide.rider": { + "version": "1.1.4", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.test-framework": "1.1.1" + }, + "url": "https://packages.unity.com" + }, + "com.unity.ide.vscode": { + "version": "1.2.1", + "depth": 0, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.mathematics": { + "version": "1.2.1", + "depth": 3, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.ml-agents": { + "version": "1.7.2-preview", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.barracuda": "1.2.1-preview", + "com.unity.modules.imageconversion": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.physics2d": "1.0.0", + "com.unity.modules.unityanalytics": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.test-framework": { + "version": "1.1.16", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.ext.nunit": "1.0.0", + "com.unity.modules.imgui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.textmeshpro": { + "version": "2.1.1", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.ugui": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.timeline": { + "version": "1.2.17", + "depth": 0, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.ugui": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.imgui": "1.0.0" + } + }, + "com.unity.modules.ai": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.androidjni": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.animation": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.assetbundle": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.audio": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.cloth": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics": "1.0.0" + } + }, + "com.unity.modules.director": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.animation": "1.0.0" + } + }, + "com.unity.modules.imageconversion": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.imgui": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.jsonserialize": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.particlesystem": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.physics": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.physics2d": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.screencapture": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.imageconversion": "1.0.0" + } + }, + "com.unity.modules.subsystems": { + "version": "1.0.0", + "depth": 1, + "source": "builtin", + "dependencies": { + "com.unity.modules.jsonserialize": "1.0.0" + } + }, + "com.unity.modules.terrain": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.terrainphysics": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.terrain": "1.0.0" + } + }, + "com.unity.modules.tilemap": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics2d": "1.0.0" + } + }, + "com.unity.modules.ui": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.uielements": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.imgui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0" + } + }, + "com.unity.modules.umbra": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.unityanalytics": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0" + } + }, + "com.unity.modules.unitywebrequest": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.unitywebrequestassetbundle": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.assetbundle": "1.0.0", + "com.unity.modules.unitywebrequest": "1.0.0" + } + }, + "com.unity.modules.unitywebrequestaudio": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.audio": "1.0.0" + } + }, + "com.unity.modules.unitywebrequesttexture": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.imageconversion": "1.0.0" + } + }, + "com.unity.modules.unitywebrequestwww": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.unitywebrequestassetbundle": "1.0.0", + "com.unity.modules.unitywebrequestaudio": "1.0.0", + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.assetbundle": "1.0.0", + "com.unity.modules.imageconversion": "1.0.0" + } + }, + "com.unity.modules.vehicles": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics": "1.0.0" + } + }, + "com.unity.modules.video": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.unitywebrequest": "1.0.0" + } + }, + "com.unity.modules.vr": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.xr": "1.0.0" + } + }, + "com.unity.modules.wind": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.xr": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.subsystems": "1.0.0" + } + } + } +} diff --git a/PickUpandDelivery/ProjectSettings/AudioManager.asset b/PickUpandDelivery/ProjectSettings/AudioManager.asset new file mode 100644 index 0000000000000000000000000000000000000000..07ebfb05df3b58b4a596eac64cd19529d36ce565 --- /dev/null +++ b/PickUpandDelivery/ProjectSettings/AudioManager.asset @@ -0,0 +1,19 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!11 &1 +AudioManager: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Volume: 1 + Rolloff Scale: 1 + Doppler Factor: 1 + Default Speaker Mode: 2 + m_SampleRate: 0 + m_DSPBufferSize: 1024 + m_VirtualVoiceCount: 512 + m_RealVoiceCount: 32 + m_SpatializerPlugin: + m_AmbisonicDecoderPlugin: + m_DisableAudio: 0 + m_VirtualizeEffects: 1 + m_RequestedDSPBufferSize: 1024 diff --git a/PickUpandDelivery/ProjectSettings/ClusterInputManager.asset b/PickUpandDelivery/ProjectSettings/ClusterInputManager.asset new file mode 100644 index 0000000000000000000000000000000000000000..e7886b266a005f4d9d80f2fef8d1649dcfd3ed2b --- /dev/null +++ b/PickUpandDelivery/ProjectSettings/ClusterInputManager.asset @@ -0,0 +1,6 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!236 &1 +ClusterInputManager: + m_ObjectHideFlags: 0 + m_Inputs: [] diff --git a/PickUpandDelivery/ProjectSettings/DynamicsManager.asset b/PickUpandDelivery/ProjectSettings/DynamicsManager.asset new file mode 100644 index 0000000000000000000000000000000000000000..cdc1f3eab509699e163f46fd14f0e81eb3a5dbaf --- /dev/null +++ b/PickUpandDelivery/ProjectSettings/DynamicsManager.asset @@ -0,0 +1,34 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!55 &1 +PhysicsManager: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_Gravity: {x: 0, y: -9.81, z: 0} + m_DefaultMaterial: {fileID: 0} + m_BounceThreshold: 2 + m_SleepThreshold: 0.005 + m_DefaultContactOffset: 0.01 + m_DefaultSolverIterations: 6 + m_DefaultSolverVelocityIterations: 1 + m_QueriesHitBackfaces: 0 + m_QueriesHitTriggers: 1 + m_EnableAdaptiveForce: 0 + m_ClothInterCollisionDistance: 0 + m_ClothInterCollisionStiffness: 0 + m_ContactsGeneration: 1 + m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + m_AutoSimulation: 1 + m_AutoSyncTransforms: 0 + m_ReuseCollisionCallbacks: 1 + m_ClothInterCollisionSettingsToggle: 0 + m_ContactPairsMode: 0 + m_BroadphaseType: 0 + m_WorldBounds: + m_Center: {x: 0, y: 0, z: 0} + m_Extent: {x: 250, y: 250, z: 250} + m_WorldSubdivisions: 8 + m_FrictionType: 0 + m_EnableEnhancedDeterminism: 0 + m_EnableUnifiedHeightmaps: 1 + m_DefaultMaxAngluarSpeed: 7 diff --git a/PickUpandDelivery/ProjectSettings/EditorBuildSettings.asset b/PickUpandDelivery/ProjectSettings/EditorBuildSettings.asset new file mode 100644 index 0000000000000000000000000000000000000000..0147887ef4b113c3a3b8da44ef30e3208f1e9120 --- /dev/null +++ b/PickUpandDelivery/ProjectSettings/EditorBuildSettings.asset @@ -0,0 +1,8 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1045 &1 +EditorBuildSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Scenes: [] + m_configObjects: {} diff --git a/PickUpandDelivery/ProjectSettings/EditorSettings.asset b/PickUpandDelivery/ProjectSettings/EditorSettings.asset new file mode 100644 index 0000000000000000000000000000000000000000..f92054474a36ddeca10712dccb2aaf7a6a3bcfb9 --- /dev/null +++ b/PickUpandDelivery/ProjectSettings/EditorSettings.asset @@ -0,0 +1,35 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!159 &1 +EditorSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_ExternalVersionControlSupport: Visible Meta Files + m_SerializationMode: 2 + m_LineEndingsForNewScripts: 0 + m_DefaultBehaviorMode: 0 + m_PrefabRegularEnvironment: {fileID: 0} + m_PrefabUIEnvironment: {fileID: 0} + m_SpritePackerMode: 0 + m_SpritePackerPaddingPower: 1 + m_EtcTextureCompressorBehavior: 1 + m_EtcTextureFastCompressor: 1 + m_EtcTextureNormalCompressor: 2 + m_EtcTextureBestCompressor: 4 + m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef;rsp;asmref + m_ProjectGenerationRootNamespace: + m_CollabEditorSettings: + inProgressEnabled: 1 + m_EnableTextureStreamingInEditMode: 1 + m_EnableTextureStreamingInPlayMode: 1 + m_AsyncShaderCompilation: 1 + m_EnterPlayModeOptionsEnabled: 0 + m_EnterPlayModeOptions: 3 + m_ShowLightmapResolutionOverlay: 1 + m_UseLegacyProbeSampleCount: 0 + m_AssetPipelineMode: 1 + m_CacheServerMode: 0 + m_CacheServerEndpoint: + m_CacheServerNamespacePrefix: default + m_CacheServerEnableDownload: 1 + m_CacheServerEnableUpload: 1 diff --git a/PickUpandDelivery/ProjectSettings/GraphicsSettings.asset b/PickUpandDelivery/ProjectSettings/GraphicsSettings.asset new file mode 100644 index 0000000000000000000000000000000000000000..43369e3c51bec3405f9e8d1388aa0468ab413513 --- /dev/null +++ b/PickUpandDelivery/ProjectSettings/GraphicsSettings.asset @@ -0,0 +1,63 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!30 &1 +GraphicsSettings: + m_ObjectHideFlags: 0 + serializedVersion: 13 + m_Deferred: + m_Mode: 1 + m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0} + m_DeferredReflections: + m_Mode: 1 + m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0} + m_ScreenSpaceShadows: + m_Mode: 1 + m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0} + m_LegacyDeferred: + m_Mode: 1 + m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0} + m_DepthNormals: + m_Mode: 1 + m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0} + m_MotionVectors: + m_Mode: 1 + m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0} + m_LightHalo: + m_Mode: 1 + m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0} + m_LensFlare: + m_Mode: 1 + m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0} + m_AlwaysIncludedShaders: + - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} + m_PreloadedShaders: [] + m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, + type: 0} + m_CustomRenderPipeline: {fileID: 0} + m_TransparencySortMode: 0 + m_TransparencySortAxis: {x: 0, y: 0, z: 1} + m_DefaultRenderingPath: 1 + m_DefaultMobileRenderingPath: 1 + m_TierSettings: [] + m_LightmapStripping: 0 + m_FogStripping: 0 + m_InstancingStripping: 0 + m_LightmapKeepPlain: 1 + m_LightmapKeepDirCombined: 1 + m_LightmapKeepDynamicPlain: 1 + m_LightmapKeepDynamicDirCombined: 1 + m_LightmapKeepShadowMask: 1 + m_LightmapKeepSubtractive: 1 + m_FogKeepLinear: 1 + m_FogKeepExp: 1 + m_FogKeepExp2: 1 + m_AlbedoSwatchInfos: [] + m_LightsUseLinearIntensity: 0 + m_LightsUseColorTemperature: 0 + m_LogWhenShaderIsCompiled: 0 + m_AllowEnlightenSupportForUpgradedProject: 0 diff --git a/PickUpandDelivery/ProjectSettings/InputManager.asset b/PickUpandDelivery/ProjectSettings/InputManager.asset new file mode 100644 index 0000000000000000000000000000000000000000..17c8f538e2152c0a0310b4870979eeecece2153c --- /dev/null +++ b/PickUpandDelivery/ProjectSettings/InputManager.asset @@ -0,0 +1,295 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!13 &1 +InputManager: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Axes: + - serializedVersion: 3 + m_Name: Horizontal + descriptiveName: + descriptiveNegativeName: + negativeButton: left + positiveButton: right + altNegativeButton: a + altPositiveButton: d + gravity: 3 + dead: 0.001 + sensitivity: 3 + snap: 1 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Vertical + descriptiveName: + descriptiveNegativeName: + negativeButton: down + positiveButton: up + altNegativeButton: s + altPositiveButton: w + gravity: 3 + dead: 0.001 + sensitivity: 3 + snap: 1 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire1 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left ctrl + altNegativeButton: + altPositiveButton: mouse 0 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire2 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left alt + altNegativeButton: + altPositiveButton: mouse 1 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire3 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left shift + altNegativeButton: + altPositiveButton: mouse 2 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Jump + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: space + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Mouse X + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0 + sensitivity: 0.1 + snap: 0 + invert: 0 + type: 1 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Mouse Y + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0 + sensitivity: 0.1 + snap: 0 + invert: 0 + type: 1 + axis: 1 + joyNum: 0 + - serializedVersion: 3 + m_Name: Mouse ScrollWheel + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0 + sensitivity: 0.1 + snap: 0 + invert: 0 + type: 1 + axis: 2 + joyNum: 0 + - serializedVersion: 3 + m_Name: Horizontal + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0.19 + sensitivity: 1 + snap: 0 + invert: 0 + type: 2 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Vertical + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0.19 + sensitivity: 1 + snap: 0 + invert: 1 + type: 2 + axis: 1 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire1 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 0 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire2 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 1 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire3 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 2 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Jump + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 3 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Submit + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: return + altNegativeButton: + altPositiveButton: joystick button 0 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Submit + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: enter + altNegativeButton: + altPositiveButton: space + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Cancel + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: escape + altNegativeButton: + altPositiveButton: joystick button 1 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 diff --git a/PickUpandDelivery/ProjectSettings/NavMeshAreas.asset b/PickUpandDelivery/ProjectSettings/NavMeshAreas.asset new file mode 100644 index 0000000000000000000000000000000000000000..3b0b7c3d183abdd300112f56965916ef11667f54 --- /dev/null +++ b/PickUpandDelivery/ProjectSettings/NavMeshAreas.asset @@ -0,0 +1,91 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!126 &1 +NavMeshProjectSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + areas: + - name: Walkable + cost: 1 + - name: Not Walkable + cost: 1 + - name: Jump + cost: 2 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + m_LastAgentTypeID: -887442657 + m_Settings: + - serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.75 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_SettingNames: + - Humanoid diff --git a/PickUpandDelivery/ProjectSettings/PackageManagerSettings.asset b/PickUpandDelivery/ProjectSettings/PackageManagerSettings.asset new file mode 100644 index 0000000000000000000000000000000000000000..9418901fcb67b88885674769811bfbd5d207207b --- /dev/null +++ b/PickUpandDelivery/ProjectSettings/PackageManagerSettings.asset @@ -0,0 +1,38 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &1 +MonoBehaviour: + m_ObjectHideFlags: 61 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 0} + m_Name: + m_EditorClassIdentifier: UnityEditor:UnityEditor.PackageManager.UI:PackageManagerProjectSettings + m_ScopedRegistriesSettingsExpanded: 1 + oneTimeWarningShown: 0 + m_Registries: + - m_Id: main + m_Name: + m_Url: https://packages.unity.com + m_Scopes: [] + m_IsDefault: 1 + m_UserSelectedRegistryName: + m_UserAddingNewScopedRegistry: 0 + m_RegistryInfoDraft: + m_ErrorMessage: + m_Original: + m_Id: + m_Name: + m_Url: + m_Scopes: [] + m_IsDefault: 0 + m_Modified: 0 + m_Name: + m_Url: + m_Scopes: + - + m_SelectedScopeIndex: 0 diff --git a/PickUpandDelivery/ProjectSettings/Physics2DSettings.asset b/PickUpandDelivery/ProjectSettings/Physics2DSettings.asset new file mode 100644 index 0000000000000000000000000000000000000000..47880b1c8c8e3b6306101004bb9826527d80e05e --- /dev/null +++ b/PickUpandDelivery/ProjectSettings/Physics2DSettings.asset @@ -0,0 +1,56 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!19 &1 +Physics2DSettings: + m_ObjectHideFlags: 0 + serializedVersion: 4 + m_Gravity: {x: 0, y: -9.81} + m_DefaultMaterial: {fileID: 0} + m_VelocityIterations: 8 + m_PositionIterations: 3 + m_VelocityThreshold: 1 + m_MaxLinearCorrection: 0.2 + m_MaxAngularCorrection: 8 + m_MaxTranslationSpeed: 100 + m_MaxRotationSpeed: 360 + m_BaumgarteScale: 0.2 + m_BaumgarteTimeOfImpactScale: 0.75 + m_TimeToSleep: 0.5 + m_LinearSleepTolerance: 0.01 + m_AngularSleepTolerance: 2 + m_DefaultContactOffset: 0.01 + m_JobOptions: + serializedVersion: 2 + useMultithreading: 0 + useConsistencySorting: 0 + m_InterpolationPosesPerJob: 100 + m_NewContactsPerJob: 30 + m_CollideContactsPerJob: 100 + m_ClearFlagsPerJob: 200 + m_ClearBodyForcesPerJob: 200 + m_SyncDiscreteFixturesPerJob: 50 + m_SyncContinuousFixturesPerJob: 50 + m_FindNearestContactsPerJob: 100 + m_UpdateTriggerContactsPerJob: 100 + m_IslandSolverCostThreshold: 100 + m_IslandSolverBodyCostScale: 1 + m_IslandSolverContactCostScale: 10 + m_IslandSolverJointCostScale: 10 + m_IslandSolverBodiesPerJob: 50 + m_IslandSolverContactsPerJob: 50 + m_AutoSimulation: 1 + m_QueriesHitTriggers: 1 + m_QueriesStartInColliders: 1 + m_CallbacksOnDisable: 1 + m_ReuseCollisionCallbacks: 1 + m_AutoSyncTransforms: 0 + m_AlwaysShowColliders: 0 + m_ShowColliderSleep: 1 + m_ShowColliderContacts: 0 + m_ShowColliderAABB: 0 + m_ContactArrowScale: 0.2 + m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412} + m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432} + m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745} + m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804} + m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff diff --git a/PickUpandDelivery/ProjectSettings/PresetManager.asset b/PickUpandDelivery/ProjectSettings/PresetManager.asset new file mode 100644 index 0000000000000000000000000000000000000000..67a94daefe2e6bce3ec73546ad7cda94f702ad22 --- /dev/null +++ b/PickUpandDelivery/ProjectSettings/PresetManager.asset @@ -0,0 +1,7 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1386491679 &1 +PresetManager: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_DefaultPresets: {} diff --git a/PickUpandDelivery/ProjectSettings/ProjectSettings.asset b/PickUpandDelivery/ProjectSettings/ProjectSettings.asset new file mode 100644 index 0000000000000000000000000000000000000000..fed8e2fdaf302936ce5cc6051236b163956d99d8 --- /dev/null +++ b/PickUpandDelivery/ProjectSettings/ProjectSettings.asset @@ -0,0 +1,668 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!129 &1 +PlayerSettings: + m_ObjectHideFlags: 0 + serializedVersion: 20 + productGUID: b51819efc0bece9459ecfe47e46deed1 + AndroidProfiler: 0 + AndroidFilterTouchesWhenObscured: 0 + AndroidEnableSustainedPerformanceMode: 0 + defaultScreenOrientation: 4 + targetDevice: 2 + useOnDemandResources: 0 + accelerometerFrequency: 60 + companyName: DefaultCompany + productName: Pick Up and Delivery + defaultCursor: {fileID: 0} + cursorHotspot: {x: 0, y: 0} + m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1} + m_ShowUnitySplashScreen: 1 + m_ShowUnitySplashLogo: 1 + m_SplashScreenOverlayOpacity: 1 + m_SplashScreenAnimation: 1 + m_SplashScreenLogoStyle: 1 + m_SplashScreenDrawMode: 0 + m_SplashScreenBackgroundAnimationZoom: 1 + m_SplashScreenLogoAnimationZoom: 1 + m_SplashScreenBackgroundLandscapeAspect: 1 + m_SplashScreenBackgroundPortraitAspect: 1 + m_SplashScreenBackgroundLandscapeUvs: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + m_SplashScreenBackgroundPortraitUvs: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + m_SplashScreenLogos: [] + m_VirtualRealitySplashScreen: {fileID: 0} + m_HolographicTrackingLossScreen: {fileID: 0} + defaultScreenWidth: 1024 + defaultScreenHeight: 768 + defaultScreenWidthWeb: 960 + defaultScreenHeightWeb: 600 + m_StereoRenderingPath: 0 + m_ActiveColorSpace: 0 + m_MTRendering: 1 + m_StackTraceTypes: 010000000100000001000000010000000100000001000000 + iosShowActivityIndicatorOnLoading: -1 + androidShowActivityIndicatorOnLoading: -1 + iosUseCustomAppBackgroundBehavior: 0 + iosAllowHTTPDownload: 1 + allowedAutorotateToPortrait: 1 + allowedAutorotateToPortraitUpsideDown: 1 + allowedAutorotateToLandscapeRight: 1 + allowedAutorotateToLandscapeLeft: 1 + useOSAutorotation: 1 + use32BitDisplayBuffer: 1 + preserveFramebufferAlpha: 0 + disableDepthAndStencilBuffers: 0 + androidStartInFullscreen: 1 + androidRenderOutsideSafeArea: 1 + androidUseSwappy: 0 + androidBlitType: 0 + defaultIsNativeResolution: 1 + macRetinaSupport: 1 + runInBackground: 1 + captureSingleScreen: 0 + muteOtherAudioSources: 0 + Prepare IOS For Recording: 0 + Force IOS Speakers When Recording: 0 + deferSystemGesturesMode: 0 + hideHomeButton: 0 + submitAnalytics: 1 + usePlayerLog: 1 + bakeCollisionMeshes: 0 + forceSingleInstance: 0 + useFlipModelSwapchain: 1 + resizableWindow: 0 + useMacAppStoreValidation: 0 + macAppStoreCategory: public.app-category.games + gpuSkinning: 1 + xboxPIXTextureCapture: 0 + xboxEnableAvatar: 0 + xboxEnableKinect: 0 + xboxEnableKinectAutoTracking: 0 + xboxEnableFitness: 0 + visibleInBackground: 1 + allowFullscreenSwitch: 1 + fullscreenMode: 1 + xboxSpeechDB: 0 + xboxEnableHeadOrientation: 0 + xboxEnableGuest: 0 + xboxEnablePIXSampling: 0 + metalFramebufferOnly: 0 + xboxOneResolution: 0 + xboxOneSResolution: 0 + xboxOneXResolution: 3 + xboxOneMonoLoggingLevel: 0 + xboxOneLoggingLevel: 1 + xboxOneDisableEsram: 0 + xboxOneEnableTypeOptimization: 0 + xboxOnePresentImmediateThreshold: 0 + switchQueueCommandMemory: 0 + switchQueueControlMemory: 16384 + switchQueueComputeMemory: 262144 + switchNVNShaderPoolsGranularity: 33554432 + switchNVNDefaultPoolsGranularity: 16777216 + switchNVNOtherPoolsGranularity: 16777216 + switchNVNMaxPublicTextureIDCount: 0 + switchNVNMaxPublicSamplerIDCount: 0 + stadiaPresentMode: 0 + stadiaTargetFramerate: 0 + vulkanNumSwapchainBuffers: 3 + vulkanEnableSetSRGBWrite: 0 + vulkanEnableLateAcquireNextImage: 0 + m_SupportedAspectRatios: + 4:3: 1 + 5:4: 1 + 16:10: 1 + 16:9: 1 + Others: 1 + bundleVersion: 0.1 + preloadedAssets: [] + metroInputSource: 0 + wsaTransparentSwapchain: 0 + m_HolographicPauseOnTrackingLoss: 1 + xboxOneDisableKinectGpuReservation: 1 + xboxOneEnable7thCore: 1 + vrSettings: + cardboard: + depthFormat: 0 + enableTransitionView: 0 + daydream: + depthFormat: 0 + useSustainedPerformanceMode: 0 + enableVideoLayer: 0 + useProtectedVideoMemory: 0 + minimumSupportedHeadTracking: 0 + maximumSupportedHeadTracking: 1 + hololens: + depthFormat: 1 + depthBufferSharingEnabled: 1 + lumin: + depthFormat: 0 + frameTiming: 2 + enableGLCache: 0 + glCacheMaxBlobSize: 524288 + glCacheMaxFileSize: 8388608 + oculus: + sharedDepthBuffer: 1 + dashSupport: 1 + lowOverheadMode: 0 + protectedContext: 0 + v2Signing: 1 + enable360StereoCapture: 0 + isWsaHolographicRemotingEnabled: 0 + enableFrameTimingStats: 0 + useHDRDisplay: 0 + D3DHDRBitDepth: 0 + m_ColorGamuts: 00000000 + targetPixelDensity: 30 + resolutionScalingMode: 0 + androidSupportedAspectRatio: 1 + androidMaxAspectRatio: 2.1 + applicationIdentifier: {} + buildNumber: {} + AndroidBundleVersionCode: 1 + AndroidMinSdkVersion: 19 + AndroidTargetSdkVersion: 0 + AndroidPreferredInstallLocation: 1 + aotOptions: + stripEngineCode: 1 + iPhoneStrippingLevel: 0 + iPhoneScriptCallOptimization: 0 + ForceInternetPermission: 0 + ForceSDCardPermission: 0 + CreateWallpaper: 0 + APKExpansionFiles: 0 + keepLoadedShadersAlive: 0 + StripUnusedMeshComponents: 1 + VertexChannelCompressionMask: 4054 + iPhoneSdkVersion: 988 + iOSTargetOSVersionString: 10.0 + tvOSSdkVersion: 0 + tvOSRequireExtendedGameController: 0 + tvOSTargetOSVersionString: 10.0 + uIPrerenderedIcon: 0 + uIRequiresPersistentWiFi: 0 + uIRequiresFullScreen: 1 + uIStatusBarHidden: 1 + uIExitOnSuspend: 0 + uIStatusBarStyle: 0 + appleTVSplashScreen: {fileID: 0} + appleTVSplashScreen2x: {fileID: 0} + tvOSSmallIconLayers: [] + tvOSSmallIconLayers2x: [] + tvOSLargeIconLayers: [] + tvOSLargeIconLayers2x: [] + tvOSTopShelfImageLayers: [] + tvOSTopShelfImageLayers2x: [] + tvOSTopShelfImageWideLayers: [] + tvOSTopShelfImageWideLayers2x: [] + iOSLaunchScreenType: 0 + iOSLaunchScreenPortrait: {fileID: 0} + iOSLaunchScreenLandscape: {fileID: 0} + iOSLaunchScreenBackgroundColor: + serializedVersion: 2 + rgba: 0 + iOSLaunchScreenFillPct: 100 + iOSLaunchScreenSize: 100 + iOSLaunchScreenCustomXibPath: + iOSLaunchScreeniPadType: 0 + iOSLaunchScreeniPadImage: {fileID: 0} + iOSLaunchScreeniPadBackgroundColor: + serializedVersion: 2 + rgba: 0 + iOSLaunchScreeniPadFillPct: 100 + iOSLaunchScreeniPadSize: 100 + iOSLaunchScreeniPadCustomXibPath: + iOSUseLaunchScreenStoryboard: 0 + iOSLaunchScreenCustomStoryboardPath: + iOSDeviceRequirements: [] + iOSURLSchemes: [] + iOSBackgroundModes: 0 + iOSMetalForceHardShadows: 0 + metalEditorSupport: 1 + metalAPIValidation: 1 + iOSRenderExtraFrameOnPause: 0 + appleDeveloperTeamID: + iOSManualSigningProvisioningProfileID: + tvOSManualSigningProvisioningProfileID: + iOSManualSigningProvisioningProfileType: 0 + tvOSManualSigningProvisioningProfileType: 0 + appleEnableAutomaticSigning: 0 + iOSRequireARKit: 0 + iOSAutomaticallyDetectAndAddCapabilities: 1 + appleEnableProMotion: 0 + clonedFromGUID: c0afd0d1d80e3634a9dac47e8a0426ea + templatePackageId: com.unity.template.3d@4.2.8 + templateDefaultScene: Assets/Scenes/SampleScene.unity + AndroidTargetArchitectures: 1 + AndroidSplashScreenScale: 0 + androidSplashScreen: {fileID: 0} + AndroidKeystoreName: + AndroidKeyaliasName: + AndroidBuildApkPerCpuArchitecture: 0 + AndroidTVCompatibility: 0 + AndroidIsGame: 1 + AndroidEnableTango: 0 + androidEnableBanner: 1 + androidUseLowAccuracyLocation: 0 + androidUseCustomKeystore: 0 + m_AndroidBanners: + - width: 320 + height: 180 + banner: {fileID: 0} + androidGamepadSupportLevel: 0 + AndroidValidateAppBundleSize: 1 + AndroidAppBundleSizeToValidate: 150 + m_BuildTargetIcons: [] + m_BuildTargetPlatformIcons: [] + m_BuildTargetBatching: + - m_BuildTarget: Standalone + m_StaticBatching: 1 + m_DynamicBatching: 0 + - m_BuildTarget: tvOS + m_StaticBatching: 1 + m_DynamicBatching: 0 + - m_BuildTarget: Android + m_StaticBatching: 1 + m_DynamicBatching: 0 + - m_BuildTarget: iPhone + m_StaticBatching: 1 + m_DynamicBatching: 0 + - m_BuildTarget: WebGL + m_StaticBatching: 0 + m_DynamicBatching: 0 + m_BuildTargetGraphicsJobs: + - m_BuildTarget: MacStandaloneSupport + m_GraphicsJobs: 0 + - m_BuildTarget: Switch + m_GraphicsJobs: 1 + - m_BuildTarget: MetroSupport + m_GraphicsJobs: 1 + - m_BuildTarget: AppleTVSupport + m_GraphicsJobs: 0 + - m_BuildTarget: BJMSupport + m_GraphicsJobs: 1 + - m_BuildTarget: LinuxStandaloneSupport + m_GraphicsJobs: 1 + - m_BuildTarget: PS4Player + m_GraphicsJobs: 1 + - m_BuildTarget: iOSSupport + m_GraphicsJobs: 0 + - m_BuildTarget: WindowsStandaloneSupport + m_GraphicsJobs: 1 + - m_BuildTarget: XboxOnePlayer + m_GraphicsJobs: 1 + - m_BuildTarget: LuminSupport + m_GraphicsJobs: 0 + - m_BuildTarget: AndroidPlayer + m_GraphicsJobs: 0 + - m_BuildTarget: WebGLSupport + m_GraphicsJobs: 0 + m_BuildTargetGraphicsJobMode: + - m_BuildTarget: PS4Player + m_GraphicsJobMode: 0 + - m_BuildTarget: XboxOnePlayer + m_GraphicsJobMode: 0 + m_BuildTargetGraphicsAPIs: + - m_BuildTarget: AndroidPlayer + m_APIs: 150000000b000000 + m_Automatic: 0 + - m_BuildTarget: iOSSupport + m_APIs: 10000000 + m_Automatic: 1 + - m_BuildTarget: AppleTVSupport + m_APIs: 10000000 + m_Automatic: 0 + - m_BuildTarget: WebGLSupport + m_APIs: 0b000000 + m_Automatic: 1 + m_BuildTargetVRSettings: + - m_BuildTarget: Standalone + m_Enabled: 0 + m_Devices: + - Oculus + - OpenVR + openGLRequireES31: 0 + openGLRequireES31AEP: 0 + openGLRequireES32: 0 + m_TemplateCustomTags: {} + mobileMTRendering: + Android: 1 + iPhone: 1 + tvOS: 1 + m_BuildTargetGroupLightmapEncodingQuality: [] + m_BuildTargetGroupLightmapSettings: [] + playModeTestRunnerEnabled: 0 + runPlayModeTestAsEditModeTest: 0 + actionOnDotNetUnhandledException: 1 + enableInternalProfiler: 0 + logObjCUncaughtExceptions: 1 + enableCrashReportAPI: 0 + cameraUsageDescription: + locationUsageDescription: + microphoneUsageDescription: + switchNetLibKey: + switchSocketMemoryPoolSize: 6144 + switchSocketAllocatorPoolSize: 128 + switchSocketConcurrencyLimit: 14 + switchScreenResolutionBehavior: 2 + switchUseCPUProfiler: 0 + switchApplicationID: 0x01004b9000490000 + switchNSODependencies: + switchTitleNames_0: + switchTitleNames_1: + switchTitleNames_2: + switchTitleNames_3: + switchTitleNames_4: + switchTitleNames_5: + switchTitleNames_6: + switchTitleNames_7: + switchTitleNames_8: + switchTitleNames_9: + switchTitleNames_10: + switchTitleNames_11: + switchTitleNames_12: + switchTitleNames_13: + switchTitleNames_14: + switchPublisherNames_0: + switchPublisherNames_1: + switchPublisherNames_2: + switchPublisherNames_3: + switchPublisherNames_4: + switchPublisherNames_5: + switchPublisherNames_6: + switchPublisherNames_7: + switchPublisherNames_8: + switchPublisherNames_9: + switchPublisherNames_10: + switchPublisherNames_11: + switchPublisherNames_12: + switchPublisherNames_13: + switchPublisherNames_14: + switchIcons_0: {fileID: 0} + switchIcons_1: {fileID: 0} + switchIcons_2: {fileID: 0} + switchIcons_3: {fileID: 0} + switchIcons_4: {fileID: 0} + switchIcons_5: {fileID: 0} + switchIcons_6: {fileID: 0} + switchIcons_7: {fileID: 0} + switchIcons_8: {fileID: 0} + switchIcons_9: {fileID: 0} + switchIcons_10: {fileID: 0} + switchIcons_11: {fileID: 0} + switchIcons_12: {fileID: 0} + switchIcons_13: {fileID: 0} + switchIcons_14: {fileID: 0} + switchSmallIcons_0: {fileID: 0} + switchSmallIcons_1: {fileID: 0} + switchSmallIcons_2: {fileID: 0} + switchSmallIcons_3: {fileID: 0} + switchSmallIcons_4: {fileID: 0} + switchSmallIcons_5: {fileID: 0} + switchSmallIcons_6: {fileID: 0} + switchSmallIcons_7: {fileID: 0} + switchSmallIcons_8: {fileID: 0} + switchSmallIcons_9: {fileID: 0} + switchSmallIcons_10: {fileID: 0} + switchSmallIcons_11: {fileID: 0} + switchSmallIcons_12: {fileID: 0} + switchSmallIcons_13: {fileID: 0} + switchSmallIcons_14: {fileID: 0} + switchManualHTML: + switchAccessibleURLs: + switchLegalInformation: + switchMainThreadStackSize: 1048576 + switchPresenceGroupId: + switchLogoHandling: 0 + switchReleaseVersion: 0 + switchDisplayVersion: 1.0.0 + switchStartupUserAccount: 0 + switchTouchScreenUsage: 0 + switchSupportedLanguagesMask: 0 + switchLogoType: 0 + switchApplicationErrorCodeCategory: + switchUserAccountSaveDataSize: 0 + switchUserAccountSaveDataJournalSize: 0 + switchApplicationAttribute: 0 + switchCardSpecSize: -1 + switchCardSpecClock: -1 + switchRatingsMask: 0 + switchRatingsInt_0: 0 + switchRatingsInt_1: 0 + switchRatingsInt_2: 0 + switchRatingsInt_3: 0 + switchRatingsInt_4: 0 + switchRatingsInt_5: 0 + switchRatingsInt_6: 0 + switchRatingsInt_7: 0 + switchRatingsInt_8: 0 + switchRatingsInt_9: 0 + switchRatingsInt_10: 0 + switchRatingsInt_11: 0 + switchRatingsInt_12: 0 + switchLocalCommunicationIds_0: + switchLocalCommunicationIds_1: + switchLocalCommunicationIds_2: + switchLocalCommunicationIds_3: + switchLocalCommunicationIds_4: + switchLocalCommunicationIds_5: + switchLocalCommunicationIds_6: + switchLocalCommunicationIds_7: + switchParentalControl: 0 + switchAllowsScreenshot: 1 + switchAllowsVideoCapturing: 1 + switchAllowsRuntimeAddOnContentInstall: 0 + switchDataLossConfirmation: 0 + switchUserAccountLockEnabled: 0 + switchSystemResourceMemory: 16777216 + switchSupportedNpadStyles: 22 + switchNativeFsCacheSize: 32 + switchIsHoldTypeHorizontal: 0 + switchSupportedNpadCount: 8 + switchSocketConfigEnabled: 0 + switchTcpInitialSendBufferSize: 32 + switchTcpInitialReceiveBufferSize: 64 + switchTcpAutoSendBufferSizeMax: 256 + switchTcpAutoReceiveBufferSizeMax: 256 + switchUdpSendBufferSize: 9 + switchUdpReceiveBufferSize: 42 + switchSocketBufferEfficiency: 4 + switchSocketInitializeEnabled: 1 + switchNetworkInterfaceManagerInitializeEnabled: 1 + switchPlayerConnectionEnabled: 1 + ps4NPAgeRating: 12 + ps4NPTitleSecret: + ps4NPTrophyPackPath: + ps4ParentalLevel: 11 + ps4ContentID: ED1633-NPXX51362_00-0000000000000000 + ps4Category: 0 + ps4MasterVersion: 01.00 + ps4AppVersion: 01.00 + ps4AppType: 0 + ps4ParamSfxPath: + ps4VideoOutPixelFormat: 0 + ps4VideoOutInitialWidth: 1920 + ps4VideoOutBaseModeInitialWidth: 1920 + ps4VideoOutReprojectionRate: 60 + ps4PronunciationXMLPath: + ps4PronunciationSIGPath: + ps4BackgroundImagePath: + ps4StartupImagePath: + ps4StartupImagesFolder: + ps4IconImagesFolder: + ps4SaveDataImagePath: + ps4SdkOverride: + ps4BGMPath: + ps4ShareFilePath: + ps4ShareOverlayImagePath: + ps4PrivacyGuardImagePath: + ps4ExtraSceSysFile: + ps4NPtitleDatPath: + ps4RemotePlayKeyAssignment: -1 + ps4RemotePlayKeyMappingDir: + ps4PlayTogetherPlayerCount: 0 + ps4EnterButtonAssignment: 1 + ps4ApplicationParam1: 0 + ps4ApplicationParam2: 0 + ps4ApplicationParam3: 0 + ps4ApplicationParam4: 0 + ps4DownloadDataSize: 0 + ps4GarlicHeapSize: 2048 + ps4ProGarlicHeapSize: 2560 + playerPrefsMaxSize: 32768 + ps4Passcode: frAQBc8Wsa1xVPfvJcrgRYwTiizs2trQ + ps4pnSessions: 1 + ps4pnPresence: 1 + ps4pnFriends: 1 + ps4pnGameCustomData: 1 + playerPrefsSupport: 0 + enableApplicationExit: 0 + resetTempFolder: 1 + restrictedAudioUsageRights: 0 + ps4UseResolutionFallback: 0 + ps4ReprojectionSupport: 0 + ps4UseAudio3dBackend: 0 + ps4UseLowGarlicFragmentationMode: 1 + ps4SocialScreenEnabled: 0 + ps4ScriptOptimizationLevel: 0 + ps4Audio3dVirtualSpeakerCount: 14 + ps4attribCpuUsage: 0 + ps4PatchPkgPath: + ps4PatchLatestPkgPath: + ps4PatchChangeinfoPath: + ps4PatchDayOne: 0 + ps4attribUserManagement: 0 + ps4attribMoveSupport: 0 + ps4attrib3DSupport: 0 + ps4attribShareSupport: 0 + ps4attribExclusiveVR: 0 + ps4disableAutoHideSplash: 0 + ps4videoRecordingFeaturesUsed: 0 + ps4contentSearchFeaturesUsed: 0 + ps4CompatibilityPS5: 0 + ps4GPU800MHz: 1 + ps4attribEyeToEyeDistanceSettingVR: 0 + ps4IncludedModules: [] + ps4attribVROutputEnabled: 0 + monoEnv: + splashScreenBackgroundSourceLandscape: {fileID: 0} + splashScreenBackgroundSourcePortrait: {fileID: 0} + blurSplashScreenBackground: 1 + spritePackerPolicy: + webGLMemorySize: 16 + webGLExceptionSupport: 1 + webGLNameFilesAsHashes: 0 + webGLDataCaching: 1 + webGLDebugSymbols: 0 + webGLEmscriptenArgs: + webGLModulesDirectory: + webGLTemplate: APPLICATION:Default + webGLAnalyzeBuildSize: 0 + webGLUseEmbeddedResources: 0 + webGLCompressionFormat: 1 + webGLLinkerTarget: 1 + webGLThreadsSupport: 0 + webGLWasmStreaming: 0 + scriptingDefineSymbols: {} + platformArchitecture: {} + scriptingBackend: {} + il2cppCompilerConfiguration: {} + managedStrippingLevel: {} + incrementalIl2cppBuild: {} + allowUnsafeCode: 0 + additionalIl2CppArgs: + scriptingRuntimeVersion: 1 + gcIncremental: 0 + gcWBarrierValidation: 0 + apiCompatibilityLevelPerPlatform: {} + m_RenderingPath: 1 + m_MobileRenderingPath: 1 + metroPackageName: Template_3D + metroPackageVersion: + metroCertificatePath: + metroCertificatePassword: + metroCertificateSubject: + metroCertificateIssuer: + metroCertificateNotAfter: 0000000000000000 + metroApplicationDescription: Template_3D + wsaImages: {} + metroTileShortName: + metroTileShowName: 0 + metroMediumTileShowName: 0 + metroLargeTileShowName: 0 + metroWideTileShowName: 0 + metroSupportStreamingInstall: 0 + metroLastRequiredScene: 0 + metroDefaultTileSize: 1 + metroTileForegroundText: 2 + metroTileBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21568628, a: 0} + metroSplashScreenBackgroundColor: {r: 0.12941177, g: 0.17254902, b: 0.21568628, + a: 1} + metroSplashScreenUseBackgroundColor: 0 + platformCapabilities: {} + metroTargetDeviceFamilies: {} + metroFTAName: + metroFTAFileTypes: [] + metroProtocolName: + XboxOneProductId: + XboxOneUpdateKey: + XboxOneSandboxId: + XboxOneContentId: + XboxOneTitleId: + XboxOneSCId: + XboxOneGameOsOverridePath: + XboxOnePackagingOverridePath: + XboxOneAppManifestOverridePath: + XboxOneVersion: 1.0.0.0 + XboxOnePackageEncryption: 0 + XboxOnePackageUpdateGranularity: 2 + XboxOneDescription: + XboxOneLanguage: + - enus + XboxOneCapability: [] + XboxOneGameRating: {} + XboxOneIsContentPackage: 0 + XboxOneEnableGPUVariability: 1 + XboxOneSockets: {} + XboxOneSplashScreen: {fileID: 0} + XboxOneAllowedProductIds: [] + XboxOnePersistentLocalStorageSize: 0 + XboxOneXTitleMemory: 8 + XboxOneOverrideIdentityName: + XboxOneOverrideIdentityPublisher: + vrEditorSettings: + daydream: + daydreamIconForeground: {fileID: 0} + daydreamIconBackground: {fileID: 0} + cloudServicesEnabled: + UNet: 1 + luminIcon: + m_Name: + m_ModelFolderPath: + m_PortalFolderPath: + luminCert: + m_CertPath: + m_SignPackage: 1 + luminIsChannelApp: 0 + luminVersion: + m_VersionCode: 1 + m_VersionName: + apiCompatibilityLevel: 6 + cloudProjectId: + framebufferDepthMemorylessMode: 0 + projectName: + organizationId: + cloudEnabled: 0 + enableNativePlatformBackendsForNewInputSystem: 0 + disableOldInputManagerSupport: 0 + legacyClampBlendShapeWeights: 0 diff --git a/PickUpandDelivery/ProjectSettings/ProjectVersion.txt b/PickUpandDelivery/ProjectSettings/ProjectVersion.txt new file mode 100644 index 0000000000000000000000000000000000000000..ae9c8eb06f742d9b7e103ee8f850877780afa0ed --- /dev/null +++ b/PickUpandDelivery/ProjectSettings/ProjectVersion.txt @@ -0,0 +1,2 @@ +m_EditorVersion: 2019.4.12f1 +m_EditorVersionWithRevision: 2019.4.12f1 (225e826a680e) diff --git a/PickUpandDelivery/ProjectSettings/QualitySettings.asset b/PickUpandDelivery/ProjectSettings/QualitySettings.asset new file mode 100644 index 0000000000000000000000000000000000000000..7b7658d6ebf4a0302c34bf5cc1e9d30813705a9e --- /dev/null +++ b/PickUpandDelivery/ProjectSettings/QualitySettings.asset @@ -0,0 +1,232 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!47 &1 +QualitySettings: + m_ObjectHideFlags: 0 + serializedVersion: 5 + m_CurrentQuality: 5 + m_QualitySettings: + - serializedVersion: 2 + name: Very Low + pixelLightCount: 0 + shadows: 0 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 15 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 0 + blendWeights: 1 + textureQuality: 1 + anisotropicTextures: 0 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 0 + lodBias: 0.3 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 4 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Low + pixelLightCount: 0 + shadows: 0 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 20 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 0 + blendWeights: 2 + textureQuality: 0 + anisotropicTextures: 0 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 0 + lodBias: 0.4 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 16 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Medium + pixelLightCount: 1 + shadows: 1 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 20 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 0 + blendWeights: 2 + textureQuality: 0 + anisotropicTextures: 1 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 1 + lodBias: 0.7 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 64 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: High + pixelLightCount: 2 + shadows: 2 + shadowResolution: 1 + shadowProjection: 1 + shadowCascades: 2 + shadowDistance: 40 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 1 + blendWeights: 2 + textureQuality: 0 + anisotropicTextures: 1 + antiAliasing: 0 + softParticles: 0 + softVegetation: 1 + realtimeReflectionProbes: 1 + billboardsFaceCameraPosition: 1 + vSyncCount: 1 + lodBias: 1 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 256 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Very High + pixelLightCount: 3 + shadows: 2 + shadowResolution: 2 + shadowProjection: 1 + shadowCascades: 2 + shadowDistance: 70 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 1 + blendWeights: 4 + textureQuality: 0 + anisotropicTextures: 2 + antiAliasing: 2 + softParticles: 1 + softVegetation: 1 + realtimeReflectionProbes: 1 + billboardsFaceCameraPosition: 1 + vSyncCount: 1 + lodBias: 1.5 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 1024 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Ultra + pixelLightCount: 4 + shadows: 2 + shadowResolution: 2 + shadowProjection: 1 + shadowCascades: 4 + shadowDistance: 150 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 1 + blendWeights: 4 + textureQuality: 0 + anisotropicTextures: 2 + antiAliasing: 2 + softParticles: 1 + softVegetation: 1 + realtimeReflectionProbes: 1 + billboardsFaceCameraPosition: 1 + vSyncCount: 1 + lodBias: 2 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 4096 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + m_PerPlatformDefaultQuality: + Android: 2 + Lumin: 5 + Nintendo 3DS: 5 + Nintendo Switch: 5 + PS4: 5 + PSP2: 2 + Stadia: 5 + Standalone: 5 + WebGL: 3 + Windows Store Apps: 5 + XboxOne: 5 + iPhone: 2 + tvOS: 2 diff --git a/PickUpandDelivery/ProjectSettings/TagManager.asset b/PickUpandDelivery/ProjectSettings/TagManager.asset new file mode 100644 index 0000000000000000000000000000000000000000..1c92a7840ec11895c76785f65d949a3d20d53355 --- /dev/null +++ b/PickUpandDelivery/ProjectSettings/TagManager.asset @@ -0,0 +1,43 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!78 &1 +TagManager: + serializedVersion: 2 + tags: [] + layers: + - Default + - TransparentFX + - Ignore Raycast + - + - Water + - UI + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + m_SortingLayers: + - name: Default + uniqueID: 0 + locked: 0 diff --git a/PickUpandDelivery/ProjectSettings/TimeManager.asset b/PickUpandDelivery/ProjectSettings/TimeManager.asset new file mode 100644 index 0000000000000000000000000000000000000000..558a017e1f50b2db73414a1abad3c033922774f8 --- /dev/null +++ b/PickUpandDelivery/ProjectSettings/TimeManager.asset @@ -0,0 +1,9 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!5 &1 +TimeManager: + m_ObjectHideFlags: 0 + Fixed Timestep: 0.02 + Maximum Allowed Timestep: 0.33333334 + m_TimeScale: 1 + Maximum Particle Timestep: 0.03 diff --git a/PickUpandDelivery/ProjectSettings/UnityConnectSettings.asset b/PickUpandDelivery/ProjectSettings/UnityConnectSettings.asset new file mode 100644 index 0000000000000000000000000000000000000000..fa0b146579fb787323d29e1d7b7768a0541031af --- /dev/null +++ b/PickUpandDelivery/ProjectSettings/UnityConnectSettings.asset @@ -0,0 +1,34 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!310 &1 +UnityConnectSettings: + m_ObjectHideFlags: 0 + serializedVersion: 1 + m_Enabled: 0 + m_TestMode: 0 + m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events + m_EventUrl: https://cdp.cloud.unity3d.com/v1/events + m_ConfigUrl: https://config.uca.cloud.unity3d.com + m_TestInitMode: 0 + CrashReportingSettings: + m_EventUrl: https://perf-events.cloud.unity3d.com + m_Enabled: 0 + m_LogBufferSize: 10 + m_CaptureEditorExceptions: 1 + UnityPurchasingSettings: + m_Enabled: 0 + m_TestMode: 0 + UnityAnalyticsSettings: + m_Enabled: 0 + m_TestMode: 0 + m_InitializeOnStartup: 1 + UnityAdsSettings: + m_Enabled: 0 + m_InitializeOnStartup: 1 + m_TestMode: 0 + m_IosGameId: + m_AndroidGameId: + m_GameIds: {} + m_GameId: + PerformanceReportingSettings: + m_Enabled: 0 diff --git a/PickUpandDelivery/ProjectSettings/VFXManager.asset b/PickUpandDelivery/ProjectSettings/VFXManager.asset new file mode 100644 index 0000000000000000000000000000000000000000..3a95c98bec50cf72538061fd26eee95398f72128 --- /dev/null +++ b/PickUpandDelivery/ProjectSettings/VFXManager.asset @@ -0,0 +1,12 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!937362698 &1 +VFXManager: + m_ObjectHideFlags: 0 + m_IndirectShader: {fileID: 0} + m_CopyBufferShader: {fileID: 0} + m_SortShader: {fileID: 0} + m_StripUpdateShader: {fileID: 0} + m_RenderPipeSettingsPath: + m_FixedTimeStep: 0.016666668 + m_MaxDeltaTime: 0.05 diff --git a/PickUpandDelivery/ProjectSettings/XRSettings.asset b/PickUpandDelivery/ProjectSettings/XRSettings.asset new file mode 100644 index 0000000000000000000000000000000000000000..482590c196f7a82116679f58176b9d1aff21d7f9 --- /dev/null +++ b/PickUpandDelivery/ProjectSettings/XRSettings.asset @@ -0,0 +1,10 @@ +{ + "m_SettingKeys": [ + "VR Device Disabled", + "VR Device User Alert" + ], + "m_SettingValues": [ + "False", + "False" + ] +} \ No newline at end of file