4 #include <geometry_msgs/PolygonStamped.h> 7 #include <sensor_msgs/PointCloud2.h> 9 #include <pcl/point_cloud.h> 10 #include <pcl/point_types.h> 11 #include <boost/foreach.hpp> 13 #include <frontier_exploration/Frontier.h> 14 #include <frontier_exploration/UpdateBoundaryPolygon.h> 15 #include <frontier_exploration/GetNextFrontier.h> 28 BoundedExploreLayer::BoundedExploreLayer(){}
30 BoundedExploreLayer::~BoundedExploreLayer(){
31 polygonService_.shutdown();
32 frontierService_.shutdown();
37 void BoundedExploreLayer::onInitialize(){
40 frontier_cloud_pub = nh_.
advertise<sensor_msgs::PointCloud2>(
"frontiers",5);
44 bool explore_clear_space;
45 nh_.
param(
"explore_clear_space", explore_clear_space,
true);
46 if(explore_clear_space){
47 default_value_ = NO_INFORMATION;
49 default_value_ = FREE_SPACE;
54 nh_.
param<
bool>(
"resize_to_boundary", resize_to_boundary_,
true);
55 nh_.
param<std::string>(
"frontier_travel_point", frontier_travel_point_,
"closest");
57 polygonService_ = nh_.
advertiseService(
"update_boundary_polygon", &BoundedExploreLayer::updateBoundaryPolygonService,
this);
58 frontierService_ = nh_.
advertiseService(
"get_next_frontier", &BoundedExploreLayer::getNextFrontierService,
this);
60 dsrv_ =
new dynamic_reconfigure::Server<costmap_2d::GenericPluginConfig>(nh_);
61 dynamic_reconfigure::Server<costmap_2d::GenericPluginConfig>::CallbackType cb = boost::bind(
62 &BoundedExploreLayer::reconfigureCB,
this, _1, _2);
63 dsrv_->setCallback(cb);
68 void BoundedExploreLayer::matchSize(){
69 Costmap2D* master = layered_costmap_->getCostmap();
70 resizeMap(master->getSizeInCellsX(), master->getSizeInCellsY(), master->getResolution(),
71 master->getOriginX(), master->getOriginY());
75 void BoundedExploreLayer::reconfigureCB(costmap_2d::GenericPluginConfig &config, uint32_t level){
76 enabled_ = config.enabled;
79 bool BoundedExploreLayer::getNextFrontierService(frontier_exploration::GetNextFrontier::Request &req, frontier_exploration::GetNextFrontier::Response &res){
80 return getNextFrontier(req.start_pose, res.next_frontier);
83 bool BoundedExploreLayer::getNextFrontier(geometry_msgs::PoseStamped start_pose, geometry_msgs::PoseStamped &next_frontier){
92 if(start_pose.header.frame_id != layered_costmap_->getGlobalFrameID()){
94 if(!tf_listener_.waitForTransform(layered_costmap_->getGlobalFrameID(), start_pose.header.frame_id,
ros::Time::now(),
ros::Duration(10))) {
95 ROS_ERROR_STREAM(
"Couldn't transform from "<<layered_costmap_->getGlobalFrameID()<<
" to "<< start_pose.header.frame_id);
98 geometry_msgs::PoseStamped temp_pose = start_pose;
99 tf_listener_.transformPose(layered_costmap_->getGlobalFrameID(),temp_pose,start_pose);
105 std::list<Frontier> frontier_list = frontierSearch.
searchFrom(start_pose.pose.position);
107 if(frontier_list.size() == 0){
108 ROS_DEBUG(
"No frontiers found, exploration complete");
114 selected.min_distance = std::numeric_limits<double>::infinity();
117 pcl::PointCloud<pcl::PointXYZI> frontier_cloud_viz;
118 pcl::PointXYZI frontier_point_viz(50);
121 BOOST_FOREACH(Frontier frontier, frontier_list){
123 frontier_point_viz.x = frontier.initial.x;
124 frontier_point_viz.y = frontier.initial.y;
125 frontier_cloud_viz.push_back(frontier_point_viz);
128 if (frontier.min_distance < selected.min_distance){
130 max = frontier_cloud_viz.size()-1;
135 frontier_cloud_viz[max].intensity = 100;
138 sensor_msgs::PointCloud2 frontier_viz_output;
140 frontier_viz_output.header.frame_id = layered_costmap_->getGlobalFrameID();
142 frontier_cloud_pub.publish(frontier_viz_output);
145 next_frontier.header.frame_id = layered_costmap_->getGlobalFrameID();
149 if(frontier_travel_point_ ==
"closest"){
150 next_frontier.pose.position = selected.initial;
151 }
else if(frontier_travel_point_ ==
"middle"){
152 next_frontier.pose.position = selected.middle;
153 }
else if(frontier_travel_point_ ==
"centroid"){
154 next_frontier.pose.position = selected.centroid;
156 ROS_ERROR(
"Invalid 'frontier_travel_point' parameter, falling back to 'closest'");
157 next_frontier.pose.position = selected.initial;
165 bool BoundedExploreLayer::updateBoundaryPolygonService(frontier_exploration::UpdateBoundaryPolygon::Request &req, frontier_exploration::UpdateBoundaryPolygon::Response &res){
167 return updateBoundaryPolygon(req.explore_boundary);
171 void BoundedExploreLayer::reset(){
176 memset(costmap_, default_value_, size_x_ * size_y_ *
sizeof(
unsigned char));
180 bool BoundedExploreLayer::updateBoundaryPolygon(geometry_msgs::PolygonStamped polygon_stamped){
183 polygon_.points.clear();
186 if(!tf_listener_.waitForTransform(layered_costmap_->getGlobalFrameID(), polygon_stamped.header.frame_id,
ros::Time::now(),
ros::Duration(10))) {
187 ROS_ERROR_STREAM(
"Couldn't transform from "<<layered_costmap_->getGlobalFrameID()<<
" to "<< polygon_stamped.header.frame_id);
192 geometry_msgs::PointStamped in, out;
193 in.header = polygon_stamped.header;
194 BOOST_FOREACH(geometry_msgs::Point32 point32, polygon_stamped.polygon.points){
196 tf_listener_.transformPoint(layered_costmap_->getGlobalFrameID(),in,out);
201 if(polygon_.points.empty()){
202 geometry_msgs::Point32 temp;
203 temp.x = getOriginX();
204 temp.y = getOriginY();
205 polygon_.points.push_back(temp);
206 temp.y = getSizeInMetersY();
207 polygon_.points.push_back(temp);
208 temp.x = getSizeInMetersX();
209 polygon_.points.push_back(temp);
210 temp.y = getOriginY();
211 polygon_.points.push_back(temp);
214 if(resize_to_boundary_){
218 double min_x = std::numeric_limits<double>::infinity();
219 double min_y = std::numeric_limits<double>::infinity();
220 double max_x = -std::numeric_limits<double>::infinity();
221 double max_y = -std::numeric_limits<double>::infinity();
223 BOOST_FOREACH(geometry_msgs::Point32 point, polygon_.points){
224 min_x = std::min(min_x,(
double)point.x);
225 min_y = std::min(min_y,(
double)point.y);
226 max_x = std::max(max_x,(
double)point.x);
227 max_y = std::max(max_y,(
double)point.y);
232 worldToMapNoBounds(max_x - min_x, max_y - min_y, size_x, size_y);
233 layered_costmap_->resizeMap(size_x, size_y, layered_costmap_->getCostmap()->getResolution(), min_x, min_y);
243 void BoundedExploreLayer::updateBounds(
double robot_x,
double robot_y,
double robot_yaw,
double* min_x,
244 double* min_y,
double* max_x,
double* max_y){
247 if (!enabled_ || !configured_){
return; }
250 *min_x = getOriginX();
251 *min_y = getOriginY();
252 *max_x = getSizeInMetersX()+getOriginX();
253 *max_y = getSizeInMetersY()+getOriginY();
257 void BoundedExploreLayer::updateCosts(
costmap_2d::Costmap2D& master_grid,
int min_i,
int min_j,
int max_i,
int max_j){
259 if (!enabled_ || !configured_){
return; }
262 MarkCell marker(costmap_, LETHAL_OBSTACLE);
265 for(
int i = 0, j = polygon_.points.size()-1; i < polygon_.points.size(); j = i++){
267 int x_1, y_1, x_2, y_2;
268 worldToMapEnforceBounds(polygon_.points[i].x, polygon_.points[i].y, x_1,y_1);
269 worldToMapEnforceBounds(polygon_.points[j].x, polygon_.points[j].y, x_2,y_2);
271 raytraceLine(marker,x_1,y_1,x_2,y_2);
274 mapUpdateKeepObstacles(master_grid, min_i, min_j, max_i, max_j);
279 void BoundedExploreLayer::mapUpdateKeepObstacles(
costmap_2d::Costmap2D& master_grid,
int min_i,
int min_j,
int max_i,
int max_j){
283 unsigned char* master = master_grid.
getCharMap();
286 for (
int j = min_j; j < max_j; j++)
288 unsigned int it = span*j+min_i;
289 for (
int i = min_i; i < max_i; i++)
292 if(master[it] != LETHAL_OBSTACLE && (costmap_[it] == LETHAL_OBSTACLE || costmap_[it] > master[it])){
293 master[it] = costmap_[it];
geometry_msgs::Point32 toPoint32(geometry_msgs::Point pt)
PLUGINLIB_EXPORT_CLASS(BAGReader, nodelet::Nodelet)
costmap_2d layer plugin that holds the state for a bounded frontier exploration task. Manages the boundary polygon, superimposes the polygon on the overall exploration costmap, and processes costmap to find next frontier to explore.
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
static const unsigned char FREE_SPACE
unsigned char * getCharMap() const
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
std::list< Frontier > searchFrom(geometry_msgs::Point position)
Runs search implementation, outward from the start position.
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
Thread-safe implementation of a frontier-search task for an input costmap.
unsigned int getSizeInCellsX() const
static geometry_msgs::Quaternion createQuaternionMsgFromYaw(double yaw)
geometry_msgs::Point toPoint(geometry_msgs::Point32 pt)
static const unsigned char LETHAL_OBSTACLE
static const unsigned char NO_INFORMATION
double yawOfVector(const T &origin, const S &end)
Calculate the yaw of vector defined by origin and end points.
void toROSMsg(const sensor_msgs::PointCloud2 &cloud, sensor_msgs::Image &image)
#define ROS_ERROR_STREAM(args)
ROSCPP_DECL void spinOnce()