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