00001
00024 #include "ccny_rgbd/apps/navigator.h"
00025 #include "aruco/aruco.h"
00026 namespace ccny_rgbd {
00027
00028 Navigator::Navigator(
00029 const ros::NodeHandle& nh,
00030 const ros::NodeHandle& nh_private):
00031 nh_(nh),
00032 nh_private_(nh_private),
00033 rgbd_frame_index_(0)
00034 {
00035 ROS_INFO("Starting Navigator node");
00036
00037
00038
00039 initParams();
00040
00041
00042
00043 keyframes_pub_ = nh_.advertise<PointCloudT>(
00044 "keyframes", queue_size_);
00045 poses_pub_ = nh_.advertise<visualization_msgs::Marker>(
00046 "keyframe_poses", queue_size_);
00047 kf_assoc_pub_ = nh_.advertise<visualization_msgs::Marker>(
00048 "keyframe_associations", queue_size_);
00049 path_pub_ = nh_.advertise<PathMsg>(
00050 "mapper_path", queue_size_);
00051 aruco_pub_ = nh_.advertise<PathMsg>(
00052 "aRuco_path", queue_size_);
00053
00054
00055
00056 pub_keyframe_service_ = nh_.advertiseService(
00057 "publish_keyframe", &Navigator::publishKeyframeSrvCallback, this);
00058 pub_keyframes_service_ = nh_.advertiseService(
00059 "publish_keyframes", &Navigator::publishKeyframesSrvCallback, this);
00060 save_kf_service_ = nh_.advertiseService(
00061 "save_keyframes", &Navigator::saveKeyframesSrvCallback, this);
00062 load_kf_service_ = nh_.advertiseService(
00063 "load_keyframes", &Navigator::loadKeyframesSrvCallback, this);
00064 save_pcd_map_service_ = nh_.advertiseService(
00065 "save_pcd_map", &Navigator::savePcdMapSrvCallback, this);
00066 save_octomap_service_ = nh_.advertiseService(
00067 "save_octomap", &Navigator::saveOctomapSrvCallback, this);
00068 add_manual_keyframe_service_ = nh_.advertiseService(
00069 "add_manual_keyframe", &Navigator::addManualKeyframeSrvCallback, this);
00070 generate_graph_service_ = nh_.advertiseService(
00071 "generate_graph", &Navigator::generateGraphSrvCallback, this);
00072 solve_graph_service_ = nh_.advertiseService(
00073 "solve_graph", &Navigator::solveGraphSrvCallback, this);
00074
00075
00076
00077 ImageTransport rgb_it(nh_);
00078 ImageTransport depth_it(nh_);
00079
00080 sub_rgb_.subscribe(rgb_it, "/camera/rgb/image_rect_color", queue_size_);
00081 sub_depth_.subscribe(depth_it, "/camera/depth_registered/image_rect_raw", queue_size_);
00082 sub_info_.subscribe(nh_, "/camera/rgb/camera_info", queue_size_);
00083
00084
00085 sync_.reset(new RGBDSynchronizer3(
00086 RGBDSyncPolicy3(queue_size_), sub_rgb_, sub_depth_, sub_info_));
00087
00088 sync_->registerCallback(boost::bind(&Navigator::RGBDCallback, this, _1, _2, _3));
00089 }
00090
00091 Navigator::~Navigator()
00092 {
00093
00094 }
00095 aruco::MarkerDetector MDetector;
00096 rgbdtools::KeyframeGraphSolverISAM solver_;
00097 void Navigator::initParams()
00098 {
00099 bool verbose;
00100
00101 if (!nh_private_.getParam ("verbose", verbose))
00102 verbose = true;
00103 if (!nh_private_.getParam ("queue_size", queue_size_))
00104 queue_size_ = 5;
00105 if (!nh_private_.getParam ("fixed_frame", fixed_frame_))
00106 fixed_frame_ = "/odom";
00107 if (!nh_private_.getParam ("pcd_map_res", pcd_map_res_))
00108 pcd_map_res_ = 0.01;
00109 if (!nh_private_.getParam ("octomap_res", octomap_res_))
00110 octomap_res_ = 0.05;
00111 if (!nh_private_.getParam ("octomap_with_color", octomap_with_color_))
00112 octomap_with_color_ = true;
00113 if (!nh_private_.getParam ("kf_dist_eps", kf_dist_eps_))
00114 kf_dist_eps_ = 0.10;
00115 if (!nh_private_.getParam ("kf_angle_eps", kf_angle_eps_))
00116 kf_angle_eps_ = 10.0 * M_PI / 180.0;
00117 if (!nh_private_.getParam ("max_range", max_range_))
00118 max_range_ = 05.0;
00119 if (!nh_private_.getParam ("max_stdev", max_stdev_))
00120 max_stdev_ = 555;
00121 if (!nh_private_.getParam ("max_map_z", max_map_z_))
00122 max_map_z_ = std::numeric_limits<double>::infinity();
00123
00124
00125 MDetector.setThresholdParams( 10.0,7.0);
00126 MDetector.setCornerRefinementMethod(aruco::MarkerDetector::LINES);
00127
00128 int graph_n_keypoints;
00129 int graph_n_candidates;
00130 int graph_k_nearest_neighbors;
00131 bool graph_matcher_use_desc_ratio_test = true;
00132
00133 if (!nh_private_.getParam ("graph/n_keypoints", graph_n_keypoints))
00134 graph_n_keypoints = 500;
00135 if (!nh_private_.getParam ("graph/n_candidates", graph_n_candidates))
00136 graph_n_candidates = 10;
00137 if (!nh_private_.getParam ("graph/k_nearest_neighbors", graph_k_nearest_neighbors))
00138 graph_k_nearest_neighbors = 4;
00139 int min_inliers = 25;
00140
00141 graph_detector_.setMapping(false);
00142 graph_detector_.setNKeypoints(graph_n_keypoints);
00143 graph_detector_.setNCandidates(graph_n_candidates);
00144 graph_detector_.setKNearestNeighbors(graph_k_nearest_neighbors);
00145 graph_detector_.setMatcherUseDescRatioTest(graph_matcher_use_desc_ratio_test);
00146 graph_detector_.setSacMinInliers(min_inliers);
00147 graph_detector_.setSACReestimateTf(false);
00148 graph_detector_.setSACSaveResults(true);
00149 graph_detector_.setVerbose(verbose);
00150 graph_detector_.setMaxIterations(300);
00151 }
00152
00153 void Navigator::filter_aruco()
00154 {
00155 double max_dist_ = 0.2*0.2;
00156 std::vector<std::vector<double> > positions;
00157 std::vector<std::vector<int> > inds;
00158 for(u_int i = 0; i < aruco_pos.size(); i++)
00159 {
00160 std::vector<double> val;
00161 val.push_back(0);
00162 val.push_back(0);
00163 val.push_back(0);
00164 std::vector<int> sub_inds;
00165 for(u_int j = 0; j < aruco_pos.size() ; j++)
00166 {
00167 double man_dist = std::pow(aruco_pos[i][0]-aruco_pos[j][0],2)+ std::pow(aruco_pos[i][1]-aruco_pos[j][1],2)+ std::pow(aruco_pos[i][2]-aruco_pos[j][2],2);
00168 if (man_dist < max_dist_)
00169 {
00170 sub_inds.push_back(j);
00171 val[0] += aruco_pos[j][0];
00172 val[1] += aruco_pos[j][1];
00173 val[2] += aruco_pos[j][2];
00174 }
00175
00176 }
00177 val[0] /= sub_inds.size();
00178 val[1] /= sub_inds.size();
00179 val[2] /= sub_inds.size();
00180 positions.push_back(val);
00181 inds.push_back(sub_inds);
00182 }
00183 PathMsg ar;
00184 ar.header.frame_id = fixed_frame_;
00185 ar.header.seq = 0;
00186 ar.header.stamp = ros::Time::now();
00187 double min_readings = 2;
00188 std::vector<std::vector<double> > aruc;
00189
00190 for(u_int i = 0; i < positions.size(); i++)
00191 {
00192 std::vector<double> val;
00193 val.push_back(0);
00194 val.push_back(0);
00195 val.push_back(0);
00196 std::vector<int> sub_inds;
00197 for(u_int j = 0; j < positions.size() ; j++)
00198 {
00199 if(inds[j].size() <= min_readings)
00200 {
00201 continue;
00202 }
00203 double dist = std::pow(positions[i][0]-positions[j][0],2)+ std::pow(positions[i][1]-positions[j][1],2)+ std::pow(positions[i][2]-positions[j][2],2);
00204 if (dist < max_dist_)
00205 {
00206 sub_inds.push_back(j);
00207 val[0] += positions[j][0];
00208 val[1] += positions[j][1];
00209 val[2] += positions[j][2];
00210 }
00211
00212 }
00213 if(sub_inds.size() <= min_readings)
00214 {
00215 val[0] = -99999;
00216 aruc.push_back(val);
00217 continue;
00218 }
00219 if(!(val[0]==-99999))
00220 {
00221 val[0] /= sub_inds.size();
00222 val[1] /= sub_inds.size();
00223 val[2] /= sub_inds.size();
00224 }
00225 aruc.push_back(val);
00226 }
00227 aruco_pos.clear();
00228 for(u_int i = 0; i< aruc.size(); i++)
00229 {
00230 geometry_msgs::PoseStamped pose;
00231 if(aruc[i][0] == -99999)
00232 continue;
00233 rgbdtools::RGBDKeyframe keyframe=keyframes_[aruco_kfs[i]];
00234 pose.header.frame_id = fixed_frame_;
00235 pose.header.seq = keyframe.header.seq;
00236 pose.header.stamp.sec = keyframe.header.stamp.sec;
00237 pose.header.stamp.nsec = keyframe.header.stamp.nsec;
00238 pose.pose.position.x = aruc[i][0];
00239 pose.pose.position.y = aruc[i][1];
00240 pose.pose.position.z = aruc[i][2];
00241 pose.pose.orientation.x = 1;
00242 pose.pose.orientation.y = 0;
00243 pose.pose.orientation.z = 0;
00244 pose.pose.orientation.w = 1;
00245 ar.poses.push_back(pose);
00246 std::vector<double> pos;
00247 pos.push_back(aruc[i][0]);
00248 pos.push_back(aruc[i][1]);
00249 pos.push_back(aruc[i][2]);
00250 aruco_pos.push_back(pos);
00251 }
00252 aruco_pub_.publish(ar);
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278 }
00279
00280 bool first = true;
00281 aruco::CameraParameters param;
00282 cv::Mat intr, dist;
00283 cv::Size CamSize;
00284
00285 void Navigator::RGBDCallback(
00286 const ImageMsg::ConstPtr& rgb_msg,
00287 const ImageMsg::ConstPtr& depth_msg,
00288 const CameraInfoMsg::ConstPtr& info_msg)
00289 {
00290 tf::StampedTransform transform;
00291
00292 const ros::Time& time = rgb_msg->header.stamp;
00293 if (first)
00294 {
00295 convertCameraInfoToMats(info_msg, intr, dist);
00296 CamSize.width = info_msg->width;
00297 CamSize.height = info_msg->height;
00298 param.CameraMatrix = intr;
00299 param.CamSize = CamSize;
00300 param.Distorsion = dist;
00301
00302 first = false;
00303 }
00304 try{
00305 tf_listener_.waitForTransform(
00306 fixed_frame_, rgb_msg->header.frame_id, time, ros::Duration(0.1));
00307 tf_listener_.lookupTransform(
00308 fixed_frame_, rgb_msg->header.frame_id, time, transform);
00309 }
00310 catch(...)
00311 {
00312 return;
00313 }
00314
00315
00316 rgbdtools::RGBDFrame frame;
00317 createRGBDFrameFromROSMessages(rgb_msg, depth_msg, info_msg, frame);
00318 frame.index = rgbd_frame_index_;
00319 rgbd_frame_index_++;
00320 std::vector<aruco::Marker> markers;
00321
00322 ros::WallTime start_detect = ros::WallTime::now();
00323
00324 MDetector.detect(frame.rgb_img,markers,param,0.20);
00325 if (markers.size()>0)
00326 {
00327 manual_add_ = true;
00328 solver_.giveMarkers(markers);
00329 }
00330 ros::WallTime end_detect = ros::WallTime::now();
00331
00332
00333 addKeyframe(frame,eigenAffineFromTf( transform));
00334
00335 ros::WallTime prepare_start = ros::WallTime::now();
00336 graph_detector_.prepareFeaturesForRANSAC_Iterative(keyframes_.size()-1,keyframes_);
00337 ros::WallTime prepare_end = ros::WallTime::now();
00338
00339 ros::WallTime matrix_start = ros::WallTime::now();
00340 graph_detector_.buildMatchMatrixSurfTree_Iterative(keyframes_.size()-1,keyframes_);
00341 ros::WallTime matrix_end = ros::WallTime::now();
00342
00343 ros::WallTime candidate_start = ros::WallTime::now();
00344 graph_detector_.buildCandidateMatrixSurfTree_Iterative(keyframes_.size()-1);
00345 ros::WallTime candidate_end = ros::WallTime::now();
00346
00347 ros::WallTime correspondence_start = ros::WallTime::now();
00348 graph_detector_.buildCorrespondenceMatrix_mine_Iterative(keyframes_.size()-1,keyframes_,associations_);
00349 ros::WallTime correspondence_end = ros::WallTime::now();
00350
00351 ros::WallTime solver_start = ros::WallTime::now();
00352 solver_.add_edges(keyframes_.size()-1,keyframes_,associations_);
00353 solver_.solve_Iterative(keyframes_);
00354 solver_.getArucoPos(&aruco_pos,&aruco_kfs,keyframes_);
00355 ros::WallTime solver_end = ros::WallTime::now();
00356
00357 ros::WallTime filter_start = ros::WallTime::now();
00358 filter_aruco();
00359 ros::WallTime filter_end = ros::WallTime::now();
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 ros::WallTime publish_start = ros::WallTime::now();
00380 publishKeyframePoses();
00381 publishPath();
00382 publishArucoPos();
00383 publishKeyframeAssociations();
00384 ros::WallTime publish_end = ros::WallTime::now();
00385 std::cout << "Statistics:" << std::endl;
00386 std::cout << "Prepare Features: " << 1000.0 * (prepare_end - prepare_start ).toSec() << std::endl;
00387 std::cout << "Building Matrix: " << 1000.0 * (matrix_end - matrix_start ).toSec() << std::endl;
00388 std::cout << "Finding Candidates: " << 1000.0 * (candidate_end - candidate_start ).toSec() << std::endl;
00389 std::cout << "Creating Correspondeces: " << 1000.0 * (correspondence_end - correspondence_start ).toSec() << std::endl;
00390 std::cout << "Solving graph: " << 1000.0 * (solver_end - solver_start ).toSec() << std::endl;
00391 std::cout << "Filtering Aruco: " << 1000.0 * (filter_end - filter_start ).toSec() << std::endl;
00392 std::cout << "Publishing Results: " << 1000.0 * (publish_end - publish_start ).toSec() << std::endl;
00393
00394 }
00395
00396 int triple_add=0;
00397
00398
00399 bool Navigator::processFrame(
00400 const rgbdtools::RGBDFrame& frame,
00401 const AffineTransform& pose)
00402 {
00403
00404 geometry_msgs::PoseStamped frame_pose;
00405 tf::Transform frame_tf = tfFromEigenAffine(pose);
00406 tf::poseTFToMsg(frame_tf, frame_pose.pose);
00407
00408
00409 frame_pose.header.frame_id = fixed_frame_;
00410 frame_pose.header.seq = frame.header.seq;
00411 frame_pose.header.stamp.sec = frame.header.stamp.sec;
00412 frame_pose.header.stamp.nsec = frame.header.stamp.nsec;
00413
00414 path_msg_.poses.push_back(frame_pose);
00415
00416
00417 bool result;
00418
00419 if(keyframes_.empty() || manual_add_)
00420 {
00421 result = true;
00422 }
00423 else
00424 {
00425 double dist, angle;
00426 getTfDifference(tfFromEigenAffine(pose),
00427 tfFromEigenAffine(keyframes_.back().pose),
00428 dist, angle);
00429
00430 if (triple_add >0 || dist > kf_dist_eps_ || angle > kf_angle_eps_)
00431 {
00432 result = true;
00433
00434
00435
00436
00437
00438
00439
00440
00441 }
00442 else
00443 result = false;
00444 }
00445
00446 if (result)
00447 {
00448 addKeyframe(frame, pose);
00449 }
00450 return result;
00451 }
00452
00453 void Navigator::addKeyframe(
00454 const rgbdtools::RGBDFrame& frame,
00455 const AffineTransform& pose)
00456 {
00457 rgbdtools::RGBDKeyframe keyframe(frame);
00458 keyframe.pose = pose;
00459
00460 if (manual_add_)
00461 {
00462 ROS_INFO("Adding frame manually");
00463 manual_add_ = false;
00464 keyframe.manually_added = true;
00465 }
00466 keyframes_.push_back(keyframe);
00467 }
00468
00469 bool Navigator::publishKeyframeSrvCallback(
00470 PublishKeyframe::Request& request,
00471 PublishKeyframe::Response& response)
00472 {
00473 int kf_idx = request.id;
00474
00475 if (kf_idx >= 0 && kf_idx < (int)keyframes_.size())
00476 {
00477 ROS_INFO("Publishing keyframe %d", kf_idx);
00478 publishKeyframeData(kf_idx);
00479 Pose(kf_idx);
00480 return true;
00481 }
00482 else
00483 {
00484 ROS_ERROR("Index out of range");
00485 return false;
00486 }
00487 }
00488
00489 bool Navigator::publishKeyframesSrvCallback(
00490 PublishKeyframes::Request& request,
00491 PublishKeyframes::Response& response)
00492 {
00493 bool found_match = false;
00494
00495
00496
00497 boost::regex expression(request.re);
00498
00499 for (unsigned int kf_idx = 0; kf_idx < keyframes_.size(); ++kf_idx)
00500 {
00501 std::stringstream ss;
00502 ss << kf_idx;
00503 std::string kf_idx_string = ss.str();
00504
00505 boost::smatch match;
00506
00507 if(boost::regex_match(kf_idx_string, match, expression))
00508 {
00509 found_match = true;
00510 ROS_INFO("Publishing keyframe %d", kf_idx);
00511 publishKeyframeData(kf_idx);
00512 publishKeyframePose(kf_idx);
00513 usleep(25000);
00514 }
00515 }
00516
00517 publishPath();
00518
00519 return found_match;
00520 }
00521
00522 void Navigator::publishKeyframeData(int i)
00523 {
00524
00525
00526
00527
00528 rgbdtools::RGBDKeyframe& keyframe = keyframes_[i];
00529
00530
00531 PointCloudT cloud;
00532 keyframe.constructDensePointCloud(cloud, max_range_, max_stdev_);
00533
00534
00535 PointCloudT cloud_ff;
00536 pcl::transformPointCloud(cloud, cloud_ff, keyframe.pose);
00537
00538 cloud_ff.header.frame_id = fixed_frame_;
00539
00540 keyframes_pub_.publish(cloud_ff);
00541 }
00542
00543 void Navigator::publishKeyframeAssociations()
00544 {
00545 visualization_msgs::Marker marker;
00546 marker.header.stamp = ros::Time::now();
00547 marker.header.frame_id = fixed_frame_;
00548 marker.id = 0;
00549 marker.type = visualization_msgs::Marker::LINE_LIST;
00550 marker.action = visualization_msgs::Marker::ADD;
00551
00552 marker.points.resize(associations_.size() * 2);
00553
00554 marker.color.a = 1.0;
00555
00556 for (unsigned int as_idx = 0; as_idx < associations_.size(); ++as_idx)
00557 {
00558
00559 const rgbdtools::KeyframeAssociation& association = associations_[as_idx];
00560 int kf_idx_a = association.kf_idx_a;
00561 int kf_idx_b = association.kf_idx_b;
00562 rgbdtools::RGBDKeyframe& keyframe_a = keyframes_[kf_idx_a];
00563 rgbdtools::RGBDKeyframe& keyframe_b = keyframes_[kf_idx_b];
00564
00565 int idx_start = as_idx*2;
00566 int idx_end = as_idx*2 + 1;
00567
00568 tf::Transform keyframe_a_pose = tfFromEigenAffine(keyframe_a.pose);
00569 tf::Transform keyframe_b_pose = tfFromEigenAffine(keyframe_b.pose);
00570
00571
00572 marker.points[idx_start].x = keyframe_a_pose.getOrigin().getX();
00573 marker.points[idx_start].y = keyframe_a_pose.getOrigin().getY();
00574 marker.points[idx_start].z = keyframe_a_pose.getOrigin().getZ();
00575
00576
00577 marker.points[idx_end].x = keyframe_b_pose.getOrigin().getX();
00578 marker.points[idx_end].y = keyframe_b_pose.getOrigin().getY();
00579 marker.points[idx_end].z = keyframe_b_pose.getOrigin().getZ();
00580
00581 if (association.type == rgbdtools::KeyframeAssociation::VO)
00582 {
00583 marker.ns = "VO";
00584 marker.scale.x = 0.002;
00585
00586 marker.color.r = 0.0;
00587 marker.color.g = 1.0;
00588 marker.color.b = 0.0;
00589 }
00590 else if (association.type == rgbdtools::KeyframeAssociation::RANSAC)
00591 {
00592 marker.ns = "RANSAC";
00593 marker.scale.x = 0.002;
00594
00595 marker.color.r = 1.0;
00596 marker.color.g = 1.0;
00597 marker.color.b = 0.0;
00598 }
00599
00600 kf_assoc_pub_.publish(marker);
00601 }
00602 }
00603
00604 void Navigator::publishKeyframePoses()
00605 {
00606 for(unsigned int kf_idx = 0; kf_idx < keyframes_.size(); ++kf_idx)
00607 {
00608 publishKeyframePose(kf_idx);
00609 }
00610 }
00611
00612 void Navigator::publishArucoPos()
00613 {
00614 for(u_int i = 0; i < aruco_pos.size(); i++)
00615 {
00616 visualization_msgs::Marker marker;
00617 marker.header.stamp = ros::Time::now();
00618 marker.header.frame_id = fixed_frame_;
00619 marker.ns = "Aruco_pos";
00620 marker.id = i;
00621 marker.type = visualization_msgs::Marker::SPHERE;
00622 marker.action = visualization_msgs::Marker::ADD;
00623 marker.pose.position.x = aruco_pos[i][0];
00624 marker.pose.position.y = aruco_pos[i][1];
00625 marker.pose.position.z = aruco_pos[i][2];
00626 marker.pose.orientation.x = 0.0;
00627 marker.pose.orientation.y = 0.0;
00628 marker.pose.orientation.z = 0.0;
00629 marker.pose.orientation.w = 1.0;
00630 marker.scale.x = 0.1;
00631 marker.scale.y = 0.1;
00632 marker.scale.z = 0.1;
00633 marker.color.a = 1.0;
00634 marker.color.r = 1.0;
00635 marker.color.g = 0.0;
00636 marker.color.b = 0.0;
00637 poses_pub_.publish(marker);
00638 }
00639 }
00640 void Navigator::publishPath()
00641 {
00642 PathMsg kfs;
00643 kfs.header.frame_id = fixed_frame_;
00644 kfs.header.seq = 0;
00645 kfs.header.stamp = ros::Time::now();
00646 for(u_int i = solver_.n_original_poses; i < keyframes_.size(); i++)
00647 {
00648 const rgbdtools::RGBDKeyframe& keyframe=keyframes_[i];
00649
00650 if(!keyframe.used)
00651 {
00652 continue;
00653 }
00654
00655 geometry_msgs::PoseStamped pose;
00656 pose.header.frame_id = fixed_frame_;
00657 pose.header.seq = keyframe.header.seq;
00658 pose.header.stamp.sec = keyframe.header.stamp.sec;
00659 pose.header.stamp.nsec = keyframe.header.stamp.nsec;
00660 pose.pose.position.x = keyframe.pose(0,3);
00661 pose.pose.position.y = keyframe.pose(1,3);
00662 pose.pose.position.z = keyframe.pose(2,3);
00663 pose.pose.orientation.x = 1;
00664 pose.pose.orientation.y = 0;
00665 pose.pose.orientation.z = 0;
00666 pose.pose.orientation.w = 1;
00667 kfs.poses.push_back(pose);
00668 }
00669 if(kfs.poses.size()!=0)
00670 path_pub_.publish(kfs);
00671 }
00672
00673 void Navigator::publishKeyframePose(int i)
00674 {
00675 rgbdtools::RGBDKeyframe& keyframe = keyframes_[i];
00676
00677
00678
00679 visualization_msgs::Marker marker;
00680 marker.header.stamp = ros::Time::now();
00681 marker.header.frame_id = fixed_frame_;
00682 marker.ns = "keyframe_poses";
00683 marker.id = i;
00684 marker.type = visualization_msgs::Marker::ARROW;
00685 marker.action = visualization_msgs::Marker::ADD;
00686 marker.points.resize(2);
00687
00688
00689 tf::Transform keyframe_pose = tfFromEigenAffine(keyframe.pose);
00690 marker.points[0].x = keyframe_pose.getOrigin().getX();
00691 marker.points[0].y = keyframe_pose.getOrigin().getY();
00692 marker.points[0].z = keyframe_pose.getOrigin().getZ();
00693
00694
00695 tf::Transform ep;
00696 ep.setIdentity();
00697 ep.setOrigin(tf::Vector3(0.00, 0.00, 0.12));
00698 ep = keyframe_pose * ep;
00699
00700 marker.points[1].x = ep.getOrigin().getX();
00701 marker.points[1].y = ep.getOrigin().getY();
00702 marker.points[1].z = ep.getOrigin().getZ();
00703
00704 marker.scale.x = 0.02;
00705 marker.scale.y = 0.05;
00706 if((u_int)i < solver_.n_original_poses)
00707 {
00708 marker.color.a = 1.0;
00709 marker.color.r = 0.0;
00710 marker.color.g = 1.0;
00711 marker.color.b = 0.0;
00712 }
00713 else
00714 {
00715 if(!keyframe.used)
00716 {
00717 marker.color.a = 0.5;
00718 marker.color.r = 1.0;
00719 marker.color.g = 0.0;
00720 marker.color.b = 0.0;
00721 }
00722 else
00723 {
00724 marker.color.a = 1.0;
00725 marker.color.r = 1.0;
00726 marker.color.g = 1.0;
00727 marker.color.b = 0.0;
00728 }
00729
00730 }
00731 poses_pub_.publish(marker);
00732
00733
00734
00735 visualization_msgs::Marker marker_text;
00736 marker_text.header.stamp = ros::Time::now();
00737 marker_text.header.frame_id = fixed_frame_;
00738 marker_text.ns = "keyframe_indexes";
00739 marker_text.id = i;
00740 marker_text.type = visualization_msgs::Marker::TEXT_VIEW_FACING;
00741 marker_text.action = visualization_msgs::Marker::ADD;
00742
00743 tf::poseTFToMsg(keyframe_pose, marker_text.pose);
00744
00745 marker_text.pose.position.z -= 0.05;
00746
00747 char label[6];
00748 sprintf(label, "%d", i);
00749 marker_text.text = label;
00750
00751 marker_text.color.a = 1.0;
00752 marker_text.color.r = 1.0;
00753 marker_text.color.g = 1.0;
00754 marker_text.color.b = 0.0;
00755
00756 marker_text.scale.z = 0.05;
00757
00758 poses_pub_.publish(marker_text);
00759 }
00760
00761 bool Navigator::saveKeyframesSrvCallback(
00762 Save::Request& request,
00763 Save::Response& response)
00764 {
00765 std::string filepath = request.filename;
00766
00767 ROS_INFO("Saving keyframes...");
00768 std::string filepath_keyframes = filepath + "/keyframes/";
00769 bool result_kf = saveKeyframes(keyframes_, filepath_keyframes);
00770 if (result_kf) ROS_INFO("Keyframes saved to %s", filepath.c_str());
00771 else ROS_ERROR("Keyframe saving failed!");
00772
00773 ROS_INFO("Saving path...");
00774 bool result_path = savePath(filepath);
00775 savePathTUMFormat(filepath);
00776 if (result_path ) ROS_INFO("Path saved to %s", filepath.c_str());
00777 else ROS_ERROR("Path saving failed!");
00778 solver_.save_graph(filepath);
00779
00780 return result_kf && result_path;
00781 }
00782
00783 bool Navigator::loadKeyframesSrvCallback(
00784 Load::Request& request,
00785 Load::Response& response)
00786 {
00787 bool skip = false;
00788 ros::WallTime start_all = ros::WallTime::now();
00789 std::string filepath1 = request.filename;
00790 char buffer[200];
00791 std::string filepath;
00792 if(filepath1.at(filepath1.size()-1)=='!')
00793 {
00794 skip = true;
00795 int copied = filepath1.copy(buffer,filepath1.size()-1,0);
00796 buffer[copied] = '\0';
00797 filepath = buffer;
00798 }
00799 else
00800 {
00801 filepath = filepath1;
00802 }
00803 ROS_INFO("Loading keyframes...");
00804 std::string filepath_keyframes = filepath + "/keyframes/";
00805 bool result_kf = loadKeyframes(keyframes_, filepath_keyframes);
00806 if (result_kf) ROS_INFO("Keyframes loaded successfully");
00807 else ROS_ERROR("Keyframe loading failed!");
00808
00809 ROS_INFO("Loading path...");
00810 bool result_path = loadPath(filepath);
00811 if (result_path) ROS_INFO("Path loaded successfully");
00812 else ROS_ERROR("Path loading failed!");
00813 publishKeyframePoses();
00814 solver_.parse((filepath).c_str(),keyframes_);
00815 publishKeyframePoses();
00816 if(!(result_kf && result_path))
00817 return false;
00818 if(skip)
00819 return result_kf && result_path;
00820 graph_detector_.generateKeyframeAssociations_Iterative(keyframes_,associations_);
00821 double dur = getMsDuration(start_all);
00822
00823 ROS_INFO("Everything took %.1f ms", dur);
00824 return result_kf && result_path;
00825 }
00826
00827 bool Navigator::savePcdMapSrvCallback(
00828 Save::Request& request,
00829 Save::Response& response)
00830 {
00831 ROS_INFO("Saving map as pcd...");
00832 const std::string& path = request.filename;
00833 bool result = savePcdMap(path);
00834
00835 if (result) ROS_INFO("Pcd map saved to %s", path.c_str());
00836 else ROS_ERROR("Pcd map saving failed");
00837
00838 return result;
00839 }
00840
00841 bool Navigator::saveOctomapSrvCallback(
00842 Save::Request& request,
00843 Save::Response& response)
00844 {
00845 ROS_INFO("Saving map as Octomap...");
00846 const std::string& path = request.filename;
00847 bool result = saveOctomap(path);
00848
00849 if (result) ROS_INFO("Octomap saved to %s", path.c_str());
00850 else ROS_ERROR("Octomap saving failed");
00851
00852 return result;
00853 }
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954 bool Navigator::addManualKeyframeSrvCallback(
00955 AddManualKeyframe::Request& request,
00956 AddManualKeyframe::Response& response)
00957 {
00958
00959 manual_add_ = true;
00960
00961 return true;
00962 }
00963
00964 bool Navigator::generateGraphSrvCallback(
00965 GenerateGraph::Request& request,
00966 GenerateGraph::Response& response)
00967 {
00968 associations_.clear();
00969 graph_detector_.generateKeyframeAssociations(keyframes_, associations_);
00970
00971 ROS_INFO("%d associations detected", (int)associations_.size());
00972 publishKeyframePoses();
00973 publishKeyframeAssociations();
00974
00975 return true;
00976 }
00977
00978 bool Navigator::solveGraphSrvCallback(
00979 SolveGraph::Request& request,
00980 SolveGraph::Response& response)
00981 {
00982 ros::WallTime start = ros::WallTime::now();
00983
00984
00985
00986 solver_.solve(keyframes_, associations_);
00987
00988 max_map_z_ = getmaxheight(path_msg_)+0.2;
00989 min_map_z_= getminheight(path_msg_)-0.5;
00990
00991
00992
00993
00994
00995
00996
00997
00998 double dur = getMsDuration(start);
00999
01000 ROS_INFO("Solving took %.1f ms", dur);
01001
01002
01003 publishKeyframePoses();
01004 publishKeyframeAssociations();
01005
01006 return true;
01007 }
01008
01009
01013 void Navigator::updatePathFromKeyframePoses()
01014 {
01015 int kf_size = keyframes_.size();
01016 int f_size = path_msg_.poses.size();
01017
01018
01019 AffineTransformVector path_new;
01020 path_new.resize(f_size);
01021
01022 if (kf_size < 2) return;
01023
01024 for (int kf_idx = 0; kf_idx < kf_size - 1; ++kf_idx)
01025 {
01026
01027 const rgbdtools::RGBDKeyframe& keyframe_a = keyframes_[kf_idx];
01028 const rgbdtools::RGBDKeyframe& keyframe_b = keyframes_[kf_idx + 1];
01029
01030
01031 int f_idx_a = keyframe_a.index;
01032 int f_idx_b = keyframe_b.index;
01033
01034
01035 tf::Transform kf_pose_a = tfFromEigenAffine(keyframe_a.pose);
01036 tf::Transform kf_pose_b = tfFromEigenAffine(keyframe_b.pose);
01037
01038
01039 tf::Transform kf_pose_a_prev, kf_pose_b_prev;
01040 tf::poseMsgToTF(path_msg_.poses[f_idx_a].pose, kf_pose_a_prev);
01041 tf::poseMsgToTF(path_msg_.poses[f_idx_b].pose, kf_pose_b_prev);
01042
01043
01044 tf::Transform kf_motion = kf_pose_a.inverse() * kf_pose_b;
01045 tf::Transform kf_motion_prev = kf_pose_a_prev.inverse() * kf_pose_b_prev;
01046
01047
01048 tf::Transform correction = kf_motion_prev.inverse() * kf_motion;
01049
01050
01051 for (int f_idx = f_idx_a; f_idx < f_idx_b; ++f_idx)
01052 {
01053
01054 double interp_scale = (double)(f_idx - f_idx_a) / (double)(f_idx_b - f_idx_a);
01055
01056
01057 tf::Vector3 v_interp = correction.getOrigin() * interp_scale;
01058 tf::Quaternion q_interp = tf::Quaternion::getIdentity();
01059 q_interp.slerp(correction.getRotation(), interp_scale);
01060
01061
01062 tf::Transform interpolated_correction;
01063 interpolated_correction.setOrigin(v_interp);
01064 interpolated_correction.setRotation(q_interp);
01065
01066
01067 tf::Transform frame_pose_prev;
01068 tf::poseMsgToTF(path_msg_.poses[f_idx].pose, frame_pose_prev);
01069
01070
01071 tf::Transform frame_motion_prev = kf_pose_a_prev.inverse() * frame_pose_prev;
01072
01073
01074 tf::Transform interpolated_motion = frame_motion_prev * interpolated_correction;
01075
01076
01077 path_new[f_idx] = keyframe_a.pose * eigenAffineFromTf(interpolated_motion);
01078 }
01079 }
01080
01081
01082 const rgbdtools::RGBDKeyframe& last_kf = keyframes_[kf_size - 1];
01083
01084 tf::Transform last_kf_pose_prev;
01085 tf::poseMsgToTF(path_msg_.poses[last_kf.index].pose, last_kf_pose_prev);
01086
01087
01088 for (int f_idx = last_kf.index; f_idx < f_size; ++f_idx)
01089 {
01090
01091 tf::Transform frame_pose_prev;
01092 tf::poseMsgToTF(path_msg_.poses[f_idx].pose, frame_pose_prev);
01093
01094
01095 tf::Transform frame_motion_prev = last_kf_pose_prev.inverse() * frame_pose_prev;
01096
01097
01098 path_new[f_idx] = last_kf.pose * eigenAffineFromTf(frame_motion_prev);
01099 }
01100
01101
01102 pathEigenAffineToROS(path_new, path_msg_);
01103 }
01104
01105
01106 bool Navigator::savePcdMap(const std::string& path)
01107 {
01108 PointCloudT pcd_map;
01109 buildPcdMap(pcd_map);
01110
01111
01112 pcl::PCDWriter writer;
01113 int result_pcd = writer.writeBinary<PointT>(path, pcd_map);
01114
01115 if (result_pcd < 0) return false;
01116 else return true;
01117 }
01118
01119 void Navigator::buildPcdMap(PointCloudT& map_cloud)
01120 {
01121 PointCloudT::Ptr aggregate_cloud(new PointCloudT());
01122 aggregate_cloud->header.frame_id = fixed_frame_;
01123
01124
01125 for (unsigned int kf_idx = 0; kf_idx < keyframes_.size(); ++kf_idx)
01126 {
01127 const rgbdtools::RGBDKeyframe& keyframe = keyframes_[kf_idx];
01128
01129 PointCloudT cloud;
01130 keyframe.constructDensePointCloud(cloud, max_range_, max_stdev_);
01131
01132 PointCloudT cloud_tf;
01133 pcl::transformPointCloud(cloud, cloud_tf, keyframe.pose);
01134 cloud_tf.header.frame_id = fixed_frame_;
01135
01136 *aggregate_cloud += cloud_tf;
01137 }
01138
01139
01140 pcl::VoxelGrid<PointT> vgf;
01141 vgf.setInputCloud(aggregate_cloud);
01142 vgf.setLeafSize(pcd_map_res_, pcd_map_res_, pcd_map_res_);
01143 vgf.setFilterFieldName("z");
01144 vgf.setFilterLimits (-std::numeric_limits<double>::infinity(), max_map_z_);
01145
01146 vgf.filter(map_cloud);
01147 }
01148 void Navigator::buildFullCloud(PointCloudT& map_cloud)
01149 {
01150 PointCloudT::Ptr aggregate_cloud(new PointCloudT());
01151 aggregate_cloud->header.frame_id = fixed_frame_;
01152
01153
01154 for (unsigned int kf_idx = 0; kf_idx < keyframes_.size(); ++kf_idx)
01155 {
01156 const rgbdtools::RGBDKeyframe& keyframe = keyframes_[kf_idx];
01157
01158 PointCloudT cloud;
01159 keyframe.constructDensePointCloud(cloud, max_range_, max_stdev_);
01160
01161 PointCloudT cloud_tf;
01162 pcl::transformPointCloud(cloud, cloud_tf, keyframe.pose);
01163 cloud_tf.header.frame_id = fixed_frame_;
01164
01165 *aggregate_cloud += cloud_tf;
01166 }
01167 map_cloud = *aggregate_cloud;
01168 }
01169
01170 bool Navigator::saveOctomap(const std::string& path)
01171 {
01172 bool result;
01173
01174 if (octomap_with_color_)
01175 {
01176 octomap::ColorOcTree tree(octomap_res_);
01177 buildColorOctomap(tree);
01178 result = tree.write(path);
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194 }
01195 else
01196 result = false;
01197 return result;
01198 }
01199
01200
01201 void Navigator::buildColorOctomap(octomap::ColorOcTree& tree)
01202 {
01203 ROS_INFO("Building Octomap with color...");
01204
01205 octomap::point3d sensor_origin(0.0, 0.0, 0.0);
01206 for (unsigned int kf_idx = 0; kf_idx < keyframes_.size(); ++kf_idx)
01207 {
01208 ROS_INFO("Processing keyframe %u", kf_idx);
01209 const rgbdtools::RGBDKeyframe& keyframe = keyframes_[kf_idx];
01210
01211
01212 PointCloudT::Ptr cloud_unf(new PointCloudT());
01213 keyframe.constructDensePointCloud(*cloud_unf, max_range_, max_stdev_);
01214
01215
01216 pcl::transformPointCloud(*cloud_unf, *cloud_unf, keyframe.pose);
01217 PointCloudT cloud;
01218 pcl::PassThrough<PointT> pass;
01219 pass.setInputCloud (cloud_unf);
01220 pass.setFilterFieldName ("z");
01221 pass.setFilterLimits (-std::numeric_limits<double>::infinity(), max_map_z_);
01222 pass.filter(cloud);
01223 pcl::transformPointCloud(cloud, cloud, keyframe.pose.inverse());
01224
01225 octomap::pose6d frame_origin = poseTfToOctomap(tfFromEigenAffine(keyframe.pose));
01226
01227
01228 octomap::Pointcloud octomap_cloud;
01229 for (unsigned int pt_idx = 0; pt_idx < cloud.points.size(); ++pt_idx)
01230 {
01231 const PointT& p = cloud.points[pt_idx];
01232 if (!std::isnan(p.z))
01233 octomap_cloud.push_back(p.x, p.y, p.z);
01234 }
01235
01236
01237 tree.insertScan(octomap_cloud, sensor_origin, frame_origin);
01238
01239
01240 PointCloudT cloud_tf;
01241 pcl::transformPointCloud(cloud, cloud_tf, keyframe.pose);
01242 for (unsigned int pt_idx = 0; pt_idx < cloud_tf.points.size(); ++pt_idx)
01243 {
01244 const PointT& p = cloud_tf.points[pt_idx];
01245 if (!std::isnan(p.z))
01246 {
01247 octomap::point3d endpoint(p.x, p.y, p.z);
01248 octomap::ColorOcTreeNode* n = tree.search(endpoint);
01249 if (n) n->setColor(p.r, p.g, p.b);
01250 }
01251 }
01252
01253 tree.updateInnerOccupancy();
01254 }
01255 }
01256
01257
01258
01259
01260
01261
01262
01263 bool Navigator::savePath(const std::string& filepath)
01264 {
01265
01266 std::string filename = filepath + "/path.txt";
01267 std::ofstream file(filename.c_str());
01268 if (!file.is_open()) return false;
01269
01270 file << "# index seq stamp.sec stamp.nsec x y z qx qy qz qw" << std::endl;
01271
01272 for (unsigned int idx = 0; idx < path_msg_.poses.size(); ++idx)
01273 {
01274 const geometry_msgs::PoseStamped& pose = path_msg_.poses[idx];
01275
01276 file << idx << " "
01277 << pose.header.seq << " "
01278 << pose.header.stamp.sec << " "
01279 << pose.header.stamp.nsec << " "
01280 << pose.pose.position.x << " "
01281 << pose.pose.position.y << " "
01282 << pose.pose.position.z << " "
01283 << pose.pose.orientation.x << " "
01284 << pose.pose.orientation.y << " "
01285 << pose.pose.orientation.z << " "
01286 << pose.pose.orientation.w << std::endl;
01287 }
01288
01289 file.close();
01290
01291 return true;
01292 }
01293
01294 bool Navigator::savePathTUMFormat(const std::string& filepath)
01295 {
01296
01297 std::string filename = filepath + "/path.tum.txt";
01298 std::ofstream file(filename.c_str());
01299 if (!file.is_open()) return false;
01300
01301 file << "# stamp x y z qx qy qz qw" << std::endl;
01302
01303 for (unsigned int idx = 0; idx < path_msg_.poses.size(); ++idx)
01304 {
01305 const geometry_msgs::PoseStamped& pose = path_msg_.poses[idx];
01306
01307 file << pose.header.stamp.sec << "."
01308 << pose.header.stamp.nsec << " "
01309 << pose.pose.position.x << " "
01310 << pose.pose.position.y << " "
01311 << pose.pose.position.z << " "
01312 << pose.pose.orientation.x << " "
01313 << pose.pose.orientation.y << " "
01314 << pose.pose.orientation.z << " "
01315 << pose.pose.orientation.w << std::endl;
01316 }
01317
01318 file.close();
01319
01320 return true;
01321 }
01322
01323 bool Navigator::loadPath(const std::string& filepath)
01324 {
01325 path_msg_.poses.clear();
01326
01327
01328 std::string filename = filepath + "/path.txt";
01329 std::ifstream file(filename.c_str());
01330 if (!file.is_open()) return false;
01331
01332 std::string line;
01333
01334
01335 getline(file, line);
01336
01337
01338 while(std::getline(file, line))
01339 {
01340 std::istringstream is(line);
01341
01342
01343 geometry_msgs::PoseStamped pose;
01344 pose.header.frame_id = fixed_frame_;
01345 int idx;
01346
01347 is >> idx
01348 >> pose.header.seq
01349 >> pose.header.stamp.sec
01350 >> pose.header.stamp.nsec
01351 >> pose.pose.position.x
01352 >> pose.pose.position.y
01353 >> pose.pose.position.z
01354 >> pose.pose.orientation.x
01355 >> pose.pose.orientation.y
01356 >> pose.pose.orientation.z
01357 >> pose.pose.orientation.w;
01358
01359
01360 path_msg_.poses.push_back(pose);
01361 }
01362
01363 file.close();
01364 return true;
01365 }
01366
01367 }
01368