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
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);
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
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
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;
00118 bool belong_old;
00119 double distance;
00120 double R1 = 0.5;
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;
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
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)
00150 {
00151
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
00187
00188 vector<pair<point3d, point3d>> extractCandidateViewPoints(vector<vector<point3d>> frontier_groups, point3d sensor_orig, int n ) {
00189 double R2_min = 1.0;
00190 double R2_max = 5.0;
00191 double R3 = 0.3;
00192
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;
00217 continue;
00218 }
00219
00220 else{
00221
00222
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;
00228 continue;
00229 }
00230 }
00231
00232
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;
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
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