00001
00064 #define HAS_RGB 1
00065
00066
00067
00068
00069
00070
00071 #include <sstream>
00072 #include <fstream>
00073
00074
00075 #include <ros/ros.h>
00076 #include <pluginlib/class_list_macros.h>
00077 #include <nodelet/nodelet.h>
00078 #include <tf_conversions/tf_eigen.h>
00079 #include <tf/transform_broadcaster.h>
00080 #include <actionlib/server/simple_action_server.h>
00081 #include <pcl/point_types.h>
00082 #define PCL_MINOR (PCL_VERSION[2] - '0')
00083
00084 #include <pcl/filters/passthrough.h>
00085 #include <pcl_ros/transforms.h>
00086 #include <pcl_ros/point_cloud.h>
00087 #include <tf/transform_listener.h>
00088 #include <tf_conversions/tf_kdl.h>
00089 #include <pcl/io/pcd_io.h>
00090 #include <pcl_conversions/pcl_conversions.h>
00091 #include <visualization_msgs/Marker.h>
00092 #include "cob_3d_registration/RegistrationPCD.h"
00093 #include "cob_3d_registration/Parameterlist.h"
00094 #include "cob_3d_registration/EvaluationResult.h"
00095 #include "parameters/parameters_bag.h"
00096
00097 #include <sensor_msgs/CameraInfo.h>
00098
00099 #include <cob_3d_registration/registration_icp.h>
00100
00101 #include <vtkCommand.h>
00102 #include <pcl/features/feature.h>
00103 #ifndef GICP_ENABLE
00104 #include <cob_3d_registration/registration_icp_moments.h>
00105 #include <cob_3d_registration/registration_icp_fpfh.h>
00106 #include <cob_3d_registration/registration_icp_narf.h>
00107
00108
00109
00110 #include <opencv/cv.h>
00111
00112 #include <cob_3d_registration/registration_icp_edges.h>
00113 #include <cob_3d_registration/registration_info.h>
00114
00115 #endif
00116
00117 #include <pcl/filters/voxel_grid.h>
00118 #include <cob_3d_registration/preprocessing/kinect_error.h>
00119
00120 #include <cv_bridge/cv_bridge.h>
00121 #include <sys/stat.h>
00122
00123 #include <cob_3d_registration/measurements/measure.h>
00124 #include <cob_srvs/Trigger.h>
00125 #include <cob_3d_mapping_msgs/TriggerAction.h>
00126
00127 #ifdef PCL_VERSION_COMPARE
00128 #include <pcl/point_traits.h>
00129 #include <pcl/kdtree/kdtree_flann.h>
00130 #include <pcl/common/eigen.h>
00131 #include <pcl/registration/correspondence_estimation.h>
00132 #else
00133 #include <pcl/ros/point_traits.h>
00134 #endif
00135
00136
00137
00138
00139
00140
00141 using namespace tf;
00142 #define SHOW_MAP 0
00143
00145 class MemoryOperator
00146 {
00147 measurement_tools::MemoryUsage mu_;
00148 int max_used_;
00149 bool run_, running_;
00150 public:
00151 MemoryOperator():
00152 max_used_(0), run_(true), running_(false)
00153 {
00154 }
00155
00156 void halt() {
00157 run_=false;
00158 }
00159
00160 void wait() {
00161 ROS_INFO("halt");
00162 while(running_) run_=false;
00163 ROS_INFO("halt");
00164 }
00165
00166 int getKB() {
00167 return max_used_;
00168 }
00169
00170 void run() {
00171 running_ = true;
00172 while(run_) {
00173 int m = mu_.getKB();
00174 max_used_ = std::max(m, max_used_);
00175 usleep(10000);
00176 }
00177 running_=false;
00178 }
00179 };
00180
00181
00182
00183 class RegistrationNodelet : public nodelet::Nodelet
00184 {
00185 #if HAS_RGB
00186 typedef pcl::PointXYZRGB Point;
00187 #else
00188 typedef pcl::PointXYZ Point;
00189 #endif
00190
00191 public:
00192
00193 RegistrationNodelet():
00194 ctr_(0), reg_(NULL), is_running_(false)
00195 {
00196
00197 }
00198
00199 RegistrationNodelet(bool dummy):
00200 ctr_(0), reg_(NULL), is_running_(false)
00201 {
00202 }
00203
00204
00205
00206 ~RegistrationNodelet()
00207 {
00209 delete reg_;
00210 }
00211
00219 void
00220 onInit()
00221 {
00222
00223 parameters_.setNodeHandle(n_);
00224 n_ = getNodeHandle();
00225
00226 parameters_.addParameter("world_frame_id");
00227 if(!parameters_.getParam("world_frame_id",world_id_))
00228 world_id_="/map";
00229
00230 parameters_.addParameter("corrected_frame_id");
00231 if(!parameters_.getParam("corrected_frame_id",corrected_id_))
00232 corrected_id_="/camera_registered";
00233
00234
00235 parameters_.addParameter("algo");
00236 parameters_.addParameter("voxelsize");
00237
00238
00239 parameters_.addParameter("max_iterations");
00240 parameters_.addParameter("corr_dist");
00241 parameters_.addParameter("trf_epsilon");
00242 parameters_.addParameter("outlier_rejection_threshold");
00243 parameters_.addParameter("use_only_last_refrence");
00244
00245
00246
00247 parameters_.addParameter("moments_radius");
00248
00249
00250 parameters_.addParameter("fpfh_radius");
00251
00252
00253 parameters_.addParameter("edge_radius");
00254 parameters_.addParameter("threshold");
00255 parameters_.addParameter("distance_threshold");
00256
00257
00258 parameters_.addParameter("use_icp");
00259 parameters_.addParameter("threshold_diff");
00260 parameters_.addParameter("threshold_step");
00261 parameters_.addParameter("min_info");
00262 parameters_.addParameter("max_info");
00263 parameters_.addParameter("always_relevant_changes");
00264
00265 reset_server_ = n_.advertiseService("reset", &RegistrationNodelet::reset, this);
00266 camera_info_sub_ = n_.subscribe("camera_info", 1, &RegistrationNodelet::cameraInfoSubCallback, this);
00267 point_cloud_pub_aligned_ = n_.advertise<pcl::PointCloud<Point> >("point_cloud2_aligned",1);
00268 keyframe_trigger_server_ = n_.advertiseService("trigger_keyframe", &RegistrationNodelet::onKeyframeCallback, this);
00269 as_= boost::shared_ptr<actionlib::SimpleActionServer<cob_3d_mapping_msgs::TriggerAction> >(new actionlib::SimpleActionServer<cob_3d_mapping_msgs::TriggerAction>(n_, "trigger_mapping", boost::bind(&RegistrationNodelet::actionCallback, this, _1), false));
00270 as_->start();
00271
00272 marker_pub_ = n_.advertise<pcl::PointCloud<Point> >("result_marker",1);
00273
00274
00275
00276
00277
00278 buildAlgo();
00279
00280
00281
00282 }
00283
00294 bool
00295 reset(cob_srvs::Trigger::Request &req,
00296 cob_srvs::Trigger::Response &res)
00297 {
00298
00299 ROS_INFO("Resetting transformation...");
00300 if(reg_) buildAlgo();
00301 return true;
00302 }
00303
00304 double _time_;
00315 void
00316 pointCloudSubCallback(const pcl::PointCloud<Point>::Ptr& pc_in)
00317 {
00318 pc_frame_id_=pc_in->header.frame_id;
00319
00320 if(reg_==0 || pc_in==0 || pc_in->size()<1 || !is_running_)
00321 return;
00322
00323 reg_->setInputOginalCloud(pc_in);
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 if(do_register(*pc_in,cv_bridge::CvImagePtr(),NULL)||ctr_==0) {
00348 if(point_cloud_pub_aligned_.getNumSubscribers()>0) {
00349 pcl::PointCloud<Point> pc;
00350 pc.header.frame_id = pc_in->header.frame_id;
00351 pcl::transformPointCloud(*pc_in,pc,reg_->getTransformation());
00352 point_cloud_pub_aligned_.publish(pc);
00353 }
00354
00355 StampedTransform transform;
00356 Eigen::Affine3d af;
00357 af.matrix()=reg_->getTransformation().cast<double>();
00358
00359 tf::transformEigenToTF(af,transform);
00360
00361 std_msgs::Header header;
00362 pcl_conversions::fromPCL(pc_in->header, header);
00363 tf_br_.sendTransform(tf::StampedTransform(transform, header.stamp, world_id_, corrected_id_));
00364
00365 ROS_WARN("registration successful");
00366 }
00367 else
00368 ROS_WARN("registration not successful");
00369 ctr_++;
00370
00371 if(marker_pub_.getNumSubscribers()>0)
00372 {
00373 std::string s_algo;
00374 if(parameters_.getParam("algo",s_algo) && s_algo=="info") {
00375 pcl::PointCloud<Point> result = *((cob_3d_registration::Registration_Infobased<Point>*)reg_)->getMarkers2();
00376 result.header=pc_in->header;
00377 marker_pub_.publish(result);
00378 }
00379 }
00380 }
00381
00396 bool onKeyframeCallback(cob_srvs::Trigger::Request &req,
00397 cob_srvs::Trigger::Response &res)
00398 {
00399 res.success.data = false;
00400
00401 if(reg_==0 || pc_frame_id_.size()<1 || !is_running_)
00402 return true;
00403
00404 StampedTransform transform;
00405 try
00406 {
00407 std::stringstream ss2;
00408 tf_listener_.waitForTransform(world_id_, pc_frame_id_, ros::Time(0), ros::Duration(0.1));
00409 tf_listener_.lookupTransform(world_id_, pc_frame_id_, ros::Time(0), transform);
00410
00411 ROS_DEBUG("Registering new point cloud");
00412
00413 Eigen::Affine3d af;
00414 tf::transformTFToEigen(transform, af);
00415 reg_->setOdometry(af.matrix().cast<float>());
00416 reg_->setMoved(true);
00417
00418 }
00419 catch (tf::TransformException ex)
00420 {
00421 ROS_ERROR("[registration] : %s",ex.what());
00422 return false;
00423 }
00424
00425 res.success.data = true;
00426 return true;
00427 }
00428
00438 void
00439 actionCallback(const cob_3d_mapping_msgs::TriggerGoalConstPtr &goal)
00440 {
00441 cob_3d_mapping_msgs::TriggerResult result;
00442 if(goal->start && !is_running_)
00443 {
00444 ROS_INFO("Starting mapping...");
00445 point_cloud_sub_ = n_.subscribe("point_cloud2", 1, &RegistrationNodelet::pointCloudSubCallback, this);
00446
00447
00448 is_running_ = true;
00449 }
00450 else if(!goal->start && is_running_)
00451 {
00452 ROS_INFO("Stopping mapping...");
00453 point_cloud_sub_.shutdown();
00454
00455
00456 is_running_ = false;
00457 }
00458 as_->setSucceeded(result);
00459 }
00460
00465 void createParamters(const std::string &algo) {
00466
00467
00468 if(algo.find("icp")==0 || algo.find("gicp")==0 || algo=="fastslam") {
00469
00470
00471 parameters_.createParam(n_,"voxelsize",0.04).setMin(0.04).setMax(0.041).setStep(10.02);
00472 }
00473
00474
00475 if(algo.find("icp")==0 || algo.find("gicp")==0) {
00476 parameters_.createParam(n_,"max_iterations",40).setMin(40).setMax(41).setStep(30);
00477 parameters_.createParam(n_,"corr_dist",0.2).setMin(0.2).setMax(0.3).setStep(0.2);
00478 parameters_.createParam(n_,"trf_epsilon",3.5).setMin(3.5).setMax(3.6).setStep(1.);
00479 parameters_.createParam(n_,"outlier_rejection_threshold",0.1).setMax(0.3).setStep(0.1);
00480 parameters_.createParam(n_,"use_only_last_refrence",1).setMax(1).setStep(2);
00481 }
00482
00483
00484 if(algo=="icp_moments") {
00485 parameters_.setParam("voxelsize_min",0.04);
00486 parameters_.createParam(n_,"moments_radius",0.05).setMax(0.2).setStep(0.05);
00487 }
00488
00489
00490 if(algo=="icp_fpfh") {
00491 parameters_.setParam("voxelsize_min",0.04);
00492 parameters_.createParam(n_,"fpfh_radius",0.05).setMax(0.2).setStep(0.05);
00493 }
00494
00495
00496 if(algo=="icp_edges") {
00497
00498 parameters_.createParam(n_,"threshold",0.45).setMin(0.45).setMax(0.456).setStep(0.1);
00499
00500 }
00501
00502
00503 if(algo=="info") {
00504 parameters_.createParam(n_,"use_icp",1).setMax(1).setStep(1);
00505 }
00506 }
00507
00512 void publishParameters() {
00513 ros::ServiceClient client = n_.serviceClient< ::cob_3d_registration::Parameterlist>("paramterlist");
00514 ::cob_3d_registration::Parameterlist srv;
00515
00516 const std::map<std::string, int> &is = parameters_.getInts();
00517 for(std::map<std::string, int>::const_iterator it=is.begin(); it!=is.end(); it++) {
00518 std::ostringstream s;
00519 s<<it->second;
00520 srv.request.types.push_back("int");
00521 srv.request.names.push_back(it->first);
00522 srv.request.values.push_back(s.str());
00523 }
00524
00525 const std::map<std::string, double> &ds = parameters_.getDoubles();
00526 for(std::map<std::string, double>::const_iterator it=ds.begin(); it!=ds.end(); it++) {
00527 std::ostringstream s;
00528 s<<it->second;
00529 srv.request.types.push_back("double");
00530 srv.request.names.push_back(it->first);
00531 srv.request.values.push_back(s.str());
00532 }
00533
00534 const std::map<std::string, std::string> &ss = parameters_.getStrings();
00535 for(std::map<std::string, std::string>::const_iterator it=ss.begin(); it!=ss.end(); it++) {
00536 std::ostringstream s;
00537 s<<it->second;
00538 srv.request.types.push_back("string");
00539 srv.request.names.push_back(it->first);
00540 srv.request.values.push_back(s.str());
00541 }
00542
00543 bool b=false;
00544 int tries=0;
00545 do {
00546 b=client.call(srv);
00547 if(!b) sleep(2);
00548 ++tries;
00549 } while(!b && tries<5);
00550
00551 if (b)
00552 {
00553 ROS_DEBUG("published paramters successfully");
00554 }
00555 else
00556 {
00557 ROS_ERROR("Failed to call paramterlist service");
00558 }
00559 }
00560
00565 void buildAlgo()
00566 {
00567 delete reg_;
00568 reg_=NULL;
00569
00570
00571 int e_algo=E_ALGO_ICP_EDGES;
00572
00573
00574 std::string s_algo;
00575 if(parameters_.getParam("algo",s_algo)) {
00576 if(s_algo=="icp")
00577 e_algo=E_ALGO_ICP;
00578 else if(s_algo=="icp lm")
00579 e_algo=E_ALGO_ICP_LM;
00580 else if(s_algo=="gicp")
00581 e_algo=E_ALGO_GICP;
00582 else if(s_algo=="icp_moments")
00583 e_algo=E_ALGO_ICP_MOMENTS;
00584 else if(s_algo=="icp_fpfh")
00585 e_algo=E_ALGO_ICP_FPFH;
00586 else if(s_algo=="icp_narf")
00587 e_algo=E_ALGO_ICP_NARF;
00588
00589
00590 else if(s_algo=="icp_edges")
00591 e_algo=E_ALGO_ICP_EDGES;
00592 else if(s_algo=="info")
00593 e_algo=E_ALGO_INFO;
00594 else if(s_algo=="cor")
00595 e_algo=E_ALGO_COR;
00596 else
00597 ROS_WARN("algo %s not found", s_algo.c_str());
00598
00599 }
00600 else
00601 ROS_WARN("using algo icp");
00602
00603
00604 ROS_INFO("init %s", s_algo.c_str());
00605 switch(e_algo) {
00606 case E_ALGO_ICP:
00607 reg_ = new cob_3d_registration::Registration_ICP<Point>();
00608
00609 setSettings_ICP((cob_3d_registration::Registration_ICP<Point>*)reg_);
00610 break;
00611
00612 case E_ALGO_GICP:
00613 reg_ = new cob_3d_registration::Registration_ICP<Point>();
00614
00615 setSettings_ICP((cob_3d_registration::Registration_ICP<Point>*)reg_);
00616 ((cob_3d_registration::Registration_ICP<Point>*)reg_)->setUseGICP(true);
00617
00618 break;
00619
00620 case E_ALGO_ICP_LM:
00621 reg_ = new cob_3d_registration::Registration_ICP<Point>();
00622 ((cob_3d_registration::Registration_ICP<Point>*)reg_)->setNonLinear(true);
00623
00624 setSettings_ICP((cob_3d_registration::Registration_ICP<Point>*)reg_);
00625 break;
00626
00627 case E_ALGO_ICP_MOMENTS:
00628 #ifndef GICP_ENABLE
00629 reg_ = new cob_3d_registration::Registration_ICP_Moments<Point>();
00630
00631 setSettings_ICP_Moments((cob_3d_registration::Registration_ICP_Moments<Point>*)reg_);
00632 #else
00633 ROS_ERROR("not supported");
00634 #endif
00635 break;
00636
00637 case E_ALGO_ICP_FPFH:
00638 #ifndef GICP_ENABLE
00639 reg_ = new cob_3d_registration::Registration_ICP_FPFH<Point>();
00640
00641 setSettings_ICP_FPFH((cob_3d_registration::Registration_ICP_FPFH<Point>*)reg_);
00642 #else
00643 ROS_ERROR("not supported");
00644 #endif
00645 break;
00646
00647 case E_ALGO_ICP_NARF:
00648 #ifndef GICP_ENABLE
00649 reg_ = new cob_3d_registration::Registration_ICP_NARF<Point>();
00650
00651 setSettings_ICP_NARF((cob_3d_registration::Registration_ICP_NARF<Point>*)reg_);
00652 #else
00653 ROS_ERROR("not supported");
00654 #endif
00655 break;
00656
00657 case E_ALGO_ICP_EDGES:
00658 #ifndef GICP_ENABLE
00659 #if HAS_RGB
00660 reg_ = new cob_3d_registration::Registration_ICP_Edges<Point>();
00661
00662 setSettings_ICP_Edges((cob_3d_registration::Registration_ICP_Edges<Point>*)reg_);
00663 #endif
00664 #else
00665 ROS_ERROR("not supported");
00666 #endif
00667 break;
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679 case E_ALGO_INFO:
00680 #ifndef GICP_ENABLE
00681 reg_ = new cob_3d_registration::Registration_Infobased<Point>();
00682
00683 setSettings_Info((cob_3d_registration::Registration_Infobased<Point>*)reg_);
00684 #else
00685 ROS_ERROR("not supported");
00686 #endif
00687 break;
00688
00689 case E_ALGO_COR:
00690
00691 #if 0
00692 reg_ = new cob_3d_registration::Registration_Corrospondence<Point>();
00693
00694
00695
00696
00697
00698 #else
00699 ROS_ERROR("not supported");
00700 #endif
00701 break;
00702
00703 }
00704 ROS_INFO("done");
00705
00706 }
00707
00712 bool registerService(::cob_3d_registration::RegistrationPCD::Request &req,
00713 ::cob_3d_registration::RegistrationPCD::Response &res )
00714 {
00715 ROS_INFO("register...");
00716
00717
00718 pcl::PointCloud<Point> pc;
00719 pcl::io::loadPCDFile(req.pcd_fn, pc);
00720
00721 for(int i=0; i<(int)pc.size(); i++) {
00722 if(pc[i].z==0||pc[i].z>10)
00723 pc[i].z=pc[i].y=pc[i].x=std::numeric_limits<float>::quiet_NaN();
00724 }
00725
00726 sensor_msgs::Image img;
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742 cv::Mat img_depth(pc.height, pc.width, CV_16UC1);
00743 #ifdef USE_DEPTH_IMG_
00744 sensor_msgs::Image img_depth;
00745 {
00746 FILE *fp = fopen(req.depth_img_fn.c_str(), "rb");
00747 if(!fp) return false;
00748
00749 struct stat filestatus;
00750 stat(req.img_fn.c_str(), &filestatus );
00751
00752 uint8_t *up = new uint8_t[filestatus.st_size];
00753 fread(up,filestatus.st_size,1,fp);
00754 img_depth.deserialize(up);
00755 delete up;
00756
00757 fclose(fp);
00758 }
00759 #elif 0
00760 cv::Mat cv_pc(pc.height, pc.width, CV_32FC1);
00761 for(int x=0; x<pc.width; x++)
00762 for(int y=0; y<pc.height; y++)
00763 *(cv_pc.ptr<float>(y)+x) = pc.points[x+y*pc.width].z;
00764
00765 ipa_Utils::ConvertToShowImage(cv_pc, img_depth, 1, 0., 5.);
00766 #else
00767 for(int x=0; x<(int)pc.width; x++)
00768 for(int y=0; y<(int)pc.height; y++) {
00769 int raw_depth = std::max(0, (int)(((1./pc.points[x+y*pc.width].z)-3.3309495161)/-0.0030711016));
00770 *(img_depth.ptr<unsigned short>(y)+x) = raw_depth<2048?raw_depth:0;
00771 }
00772 #endif
00773
00774 cv_bridge::CvImagePtr cv_ptr;
00775 try
00776 {
00777 cv_ptr = cv_bridge::toCvCopy(img, "rgb8");
00778 }
00779 catch (cv_bridge::Exception& e)
00780 {
00781 ROS_ERROR("cv_bridge exception: %s", e.what());
00782 return false;
00783 }
00784
00785 cv_bridge::CvImagePtr cv_ptr_depth;
00786 #ifdef USE_DEPTH_IMG_
00787 try
00788 {
00789 cv_ptr_depth = cv_bridge::toCvCopy(img_depth, "rgb8");
00790 img_depth = cv_ptr_depth->image;
00791 }
00792 catch (cv_bridge::Exception& e)
00793 {
00794 ROS_ERROR("cv_bridge exception: %s", e.what());
00795 return false;
00796 }
00797 #endif
00798
00799 reg_->setInputOginalCloud(boost::shared_ptr<const pcl::PointCloud<Point> >(new pcl::PointCloud<Point>(pc)));
00800
00801 measurement_tools::PrecisionStopWatchAll psw;
00802 do_preprocess(pc,cv_ptr,img_depth);
00803 ROS_INFO("do_preprocess took %f", psw.precisionStop());
00804 psw.precisionStart();
00805 do_register(pc,cv_ptr,&img_depth);
00806 ROS_INFO("do_register took %f", psw.precisionStop());
00807
00808 publish_results();
00809
00810
00811 #if SHOW_MAP
00812
00813 if(marker_pub_.getNumSubscribers()&®_->getMarkers()) {
00814 for(int i=0; i<reg_->getMarkers()->size(); i++)
00815 #if HAS_RGB
00816 publishMarkerPoint(reg_->getMarkers()->points[i], i, reg_->getMarkers()->points[i].r/255., reg_->getMarkers()->points[i].g/255., reg_->getMarkers()->points[i].b/255.);
00817 #else
00818 publishMarkerPoint(reg_->getMarkers()->points[i], i, 1,0,0);
00819 #endif
00820 }
00821
00822 #ifndef GICP_ENABLE
00823 std::string s_algo;
00824 if(parameters_.getParam("algo",s_algo) && s_algo=="info") {
00825 pcl::PointCloud<Point> result = *((cob_3d_registration::Registration_Infobased<Point>*)reg_)->getMarkers2();
00826 result.header.frame_id="/head_cam3d_frame";
00827 marker2_pub_.publish(result);
00828
00829 for(int i=0; i<((cob_3d_registration::Registration_Infobased<Point>*)reg_)->getSource().size(); i++)
00830 publishLineMarker( ((cob_3d_registration::Registration_Infobased<Point>*)reg_)->getSource().points[i].getVector3fMap(), ((cob_3d_registration::Registration_Infobased<Point>*)reg_)->getTarget().points[i].getVector3fMap(), -i);
00831 }
00832 else if(parameters_.getParam("algo",s_algo) && s_algo=="cor") {
00833 #ifdef PCL_VERSION_COMPARE
00834 pcl::Correspondences cor;
00835 #else
00836 pcl::registration::Correspondences cor;
00837 #endif
00838 ((Registration_Corrospondence<Point>*)reg_)->getKeypoints()->getCorrespondences(cor);
00839 for(int i=0; i<cor.size(); i++)
00840 publishLineMarker( ((cob_3d_registration::Registration_Corrospondence<Point>*)reg_)->getKeypoints()->getSourcePoints()->points[cor[i].indexQuery].getVector3fMap(), ((cob_3d_registration::Registration_Corrospondence<Point>*)reg_)->getKeypoints()->getTargetPoints()->points[cor[i].indexMatch].getVector3fMap(), -i);
00841 }
00842 #endif
00843
00844 if(registration_result_) {
00845 pcl::PointCloud<Point> result;
00846 pcl::io::loadPCDFile(req.pcd_fn, result);
00847 static pcl::PointCloud<Point> map;
00848 pcl::transformPointCloud(result,result,reg_->getTransformation());
00849 map.header.frame_id = result.header.frame_id;
00850 map += result;
00851
00852 pcl::VoxelGrid<Point> voxel;
00853 voxel.setInputCloud(map.makeShared());
00854 float voxelsize=0.04;
00855 voxel.setLeafSize(voxelsize,voxelsize,voxelsize);
00856 voxel.filter(map);
00857
00858 map.header.frame_id="/head_cam3d_link";
00859 point_cloud_pub_.publish(map);
00860
00861 {
00862 std::string s_algo;
00863 parameters_.getParam("algo",s_algo);
00864 pcl::io::savePCDFileBinary("/home/goa-jh/Dropbox/"+s_algo+"_map.pcd",map);
00865 }
00866 }
00867 else
00868 ROS_INFO("not successful");
00869 #endif
00870
00871 return true;
00872 }
00873
00874
00875 ros::NodeHandle n_;
00876 ros::Time stamp_;
00877
00878
00879 protected:
00880
00884 void publish_results()
00885 {
00886 ros::ServiceClient client = n_.serviceClient< ::cob_3d_registration::EvaluationResult>("evaluate");
00887 ::cob_3d_registration::EvaluationResult srv;
00888
00889 srv.request.duration = duration_;
00890 srv.request.memory = memory_usage_kb_;
00891 srv.request.state = registration_result_;
00892
00893 Eigen::Matrix4f T = reg_->getTransformation(), T2=Eigen::Matrix4f::Identity();
00894
00895 Eigen::Vector3f Z;
00896 Z(0)=Z(1)=0.f;Z(2)=1.f;
00897 Eigen::AngleAxisf aa(M_PI,Z);
00898 for(int i=0; i<3; i++)
00899 for(int j=0; j<3; j++)
00900 T2(i,j)=aa.toRotationMatrix()(i,j);
00901 T=T2*T;
00902
00903 for(int i=0; i<4; i++)
00904 for(int j=0; j<4; j++)
00905 srv.request.transformation.push_back( T(i,j) );
00906
00907 if (client.call(srv))
00908 {
00909 ROS_DEBUG("published paramters successfully");
00910 }
00911 else
00912 {
00913 ROS_ERROR("Failed to call paramterlist service");
00914 }
00915 }
00916
00921 bool do_preprocess(pcl::PointCloud<Point> &pc, cv_bridge::CvImagePtr &cv_ptr, cv::Mat &img_depth) {
00922
00923 #if NEED_GAZEBO_BUG_
00924
00925 for(int i=0; i<pc.size(); i++) {
00926 if(pc.points[i].z>5||pc.points[i].z<0.5) {
00927 pc.points.erase(pc.points.begin()+i);
00928 --i;
00929 }
00930 }
00931 pc.width=pc.size();
00932 pc.height=1;
00933 #endif
00934
00935 pcl::PassThrough<Point> pass;
00936 pass.setInputCloud (pc.makeShared());
00937 pass.setFilterFieldName ("z");
00938 pass.setFilterLimits (0.0, 6.0);
00939 pass.filter (pc);
00940
00941 int simulate_distortion;
00942 if(parameters_.getParam("simulate_distortion",simulate_distortion)&&simulate_distortion) {
00943 ROS_INFO("simulationg distortion");
00944
00945 preprocessing::KinectErrorGenerator<Point> filter;
00946 filter.setInputCloud(pc.makeShared());
00947 filter.filter(pc);
00948 }
00949
00950 double voxelsize;
00951 if(parameters_.getParam("voxelsize",voxelsize) && voxelsize>0.f) {
00952 ROS_INFO("voxelize with %f", voxelsize);
00953
00954 pcl::VoxelGrid<Point> voxel;
00955 voxel.setInputCloud(pc.makeShared());
00956 voxel.setLeafSize(voxelsize,voxelsize,voxelsize);
00957 voxel.filter(pc);
00958
00959 ROS_INFO("resulting pc with %d points", (int)pc.size());
00960
00961 if(((cob_3d_registration::Registration_ICP<Point>*)reg_)->getMap()) {
00962 voxel.setInputCloud(((cob_3d_registration::Registration_ICP<Point>*)reg_)->getMap());
00963 voxel.setLeafSize(voxelsize,voxelsize,voxelsize);
00964 voxel.filter(*reg_->getMap());
00965 }
00966
00967 }
00968
00969 return true;
00970 }
00971
00978 bool do_register(const pcl::PointCloud<Point> &pc, const cv_bridge::CvImagePtr &cv_ptr, cv::Mat *img_depth) {
00979 if(reg_==NULL)
00980 return false;
00981
00982 if(cv_ptr) reg_->setInputImage(boost::shared_ptr<const cv::Mat>(new cv::Mat(cv_ptr->image)));
00983 if(img_depth) reg_->setInputDepthImage(boost::shared_ptr<const cv::Mat>(new cv::Mat(*img_depth)));
00984 reg_->setInputCloud(pc.makeShared());
00985
00986
00987
00988
00989
00990
00991 bool ret = reg_->compute();
00992
00993 registration_result_ = ret;
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010 return ret;
01011 }
01012
01013 void
01014 cameraInfoSubCallback(sensor_msgs::CameraInfo::ConstPtr ci)
01015 {
01016 std::string s_algo;
01017 if(parameters_.getParam("algo",s_algo) && s_algo=="info")
01018
01019 ((cob_3d_registration::Registration_Infobased<Point>*)reg_)->setKinectParameters(
01020 ci->P[0],
01021 ci->P[2],
01022 ci->P[6]
01023 );
01024 }
01025
01026 ros::ServiceServer reset_server_;
01027 ros::Subscriber camera_info_sub_;
01028 ros::Publisher point_cloud_pub_aligned_;
01029 ros::ServiceServer keyframe_trigger_server_;
01030 ros::Subscriber point_cloud_sub_;
01031 ros::ServiceServer register_ser_;
01032 tf::TransformBroadcaster tf_br_;
01033 tf::TransformListener tf_listener_;
01034 ros::Publisher point_cloud_pub_;
01035 ros::Publisher marker2_pub_;
01036 ros::Publisher marker_pub_;
01037 boost::shared_ptr<actionlib::SimpleActionServer<cob_3d_mapping_msgs::TriggerAction> > as_;
01038 unsigned int ctr_;
01039
01041 ParameterBucket parameters_;
01042
01044 cob_3d_registration::GeneralRegistration<Point> *reg_;
01045
01046 bool is_running_;
01047
01048
01049
01051 double duration_;
01053 int memory_usage_kb_;
01055 bool registration_result_;
01056
01057 std::string corrected_id_, world_id_, pc_frame_id_;
01058
01059 enum {E_ALGO_ICP=1,E_ALGO_ICP_LM=2,E_ALGO_GICP=3,E_ALGO_ICP_MOMENTS=4,E_ALGO_ICP_FPFH=5, E_ALGO_ICP_NARF=6, E_ALGO_FASTSLAM=7, E_ALGO_ICP_EDGES=8, E_ALGO_INFO=10, E_ALGO_COR=11, E_ALGO_NONE=0};
01060
01061
01062 void setSettings_ICP(cob_3d_registration::Registration_ICP<Point> *pr) {
01063 double d=0.;
01064 int i=0;
01065
01066 if(parameters_.getParam("corr_dist",d))
01067 pr->setCorrDist(d);
01068 if(parameters_.getParam("max_iterations",i))
01069 pr->setMaxIterations(i);
01070 if(parameters_.getParam("trf_epsilon",d))
01071 pr->setTrfEpsilon(pow(10,-d));
01072 if(parameters_.getParam("outlier_rejection_threshold",d))
01073 pr->setOutlierRejectionThreshold(d);
01074 if(parameters_.getParam("use_only_last_refrence",i))
01075 pr->setUseOnlyLastReference(i!=0);
01076 }
01077
01078 #ifndef GICP_ENABLE
01079 void setSettings_ICP_Moments(cob_3d_registration::Registration_ICP_Moments<Point> *pr) {
01080 setSettings_ICP(pr);
01081
01082 double d=0.;
01083
01084 if(parameters_.getParam("moments_radius",d))
01085 pr->setMomentRadius(d);
01086 }
01087 void setSettings_ICP_FPFH(cob_3d_registration::Registration_ICP_FPFH<Point> *pr) {
01088 setSettings_ICP(pr);
01089
01090 double d=0.;
01091
01092 if(parameters_.getParam("fpfh_radius",d))
01093 pr->setFPFHRadius(d);
01094 }
01095 void setSettings_ICP_NARF(cob_3d_registration::Registration_ICP_NARF<Point> *pr) {
01096 setSettings_ICP(pr);
01097 }
01098 void setSettings_ICP_Edges(cob_3d_registration::Registration_ICP_Edges<Point> *pr) {
01099 double d=0.;
01100
01101 if(parameters_.getParam("edge_radius",d))
01102 pr->setRadius(d);
01103 if(parameters_.getParam("threshold",d))
01104 pr->setThreshold(d);
01105 if(parameters_.getParam("distance_threshold",d))
01106 pr->setDisThreshold(d);
01107 setSettings_ICP(pr);
01108 }
01109 void setSettings_Info(cob_3d_registration::Registration_Infobased<Point> *pr) {
01110 int i=0;
01111 double f=0.;
01112
01113
01114
01115
01116 if(parameters_.getParam("threshold_diff",f))
01117 pr->setThresholdDiff(f);
01118 if(parameters_.getParam("threshold_step",f))
01119 ((cob_3d_registration::Registration_Infobased<Point>*)reg_)->setThresholdStep(f);
01120 if(parameters_.getParam("min_info",i))
01121 ((cob_3d_registration::Registration_Infobased<Point>*)reg_)->setMinInfo(i);
01122 if(parameters_.getParam("max_info",i))
01123 ((cob_3d_registration::Registration_Infobased<Point>*)reg_)->setMaxInfo(i);
01124 if(parameters_.getParam("always_relevant_changes",i))
01125 ((cob_3d_registration::Registration_Infobased<Point>*)reg_)->SetAlwaysRelevantChanges(i!=0);
01126 if(parameters_.getParam("check_samples",i))
01127 ((cob_3d_registration::Registration_Infobased<Point>*)reg_)->setCheckBySamples(i!=0);
01128 }
01129 #endif
01130
01131
01132 void publishMarkerPoint(const Point &p, int id, float r, float g, float b, float Size=0.02)
01133 {
01134 if(!marker_pub_.getNumSubscribers())
01135 return;
01136
01137 visualization_msgs::Marker marker;
01138 marker.action = visualization_msgs::Marker::ADD;
01139 marker.type = visualization_msgs::Marker::CUBE;
01140 marker.lifetime = ros::Duration(0);
01141 marker.header.frame_id="/head_cam3d_frame";
01142
01143
01144 marker.pose.orientation.x = 0.0;
01145 marker.pose.orientation.y = 0.0;
01146 marker.pose.orientation.z = 0.0;
01147 marker.pose.orientation.w = 1.0;
01148
01149 marker.scale.x = Size;
01150 marker.scale.y = Size;
01151 marker.scale.z = Size;
01152 marker.color.r = r;
01153 marker.color.g = g;
01154 marker.color.b = b;
01155 marker.color.a = 1.0;
01156
01157 marker.id = id;
01158 marker.pose.position.x = p.x;
01159 marker.pose.position.y = p.y;
01160 marker.pose.position.z = p.z;
01161
01162 marker_pub_.publish(marker);
01163 }
01164
01165 void publishLineMarker(Eigen::Vector3f a, Eigen::Vector3f b, const int id=rand()%111111)
01166 {
01167 visualization_msgs::Marker marker;
01168 marker.action = visualization_msgs::Marker::ADD;
01169 marker.type = visualization_msgs::Marker::LINE_STRIP;
01170 marker.lifetime = ros::Duration(id<0?0:4);
01171 marker.header.frame_id="/head_cam3d_frame";
01172
01173 marker.pose.orientation.x = 0.0;
01174 marker.pose.orientation.y = 0.0;
01175 marker.pose.orientation.z = 0.0;
01176 marker.pose.orientation.w = 1.0;
01177
01178 marker.scale.x = 0.02;
01179 marker.scale.y = 0.02;
01180 marker.scale.z = 0.02;
01181 marker.color.r = 0;
01182 marker.color.g = 1;
01183 marker.color.b = 0;
01184 marker.color.a = 1.0;
01185
01186 marker.id = id;
01187
01188 marker.points.resize(2);
01189
01190 marker.points[0].x = a(0);
01191 marker.points[0].y = a(1);
01192 marker.points[0].z = a(2);
01193
01194 marker.points[1].x = b(0);
01195 marker.points[1].y = b(1);
01196 marker.points[1].z = b(2);
01197
01198 marker_pub_.publish(marker);
01199 }
01200
01201 };
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226 PLUGINLIB_DECLARE_CLASS(cob_3d_registration, RegistrationNodelet, RegistrationNodelet, nodelet::Nodelet)
01227