diff --git a/Changelog.md b/Changelog.md
index dcfada4e..3eeccace 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,5 +1,23 @@
# Changelog
+Version 1.1.3 - 2023-10-24
+----------------------------
+Added:
+- Add Working_with_Preprocessed_Data.md to explain how you can work with your preprocessed data.
+- Add Debug_and_Visualiser_Your_Planner.md to explain how you can use the JSON output to debug and visualise with PlanViz
+
+Changed:
+- Additional option `OutputScreen` in the input argument, which allows you to choose the level of details of the output JSON file.
+- Readme, Parepare_Your_Planner, and compile.sh suggests running the start-kit under repo root directory.
+- Simplified duplicated output appears in couts and log files
+- Updated documentation (add more descriptions regarding the coordination system in Prepare_Your_Planner.md)
+- Updated documentation (add corresponding descriptions of `OutputScreen` in Input_Output_Format.md)
+- Terminate all processes when the main process (the simulation) is terminated.
+
+Fixed:
+- Fixed issue with running start-kit under repo root directory python cannot find compiled MAPF module for importing.
+- Fixed issue with missing fie_storage_path for pybind.
+
Version 1.1.2 - 2023-08-29
----------------------------
Fixed:
diff --git a/Debug_and_Visualise_Your_Planner.md b/Debug_and_Visualise_Your_Planner.md
new file mode 100644
index 00000000..c7ec8279
--- /dev/null
+++ b/Debug_and_Visualise_Your_Planner.md
@@ -0,0 +1,71 @@
+# Debug and Visualise Your Planner
+The output file provides some related information to help you design and debug your planner.
+Begin by familiarizing yourself with the structure of the output JSON file. Please refer to the [Input_Output_Format.md](./Input_Output_Format.md).
+
+## Debug your planner using Output File
+To debug your planners, there are some properties that can help you to learn how your planner coordinate the robots. Here are some suggestions that you might be interested to look at:
+1. Check for Validity: Inspect the `errors` and `AllValid` properties to identify and address any invalid actions.
+2. Review Paths: Study the `plannerPaths` and `actualPaths` results to check whether your planner behaves consistently with your expectations or not.
+3. Analyze Planner Times: Look at the `plannerTimes` property to understand the time taken by your planner during each planning episode. Investigate further if you notice significant deviations from expected planning times.
+4. Other ways: you can also compare your performance and design a better planner by simply looking at the `numTaskFinished` results and analysing the tasks finished by `events` and `tasks`.
+
+## Visualise your planner using Output File
+We also provide a tool called [PlanViz](https://github.com/MAPF-Competition/PlanViz) for visualising your plan with the output JSON file.
+PlanViz shows the animation of the actualPaths of agents in the JSON file.
+While the actual paths are always valid and conflict-free, the plannerPaths might contain conflicts and invalid moves.
+In such cases, PlanViz can highlight the problematic agents with red color.
+You can also click each item in the error list to jump to the corresponding timestep.
+Note that PlanViz does not do any validation or error checking.
+Therefore, the errors it shows are those recorded in the JSON file.
+If you modify the JSON file manually, the error list and agent highlighting can be inconsistent with the movement.
+
+For more details, please refer to the [Visualiser Page](https://github.com/MAPF-Competition/PlanViz).
+
+### Use PlanViz
+
+Following the instruction in the [Visualiser Page](https://github.com/MAPF-Competition/PlanViz), one can start PlanViz by running the following command
+```
+python3 plan_viz.py --map ../example/warehouse_small.map --plan ../example/warehouse_small.json --grid --aid --static --ca
+```
+You will see something similar to the figure below:
+
+![A screenshot of the PlanViz UI.](./image/UI.png)
+
+The UI of PlanViz consists of a main canvas, which shows the visualization, and a UI panel, which users can interact with. In the main canvas, we use the following markers to represent agents and tasks:
+
+![Markers for agents and tasks.](./image/markers.png)
+
+We will explain the UI panel in five sections: Animation Control, Visualization Options, Timestep Selector, Error List, and Event List. For instructions on how to debug errors, see the [error list section](#errorlist).
+
+#### Animation Control
+The animation control section shows the current timestep in the visualization and provides buttons for controlling the animation. You can use `Play/Pause` to start/stop the animation and `Next/Prev` to make agents move one step forward/backward.
+
+
+#### Visualization Options
+
+The visualization option section allows users to choose what to be displayed in the main canvas:
+
+![Different visualization options](./image/visualization_option.png)
+
+Note that, when "Show colliding agents" is turned on, an agent will be marked as always red if it has a collision in any timestep. You can also use the drop-down list of shown tasks to select which tasks to display:
+![Different options for displaying tasks.](./image/tasks_drop_down.png)
+
+#### Timestep Selector
+The timestep selector section allows users to jump to a specific timestep. Note that you need to pause PlanViz before using it.
+
+
+Error List
+
+
+The error list section shows the errors (planner timeout, collisions in the planned paths, etc.) in the JSON input file. You can interact with a collision error by single or double-clicking it:
+
+![](./image/single_click.gif)
+
+*When "Show colliding agents" is turned off, single-clicking a conflict will mark the two colliding agents red.*
+
+![](./image/double_click.gif)
+
+*Double-clicking a conflict will make PlanViz jump to the specific timestep and show the collision.*
+#### Event List
+
+The event list section shows the events (assignment and completion of tasks) in the JSON input file. Single-clicking an event will make PlanViz jump to the timestep right before the event timestep.
diff --git a/Input_Output_Format.md b/Input_Output_Format.md
index e8fe100c..6d5e3cd3 100644
--- a/Input_Output_Format.md
+++ b/Input_Output_Format.md
@@ -6,9 +6,11 @@
| --help | |
| --inputFile | String
The input file describes the problem to be solved in JSON format |
| --output | String
The output file describes the planner result in JSON format |
+| --outputScreen | Int (=1)
The level of details in the output file (=1 to show all, = 2 to show problem summary, start and actual path and =3 to show only problem summary). |
| --evaluationMode | Boolean
when run in this mode the program will check the validity of the planned and executed actions in an existing plan, as specified by the --output parameter |
| --simulationTime | Int
The maximum number of timesteps allowed for solving the problem, we sometimes refer to this as planning horizon |
-| --planTimeLimit | Int
The amount of time available for planning in each timestep, if this time limit exceeded by the planner, all robots are issued wait commands at current timestep |
+| --fileStoragePath | String
The folder path that your local preprocessing file locates |
+| --planTimeLimit | Int
The amount of time available for planning in each timestep, if this time limit is exceeded by the planner, all robots are issued wait commands at current timestep |
| --preprocessTimeLimit | Int
The amount of time in seconds available for loading and precomputing auxiliary data before the problem-solving process begins |
| --logFile | String
An output file that records all warnings and errors issued by the simulator in the event of invalid or incomplete actions from the planner |
@@ -19,10 +21,10 @@ All paths here is the relative path relative to the location of input JSON file
| properties | |
|------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| mapFile | String
The relative path to the file that describes the grid environment input. We use the grid map format as described in the next section (with a section link to the relevant section) |
-| robotFile | String
The relative path to the file that describes the start locations for robots. The first line indicates the number of robots n. The following n lines correspond to the start locations of the n robots..* |
+| agentFile | String
The relative path to the file that describes the start locations for robots. The first line indicates the number of robots n. The following n lines correspond to the start locations of the n robots..* |
| taskFile | String
The relative path to the file that describes the locations for tasks. The first line indicates the number of tasks m. The following m lines contain single integers that correspond to the locations of the m tasks on the grid.\* |
-| numTasksReveal | Int (=1)
The number of tasks/errands revealed to an robot at any one time. Every time an robot finishes a task/errand a new task is revealed. By default, this is 1, which means only the next 1 task/errand is known to the robot. |
-| taskAssignmentStrategy | String (=roundrobin)
The strategy for assigning tasks (`greedy`,`roundrobin` or `roundrobin-fixed`). Every time an robot finished a task/errand, a task assignment strategy decides the next task assigned to the robot. `greedy` will assign the next unassgined task from task file line by line. While for `roundrobin` and `roundrobin-fixed`, tasks assignment is pre-deceided by the system using a round robin strategy, where the $i_{th}$ robot will get the $i + n_i*(team size)$ task and $n_i$ is the task counter for robot $i$, starts from 0 and growth by 1 upon a task finish. The difference between "roundrobin" and "roundrobin-fixed" is that for "roundrobin-fixed", the simulation will stop when all the tasks from the task files are finished, and for "roundrobin" the task assignment system will iteratively read the task file from the first line to simulate planning for "infinite" tasks/errands. |
+| numTasksReveal | Int (=1)
The number of tasks/errands revealed to a robot at any one time. Every time a robot finishes a task/errand a new task is revealed. By default, this is 1, which means only the next 1 task/errand is known to the robot. |
+| taskAssignmentStrategy | String (=roundrobin)
The strategy for assigning tasks (`greedy`,`roundrobin` or `roundrobin-fixed`). Every time a robot finishes a task/errand, a task assignment strategy decides the next task assigned to the robot. `greedy` will assign the next unassigned task from task file line by line. While for `roundrobin` and `roundrobin-fixed`, tasks assignment is pre-decided by the system using a round-robin strategy, where the $i_{th}$ robot will get the $i + n_i*(team size)$ task and $n_i$ is the task counter for robot $i$, starts from 0 and growth by 1 upon a task finish. The difference between "roundrobin" and "roundrobin-fixed" is that for "roundrobin-fixed", the simulation will stop when all the tasks from the task files are finished, and for "roundrobin" the task assignment system will iteratively read the task file from the first line to simulate planning for "infinite" tasks/errands. |
| teamSize | Int
The number of robots in the simulation |
diff --git a/Prepare_Your_Planner.md b/Prepare_Your_Planner.md
index 68f84100..f639dd07 100644
--- a/Prepare_Your_Planner.md
+++ b/Prepare_Your_Planner.md
@@ -2,34 +2,34 @@
To run the program, please refer to [README.md](./README.md) to download the start-kit and compile.
## Planner Integration
-- Before your planning, getting familiar with the data structures:
- - Coordination system of the map: the location of robot on the map is based on its coordination (x,y), where x refers to the row the robot stays at, and y refers to the column it stays at. For the first row (the topest row), x = 0, and for the first column (the left most column), y = 0.
+- Before your planning, get familiar with the data structures:
+ - Coordination system of the map: the location of a robot on the map is based on its coordination (x,y), where x refers to the row the robot stays at, and y refers to the column it stays at. For the first row (the topest row), x = 0, and for the first column (the leftmost column), y = 0. You can find a visualization [here](./image/coordination_system.pdf)
- Map: the map is a vector of int, the index is calculated by linearise the (row, column) of a location to (row * total number of columns of the map) + column, the value is either 1: non-traversable or 0: traversable.
- - A State of robot: a state contains the current location (map location index), current timestep and current facing orientation (0:east, 1:south, 2:west, 3:north).
- - Tasks of robots: a task of an robot is a int, represents a single location (linearised) in the map.
+ - A State of a robot: a state containing the current location (map location index), current timestep and current facing orientation (0:east, 1:south, 2:west, 3:north).
+ - Tasks of robots: a task of a robot is an int, which represents a single location (linearised) in the map.
- Action enum: the four possible actions are encoded in our start actions as: FW - forward, CR - Clockwise rotate, CCR - Counter clockwise rotate, W - Wait, NA - Unknown actions
-- Start your planing with SharedEnvironment API: Your planner can have access to the shared environment (defined as env in inc/MAPFPlanner.h) and plan based on the things we shared with you in the shared environment. The shared environment contains:
+- Start your planning with SharedEnvironment API: Your planner can have access to the shared environment (defined as env in inc/MAPFPlanner.h) and plan based on the things we shared with you in the shared environment. The shared environment contains:
- num_of_robots: int, the total team size.
- rows: int, the number of rows of the map.
- cols: int, the number of columns of the map.
- map_name: string, the map file name.
- map: vector of int, stores the map.
- - file_storage_path: string, use for indicating the path for file storage, refer to section 'Local Preprocessing and Large Files'.
- - goal locations, vector of vector of pair : current tasks locations allocate to each robot.
+ - file_storage_path: string, used for indicating the path for file storage, refer to section 'Local Preprocessing and Large Files'.
+ - goal locations, vector of vector of pair : current tasks locations allocated to each robot. The first int of a task (pair of int) is the goal location, and the second int indicates the timestep that the task was allocated.
- current_timestep: int, the current time step that our system already simulated the robots' actions.
- curr_states: vector of State, the current state for each robot at the current time step,
-- Be aware of time is ticking while planning: at every timestep, we will ask your planner to compute the next valid action for each robot within a given planing time limit. This is given as the input parameter of the function in the planner class (preprocess_time_limit in function 'initialize' and time_limit in function 'plan', both are int). The preprocess_time_limit is the maximum time to preprocess your map. If this process cost more than the time limit, then your planner fails and the system terminates with fail to preprocess within time limit. As for the time_limit in function plan, it is a soft limit, which means if you do not return actions within the time limit, the program will continues, and all robots will wait in place until the next planning episode.
-- Return your plan using actions: Once you have plans for the next timestep, you can directly re-assign valuses to the input paramter 'actions' to your plans.
+- Be aware that time is ticking while planning: at every timestep, we will ask your planner to compute the next valid action for each robot within a given planning time limit. This is given as the input parameter of the function in the planner class (preprocess_time_limit in function 'initialize' and time_limit in function 'plan', both are int). The preprocess_time_limit is the maximum time to preprocess your map. If this process costs more than the time limit, then your planner fails and the system terminates with a failure to preprocess within the time limit. As for the time_limit in the function plan, it is a soft limit, which means if you do not return actions within the time limit, the program will continue, and all robots will wait in place until the next planning episode.
+- Return your plan using actions: Once you have plans for the next timestep, you can directly re-assign values to the input parameter 'actions' to your plans.
- actions: vector of Action, given in input parameter. It contains the actions for each robot that we require you to plan for the next timestep.
- For more details, read the interface implementation in src/MAPFPlanner.cpp, inc/MAPFPlanner.h, inc/SharedEnv.h.
- Implement your planner in the file src/MAPFPlanner.cpp and inc/MAPFPlanner.h. See examples in src/MAPFPlanner.cpp
- - Implement your preprocessing in the function MAPFPlanner::initialize that provided to you.
+ - Implement your preprocessing in the function MAPFPlanner::initialize that is provided to you.
- Implement your planner in the function MAPFPlanner::plan that provided to you
- - Don’t override any operating system related functions (signal handlers)
+ - Don’t override any operating system-related functions (signal handlers)
- Don’t modify any start kit functions and modify / call / interfere with any start kit variables or objects, including those in:
- src/ActionModel.cpp, src/common.cpp, src/CompetitionSystem.cpp, src/driver.cpp, scr/Evaluation.cpp, src/Grid.cpp, src/Logger.cpp, src/States.cpp, src/Validator.cpp, inc/ActionModel.h, inc/CompetitionSystem.h, Evaluation.h, Grid.h, Logger.h, SharedEnv.h, States.h, Tasks.h, Validator.h, common.h
+ src/ActionModel.cpp, src/common.cpp, src/CompetitionSystem.cpp, src/driver.cpp, src/Evaluation.cpp, src/Grid.cpp, src/Logger.cpp, src/States.cpp, src/Validator.cpp, inc/ActionModel.h, inc/CompetitionSystem.h, Evaluation.h, Grid.h, Logger.h, SharedEnv.h, States.h, Tasks.h, Validator.h, common.h
- Don’t interfere with the running program -- stack manipulation etc
- Including dependencies in the submission repo,
- or specify your dependency packages in apt.txt. The packages must be available for installation through apt-get on Ubuntu 22.
@@ -37,7 +37,7 @@ To run the program, please refer to [README.md](./README.md) to download the sta
## Python Interface
-We also provide a python interface for python users based on pybind11.
+We also provide a Python interface for Python users based on pybind11.
Dependency: [Pybind11](https://pybind11.readthedocs.io/en/stable/)
@@ -50,22 +50,21 @@ To use the python interface, one can use the following to compile the program th
```shell
mkdir build
-cd buld
-cmake ../ -DCMAKE_BUILD_TYPE=Release -DPYTHON=true
-make -j
-./lifelong --inputFile the_input_file_name -o output_file_location
+cmake -B build ./ -DCMAKE_BUILD_TYPE=Release -DPYTHON=true
+make -C build -j
+./build/lifelong --inputFile the_input_file_name -o output_file_location
```
-Once compiled, the program looks for `pyMAPFPlanner` python module under `./python` or `../python` relative to the location of `lifelong`. Alternatively, you can specify a path in `config.json` and use cmake flag `-DCOPY_PY_PATH_CONFIG=ON` (which copies the `config.json` to target build folder), so that the problem will look for the `pyMAPFPlanner` in the specified folder.
+Once compiled, the program looks for `pyMAPFPlanner` python module under `./python` or `../python` relative to the current working direction. Additionally, you can specify a path in `config.json` and use cmake flag `-DCOPY_PY_PATH_CONFIG=ON` (which copies the `config.json` to the target build folder), so that the problem will look for the `pyMAPFPlanner` in the specified folder.
Additionally, you can specify a specific python version by `-DPYBIND11_PYTHON_VERSION` or an exact python install by `-DPYTHON_EXECUTABLE`
For example:
```shell
-cmake ../ -DCMAKE_BUILD_TYPE=Release -DPYTHON=true -DPYBIND11_PYTHON_VERSION=3.6
+cmake -B build ./ -DCMAKE_BUILD_TYPE=Release -DPYTHON=true -DPYBIND11_PYTHON_VERSION=3.6
#or
-cmake ../ -DCMAKE_BUILD_TYPE=Release -DPYTHON=true -DPYTHON_EXECUTABLE=path/to/python
+cmake -B build ./ -DCMAKE_BUILD_TYPE=Release -DPYTHON=true -DPYTHON_EXECUTABLE=path/to/python
```
Python packages can also be installed through apt-get, thus you can specify the package you want to install in `apt.txt`.
@@ -73,9 +72,9 @@ For example, to install `numpy`, you can put `python3-numpy` in `apt.txt``.
## Compile.sh
-- The evalution system will execuate the `compile.sh` to build your program on the contest server.
-- The evalution system looks for `./build/lifelong` for evaluation.
-- Make sure your `compile.sh` result an execuatable `lifelong` under `build` folder.
+- The evaluation system will execute the `compile.sh` to build your program on the contest server.
+- The evaluation system looks for and execuates `./build/lifelong` for evaluation.
+- Make sure your `compile.sh` result an executable `lifelong` under `build` folder.
- The compile.sh build the c++ interface implementation on default. To build python implementation remove the commands after `# build exec for cpp` and uncomment the commands after `# build exec for python`.
- You may adjust the `compile.sh` to match what your implementation needs.
@@ -83,63 +82,45 @@ For example, to install `numpy`, you can put `python3-numpy` in `apt.txt``.
- Input Output Description
- Refer to the [Input_Output_Format.md]
- Local Test
- - Test problems are provided under `example_problems` folder. Use any json input file there for testing.
- - Once your planner is implemented, run your code according to the instructions in Compile and Run section
+ - Test problems are provided under `example_problems` folder. Use any JSON input file there for testing.
+ - Once your planner is implemented, run your code according to the compile instructions.
- Results are in the output_file_location that you specify in the command line
## Test in Docker
-The evaluation system builds and execuates your implementation in a docker container which act as a sandbox.
+The evaluation system builds and execuates your implementation in a docker container which acts as a sandbox.
To make sure your implementation builds and runs in the docker container. You could test your implementation in a docker container locally.
### Install Docker
-Install latest docker release on your machine, [https://docs.docker.com/engine/install/](https://docs.docker.com/engine/install/).
+Install the latest Docker release on your machine, [https://docs.docker.com/engine/install/](https://docs.docker.com/engine/install/).
### Using `RunInDocker.sh`
-* The evaluation system uses a offical [ubuntu:jammy](https://hub.docker.com/layers/library/ubuntu/jammy/images/sha256-b060fffe8e1561c9c3e6dea6db487b900100fc26830b9ea2ec966c151ab4c020?context=explore) image as base image.
-* In the root of your code base, run command `./RunInDocker.sh`. This script will automatically generate a Dockerfile to build the docker image.
+* The evaluation system uses an official [ubuntu:jammy](https://hub.docker.com/layers/library/ubuntu/jammy/images/sha256-b060fffe8e1561c9c3e6dea6db487b900100fc26830b9ea2ec966c151ab4c020?context=explore) image as base image.
+* In the root of your code base, run the command `./RunInDocker.sh`. This script will automatically generate a Dockerfile to build the Docker image.
* It will copy your codes to the Docker Environment, install dependencies listed in `apt.txt` using apt-get, and compile your code using `compile.sh`.
* You are inside the docker container when the script finishes.
-* You can run the compiled program in side docker container now.
+* You can run the compiled program inside Docker container now.
* The docker image name `` is `mapf_image` and the container name `` is `mapf_test`.
* The default working directory is `/MAPF/codes/`.
-* You can now test and execuate your implementation in the container
-* Exit the container with command: `exit`.
+* You can now test and evaluate your implementation in the container
+* Exit the container with the command: `exit`.
### Start an existing container:
- * In background: `docker container start `
+ * In the background: `docker container start `
* Interactively: `docker container start -i `
-### Execuate Commands Outside the Container
-If the docker container is started in background, you can run commands from the outside of the docker container (treat docker container as executable).
+### Execute Commands Outside the Container
+If the docker container is started in the background, you can run commands from the outside of the docker container (treat the docker container as executable).
- * Use prefix: `docker container exec ` fow any command you want to execuate, for example:
+ * Use prefix: `docker container exec `for any command you want to execute, for example:
```shell
docker container exec mapf_test ./build/lifelong --inputFile ./example_problems/random.domain/random_20.json -o test.json
```
- * All outputs are stored inside the container. You could copy files from docker container. For example: `docker cp mapf_test:/MAPF/codes/test.json ./test.json`, which copies `test.json` to your current working directory.
+ * All outputs are stored inside the container. You could copy files from the Docker container. For example: `docker cp mapf_test:/MAPF/codes/test.json ./test.json`, which copies `test.json` to your current working directory.
## Preprocessing and Large File Storage
-### Evaluation Preprocessing
-At the start of each benchmark problem evaluation, a preprocessing stage calls `MAPFPlanner:initialize` function:
-- The planner has the opportunity to analyse the map and compute auxiliary data before proceeding to the evaluation stage.
-- Preprocessing time is limited to 30 Minutes per map.
-- Nothing you do at this stage will be counted into your final score.
-- You have no access to tasks and robot locations at this stage.
-
-### Local Preprocessing and Large Files
-As benchmark maps are public accessable and given in the start-kit example_problems. Participants can compute auxiliary data offline or train machine learning models offline and upload the result data for submission evaluation.
-
-Participants can push these auxiliary data to their github submission repo, but file size limits are applied by github.
-
-To uoload files larger than than 2 GB, participants should use the large file storage service provided by the competition:
-- A `Large File Storage` button can be found on the `My Submission` page.
-- Click the button opens a storage management panel.
-- Upload or delete files using this panel.
-
-The uploaded file will be synced to the evaluation server when evaluation starts:
-- The folder stores these files will be mounted to the docker container with read only access.
-- The path to the folder can be accessed at `MAPFPlanner::env->file_storage_path`
+Prior to the start of each evaluation, we allow your planner 30 minutes of preprocessing time per map to load supporting files and initialise supporting data structures.
+If your planner makes use of such strategies please refer to the documentation in [Working_with_Preprocessed_Data.md](./Working_with_Preprocessed_Data.md).
diff --git a/README.md b/README.md
index c1c9fbf9..b809e198 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,7 @@ $ cd your_submission_repo
## Compile the start-kit
-### Denpendencies
+### Dependencies
- [cmake >= 3.16](https://cmake.org/)
- [libboost >= 1.49.0](https://www.boost.org/)
@@ -40,26 +40,25 @@ Using `compile.sh`:
Using cmake:
```shell
mkdir build
-cd build
-cmake ../ -DCMAKE_BUILD_TYPE=Release
-make -j
+cmake -B build ./ -DCMAKE_BUILD_TYPE=Release
+make -C build -j
```
## Run the start kit
Running the start-kit using commands:
```shell
-./lifelong --inputFile the_input_file_name -o output_file_location
+./build/lifelong --inputFile the_input_file_name -o output_file_location
```
for example:
```shell
-./lifelong --inputFile ../example_problems/random.domain/random_20.json -o test.json
+./build/lifelong --inputFile ./example_problems/random.domain/random_20.json -o test.json
```
more info on help:
```shell
-./lifelong --help
+./build/lifelong --help
```
## Windows users
@@ -80,9 +79,11 @@ If your private start-kit copy repo was created before a start-kit upgrade, you
You can check `version.txt` to know the current version of your start-kit.
-The `upgrade_start_kit.sh` will check which file is marked as an upgrade needed and pull those files from the start-kit.
+The `upgrade_start_kit.sh` will check which file is marked as an upgrade needed and pull those files from the start-kit. It will pull and stage the files, but not commit them. This allows you to review the changes before committing them.
-The upgrade may overwrite some of your changes to `CMakeLists.txt` and `apt.txt`, you could compare the difference using `git diff` and decide whether to revert some modifications on these files.
+For files stated as unmodifiable in [Parepare_Your_Planner.md](./Prepare_Your_Planner.md), you always commit their changes.
+
+The upgrade may overwrite some of your changes to `CMakeLists.txt`, `compile.sh`, and `apt.txt`, you could compare the difference using `git diff` and decide whether to revert some modifications or partially accept changes on these files.
The upgrade script will not touch any participants' created file, `python/pyMAPFPlanner.py`, `inc/MAPFPlanner.h` and `src/MAPFPlanner.cpp`. So that participants' implementations should not be influenced by the start-kit upgrade.
@@ -94,10 +95,11 @@ Please refer to the [Input_Output_Format.md](./Input_Output_Format.md).
Please refer to the [Prepare_Your_Planner.md](./Prepare_Your_Planner.md).
-## Visualisation
-We provide a visualisation tool written in Python: [https://github.com/MAPF-Competition/MAPF_analysis](https://github.com/MAPF-Competition/MAPF_analysis).
+## Debug and Visualise Your Planner
+We provide a visualisation tool written in Python: [https://github.com/MAPF-Competition/PlanViz](https://github.com/MAPF-Competition/PlanViz).
+It is able to visualise the output of the start-kit program and help participants debug the implementations.
-It is able to visualise the output of the start-kit program and help participants to debug the implementations.
+Please refer to the project website for more information. Also the document [Debug_and_Visualise_Your_Planner](./Debug_and_Visualise_Your_Planner.md) which provides helpful hints for interpreting and diagnosing planner output.
## Submission Instruction
diff --git a/Submission_Instruction.md b/Submission_Instruction.md
index af3dfbd3..4834d2c9 100644
--- a/Submission_Instruction.md
+++ b/Submission_Instruction.md
@@ -14,7 +14,7 @@ $ git push origin
Once you commit your implementation to your submission repo you can begin the evaluation process.
From the competition website, navigate to the My Submission Page. Here you will be able to see details of your entry and submission history (make sure you are logged in!).
-You can evaulate a specific branch under `Evaluate the Branch`, this allows for different algorithms or variant features.
+You can evaluate a specific branch under `Evaluate the Branch`, this allows for different algorithms or variant features.
Then click the `Start Evaluation` button on this page to evaluate your new submission.
diff --git a/Working_with_Preprocessed_Data.md b/Working_with_Preprocessed_Data.md
new file mode 100644
index 00000000..014351df
--- /dev/null
+++ b/Working_with_Preprocessed_Data.md
@@ -0,0 +1,43 @@
+Some algorithms have an offline preprocessing step to compute auxiliary data. The pre-computed data is then loaded and made available to improve the performance of online planning.
+Examples of auxiliary data include machine learning models (weights), strong bounding heuristics and sophisticated constraints that prune the search space.
+In this document, we explain how to work with such auxiliary data if your submission makes use of it.
+
+## Generate auxiliary data
+
+The creation of auxiliary data is the responsibility of each participant. We assume you have external programs that can read and analyse problem instances. These programs run locally (i.e., on your machines or cloud instances) and they can take as long as required (e.g., days).
+They may also interact with your planner, but you should not implement these procedures directly in your planner.
+Instead, your planner should load the resulting auxiliary data during the evaluation of each submission, as part of our 30-minute preprocessing step.
+
+After the competition, we will open-source your submission. For this reason, we recommend you add the code to generate the auxiliary data to your submission repository. This will allow members of the community to replicate your results in the future and may lead to wider adoption of your implementation.
+
+## Prepare for search
+
+Suppose, your auxiliary data is called `example.data` and is located on your local machine in directory `/tmp`.
+You will need to make this file available to your planner, which is accomplished with the help of the `--fileStoragePath` argument, for example:
+
+```
+./build/lifelong --inputFile ./example_problems/random.domain/random_20.json -o test.json --fileStoragePath /tmp
+```
+
+Before evaluation, the start-kit environment calls `MAPFPlanner::initialize` function, which you will implement.
+Locate your auxiliary data by reading the variable `MAPFPlanner::env->file_storage_path`. For example, to load `example.data`, your planner can read
+`
+path = env->file_storage_path + "/example.data"
+`.
+You now have 30 minutes to load your auxiliary data file and initialise supporting data structures.
+These will then be used by your planner during online evaluation.
+
+## Upload to the evaluation server
+
+Auxiliary data files can be quite large and should not be added to your submission repository.
+Instead, we provide a large file hosting service to achieve the same result.
+
+Navigate to the `My Submission` page:
+- A `Large File Storage` button can be found at the bottom of the page.
+- Click the button to open a storage management panel.
+- Upload or delete files using this panel.
+
+The uploaded file will be synced to the evaluation server when the evaluation starts.
+The folder that stores these files will be mounted to the docker container with read-only access.
+All of your submissions have access to this folder.
+If a particular submission requires updated auxiliary data, you will need to manually delete and re-upload via the `My Submission` page.
diff --git a/compile.sh b/compile.sh
index b0aa664b..1c66a303 100755
--- a/compile.sh
+++ b/compile.sh
@@ -4,13 +4,11 @@ mkdir build
# build exec for cpp
-cd build
-cmake ../
-make -j
+cmake -B build ./ -DCMAKE_BUILD_TYPE=Release
+make -C build -j
# build exec for python
-# cd build
-# cmake ../ -DPYTHON=true
-# make -j
+# cmake -B build ./ -DPYTHON=true -DCMAKE_BUILD_TYPE=Release
+# make -C build -j
diff --git a/image/UI.png b/image/UI.png
new file mode 100644
index 00000000..2084751b
Binary files /dev/null and b/image/UI.png differ
diff --git a/image/coordination_system.pdf b/image/coordination_system.pdf
new file mode 100644
index 00000000..9d3a3428
Binary files /dev/null and b/image/coordination_system.pdf differ
diff --git a/image/double_click.gif b/image/double_click.gif
new file mode 100644
index 00000000..f2767ff3
Binary files /dev/null and b/image/double_click.gif differ
diff --git a/image/markers.png b/image/markers.png
new file mode 100644
index 00000000..134d076b
Binary files /dev/null and b/image/markers.png differ
diff --git a/image/single_click.gif b/image/single_click.gif
new file mode 100644
index 00000000..7fd33f06
Binary files /dev/null and b/image/single_click.gif differ
diff --git a/image/tasks_drop_down.png b/image/tasks_drop_down.png
new file mode 100644
index 00000000..ddef0a7c
Binary files /dev/null and b/image/tasks_drop_down.png differ
diff --git a/image/visualization_option.png b/image/visualization_option.png
new file mode 100644
index 00000000..3d695c75
Binary files /dev/null and b/image/visualization_option.png differ
diff --git a/inc/CompetitionSystem.h b/inc/CompetitionSystem.h
index 6400f4ae..8a54764b 100644
--- a/inc/CompetitionSystem.h
+++ b/inc/CompetitionSystem.h
@@ -43,7 +43,7 @@ class BaseSystem
void savePaths(const string &fileName, int option) const; //option = 0: save actual movement, option = 1: save planner movement
//void saveSimulationIssues(const string &fileName) const;
- void saveResults(const string &fileName) const;
+ void saveResults(const string &fileName, int screen) const;
protected:
diff --git a/python/MAPFbinding.cpp b/python/MAPFbinding.cpp
index 0dba9486..a46368f2 100644
--- a/python/MAPFbinding.cpp
+++ b/python/MAPFbinding.cpp
@@ -48,20 +48,24 @@ PYBIND11_MODULE(MAPF, m ){
.def_readonly("goal_locations",&SharedEnvironment::goal_locations)
.def_readonly("curr_timestep",&SharedEnvironment::curr_timestep)
.def_readonly("map",&SharedEnvironment::map)
+ .def_readonly("map_name",&SharedEnvironment::map_name)
+ .def_readonly("file_storage_path", &SharedEnvironment::file_storage_path)
.def_readonly("curr_states",&SharedEnvironment::curr_states);
- //in case that users want to use numpy arrays
+ //in case that users want to use numpy arrays, or reimplement a gym-like environment, they can modify the pyEnvironment
pybind11::class_(m,"pyEnvironment")
.def(pybind11::init())
.def("get_rows",&pyEnvironment::get_rows)
.def("get_cols",&pyEnvironment::get_cols)
.def("get_currtimestep",&pyEnvironment::get_currtimestep)
.def("get_map",&pyEnvironment::get_map)
+ .def("get_map_name", &pyEnvironment::get_map_name)
.def("get_goal_locations",&pyEnvironment::get_goal_locations)
.def("get_num_of_agents",&pyEnvironment::get_num_of_agents)
+ .def("get_file_storage_path", &pyEnvironment::get_file_storage_path)
.def_readonly("env",&pyEnvironment::env,pybind11::return_value_policy::reference)
.def("get_curr_states",&pyEnvironment::get_curr_states);
diff --git a/python/__pycache__/pyMAPFPlanner.cpython-36.pyc b/python/__pycache__/pyMAPFPlanner.cpython-36.pyc
deleted file mode 100644
index dc6d1287..00000000
Binary files a/python/__pycache__/pyMAPFPlanner.cpython-36.pyc and /dev/null differ
diff --git a/python/__pycache__/testlib.cpython-36.pyc b/python/__pycache__/testlib.cpython-36.pyc
deleted file mode 100644
index 81d13edb..00000000
Binary files a/python/__pycache__/testlib.cpython-36.pyc and /dev/null differ
diff --git a/python/pyEnvironment.hpp b/python/pyEnvironment.hpp
index 16e1501d..46f3abcc 100644
--- a/python/pyEnvironment.hpp
+++ b/python/pyEnvironment.hpp
@@ -12,18 +12,14 @@
+// in case of someone wants to implement a gym wrapper,
+// they can modify the pyEnvironment and expose them to python
class pyEnvironment{
public:
pyEnvironment(SharedEnvironment *env):env(env){}
- pyEnvironment(std::string inputJSON){
-
- }
-
- void step(std::vector &actions);
-
pybind11::array_t get_curr_states(){
int num_agents=env->curr_states.size();
@@ -35,7 +31,6 @@ class pyEnvironment{
ptr[3 * i + 1] = env->curr_states[i].orientation;
ptr[3 * i + 2] = env->curr_states[i].timestep;
}
-
return states_array;
}
@@ -53,12 +48,15 @@ class pyEnvironment{
int get_cols(){return env->cols;}
int get_num_of_agents(){return env->num_of_agents;}
+ std::string get_file_storage_path(){
+ return env->file_storage_path;
+ }
std::vector>>get_goal_locations(){
return env->goal_locations;
}
-
+ std::string get_map_name(){ return env->map_name; }
int get_currtimestep(){return env->curr_timestep;}
SharedEnvironment* env;
diff --git a/python/pyMAPFPlanner.cpp b/python/pyMAPFPlanner.cpp
index e4d406fe..ecf979fd 100644
--- a/python/pyMAPFPlanner.cpp
+++ b/python/pyMAPFPlanner.cpp
@@ -7,13 +7,13 @@ pyMAPFPlanner::pyMAPFPlanner():MAPFPlanner(){
py_env=new pyEnvironment(env);
std::ifstream configFile("config.json");
- if(!configFile){
- //default
- std::cout<<"setting to default python path"<>configData;
diff --git a/src/ActionModel.cpp b/src/ActionModel.cpp
index a7ad3260..70041764 100644
--- a/src/ActionModel.cpp
+++ b/src/ActionModel.cpp
@@ -35,18 +35,16 @@ bool ActionModelWithRotate::is_valid(const vector& prev, const vector= grid.map.size() ||
(abs(next[i].location / cols - prev[i].location/cols) + abs(next[i].location % cols - prev[i].location %cols) > 1 ))
{
- cout << "ERROR: agent " << i << " moves out of map size. " << endl;
errors.push_back(make_tuple("unallowed move",i,-1,next[i].timestep));
return false;
}
if (grid.map[next[i].location] == 1) {
- cout << "ERROR: agent " << i << " moves to an obstacle. " << endl;
errors.push_back(make_tuple("unallowed move",i,-1,next[i].timestep));
return false;
}
+
if (vertex_occupied.find(next[i].location) != vertex_occupied.end()) {
- cout << "ERROR: agents " << i << " and " << vertex_occupied[next[i].location] << " have a vertex conflict. " << endl;
errors.push_back(make_tuple("vertex conflict",i,vertex_occupied[next[i].location], next[i].timestep));
return false;
}
@@ -54,7 +52,6 @@ bool ActionModelWithRotate::is_valid(const vector& prev, const vector BaseSystem::move(vector& actions)
task.t_completed = timestep;
finished_tasks_this_timestep.push_back(task);
events[k].push_back(make_tuple(task.task_id, timestep,"finished"));
- log_event_finished(k, task.task_id, timestep);
+ // log_event_finished(k, task.task_id, timestep);
}
paths[k].push_back(curr_states[k]);
actual_movements[k].push_back(actions[k]);
@@ -76,9 +76,7 @@ void BaseSystem::sync_shared_env() {
vector BaseSystem::plan_wrapper()
{
- std::cout<<"wrapper called"< actions;
- std::cout<<"planning"<plan(plan_time_limit, actions);
return actions;
@@ -179,9 +177,6 @@ void BaseSystem::simulate(int simulation_time)
for (; timestep < simulation_time; )
{
- cout << "----------------------------" << std::endl;
- cout << "Timestep " << timestep << std::endl;
-
// find a plan
sync_shared_env();
// vector actions = planner->plan(plan_time_limit);
@@ -212,7 +207,6 @@ void BaseSystem::simulate(int simulation_time)
auto diff = end-start;
planner_times.push_back(std::chrono::duration(diff).count());
}
- cout << new_finished_tasks.size() << " tasks has been finished in this timestep" << std::endl;
// update tasks
for (auto task : new_finished_tasks)
@@ -223,7 +217,6 @@ void BaseSystem::simulate(int simulation_time)
num_of_tasks++;
num_of_task_finish++;
}
- cout << num_of_tasks << " tasks has been finished by far in total" << std::endl;
update_tasks();
@@ -242,12 +235,9 @@ void BaseSystem::simulate(int simulation_time)
}
if (complete_all)
{
- cout << std::endl << "All task finished!" << std::endl;
break;
}
}
-
- cout << std::endl << "Done!" << std::endl;
}
@@ -331,7 +321,7 @@ void BaseSystem::savePaths(const string &fileName, int option) const
}
-void BaseSystem::saveResults(const string &fileName) const
+void BaseSystem::saveResults(const string &fileName, int screen) const
{
json js;
// Save action model
@@ -343,29 +333,32 @@ void BaseSystem::saveResults(const string &fileName) const
js["teamSize"] = num_of_agents;
// Save start locations[x,y,orientation]
- json start = json::array();
- for (int i = 0; i < num_of_agents; i++)
+ if (screen <= 2)
{
- json s = json::array();
- s.push_back(starts[i].location/map.cols);
- s.push_back(starts[i].location%map.cols);
- switch (starts[i].orientation)
+ json start = json::array();
+ for (int i = 0; i < num_of_agents; i++)
{
- case 0:
- s.push_back("E");
- break;
- case 1:
- s.push_back("S");
- case 2:
- s.push_back("W");
- break;
- case 3:
- s.push_back("N");
- break;
+ json s = json::array();
+ s.push_back(starts[i].location/map.cols);
+ s.push_back(starts[i].location%map.cols);
+ switch (starts[i].orientation)
+ {
+ case 0:
+ s.push_back("E");
+ break;
+ case 1:
+ s.push_back("S");
+ case 2:
+ s.push_back("W");
+ break;
+ case 3:
+ s.push_back("N");
+ break;
+ }
+ start.push_back(s);
}
- start.push_back(s);
+ js["start"] = start;
}
- js["start"] = start;
js["numTaskFinished"] = num_of_task_finish;
int sum_of_cost = 0;
@@ -385,147 +378,153 @@ void BaseSystem::saveResults(const string &fileName) const
}
js["sumOfCost"] = sum_of_cost;
js["makespan"] = makespan;
-
- // Save actual paths
- json apaths = json::array();
- for (int i = 0; i < num_of_agents; i++)
+
+ if (screen <= 2)
{
- std::string path;
- bool first = true;
- for (const auto action : actual_movements[i])
+ // Save actual paths
+ json apaths = json::array();
+ for (int i = 0; i < num_of_agents; i++)
{
- if (!first)
- {
- path+= ",";
- }
- else
+ std::string path;
+ bool first = true;
+ for (const auto action : actual_movements[i])
{
- first = false;
- }
+ if (!first)
+ {
+ path+= ",";
+ }
+ else
+ {
+ first = false;
+ }
- if (action == Action::FW)
- {
- path+="F";
- }
- else if (action == Action::CR)
- {
- path+="R";
- }
- else if (action == Action::CCR)
- {
- path+="C";
- }
- else if (action == Action::NA)
- {
- path+="T";
- }
- else
- {
- path+="W";
+ if (action == Action::FW)
+ {
+ path+="F";
+ }
+ else if (action == Action::CR)
+ {
+ path+="R";
+ }
+ else if (action == Action::CCR)
+ {
+ path+="C";
+ }
+ else if (action == Action::NA)
+ {
+ path+="T";
+ }
+ else
+ {
+ path+="W";
+ }
}
+ apaths.push_back(path);
}
- apaths.push_back(path);
+ js["actualPaths"] = apaths;
}
- js["actualPaths"] = apaths;
- //planned paths
- json ppaths = json::array();
- for (int i = 0; i < num_of_agents; i++)
+ if (screen <=1)
{
- std::string path;
- bool first = true;
- for (const auto action : planner_movements[i])
+ //planned paths
+ json ppaths = json::array();
+ for (int i = 0; i < num_of_agents; i++)
{
- if (!first)
- {
- path+= ",";
- }
- else
- {
- first = false;
- }
-
- if (action == Action::FW)
- {
- path+="F";
- }
- else if (action == Action::CR)
- {
- path+="R";
- }
- else if (action == Action::CCR)
- {
- path+="C";
- }
- else if (action == Action::NA)
- {
- path+="T";
- }
- else
+ std::string path;
+ bool first = true;
+ for (const auto action : planner_movements[i])
{
- path+="W";
- }
- }
- ppaths.push_back(path);
- }
- js["plannerPaths"] = ppaths;
+ if (!first)
+ {
+ path+= ",";
+ }
+ else
+ {
+ first = false;
+ }
- json planning_times = json::array();
- for (double time: planner_times)
- planning_times.push_back(time);
- js["plannerTimes"] = planning_times;
+ if (action == Action::FW)
+ {
+ path+="F";
+ }
+ else if (action == Action::CR)
+ {
+ path+="R";
+ }
+ else if (action == Action::CCR)
+ {
+ path+="C";
+ }
+ else if (action == Action::NA)
+ {
+ path+="T";
+ }
+ else
+ {
+ path+="W";
+ }
+ }
+ ppaths.push_back(path);
+ }
+ js["plannerPaths"] = ppaths;
- // Save errors
- json errors = json::array();
- for (auto error: model->errors)
- {
- std::string error_msg;
- int agent1;
- int agent2;
- int timestep;
- std::tie(error_msg,agent1,agent2,timestep) = error;
- json e = json::array();
- e.push_back(agent1);
- e.push_back(agent2);
- e.push_back(timestep);
- e.push_back(error_msg);
- errors.push_back(e);
+ json planning_times = json::array();
+ for (double time: planner_times)
+ planning_times.push_back(time);
+ js["plannerTimes"] = planning_times;
- }
- js["errors"] = errors;
-
- // Save events
- json events_json = json::array();
- for (int i = 0; i < num_of_agents; i++)
- {
- json event = json::array();
- for(auto e: events[i])
+ // Save errors
+ json errors = json::array();
+ for (auto error: model->errors)
{
- json ev = json::array();
- std::string event_msg;
- int task_id;
+ std::string error_msg;
+ int agent1;
+ int agent2;
int timestep;
- std::tie(task_id,timestep,event_msg) = e;
- ev.push_back(task_id);
- ev.push_back(timestep);
- ev.push_back(event_msg);
- event.push_back(ev);
+ std::tie(error_msg,agent1,agent2,timestep) = error;
+ json e = json::array();
+ e.push_back(agent1);
+ e.push_back(agent2);
+ e.push_back(timestep);
+ e.push_back(error_msg);
+ errors.push_back(e);
+
}
- events_json.push_back(event);
- }
- js["events"] = events_json;
+ js["errors"] = errors;
- // Save all tasks
- json tasks = json::array();
- for (auto t: all_tasks)
- {
- json task = json::array();
- task.push_back(t.task_id);
- task.push_back(t.location/map.cols);
- task.push_back(t.location%map.cols);
- tasks.push_back(task);
+ // Save events
+ json events_json = json::array();
+ for (int i = 0; i < num_of_agents; i++)
+ {
+ json event = json::array();
+ for(auto e: events[i])
+ {
+ json ev = json::array();
+ std::string event_msg;
+ int task_id;
+ int timestep;
+ std::tie(task_id,timestep,event_msg) = e;
+ ev.push_back(task_id);
+ ev.push_back(timestep);
+ ev.push_back(event_msg);
+ event.push_back(ev);
+ }
+ events_json.push_back(event);
+ }
+ js["events"] = events_json;
+
+ // Save all tasks
+ json tasks = json::array();
+ for (auto t: all_tasks)
+ {
+ json task = json::array();
+ task.push_back(t.task_id);
+ task.push_back(t.location/map.cols);
+ task.push_back(t.location%map.cols);
+ tasks.push_back(task);
+ }
+ js["tasks"] = tasks;
}
- js["tasks"] = tasks;
std::ofstream f(fileName,std::ios_base::trunc |std::ios_base::out);
f << std::setw(4) << js;
@@ -560,7 +559,6 @@ bool FixedAssignSystem::load_agent_tasks(string fname)
for (int i = 0; i < num_of_agents; i++)
{
- cout << "agent " << i << ": ";
getline(myfile, line);
while (!myfile.eof() && line[0] == '#')
@@ -574,15 +572,12 @@ bool FixedAssignSystem::load_agent_tasks(string fname)
auto loc = atoi((*beg).c_str());
// agent_start_locations[i] = {loc, 0};
starts[i] = State(loc, 0, 0);
- cout << loc;
beg++;
for (int j = 0; j < num_landmarks; j++, beg++)
{
auto loc = atoi((*beg).c_str());
task_queue[i].emplace_back(task_id++, loc, 0, i);
- cout << " -> " << loc;
}
- cout << endl;
}
myfile.close();
@@ -601,7 +596,7 @@ void FixedAssignSystem::update_tasks()
assigned_tasks[k].push_back(task);
events[k].push_back(make_tuple(task.task_id,timestep,"assigned"));
all_tasks.push_back(task);
- log_event_assigned(k, task.task_id, timestep);
+ // log_event_assigned(k, task.task_id, timestep);
}
}
}
@@ -613,8 +608,6 @@ void TaskAssignSystem::update_tasks()
{
while (assigned_tasks[k].size() < num_tasks_reveal && !task_queue.empty())
{
- std::cout << "assigned task " << task_queue.front().task_id <<
- " with loc " << task_queue.front().location << " to agent " << k << std::endl;
Task task = task_queue.front();
task.t_assigned = timestep;
task.agent_assigned = k;
@@ -622,7 +615,7 @@ void TaskAssignSystem::update_tasks()
assigned_tasks[k].push_back(task);
events[k].push_back(make_tuple(task.task_id,timestep,"assigned"));
all_tasks.push_back(task);
- log_event_assigned(k, task.task_id, timestep);
+ // log_event_assigned(k, task.task_id, timestep);
}
}
}
@@ -638,7 +631,7 @@ void InfAssignSystem::update_tasks(){
Task task(task_id,loc,timestep,k);
assigned_tasks[k].push_back(task);
events[k].push_back(make_tuple(task.task_id,timestep,"assigned"));
- log_event_assigned(k, task.task_id, timestep);
+ // log_event_assigned(k, task.task_id, timestep);
all_tasks.push_back(task);
task_id++;
task_counter[k]++;
diff --git a/src/Grid.cpp b/src/Grid.cpp
index b78abb18..9343f285 100644
--- a/src/Grid.cpp
+++ b/src/Grid.cpp
@@ -12,7 +12,7 @@ Grid::Grid(string fname)
exit(-1);
}
- cout << "*** Loading map ***" << std::endl;
+ // cout << "*** Loading map ***" << std::endl;
clock_t t = std::clock();
size_t pos = fname.rfind('.'); // position of the file extension
map_name = fname.substr(0, pos); // get the name without extension
@@ -66,6 +66,6 @@ Grid::Grid(string fname)
myfile.close();
double runtime = (std::clock() - t) / CLOCKS_PER_SEC;
- cout << "Map size: " << rows << "x" << cols;
- cout << "\tDone! (load time: " << runtime << " s)" << std::endl;
+ // cout << "Map size: " << rows << "x" << cols;
+ // cout << "\tDone! (load time: " << runtime << " s)" << std::endl;
}
diff --git a/src/MAPFPlanner.cpp b/src/MAPFPlanner.cpp
index afd494ff..be1411d4 100644
--- a/src/MAPFPlanner.cpp
+++ b/src/MAPFPlanner.cpp
@@ -30,7 +30,6 @@ struct cmp
void MAPFPlanner::initialize(int preprocess_time_limit)
{
- cout << "planner initialize done" << endl;
}
diff --git a/src/driver.cpp b/src/driver.cpp
index 65535acd..9edacb5e 100644
--- a/src/driver.cpp
+++ b/src/driver.cpp
@@ -28,7 +28,7 @@ void sigint_handler(int a)
fprintf(stdout, "stop the simulation...\n");
if (!vm["evaluationMode"].as())
{
- system_ptr->saveResults(vm["output"].as());
+ system_ptr->saveResults(vm["output"].as(),vm["outputScreen"].as());
}
_exit(0);
}
@@ -37,7 +37,7 @@ void sigint_handler(int a)
int main(int argc, char **argv)
{
#ifdef PYTHON
- std::cout<<"Using Python="<()->default_value("."), "input folder")
("inputFile,i", po::value()->required(), "input file name")
("output,o", po::value()->default_value("./test.json"), "output file name")
+ ("outputScreen", po::value()->default_value(1), "the level of details in the output file, 1--showing all the output, 2--ignore the events and tasks, 3--ignore the events, tasks, errors, planner times, starts and paths")
("evaluationMode", po::value()->default_value(false), "evaluate an existing output file")
("simulationTime", po::value()->default_value(5000), "run simulation")
("fileStoragePath", po::value()->default_value(""), "the path to the storage path")
@@ -69,7 +70,6 @@ int main(int argc, char **argv)
boost::filesystem::path p(vm["inputFile"].as());
boost::filesystem::path dir = p.parent_path();
std::string base_folder = dir.string();
- std::cout << base_folder << std::endl;
if (base_folder.size() > 0 && base_folder.back() != '/')
{
base_folder += "/";
@@ -124,7 +124,6 @@ int main(int argc, char **argv)
std::vector agents = read_int_vec(base_folder + read_param_json(data, "agentFile"), team_size);
std::vector tasks = read_int_vec(base_folder + read_param_json(data, "taskFile"));
- std::cout << agents.size() << " agents and " << tasks.size() << " tasks"<< std::endl;
if (agents.size() > tasks.size())
logger->log_warning("Not enough tasks for robots (number of tasks < team size)");
@@ -165,10 +164,10 @@ int main(int argc, char **argv)
if (!vm["evaluationMode"].as())
{
- system_ptr->saveResults(vm["output"].as());
+ system_ptr->saveResults(vm["output"].as(),vm["outputScreen"].as());
}
delete model;
delete logger;
- return 0;
+ _exit(0);
}
diff --git a/utils/upgrade_file_list.txt b/utils/upgrade_file_list.txt
index 0d6325c2..3df6931e 100644
--- a/utils/upgrade_file_list.txt
+++ b/utils/upgrade_file_list.txt
@@ -165,3 +165,7 @@ example_problems/warehouse.domain/warehouse_small_400.json
example_problems/warehouse.domain/warehouse_small_50.json
example_problems/warehouse.domain/warehouse_small_60.json
example_problems/warehouse.domain/warehouse_small_800.json
+compile.sh
+Working_with_Preprocessed_Data.md
+Changelog.md
+Debug_and_Visualise_Your_Planner.md
\ No newline at end of file