00001
00002 #include "exploration.h"
00003 #include "navigation_utils.h"
00004 #include "gpregressor.h"
00005 #include "covMaterniso3.h"
00006
00007
00008 #include <iostream>
00009 #include <fstream>
00010
00011
00012
00013
00014
00015 #include <visualization_msgs/Marker.h>
00016 #include <visualization_msgs/MarkerArray.h>
00017
00018
00019
00020
00021 using namespace std;
00022
00023
00024 int main(int argc, char **argv) {
00025 ros::init(argc, argv, "turtlebot_exploration_3d");
00026 ros::NodeHandle nh;
00027
00028
00029 time_t rawtime;
00030 struct tm * timeinfo;
00031 char buffer[80];
00032 time (&rawtime);
00033 timeinfo = localtime(&rawtime);
00034
00035
00036
00037
00038 strftime(buffer,80,"Octomap3D_%m%d_%R_%S.ot",timeinfo);
00039 octomap_name_3d = buffer;
00040
00041
00042 ros::Subscriber kinect_sub = nh.subscribe<sensor_msgs::PointCloud2>("/camera/depth_registered/points", 1, kinectCallbacks);
00043 ros::Publisher GoalMarker_pub = nh.advertise<visualization_msgs::Marker>( "Goal_Marker", 1 );
00044 ros::Publisher Candidates_pub = nh.advertise<visualization_msgs::MarkerArray>("Candidate_MIs", 1);
00045 ros::Publisher Frontier_points_pub = nh.advertise<visualization_msgs::Marker>("Frontier_points", 1);
00046 ros::Publisher pub_twist = nh.advertise<geometry_msgs::Twist>("/cmd_vel_mux/input/teleop", 1);
00047 ros::Publisher Octomap_pub = nh.advertise<octomap_msgs::Octomap>("octomap_3d",1);
00048
00049
00050 tf_listener = new tf::TransformListener();
00051 tf::StampedTransform transform;
00052 tf::Quaternion Goal_heading;
00053
00054 visualization_msgs::MarkerArray CandidatesMarker_array;
00055 visualization_msgs::Marker Frontier_points_cubelist;
00056 geometry_msgs::Twist twist_cmd;
00057
00058 ros::Time now_marker = ros::Time::now();
00059
00060
00061 int max_idx = 0;
00062
00063 point3d Sensor_PrincipalAxis(1, 0, 0);
00064 octomap::OcTreeNode *n;
00065 octomap::OcTree new_tree(octo_reso);
00066 octomap::OcTree new_tree_2d(octo_reso);
00067 cur_tree = &new_tree;
00068 cur_tree_2d = &new_tree_2d;
00069 point3d next_vp;
00070
00071 bool got_tf = false;
00072 bool arrived;
00073
00074
00075 for(int i =0; i < 6; i++){
00076
00077 got_tf = false;
00078 while(!got_tf){
00079 try{
00080 tf_listener->lookupTransform("/map", "/camera_rgb_frame", ros::Time(0), transform);
00081 kinect_orig = point3d(transform.getOrigin().x(), transform.getOrigin().y(), transform.getOrigin().z());
00082 got_tf = true;
00083 }
00084 catch (tf::TransformException ex) {
00085 ROS_WARN("Wait for tf: Kinect frame");
00086 }
00087 ros::Duration(0.05).sleep();
00088 }
00089
00090
00091 ros::spinOnce();
00092
00093
00094 twist_cmd.linear.x = twist_cmd.linear.y = twist_cmd.angular.z = 0;
00095 ros::Time start_turn = ros::Time::now();
00096
00097 ROS_WARN("Rotate 60 degrees");
00098 while (ros::Time::now() - start_turn < ros::Duration(2.6)){
00099 twist_cmd.angular.z = 0.6;
00100
00101 pub_twist.publish(twist_cmd);
00102 ros::Duration(0.05).sleep();
00103 }
00104
00105 twist_cmd.angular.z = 0;
00106 pub_twist.publish(twist_cmd);
00107
00108 }
00109
00110
00111 int robot_step_counter = 0;
00112
00113 while (ros::ok())
00114 {
00115 vector<vector<point3d>> frontier_groups=extractFrontierPoints(cur_tree);
00116
00117
00118 unsigned long int o = 0;
00119 for(vector<vector<point3d>>::size_type e = 0; e < frontier_groups.size(); e++) {
00120 o = o+frontier_groups[e].size();
00121 }
00122
00123 Frontier_points_cubelist.points.resize(o);
00124 ROS_INFO("frontier points %ld", o);
00125 now_marker = ros::Time::now();
00126 Frontier_points_cubelist.header.frame_id = "map";
00127 Frontier_points_cubelist.header.stamp = now_marker;
00128 Frontier_points_cubelist.ns = "frontier_points_array";
00129 Frontier_points_cubelist.id = 0;
00130 Frontier_points_cubelist.type = visualization_msgs::Marker::CUBE_LIST;
00131 Frontier_points_cubelist.action = visualization_msgs::Marker::ADD;
00132 Frontier_points_cubelist.scale.x = octo_reso;
00133 Frontier_points_cubelist.scale.y = octo_reso;
00134 Frontier_points_cubelist.scale.z = octo_reso;
00135 Frontier_points_cubelist.color.a = 1.0;
00136 Frontier_points_cubelist.color.r = (double)255/255;
00137 Frontier_points_cubelist.color.g = 0;
00138 Frontier_points_cubelist.color.b = (double)0/255;
00139 Frontier_points_cubelist.lifetime = ros::Duration();
00140
00141 unsigned long int t = 0;
00142 int l = 0;
00143 geometry_msgs::Point q;
00144 for(vector<vector<point3d>>::size_type n = 0; n < frontier_groups.size(); n++) {
00145 for(vector<point3d>::size_type m = 0; m < frontier_groups[n].size(); m++){
00146 q.x = frontier_groups[n][m].x();
00147 q.y = frontier_groups[n][m].y();
00148 q.z = frontier_groups[n][m].z()+octo_reso;
00149 Frontier_points_cubelist.points.push_back(q);
00150
00151 }
00152 t++;
00153 }
00154 ROS_INFO("Publishing %ld frontier_groups", t);
00155
00156 Frontier_points_pub.publish(Frontier_points_cubelist);
00157 Frontier_points_cubelist.points.clear();
00158
00159
00160 vector<pair<point3d, point3d>> candidates = extractCandidateViewPoints(frontier_groups, kinect_orig, num_of_samples);
00161 std::random_shuffle(candidates.begin(),candidates.end());
00162 vector<pair<point3d, point3d>> gp_test_poses = candidates;
00163 ROS_INFO("Candidate View Points: %luGenereated, %d evaluating...", candidates.size(), num_of_samples_eva);
00164 int temp_size = candidates.size()-3;
00165 if (temp_size < 1) {
00166 ROS_ERROR("Very few candidates generated, maybe finishing with exploration...");
00167 nh.shutdown();
00168 return 0;
00169 }
00170
00171
00172 candidates.resize(min(num_of_samples_eva,temp_size));
00173 frontier_groups.clear();
00174
00175
00176 vector<double> MIs(candidates.size());
00177 double before = countFreeVolume(cur_tree);
00178
00179 double begin_mi_eva_secs, end_mi_eva_secs;
00180 begin_mi_eva_secs = ros::Time::now().toSec();
00181
00182 #pragma omp parallel for
00183 for(int i = 0; i < candidates.size(); i++)
00184 {
00185 auto c = candidates[i];
00186
00187 Sensor_PrincipalAxis = point3d(1.0, 0.0, 0.0);
00188 Sensor_PrincipalAxis.rotate_IP(c.second.roll(), c.second.pitch(), c.second.yaw() );
00189 octomap::Pointcloud hits = castSensorRays(cur_tree, c.first, Sensor_PrincipalAxis);
00190
00191
00192 MIs[i] = calc_MI(cur_tree, c.first, hits, before);
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 }
00204
00205
00206
00207 double train_time, test_time;
00208 GPRegressor g(100, 3, 0.01);
00209 for (int bay_itr = 0; bay_itr < num_of_bay; bay_itr++) {
00210
00211
00212 MatrixXf gp_train_x(candidates.size(), 2), gp_train_label(candidates.size(), 1), gp_test_x(gp_test_poses.size(), 2);
00213
00214 for (int i=0; i< candidates.size(); i++){
00215 gp_train_x(i,0) = candidates[i].first.x();
00216 gp_train_x(i,1) = candidates[i].first.y();
00217 gp_train_label(i) = MIs[i];
00218 }
00219
00220 for (int i=0; i< gp_test_poses.size(); i++){
00221 gp_test_x(i,0) = gp_test_poses[i].first.x();
00222 gp_test_x(i,1) = gp_test_poses[i].first.y();
00223 }
00224
00225
00226 MatrixXf gp_mean_MI, gp_var_MI;
00227 train_time = ros::Time::now().toSec();
00228 g.train(gp_train_x, gp_train_label);
00229 train_time = ros::Time::now().toSec() - train_time;
00230
00231 test_time = ros::Time::now().toSec();
00232 g.test(gp_test_x, gp_mean_MI, gp_var_MI);
00233 test_time = ros::Time::now().toSec() - test_time;
00234 ROS_INFO("GP: Train(%zd) took %f secs , Test(%zd) took %f secs", candidates.size(), train_time, gp_test_poses.size(), test_time);
00235
00236
00237 double beta = 2.4;
00238 vector<double> bay_acq_fun(gp_test_poses.size());
00239 for (int i = 0; i < gp_test_poses.size(); i++) {
00240 bay_acq_fun[i] = gp_mean_MI(i) + beta*gp_var_MI(i);
00241 }
00242 vector<int> idx_acq = sort_MIs(bay_acq_fun);
00243
00244
00245 auto c = gp_test_poses[idx_acq[0]];
00246 Sensor_PrincipalAxis = point3d(1.0, 0.0, 0.0);
00247 Sensor_PrincipalAxis.rotate_IP(c.second.roll(), c.second.pitch(), c.second.yaw() );
00248 octomap::Pointcloud hits = castSensorRays(cur_tree, c.first, Sensor_PrincipalAxis);
00249 candidates.push_back(c);
00250 MIs.push_back(calc_MI(cur_tree, c.first, hits, before));
00251 }
00252
00253 end_mi_eva_secs = ros::Time::now().toSec();
00254 ROS_INFO("Mutual Infomation Eva took: %3.3f Secs.", end_mi_eva_secs - begin_mi_eva_secs);
00255
00256
00257 for(int i = 0; i < candidates.size(); i++) {
00258 auto c = candidates[i];
00259 MIs[i] = MIs[i] /
00260 sqrt(pow(c.first.x()-kinect_orig.x(),2) + pow(c.first.y()-kinect_orig.y(),2));
00261 }
00262
00263
00264 vector<int> idx_MI = sort_MIs(MIs);
00265
00266
00267 tf::Quaternion MI_heading;
00268 MI_heading.setRPY(0.0, -PI/2, 0.0);
00269 MI_heading.normalize();
00270
00271 CandidatesMarker_array.markers.resize(candidates.size());
00272 for (int i = 0; i < candidates.size(); i++)
00273 {
00274 CandidatesMarker_array.markers[i].header.frame_id = "map";
00275 CandidatesMarker_array.markers[i].header.stamp = ros::Time::now();
00276 CandidatesMarker_array.markers[i].ns = "candidates";
00277 CandidatesMarker_array.markers[i].id = i;
00278 CandidatesMarker_array.markers[i].type = visualization_msgs::Marker::ARROW;
00279 CandidatesMarker_array.markers[i].action = visualization_msgs::Marker::ADD;
00280 CandidatesMarker_array.markers[i].pose.position.x = candidates[i].first.x();
00281 CandidatesMarker_array.markers[i].pose.position.y = candidates[i].first.y();
00282 CandidatesMarker_array.markers[i].pose.position.z = candidates[i].first.z();
00283 CandidatesMarker_array.markers[i].pose.orientation.x = MI_heading.x();
00284 CandidatesMarker_array.markers[i].pose.orientation.y = MI_heading.y();
00285 CandidatesMarker_array.markers[i].pose.orientation.z = MI_heading.z();
00286 CandidatesMarker_array.markers[i].pose.orientation.w = MI_heading.w();
00287 CandidatesMarker_array.markers[i].scale.x = (double)2.0*MIs[i]/MIs[idx_MI[0]];
00288 CandidatesMarker_array.markers[i].scale.y = 0.2;
00289 CandidatesMarker_array.markers[i].scale.z = 0.2;
00290 CandidatesMarker_array.markers[i].color.a = (double)MIs[i]/MIs[idx_MI[0]];
00291 CandidatesMarker_array.markers[i].color.r = 0.0;
00292 CandidatesMarker_array.markers[i].color.g = 1.0;
00293 CandidatesMarker_array.markers[i].color.b = 0.0;
00294 }
00295 Candidates_pub.publish(CandidatesMarker_array);
00296 CandidatesMarker_array.markers.clear();
00297 candidates.clear();
00298
00299
00300
00301 arrived = false;
00302 int idx_ptr = 0;
00303
00304 while (!arrived) {
00305
00306 next_vp = point3d(candidates[idx_MI[idx_ptr]].first.x(),candidates[idx_MI[idx_ptr]].first.y(),candidates[idx_MI[idx_ptr]].first.z());
00307 Goal_heading.setRPY(0.0, 0.0, candidates[idx_MI[idx_ptr]].second.yaw());
00308 Goal_heading.normalize();
00309 ROS_INFO("Max MI : %f , @ location: %3.2f %3.2f %3.2f", MIs[idx_MI[idx_ptr]], next_vp.x(), next_vp.y(), next_vp.z() );
00310
00311
00312 visualization_msgs::Marker marker;
00313 marker.header.frame_id = "map";
00314 marker.header.stamp = ros::Time();
00315 marker.ns = "goal_marker";
00316 marker.id = 0;
00317 marker.type = visualization_msgs::Marker::ARROW;
00318 marker.action = visualization_msgs::Marker::ADD;
00319 marker.pose.position.x = next_vp.x();
00320 marker.pose.position.y = next_vp.y();
00321 marker.pose.position.z = 1.0;
00322 marker.pose.orientation.x = Goal_heading.x();
00323 marker.pose.orientation.y = Goal_heading.y();
00324 marker.pose.orientation.z = Goal_heading.z();
00325 marker.pose.orientation.w = Goal_heading.w();
00326 marker.scale.x = 0.5;
00327 marker.scale.y = 0.1;
00328 marker.scale.z = 0.1;
00329 marker.color.a = 1.0;
00330 marker.color.r = 1.0;
00331 marker.color.g = 1.0;
00332 marker.color.b = 0.0;
00333 GoalMarker_pub.publish( marker );
00334
00335
00336 arrived = goToDest(next_vp, Goal_heading);
00337
00338 if(arrived)
00339 {
00340
00341 got_tf = false;
00342 while(!got_tf){
00343 try{
00344 tf_listener->lookupTransform("/map", "/camera_rgb_frame", ros::Time(0), transform);
00345 kinect_orig = point3d(transform.getOrigin().x(), transform.getOrigin().y(), transform.getOrigin().z());
00346 got_tf = true;
00347 }
00348 catch (tf::TransformException ex) {
00349 ROS_WARN("Wait for tf: Kinect frame");
00350 }
00351 ros::Duration(0.05).sleep();
00352 }
00353
00354 ros::spinOnce();
00355 ROS_INFO("Succeed, new Map Free Volume: %f", countFreeVolume(cur_tree));
00356 robot_step_counter++;
00357
00358
00359 octomap_msgs::binaryMapToMsg(*cur_tree, msg_octomap);
00360 msg_octomap.binary = 1;
00361 msg_octomap.id = 1;
00362 msg_octomap.resolution = octo_reso;
00363 msg_octomap.header.frame_id = "/map";
00364 msg_octomap.header.stamp = ros::Time::now();
00365 Octomap_pub.publish(msg_octomap);
00366 ROS_INFO("Octomap updated in RVIZ");
00367
00368
00369
00370
00371
00372
00373 }
00374 else
00375 {
00376 ROS_WARN("Failed to drive to the %d th goal, switch to the sub-optimal..", idx_ptr);
00377 idx_ptr++;
00378 if(idx_ptr > MIs.size()) {
00379 ROS_ERROR("None of the goal is valid for path planning, shuting down the node");
00380 nh.shutdown();
00381 }
00382 }
00383
00384 }
00385
00386
00387
00388 }
00389 nh.shutdown();
00390 return 0;
00391 }