exploration.h
Go to the documentation of this file.
00001 #ifndef JACKALEXPLORATION_EXPLORATION_H_
00002 #define JACKALEXPLORATION_EXPLORATION_H_
00003 
00004 #include <ros/ros.h>
00005 #include <pcl/point_types.h>
00006 #include <pcl_conversions/pcl_conversions.h>
00007 #include <pcl_ros/point_cloud.h>
00008 #include "pcl_ros/transforms.h"
00009 #include <sensor_msgs/PointCloud2.h>
00010 #include <tf/transform_listener.h>
00011 #include <octomap/octomap.h>
00012 #include <octomap_msgs/Octomap.h>
00013 #include <octomap_msgs/conversions.h>
00014 
00015 #include <geometry_msgs/Pose.h>
00016 #include <algorithm>
00017 
00018 
00019 using namespace std;
00020 
00021 typedef octomap::point3d point3d;
00022 typedef pcl::PointXYZ PointType;
00023 typedef pcl::PointCloud<pcl::PointXYZ> PointCloud;
00024 const double PI = 3.1415926;
00025 const double octo_reso = 0.1;
00026 const int num_of_samples = 12;
00027 const int num_of_samples_eva = 15;
00028 const int num_of_bay = 3;
00029 
00030 
00031 octomap::OcTree* cur_tree;
00032 octomap::OcTree* cur_tree_2d;
00033 octomap_msgs::Octomap msg_octomap;
00034 
00035 tf::TransformListener *tf_listener; 
00036 
00037 point3d kinect_orig;
00038 
00039 ofstream explo_log_file;
00040 std::string octomap_name_2d, octomap_name_3d;
00041 
00042 vector<int> sort_MIs(const vector<double> &v){
00043     vector<int> idx(v.size());
00044     iota(idx.begin(), idx.end(),0);
00045 
00046     sort(idx.begin(), idx.end(), 
00047         [&v](int i1, int i2) {return v[i1] > v[i2];});
00048 
00049     return idx;
00050 }
00051 
00052 
00053 struct sensorModel {
00054     double horizontal_fov;
00055     double vertical_fov;
00056     double angle_inc_hor;
00057     double angle_inc_vel;
00058     double width;
00059     double height;
00060     double max_range;
00061     // vector<pair<double, double>> pitch_yaws;
00062     octomap::Pointcloud SensorRays;
00063     point3d InitialVector;
00064 
00065     sensorModel(double _width, double _height, double _horizontal_fov, double _vertical_fov, double _max_range)
00066             : width(_width), height(_height), horizontal_fov(_horizontal_fov), vertical_fov(_vertical_fov), max_range(_max_range) {
00067         angle_inc_hor = horizontal_fov / width;
00068         angle_inc_vel = vertical_fov / height;
00069         for(double j = -height / 2; j < height / 2; ++j) 
00070             for(double i = -width / 2; i < width / 2; ++i) {
00071                 InitialVector = point3d(1.0, 0.0, 0.0);
00072                 InitialVector.rotate_IP(0.0, j * angle_inc_vel, i * angle_inc_hor);
00073                 SensorRays.push_back(InitialVector);
00074         }
00075     }
00076 }; 
00077 sensorModel Kinect_360(64, 48, 2*PI*57/360, 2*PI*43/360, 6);    // Construct sensor model : Kinect
00078 
00079 
00080 double countFreeVolume(const octomap::OcTree *octree) {
00081     double volume = 0;
00082     for(octomap::OcTree::leaf_iterator n = octree->begin_leafs(octree->getTreeDepth()); n != octree->end_leafs(); ++n) {
00083         if(!octree->isNodeOccupied(*n))
00084             volume += pow(n.getSize(), 3);
00085     }
00086     return volume;
00087 }
00088 
00089 
00090 octomap::Pointcloud castSensorRays(const octomap::OcTree *octree, const point3d &position,
00091                                  const point3d &sensor_orientation) {
00092     octomap::Pointcloud hits;
00093 
00094     octomap::Pointcloud RaysToCast;
00095     RaysToCast.push_back(Kinect_360.SensorRays);
00096     RaysToCast.rotate(sensor_orientation.x(),sensor_orientation.y(),sensor_orientation.z());
00097     point3d end;
00098     // Cast Rays to 3d OctoTree and get hit points
00099     for(int i = 0; i < RaysToCast.size(); i++) {
00100         if(octree->castRay(position, RaysToCast.getPoint(i), end, true, Kinect_360.max_range)) {
00101             hits.push_back(end);
00102         } else {
00103             end = RaysToCast.getPoint(i) * Kinect_360.max_range;
00104             end += position;
00105             hits.push_back(end);
00106         }
00107     }
00108     return hits;
00109 }
00110 
00111 // extract 2d frontier points
00112 vector<vector<point3d>> extractFrontierPoints(const octomap::OcTree *octree) {
00113 
00114     vector<vector<point3d>> frontier_groups;
00115     vector<point3d> frontier_points;
00116     octomap::OcTreeNode *n_cur_frontier;
00117     bool frontier_true;         // whether or not a frontier point
00118     bool belong_old;            //whether or not belong to old group
00119     double distance;
00120     double R1 = 0.5;            //group size
00121     double x_cur, y_cur, z_cur;
00122 
00123 
00124     for(octomap::OcTree::leaf_iterator n = octree->begin_leafs(octree->getTreeDepth()); n != octree->end_leafs(); ++n)
00125     {
00126         frontier_true = false;
00127         unsigned long int num_free = 0; //number of free cube around frontier, for filtering out fake frontier
00128 
00129       if(!octree->isNodeOccupied(*n))
00130         {
00131          x_cur = n.getX();
00132          y_cur = n.getY();
00133          z_cur = n.getZ();
00134 
00135          if(z_cur < 0.4)    continue;
00136          if(z_cur > 0.4 + octo_reso)    continue;
00137          //if there are unknown around the cube, the cube is frontier
00138          for (double x_cur_buf = x_cur - octo_reso; x_cur_buf < x_cur + octo_reso; x_cur_buf += octo_reso)
00139              for (double y_cur_buf = y_cur - octo_reso; y_cur_buf < y_cur + octo_reso; y_cur_buf += octo_reso)
00140             {
00141                 n_cur_frontier = octree->search(point3d(x_cur_buf, y_cur_buf, z_cur));
00142                 if(!n_cur_frontier)
00143                 {
00144                     frontier_true = true;
00145                     continue;            
00146                 }
00147 
00148             }
00149             if(frontier_true)// && num_free >5 )
00150             {
00151                 // divede frontier points into groups
00152                 if(frontier_groups.size() < 1)
00153                 {
00154                     frontier_points.resize(1);
00155                     frontier_points[0] = point3d(x_cur,y_cur,z_cur);
00156                     frontier_groups.push_back(frontier_points);
00157                     frontier_points.clear();
00158                 }
00159                 else
00160                 {
00161                     bool belong_old = false;            
00162 
00163                     for(vector<vector<point3d>>::size_type u = 0; u < frontier_groups.size(); u++){
00164                             distance = sqrt(pow(frontier_groups[u][0].x()-x_cur, 2)+pow(frontier_groups[u][0].y()-y_cur, 2)) ;
00165                             if(distance < R1){
00166                                frontier_groups[u].push_back(point3d(x_cur, y_cur, z_cur));
00167                                belong_old = true;
00168                                break;
00169                             }
00170                     }
00171                     if(!belong_old){
00172                                frontier_points.resize(1);
00173                                frontier_points[0] = point3d(x_cur, y_cur, z_cur);
00174                                frontier_groups.push_back(frontier_points);
00175                                frontier_points.clear();
00176                     }                              
00177                 }
00178 
00179             } 
00180         }
00181         
00182     }
00183     return frontier_groups;
00184 }
00185 
00186 //generate candidates for moving. Input sensor_orig and initial_yaw, Output candidates
00187 //senor_orig: locationg of sensor.   initial_yaw: yaw direction of sensor
00188 vector<pair<point3d, point3d>> extractCandidateViewPoints(vector<vector<point3d>> frontier_groups, point3d sensor_orig, int n ) {
00189     double R2_min = 1.0;        // distance from candidate view point to frontier centers, in meters.
00190     double R2_max = 5.0;
00191     double R3 = 0.3;        // to other frontiers
00192     // int n = 12;
00193     octomap::OcTreeNode *n_cur_3d;
00194     vector<pair<point3d, point3d>> candidates;
00195     double z = sensor_orig.z();
00196     double x, y;
00197     double yaw;
00198     double distance_can;
00199 
00200         for(vector<vector<point3d>>::size_type u = 0; u < frontier_groups.size(); u++) {
00201             for(double yaw = 0; yaw < 2*PI; yaw += PI*2 / n)
00202                 for(double R2 = R2_min; R2<R2_max; R2+=1.0) { 
00203                 x = frontier_groups[u][0].x() - R2 * cos(yaw);
00204                 y = frontier_groups[u][0].y() - R2 * sin(yaw);
00205 
00206                 bool candidate_valid = true;
00207                 n_cur_3d = cur_tree->search(point3d(x, y, z));
00208 
00209 
00210                 if (!n_cur_3d) {
00211                     candidate_valid = false;
00212                     continue;
00213                 }
00214 
00215                 if(sqrt(pow(x - sensor_orig.x(),2) + pow(y - sensor_orig.y(),2)) < 0.25){
00216                   candidate_valid = false;// delete candidates close to sensor_orig
00217                   continue;
00218                 }
00219 
00220                 else{
00221 
00222                     // check candidate to other frontiers;
00223                     for(vector<vector<point3d>>::size_type n = 0; n < frontier_groups.size(); n++)
00224                         for(vector<point3d>::size_type m = 0; m < frontier_groups[n].size(); m++){
00225                             distance_can = sqrt(pow(x - frontier_groups[n][m].x(),2) + pow(y - frontier_groups[n][m].y(),2));
00226                             if(distance_can < R3){
00227                                 candidate_valid = false;        //delete candidates close to frontier
00228                                 continue;
00229                             }
00230                     }
00231                 
00232                     // volumn check
00233                     for (double x_buf = x - 0.3; x_buf < x + 0.3; x_buf += octo_reso) 
00234                         for (double y_buf = y - 0.3; y_buf < y + 0.3; y_buf += octo_reso)
00235                             for (double z_buf = sensor_orig.z()-0.2; z_buf <sensor_orig.z()+0.2; z_buf += octo_reso)
00236                             {
00237                                 n_cur_3d = cur_tree->search(point3d(x_buf, y_buf, z_buf));
00238                                 if(!n_cur_3d)       continue;
00239                                 else if (cur_tree->isNodeOccupied(n_cur_3d)){
00240                                 candidate_valid = false;//delete candidates which have ccupied cubes around in 3D area
00241                                 continue;
00242                                 }  
00243                             }
00244 
00245                 }
00246 
00247                 if (candidate_valid)
00248                 {
00249                     candidates.push_back(make_pair<point3d, point3d>(point3d(x, y, z), point3d(0.0, 0.0, yaw)));
00250                 }
00251             }
00252         }
00253     return candidates;
00254 }
00255 
00256 
00257 double calc_MI(const octomap::OcTree *octree, const point3d &sensor_orig, const octomap::Pointcloud &hits, const double before) {
00258     auto octree_copy = new octomap::OcTree(*octree);
00259 
00260     octree_copy->insertPointCloud(hits, sensor_orig, Kinect_360.max_range, true, true);
00261     double after = countFreeVolume(octree_copy);
00262     delete octree_copy;
00263     return after - before;
00264 }
00265 
00266 
00267 void kinectCallbacks( const sensor_msgs::PointCloud2ConstPtr& cloud2_msg ) {
00268     pcl::PCLPointCloud2 cloud2;
00269     pcl_conversions::toPCL(*cloud2_msg, cloud2);
00270     PointCloud* cloud (new PointCloud);
00271     PointCloud* cloud_local (new PointCloud);
00272     pcl::fromPCLPointCloud2(cloud2,*cloud_local);
00273     octomap::Pointcloud hits;
00274 
00275     ros::Duration(0.07).sleep();
00276     while(!pcl_ros::transformPointCloud("/map", *cloud_local, *cloud, *tf_listener))
00277     {
00278         ros::Duration(0.01).sleep();
00279     }
00280     // Insert points into octomap one by one...
00281     for (int i = 1; i< cloud->width; i++)
00282     {
00283         for (int j = 1; j< cloud->height; j++)
00284         {
00285             if(isnan(cloud->at(i,j).x))     continue;
00286             if(cloud->at(i,j).z < -1.0)     continue;  
00287             hits.push_back(point3d(cloud->at(i,j).x, cloud->at(i,j).y, cloud->at(i,j).z));
00288         }
00289     }
00290 
00291     cur_tree->insertPointCloud(hits, kinect_orig, Kinect_360.max_range);
00292     ROS_INFO("Entropy(3d map) : %f", countFreeVolume(cur_tree));
00293 
00294     cur_tree->write(octomap_name_3d);
00295     delete cloud;
00296     delete cloud_local;
00297 }
00298 
00299 
00300 #endif


turtlebot_exploration_3d
Author(s): Bona , Shawn
autogenerated on Thu Jun 6 2019 20:58:02