registration_nodelet.cpp
Go to the documentation of this file.
00001 
00064 #define HAS_RGB 1
00065 
00066 //##################
00067 //#### includes ####
00068 
00069 // standard includes
00070 //--
00071 #include <sstream>
00072 #include <fstream>
00073 
00074 // ROS includes
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 //#include <registration/registration_fastslam.h>
00109 //#include <cob_vision_utils/VisionUtils.h>
00110 #include <opencv/cv.h>
00111 
00112 #include <cob_3d_registration/registration_icp_edges.h>
00113 #include <cob_3d_registration/registration_info.h>
00114 //#include <cob_3d_registration/registration_correspondence.h>
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 //#### node class ####
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   // Constructor
00193   RegistrationNodelet():
00194     ctr_(0), reg_(NULL), is_running_(false)
00195   {
00196     //onInit();
00197   }
00198 
00199   RegistrationNodelet(bool dummy):
00200     ctr_(0), reg_(NULL), is_running_(false)
00201   {
00202   }
00203 
00204 
00205   // Destructor
00206   ~RegistrationNodelet()
00207   {
00209     delete reg_;
00210   }
00211 
00219   void
00220   onInit()
00221   {
00222     //PCLNodelet::onInit();
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"; //default value
00229 
00230     parameters_.addParameter("corrected_frame_id");
00231     if(!parameters_.getParam("corrected_frame_id",corrected_id_))
00232       corrected_id_="/camera_registered"; //default value
00233 
00234     //general
00235     parameters_.addParameter("algo");
00236     parameters_.addParameter("voxelsize");
00237 
00238     //icp
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     //icp moments
00247     parameters_.addParameter("moments_radius");
00248 
00249     //icp fpfh
00250     parameters_.addParameter("fpfh_radius");
00251 
00252     //icp edges
00253     parameters_.addParameter("edge_radius");
00254     parameters_.addParameter("threshold");
00255     parameters_.addParameter("distance_threshold");
00256 
00257     //info
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     //point_cloud_pub_ = n_.advertise<pcl::PointCloud<Point> >("result_pc",1);
00272     marker_pub_ = n_.advertise<pcl::PointCloud<Point> >("result_marker",1);
00273     //point_cloud_sub_ = n_.subscribe("point_cloud2", 1, &RegistrationNodelet::pointCloudSubCallback, this);
00274     //register_ser_ = n_.advertiseService("registration_process", &RegistrationNodelet::registerService, this);
00275     //marker_pub_ = n_.advertise<visualization_msgs::Marker>("markers", 1);
00276 
00277     //after reading params
00278     buildAlgo();
00279 
00280     //say what we are doing here
00281     //publishParameters();
00282   }
00283 
00294   bool
00295   reset(cob_srvs::Trigger::Request &req,
00296         cob_srvs::Trigger::Response &res)
00297   {
00298     //TODO: add mutex
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     /*StampedTransform transform, transform2;
00326     try
00327     {
00328       tf_listener_.waitForTransform(pc_frame_id_, world_id_, pc_in->header.stamp, ros::Duration(0.1));
00329       tf_listener_.lookupTransform(pc_frame_id_, world_id_, pc_in->header.stamp, transform);
00330 
00331       ROS_DEBUG("Registering new point cloud");
00332 
00333       Eigen::Affine3d af;
00334       tf::TransformTFToEigen(transform, af);
00335       ROS_INFO("got odometry");
00336       _time_ = transform.stamp_.toSec();
00337       reg_->setOdometry(af.matrix().cast<float>());
00338     }
00339     catch (tf::TransformException ex)
00340     {
00341       ROS_ERROR("[registration] : %s",ex.what());
00342       return;
00343     }
00344 
00345     ROS_INFO("ts diff %f",pc_in->header.stamp.toSec()-_time_);*/
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       //std::cout<<reg_->getTransformation()<<"\n";
00359       tf::transformEigenToTF(af,transform);
00360       //std::cout << transform.stamp_ << std::endl;
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       //point_cloud_sub_.subscribe(n_, "point_cloud2", 1);
00447       //transform_sub_.subscribe(n_, "transform_reg", 1);
00448       is_running_ = true;
00449     }
00450     else if(!goal->start && is_running_)
00451     {
00452       ROS_INFO("Stopping mapping...");
00453       point_cloud_sub_.shutdown();//unsubscribe();
00454       //transform_sub_.unsubscribe();
00455       //first_ = true;
00456       is_running_ = false;
00457     }
00458     as_->setSucceeded(result);
00459   }
00460 
00465   void createParamters(const std::string &algo) {
00466 
00467     //for all icp, fastslam
00468     if(algo.find("icp")==0 || algo.find("gicp")==0 || algo=="fastslam") {
00469 
00470       //TODO: not with all!!!!
00471       parameters_.createParam(n_,"voxelsize",0.04).setMin(0.04).setMax(0.041).setStep(10.02); //0cm or 2cm
00472     }
00473 
00474     //icp
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.); //10^-(1...10)
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); //true/false
00481     }
00482 
00483     //icp moments
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     //icp fpfh
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     //icp edges
00496     if(algo=="icp_edges") {
00497       //parameters_.createParam(n_,"edge_radius",0.01).setMax(0.2).setStep(0.01);
00498       parameters_.createParam(n_,"threshold",0.45).setMin(0.45).setMax(0.456).setStep(0.1);
00499       //parameters_.createParam(n_,"distance_threshold",0.01).setMax(0.2).setStep(0.01);
00500     }
00501 
00502     //info
00503     if(algo=="info") {
00504       parameters_.createParam(n_,"use_icp",1).setMax(1).setStep(1); //true/false
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     //get algo
00571     int e_algo=E_ALGO_ICP_EDGES;
00572 
00573     //parameter "algo" determines the algorithm
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       //      else if(s_algo=="fastslam")
00589       //        e_algo=E_ALGO_FASTSLAM;
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     //init: settings
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         /*case E_ALGO_FASTSLAM:
00670 #ifndef GICP_ENABLE
00671         reg_ = new cob_3d_registration::Registration_FastSLAM<Point>();
00672 
00673         //setSettings_ICP_FastSLAM((cob_3d_registration::Registration_FastSLAM<Point>*)reg_);
00674 #else
00675         ROS_ERROR("not supported");
00676 #endif
00677         break;*/
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 //#ifndef GICP_ENABLE
00691 #if 0
00692         reg_ = new cob_3d_registration::Registration_Corrospondence<Point>();
00693 
00694         //((Registration_Corrospondence<Point>*)reg_)->setKeypoints(new Keypoints_Segments<Point>);
00695         //((Registration_Corrospondence<Point>*)reg_)->setKeypoints(new Keypoints_Narf<Point>);
00696 
00697         //setSettings_Cor((cob_3d_registration::Registration_Corrospondence<Point>*)reg_);
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 //      FILE *fp = fopen(req.img_fn.c_str(), "rb");
00729 //      if(!fp) return false;
00730 //
00731 //      struct stat filestatus;
00732 //      stat(req.img_fn.c_str(), &filestatus );
00733 //
00734 //      uint8_t *up = new uint8_t[filestatus.st_size];
00735 //      fread(up,filestatus.st_size,1,fp);
00736 //      img.deserialize(up);
00737 //      delete up;
00738 //
00739 //      fclose(fp);
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     //debug purpose
00811 #if SHOW_MAP
00812 
00813     if(marker_pub_.getNumSubscribers()&&reg_->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     //rotate around 180° around z
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     //gazebo bug escaping hack
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     //MemoryOperator mo;
00987     //boost::thread workerThread(&MemoryOperator::run, &mo);
00988 
00989     //measurement_tools::PrecisionStopWatchAll psw2;
00990     //measurement_tools::PrecisionStopWatchThread psw;
00991     bool ret = reg_->compute();
00992     //duration_ = psw.precisionStop();
00993     registration_result_ = ret;
00994     /*{
00995       std::string s_algo;
00996       if(parameters_.getParam("algo",s_algo) && s_algo=="rgbdslam")
00997         duration_ = psw2.precisionStop();
00998     }*/
00999 
01000     //mo.halt();
01001     //workerThread.join();
01002 
01003     //memory_usage_kb_ = mo.getKB();
01004 
01005     //ROS_ERROR("time %f", duration_);
01006     //ROS_ERROR("memory %d", memory_usage_kb_);
01007 
01008     //std::cout<<reg_->getTransformation()<<"\n";
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_;             //subscriber for input pc
01028   ros::Publisher point_cloud_pub_aligned_;      //publisher for aligned pc
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   //evaluation values
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   //settings
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     //if(parameters_.getParam("use_icp",i))
01114     //  pr->setUseICP(i!=0);
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   /******************VISUALIZATION******************/
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     //marker.header.stamp = stamp;
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 int main(int argc, char **argv) {
01205 #if SHOW_MAP
01206   setVerbosityLevel(pcl::console::L_DEBUG);
01207 #endif
01208 
01209   ros::init(argc, argv, "registration");
01210 
01211   if(argc>1&&strcmp(argv[1],"eval")==0) { //we're sending paramters...
01212     RegistrationNodelet tn(true);
01213 
01214     tn.createParamters(argv[2]);
01215     tn.publishParameters();
01216     return 0;
01217   }
01218 
01219   RegistrationNodelet tn;
01220 
01221   ROS_INFO("Spinning node");
01222   ros::spin();
01223   return 0;
01224 }*/
01225 
01226 PLUGINLIB_DECLARE_CLASS(cob_3d_registration, RegistrationNodelet, RegistrationNodelet, nodelet::Nodelet)
01227 


cob_3d_registration
Author(s): Joshua Hampp
autogenerated on Wed Aug 26 2015 11:02:36