00001
00024 #include "ccny_rgbd/apps/keyframe_mapper.h"
00025 #include "aruco/aruco.h"
00026 namespace ccny_rgbd {
00027
00028 KeyframeMapper::KeyframeMapper(
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 RGBD Keyframe Mapper");
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
00052
00053
00054 pub_keyframe_service_ = nh_.advertiseService(
00055 "publish_keyframe", &KeyframeMapper::publishKeyframeSrvCallback, this);
00056 pub_keyframes_service_ = nh_.advertiseService(
00057 "publish_keyframes", &KeyframeMapper::publishKeyframesSrvCallback, this);
00058 save_kf_service_ = nh_.advertiseService(
00059 "save_keyframes", &KeyframeMapper::saveKeyframesSrvCallback, this);
00060 load_kf_service_ = nh_.advertiseService(
00061 "load_keyframes", &KeyframeMapper::loadKeyframesSrvCallback, this);
00062 save_pcd_map_service_ = nh_.advertiseService(
00063 "save_pcd_map", &KeyframeMapper::savePcdMapSrvCallback, this);
00064 save_octomap_service_ = nh_.advertiseService(
00065 "save_octomap", &KeyframeMapper::saveOctomapSrvCallback, this);
00066 add_manual_keyframe_service_ = nh_.advertiseService(
00067 "add_manual_keyframe", &KeyframeMapper::addManualKeyframeSrvCallback, this);
00068 generate_graph_service_ = nh_.advertiseService(
00069 "generate_graph", &KeyframeMapper::generateGraphSrvCallback, this);
00070 solve_graph_service_ = nh_.advertiseService(
00071 "solve_graph", &KeyframeMapper::solveGraphSrvCallback, this);
00072
00073
00074
00075 ImageTransport rgb_it(nh_);
00076 ImageTransport depth_it(nh_);
00077
00078 sub_rgb_.subscribe(rgb_it, "/camera/rgb/image_rect_color", queue_size_);
00079 sub_depth_.subscribe(depth_it, "/camera/depth_registered/image_rect_raw", queue_size_);
00080 sub_info_.subscribe(nh_, "/camera/rgb/camera_info", queue_size_);
00081
00082
00083 sync_.reset(new RGBDSynchronizer3(
00084 RGBDSyncPolicy3(queue_size_), sub_rgb_, sub_depth_, sub_info_));
00085
00086 sync_->registerCallback(boost::bind(&KeyframeMapper::RGBDCallback, this, _1, _2, _3));
00087 }
00088
00089 KeyframeMapper::~KeyframeMapper()
00090 {
00091
00092 }
00093 aruco::MarkerDetector MDetector;
00094 void KeyframeMapper::initParams()
00095 {
00096 bool verbose;
00097
00098 if (!nh_private_.getParam ("verbose", verbose))
00099 verbose = true;
00100 if (!nh_private_.getParam ("queue_size", queue_size_))
00101 queue_size_ = 5;
00102 if (!nh_private_.getParam ("fixed_frame", fixed_frame_))
00103 fixed_frame_ = "/odom";
00104 if (!nh_private_.getParam ("pcd_map_res", pcd_map_res_))
00105 pcd_map_res_ = 0.01;
00106 if (!nh_private_.getParam ("octomap_res", octomap_res_))
00107 octomap_res_ = 0.05;
00108 if (!nh_private_.getParam ("octomap_with_color", octomap_with_color_))
00109 octomap_with_color_ = true;
00110 if (!nh_private_.getParam ("kf_dist_eps", kf_dist_eps_))
00111 kf_dist_eps_ = 0.10;
00112 if (!nh_private_.getParam ("kf_angle_eps", kf_angle_eps_))
00113 kf_angle_eps_ = 10.0 * M_PI / 180.0;
00114 if (!nh_private_.getParam ("max_range", max_range_))
00115 max_range_ = 10.0;
00116 if (!nh_private_.getParam ("max_stdev", max_stdev_))
00117 max_stdev_ = 555;
00118 if (!nh_private_.getParam ("max_map_z", max_map_z_))
00119 max_map_z_ = std::numeric_limits<double>::infinity();
00120
00121
00122 MDetector.setThresholdParams( 10.0,7.0);
00123 MDetector.setCornerRefinementMethod(aruco::MarkerDetector::LINES);
00124
00125 int graph_n_keypoints;
00126 int graph_n_candidates;
00127 int graph_k_nearest_neighbors;
00128 bool graph_matcher_use_desc_ratio_test = true;
00129
00130 if (!nh_private_.getParam ("graph/n_keypoints", graph_n_keypoints))
00131 graph_n_keypoints = 500;
00132 if (!nh_private_.getParam ("graph/n_candidates", graph_n_candidates))
00133 graph_n_candidates = 10;
00134 if (!nh_private_.getParam ("graph/k_nearest_neighbors", graph_k_nearest_neighbors))
00135 graph_k_nearest_neighbors = 4;
00136
00137 int min_inliers = 15;
00138 graph_detector_.setNKeypoints(graph_n_keypoints);
00139 graph_detector_.setNCandidates(graph_n_candidates);
00140 graph_detector_.setKNearestNeighbors(graph_k_nearest_neighbors);
00141 graph_detector_.setMatcherUseDescRatioTest(graph_matcher_use_desc_ratio_test);
00142 graph_detector_.setSacMinInliers(min_inliers);
00143 graph_detector_.setSACReestimateTf(false);
00144 graph_detector_.setSACSaveResults(true);
00145 graph_detector_.setVerbose(verbose);
00146 }
00147
00148 void KeyframeMapper::RGBDCallback(
00149 const ImageMsg::ConstPtr& rgb_msg,
00150 const ImageMsg::ConstPtr& depth_msg,
00151 const CameraInfoMsg::ConstPtr& info_msg)
00152 {
00153 tf::StampedTransform transform;
00154
00155 const ros::Time& time = rgb_msg->header.stamp;
00156
00157
00158 try{
00159 tf_listener_.waitForTransform(
00160 fixed_frame_, rgb_msg->header.frame_id, time, ros::Duration(0.1));
00161 tf_listener_.lookupTransform(
00162 fixed_frame_, rgb_msg->header.frame_id, time, transform);
00163 }
00164 catch(...)
00165 {
00166 if(!manual_add_)
00167 {
00168 return;
00169 }
00170 }
00171
00172
00173 rgbdtools::RGBDFrame frame;
00174 createRGBDFrameFromROSMessages(rgb_msg, depth_msg, info_msg, frame);
00175 frame.index = rgbd_frame_index_;
00176 rgbd_frame_index_++;
00177
00178 int val = cv::countNonZero(frame.depth_img);
00179 if(val==0)
00180 return;
00181 std::vector<aruco::Marker> markers;
00182
00183 cv::Mat intr, dist;
00184 convertCameraInfoToMats(info_msg, intr, dist);
00185 cv::Size CamSize;
00186 CamSize.width = info_msg->width;
00187 CamSize.height = info_msg->height;
00188
00189 aruco::CameraParameters param(intr,dist,CamSize);
00190 MDetector.detect(frame.rgb_img,markers,param,0.20);
00191 if (markers.size()>0)
00192 manual_add_ = true;
00193
00194 bool result = processFrame(frame, eigenAffineFromTf(transform));
00195 if (result) publishKeyframeData(keyframes_.size() - 1);
00196
00197 publishPath();
00198 }
00199
00200 int triple_add=0;
00201
00202 bool KeyframeMapper::processFrame(
00203 const rgbdtools::RGBDFrame& frame,
00204 const AffineTransform& pose)
00205 {
00206
00207 geometry_msgs::PoseStamped frame_pose;
00208 tf::Transform frame_tf = tfFromEigenAffine(pose);
00209 tf::poseTFToMsg(frame_tf, frame_pose.pose);
00210
00211
00212 frame_pose.header.frame_id = fixed_frame_;
00213 frame_pose.header.seq = frame.header.seq;
00214 frame_pose.header.stamp.sec = frame.header.stamp.sec;
00215 frame_pose.header.stamp.nsec = frame.header.stamp.nsec;
00216
00217 path_msg_.poses.push_back(frame_pose);
00218
00219
00220 bool result;
00221
00222 if(keyframes_.empty() || manual_add_)
00223 {
00224 result = true;
00225 }
00226 else
00227 {
00228 double dist, angle;
00229 getTfDifference(tfFromEigenAffine(pose),
00230 tfFromEigenAffine(keyframes_.back().pose),
00231 dist, angle);
00232
00233 if (triple_add >0 || dist > kf_dist_eps_ || angle > kf_angle_eps_)
00234 {
00235 result = true;
00236
00237
00238
00239
00240
00241
00242
00243
00244 }
00245 else
00246 result = false;
00247 }
00248
00249 if (result)
00250 {
00251 addKeyframe(frame, pose);
00252 }
00253 return result;
00254 }
00255
00256 void KeyframeMapper::addKeyframe(
00257 const rgbdtools::RGBDFrame& frame,
00258 const AffineTransform& pose)
00259 {
00260 rgbdtools::RGBDKeyframe keyframe(frame);
00261 keyframe.pose = pose;
00262
00263 if (manual_add_)
00264 {
00265 ROS_INFO("Adding frame manually");
00266 manual_add_ = false;
00267 keyframe.manually_added = true;
00268 }
00269 keyframes_.push_back(keyframe);
00270 }
00271
00272 bool KeyframeMapper::publishKeyframeSrvCallback(
00273 PublishKeyframe::Request& request,
00274 PublishKeyframe::Response& response)
00275 {
00276 int kf_idx = request.id;
00277
00278 if (kf_idx >= 0 && kf_idx < (int)keyframes_.size())
00279 {
00280 ROS_INFO("Publishing keyframe %d", kf_idx);
00281 publishKeyframeData(kf_idx);
00282 publishKeyframePose(kf_idx);
00283 return true;
00284 }
00285 else
00286 {
00287 ROS_ERROR("Index out of range");
00288 return false;
00289 }
00290 }
00291
00292 bool KeyframeMapper::publishKeyframesSrvCallback(
00293 PublishKeyframes::Request& request,
00294 PublishKeyframes::Response& response)
00295 {
00296 bool found_match = false;
00297
00298
00299
00300 boost::regex expression(request.re);
00301
00302 for (unsigned int kf_idx = 0; kf_idx < keyframes_.size(); ++kf_idx)
00303 {
00304 std::stringstream ss;
00305 ss << kf_idx;
00306 std::string kf_idx_string = ss.str();
00307
00308 boost::smatch match;
00309
00310 if(boost::regex_match(kf_idx_string, match, expression))
00311 {
00312 found_match = true;
00313 ROS_INFO("Publishing keyframe %d", kf_idx);
00314 publishKeyframeData(kf_idx);
00315 publishKeyframePose(kf_idx);
00316 usleep(25000);
00317 }
00318 }
00319
00320 publishPath();
00321
00322 return found_match;
00323 }
00324
00325 void KeyframeMapper::publishKeyframeData(int i)
00326 {
00327 rgbdtools::RGBDKeyframe& keyframe = keyframes_[i];
00328
00329
00330 PointCloudT cloud;
00331 keyframe.constructDensePointCloud(cloud, max_range_, max_stdev_);
00332
00333
00334 PointCloudT cloud_ff;
00335 pcl::transformPointCloud(cloud, cloud_ff, keyframe.pose);
00336
00337 cloud_ff.header.frame_id = fixed_frame_;
00338
00339 keyframes_pub_.publish(cloud_ff);
00340 }
00341
00342 void KeyframeMapper::publishKeyframeAssociations()
00343 {
00344 visualization_msgs::Marker marker;
00345 marker.header.stamp = ros::Time::now();
00346 marker.header.frame_id = fixed_frame_;
00347 marker.id = 0;
00348 marker.type = visualization_msgs::Marker::LINE_LIST;
00349 marker.action = visualization_msgs::Marker::ADD;
00350
00351 marker.points.resize(associations_.size() * 2);
00352
00353 marker.color.a = 1.0;
00354
00355 for (unsigned int as_idx = 0; as_idx < associations_.size(); ++as_idx)
00356 {
00357
00358 const rgbdtools::KeyframeAssociation& association = associations_[as_idx];
00359 int kf_idx_a = association.kf_idx_a;
00360 int kf_idx_b = association.kf_idx_b;
00361 rgbdtools::RGBDKeyframe& keyframe_a = keyframes_[kf_idx_a];
00362 rgbdtools::RGBDKeyframe& keyframe_b = keyframes_[kf_idx_b];
00363
00364 int idx_start = as_idx*2;
00365 int idx_end = as_idx*2 + 1;
00366
00367 tf::Transform keyframe_a_pose = tfFromEigenAffine(keyframe_a.pose);
00368 tf::Transform keyframe_b_pose = tfFromEigenAffine(keyframe_b.pose);
00369
00370
00371 marker.points[idx_start].x = keyframe_a_pose.getOrigin().getX();
00372 marker.points[idx_start].y = keyframe_a_pose.getOrigin().getY();
00373 marker.points[idx_start].z = keyframe_a_pose.getOrigin().getZ();
00374
00375
00376 marker.points[idx_end].x = keyframe_b_pose.getOrigin().getX();
00377 marker.points[idx_end].y = keyframe_b_pose.getOrigin().getY();
00378 marker.points[idx_end].z = keyframe_b_pose.getOrigin().getZ();
00379
00380 if (association.type == rgbdtools::KeyframeAssociation::VO)
00381 {
00382 marker.ns = "VO";
00383 marker.scale.x = 0.002;
00384
00385 marker.color.r = 0.0;
00386 marker.color.g = 1.0;
00387 marker.color.b = 0.0;
00388 }
00389 else if (association.type == rgbdtools::KeyframeAssociation::RANSAC)
00390 {
00391 marker.ns = "RANSAC";
00392 marker.scale.x = 0.002;
00393
00394 marker.color.r = 1.0;
00395 marker.color.g = 1.0;
00396 marker.color.b = 0.0;
00397 }
00398
00399 kf_assoc_pub_.publish(marker);
00400 }
00401 }
00402
00403 void KeyframeMapper::publishKeyframePoses()
00404 {
00405 for(unsigned int kf_idx = 0; kf_idx < keyframes_.size(); ++kf_idx)
00406 {
00407 publishKeyframePose(kf_idx);
00408 }
00409 }
00410
00411 void KeyframeMapper::publishKeyframePose(int i)
00412 {
00413 rgbdtools::RGBDKeyframe& keyframe = keyframes_[i];
00414
00415
00416
00417 visualization_msgs::Marker marker;
00418 marker.header.stamp = ros::Time::now();
00419 marker.header.frame_id = fixed_frame_;
00420 marker.ns = "keyframe_poses";
00421 marker.id = i;
00422 marker.type = visualization_msgs::Marker::ARROW;
00423 marker.action = visualization_msgs::Marker::ADD;
00424
00425 marker.points.resize(2);
00426
00427
00428 tf::Transform keyframe_pose = tfFromEigenAffine(keyframe.pose);
00429 marker.points[0].x = keyframe_pose.getOrigin().getX();
00430 marker.points[0].y = keyframe_pose.getOrigin().getY();
00431 marker.points[0].z = keyframe_pose.getOrigin().getZ();
00432
00433
00434 tf::Transform ep;
00435 ep.setIdentity();
00436 ep.setOrigin(tf::Vector3(0.00, 0.00, 0.12));
00437 ep = keyframe_pose * ep;
00438
00439 marker.points[1].x = ep.getOrigin().getX();
00440 marker.points[1].y = ep.getOrigin().getY();
00441 marker.points[1].z = ep.getOrigin().getZ();
00442
00443 marker.scale.x = 0.02;
00444 marker.scale.y = 0.05;
00445
00446 marker.color.a = 1.0;
00447 marker.color.r = 0.0;
00448 marker.color.g = 1.0;
00449 marker.color.b = 0.0;
00450
00451 poses_pub_.publish(marker);
00452
00453
00454
00455 visualization_msgs::Marker marker_text;
00456 marker_text.header.stamp = ros::Time::now();
00457 marker_text.header.frame_id = fixed_frame_;
00458 marker_text.ns = "keyframe_indexes";
00459 marker_text.id = i;
00460 marker_text.type = visualization_msgs::Marker::TEXT_VIEW_FACING;
00461 marker_text.action = visualization_msgs::Marker::ADD;
00462
00463 tf::poseTFToMsg(keyframe_pose, marker_text.pose);
00464
00465 marker_text.pose.position.z -= 0.05;
00466
00467 char label[6];
00468 sprintf(label, "%d", i);
00469 marker_text.text = label;
00470
00471 marker_text.color.a = 1.0;
00472 marker_text.color.r = 1.0;
00473 marker_text.color.g = 1.0;
00474 marker_text.color.b = 0.0;
00475
00476 marker_text.scale.z = 0.05;
00477
00478 poses_pub_.publish(marker_text);
00479 }
00480
00481 bool KeyframeMapper::saveKeyframesSrvCallback(
00482 Save::Request& request,
00483 Save::Response& response)
00484 {
00485 std::string filepath = request.filename;
00486
00487 ROS_INFO("Saving keyframes...");
00488 std::string filepath_keyframes = filepath + "/keyframes/";
00489 bool result_kf = saveKeyframes(keyframes_, filepath_keyframes);
00490 if (result_kf) ROS_INFO("Keyframes saved to %s", filepath.c_str());
00491 else ROS_ERROR("Keyframe saving failed!");
00492
00493 ROS_INFO("Saving path...");
00494 bool result_path = savePath(filepath);
00495 savePathTUMFormat(filepath);
00496 if (result_path ) ROS_INFO("Path saved to %s", filepath.c_str());
00497 else ROS_ERROR("Path saving failed!");
00498 solver_.save_graph(filepath);
00499
00500 return result_kf && result_path;
00501 }
00502
00503 bool KeyframeMapper::loadKeyframesSrvCallback(
00504 Load::Request& request,
00505 Load::Response& response)
00506 {
00507 bool skip = false;
00508 ros::WallTime start_all = ros::WallTime::now();
00509 std::string filepath1 = request.filename;
00510 char buffer[200];
00511 std::string filepath;
00512 if(filepath1.at(filepath1.size()-1)=='!')
00513 {
00514 skip = true;
00515 int copied = filepath1.copy(buffer,filepath1.size()-1,0);
00516 buffer[copied] = '\0';
00517 filepath = buffer;
00518 }
00519 else
00520 {
00521 filepath = filepath1;
00522 }
00523 ROS_INFO("Loading keyframes...");
00524 std::string filepath_keyframes = filepath + "/keyframes/";
00525 bool result_kf = loadKeyframes(keyframes_, filepath_keyframes);
00526 if (result_kf) ROS_INFO("Keyframes loaded successfully");
00527 else ROS_ERROR("Keyframe loading failed!");
00528
00529 ROS_INFO("Loading path...");
00530 bool result_path = loadPath(filepath);
00531 if (result_path) ROS_INFO("Path loaded successfully");
00532 else ROS_ERROR("Path loading failed!");
00533 publishKeyframePoses();
00534
00535 publishKeyframePoses();
00536 if(!(result_kf && result_path))
00537 return false;
00538 if(skip)
00539 return result_kf && result_path;
00540
00541 associations_.clear();
00542 graph_detector_.generateKeyframeAssociations(keyframes_, associations_);
00543
00544 ROS_INFO("%d associations detected", (int)associations_.size());
00545 publishKeyframePoses();
00546 publishKeyframeAssociations();
00547
00548 ros::WallTime start = ros::WallTime::now();
00549
00550 solver_.solve(keyframes_, associations_);
00551
00552 double dur = getMsDuration(start);
00553
00554 ROS_INFO("Solving took %.1f ms", dur);
00555 publishKeyframePoses();
00556 publishKeyframeAssociations();
00557
00558
00559
00560
00561 filepath = request.filename + "_solved";
00562 boost::filesystem::create_directories(filepath);
00563 filepath_keyframes = filepath + "/keyframes/";
00564 boost::filesystem::create_directories(filepath_keyframes);
00565 ROS_INFO("Saving keyframes...");
00566 result_kf = saveKeyframes(keyframes_, filepath_keyframes);
00567 if (result_kf) ROS_INFO("Keyframes saved to %s", filepath_keyframes.c_str());
00568 else ROS_ERROR("Keyframe saving failed!");
00569
00570 ROS_INFO("Saving path...");
00571 result_path = savePath(filepath);
00572 savePathTUMFormat(filepath);
00573 if (result_path ) ROS_INFO("Path saved to %s", filepath.c_str());
00574 else ROS_ERROR("Path saving failed!");
00575 solver_.save_graph(filepath);
00576
00577
00578
00579 dur = getMsDuration(start_all);
00580
00581 ROS_INFO("Everything took %.1f ms", dur);
00582 return result_kf && result_path;
00583 }
00584
00585 bool KeyframeMapper::savePcdMapSrvCallback(
00586 Save::Request& request,
00587 Save::Response& response)
00588 {
00589 ROS_INFO("Saving map as pcd...");
00590 const std::string& path = request.filename;
00591 bool result = savePcdMap(path);
00592
00593 if (result) ROS_INFO("Pcd map saved to %s", path.c_str());
00594 else ROS_ERROR("Pcd map saving failed");
00595
00596 return result;
00597 }
00598
00599 bool KeyframeMapper::saveOctomapSrvCallback(
00600 Save::Request& request,
00601 Save::Response& response)
00602 {
00603 ROS_INFO("Saving map as Octomap...");
00604 const std::string& path = request.filename;
00605 bool result = saveOctomap(path);
00606
00607 if (result) ROS_INFO("Octomap saved to %s", path.c_str());
00608 else ROS_ERROR("Octomap saving failed");
00609
00610 return result;
00611 }
00612
00613 bool KeyframeMapper::addManualKeyframeSrvCallback(
00614 AddManualKeyframe::Request& request,
00615 AddManualKeyframe::Response& response)
00616 {
00617 manual_add_ = true;
00618
00619 return true;
00620 }
00621
00622 bool KeyframeMapper::generateGraphSrvCallback(
00623 GenerateGraph::Request& request,
00624 GenerateGraph::Response& response)
00625 {
00626 associations_.clear();
00627 graph_detector_.generateKeyframeAssociations(keyframes_, associations_);
00628
00629 ROS_INFO("%d associations detected", (int)associations_.size());
00630 publishKeyframePoses();
00631 publishKeyframeAssociations();
00632
00633 return true;
00634 }
00635
00636 bool KeyframeMapper::solveGraphSrvCallback(
00637 SolveGraph::Request& request,
00638 SolveGraph::Response& response)
00639 {
00640 ros::WallTime start = ros::WallTime::now();
00641
00642
00643
00644 solver_.solve(keyframes_, associations_);
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656 double dur = getMsDuration(start);
00657
00658 ROS_INFO("Solving took %.1f ms", dur);
00659
00660
00661 publishKeyframePoses();
00662 publishKeyframeAssociations();
00663
00664 return true;
00665 }
00666
00667
00671 void KeyframeMapper::updatePathFromKeyframePoses()
00672 {
00673 int kf_size = keyframes_.size();
00674 int f_size = path_msg_.poses.size();
00675
00676
00677 AffineTransformVector path_new;
00678 path_new.resize(f_size);
00679
00680 if (kf_size < 2) return;
00681
00682 for (int kf_idx = 0; kf_idx < kf_size - 1; ++kf_idx)
00683 {
00684
00685 const rgbdtools::RGBDKeyframe& keyframe_a = keyframes_[kf_idx];
00686 const rgbdtools::RGBDKeyframe& keyframe_b = keyframes_[kf_idx + 1];
00687
00688
00689 int f_idx_a = keyframe_a.index;
00690 int f_idx_b = keyframe_b.index;
00691
00692
00693 tf::Transform kf_pose_a = tfFromEigenAffine(keyframe_a.pose);
00694 tf::Transform kf_pose_b = tfFromEigenAffine(keyframe_b.pose);
00695
00696
00697 tf::Transform kf_pose_a_prev, kf_pose_b_prev;
00698 tf::poseMsgToTF(path_msg_.poses[f_idx_a].pose, kf_pose_a_prev);
00699 tf::poseMsgToTF(path_msg_.poses[f_idx_b].pose, kf_pose_b_prev);
00700
00701
00702 tf::Transform kf_motion = kf_pose_a.inverse() * kf_pose_b;
00703 tf::Transform kf_motion_prev = kf_pose_a_prev.inverse() * kf_pose_b_prev;
00704
00705
00706 tf::Transform correction = kf_motion_prev.inverse() * kf_motion;
00707
00708
00709 for (int f_idx = f_idx_a; f_idx < f_idx_b; ++f_idx)
00710 {
00711
00712 double interp_scale = (double)(f_idx - f_idx_a) / (double)(f_idx_b - f_idx_a);
00713
00714
00715 tf::Vector3 v_interp = correction.getOrigin() * interp_scale;
00716 tf::Quaternion q_interp = tf::Quaternion::getIdentity();
00717 q_interp.slerp(correction.getRotation(), interp_scale);
00718
00719
00720 tf::Transform interpolated_correction;
00721 interpolated_correction.setOrigin(v_interp);
00722 interpolated_correction.setRotation(q_interp);
00723
00724
00725 tf::Transform frame_pose_prev;
00726 tf::poseMsgToTF(path_msg_.poses[f_idx].pose, frame_pose_prev);
00727
00728
00729 tf::Transform frame_motion_prev = kf_pose_a_prev.inverse() * frame_pose_prev;
00730
00731
00732 tf::Transform interpolated_motion = frame_motion_prev * interpolated_correction;
00733
00734
00735 path_new[f_idx] = keyframe_a.pose * eigenAffineFromTf(interpolated_motion);
00736 }
00737 }
00738
00739
00740 const rgbdtools::RGBDKeyframe& last_kf = keyframes_[kf_size - 1];
00741
00742 tf::Transform last_kf_pose_prev;
00743 tf::poseMsgToTF(path_msg_.poses[last_kf.index].pose, last_kf_pose_prev);
00744
00745
00746 for (int f_idx = last_kf.index; f_idx < f_size; ++f_idx)
00747 {
00748
00749 tf::Transform frame_pose_prev;
00750 tf::poseMsgToTF(path_msg_.poses[f_idx].pose, frame_pose_prev);
00751
00752
00753 tf::Transform frame_motion_prev = last_kf_pose_prev.inverse() * frame_pose_prev;
00754
00755
00756 path_new[f_idx] = last_kf.pose * eigenAffineFromTf(frame_motion_prev);
00757 }
00758
00759
00760 pathEigenAffineToROS(path_new, path_msg_);
00761 }
00762
00763
00764 bool KeyframeMapper::savePcdMap(const std::string& path)
00765 {
00766 PointCloudT pcd_map;
00767 buildPcdMap(pcd_map);
00768
00769
00770 pcl::PCDWriter writer;
00771 int result_pcd = writer.writeBinary<PointT>(path, pcd_map);
00772
00773 if (result_pcd < 0) return false;
00774 else return true;
00775 }
00776
00777 void KeyframeMapper::buildPcdMap(PointCloudT& map_cloud)
00778 {
00779 PointCloudT::Ptr aggregate_cloud(new PointCloudT());
00780 aggregate_cloud->header.frame_id = fixed_frame_;
00781
00782
00783 for (unsigned int kf_idx = 0; kf_idx < keyframes_.size(); ++kf_idx)
00784 {
00785 const rgbdtools::RGBDKeyframe& keyframe = keyframes_[kf_idx];
00786
00787 PointCloudT cloud;
00788 keyframe.constructDensePointCloud(cloud, max_range_, max_stdev_);
00789
00790 PointCloudT cloud_tf;
00791 pcl::transformPointCloud(cloud, cloud_tf, keyframe.pose);
00792 cloud_tf.header.frame_id = fixed_frame_;
00793
00794 *aggregate_cloud += cloud_tf;
00795 }
00796
00797
00798 pcl::VoxelGrid<PointT> vgf;
00799 vgf.setInputCloud(aggregate_cloud);
00800 vgf.setLeafSize(pcd_map_res_, pcd_map_res_, pcd_map_res_);
00801 vgf.setFilterFieldName("z");
00802 vgf.setFilterLimits (-std::numeric_limits<double>::infinity(), max_map_z_);
00803
00804 vgf.filter(map_cloud);
00805 }
00806 void KeyframeMapper::buildFullCloud(PointCloudT& map_cloud)
00807 {
00808 PointCloudT::Ptr aggregate_cloud(new PointCloudT());
00809 aggregate_cloud->header.frame_id = fixed_frame_;
00810
00811
00812 for (unsigned int kf_idx = 0; kf_idx < keyframes_.size(); ++kf_idx)
00813 {
00814 const rgbdtools::RGBDKeyframe& keyframe = keyframes_[kf_idx];
00815
00816 PointCloudT cloud;
00817 keyframe.constructDensePointCloud(cloud, max_range_, max_stdev_);
00818
00819 PointCloudT cloud_tf;
00820 pcl::transformPointCloud(cloud, cloud_tf, keyframe.pose);
00821 cloud_tf.header.frame_id = fixed_frame_;
00822
00823 *aggregate_cloud += cloud_tf;
00824 }
00825 map_cloud = *aggregate_cloud;
00826 }
00827 bool KeyframeMapper::saveOctomap(const std::string& path)
00828 {
00829 bool result;
00830
00831 if (octomap_with_color_)
00832 {
00833 octomap::ColorOcTree tree(octomap_res_);
00834 buildColorOctomap(tree);
00835 result = tree.write(path);
00836 }
00837 else
00838 {
00839 octomap::OcTree tree(octomap_res_);
00840 buildOctomap(tree);
00841 result = tree.write(path);
00842 }
00843
00844 return result;
00845 }
00846
00847 void KeyframeMapper::buildOctomap(octomap::OcTree& tree)
00848 {
00849 ROS_INFO("Building Octomap...");
00850
00851 octomap::point3d sensor_origin(0.0, 0.0, 0.0);
00852
00853 for (unsigned int kf_idx = 0; kf_idx < keyframes_.size(); ++kf_idx)
00854 {
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871 PointCloudT cloud;
00872 buildFullCloud(cloud);
00873 octomap::Pointcloud octomap_cloud;
00874 for (unsigned int pt_idx = 0; pt_idx < cloud.points.size(); ++pt_idx)
00875 {
00876 const PointT& p = cloud.points[pt_idx];
00877 if (!std::isnan(p.z) && p.z < max_map_z_)
00878 octomap_cloud.push_back(p.x, p.y, p.z);
00879 }
00880 tree.insertScan(octomap_cloud,sensor_origin);
00881 }
00882 }
00883
00884 void KeyframeMapper::buildColorOctomap(octomap::ColorOcTree& tree)
00885 {
00886 ROS_INFO("Building Octomap with color...");
00887
00888 octomap::point3d sensor_origin(0.0, 0.0, 0.0);
00889
00890 for (unsigned int kf_idx = 0; kf_idx < keyframes_.size(); ++kf_idx)
00891 {
00892 ROS_INFO("Processing keyframe %u", kf_idx);
00893 const rgbdtools::RGBDKeyframe& keyframe = keyframes_[kf_idx];
00894
00895
00896 PointCloudT::Ptr cloud_unf(new PointCloudT());
00897 keyframe.constructDensePointCloud(*cloud_unf, max_range_, max_stdev_);
00898
00899
00900 pcl::transformPointCloud(*cloud_unf, *cloud_unf, keyframe.pose);
00901 PointCloudT cloud;
00902 pcl::PassThrough<PointT> pass;
00903 pass.setInputCloud (cloud_unf);
00904 pass.setFilterFieldName ("z");
00905 pass.setFilterLimits (-std::numeric_limits<double>::infinity(), max_map_z_);
00906 pass.filter(cloud);
00907 pcl::transformPointCloud(cloud, cloud, keyframe.pose.inverse());
00908
00909 octomap::pose6d frame_origin = poseTfToOctomap(tfFromEigenAffine(keyframe.pose));
00910
00911
00912 octomap::Pointcloud octomap_cloud;
00913 for (unsigned int pt_idx = 0; pt_idx < cloud.points.size(); ++pt_idx)
00914 {
00915 const PointT& p = cloud.points[pt_idx];
00916 if (!std::isnan(p.z))
00917 octomap_cloud.push_back(p.x, p.y, p.z);
00918 }
00919
00920
00921 tree.insertScan(octomap_cloud, sensor_origin, frame_origin);
00922
00923
00924 PointCloudT cloud_tf;
00925 pcl::transformPointCloud(cloud, cloud_tf, keyframe.pose);
00926 for (unsigned int pt_idx = 0; pt_idx < cloud_tf.points.size(); ++pt_idx)
00927 {
00928 const PointT& p = cloud_tf.points[pt_idx];
00929 if (!std::isnan(p.z))
00930 {
00931 octomap::point3d endpoint(p.x, p.y, p.z);
00932 octomap::ColorOcTreeNode* n = tree.search(endpoint);
00933 if (n) n->setColor(p.r, p.g, p.b);
00934 }
00935 }
00936
00937 tree.updateInnerOccupancy();
00938 }
00939 }
00940
00941 void KeyframeMapper::publishPath()
00942 {
00943 path_msg_.header.frame_id = fixed_frame_;
00944 path_pub_.publish(path_msg_);
00945 }
00946
00947 bool KeyframeMapper::savePath(const std::string& filepath)
00948 {
00949
00950 std::string filename = filepath + "/path.txt";
00951 std::ofstream file(filename.c_str());
00952 if (!file.is_open()) return false;
00953
00954 file << "# index seq stamp.sec stamp.nsec x y z qx qy qz qw" << std::endl;
00955
00956 for (unsigned int idx = 0; idx < path_msg_.poses.size(); ++idx)
00957 {
00958 const geometry_msgs::PoseStamped& pose = path_msg_.poses[idx];
00959
00960 file << idx << " "
00961 << pose.header.seq << " "
00962 << pose.header.stamp.sec << " "
00963 << pose.header.stamp.nsec << " "
00964 << pose.pose.position.x << " "
00965 << pose.pose.position.y << " "
00966 << pose.pose.position.z << " "
00967 << pose.pose.orientation.x << " "
00968 << pose.pose.orientation.y << " "
00969 << pose.pose.orientation.z << " "
00970 << pose.pose.orientation.w << std::endl;
00971 }
00972
00973 file.close();
00974
00975 return true;
00976 }
00977
00978 bool KeyframeMapper::savePathTUMFormat(const std::string& filepath)
00979 {
00980
00981 std::string filename = filepath + "/path.tum.txt";
00982 std::ofstream file(filename.c_str());
00983 if (!file.is_open()) return false;
00984
00985 file << "# stamp x y z qx qy qz qw" << std::endl;
00986
00987 for (unsigned int idx = 0; idx < path_msg_.poses.size(); ++idx)
00988 {
00989 const geometry_msgs::PoseStamped& pose = path_msg_.poses[idx];
00990
00991 file << pose.header.stamp.sec << "."
00992 << pose.header.stamp.nsec << " "
00993 << pose.pose.position.x << " "
00994 << pose.pose.position.y << " "
00995 << pose.pose.position.z << " "
00996 << pose.pose.orientation.x << " "
00997 << pose.pose.orientation.y << " "
00998 << pose.pose.orientation.z << " "
00999 << pose.pose.orientation.w << std::endl;
01000 }
01001
01002 file.close();
01003
01004 return true;
01005 }
01006
01007 bool KeyframeMapper::loadPath(const std::string& filepath)
01008 {
01009 path_msg_.poses.clear();
01010
01011
01012 std::string filename = filepath + "/path.txt";
01013 std::ifstream file(filename.c_str());
01014 if (!file.is_open()) return false;
01015
01016 std::string line;
01017
01018
01019 getline(file, line);
01020
01021
01022 while(std::getline(file, line))
01023 {
01024 std::istringstream is(line);
01025
01026
01027 geometry_msgs::PoseStamped pose;
01028 pose.header.frame_id = fixed_frame_;
01029 int idx;
01030
01031 is >> idx
01032 >> pose.header.seq
01033 >> pose.header.stamp.sec
01034 >> pose.header.stamp.nsec
01035 >> pose.pose.position.x
01036 >> pose.pose.position.y
01037 >> pose.pose.position.z
01038 >> pose.pose.orientation.x
01039 >> pose.pose.orientation.y
01040 >> pose.pose.orientation.z
01041 >> pose.pose.orientation.w;
01042
01043
01044 path_msg_.poses.push_back(pose);
01045 }
01046
01047 file.close();
01048 return true;
01049 }
01050
01051 }