10 nav_msgs::GetMap division;
12 ROS_ERROR(
"Failed to get the assigned map, cannot compute coverage path!");
16 ROS_INFO(
"Generate new coverage path...");
19 ROS_DEBUG(
"Construct minimum-spanning-tree...");
24 ROS_DEBUG(
"Generate coverage path...");
44 bool get_path (nav_msgs::GetPlan::Request &req, nav_msgs::GetPlan::Response &res)
64 bool get_waypoint (cpswarm_msgs::GetWaypoint::Request &req, cpswarm_msgs::GetWaypoint::Response &res)
78 geometry_msgs::PointStamped wp;
79 wp.header.stamp = Time::now();
80 wp.header.frame_id =
"local_origin_ned";
98 if (msg->header.stamp.isValid())
112 if (msg->header.stamp.isValid())
123 for (
auto cps : msg->states) {
125 if (cps.state !=
state)
129 auto idx =
swarm.find(cps.swarmio.node);
132 if (idx ==
swarm.end()) {
133 swarm.emplace(cps.swarmio.node, Time::now());
137 ROS_DEBUG(
"New CPS %s", cps.swarmio.node.c_str());
142 idx->second = Time::now();
147 for (
auto cps=
swarm.cbegin(); cps!=
swarm.cend();) {
149 ROS_DEBUG(
"Remove CPS %s", cps->first.c_str());
169 int main (
int argc,
char **argv)
172 init(argc, argv,
"coverage_path");
180 nh.param(this_node::getName() +
"/loop_rate", loop_rate, 1.5);
182 nh.param(this_node::getName() +
"/queue_size", queue_size, 1);
183 nh.param(this_node::getName() +
"/swarm_timeout",
swarm_timeout, 5.0);
184 nh.param(this_node::getName() +
"/visualize",
visualize,
false);
192 Subscriber pose_subscriber = nh.subscribe(
"pos_provider/pose", queue_size,
pose_callback);
193 Subscriber state_subscriber = nh.subscribe(
"state", queue_size,
state_callback);
194 Subscriber swarm_subscriber = nh.subscribe(
"swarm_state", queue_size,
swarm_callback);
196 path_publisher = nh.advertise<nav_msgs::Path>(
"coverage_path/path", queue_size,
true);
197 wp_publisher = nh.advertise<geometry_msgs::PointStamped>(
"coverage_path/waypoint", queue_size,
true);
199 map_getter = nh.serviceClient<nav_msgs::GetMap>(
"area/assigned");
200 map_getter.waitForExistence();
203 Rate rate(loop_rate);
207 ROS_DEBUG_ONCE(
"Waiting for valid position information...");
214 ROS_DEBUG_ONCE(
"Waiting for valid state information...");
221 ROS_DEBUG_ONCE(
"Waiting for valid swarm information...");
227 ServiceServer path_service = nh.advertiseService(
"coverage_path/path",
get_path);
228 ServiceServer wp_service = nh.advertiseService(
"coverage_path/waypoint",
get_waypoint);
bool get_path(nav_msgs::GetPlan::Request &req, nav_msgs::GetPlan::Response &res)
Callback function to get the coverage path.
ServiceClient map_getter
Service client to get the assigned area.
bool get_waypoint(cpswarm_msgs::GetWaypoint::Request &req, cpswarm_msgs::GetWaypoint::Response &res)
Callback function to get the current waypoint of the path.
void construct()
Generate the MST using Kruskal's algorithm.
Publisher path_publisher
Publisher to visualize the coverage path.
void swarm_callback(const cpswarm_msgs::ArrayOfStates::ConstPtr &msg)
Callback function to receive the states of the other CPSs.
vector< edge > get_mst_edges()
Get the edges of the MST.
void generate_path(geometry_msgs::Point)
Generate all way points for the path.
geometry_msgs::Point get_waypoint(geometry_msgs::Point position, double tolerance)
Get the current waypoint and possibly select next waypoint, if close enough.
bool swarm_valid
Whether valid swarm information has been received.
double swarm_timeout
Time in seconds after which it is assumed that a swarm member has left the swarm if no position updat...
Publisher wp_publisher
Publisher to visualize the current waypoint.
void pose_callback(const geometry_msgs::PoseStamped::ConstPtr &msg)
Callback function for position updates.
geometry_msgs::Pose pose
Current position of the CPS.
void initialize_graph(nav_msgs::OccupancyGrid gridmap, bool connect4=true)
Initialize the internal graph structure that represents the area division.
bool visualize
Whether to publish the coverage path on a topic for visualization.
spanning_tree tree
The minimum-spanning-tree (MST) that defines the coverage path.
mst_path path
The coverage path.
string state
Current state of the CPS.
bool reconfigure
Whether the swarm configuration has changed which requires a replanning of the path.
bool generate_path()
Generate an optimal coverage path for a given area.
map< string, Time > swarm
The UUIDs of the other swarm members.
bool state_valid
Whether a valid state has been received.
void initialize_graph(nav_msgs::OccupancyGrid gridmap, bool connect4=true)
Initialize the internal tree structure from a given grid map.
bool valid()
Check whether the current waypoint index is valid.
bool pose_valid
Whether a valid position has been received.
void initialize_tree(vector< edge > mst)
Remove edges of the graph that overlap with the tree.
void state_callback(const cpswarm_msgs::StateEvent::ConstPtr &msg)
Callback function for state updates.
int main(int argc, char **argv)
A ROS node that computes the optimal paths for area coverage with a swarm of CPSs.
nav_msgs::Path get_path()
Get the complete path.