Coverage Control Library
Loading...
Searching...
No Matches
coverage_system.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the CoverageControl library
3 *
4 * Author: Saurav Agarwal
5 * Contact: sauravag@seas.upenn.edu, agr.saurav1@gmail.com
6 * Repository: https://github.com/KumarRobotics/CoverageControl
7 *
8 * Copyright (c) 2024, Saurav Agarwal
9 *
10 * The CoverageControl library is free software: you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or (at your
13 * option) any later version.
14 *
15 * The CoverageControl library is distributed in the hope that it will be
16 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
18 * Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along with
21 * CoverageControl library. If not, see <https://www.gnu.org/licenses/>.
22 */
23
31
32namespace CoverageControl {
33
35 : CoverageSystem(params, params.pNumFeatures, params.pNumPolygons,
36 params.pNumRobots) {}
37
39 int const num_gaussians, int const num_robots)
40 : CoverageSystem(params, num_gaussians, 0, num_robots) {}
41
43 int const num_gaussians, int const num_polygons,
44 int const num_robots)
45 : params_{params}, world_idf_{WorldIDF(params_)} {
46 // Generate Bivariate Normal Distribution from random numbers
47 std::srand(
48 std::time(nullptr)); // use current time as seed for random generator
49 gen_ = std::mt19937(
50 rd_()); // Standard mersenne_twister_engine seeded with rd_()
51 distrib_pts_ = std::uniform_real_distribution<>(
52 kLargeEps, params_.pWorldMapSize * params_.pResolution - kLargeEps);
53 std::uniform_real_distribution<> distrib_var(params_.pMinSigma,
54 params_.pMaxSigma);
55 std::uniform_real_distribution<> distrib_peak(params_.pMinPeak,
56 params_.pMaxPeak);
57 for (int i = 0; i < num_gaussians; ++i) {
58 Point2 mean(distrib_pts_(gen_), distrib_pts_(gen_));
59 double sigma(distrib_var(gen_));
60 double scale(distrib_peak(gen_));
61 scale = 2 * M_PI * sigma * sigma * scale;
62 BivariateNormalDistribution dist(mean, sigma, scale);
63 world_idf_.AddNormalDistribution(dist);
64 }
65
66 std::vector<PointVector> polygons;
67 GenerateRandomPolygons(num_polygons, params_.pMaxVertices,
68 params_.pPolygonRadius,
69 params_.pWorldMapSize * params_.pResolution, polygons);
70
71 for (auto &poly : polygons) {
72 double importance = distrib_peak(gen_) * 0.5;
73 PolygonFeature poly_feature(poly, importance);
74 world_idf_.AddUniformDistributionPolygon(poly_feature);
75 }
76
77 world_idf_.GenerateMap();
78 normalization_factor_ = world_idf_.GetNormalizationFactor();
79
80 std::uniform_real_distribution<> env_point_dist(
82 robots_.reserve(num_robots);
83 for (int i = 0; i < num_robots; ++i) {
84 Point2 start_pos(env_point_dist(gen_), env_point_dist(gen_));
85 robots_.push_back(RobotModel(params_, start_pos, world_idf_));
86 }
87 InitSetup();
88}
89
91 WorldIDF const &world_idf,
92 std::string const &pos_file_name)
93 : params_{params}, world_idf_{WorldIDF(params_)} {
94 SetWorldIDF(world_idf);
95
96 // Load initial positions
97 std::ifstream file_pos(pos_file_name);
98 if (!file_pos.is_open()) {
99 std::cout << "Error: Could not open file " << pos_file_name << std::endl;
100 exit(1);
101 }
102 std::vector<Point2> robot_positions;
103 double x, y;
104 while (file_pos >> x >> y) {
105 robot_positions.push_back(Point2(x, y));
106 }
107 robots_.reserve(robot_positions.size());
108 num_robots_ = robot_positions.size();
109 for (Point2 const &pos : robot_positions) {
110 robots_.push_back(RobotModel(params_, pos, world_idf_));
111 }
112 InitSetup();
113}
114
116 WorldIDF const &world_idf,
117 std::vector<Point2> const &robot_positions)
118 : params_{params}, world_idf_{WorldIDF(params_)} {
119 SetWorldIDF(world_idf);
120
121 robots_.reserve(robot_positions.size());
122 num_robots_ = robot_positions.size();
123 for (auto const &pos : robot_positions) {
124 robots_.push_back(RobotModel(params_, pos, world_idf_));
125 }
126 InitSetup();
127}
128
130 Parameters const &params,
131 std::vector<BivariateNormalDistribution> const &dists,
132 std::vector<Point2> const &robot_positions)
133 : params_{params}, world_idf_{WorldIDF(params_)} {
134 world_idf_.AddNormalDistribution(dists);
135 num_robots_ = robot_positions.size();
136
137 // Generate the world map
138 world_idf_.GenerateMap();
139 normalization_factor_ = world_idf_.GetNormalizationFactor();
140
141 robots_.reserve(num_robots_);
142 for (auto const &pos : robot_positions) {
143 robots_.push_back(RobotModel(params_, pos, world_idf_));
144 }
145 InitSetup();
146}
147
148std::pair<MapType, MapType> const &CoverageSystem::GetCommunicationMap(
149 size_t const id, size_t map_size) {
150 communication_maps_[id] = std::make_pair(MapType::Zero(map_size, map_size),
151 MapType::Zero(map_size, map_size));
152 PointVector robot_neighbors_pos = GetRelativePositonsNeighbors(id);
153 double center = map_size / 2. - params_.pResolution / 2.;
154 Point2 center_point(center, center);
155 for (Point2 const &relative_pos : robot_neighbors_pos) {
156 Point2 scaled_indices_val =
157 relative_pos * map_size /
158 (params_.pCommunicationRange * params_.pResolution * 2.) +
159 center_point;
160 int scaled_indices_x = scaled_indices_val[0];
161 int scaled_indices_y = scaled_indices_val[1];
162 Point2 normalized_relative_pos = relative_pos / params_.pCommunicationRange;
163
164 communication_maps_[id].first(scaled_indices_x, scaled_indices_y) +=
165 normalized_relative_pos[0];
166 communication_maps_[id].second(scaled_indices_x, scaled_indices_y) +=
167 normalized_relative_pos[1];
168 }
169 return communication_maps_[id];
170}
171
172void CoverageSystem::InitSetup() {
173 num_robots_ = robots_.size();
174 robot_positions_history_.resize(num_robots_);
175
176 voronoi_cells_.resize(num_robots_);
177 communication_maps_.resize(num_robots_);
178
179 robot_global_positions_.resize(num_robots_);
180 for (size_t iRobot = 0; iRobot < num_robots_; ++iRobot) {
181 robot_global_positions_[iRobot] =
182 robots_[iRobot].GetGlobalCurrentPosition();
183 }
184 system_map_ =
185 MapType::Constant(params_.pWorldMapSize, params_.pWorldMapSize, 0);
186 exploration_map_ =
187 MapType::Constant(params_.pWorldMapSize, params_.pWorldMapSize, 1);
188 explored_idf_map_ =
189 MapType::Constant(params_.pWorldMapSize, params_.pWorldMapSize, 0);
190 total_idf_weight_ = GetWorldMap().sum();
191 relative_positions_neighbors_.resize(num_robots_);
192 neighbor_ids_.resize(num_robots_);
193 for (size_t iRobot = 0; iRobot < num_robots_; ++iRobot) {
194 relative_positions_neighbors_[iRobot].reserve(num_robots_);
195 neighbor_ids_[iRobot].reserve(num_robots_);
196 }
197 PostStepCommands();
198}
199
200void CoverageSystem::PostStepCommands(size_t robot_id) {
201 robot_global_positions_[robot_id] =
202 robots_[robot_id].GetGlobalCurrentPosition();
203 UpdateNeighbors();
204
205 if (params_.pUpdateSystemMap) {
206 MapUtils::MapBounds index, offset;
208 params_.pResolution, robot_global_positions_[robot_id],
209 params_.pSensorSize, params_.pWorldMapSize, index, offset);
210 explored_idf_map_.block(index.left + offset.left,
211 index.bottom + offset.bottom, offset.width,
212 offset.height) =
213 GetRobotSensorView(robot_id).block(offset.left, offset.bottom,
214 offset.width, offset.height);
215 exploration_map_.block(
216 index.left + offset.left, index.bottom + offset.bottom, offset.width,
217 offset.height) = MapType::Zero(offset.width, offset.height);
218 system_map_ = explored_idf_map_ - exploration_map_;
219 }
220 auto &history = robot_positions_history_[robot_id];
221 if (history.size() > 0 and
222 history.size() == size_t(params_.pRobotPosHistorySize)) {
223 history.pop_front();
224 } else {
225 history.push_back(robot_global_positions_[robot_id]);
226 }
227}
228
229void CoverageSystem::PostStepCommands() {
230 UpdateRobotPositions();
231 UpdateNeighbors();
232 if (params_.pUpdateSystemMap) {
233 UpdateSystemMap();
234 }
235 for (size_t iRobot = 0; iRobot < num_robots_; ++iRobot) {
236 auto &history = robot_positions_history_[iRobot];
237 if (history.size() > 0 and
238 history.size() == size_t(params_.pRobotPosHistorySize)) {
239 history.pop_front();
240 } else {
241 history.push_back(robot_global_positions_[iRobot]);
242 }
243 }
244}
245
246void CoverageSystem::UpdateNeighbors() {
247 for (size_t iRobot = 0; iRobot < num_robots_; ++iRobot) {
248 relative_positions_neighbors_[iRobot].clear();
249 neighbor_ids_[iRobot].clear();
250 }
251 for (size_t iRobot = 0; iRobot < num_robots_; ++iRobot) {
252 for (size_t jRobot = iRobot + 1; jRobot < num_robots_; ++jRobot) {
253 Point2 relative_pos =
254 robot_global_positions_[jRobot] - robot_global_positions_[iRobot];
255 if (relative_pos.norm() < params_.pCommunicationRange) {
256 relative_positions_neighbors_[iRobot].push_back(relative_pos);
257 neighbor_ids_[iRobot].push_back(jRobot);
258 relative_positions_neighbors_[jRobot].push_back(-relative_pos);
259 neighbor_ids_[jRobot].push_back(iRobot);
260 }
261 }
262 }
263}
264
265bool CoverageSystem::StepRobotToGoal(int const robot_id, Point2 const &goal,
266 double const speed_factor) {
267 Point2 curr_pos = robots_[robot_id].GetGlobalCurrentPosition();
268 Point2 diff = goal - curr_pos;
269 double dist = diff.norm();
270 double speed = speed_factor * dist / params_.pTimeStep;
271 if (speed <= kLargeEps) {
272 return 0;
273 }
274 speed = std::min(params_.pMaxRobotSpeed, speed);
275 Point2 direction(diff);
276 direction.normalize();
277 if (robots_[robot_id].StepControl(direction, speed)) {
278 std::cerr << "Control incorrect\n";
279 return 1;
280 }
281 PostStepCommands();
282 return 0;
283}
284
286 PointVector &actions) {
287 bool cont_flag = false;
288 UpdateRobotPositions();
289 /* #pragma omp parallel for num_threads(num_robots_) */
290 for (size_t iRobot = 0; iRobot < num_robots_; ++iRobot) {
291 actions[iRobot] = Point2(0, 0);
292 Point2 diff = goals[iRobot] - robot_global_positions_[iRobot];
293 double dist = diff.norm();
294 double speed = dist / params_.pTimeStep;
295 if (speed <= kLargeEps) {
296 continue;
297 }
298 speed = std::min(params_.pMaxRobotSpeed, speed);
299 Point2 direction(diff);
300 direction.normalize();
301 actions[iRobot] = speed * direction;
302 if (StepControl(iRobot, direction, speed)) {
303 std::cerr << "Control incorrect\n";
304 }
305 cont_flag = true;
306 }
307 PostStepCommands();
308 return cont_flag;
309}
310
312 Point2 noisy_pt;
313 noisy_pt[0] = pt[0];
314 noisy_pt[1] = pt[1];
315 auto noise_sigma = params_.pPositionsNoiseSigma;
316 { // Wrap noise generation in a mutex to avoid issues with random number
317 // generation
318 // Random number generation is not thread safe
319 std::lock_guard<std::mutex> lock(mutex_);
320 std::normal_distribution pos_noise{0.0, noise_sigma};
321 noisy_pt += Point2(pos_noise(gen_), pos_noise(gen_));
322 }
323
324 /* std::normal_distribution pos_noise{0.0, noise_sigma}; */
325 /* noisy_pt += Point2(pos_noise(gen_), pos_noise(gen_)); */
326 if (noisy_pt[0] < kLargeEps) {
327 noisy_pt[0] = kLargeEps;
328 }
329 if (noisy_pt[1] < kLargeEps) {
330 noisy_pt[1] = kLargeEps;
331 }
332 if (noisy_pt[0] > params_.pWorldMapSize - kLargeEps) {
333 noisy_pt[0] = params_.pWorldMapSize - kLargeEps;
334 }
335 if (noisy_pt[1] > params_.pWorldMapSize - kLargeEps) {
336 noisy_pt[1] = params_.pWorldMapSize - kLargeEps;
337 }
338 return noisy_pt;
339}
340int CoverageSystem::WriteRobotPositions(std::string const &file_name) const {
341 std::ofstream file_obj(file_name);
342 if (!file_obj) {
343 std::cerr << "[Error] Could not open " << file_name << " for writing."
344 << std::endl;
345 return 1;
346 }
347 file_obj << std::setprecision(kMaxPrecision);
348 for (auto const &pos : robot_global_positions_) {
349 file_obj << pos[0] << " " << pos[1] << std::endl;
350 }
351 file_obj.close();
352 return 0;
353}
354
355int CoverageSystem::WriteRobotPositions(std::string const &file_name,
356 PointVector const &positions) const {
357 std::ofstream file_obj(file_name);
358 if (!file_obj) {
359 std::cerr << "[Error] Could not open " << file_name << " for writing."
360 << std::endl;
361 return 1;
362 }
363 for (auto const &pos : positions) {
364 file_obj << pos[0] << " " << pos[1] << std::endl;
365 }
366 file_obj.close();
367 return 0;
368}
369
370int CoverageSystem::WriteEnvironment(std::string const &pos_filename,
371 std::string const &env_filename) const {
372 WriteRobotPositions(pos_filename);
373 world_idf_.WriteDistributions(env_filename);
374 return 0;
375}
376
377void CoverageSystem::RenderRecordedMap(std::string const &dir_name,
378 std::string const &video_name) const {
379 std::string frame_dir = dir_name + "/frames/";
380 std::filesystem::create_directory(frame_dir);
381 Plotter plotter(frame_dir, params_.pWorldMapSize * params_.pResolution,
382 params_.pResolution);
383 plotter.SetScale(params_.pPlotScale);
384 Plotter plotter_voronoi(frame_dir,
385 params_.pWorldMapSize * params_.pResolution,
386 params_.pResolution);
387 plotter_voronoi.SetScale(params_.pPlotScale);
388#pragma omp parallel for
389 for (size_t i = 0; i < plotter_data_.size(); ++i) {
390 auto iPlotter = plotter;
391 iPlotter.SetPlotName("map", i);
392 /* iPlotter.PlotMap(plotter_data_[i].map, plotter_data_[i].positions,
393 * plotter_data_[i].positions_history, plotter_data_[i].robot_status); */
394 iPlotter.PlotMap(plotter_data_[i].map, plotter_data_[i].positions,
395 plotter_data_[i].positions_history,
396 plotter_data_[i].robot_status,
397 params_.pCommunicationRange);
398 auto iPlotterVoronoi = plotter_voronoi;
399 iPlotterVoronoi.SetPlotName("voronoi_map", i);
400 iPlotterVoronoi.PlotMap(GetWorldMap(), plotter_data_[i].positions,
401 plotter_data_[i].voronoi,
402 plotter_data_[i].positions_history);
403 }
404 bool ffmpeg_call =
405 system(("ffmpeg -y -r 30 -i " + frame_dir +
406 "map%04d.png -vcodec libx264 -crf 25 -pix_fmt yuv420p " +
407 dir_name + "/" + video_name)
408 .c_str());
409 if (ffmpeg_call) {
410 std::cout << "Error: ffmpeg call failed." << std::endl;
411 }
412 ffmpeg_call =
413 system(("ffmpeg -y -r 30 -i " + frame_dir +
414 "voronoi_map%04d.png -vcodec libx264 -crf 25 -pix_fmt yuv420p " +
415 dir_name + "/voronoi_" + video_name)
416 .c_str());
417 if (ffmpeg_call) {
418 std::cout << "Error: ffmpeg call failed." << std::endl;
419 }
420 std::filesystem::remove_all(frame_dir);
421}
422
423void CoverageSystem::RecordPlotData(std::vector<int> const &robot_status,
424 std::string const &map_name) {
425 PlotterData data;
426 if (map_name == "world") {
427 data.map = GetWorldMap();
428 } else {
429 data.map = system_map_;
430 }
431 data.positions = robot_global_positions_;
432 data.positions_history = robot_positions_history_;
433 data.robot_status = robot_status;
434 ComputeVoronoiCells();
435 std::vector<std::list<Point2>> voronoi;
436 auto voronoi_cells = voronoi_.GetVoronoiCells();
437 for (size_t i = 0; i < num_robots_; ++i) {
438 std::list<Point2> cell_points;
439 for (auto const &pos : voronoi_cells[i].cell) {
440 cell_points.push_back(Point2(pos[0], pos[1]));
441 }
442 cell_points.push_back(cell_points.front());
443 voronoi.push_back(cell_points);
444 }
445 data.voronoi = voronoi;
446 plotter_data_.push_back(data);
447}
448
449void CoverageSystem::PlotSystemMap(std::string const &filename) const {
450 std::vector<int> robot_status(num_robots_, 0);
451 Plotter plotter("./", params_.pWorldMapSize * params_.pResolution,
452 params_.pResolution);
453 plotter.SetScale(params_.pPlotScale);
454 plotter.SetPlotName(filename);
455 plotter.PlotMap(system_map_, robot_global_positions_,
456 robot_positions_history_, robot_status,
457 params_.pCommunicationRange);
458}
459
460void CoverageSystem::PlotSystemMap(std::string const &dir_name, int const &step,
461 std::vector<int> const &robot_status) const {
462 Plotter plotter(dir_name, params_.pWorldMapSize * params_.pResolution,
463 params_.pResolution);
464 plotter.SetScale(params_.pPlotScale);
465 plotter.SetPlotName("map", step);
466 plotter.PlotMap(system_map_, robot_global_positions_,
467 robot_positions_history_, robot_status);
468}
469
470void CoverageSystem::PlotWorldMapRobots(std::string const &dir_name,
471 std::string const &map_name) const {
472 Plotter plotter(dir_name, params_.pWorldMapSize * params_.pResolution,
473 params_.pResolution);
474 plotter.SetScale(params_.pPlotScale);
475 plotter.SetPlotName(map_name);
476 std::vector<int> robot_status(num_robots_, 0);
477 plotter.PlotMap(GetWorldMap(), robot_global_positions_,
478 robot_positions_history_, robot_status);
479}
480
481void CoverageSystem::PlotWorldMap(std::string const &dir_name,
482 std::string const &map_name) const {
483 Plotter plotter(dir_name, params_.pWorldMapSize * params_.pResolution,
484 params_.pResolution);
485 plotter.SetScale(params_.pPlotScale);
486 plotter.SetPlotName(map_name);
487 plotter.PlotMap(GetWorldMap());
488}
489
490void CoverageSystem::PlotInitMap(std::string const &dir_name,
491 std::string const &map_name) const {
492 Plotter plotter(dir_name, params_.pWorldMapSize * params_.pResolution,
493 params_.pResolution);
494 plotter.SetScale(params_.pPlotScale);
495 plotter.SetPlotName(map_name);
496 plotter.PlotMap(GetWorldMap(), robot_global_positions_);
497}
498
499void CoverageSystem::PlotMapVoronoi(std::string const &dir_name,
500 int const &step) {
501 ComputeVoronoiCells();
502 Plotter plotter(dir_name, params_.pWorldMapSize * params_.pResolution,
503 params_.pResolution);
504 plotter.SetScale(params_.pPlotScale);
505 plotter.SetPlotName("voronoi_map", step);
506 plotter.PlotMap(GetWorldMap(), robot_global_positions_, voronoi_,
507 robot_positions_history_);
508}
509
510void CoverageSystem::PlotMapVoronoi(std::string const &dir_name,
511 int const &step, Voronoi const &voronoi,
512 PointVector const &goals) const {
513 Plotter plotter(dir_name, params_.pWorldMapSize * params_.pResolution,
514 params_.pResolution);
515 plotter.SetScale(params_.pPlotScale);
516 plotter.SetPlotName("map", step);
517 plotter.PlotMap(GetWorldMap(), robot_global_positions_, goals, voronoi);
518}
519
520void CoverageSystem::PlotFrontiers(std::string const &dir_name, int const &step,
521 PointVector const &frontiers) const {
522 Plotter plotter(dir_name, params_.pWorldMapSize * params_.pResolution,
523 params_.pResolution);
524 plotter.SetScale(params_.pPlotScale);
525 plotter.SetPlotName("map", step);
526 plotter.PlotMap(system_map_, robot_global_positions_,
527 robot_positions_history_, frontiers);
528}
529
530void CoverageSystem::PlotRobotSystemMap(std::string const &dir_name,
531 int const &robot_id, int const &step) {
532 Plotter plotter(dir_name, params_.pLocalMapSize * params_.pResolution,
533 params_.pResolution);
534 plotter.SetPlotName("robot_" + std::to_string(robot_id) + "_", step);
535 PointVector neighbours_positions = GetRelativePositonsNeighbors(robot_id);
536 for (Point2 &pos : neighbours_positions) {
537 pos[0] += params_.pLocalMapSize / 2;
538 pos[1] += params_.pLocalMapSize / 2;
539 }
540 plotter.PlotMap(GetRobotSystemMap(robot_id), neighbours_positions);
541}
542
543void CoverageSystem::PlotRobotIDFMap(std::string const &dir_name,
544 int const &robot_id, int const &step) {
545 Plotter plotter(dir_name, params_.pLocalMapSize * params_.pResolution,
546 params_.pResolution);
547 plotter.SetScale(params_.pPlotScale);
548 plotter.SetPlotName("robot_" + std::to_string(robot_id) + "_", step);
549 plotter.PlotMap(GetRobotLocalMap(robot_id));
550}
551
552void CoverageSystem::PlotRobotExplorationMap(std::string const &dir_name,
553 int const &robot_id,
554 int const &step) {
555 Plotter plotter(dir_name, params_.pLocalMapSize * params_.pResolution,
556 params_.pResolution);
557 plotter.SetPlotName("robot_exp_" + std::to_string(robot_id) + "_", step);
558 plotter.PlotMap(GetRobotExplorationMap(robot_id));
559}
560
561void CoverageSystem::PlotRobotSensorView(std::string const &dir_name,
562 int const &robot_id, int const &step) {
563 Plotter plotter(dir_name, params_.pSensorSize * params_.pResolution,
564 params_.pResolution);
565 plotter.SetPlotName("robot_sensor_" + std::to_string(robot_id) + "_", step);
566 plotter.PlotMap(GetRobotSensorView(robot_id));
567}
568
569void CoverageSystem::PlotRobotLocalMap(std::string const &dir_name,
570 int const &robot_id, int const &step) {
571 Plotter plotter(dir_name, params_.pLocalMapSize * params_.pResolution,
572 params_.pResolution);
573 plotter.SetPlotName("robot_map_" + std::to_string(robot_id) + "_", step);
574 plotter.PlotMap(GetRobotLocalMap(robot_id));
575}
576
577void CoverageSystem::PlotRobotObstacleMap(std::string const &dir_name,
578 int const &robot_id,
579 int const &step) {
580 Plotter plotter(dir_name, params_.pLocalMapSize * params_.pResolution,
581 params_.pResolution);
582 plotter.SetPlotName("robot_obstacle_map_" + std::to_string(robot_id) + "_",
583 step);
584 plotter.PlotMap(GetRobotObstacleMap(robot_id));
585}
586
587void CoverageSystem::PlotRobotCommunicationMaps(std::string const &dir_name,
588 int const &robot_id,
589 int const &step,
590 size_t const &map_size) {
591 auto robot_communication_maps = GetCommunicationMap(robot_id, map_size);
592 Plotter plotter_x(dir_name, map_size * params_.pResolution,
593 params_.pResolution);
594 plotter_x.SetPlotName(
595 "robot_communication_map_x_" + std::to_string(robot_id) + "_", step);
596 plotter_x.PlotMap(robot_communication_maps.first);
597 Plotter plotter_y(dir_name, map_size * params_.pResolution,
598 params_.pResolution);
599 plotter_y.SetPlotName(
600 "robot_communication_map_y_" + std::to_string(robot_id) + "_", step);
601 plotter_y.PlotMap(robot_communication_maps.second);
602}
603
604PointVector CoverageSystem::GetRelativePositonsNeighbors(
605 size_t const robot_id) {
606 if (params_.pAddNoisePositions) {
607 PointVector noisy_positions = GetRobotPositions();
608 for (Point2 &pt : noisy_positions) {
609 pt = AddNoise(pt);
610 }
611 PointVector relative_positions;
612 for (size_t i = 0; i < num_robots_; ++i) {
613 if (i == robot_id) {
614 continue;
615 }
616 if ((noisy_positions[i] - noisy_positions[robot_id]).norm() <
617 params_.pCommunicationRange) {
618 relative_positions.push_back(noisy_positions[i] -
619 noisy_positions[robot_id]);
620 }
621 }
622 return relative_positions;
623 }
624 return relative_positions_neighbors_[robot_id];
625}
626
627std::vector<double> CoverageSystem::GetLocalVoronoiFeatures(
628 int const robot_id) {
629 auto const &pos = robot_global_positions_[robot_id];
630 MapUtils::MapBounds index, offset;
632 params_.pWorldMapSize, index, offset);
633 auto robot_map = robots_[robot_id].GetRobotMap();
634 auto trimmed_local_map =
635 robot_map.block(index.left + offset.left, index.bottom + offset.bottom,
636 offset.width, offset.height);
637 Point2 map_size(offset.width, offset.height);
638
639 Point2 map_translation((index.left + offset.left) * params_.pResolution,
640 (index.bottom + offset.bottom) * params_.pResolution);
641
642 auto robot_neighbors_pos = GetRobotsInCommunication(robot_id);
643 PointVector robot_positions(robot_neighbors_pos.size() + 1);
644
645 robot_positions[0] = pos - map_translation;
646 int count = 1;
647 for (auto const &neighbor_pos : robot_neighbors_pos) {
648 robot_positions[count] = neighbor_pos - map_translation;
649 ++count;
650 }
651 Voronoi voronoi(robot_positions, trimmed_local_map, map_size,
652 params_.pResolution, true, 0);
653 auto vcell = voronoi.GetVoronoiCell();
654 return vcell.GetFeatureVector();
655}
656} // namespace CoverageControl
The CoverageSystem class is the main class for the coverage control library.
PointVector GetRobotPositions(bool force_no_noise=false)
Get the global positions of all robots.
bool StepControl(size_t robot_id, Point2 const &direction, double const speed)
Execute velocity control for robot_id.
bool StepRobotsToGoals(PointVector const &goals, PointVector &actions)
const MapType & GetWorldMap() const
Get the world map.
bool StepRobotToGoal(int const robot_id, Point2 const &goal, double const speed_factor=1)
Point2 AddNoise(Point2 const pt) const
Add noise to the given point and ensure within bounds.
void SetWorldIDF(WorldIDF const &world_idf)
Set the world IDF and recompute the world map.
Class to store parameters.
Definition parameters.h:50
double pTimeStep
Each time step corresponds to pTimeStep seconds.
Definition parameters.h:141
int pMaxVertices
Maximum number of vertices in a polygon.
Definition parameters.h:61
int pRobotPosHistorySize
Number of previous positions to store.
Definition parameters.h:140
double pCommunicationRange
Radius of communication (in meters)
Definition parameters.h:135
Class for handling the robot model.
Definition robot_model.h:61
Class for computing Voronoi cells.
Definition voronoi.h:119
Class for Importance Density Function (IDF) for the world.
Definition world_idf.h:66
void AddNormalDistribution(BivariateNormalDistribution const &distribution)
Definition world_idf.h:277
void AddUniformDistributionPolygon(PolygonFeature const &poly_feature)
Definition world_idf.h:272
The file contains the CoverageSystem class, which is the main class for the coverage control library.
double const kLargeEps
Definition constants.h:51
constexpr auto kMaxPrecision
Definition constants.h:57
std::vector< Point2 > PointVector
Definition typedefs.h:51
Eigen::Vector2d Point2
Definition typedefs.h:44
void ComputeOffsets(double const resolution, Point2 const &pos, int const submap_size, int const map_size, MapBounds &index, MapBounds &offset)
Definition map_utils.h:57
Namespace for the CoverageControl library.
void GenerateRandomPolygons(int const num_polygons, int const max_vertices, double const half_width, double const world_size, std::vector< PointVector > &polygons)
Generate random polygons.
Class to plot the map.