explore_client.cpp
Go to the documentation of this file.
1 #include <ros/ros.h>
5 
6 #include <geometry_msgs/PolygonStamped.h>
7 #include <geometry_msgs/PointStamped.h>
8 
10 
11 #include <frontier_exploration/ExploreTaskAction.h>
12 #include <frontier_exploration/ExploreTaskActionGoal.h>
13 #include <frontier_exploration/GetNextFrontier.h>
14 #include <frontier_exploration/UpdateBoundaryPolygon.h>
15 #include <costmap_2d/footprint.h>
16 #include <tf/transform_listener.h>
17 
18 #include <ros/wall_timer.h>
19 
20 #include <move_base_msgs/MoveBaseAction.h>
21 
22 #include <visualization_msgs/Marker.h>
23 #include <boost/foreach.hpp>
24 
25 
26 namespace frontier_exploration{
27 
32 
33 private:
34 
37 
41  geometry_msgs::PolygonStamped input_;
42 
44 
48  void vizPubCb(){
49 
50  visualization_msgs::Marker points, line_strip;
51 
52  points.header = line_strip.header = input_.header;
53  points.ns = line_strip.ns = "explore_points";
54 
55  points.id = 0;
56  line_strip.id = 1;
57 
58  points.type = visualization_msgs::Marker::SPHERE_LIST;
59  line_strip.type = visualization_msgs::Marker::LINE_STRIP;
60 
61  if(!input_.polygon.points.empty()){
62 
63  points.action = line_strip.action = visualization_msgs::Marker::ADD;
64  points.pose.orientation.w = line_strip.pose.orientation.w = 1.0;
65 
66  points.scale.x = points.scale.y = 0.1;
67  line_strip.scale.x = 0.05;
68 
69  BOOST_FOREACH(geometry_msgs::Point32 point, input_.polygon.points){
70  line_strip.points.push_back(costmap_2d::toPoint(point));
71  points.points.push_back(costmap_2d::toPoint(point));
72  }
73 
74  if(waiting_for_center_){
75  line_strip.points.push_back(costmap_2d::toPoint(input_.polygon.points.front()));
76  points.color.a = points.color.r = line_strip.color.r = line_strip.color.a = 1.0;
77  }else{
78  points.color.a = points.color.b = line_strip.color.b = line_strip.color.a = 1.0;
79  }
80  }else{
81  points.action = line_strip.action = visualization_msgs::Marker::DELETE;
82  }
83  point_viz_pub_.publish(points);
84  point_viz_pub_.publish(line_strip);
85 
86  }
87 
92  void pointCb(const geometry_msgs::PointStampedConstPtr& point){
93 
94  double average_distance = polygonPerimeter(input_.polygon) / input_.polygon.points.size();
95 
96  if(waiting_for_center_){
97  //flag is set so this is the last point of boundary polygon, i.e. center
98 
99  if(!pointInPolygon(point->point,input_.polygon)){
100  ROS_ERROR("Center not inside polygon, restarting");
101  }else{
103  exploreClient.waitForServer();
104  ROS_INFO("Sending goal");
105  frontier_exploration::ExploreTaskGoal goal;
106  goal.explore_center = *point;
107  goal.explore_boundary = input_;
108  exploreClient.sendGoal(goal);
109  }
110  waiting_for_center_ = false;
111  input_.polygon.points.clear();
112 
113  }else if(input_.polygon.points.empty()){
114  //first control point, so initialize header of boundary polygon
115 
116  input_.header = point->header;
117  input_.polygon.points.push_back(costmap_2d::toPoint32(point->point));
118 
119  }else if(input_.header.frame_id != point->header.frame_id){
120  ROS_ERROR("Frame mismatch, restarting polygon selection");
121  input_.polygon.points.clear();
122 
123  }else if(input_.polygon.points.size() > 1 && pointsNearby(input_.polygon.points.front(), point->point,
124  average_distance*0.1)){
125  //check if last boundary point, i.e. nearby to first point
126 
127  if(input_.polygon.points.size() < 3){
128  ROS_ERROR("Not a valid polygon, restarting");
129  input_.polygon.points.clear();
130  }else{
131  waiting_for_center_ = true;
132  ROS_WARN("Please select an initial point for exploration inside the polygon");
133  }
134 
135  }else{
136 
137  //otherwise, must be a regular point inside boundary polygon
138  input_.polygon.points.push_back(costmap_2d::toPoint32(point->point));
139  input_.header.stamp = ros::Time::now();
140  }
141 
142  }
143 
144 public:
145 
150  nh_(),
151  private_nh_("~"),
152  waiting_for_center_(false)
153  {
154  input_.header.frame_id = "map";
155  point_ = nh_.subscribe("/clicked_point",10,&FrontierExplorationClient::pointCb, this);
156  point_viz_pub_ = nh_.advertise<visualization_msgs::Marker>("exploration_polygon_marker", 10);
157  point_viz_timer_ = nh_.createWallTimer(ros::WallDuration(0.1), boost::bind(&FrontierExplorationClient::vizPubCb, this));
158  ROS_INFO("Please use the 'Point' tool in Rviz to select an exporation boundary.");
159  }
160 
161 };
162 
163 }
164 
165 int main(int argc, char** argv)
166 {
167  ros::init(argc, argv, "explore_client");
168 
170  ros::spin();
171  return 0;
172 }
bool waitForServer(const ros::Duration &timeout=ros::Duration(0, 0)) const
void publish(const boost::shared_ptr< M > &message) const
geometry_msgs::Point32 toPoint32(geometry_msgs::Point pt)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
bool pointsNearby(const T &one, const S &two, const double &proximity)
Evaluate whether two points are approximately adjacent, within a specified proximity distance...
int main(int argc, char **argv)
#define ROS_WARN(...)
FrontierExplorationClient()
Constructor for the client.
void vizPubCb()
Publish markers for visualization of points for boundary polygon.
ROSCPP_DECL void spin(Spinner &spinner)
double polygonPerimeter(const geometry_msgs::Polygon &polygon)
Calculate polygon perimeter.
#define ROS_INFO(...)
WallTimer createWallTimer(WallDuration period, void(T::*callback)(const WallTimerEvent &), T *obj, bool oneshot=false, bool autostart=true) const
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
void sendGoal(const Goal &goal, SimpleDoneCallback done_cb=SimpleDoneCallback(), SimpleActiveCallback active_cb=SimpleActiveCallback(), SimpleFeedbackCallback feedback_cb=SimpleFeedbackCallback())
void pointCb(const geometry_msgs::PointStampedConstPtr &point)
Build boundary polygon from points received through rviz gui.
geometry_msgs::Point toPoint(geometry_msgs::Point32 pt)
static Time now()
bool pointInPolygon(const T &point, const geometry_msgs::Polygon &polygon)
Evaluate if point is inside area defined by polygon. Undefined behaviour for points on line...
Client for FrontierExplorationServer that receives control points from rviz, and creates boundary pol...
#define ROS_ERROR(...)


frontier_exploration
Author(s): Paul Bovbel
autogenerated on Mon Jun 10 2019 13:25:00