00001 /********************************************************************* 00002 * 00003 * Software License Agreement (BSD License) 00004 * 00005 * Copyright (c) 2010, ISR University of Coimbra. 00006 * All rights reserved. 00007 * 00008 * Redistribution and use in source and binary forms, with or without 00009 * modification, are permitted provided that the following conditions 00010 * are met: 00011 * 00012 * * Redistributions of source code must retain the above copyright 00013 * notice, this list of conditions and the following disclaimer. 00014 * * Redistributions in binary form must reproduce the above 00015 * copyright notice, this list of conditions and the following 00016 * disclaimer in the documentation and/or other materials provided 00017 * with the distribution. 00018 * * Neither the name of the ISR University of Coimbra nor the names of its 00019 * contributors may be used to endorse or promote products derived 00020 * from this software without specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00023 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00024 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00025 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00026 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00027 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00028 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00029 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00030 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00031 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00032 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00033 * POSSIBILITY OF SUCH DAMAGE. 00034 * 00035 * Author: Gonçalo Cabrita on 5/1/2011 00036 *********************************************************************/ 00037 #include <ros/ros.h> 00038 //#include <pcl_ros/subscriber.h> 00039 #include <angles/angles.h> 00040 00041 #include <pcl_ros/point_cloud.h> 00042 #include <pcl/common/common_headers.h> 00043 00044 #include <nav_msgs/GridCells.h> 00045 #include <nav_msgs/OccupancyGrid.h> 00046 #include <nav_msgs/MapMetaData.h> 00047 #include <nav_msgs/Odometry.h> 00048 #include <nav_msgs/Path.h> 00049 #include <geometry_msgs/PoseStamped.h> 00050 #include <sensor_msgs/PointCloud2.h> 00051 #include <std_msgs/String.h> 00052 00053 #include <tf/transform_listener.h> 00054 #include <tf/message_filter.h> 00055 #include <message_filters/subscriber.h> 00056 00057 #include <visualization_msgs/Marker.h> 00058 #include <visualization_msgs/MarkerArray.h> 00059 00060 #include <vector> 00061 #include <list> 00062 00063 #include <pp_explorer/GridCellsIdentified.h> 00064 #include <pp_explorer/StringIdentified.h> 00065 #include <pp_explorer/PoseStampedIdentified.h> 00066 00067 namespace particle_plume 00068 { 00074 class PPExplorer 00075 { 00076 public: 00078 PPExplorer(); 00080 ~PPExplorer(); 00081 00083 00090 bool findYumiestSlice(geometry_msgs::PoseStamped * goal); 00091 00093 00101 bool nextYumiestSlice(geometry_msgs::PoseStamped * goal); 00102 00104 00112 bool findClearing(geometry_msgs::PoseStamped * goal); 00113 00115 00120 double getExploredArea(); 00121 00123 bool isReady(); 00124 00125 private: 00126 00128 ros::NodeHandle n_; 00130 ros::NodeHandle pn_; 00132 message_filters::Subscriber<nav_msgs::Odometry> odom_sub_; 00133 tf::TransformListener tf_; 00134 tf::MessageFilter<nav_msgs::Odometry> * tf_filter_; 00136 ros::Subscriber map_sub_; 00138 ros::Subscriber map_meta_sub_; 00140 ros::Subscriber cells_sub_; 00142 ros::Subscriber plume_sub_; 00143 //pcl_ros::Subscriber<pcl::PointXYZI> plume_sub_; 00145 ros::Subscriber obstacles_sub_; 00147 ros::Subscriber inflated_sub_; 00148 00149 // ******* Multi-robot stuff ******* 00151 bool multi_robot_; 00153 std::string unique_id_; 00155 ros::Subscriber recovery_sub_; 00157 ros::Publisher recovery_pub_; 00159 ros::Subscriber chatter_sub_; 00161 ros::Publisher chatter_pub_; 00163 ros::Subscriber poses_sub_; 00165 ros::Publisher poses_pub_; 00166 00168 std::vector<pp_explorer::GridCellsIdentified> recovery_cells_; 00169 00171 std::vector<pp_explorer::PoseStampedIdentified> other_robots_poses_; 00172 00174 bool finish_on_next_recovery_; 00175 // ********************************* 00176 00177 // ******* Debug stuff ******* 00179 ros::Publisher debug_pub_; 00181 ros::Publisher debug_goal_pub_; 00182 00183 bool debug_slices_; 00184 // *************************** 00185 00187 pcl::PointCloud<pcl::PointXYZI> plume_; 00188 00190 nav_msgs::GridCells cells_; 00191 00193 nav_msgs::OccupancyGrid map_; 00195 nav_msgs::MapMetaData map_metadata_; 00196 00198 nav_msgs::GridCells obstacles_; 00200 nav_msgs::GridCells inflated_; 00201 00203 geometry_msgs::PoseStamped robot_pose_; 00204 00206 std::string global_frame_id_; 00207 00209 00212 double pie_radius_; 00214 00217 int pie_slices_; 00219 00222 double max_visited_cells_coef_; 00224 00229 double max_odor_visited_cells_coef_; 00231 00234 int find_clearing_sim_steps_; 00236 00239 double inflation_radius_; 00240 00242 00245 double visited_cells_weight_; 00247 00250 double current_heading_weight_; 00252 00255 double odor_weight_; 00257 00260 double other_robots_weight_; 00261 00263 00266 double bubble_radius_; 00268 00271 int min_particle_count_difference_; 00272 00274 struct SliceOfPie 00275 { 00276 geometry_msgs::Pose goal; 00277 double yuminess; 00278 }; 00279 00281 std::list<SliceOfPie> best_slices_; 00282 00284 class CompareSlices 00285 { 00286 public: 00287 bool operator()(const SliceOfPie & first, const SliceOfPie & second) 00288 { 00289 if(first.yuminess < second.yuminess) return true; 00290 else return false; 00291 } 00292 }; 00293 00295 00300 void ppCallback(const sensor_msgs::PointCloud2::ConstPtr& msg); 00301 00303 00308 void cellsCallback(const nav_msgs::GridCells::ConstPtr& msg); 00309 00311 00316 void mapCallback(const nav_msgs::OccupancyGrid::ConstPtr& msg); 00317 00319 00324 void mapMetaCallback(const nav_msgs::MapMetaData::ConstPtr& msg); 00325 00327 00332 void odomCallback(const nav_msgs::Odometry::ConstPtr& msg); 00333 00335 00340 void obstaclesCallback(const nav_msgs::GridCells::ConstPtr& msg); 00341 00343 00348 void inflatedCallback(const nav_msgs::GridCells::ConstPtr& msg); 00349 00351 00356 void recoveryCellsCallback(const pp_explorer::GridCellsIdentified::ConstPtr& msg); 00357 00359 00364 void chatterCallback(const pp_explorer::StringIdentified::ConstPtr& msg); 00365 00367 00372 void posesCallback(const pp_explorer::PoseStampedIdentified::ConstPtr& msg); 00373 00374 00376 00381 void setGoal(geometry_msgs::PoseStamped * goal); 00382 00384 00392 bool testCell(geometry_msgs::Point * cell, std::vector<geometry_msgs::Point> * cells); 00393 00395 00403 bool yumiestSlice(geometry_msgs::PoseStamped * goal, geometry_msgs::PoseStamped * robot_pose); 00404 00406 00415 bool isInsidePieRadius(double x, double y, geometry_msgs::PoseStamped * robot); 00416 00418 00426 bool isInsideTheMap(int x, int y); 00427 00429 00437 bool isViableGlobalMapCell(int x, int y); 00438 00440 00448 bool isViableLocalMapGoal(double x, double y); 00449 00451 00454 void explorationComplete(); 00455 00456 bool got_map_; 00457 bool got_odom_; 00458 }; 00459 } 00460 00461 // EOF 00462