Coverage Control Library
Loading...
Searching...
No Matches
loaders.py
1# This file is part of the CoverageControl library
2#
3# Author: Saurav Agarwal
4# Contact: sauravag@seas.upenn.edu, agr.saurav1@gmail.com
5# Repository: https://github.com/KumarRobotics/CoverageControl
6#
7# Copyright (c) 2024, Saurav Agarwal
8#
9# The CoverageControl library is free software: you can redistribute it and/or
10# modify it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or (at your
12# option) any later version.
13#
14# The CoverageControl library is distributed in the hope that it will be
15# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17# Public License for more details.
18#
19# You should have received a copy of the GNU General Public License along with
20# CoverageControl library. If not, see <https://www.gnu.org/licenses/>.
21
22"""
23Module for loading datasets
24"""
25
26import torch
27from coverage_control import IOUtils
28from torch_geometric.data import Dataset
29
30from .coverage_env_utils import CoverageEnvUtils
31from .data_loader_utils import DataLoaderUtils
32
33
34
35class LocalMapCNNDataset(Dataset):
36 """
37 Dataset for CNN training
38 """
39
40 def __init__(
41 self,
42 data_dir: str,
43 stage: str,
44 use_comm_map: bool,
45 output_dim: int,
46 preload: bool = True,
47 ):
48 super().__init__(None, None, None, None)
49 """
50 Constructor for the LocalMapCNNDataset class
51 Args:
52 data_dir (str): Directory containing the data
53 stage (str): Stage of the data (train, val, test)
54 use_comm_map (bool): Whether to use communication maps
55 output_dim (int): Dimension of the output
56 preload (bool): Whether to preload the data
57 """
58
59 self.stage = stage
60 self.data_dir = data_dir
61 self.output_dim = output_dim
62 self.use_comm_map = use_comm_map
63
64 if preload is True:
65 self.load_data()
66
67 def len(self):
68 return self.dataset_size
69
70 def get(self, idx):
71 maps = self.maps[idx]
72 target = self.targets[idx]
73
74 return maps, target
75
76 def load_data(self):
77 """
78 Load the data from the data directory
79 """
80 # maps has shape (num_samples, num_robots, nuimage_size, image_size)
81 self.maps = DataLoaderUtils.load_maps(
82 f"{self.data_dir}/{self.stage}", self.use_comm_map
83 )
84 num_channels = self.maps.shape[2]
85 image_size = self.maps.shape[3]
86
87 self.maps = self.maps.view(-1, num_channels, image_size, image_size)
88 self.dataset_size = self.maps.shape[0]
89
90 # self.targets, self.targets_mean, self.targets_std = DataLoaderUtils.load_features(f"{self.data_dir}/{self.stage}", self.output_dim)
91 self.targets, self.targets_mean, self.targets_std = (
92 DataLoaderUtils.load_actions(f"{self.data_dir}/{self.stage}")
93 )
94 self.targets = self.targets.view(-1, self.targets.shape[2])
95
96
97class LocalMapGNNDataset(Dataset):
98 """
99 Deprecated
100 """
101
102 def __init__(self, data_dir, stage):
103 super().__init__(None, None, None, None)
104
105 self.stage = stage
106
107 # Coverage maps is of shape (num_samples, num_robots, 2, image_size, image_size)
108 self.coverage_maps = IOUtils.load_tensor(f"{data_dir}/{stage}/coverage_maps.pt")
109 self.num_robots = self.coverage_maps.shape[1]
110 self.dataset_size = self.coverage_maps.shape[0]
111 self.targets, self.targets_mean, self.targets_std = (
112 DataLoaderUtils.load_actions(f"{data_dir}/{stage}")
113 )
114 self.robot_positions = DataLoaderUtils.load_robot_positions(
115 f"{data_dir}/{stage}"
116 )
117
118 h_vals = torch.linspace(1.0, -1.0, self.coverage_maps.shape[-2] + 1)
119 h_vals = (h_vals[1:] + h_vals[:-1]) / 2
120 w_vals = torch.linspace(-1.0, 1.0, self.coverage_maps.shape[-1] + 1)
121 w_vals = (w_vals[1:] + w_vals[:-1]) / 2
122 self.heatmap_x = (
123 torch.stack([h_vals] * self.coverage_maps.shape[-1], axis=1) / 100
124 )
125 self.heatmap_y = (
126 torch.stack([w_vals] * self.coverage_maps.shape[-2], axis=0) / 100
127 )
128
129 # Print the details of the dataset with device information
130 print(f"Dataset: {self.stage} | Size: {self.dataset_size}")
131 print(
132 f"Coverage Maps: {self.coverage_maps.shape} | Device: {self.coverage_maps.device}"
133 )
134 print(f"Targets: {self.targets.shape} | Device: {self.targets.device}")
135 print(
136 f"Robot Positions: {self.robot_positions.shape} | Device: {self.robot_positions.device}"
137 )
138 print(f"Heatmap X: {self.heatmap_x.shape} | Device: {self.heatmap_x.device}")
139 print(f"Heatmap Y: {self.heatmap_y.shape} | Device: {self.heatmap_y.device}")
140
141 def len(self):
142 return self.dataset_size
143
144 def get(self, idx):
145 # coverage_maps is of shape (num_robots, 2, image_size, image_size)
146 coverage_maps = self.coverage_maps[idx]
147 # coverage_maps = coverage_maps.view(-1, 2, coverage_maps.shape[-2], coverage_maps.shape[-1])
148 # Add heatmaps to coverage maps
149 # heatmaps are of shape image_size x image_size
150 heatmap_x = torch.stack([self.heatmap_x] * coverage_maps.shape[0])
151 heatmap_y = torch.stack([self.heatmap_y] * coverage_maps.shape[0])
152 maps = torch.stack(
153 [coverage_maps[:, 0], coverage_maps[:, 1], heatmap_x, heatmap_y], dim=1
154 )
155 # maps = maps.view(self.num_robots, 4, maps.shape[-2], maps.shape[-1])
156
157 edge_weights = CoverageEnvUtils.RobotPositionsToEdgeWeights(
158 self.robot_positions[idx], 2048, 256
159 )
160 data = DataLoaderUtils.to_torch_geometric_data(maps, edge_weights)
161 targets = self.targets[idx]
162
163 return data, targets
164
165
166
167class CNNGNNDataset(Dataset):
168 """
169 Dataset for hybrid CNN-GNN training
170 """
171
172 def __init__(self, data_dir, stage, use_comm_map, world_size):
173 super().__init__(None, None, None, None)
174
175 self.stage = stage
176
177 self.maps = DataLoaderUtils.load_maps(f"{data_dir}/{stage}", use_comm_map)
178 self.dataset_size = self.maps.shape[0]
179
180 self.targets, self.targets_mean, self.targets_std = (
181 DataLoaderUtils.load_actions(f"{data_dir}/{stage}")
182 )
183 self.edge_weights = DataLoaderUtils.load_edge_weights(f"{data_dir}/{stage}")
184
185 self.robot_positions = DataLoaderUtils.load_robot_positions(
186 f"{data_dir}/{stage}"
187 )
188 self.robot_positions = (self.robot_positions + world_size / 2) / world_size
189
190 # Print the details of the dataset with device information
191 print(f"Dataset: {self.stage} | Size: {self.dataset_size}")
192 print(f"Maps: {self.maps.shape} | Device: {self.maps.device}")
193 print(f"Targets: {self.targets.shape} | Device: {self.targets.device}")
194 print(
195 f"Edge Weights: {self.edge_weights.shape} | Device: {self.edge_weights.device}"
196 )
197 print(f"Targets: {self.targets.shape} | Device: {self.targets.device}")
198 print(
199 f"Robot Positions: {self.robot_positions.shape} | Device: {self.robot_positions.device}"
200 )
201
202 def len(self):
203 return self.dataset_size
204
205 def get(self, idx):
206 data = DataLoaderUtils.to_torch_geometric_data(
207 self.maps[idx], self.edge_weights[idx], self.robot_positions[idx]
208 )
209 # data = CoverageEnvUtils.GetTorchGeometricDataRobotPositions(self.maps[idx], self.robot_positions[idx])
210 targets = self.targets[idx]
211
212 if targets.dim == 3:
213 targets = targets.view(-1, targets.shape[-1])
214
215 return data, targets
216
217
218
219class VoronoiGNNDataset(Dataset):
220 """
221 Dataset for non-hybrid GNN training
222 """
223
224 def __init__(self, data_dir, stage, output_dim):
225 super().__init__(None, None, None, None)
226
227 self.stage = stage
228 self.output_dim = output_dim
229
230 self.features = DataLoaderUtils.load_features(f"{data_dir}/{stage}", output_dim)
231 self.dataset_size = self.features[0].shape[0]
232 self.targets, self.targets_mean, self.targets_std = (
233 DataLoaderUtils.load_actions(f"{data_dir}/{stage}")
234 )
235 self.edge_weights = DataLoaderUtils.load_edge_weights(f"{data_dir}/{stage}")
236
237 def len(self):
238 return self.dataset_size
239
240 def get(self, idx):
241 data = DataLoaderUtils.to_torch_geometric_data(
242 self.features[idx], self.edge_weights[idx], self.targets[idx]
243 )
244
245 return data, data.y
Dataset for hybrid CNN-GNN training.
Definition loaders.py:170
load_data(self)
Load the data from the data directory.
Definition loaders.py:79