area_division.cpp
Go to the documentation of this file.
1 #include "area_division.h"
2 
6 void divide_area ()
7 {
8  // convert swarm pose to grid
9  map<string, vector<int>> swarm_grid;
10  for (auto cps : swarm_pose) {
11  vector<int> pos(2);
12  pos[0] = int(round((cps.second.pose.position.x - gridmap.info.origin.position.x) / gridmap.info.resolution));
13  pos[1] = int(round((cps.second.pose.position.y - gridmap.info.origin.position.y) / gridmap.info.resolution));
14  swarm_grid.emplace(cps.first, pos);
15  ROS_DEBUG("Other CPS %s at (%d,%d)", cps.first.c_str(), pos[0], pos[1]);
16  }
17 
18  // add this robot to swarm grid
19  vector<int> pos(2);
20  pos[0] = int(round((pose.position.x - gridmap.info.origin.position.x) / gridmap.info.resolution));
21  pos[1] = int(round((pose.position.y - gridmap.info.origin.position.y) / gridmap.info.resolution));
22  swarm_grid.emplace(uuid, pos);
23  ROS_DEBUG("Me %s at (%d,%d)", uuid.c_str(), pos[0], pos[1]);
24 
25  // divide area
26  ROS_INFO("Dividing area...");
27  vector<signed char, allocator<signed char>> map = gridmap.data;
28  division->initialize_map((int)gridmap.info.width, (int)gridmap.info.height, map);
29  division->initialize_cps(swarm_grid);
30  division->divide();
31 
32  // visualize area
33  if (visualize)
35 
36  reconfigure = false;
37 }
38 
42 void sync ()
43 {
44  // start synchronization sequence
45  if (sync_start + Duration(swarm_timeout) < Time::now()) {
46  // stop moving
47  geometry_msgs::PoseStamped goal_pose;
48  goal_pose.header.stamp = Time::now();
49  goal_pose.pose = pose;
50  pos_pub.publish(goal_pose);
51 
52  // reset information about swarm
53  swarm_pose.clear();
54 
55  // start of synchronization time window
56  sync_start = Time::now();
57 
58  // send event to swarm
59  cpswarm_msgs::AreaDivisionEvent event;
60  event.header.stamp = Time::now();
61  event.swarmio.name = "area_division";
62  geometry_msgs::PoseStamped ps;
63  ps.header.frame_id = "local_origin_ned";
64  ps.pose = pose;
65  event.pose = ps;
66  swarm_pub.publish(event);
67  }
68 }
69 
76 bool get_area (nav_msgs::GetMap::Request &req, nav_msgs::GetMap::Response &res)
77 {
78  // synchronize with swarm
79  sync();
80 
81  // wait for swarm updates
82  while (Time::now() <= sync_start + Duration(swarm_timeout)) {
83  rate->sleep();
84  spinOnce();
85  }
86 
87  // swarm configuration changed
88  if (reconfigure) {
89  // divide area
90  divide_area();
91  }
92 
93  // return assigned area
94  res.map = division->get_grid(gridmap, uuid);
95 
96  return true;
97 }
98 
103 void uuid_callback (const swarmros::String::ConstPtr& msg)
104 {
105  uuid = msg->value;
106 }
107 
112 void pose_callback (const geometry_msgs::PoseStamped::ConstPtr& msg)
113 {
114  // store new position and orientation in class variables
115  pose = msg->pose;
116 
117  // valid pose received
118  if (msg->header.stamp.isValid())
119  pose_valid = true;
120 }
121 
126 void swarm_callback (const cpswarm_msgs::AreaDivisionEvent::ConstPtr& msg)
127 {
128  // synchronize with swarm
129  sync();
130 
131  // recalculate area division
132  reconfigure = true;
133 
134  // check if cps is already known
135  auto idx = swarm_pose.find(msg->swarmio.node);
136 
137  // add new cps
138  if (idx == swarm_pose.end()) {
139  ROS_DEBUG("Add CPS %s", msg->swarmio.node.c_str());
140 
141  // add cps
142  swarm_pose.emplace(msg->swarmio.node, msg->pose);
143  }
144 
145  // update existing cps
146  else {
147  ROS_DEBUG("Update CPS %s", msg->swarmio.node.c_str());
148 
149  // update cps
150  idx->second.header.stamp = Time::now();
151  idx->second = msg->pose;
152  }
153 }
154 
159 void map_callback (const nav_msgs::OccupancyGrid::ConstPtr& msg)
160 {
161  // TODO: react to map changes, i.e., reconfigure = true
162  gridmap = *msg;
163  map_valid = true;
164 }
165 
172 int main (int argc, char **argv)
173 {
174  // init ros node
175  init(argc, argv, "area_division");
176  NodeHandle nh;
177 
178  // init global variables
179  reconfigure = true;
180  sync_start = Time::now();
181 
182  // read parameters
183  double loop_rate;
184  nh.param(this_node::getName() + "/loop_rate", loop_rate, 1.5);
185  int queue_size;
186  nh.param(this_node::getName() + "/queue_size", queue_size, 10);
187  nh.param(this_node::getName() + "/swarm_timeout", swarm_timeout, 5.0);
188  nh.param(this_node::getName() + "/visualize", visualize, false);
189 
190  // initialize flags
191  uuid = "";
192  pose_valid = false;
193  swarm_valid = false;
194  map_valid = false;
195 
196  // publishers and subscribers
197  Subscriber uuid_sub = nh.subscribe("bridge/uuid", queue_size, uuid_callback);
198  Subscriber pose_sub = nh.subscribe("pos_provider/pose", queue_size, pose_callback);
199  Subscriber swarm_sub = nh.subscribe("bridge/events/area_division", queue_size, swarm_callback);
200  Subscriber map_sub = nh.subscribe("area_provider/map", queue_size, map_callback); // TODO: use explored/merged map
201  pos_pub = nh.advertise<geometry_msgs::PoseStamped>("pos_controller/goal_position", queue_size, true);
202  swarm_pub = nh.advertise<cpswarm_msgs::AreaDivisionEvent>("area_division", queue_size, true);
203  if (visualize)
204  area_pub = nh.advertise<nav_msgs::OccupancyGrid>("assigned_map", queue_size, true);
205 
206  // init loop rate
207  rate = new Rate(loop_rate);
208 
209  // init uuid
210  while (ok() && uuid == "") {
211  ROS_DEBUG_ONCE("Waiting for UUID...");
212  rate->sleep();
213  spinOnce();
214  }
215 
216  // init position
217  while (ok() && pose_valid == false) {
218  ROS_DEBUG_ONCE("Waiting for valid position information...");
219  rate->sleep();
220  spinOnce();
221  }
222 
223  // init map
224  while (ok() && map_valid == false) {
225  ROS_DEBUG_ONCE("Waiting for grid map...");
226  rate->sleep();
227  spinOnce();
228  }
229 
230  // create area division object
231  division = new area_division();
232 
233  // provide area service
234  ServiceServer area_service = nh.advertiseService("area/assigned", get_area);
235  spin();
236 
237  // clean up
238  delete rate;
239  delete division;
240 
241  return 0;
242 }
Publisher area_pub
Publisher to visualize the assigned area grid map.
Definition: area_division.h:35
bool visualize
Whether to publish the area division on a topic for visualization.
Definition: area_division.h:85
bool swarm_valid
Whether valid position information has been received from the other swarm members.
Definition: area_division.h:50
A class to divide the environment optimally among multiple cyber physical systems (CPSs)...
void divide_area()
Divide the area of the grid map equally among multiple CPSs.
void uuid_callback(const swarmros::String::ConstPtr &msg)
Callback function to receive the UUID from the communication library.
double swarm_timeout
The time in seconds to wait after an area division event before starting the area division...
Definition: area_division.h:80
bool pose_valid
Whether a valid position has been received.
Definition: area_division.h:60
nav_msgs::OccupancyGrid gridmap
The complete grid map.
Definition: area_division.h:65
geometry_msgs::Pose pose
Current position of the CPS.
Definition: area_division.h:55
Publisher swarm_pub
Publisher to syncronize with other CPSs.
Definition: area_division.h:30
void pose_callback(const geometry_msgs::PoseStamped::ConstPtr &msg)
Callback function for position updates.
Time sync_start
The time at which the synchronization for the area division started.
Definition: area_division.h:95
void initialize_cps(map< string, vector< int >> cpss)
Define the CPS positions.
void divide()
Perform the area division.
area_division * division
The object encapsulating the area division optimization algorithm.
Definition: area_division.h:75
string uuid
UUID of this CPS.
Definition: area_division.h:20
void initialize_map(int r, int c, vector< signed char > src)
Define the grid map.
void sync()
Synchronize The CPSs by exchanging an event.
map< string, geometry_msgs::PoseStamped > swarm_pose
The positions of the other swarm members.
Definition: area_division.h:45
int main(int argc, char **argv)
A ROS node that divides the available area among a swarm of CPSs.
Publisher pos_pub
Publisher to stop the CPS.
Definition: area_division.h:25
void swarm_callback(const cpswarm_msgs::AreaDivisionEvent::ConstPtr &msg)
Callback function to receive area division requests from other CPSs.
nav_msgs::OccupancyGrid get_grid(nav_msgs::OccupancyGrid map, string cps)
Get the region assigned to a CPS.
bool map_valid
Whether a valid grid map has been received.
Definition: area_division.h:70
bool reconfigure
Whether the swarm configuration has changed and the area needs to be divided again.
Definition: area_division.h:90
Rate * rate
ROS rate object for controlling loop rates.
Definition: area_division.h:40
bool get_area(nav_msgs::GetMap::Request &req, nav_msgs::GetMap::Response &res)
Callback function to get the area assignment of this CPS.
void map_callback(const nav_msgs::OccupancyGrid::ConstPtr &msg)
Callback function to receive the grid map.


area_division
Author(s): Micha Sende
autogenerated on Thu Oct 31 2019 09:22:46