From 97748c741804b3ed656d52066d752a5a788bc585 Mon Sep 17 00:00:00 2001 From: Saurav Agarwal Date: Thu, 25 Apr 2024 06:43:03 -0400 Subject: [PATCH] linting --- cppsrc/main/coverage_algorithm.cpp | 23 -- cppsrc/main/world_idf.cpp | 23 -- pyproject.toml | 2 +- python/scripts/coverage_env/coverage_class.py | 40 +-- .../scripts/coverage_env/coverage_simple.py | 26 +- python/scripts/coverage_env/world_idf.py | 21 -- .../scripts/coverage_env/world_map_numpy.py | 20 -- .../data_generation/data_generation.py | 40 +-- .../data_generation/simple_data_generation.py | 249 ++++++++++++------ python/scripts/evaluators/eval.py | 20 -- python/scripts/evaluators/eval_single_env.py | 24 +- python/scripts/training/train_cnn.py | 26 +- python/scripts/training/train_lpac.py | 29 +- 13 files changed, 202 insertions(+), 341 deletions(-) diff --git a/cppsrc/main/coverage_algorithm.cpp b/cppsrc/main/coverage_algorithm.cpp index fcd1c73..73643ef 100644 --- a/cppsrc/main/coverage_algorithm.cpp +++ b/cppsrc/main/coverage_algorithm.cpp @@ -1,26 +1,3 @@ -/* - * This file is part of the CoverageControl library - * - * Author: Saurav Agarwal - * Contact: sauravag@seas.upenn.edu, agr.saurav1@gmail.com - * Repository: https://github.com/KumarRobotics/CoverageControl - * - * Copyright (c) 2024, Saurav Agarwal - * - * The CoverageControl library 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. - * - * The CoverageControl library 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 - * CoverageControl library. If not, see . - */ - /*! * \file coverage_algorithm.cpp * \brief Program to test the CVT-based (Lloyd's) coverage control algorithms diff --git a/cppsrc/main/world_idf.cpp b/cppsrc/main/world_idf.cpp index bc48f30..dd2e52a 100644 --- a/cppsrc/main/world_idf.cpp +++ b/cppsrc/main/world_idf.cpp @@ -1,26 +1,3 @@ -/* - * This file is part of the CoverageControl library - * - * Author: Saurav Agarwal - * Contact: sauravag@seas.upenn.edu, agr.saurav1@gmail.com - * Repository: https://github.com/KumarRobotics/CoverageControl - * - * Copyright (c) 2024, Saurav Agarwal - * - * The CoverageControl library 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. - * - * The CoverageControl library 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 - * CoverageControl library. If not, see . - */ - /*! * \file world_idf.cpp * \brief Program to test generation of IDF diff --git a/pyproject.toml b/pyproject.toml index b0cb528..1fa0410 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -75,7 +75,7 @@ repair-wheel-command = "" # before-test="" test-command = "pytest -ra --showlocals --ignore={project}/python/tests/deprecated {project}/python/tests/test_coverage_env_utils.py {project}/python/tests/test_coverage.py {project}/python/tests/test_env_io.py {project}/python/tests/test_map_generation.py {project}/python/tests/test_models.py {project}/python/tests/test_package.py {project}/python/tests/test_parameters.py {project}/python/tests/test_parity.py" -before-test = "pip install pytest torch torchvision torch_geometric && wget https://github.com/KumarRobotics/CoverageControl/releases/download/v1.1.0/pytest_data.tar.gz && tar -xvf pytest_data.tar.gz -C python/tests/ && rm pytest_data.tar.gz" +before-test = "pip install pytest torch torchvision torch_geometric && wget https://github.com/KumarRobotics/CoverageControl/releases/download/v1.2.0/pytest_data.tar.gz && tar -xvf pytest_data.tar.gz -C python/tests/ && rm pytest_data.tar.gz" test-requires = [] test-extras = [] diff --git a/python/scripts/coverage_env/coverage_class.py b/python/scripts/coverage_env/coverage_class.py index 96b72e3..ed68eb6 100644 --- a/python/scripts/coverage_env/coverage_class.py +++ b/python/scripts/coverage_env/coverage_class.py @@ -1,37 +1,18 @@ -# This file is part of the CoverageControl library -# -# Author: Saurav Agarwal -# Contact: sauravag@seas.upenn.edu, agr.saurav1@gmail.com -# Repository: https://github.com/KumarRobotics/CoverageControl -# -# Copyright (c) 2024, Saurav Agarwal -# -# The CoverageControl library 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. -# -# The CoverageControl library 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 -# CoverageControl library. If not, see . - """ An example class to use the CoverageControl library to run a coverage algorithm """ + import sys -import coverage_control as cc # Main library -from coverage_control import CoverageSystem +import coverage_control as cc # Main library +from coverage_control import CoverageSystem +from coverage_control.algorithms import ClairvoyantCVT as CoverageAlgorithm # Algorithms available: # ClairvoyantCVT # CentralizedCVT # DecentralizedCVT # NearOptimalCVT -from coverage_control.algorithms import ClairvoyantCVT as CoverageAlgorithm + class RunCoverageAlgorithm: """ @@ -45,15 +26,18 @@ def __init__(self, params_filename=None): self.params_ = cc.Parameters() self.env = CoverageSystem(self.params_) - self.controller = CoverageAlgorithm(self.params_, self.params_.pNumRobots, self.env) + self.controller = CoverageAlgorithm( + self.params_, self.params_.pNumRobots, self.env + ) def step(self): """ Run one step of the coverage algorithm """ - self.controller.ComputeActions(); + self.controller.ComputeActions() actions = self.controller.GetActions() error_flag = self.env.StepActions(actions) + return error_flag def execute(self): @@ -68,10 +52,12 @@ def execute(self): while num_steps <= self.params_.pEpisodeSteps: if self.step(): print(f"Error in step {num_steps}") + break if self.controller.IsConverged(): print(f"Converged in step {num_steps}") + break num_steps = num_steps + 1 @@ -79,8 +65,8 @@ def execute(self): final_cost = self.env.GetObjectiveValue() print(f"Improvement %: {100 * (init_cost - final_cost)/init_cost:.2f}") -if __name__ == '__main__': +if __name__ == "__main__": if len(sys.argv) > 1: cc = RunCoverageAlgorithm(sys.argv[1]) else: diff --git a/python/scripts/coverage_env/coverage_simple.py b/python/scripts/coverage_env/coverage_simple.py index da8add1..70229da 100644 --- a/python/scripts/coverage_env/coverage_simple.py +++ b/python/scripts/coverage_env/coverage_simple.py @@ -1,36 +1,14 @@ -# This file is part of the CoverageControl library -# -# Author: Saurav Agarwal -# Contact: sauravag@seas.upenn.edu, agr.saurav1@gmail.com -# Repository: https://github.com/KumarRobotics/CoverageControl -# -# Copyright (c) 2024, Saurav Agarwal -# -# The CoverageControl library 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. -# -# The CoverageControl library 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 -# CoverageControl library. If not, see . - """ A simple example of using the CoverageControl library """ import coverage_control as cc - +from coverage_control.algorithms import ClairvoyantCVT as CoverageAlgorithm # Algorithms available: # ClairvoyantCVT # CentralizedCVT # DecentralizedCVT # NearOptimalCVT -from coverage_control.algorithms import ClairvoyantCVT as CoverageAlgorithm params = cc.Parameters() @@ -53,10 +31,12 @@ if env.StepActions(actions): print(f"Error in step {i}") + break if controller.IsConverged(): print(f"Converged in step {i}") + break # print some metrics diff --git a/python/scripts/coverage_env/world_idf.py b/python/scripts/coverage_env/world_idf.py index 6e501f8..d812c2e 100644 --- a/python/scripts/coverage_env/world_idf.py +++ b/python/scripts/coverage_env/world_idf.py @@ -1,29 +1,8 @@ -# This file is part of the CoverageControl library -# -# Author: Saurav Agarwal -# Contact: sauravag@seas.upenn.edu, agr.saurav1@gmail.com -# Repository: https://github.com/KumarRobotics/CoverageControl -# -# Copyright (c) 2024, Saurav Agarwal -# -# The CoverageControl library 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. -# -# The CoverageControl library 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 -# CoverageControl library. If not, see . """ A simple example of using WorldIDF """ import coverage_control -import numpy as np params = coverage_control.Parameters() params.pNumRobots = 1 diff --git a/python/scripts/coverage_env/world_map_numpy.py b/python/scripts/coverage_env/world_map_numpy.py index 82a36e3..20454c4 100644 --- a/python/scripts/coverage_env/world_map_numpy.py +++ b/python/scripts/coverage_env/world_map_numpy.py @@ -1,23 +1,3 @@ -# This file is part of the CoverageControl library -# -# Author: Saurav Agarwal -# Contact: sauravag@seas.upenn.edu, agr.saurav1@gmail.com -# Repository: https://github.com/KumarRobotics/CoverageControl -# -# Copyright (c) 2024, Saurav Agarwal -# -# The CoverageControl library 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. -# -# The CoverageControl library 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 -# CoverageControl library. If not, see . """ A simple example of using WorldIDF """ diff --git a/python/scripts/data_generation/data_generation.py b/python/scripts/data_generation/data_generation.py index 98e3294..5b6914b 100644 --- a/python/scripts/data_generation/data_generation.py +++ b/python/scripts/data_generation/data_generation.py @@ -1,28 +1,6 @@ -# This file is part of the CoverageControl library -# -# Author: Saurav Agarwal -# Contact: sauravag@seas.upenn.edu, agr.saurav1@gmail.com -# Repository: https://github.com/KumarRobotics/CoverageControl -# -# Copyright (c) 2024, Saurav Agarwal -# -# The CoverageControl library 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. -# -# The CoverageControl library 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 -# CoverageControl library. If not, see . - # @file data_generation.py # This file contains the code to generate a dataset for learning # - # DataDir = "${CoverageControl_ws}/datasets/lpac" # Absolute location # EnvironmentConfig = "${CoverageControl_ws}/datasets/lpac/coverage_control_params.toml" # Absolute location # @@ -48,30 +26,30 @@ # TrainRatio = 0.7 # ValRatio = 0.2 # TestRatio = 0.1 - -## @file data_generation.py +# @file data_generation.py # @brief Class to generate CoverageControl dataset for LPAC architecture - -import os -import sys -import pathlib import datetime import math +import os +import pathlib +import sys import coverage_control import torch -from coverage_control import CoverageSystem, IOUtils +from coverage_control import CoverageSystem +from coverage_control import IOUtils from coverage_control.algorithms import ClairvoyantCVT as CoverageAlgorithm from coverage_control.nn import CoverageEnvUtils -## @ingroup python_api +# @ingroup python_api + + class DatasetGenerator: """ Class to generate CoverageControl dataset for LPAC architecture """ def __init__(self, config_file, append_dir=None): - self.config = IOUtils.load_toml(config_file) self.data_dir = IOUtils.sanitize_path(self.config["DataDir"]) self.dataset_dir = self.data_dir + "/data/" diff --git a/python/scripts/data_generation/simple_data_generation.py b/python/scripts/data_generation/simple_data_generation.py index f8aa811..996cd3f 100644 --- a/python/scripts/data_generation/simple_data_generation.py +++ b/python/scripts/data_generation/simple_data_generation.py @@ -1,28 +1,6 @@ -# This file is part of the CoverageControl library -# -# Author: Saurav Agarwal -# Contact: sauravag@seas.upenn.edu, agr.saurav1@gmail.com -# Repository: https://github.com/KumarRobotics/CoverageControl -# -# Copyright (c) 2024, Saurav Agarwal -# -# The CoverageControl library 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. -# -# The CoverageControl library 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 -# CoverageControl library. If not, see . - # @file simple_data_generation.py # This file contains the code to generate a dataset for learning # - # Uses the following configuration given in a toml file: # DataDir = "${CoverageControl_ws}/datasets/lpac" # Absolute location # EnvironmentConfig = "${CoverageControl_ws}/datasets/lpac/coverage_control_params.toml" # Absolute location @@ -42,27 +20,28 @@ # TriggerPostProcessing = 100 # # CNNMapSize = 32 - -## @file simple_data_generation.py +# @file simple_data_generation.py # @brief Generates a dataset for coverage control learning - -import os -import sys -import torch import math +import os import pathlib +import sys import coverage_control -from coverage_control import IOUtils +import torch from coverage_control import CoverageSystem +from coverage_control import IOUtils from coverage_control.algorithms import ClairvoyantCVT as CoverageAlgorithm from coverage_control.nn import CoverageEnvUtils -## @ingroup python_api -class SimpleDatasetGenerator(): +# @ingroup python_api + + +class SimpleDatasetGenerator: """ Class for generating dataset for learning """ + def __init__(self, config_file: str, append_dir: str = None): """ Constructor for the class @@ -73,13 +52,14 @@ def __init__(self, config_file: str, append_dir: str = None): """ self.config = IOUtils.load_toml(config_file) - self.data_dir = IOUtils.sanitize_path(self.config['DataDir']) - self.dataset_dir = self.data_dir + '/data/' + self.data_dir = IOUtils.sanitize_path(self.config["DataDir"]) + self.dataset_dir = self.data_dir + "/data/" + if append_dir is not None: self.dataset_dir += append_dir if not pathlib.Path(self.data_dir).exists(): - print(f'{self.data_dir} does not exist') + print(f"{self.data_dir} does not exist") exit() if not pathlib.Path(self.dataset_dir).exists(): @@ -87,8 +67,9 @@ def __init__(self, config_file: str, append_dir: str = None): env_config_file = IOUtils.sanitize_path(self.config["EnvironmentConfig"]) env_config_file = pathlib.Path(env_config_file) + if not env_config_file.exists(): - print(f'{env_config_file} does not exist') + print(f"{env_config_file} does not exist") exit() self.env_params = coverage_control.Parameters(env_config_file.as_posix()) @@ -107,6 +88,7 @@ def __init__(self, config_file: str, append_dir: str = None): self.every_num_step = self.config["EveryNumSteps"] self.trigger_size = self.config["TriggerPostProcessing"] self.converged_data_ratio = self.config["ConvergedDataRatio"] + if self.trigger_size == 0 or self.trigger_size > self.num_dataset: self.trigger_size = self.num_dataset @@ -118,13 +100,35 @@ def __init__(self, config_file: str, append_dir: str = None): # Initialize tensors self.actions = torch.zeros((self.num_dataset, self.num_robots, 2)) self.robot_positions = torch.zeros((self.num_dataset, self.num_robots, 2)) - self.raw_local_maps = torch.zeros((self.trigger_size, self.num_robots, self.env_params.pLocalMapSize, self.env_params.pLocalMapSize)) - self.raw_obstacle_maps = torch.zeros((self.trigger_size, self.num_robots, self.env_params.pLocalMapSize, self.env_params.pLocalMapSize)) - self.local_maps = torch.zeros((self.num_dataset, self.num_robots, self.cnn_map_size, self.cnn_map_size)) - self.obstacle_maps = torch.zeros((self.num_dataset, self.num_robots, self.cnn_map_size, self.cnn_map_size)) - self.comm_maps = torch.zeros((self.num_dataset, self.num_robots, 2, self.cnn_map_size, self.cnn_map_size)) + self.raw_local_maps = torch.zeros( + ( + self.trigger_size, + self.num_robots, + self.env_params.pLocalMapSize, + self.env_params.pLocalMapSize, + ) + ) + self.raw_obstacle_maps = torch.zeros( + ( + self.trigger_size, + self.num_robots, + self.env_params.pLocalMapSize, + self.env_params.pLocalMapSize, + ) + ) + self.local_maps = torch.zeros( + (self.num_dataset, self.num_robots, self.cnn_map_size, self.cnn_map_size) + ) + self.obstacle_maps = torch.zeros( + (self.num_dataset, self.num_robots, self.cnn_map_size, self.cnn_map_size) + ) + self.comm_maps = torch.zeros( + (self.num_dataset, self.num_robots, 2, self.cnn_map_size, self.cnn_map_size) + ) self.coverage_features = torch.zeros((self.num_dataset, self.num_robots, 7)) - self.edge_weights = torch.zeros((self.num_dataset, self.num_robots, self.num_robots)) + self.edge_weights = torch.zeros( + (self.num_dataset, self.num_robots, self.num_robots) + ) self.run_data_generation() self.trigger_post_processing() @@ -134,28 +138,43 @@ def __init__(self, config_file: str, append_dir: str = None): def run_data_generation(self): num_non_converged_env = 0 + while self.dataset_count < self.num_dataset: - self.env = CoverageSystem(self.env_params, self.env_params.pNumFeatures, self.num_robots) + self.env = CoverageSystem( + self.env_params, self.env_params.pNumFeatures, self.num_robots + ) self.alg = CoverageAlgorithm(self.env_params, self.num_robots, self.env) self.env_count += 1 - print('Environment: ' + str(self.env_count)) + print("Environment: " + str(self.env_count)) num_steps = 0 is_converged = False - while num_steps < self.env_params.pEpisodeSteps and not is_converged and self.dataset_count < self.num_dataset: + + while ( + num_steps < self.env_params.pEpisodeSteps + and not is_converged + and self.dataset_count < self.num_dataset + ): if num_steps % self.every_num_step == 0: is_converged = self.step_with_save() else: is_converged = self.step_without_save() num_steps += 1 + if num_steps == self.env_params.pEpisodeSteps: num_non_converged_env += 1 - print('Non-converged environment: ' + str(num_non_converged_env)) + print("Non-converged environment: " + str(num_non_converged_env)) - print('Converged in ' + str(num_steps) + ' steps') + print("Converged in " + str(num_steps) + " steps") - num_converged_data = math.ceil(self.converged_data_ratio * num_steps / self.every_num_step) + num_converged_data = math.ceil( + self.converged_data_ratio * num_steps / self.every_num_step + ) converged_data_count = 0 - while converged_data_count < num_converged_data and self.dataset_count < self.num_dataset: + + while ( + converged_data_count < num_converged_data + and self.dataset_count < self.num_dataset + ): self.step_with_save() converged_data_count += 1 @@ -167,36 +186,69 @@ def step_with_save(self): self.actions[count] = CoverageEnvUtils.to_tensor(actions) self.robot_positions[count] = CoverageEnvUtils.get_robot_positions(self.env) self.coverage_features[count] = CoverageEnvUtils.get_voronoi_features(self.env) - self.raw_local_maps[self.trigger_count] = CoverageEnvUtils.get_raw_local_maps(self.env, self.env_params) - self.raw_obstacle_maps[self.trigger_count] = CoverageEnvUtils.get_raw_obstacle_maps(self.env, self.env_params) - self.comm_maps[count] = CoverageEnvUtils.get_communication_maps(self.env, self.env_params, self.cnn_map_size) - self.edge_weights[count] = CoverageEnvUtils.get_weights(self.env, self.env_params) + self.raw_local_maps[self.trigger_count] = CoverageEnvUtils.get_raw_local_maps( + self.env, self.env_params + ) + self.raw_obstacle_maps[self.trigger_count] = ( + CoverageEnvUtils.get_raw_obstacle_maps(self.env, self.env_params) + ) + self.comm_maps[count] = CoverageEnvUtils.get_communication_maps( + self.env, self.env_params, self.cnn_map_size + ) + self.edge_weights[count] = CoverageEnvUtils.get_weights( + self.env, self.env_params + ) self.dataset_count += 1 + if self.dataset_count % 100 == 0: - print(f'Dataset: {self.dataset_count}/{self.num_dataset}') + print(f"Dataset: {self.dataset_count}/{self.num_dataset}") self.trigger_count += 1 + if self.trigger_count == self.trigger_size: self.trigger_post_processing() self.trigger_count = 0 - if(self.env.StepActions(actions)): + if self.env.StepActions(actions): return True + return converged def trigger_post_processing(self): - if self.trigger_start_idx > self.num_dataset -1: + if self.trigger_start_idx > self.num_dataset - 1: return - trigger_end_idx = min(self.num_dataset, self.trigger_start_idx + self.trigger_size) - raw_local_maps = self.raw_local_maps[0:trigger_end_idx - self.trigger_start_idx] + trigger_end_idx = min( + self.num_dataset, self.trigger_start_idx + self.trigger_size + ) + raw_local_maps = self.raw_local_maps[ + 0 : trigger_end_idx - self.trigger_start_idx + ] raw_local_maps = raw_local_maps.to(self.device) - resized_local_maps = CoverageEnvUtils.resize_maps(raw_local_maps, self.cnn_map_size) - self.local_maps[self.trigger_start_idx:trigger_end_idx] = resized_local_maps.view(-1, self.num_robots, self.cnn_map_size, self.cnn_map_size).cpu().clone() - - raw_obstacle_maps = self.raw_obstacle_maps[0:trigger_end_idx - self.trigger_start_idx] + resized_local_maps = CoverageEnvUtils.resize_maps( + raw_local_maps, self.cnn_map_size + ) + self.local_maps[self.trigger_start_idx : trigger_end_idx] = ( + resized_local_maps.view( + -1, self.num_robots, self.cnn_map_size, self.cnn_map_size + ) + .cpu() + .clone() + ) + + raw_obstacle_maps = self.raw_obstacle_maps[ + 0 : trigger_end_idx - self.trigger_start_idx + ] raw_obstacle_maps = raw_obstacle_maps.to(self.device) - resized_obstacle_maps = CoverageEnvUtils.resize_maps(raw_obstacle_maps, self.cnn_map_size) - self.obstacle_maps[self.trigger_start_idx:trigger_end_idx] = resized_obstacle_maps.view(-1, self.num_robots, self.cnn_map_size, self.cnn_map_size).cpu().clone() + resized_obstacle_maps = CoverageEnvUtils.resize_maps( + raw_obstacle_maps, self.cnn_map_size + ) + self.obstacle_maps[self.trigger_start_idx : trigger_end_idx] = ( + resized_obstacle_maps.view( + -1, self.num_robots, self.cnn_map_size, self.cnn_map_size + ) + .cpu() + .clone() + ) self.trigger_start_idx = trigger_end_idx @@ -204,6 +256,7 @@ def normalize_tensor(self, tensor): tensor_mean = tensor.mean(dim=[0, 1]) tensor_std = tensor.std(dim=[0, 1]) tensor = (tensor - tensor_mean) / tensor_std + return tensor, tensor_mean, tensor_std def normalize_communication_maps(self): @@ -211,28 +264,32 @@ def normalize_communication_maps(self): max_val = self.comm_maps.max() range_val = max_val - min_val self.comm_maps = (self.comm_maps - min_val) / range_val - print('Communication map min: ' + str(min_val)) - print('Communication map max: ' + str(max_val)) + print("Communication map min: " + str(min_val)) + print("Communication map max: " + str(max_val)) + return min_val, range_val def save_dataset(self): dataset_dir_path = pathlib.Path(self.dataset_dir) - torch.save(self.robot_positions, dataset_dir_path / 'robot_positions.pt') - torch.save(self.local_maps.to_sparse(), dataset_dir_path / 'local_maps.pt') - torch.save(self.obstacle_maps.to_sparse(), dataset_dir_path / 'obstacle_maps.pt') - torch.save(self.edge_weights.to_sparse(), dataset_dir_path / 'edge_weights.pt') + torch.save(self.robot_positions, dataset_dir_path / "robot_positions.pt") + torch.save(self.local_maps.to_sparse(), dataset_dir_path / "local_maps.pt") + torch.save( + self.obstacle_maps.to_sparse(), dataset_dir_path / "obstacle_maps.pt" + ) + torch.save(self.edge_weights.to_sparse(), dataset_dir_path / "edge_weights.pt") - torch.save(self.comm_maps.to_sparse(), dataset_dir_path / 'comm_maps.pt') - - torch.save(self.actions, dataset_dir_path / 'actions.pt') - torch.save(self.coverage_features, dataset_dir_path / 'coverage_features.pt') + torch.save(self.comm_maps.to_sparse(), dataset_dir_path / "comm_maps.pt") + torch.save(self.actions, dataset_dir_path / "actions.pt") + torch.save(self.coverage_features, dataset_dir_path / "coverage_features.pt") def step_without_save(self): self.alg.ComputeActions() converged = self.alg.IsConverged() - if (self.env.StepActions(self.alg.GetActions())): + + if self.env.StepActions(self.alg.GetActions()): return True + return converged def get_tensor_byte_size_MB(self, tensor): @@ -240,18 +297,40 @@ def get_tensor_byte_size_MB(self, tensor): def print_tensor_sizes(self, file=sys.stdout): # Set to two decimal places - print('Tensor sizes:', file=file) - print('Actions:', self.get_tensor_byte_size_MB(self.actions), file=file) - print('Robot positions:', self.get_tensor_byte_size_MB(self.robot_positions), file=file) - print('Raw local maps:', self.get_tensor_byte_size_MB(self.raw_local_maps), file=file) - print('Raw obstacle maps:', self.get_tensor_byte_size_MB(self.raw_obstacle_maps), file=file) - print('Local maps:', self.get_tensor_byte_size_MB(self.local_maps), file=file) - print('Obstacle maps:', self.get_tensor_byte_size_MB(self.obstacle_maps), file=file) - print('Comm maps:', self.get_tensor_byte_size_MB(self.comm_maps), file=file) - print('Coverage features:', self.get_tensor_byte_size_MB(self.coverage_features), file=file) - -if __name__ == '__main__': + print("Tensor sizes:", file=file) + print("Actions:", self.get_tensor_byte_size_MB(self.actions), file=file) + print( + "Robot positions:", + self.get_tensor_byte_size_MB(self.robot_positions), + file=file, + ) + print( + "Raw local maps:", + self.get_tensor_byte_size_MB(self.raw_local_maps), + file=file, + ) + print( + "Raw obstacle maps:", + self.get_tensor_byte_size_MB(self.raw_obstacle_maps), + file=file, + ) + print("Local maps:", self.get_tensor_byte_size_MB(self.local_maps), file=file) + print( + "Obstacle maps:", + self.get_tensor_byte_size_MB(self.obstacle_maps), + file=file, + ) + print("Comm maps:", self.get_tensor_byte_size_MB(self.comm_maps), file=file) + print( + "Coverage features:", + self.get_tensor_byte_size_MB(self.coverage_features), + file=file, + ) + + +if __name__ == "__main__": config_file = sys.argv[1] + if len(sys.argv) > 2: append_folder = sys.argv[2] else: diff --git a/python/scripts/evaluators/eval.py b/python/scripts/evaluators/eval.py index 93f6587..bca4cd7 100644 --- a/python/scripts/evaluators/eval.py +++ b/python/scripts/evaluators/eval.py @@ -1,23 +1,3 @@ -# This file is part of the CoverageControl library -# -# Author: Saurav Agarwal -# Contact: sauravag@seas.upenn.edu, agr.saurav1@gmail.com -# Repository: https://github.com/KumarRobotics/CoverageControl -# -# Copyright (c) 2024, Saurav Agarwal -# -# The CoverageControl library 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. -# -# The CoverageControl library 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 -# CoverageControl library. If not, see . # @file eval.py # @brief Evaluates the performance of the controllers on a set of environments import os diff --git a/python/scripts/evaluators/eval_single_env.py b/python/scripts/evaluators/eval_single_env.py index 6823870..271993e 100644 --- a/python/scripts/evaluators/eval_single_env.py +++ b/python/scripts/evaluators/eval_single_env.py @@ -1,23 +1,3 @@ -# This file is part of the CoverageControl library -# -# Author: Saurav Agarwal -# Contact: sauravag@seas.upenn.edu, agr.saurav1@gmail.com -# Repository: https://github.com/KumarRobotics/CoverageControl -# -# Copyright (c) 2024, Saurav Agarwal -# -# The CoverageControl library 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. -# -# The CoverageControl library 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 -# CoverageControl library. If not, see . # @file eval_single_env.py # @brief Evaluate a single dataset with multiple controllers import os @@ -62,16 +42,19 @@ def __init__(self, in_config): self.pos_file = None file_exists = False + if "FeatureFile" in self.config and "RobotPosFile" in self.config: self.feature_file = self.env_dir + self.config["FeatureFile"] self.pos_file = self.env_dir + self.config["RobotPosFile"] print(self.feature_file) print(self.pos_file) + if os.path.isfile(self.feature_file): feature_file_exists = True else: print(f"Feature file {self.feature_file} not found") feature_file_exists = False + if os.path.isfile(self.pos_file): pos_file_exists = True else: @@ -88,6 +71,7 @@ def __init__(self, in_config): else: self.env_main = CoverageSystem(self.cc_params) self.world_idf = self.env_main.GetWorldIDF() + if self.feature_file is not None and self.pos_file is not None: self.env_main.WriteEnvironment(self.pos_file, self.feature_file) diff --git a/python/scripts/training/train_cnn.py b/python/scripts/training/train_cnn.py index 8901c5a..65a4703 100644 --- a/python/scripts/training/train_cnn.py +++ b/python/scripts/training/train_cnn.py @@ -1,32 +1,12 @@ -# This file is part of the CoverageControl library -# -# Author: Saurav Agarwal -# Contact: sauravag@seas.upenn.edu, agr.saurav1@gmail.com -# Repository: https://github.com/KumarRobotics/CoverageControl -# -# Copyright (c) 2024, Saurav Agarwal -# -# The CoverageControl library 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. -# -# The CoverageControl library 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 -# CoverageControl library. If not, see . - import os import pathlib import sys import torch -import torch_geometric from coverage_control import IOUtils -from coverage_control.nn import CNN, LocalMapCNNDataset, TrainModel +from coverage_control.nn import CNN +from coverage_control.nn import LocalMapCNNDataset +from coverage_control.nn import TrainModel # Set the device device = torch.device("cuda" if torch.cuda.is_available() else "cpu") diff --git a/python/scripts/training/train_lpac.py b/python/scripts/training/train_lpac.py index 6d7cc12..79ccef5 100644 --- a/python/scripts/training/train_lpac.py +++ b/python/scripts/training/train_lpac.py @@ -1,30 +1,9 @@ -# This file is part of the CoverageControl library -# -# Author: Saurav Agarwal -# Contact: sauravag@seas.upenn.edu, agr.saurav1@gmail.com -# Repository: https://github.com/KumarRobotics/CoverageControl -# -# Copyright (c) 2024, Saurav Agarwal -# -# The CoverageControl library 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. -# -# The CoverageControl library 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 -# CoverageControl library. If not, see . - """ Train the LPAC model """ -## @file train_lpac.py -# @brief Train the LPAC model +# @file train_lpac.py +# @brief Train the LPAC model import os import pathlib import sys @@ -32,7 +11,9 @@ import torch import torch_geometric from coverage_control import IOUtils -from coverage_control.nn import LPAC, CNNGNNDataset, TrainModel +from coverage_control.nn import CNNGNNDataset +from coverage_control.nn import LPAC +from coverage_control.nn import TrainModel # Set the device device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")