40    : 
CoverageSystem(params, params.pNumGaussianFeatures, params.pNumPolygons,
 
 
   44                               int const num_gaussians, 
int const num_robots)
 
 
   48                               int const num_gaussians, 
int const num_polygons,
 
   56  distrib_pts_ = std::uniform_real_distribution<>(
 
   58  std::uniform_real_distribution<> distrib_var(params_.
pMinSigma,
 
   60  std::uniform_real_distribution<> distrib_peak(params_.
pMinPeak,
 
   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_));
 
   70      sigma = distrib_var(gen_);
 
   76      scale = distrib_peak(gen_);
 
   80    world_idf_ptr_->AddNormalDistribution(dist);
 
   83  std::vector<PointVector> polygons;
 
   88  for (
auto &poly : polygons) {
 
   90    double importance = 0.00005;
 
   94      importance = distrib_peak(gen_) * importance;
 
   97    world_idf_ptr_->AddUniformDistributionPolygon(poly_feature);
 
  100  world_idf_ptr_->GenerateMap();
 
  101  normalization_factor_ = world_idf_ptr_->GetNormalizationFactor();
 
  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_));
 
 
  115                               std::string 
const &pos_file_name)
 
  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;
 
  125  std::vector<Point2> robot_positions;
 
  127  while (file_pos >> x >> y) {
 
  128    robot_positions.push_back(
Point2(x, y));
 
  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;
 
  137  for (
Point2 const &pos : robot_positions) {
 
  138    robots_.push_back(
RobotModel(params_, pos, world_idf_ptr_));
 
 
  145                               std::vector<Point2> 
const &robot_positions)
 
  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_));
 
 
  159    std::vector<BivariateNormalDistribution> 
const &dists,
 
  160    std::vector<Point2> 
const &robot_positions)
 
  162  world_idf_ptr_ = std::make_shared<WorldIDF>(params_);
 
  163  world_idf_ptr_->AddNormalDistribution(dists);
 
  164  num_robots_ = robot_positions.size();
 
  167  world_idf_ptr_->GenerateMap();
 
  168  normalization_factor_ = world_idf_ptr_->GetNormalizationFactor();
 
  170  robots_.reserve(num_robots_);
 
  171  for (
auto const &pos : robot_positions) {
 
  172    robots_.push_back(
RobotModel(params_, pos, world_idf_ptr_));
 
 
  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));
 
  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 /
 
  189    int scaled_indices_x = std::round(scaled_indices_val[0]);
 
  190    int scaled_indices_y = std::round(scaled_indices_val[1]);
 
  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];
 
  198  return communication_maps;
 
 
  201void CoverageSystem::InitSetup() {
 
  202  num_robots_ = robots_.size();
 
  203  robot_positions_history_.resize(num_robots_);
 
  205  voronoi_cells_.resize(num_robots_);
 
  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();
 
  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_);
 
  228void CoverageSystem::PostStepCommands(
size_t robot_id) {
 
  229  robot_global_positions_[robot_id] =
 
  230      robots_[robot_id].GetGlobalCurrentPosition();
 
  234    MapUtils::MapBounds index, offset;
 
  236        params_.
pResolution, robot_global_positions_[robot_id],
 
  238    explored_idf_map_.block(index.left + offset.left,
 
  239                            index.bottom + offset.bottom, offset.width,
 
  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_;
 
  248  auto &history = robot_positions_history_[robot_id];
 
  249  if (history.size() > 0 and
 
  253    history.push_back(robot_global_positions_[robot_id]);
 
  257void CoverageSystem::PostStepCommands() {
 
  258  UpdateRobotPositions();
 
  263  for (
size_t iRobot = 0; iRobot < num_robots_; ++iRobot) {
 
  264    auto &history = robot_positions_history_[iRobot];
 
  265    if (history.size() > 0 and
 
  269      history.push_back(robot_global_positions_[iRobot]);
 
  274void CoverageSystem::UpdateNeighbors() {
 
  275  for (
size_t iRobot = 0; iRobot < num_robots_; ++iRobot) {
 
  276    relative_positions_neighbors_[iRobot].clear();
 
  277    neighbor_ids_[iRobot].clear();
 
  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];
 
  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);
 
  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;
 
  304  direction.normalize();
 
  305  if (robots_[robot_id].
StepControl(direction, speed)) {
 
  306    std::cerr << 
"Control incorrect\n";
 
 
  315  bool cont_flag = 
false;
 
  316  UpdateRobotPositions();
 
  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();
 
  328    direction.normalize();
 
  329    actions[iRobot] = speed * direction;
 
  331      std::cerr << 
"Control incorrect\n";
 
 
  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_));
 
 
  369  std::ofstream file_obj(file_name);
 
  371    std::cerr << 
"[Error] Could not open " << file_name << 
" for writing." 
  376  for (
auto const &pos : robot_global_positions_) {
 
  377    file_obj << pos[0] << 
" " << pos[1] << std::endl;
 
 
  385  std::ofstream file_obj(file_name);
 
  387    std::cerr << 
"[Error] Could not open " << file_name << 
" for writing." 
  391  for (
auto const &pos : positions) {
 
  392    file_obj << pos[0] << 
" " << pos[1] << std::endl;
 
 
  399                                     std::string 
const &env_filename)
 const {
 
  401  world_idf_ptr_->WriteDistributions(env_filename);
 
 
  406                                       std::string 
const &video_name)
 const {
 
  407  std::string frame_dir = dir_name + 
"/frames/";
 
  408  std::filesystem::create_directory(frame_dir);
 
  412  Plotter plotter_voronoi(frame_dir,
 
  416#pragma omp parallel for 
  417  for (
size_t i = 0; i < plotter_data_.size(); ++i) {
 
  418    auto iPlotter = plotter;
 
  422    iPlotter.PlotMap(plotter_data_[i].map, plotter_data_[i].positions,
 
  423                     plotter_data_[i].positions_history,
 
  424                     plotter_data_[i].robot_status,
 
  426    auto iPlotterVoronoi = plotter_voronoi;
 
  428    iPlotterVoronoi.PlotMap(plotter_data_[i].world_map, plotter_data_[i].positions,
 
  429                            plotter_data_[i].voronoi,
 
  430                            plotter_data_[i].positions_history);
 
  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)
 
  438    std::cout << 
"Error: ffmpeg call failed." << std::endl;
 
  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)
 
  446    std::cout << 
"Error: ffmpeg call failed." << std::endl;
 
  448  std::filesystem::remove_all(frame_dir);
 
 
  452                                    std::string 
const &map_name) {
 
  454  if (map_name == 
"world") {
 
  457    data.
map = system_map_;
 
  459  data.
positions = robot_global_positions_;
 
  463  std::vector<std::list<Point2>> voronoi;
 
  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]));
 
  470    cell_points.push_back(cell_points.front());
 
  471    voronoi.push_back(cell_points);
 
  475  plotter_data_.push_back(data);
 
 
  479  std::vector<int> robot_status(num_robots_, 0);
 
  484  plotter.PlotMap(system_map_, robot_global_positions_,
 
  485                  robot_positions_history_, robot_status,
 
 
  490                                   std::vector<int> 
const &robot_status)
 const {
 
  495  plotter.PlotMap(system_map_, robot_global_positions_,
 
  496                  robot_positions_history_, robot_status);
 
 
  500                                        std::string 
const &map_name)
 const {
 
  505  std::vector<int> robot_status(num_robots_, 0);
 
  506  plotter.PlotMap(
GetWorldMap(), robot_global_positions_,
 
  507                  robot_positions_history_, robot_status);
 
 
  511                                  std::string 
const &map_name)
 const {
 
 
  520                                 std::string 
const &map_name)
 const {
 
  525  plotter.PlotMap(
GetWorldMap(), robot_global_positions_);
 
 
  535  plotter.PlotMap(
GetWorldMap(), robot_global_positions_, voronoi_,
 
  536                  robot_positions_history_);
 
 
  540                                    int const &step, 
Voronoi const &voronoi,
 
  546  plotter.PlotMap(
GetWorldMap(), robot_global_positions_, goals, voronoi);
 
 
  555  plotter.PlotMap(system_map_, robot_global_positions_,
 
  556                  robot_positions_history_, frontiers);
 
 
  560                                        int const &robot_id, 
int const &step) {
 
  563  plotter.
SetPlotName(
"robot_" + std::to_string(robot_id) + 
"_", step);
 
  565  for (
Point2 &pos : neighbours_positions) {
 
 
  573                                     int const &robot_id, 
int const &step) {
 
  577  plotter.
SetPlotName(
"robot_" + std::to_string(robot_id) + 
"_", step);
 
 
  586  plotter.
SetPlotName(
"robot_exp_" + std::to_string(robot_id) + 
"_", step);
 
 
  591                                         int const &robot_id, 
int const &step) {
 
  594  plotter.
SetPlotName(
"robot_sensor_" + std::to_string(robot_id) + 
"_", step);
 
 
  603  plotter.
SetPlotName(
"robot_obstacle_map_" + std::to_string(robot_id) + 
"_",
 
 
  611                                                size_t const &map_size) {
 
  616      "robot_communication_map_x_" + std::to_string(robot_id) + 
"_", step);
 
  617  plotter_x.PlotMap(robot_communication_maps.first);
 
  621      "robot_communication_map_y_" + std::to_string(robot_id) + 
"_", step);
 
  622  plotter_y.PlotMap(robot_communication_maps.second);
 
 
  626    size_t const robot_id) {
 
  629    for (
Point2 &pt : noisy_positions) {
 
  633    for (
size_t i = 0; i < num_robots_; ++i) {
 
  637      if ((noisy_positions[i] - noisy_positions[robot_id]).norm() <
 
  639        relative_positions.push_back(noisy_positions[i] -
 
  640                                     noisy_positions[robot_id]);
 
  643    return relative_positions;
 
  645  return relative_positions_neighbors_[robot_id];
 
 
  649    int const robot_id) {
 
  650  auto const &pos = robot_global_positions_[robot_id];
 
  654  auto robot_map = robots_[robot_id].GetRobotMap();
 
  655  auto trimmed_local_map =
 
  664  PointVector robot_positions(robot_neighbors_pos.size() + 1);
 
  666  robot_positions[0] = pos - map_translation;
 
  668  for (
auto const &neighbor_pos : robot_neighbors_pos) {
 
  669    robot_positions[count] = neighbor_pos - map_translation;
 
  672  Voronoi voronoi(robot_positions, trimmed_local_map, map_size,
 
  675  return vcell.GetFeatureVector();
 
 
Class for Bivariate Normal Distribution.
 
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
 
void ComputeVoronoiCells()
 
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.
 
double pTimeStep
Each time step corresponds to pTimeStep seconds.
 
int pNumRobots
Number of robots.
 
double pPositionsNoiseSigma
 
int pMaxVertices
Maximum number of vertices in a polygon.
 
int pRobotPosHistorySize
Number of previous positions to store.
 
double pCommunicationRange
Radius of communication (in meters)
 
void SetPlotName(std::string const &name)
 
void SetScale(double const &sc)
 
Class for handling the robot model.
 
Class for computing Voronoi cells.
 
auto GetVoronoiCells() const
 
Class for Importance Density Function (IDF) for the world.
 
The file contains the CoverageSystem class, which is the main class for the coverage control library.
 
constexpr auto kMaxPrecision
 
std::vector< Point2 > PointVector
 
void ComputeOffsets(double const resolution, Point2 const &pos, int const submap_size, int const map_size, MapBounds &index, MapBounds &offset)
 
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.
 
Provides utilities for polygon manipulation using CGAL.
 
Data structure to store plotter data.
 
std::vector< std::list< Point2 > > voronoi
 
std::vector< std::list< Point2 > > positions_history
 
std::vector< int > robot_status
 
A struct to store a polygon feature and a uniform importance value.