target_adaptive_tracking_nodelet.cpp
Go to the documentation of this file.
00001 // Copyright (C) 2015 by Krishneel Chaudhary, JSK Lab,
00002 // The University of Tokyo, Japan
00003 
00004 #include <jsk_pcl_ros/target_adaptive_tracking.h>
00005 #include <map>
00006 
00007 namespace jsk_pcl_ros 
00008 {
00009    TargetAdaptiveTracking::TargetAdaptiveTracking() :
00010       DiagnosticNodelet("target_adaptive_tracking"),
00011       init_counter_(0),
00012       update_counter_(0),
00013       growth_rate_(1.15)
00014    {
00015       this->object_reference_ = ModelsPtr(new Models);
00016       this->background_reference_ = ModelsPtr(new Models);
00017       this->previous_template_ = pcl::PointCloud<PointT>::Ptr(
00018          new pcl::PointCloud<PointT>);
00019    }
00020 
00021    void TargetAdaptiveTracking::onInit()
00022    {
00023       DiagnosticNodelet::onInit();
00024       
00025       srv_ = boost::shared_ptr<dynamic_reconfigure::Server<Config> >(
00026          new dynamic_reconfigure::Server<Config>);
00027       dynamic_reconfigure::Server<Config>::CallbackType f =
00028        boost::bind(&TargetAdaptiveTracking::configCallback, this, _1, _2);
00029       srv_->setCallback(f);
00030       
00031       this->pub_cloud_ = advertise<sensor_msgs::PointCloud2>(
00032          *pnh_, "/target_adaptive_tracking/output/cloud", 1);
00033 
00034       // this->pub_templ_ = advertise<sensor_msgs::PointCloud2>(
00035       //    *pnh_, "/target_adaptive_tracking/output/template", 1);
00036 
00037       this->pub_templ_ = advertise<sensor_msgs::PointCloud2>(
00038          *pnh_, "/selected_pointcloud", 1);
00039     
00040       this->pub_sindices_ = advertise<
00041          jsk_recognition_msgs::ClusterPointIndices>(
00042             *pnh_, "/target_adaptive_tracking/supervoxel/indices", 1);
00043     
00044       this->pub_scloud_ = advertise<sensor_msgs::PointCloud2>(
00045          *pnh_, "/target_adaptive_tracking/supervoxel/cloud", 1);
00046 
00047       this->pub_normal_ = advertise<sensor_msgs::PointCloud2>(
00048          *pnh_, "/target_adaptive_tracking/output/normal", 1);
00049 
00050       this->pub_tdp_ = advertise<jsk_recognition_msgs::ClusterPointIndices>(
00051             *pnh_, "/target_adaptive_tracking/supervoxel/tdp_indices", 1);
00052 
00053       this->pub_inliers_ = advertise<sensor_msgs::PointCloud2>(
00054          *pnh_, "/target_adaptive_tracking/output/inliers", 1);
00055  
00056       this->pub_centroids_ = advertise<sensor_msgs::PointCloud2>(
00057          *pnh_, "/target_adaptive_tracking/output/centroids", 1);
00058 
00059       this->pub_pose_ = advertise<geometry_msgs::PoseStamped>(
00060          *pnh_, "/target_adaptive_tracking/output/object_pose", 1);
00061 
00062       this->pub_prob_ = advertise<sensor_msgs::PointCloud2>(
00063          *pnh_, "/target_adaptive_tracking/output/probability_map", 1);
00064 
00065       onInitPostProcess();
00066    }
00067 
00068    void TargetAdaptiveTracking::subscribe()
00069    {
00070       this->sub_obj_cloud_.subscribe(*pnh_, "input_obj_cloud", 1);
00071       this->sub_bkgd_cloud_.subscribe(*pnh_, "input_bkgd_cloud", 1);
00072       this->sub_obj_pose_.subscribe(*pnh_, "input_obj_pose", 1);
00073       this->obj_sync_ = boost::make_shared<message_filters::Synchronizer<
00074          ObjectSyncPolicy> >(100);
00075       this->obj_sync_->connectInput(
00076          sub_obj_cloud_, sub_bkgd_cloud_, sub_obj_pose_);
00077       this->obj_sync_->registerCallback(
00078          boost::bind(&TargetAdaptiveTracking::objInitCallback,
00079                      this, _1, _2, _3));
00080       this->sub_cloud_.subscribe(*pnh_, "input_cloud", 1);
00081       this->sub_pose_.subscribe(*pnh_, "input_pose", 1);
00082       this->sync_ = boost::make_shared<message_filters::Synchronizer<
00083          SyncPolicy> >(100);
00084       this->sync_->connectInput(sub_cloud_, sub_pose_);
00085       this->sync_->registerCallback(
00086          boost::bind(&TargetAdaptiveTracking::callback,
00087                      this, _1, _2));
00088    }
00089 
00090    void TargetAdaptiveTracking::unsubscribe()
00091    {
00092       this->sub_cloud_.unsubscribe();
00093       this->sub_pose_.unsubscribe();
00094       this->sub_obj_cloud_.unsubscribe();
00095       this->sub_obj_pose_.unsubscribe();
00096    }
00097 
00098    void TargetAdaptiveTracking::objInitCallback(
00099       const sensor_msgs::PointCloud2::ConstPtr &cloud_msg,
00100       const sensor_msgs::PointCloud2::ConstPtr &bkgd_msg,
00101       const geometry_msgs::PoseStamped::ConstPtr &pose_msg)
00102    {
00103       pcl::PointCloud<PointT>::Ptr cloud (new pcl::PointCloud<PointT>);
00104       pcl::fromROSMsg(*cloud_msg, *cloud);
00105       pcl::PointCloud<PointT>::Ptr bkgd_cloud (new pcl::PointCloud<PointT>);
00106       pcl::fromROSMsg(*bkgd_msg, *bkgd_cloud);
00107       if (this->init_counter_++ > 0) {
00108          ROS_WARN("Object is re-initalized! stopping & reseting...");
00109       }
00110       if (!cloud->empty() && !bkgd_cloud->empty()) {
00111          this->motion_history_.clear();
00112          PointXYZRPY motion_displacement;
00113          this->estimatedPFPose(pose_msg, motion_displacement);
00114          this->previous_pose_ = this->current_pose_;
00115          this->object_reference_ = ModelsPtr(new Models);
00116          this->processInitCloud(cloud, this->object_reference_);
00117          this->background_reference_ = ModelsPtr(new Models);
00118          this->processInitCloud(bkgd_cloud, this->background_reference_);
00119          previous_distance_ = this->templateCloudFilterLenght(cloud);
00120          this->previous_template_->clear();
00121          pcl::copyPointCloud<PointT, PointT>(*cloud, *previous_template_);
00122          this->previous_transform_ = tf::Transform::getIdentity();
00123          
00124          sensor_msgs::PointCloud2 ros_templ;
00125          pcl::toROSMsg(*cloud, ros_templ);
00126          ros_templ.header = cloud_msg->header;
00127          this->pub_templ_.publish(ros_templ);
00128       }
00129    }
00130 
00131    void TargetAdaptiveTracking::processInitCloud(
00132       const pcl::PointCloud<PointT>::Ptr cloud,
00133       ModelsPtr object_reference)
00134    {
00135       if (cloud->empty()) {
00136          ROS_ERROR("OBJECT INIT CLOUD IS EMPTY");
00137          return;
00138       }
00139       float seed_resolution = static_cast<float>(this->seed_resolution_) / 2.0f;
00140       float seed_factor = seed_resolution;
00141       for (int i = 0; i < 3; i++) {
00142          std::map <uint32_t, pcl::Supervoxel<PointT>::Ptr> supervoxel_clusters;
00143          std::multimap<uint32_t, uint32_t> supervoxel_adjacency;
00144          this->supervoxelSegmentation(
00145             cloud, supervoxel_clusters, supervoxel_adjacency, seed_resolution);
00146          ModelsPtr obj_ref(new Models);
00147          std::vector<AdjacentInfo> supervoxel_list;
00148          this->voxelizeAndProcessPointCloud(
00149             cloud, supervoxel_clusters, supervoxel_adjacency,
00150             supervoxel_list, obj_ref, true, true, true, true);
00151          for (int j = 0; j < obj_ref->size(); j++) {
00152             object_reference->push_back(obj_ref->operator[](j));
00153          }
00154          seed_resolution += seed_factor;
00155       }
00156    }
00157 
00158    void TargetAdaptiveTracking::callback(
00159       const sensor_msgs::PointCloud2::ConstPtr &cloud_msg,
00160       const geometry_msgs::PoseStamped::ConstPtr &pose_msg) {
00161       if (this->object_reference_->empty())
00162       {
00163          ROS_WARN("No Model To Track Selected");
00164          return;
00165       }
00166       ROS_INFO("\n\n\033[34m------------RUNNING CALLBACK-------------\033[0m");
00167       ros::Time begin = ros::Time::now();
00168       PointXYZRPY motion_displacement;
00169       this->estimatedPFPose(pose_msg, motion_displacement);
00170       std::cout << "Motion Displacement: " << motion_displacement << std::endl;
00171       
00172       pcl::PointCloud<PointT>::Ptr cloud (new pcl::PointCloud<PointT>);
00173       pcl::fromROSMsg(*cloud_msg, *cloud);
00174       bool use_tf = false;
00175       tf::TransformListener tf_listener;
00176       tf::StampedTransform transform;
00177       ros::Time now = ros::Time(0);
00178       std::string child_frame = "/camera_rgb_optical_frame";
00179       std::string parent_frame = "/track_result";
00180       Eigen::Affine3f transform_model = Eigen::Affine3f::Identity();
00181       tf::Transform update_transform;
00182       if (use_tf) {
00183          bool wft_ok = tf_listener.waitForTransform(
00184             child_frame, parent_frame, now, ros::Duration(2.0f));
00185          if (!wft_ok) {
00186             ROS_ERROR("CANNOT TRANSFORM SOURCE AND TARGET FRAMES");
00187             return;
00188          }
00189          tf_listener.lookupTransform(
00190             child_frame, parent_frame, now, transform);
00191          tf::Quaternion tf_quaternion =  transform.getRotation();
00192          transform_model = Eigen::Affine3f::Identity();
00193          transform_model.translation() <<
00194             transform.getOrigin().getX(),
00195             transform.getOrigin().getY(),
00196             transform.getOrigin().getZ();
00197          Eigen::Quaternion<float> quaternion = Eigen::Quaternion<float>(
00198             tf_quaternion.w(), tf_quaternion.x(),
00199             tf_quaternion.y(), tf_quaternion.z());
00200          transform_model.rotate(quaternion);
00201          tf::Vector3 origin = tf::Vector3(transform.getOrigin().getX(),
00202                                           transform.getOrigin().getY(),
00203                                           transform.getOrigin().getZ());
00204          update_transform.setOrigin(origin);
00205          tf::Quaternion update_quaternion = tf_quaternion;
00206          update_transform.setRotation(update_quaternion +
00207                                       this->previous_transform_.getRotation());
00208         
00209       } else {
00210          transform_model = Eigen::Affine3f::Identity();
00211          transform_model.translation() << pose_msg->pose.position.x,
00212             pose_msg->pose.position.y, pose_msg->pose.position.z;
00213          Eigen::Quaternion<float> pf_quat = Eigen::Quaternion<float>(
00214             pose_msg->pose.orientation.w, pose_msg->pose.orientation.x,
00215             pose_msg->pose.orientation.y, pose_msg->pose.orientation.z);
00216          transform_model.rotate(pf_quat);
00217          tf::Vector3 origin = tf::Vector3(
00218             pose_msg->pose.position.x,
00219             pose_msg->pose.position.y,
00220             pose_msg->pose.position.z);
00221          update_transform.setOrigin(origin);
00222          tf::Quaternion update_quaternion = tf::Quaternion(
00223             pose_msg->pose.orientation.x, pose_msg->pose.orientation.y,
00224             pose_msg->pose.orientation.z, pose_msg->pose.orientation.w);
00225          update_transform.setRotation(update_quaternion *
00226                                       this->previous_transform_.getRotation());
00227       }
00228     
00229       Eigen::Affine3f transform_reference = Eigen::Affine3f::Identity();
00230       const int motion_hist_index = static_cast<int>(
00231          this->motion_history_.size()) - 1;
00232       transform_reference.translation() <<
00233          motion_history_[motion_hist_index].x,
00234          motion_history_[motion_hist_index].y,
00235          motion_history_[motion_hist_index].z;
00236       Eigen::Affine3f transformation_matrix = transform_model *
00237          transform_reference.inverse();
00238       bool is_cloud_exist = this->filterPointCloud(
00239          cloud, this->current_pose_, this->object_reference_, 1.5f);
00240       if (is_cloud_exist && this->update_filter_template_) {
00241          this->targetDescriptiveSurfelsEstimationAndUpdate(
00242             cloud, transformation_matrix, motion_displacement,
00243             cloud_msg->header);
00244       }
00245       ros::Time end = ros::Time::now();
00246       std::cout << "Processing Time: " << end - begin << std::endl;
00247       
00248       static tf::TransformBroadcaster br;
00249       br.sendTransform(tf::StampedTransform(
00250                           update_transform, cloud_msg->header.stamp,
00251                           cloud_msg->header.frame_id, "object_pose"));
00252       this->previous_transform_ = update_transform;
00253 
00254       geometry_msgs::PoseStamped update_pose;
00255       tf::poseTFToMsg(update_transform, update_pose.pose);
00256       update_pose.header.stamp = cloud_msg->header.stamp;
00257       update_pose.header.frame_id = child_frame;
00258       this->pub_pose_.publish(update_pose);
00259     
00260       sensor_msgs::PointCloud2 ros_cloud;
00261       pcl::toROSMsg(*cloud, ros_cloud);
00262       ros_cloud.header.stamp = cloud_msg->header.stamp;
00263       ros_cloud.header.frame_id = child_frame;
00264       this->pub_cloud_.publish(ros_cloud);
00265    }
00266 
00267    void TargetAdaptiveTracking::voxelizeAndProcessPointCloud(
00268       const pcl::PointCloud<PointT>::Ptr cloud,
00269       const std::map <uint32_t, pcl::Supervoxel<PointT>::Ptr> &
00270       supervoxel_clusters,
00271       const std::multimap<uint32_t, uint32_t> &supervoxel_adjacency,
00272       std::vector<AdjacentInfo> &supervoxel_list,
00273       TargetAdaptiveTracking::ModelsPtr &models,
00274       bool norm_flag, bool feat_flag, bool cent_flag, bool neigh_pfh)
00275    {
00276       if (cloud->empty() || supervoxel_clusters.empty()) {
00277          return;
00278       }
00279       models = ModelsPtr(new Models);
00280       int icounter = 0;
00281       for (std::multimap<uint32_t, pcl::Supervoxel<PointT>::Ptr>::const_iterator
00282               label_itr = supervoxel_clusters.begin(); label_itr !=
00283               supervoxel_clusters.end(); label_itr++) {
00284          ReferenceModel ref_model;
00285          ref_model.flag = true;
00286          ref_model.supervoxel_index = label_itr->first;
00287          uint32_t supervoxel_label = label_itr->first;
00288          pcl::Supervoxel<PointT>::Ptr supervoxel =
00289             supervoxel_clusters.at(supervoxel_label);
00290          if (supervoxel->voxels_->size() > min_cluster_size_) {
00291             std::vector<uint32_t> adjacent_voxels;
00292             for (std::multimap<uint32_t, uint32_t>::const_iterator
00293                     adjacent_itr = supervoxel_adjacency.equal_range(
00294                        supervoxel_label).first; adjacent_itr !=
00295                     supervoxel_adjacency.equal_range(
00296                        supervoxel_label).second; ++adjacent_itr) {
00297                pcl::Supervoxel<PointT>::Ptr neighbor_supervoxel =
00298                   supervoxel_clusters.at(adjacent_itr->second);
00299                if (neighbor_supervoxel->voxels_->size() >
00300                    min_cluster_size_) {
00301                   adjacent_voxels.push_back(adjacent_itr->second);
00302                }
00303                icounter++;
00304             }
00305             AdjacentInfo a_info;
00306             a_info.adjacent_voxel_indices[supervoxel_label] = adjacent_voxels;
00307             supervoxel_list.push_back(a_info);
00308             a_info.voxel_index = supervoxel_label;
00309             ref_model.cluster_neigbors = a_info;
00310             ref_model.cluster_cloud = pcl::PointCloud<PointT>::Ptr(
00311                new pcl::PointCloud<PointT>);
00312             ref_model.cluster_cloud = supervoxel->voxels_;
00313             if (norm_flag) {
00314                ref_model.cluster_normals = pcl::PointCloud<pcl::Normal>::Ptr(
00315                   new pcl::PointCloud<pcl::Normal>);
00316                ref_model.cluster_normals = supervoxel->normals_;
00317             }
00318             if (feat_flag) {
00319                this->computeCloudClusterRPYHistogram(
00320                   ref_model.cluster_cloud,
00321                   ref_model.cluster_normals,
00322                   ref_model.cluster_vfh_hist);
00323                this->computeColorHistogram(
00324                   ref_model.cluster_cloud,
00325                   ref_model.cluster_color_hist);
00326             }
00327             if (cent_flag) {
00328                ref_model.cluster_centroid = Eigen::Vector4f();
00329                ref_model.cluster_centroid =
00330                   supervoxel->centroid_.getVector4fMap();
00331             }
00332             ref_model.flag = false;
00333             ref_model.match_counter = 0;
00334             models->push_back(ref_model);
00335          }
00336       }
00337       std::cout << "Cloud Voxel size: "  << models->size() << std::endl;
00338 
00339       // compute the local pfh
00340       if (neigh_pfh) {
00341          for (int i = 0; i < models->size(); i++) {
00342             this->computeLocalPairwiseFeautures(
00343                supervoxel_clusters,
00344                models->operator[](i).cluster_neigbors.adjacent_voxel_indices,
00345                models->operator[](i).neigbour_pfh);
00346          }
00347       }
00348    }
00349 
00350    void TargetAdaptiveTracking::targetDescriptiveSurfelsEstimationAndUpdate(
00351       pcl::PointCloud<PointT>::Ptr cloud,
00352       const Eigen::Affine3f &transformation_matrix,
00353       const TargetAdaptiveTracking::PointXYZRPY &motion_disp,
00354       const std_msgs::Header header)
00355    {
00356       if (cloud->empty()) {
00357          ROS_ERROR("ERROR: Global Layer Input Empty");
00358          return;
00359       }
00360       pcl::PointCloud<PointT>::Ptr n_cloud(new pcl::PointCloud<PointT>);
00361       Models obj_ref = *object_reference_;
00362       std::map <uint32_t, pcl::Supervoxel<PointT>::Ptr> supervoxel_clusters;
00363       std::multimap<uint32_t, uint32_t> supervoxel_adjacency;
00364       this->supervoxelSegmentation(cloud,
00365                                    supervoxel_clusters,
00366                                    supervoxel_adjacency);
00367       Eigen::Matrix<float, 3, 3> rotation_matrix;
00368       rotation_matrix = transformation_matrix.rotation();
00369     
00370       std::vector<AdjacentInfo> supervoxel_list;
00371       ModelsPtr t_voxels = ModelsPtr(new Models);
00372       this->voxelizeAndProcessPointCloud(
00373          cloud, supervoxel_clusters, supervoxel_adjacency,
00374          supervoxel_list, t_voxels, true, false, true);
00375       Models target_voxels = *t_voxels;
00376     
00377       ROS_INFO("\033[35m MODEL TRANSITION FOR MATCHING \033[0m");    
00378       std::map<int, int> matching_indices;
00379       pcl::PointCloud<PointT>::Ptr template_cloud(new pcl::PointCloud<PointT>);
00380       for (int j = 0; j < obj_ref.size(); j++) {
00381          if (!obj_ref[j].flag) {
00382             float distance = FLT_MAX;
00383             int nearest_index = -1;
00384             Eigen::Vector4f obj_centroid;
00385             obj_centroid = transformation_matrix * obj_ref[j].cluster_centroid;
00386             for (int i = 0; i < target_voxels.size(); i++) {
00387                if (!target_voxels[i].flag) {
00388                   Eigen::Vector4f t_centroid =
00389                      target_voxels[i].cluster_centroid;
00390                   t_centroid(3) = 1.0f;
00391                   float dist = static_cast<float>(
00392                      pcl::distances::l2(obj_centroid, t_centroid));
00393                   if (dist < distance) {
00394                      distance = dist;
00395                      nearest_index = i;
00396                   }
00397                }
00398             }
00399             if (nearest_index != -1) {
00400                matching_indices[j] = nearest_index;
00401             }
00402             const int motion_hist_index = this->motion_history_.size() - 1;
00403             obj_ref[j].centroid_distance(0) = obj_ref[j].cluster_centroid(0) -
00404                this->motion_history_[motion_hist_index].x;
00405             obj_ref[j].centroid_distance(1) = obj_ref[j].cluster_centroid(1) -
00406                this->motion_history_[motion_hist_index].y;
00407             obj_ref[j].centroid_distance(2) = obj_ref[j].cluster_centroid(2) -
00408                this->motion_history_[motion_hist_index].z;
00409          }
00410       }
00411       ROS_INFO("\033[35m MATCHING THROUGH NIEGBOUR SEARCH \033[0m");
00412       int counter = 0;
00413       float connectivity_lenght = 2.0f;
00414       pcl::PointCloud<PointT>::Ptr est_centroid_cloud(
00415          new pcl::PointCloud<PointT>);
00416       std::multimap<uint32_t, Eigen::Vector3f> estimated_centroids;
00417       std::multimap<uint32_t, float> estimated_match_prob;
00418       std::multimap<uint32_t, ReferenceModel*> estimated_match_info;
00419       std::vector<uint32_t> best_match_index;
00420       std::multimap<uint32_t, float> all_probabilites;
00421       for (std::map<int, int>::iterator itr = matching_indices.begin();
00422            itr != matching_indices.end(); itr++) {
00423          if (!target_voxels[itr->second].flag) {
00424             std::map<uint32_t, std::vector<uint32_t> > neigb =
00425                target_voxels[itr->second].cluster_neigbors.adjacent_voxel_indices;
00426             uint32_t v_ind = target_voxels[
00427                itr->second].cluster_neigbors.voxel_index;
00428             uint32_t bm_index = v_ind;
00429             float probability = 0.0f;
00430             ReferenceModel *voxel_model = new ReferenceModel;
00431             probability = this->targetCandidateToReferenceLikelihood<float>(
00432                obj_ref[itr->first], target_voxels[itr->second].cluster_cloud,
00433                target_voxels[itr->second].cluster_normals,
00434                target_voxels[itr->second].cluster_centroid, voxel_model);
00435             voxel_model->query_index = itr->first;
00436 
00437             // TODO(.) collect the neigbours here instead of next for
00438             // loop
00439 
00440             bool is_voxel_adjacency_info = true;
00441             float local_weight = 0.0f;
00442             if (is_voxel_adjacency_info) {
00443                cv::Mat histogram_phf;
00444                this->computeLocalPairwiseFeautures(
00445                   supervoxel_clusters, neigb, histogram_phf);
00446                voxel_model->cluster_neigbors.adjacent_voxel_indices = neigb;
00447                voxel_model->neigbour_pfh = histogram_phf.clone();
00448                float dist_phf = static_cast<float>(
00449                   cv::compareHist(obj_ref[itr->first].neigbour_pfh,
00450                                   histogram_phf, CV_COMP_BHATTACHARYYA));
00451                local_weight = std::exp(-this->structure_scaling_ * dist_phf);
00452                probability *= local_weight;
00453             }
00454             for (std::vector<uint32_t>::iterator it =
00455                     neigb.find(v_ind)->second.begin();
00456                  it != neigb.find(v_ind)->second.end(); it++) {
00457                ReferenceModel *voxel_mod = new ReferenceModel;
00458                float prob = this->targetCandidateToReferenceLikelihood<float>(
00459                   obj_ref[itr->first], supervoxel_clusters.at(*it)->voxels_,
00460                   supervoxel_clusters.at(*it)->normals_,
00461                   supervoxel_clusters.at(*it)->centroid_.getVector4fMap(),
00462                   voxel_mod);
00463                voxel_mod->query_index = itr->first;
00464                if (is_voxel_adjacency_info) {
00465                   std::map<uint32_t, std::vector<uint32_t> > local_adjacency;
00466                   std::vector<uint32_t> list_adj;
00467                   for (std::multimap<uint32_t, uint32_t>::const_iterator
00468                           adjacent_itr = supervoxel_adjacency.equal_range(
00469                              *it).first; adjacent_itr !=
00470                           supervoxel_adjacency.equal_range(*it).second;
00471                        ++adjacent_itr) {
00472                      list_adj.push_back(adjacent_itr->second);
00473                   }
00474                   local_adjacency[*it] = list_adj;
00475                   cv::Mat local_phf;
00476                   this->computeLocalPairwiseFeautures(
00477                      supervoxel_clusters, local_adjacency, local_phf);
00478                   voxel_mod->neigbour_pfh = local_phf.clone();
00479                   voxel_mod->cluster_neigbors.adjacent_voxel_indices =
00480                      local_adjacency;
00481                   float dist_phf = static_cast<float>(
00482                      cv::compareHist(obj_ref[itr->first].neigbour_pfh,
00483                                      local_phf, CV_COMP_BHATTACHARYYA));
00484                   float phf_prob = std::exp(-this->structure_scaling_ * dist_phf);
00485                   local_weight = phf_prob;
00486                   prob *= phf_prob;
00487                }
00488 
00489                float matching_dist = static_cast<float>(pcl::distances::l2(
00490                      supervoxel_clusters.at(v_ind)->centroid_.getVector4fMap(),
00491                      supervoxel_clusters.at(*it)->centroid_.getVector4fMap()));
00492                if (matching_dist > this->seed_resolution_ / connectivity_lenght) {
00493                   prob *= 0.0f;
00494                }
00495                if (prob > probability) {
00496                   probability = prob;
00497                   bm_index = *it;
00498                   voxel_model = voxel_mod;
00499                }
00500             }
00501             all_probabilites.insert(
00502                std::pair<uint32_t, float>(bm_index, probability));
00503             if (probability > threshold_) {
00504                Eigen::Vector3f estimated_position = supervoxel_clusters.at(
00505                   bm_index)->centroid_.getVector3fMap() - rotation_matrix *
00506                   obj_ref[itr->first].centroid_distance /* local_weight*/;
00507                Eigen::Vector4f estimated_pos = Eigen::Vector4f(
00508                   estimated_position(0), estimated_position(1),
00509                   estimated_position(2), 0.0f);
00510                float match_dist = static_cast<float>(
00511                   pcl::distances::l2(estimated_pos, current_pose_));
00512 
00513                if (match_dist < this->seed_resolution_ / connectivity_lenght) {
00514                   best_match_index.push_back(bm_index);
00515                   estimated_centroids.insert(
00516                      std::pair<uint32_t, Eigen::Vector3f>(
00517                         bm_index, estimated_position));
00518                   estimated_match_prob.insert(
00519                      std::pair<uint32_t, float>(bm_index, probability));
00520                   estimated_match_info.insert(
00521                      std::pair<uint32_t, ReferenceModel*>(
00522                         bm_index, voxel_model));
00523                   obj_ref[itr->first].history_window.push_back(1);
00524                   PointT pt;
00525                   pt.x = estimated_position(0);
00526                   pt.y = estimated_position(1);
00527                   pt.z = estimated_position(2);
00528                   pt.r = 255;
00529                   est_centroid_cloud->push_back(pt);
00530                   counter++;
00531                } else {
00532                   ROS_WARN("-- Outlier not added...");
00533                }
00534             } else {
00535                obj_ref[itr->first].history_window.push_back(0);
00536             }
00537          }
00538       }
00539       pcl::PointCloud<PointT>::Ptr prob_cloud(new pcl::PointCloud<PointT>);
00540       for (std::multimap<uint32_t, float>::iterator it = all_probabilites.begin();
00541            it != all_probabilites.end(); it++) {
00542          if (it->second > eps_distance_) {
00543             for (int i = 0; i < supervoxel_clusters.at(
00544                     it->first)->voxels_->size(); i++) {
00545                PointT pt = supervoxel_clusters.at(it->first)->voxels_->points[i];
00546                pt.r = 255 * it->second;
00547                pt.g = 255 * it->second;
00548                pt.b = 255 * it->second;
00549                prob_cloud->push_back(pt);
00550             }
00551          }
00552       }
00553       sensor_msgs::PointCloud2 ros_prob;
00554       pcl::toROSMsg(*prob_cloud, ros_prob);
00555       ros_prob.header = header;
00556       this->pub_prob_.publish(ros_prob);
00557     
00558       pcl::PointCloud<PointT>::Ptr inliers(new pcl::PointCloud<PointT>);
00559       std::vector<uint32_t> outlier_index;
00560 
00561       ROS_INFO("\033[35m OUTLIER FILTERING VIA BACKPROJECTION \033[0m");
00562       Eigen::Matrix<float, 3, 3> inv_rotation_matrix = rotation_matrix.inverse();
00563       PointT ptt;
00564       ptt.x = previous_pose_(0);
00565       ptt.y = previous_pose_(1);
00566       ptt.z = previous_pose_(2);
00567       ptt.b = 255;
00568       inliers->push_back(ptt);
00569       std::vector<uint32_t> matching_indx = best_match_index;
00570       best_match_index.clear();
00571       for (std::vector<uint32_t>::iterator it = matching_indx.begin();
00572            it != matching_indx.end(); it++) {
00573          Eigen::Vector4f cur_pt = supervoxel_clusters.at(
00574             *it)->centroid_.getVector4fMap();
00575          Eigen::Vector3f demean_pts = Eigen::Vector3f();
00576          demean_pts(0) = cur_pt(0) - this->current_pose_(0);
00577          demean_pts(1) = cur_pt(1) - this->current_pose_(1);
00578          demean_pts(2) = cur_pt(2) - this->current_pose_(2);
00579          int query_idx = estimated_match_info.find(*it)->second->query_index;
00580          Eigen::Vector3f abs_position = -(inv_rotation_matrix * demean_pts) +
00581             obj_ref[query_idx].cluster_centroid.head<3>();
00582          Eigen::Vector4f prev_vote = Eigen::Vector4f(
00583             abs_position(0), abs_position(1), abs_position(2), 0.0f);
00584          float matching_dist = static_cast<float>(
00585             pcl::distances::l2(prev_vote, this->previous_pose_));
00586 
00587          PointT pt;
00588          pt.x = abs_position(0);
00589          pt.y = abs_position(1);
00590          pt.z = abs_position(2);
00591          if (matching_dist < this->seed_resolution_ / connectivity_lenght) {
00592             best_match_index.push_back(*it);
00593             pt.r = 255;
00594             pt.b = 255;
00595          } else {
00596             pt.g = 255;
00597             pt.b = 255;
00598          }
00599          inliers->push_back(pt);
00600       }
00601       /*
00602         std::cout << "TOTAL POINTS: " << estimated_centroids.size() << std::endl;
00603         std::cout << "Cloud Size: " << est_centroid_cloud->size() << "\t"
00604         << inliers->size() << "\t" << counter << "\t Best Match: "
00605         << best_match_index.size() << "\t Query-Test"
00606         << matching_indices.size() << std::endl;
00607       */
00608       
00609       pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr centroid_normal(
00610          new pcl::PointCloud<pcl::PointXYZRGBNormal>);
00611 
00612       // visualization of removed normal
00613       for (std::vector<uint32_t>::iterator it = outlier_index.begin();
00614            it != outlier_index.end(); it++) {
00615          Eigen::Vector4f c_centroid = supervoxel_clusters.at(
00616             *it)->centroid_.getVector4fMap();
00617          Eigen::Vector4f c_normal = this->cloudMeanNormal(
00618             supervoxel_clusters.at(*it)->normals_);
00619          centroid_normal->push_back(
00620             this->convertVector4fToPointXyzRgbNormal(
00621                c_centroid, c_normal, cv::Scalar(0, 0, 255)));
00622       }
00623       
00624       ROS_INFO("\033[35m CONVEX VOXELS \033[0m");
00625       pcl::PointCloud<PointT>::Ptr output(new pcl::PointCloud<PointT>);
00626       std::vector<uint32_t> neigb_lookup;
00627       neigb_lookup = best_match_index;
00628       std::vector<uint32_t> convex_ok;
00629       std::map<uint32_t, ReferenceModel*> convex_local_voxels;
00630     
00631       for (std::vector<uint32_t>::iterator it = best_match_index.begin();
00632            it != best_match_index.end(); it++) {
00633          std::pair<std::multimap<uint32_t, uint32_t>::iterator,
00634                    std::multimap<uint32_t, uint32_t>::iterator> ret;
00635          ret = supervoxel_adjacency.equal_range(*it);
00636          Eigen::Vector4f c_centroid = supervoxel_clusters.at(
00637             *it)->centroid_.getVector4fMap();
00638          Eigen::Vector4f c_normal = this->cloudMeanNormal(
00639             supervoxel_clusters.at(*it)->normals_);
00640 
00641          centroid_normal->push_back(
00642             this->convertVector4fToPointXyzRgbNormal(
00643                c_centroid, c_normal, cv::Scalar(255, 0, 0)));
00644          
00645          for (std::multimap<uint32_t, uint32_t>::iterator itr = ret.first;
00646               itr != ret.second; itr++) {
00647             bool is_process_neigh = true;
00648             for (std::vector<uint32_t>::iterator lup_it = neigb_lookup.begin();
00649                  lup_it != neigb_lookup.end(); lup_it++) {
00650                if (*lup_it == itr->second) {
00651                   is_process_neigh = false;
00652                   break;
00653                }
00654             }
00655             if (!supervoxel_clusters.at(itr->second)->voxels_->empty() &&
00656                 is_process_neigh) {
00657                bool is_common_neigh = false;
00658                if (!is_common_neigh) {
00659                   neigb_lookup.push_back(itr->second);
00660                   Eigen::Vector4f n_centroid = supervoxel_clusters.at(
00661                      itr->second)->centroid_.getVector4fMap();
00662                   Eigen::Vector4f n_normal = this->cloudMeanNormal(
00663                      supervoxel_clusters.at(itr->second)->normals_);
00664                   float convx_weight = this->localVoxelConvexityLikelihood<
00665                      float>(c_centroid, c_normal, n_centroid, n_normal);
00666                   if (convx_weight > 0.0f) {
00667                      *output = *output + *supervoxel_clusters.at(
00668                         itr->second)->voxels_;
00669 
00670                      ReferenceModel *ref_model = new ReferenceModel;
00671                      this->processVoxelForReferenceModel(
00672                         supervoxel_clusters, supervoxel_adjacency,
00673                         itr->second, ref_model);
00674                      if (!ref_model->flag) {
00675                         Eigen::Vector4f convx_centroid = Eigen::Vector4f();
00676                         convx_centroid = transformation_matrix.inverse() *
00677                            ref_model->cluster_centroid;
00678                         for (int j = 0; j < this->object_reference_->size();
00679                              j++) {
00680                            float rev_match_dist = static_cast<float>(
00681                               pcl::distances::l2(convx_centroid,
00682                                this->object_reference_->operator[](
00683                                   j).cluster_centroid));
00684                            if (rev_match_dist < this->seed_resolution_) {
00685                               float convx_dist = static_cast<float>(
00686                                  cv::compareHist(ref_model->cluster_vfh_hist,
00687                                                  object_reference_->operator[](
00688                                                     j).cluster_vfh_hist,
00689                                                  CV_COMP_BHATTACHARYYA));
00690                               float convx_prob = std::exp(
00691                                  -1 * this->vfh_scaling_ * convx_dist);
00692                               if (convx_prob > this->threshold_) {
00693                                  ref_model->query_index = static_cast<int>(j);
00694                                  estimated_match_info.insert(
00695                                     std::pair<int32_t, ReferenceModel*>(
00696                                        itr->second, ref_model));
00697                                  convex_ok.push_back(itr->second);
00698                                  estimated_match_prob.insert(
00699                                     std::pair<uint32_t, float>(
00700                                        itr->second, convx_prob));
00701                                  centroid_normal->push_back(
00702                                     this->convertVector4fToPointXyzRgbNormal(
00703                                        n_centroid, n_normal,
00704                                        cv::Scalar(0, 255, 0)));
00705                                  ROS_INFO("\033[34m Added VOXEL \033[0m");
00706                                  break;
00707                               }
00708                            } else {
00709                               // TODO(complete): here
00710                               // mark and test on object in next (t +
00711                               // 1)
00712                               convex_local_voxels[itr->second] = ref_model;
00713                               centroid_normal->push_back(
00714                                  this->convertVector4fToPointXyzRgbNormal(
00715                                     n_centroid, n_normal, cv::Scalar(0, 255, 0)));
00716                            }
00717                         }
00718                      }
00719                   }
00720                } else {
00721                   std::pair<
00722                      std::multimap<uint32_t, uint32_t>::iterator,
00723                      std::multimap<uint32_t, uint32_t>::iterator> comm_neigb;
00724                   comm_neigb = supervoxel_adjacency.equal_range(itr->second);
00725                   uint32_t common_neigbour_index = 0;
00726                   for (std::multimap<uint32_t, uint32_t>::iterator c_itr =
00727                           comm_neigb.first; c_itr != comm_neigb.second;
00728                        c_itr++) {
00729                      if (!supervoxel_clusters.at(
00730                             c_itr->second)->voxels_->empty()) {
00731                         bool is_common_neigh = false;
00732                         for (std::map<uint32_t, uint32_t>::iterator itr_ret =
00733                                 supervoxel_adjacency.equal_range(c_itr->first).
00734                                 first; itr_ret !=supervoxel_adjacency.equal_range(
00735                                    c_itr->first).second; itr_ret++) {
00736                            if (itr_ret->second == *it) {
00737                               is_common_neigh = true;
00738                               common_neigbour_index = c_itr->second;
00739                               break;
00740                            }
00741                         }
00742                         if (is_common_neigh) {
00743                            break;
00744                         }
00745                      }
00746                   }
00747                   if (common_neigbour_index > 0) {
00748                      Eigen::Vector4f n_centroid_b = supervoxel_clusters.at(
00749                         itr->second)->centroid_.getVector4fMap();
00750                      Eigen::Vector4f n_normal_b = this->cloudMeanNormal(
00751                         supervoxel_clusters.at(itr->second)->normals_);
00752                      Eigen::Vector4f n_centroid_c = supervoxel_clusters.at(
00753                         common_neigbour_index)->centroid_.getVector4fMap();
00754                      Eigen::Vector4f n_normal_c = this->cloudMeanNormal(
00755                         supervoxel_clusters.at(common_neigbour_index)->normals_);
00756                      float convx_weight_ab = this->localVoxelConvexityLikelihood<
00757                         float>(c_centroid, c_normal, n_centroid_b, n_normal_b);
00758                      float convx_weight_ac = this->localVoxelConvexityLikelihood<
00759                         float>(c_centroid, c_normal, n_centroid_c, n_normal_c);
00760                      float convx_weight_bc = this->localVoxelConvexityLikelihood<
00761                         float>(n_centroid_b, n_normal_b, n_centroid_c,
00762                                n_normal_c);
00763                      if (convx_weight_ab != 0.0f &&
00764                          convx_weight_ac != 0.0f &&
00765                          convx_weight_bc != 0.0f) {
00766                         *output = *output + *supervoxel_clusters.at(
00767                            itr->second)->voxels_;
00768                         centroid_normal->push_back(
00769                            this->convertVector4fToPointXyzRgbNormal(
00770                               n_centroid_b, n_normal_b, cv::Scalar(0, 255, 0)));
00771                         neigb_lookup.push_back(itr->second);
00772                         ReferenceModel *ref_model = new ReferenceModel;
00773                         this->processVoxelForReferenceModel(
00774                            supervoxel_clusters, supervoxel_adjacency,
00775                            itr->second, ref_model);
00776                         if (!ref_model->flag) {
00777                            Eigen::Vector4f convx_centroid = Eigen::Vector4f();
00778                            convx_centroid = transformation_matrix.inverse() *
00779                               ref_model->cluster_centroid;
00780                            for (int j = 0; j < this->object_reference_->size(); j++) {
00781                               float rev_match_dist = static_cast<float>(
00782                                  pcl::distances::l2(convx_centroid,
00783                                     this->object_reference_->operator[](
00784                                        j).cluster_centroid));
00785                               if (rev_match_dist < this->seed_resolution_) {
00786                                  float convx_dist = static_cast<float>(
00787                                     cv::compareHist(ref_model->cluster_vfh_hist,
00788                                        object_reference_->operator[](
00789                                           j).cluster_vfh_hist, CV_COMP_BHATTACHARYYA));
00790                                  float convx_prob = std::exp(
00791                                     -1 * this->vfh_scaling_ * convx_dist);
00792                                  if (convx_prob > this->threshold_) {
00793                                     ref_model->query_index = static_cast<int>(j);
00794                                     estimated_match_info.insert(
00795                                        std::pair<int32_t, ReferenceModel*>(
00796                                           itr->second, ref_model));
00797                                     convex_ok.push_back(itr->second);
00798                                     estimated_match_prob.insert(
00799                                        std::pair<uint32_t, float>(
00800                                           itr->second, convx_prob));
00801                                     centroid_normal->push_back(
00802                                        this->convertVector4fToPointXyzRgbNormal(
00803                                           n_centroid_b, n_normal_b,
00804                                           cv::Scalar(0, 255, 0)));
00805                                     break;
00806                                  }
00807                               } else {
00808                                  convex_local_voxels[itr->second] = ref_model;
00809                               }
00810                            }
00811                         }
00812                      }
00813                   }
00814                }
00815             }
00816          }
00817          *output = *output + *supervoxel_clusters.at(*it)->voxels_;
00818       }
00819       for (int i = 0; i < convex_ok.size(); i++) {
00820          best_match_index.push_back(convex_ok[i]);
00821       }
00822 
00823       ModelsPtr transform_model (new Models);
00824       this->transformModelPrimitives(
00825          this->object_reference_, transform_model, transformation_matrix);
00826       obj_ref.clear();
00827       obj_ref = *transform_model;
00828       if (best_match_index.size() > 2 && this->update_tracker_reference_) {
00829          ROS_INFO("\n\033[32mUpdating Tracking Reference Model\033[0m \n");
00830          std::map<int, ReferenceModel> matching_surfels;
00831          for (std::vector<uint32_t>::iterator it = best_match_index.begin();
00832               it != best_match_index.end(); it++) {
00833             float adaptive_factor = estimated_match_prob.find(*it)->second;
00834             std::pair<std::multimap<uint32_t, ReferenceModel*>::iterator,
00835                       std::multimap<uint32_t, ReferenceModel*>::iterator> ret;
00836             ret = estimated_match_info.equal_range(*it);
00837             for (std::multimap<uint32_t, ReferenceModel*>::iterator itr =
00838                     ret.first; itr != ret.second; ++itr) {
00839                cv::Mat nvfh_hist = cv::Mat::zeros(
00840                   itr->second->cluster_vfh_hist.size(), CV_32F);
00841                nvfh_hist = itr->second->cluster_vfh_hist * adaptive_factor +
00842                   obj_ref[itr->second->query_index].cluster_vfh_hist *
00843                   (1 - adaptive_factor);
00844                cv::normalize(nvfh_hist, nvfh_hist, 0, 1,
00845                              cv::NORM_MINMAX, -1, cv::Mat());
00846                cv::Mat ncolor_hist = cv::Mat::zeros(
00847                   itr->second->cluster_color_hist.size(),
00848                   itr->second->cluster_color_hist.type());
00849                ncolor_hist = itr->second->cluster_color_hist * adaptive_factor +
00850                   obj_ref[itr->second->query_index].cluster_color_hist *
00851                   (1 - adaptive_factor);
00852                cv::normalize(ncolor_hist, ncolor_hist, 0, 1,
00853                              cv::NORM_MINMAX, -1, cv::Mat());
00854                cv::Mat local_phf = cv::Mat::zeros(
00855                   itr->second->neigbour_pfh.size(),
00856                   itr->second->neigbour_pfh.type());
00857                local_phf = itr->second->neigbour_pfh * adaptive_factor +
00858                   obj_ref[itr->second->query_index].neigbour_pfh *
00859                   (1 - adaptive_factor);
00860                cv::normalize(local_phf, local_phf, 0, 1,
00861                              cv::NORM_MINMAX, -1, cv::Mat());
00862                int query_idx = estimated_match_info.find(
00863                   *it)->second->query_index;
00864                obj_ref[query_idx].cluster_cloud = supervoxel_clusters.at(
00865                   *it)->voxels_;
00866                obj_ref[query_idx].cluster_vfh_hist = nvfh_hist.clone();
00867                obj_ref[query_idx].cluster_color_hist = ncolor_hist.clone();
00868                obj_ref[query_idx].cluster_normals = supervoxel_clusters.at(
00869                   *it)->normals_;
00870                obj_ref[query_idx].cluster_centroid = supervoxel_clusters.at(
00871                   *it)->centroid_.getVector4fMap();
00872                obj_ref[query_idx].neigbour_pfh = local_phf.clone();
00873                obj_ref[query_idx].flag = false;
00874                matching_surfels[query_idx] = obj_ref[query_idx];
00875                obj_ref[query_idx].match_counter++;
00876             }
00877          }
00878          this->motion_history_.push_back(this->tracker_pose_);
00879          this->previous_pose_ = this->current_pose_;
00880          // std::cout << "Updating Ref Model: " << matching_surfels.size()
00881          //           << "\t Convex: " << convex_local_voxels.size()
00882          //           << std::endl;
00883        
00884          for (std::map<int, ReferenceModel>::iterator it =
00885                  matching_surfels.begin(); it != matching_surfels.end(); it++) {
00886             this->object_reference_->operator[](it->first) = it->second;
00887          }
00888          for (std::map<uint32_t, ReferenceModel*>::iterator it =
00889                  convex_local_voxels.begin(); it != convex_local_voxels.begin();
00890               it++) {
00891             this->object_reference_->push_back(*(it->second));
00892          }
00893          ModelsPtr tmp_model(new Models);
00894          if (this->update_counter_++ == this->history_window_size_) {
00895             for (int i = 0; i < this->object_reference_->size(); i++) {
00896                if (this->object_reference_->operator[](i).match_counter > 0) {
00897                   ReferenceModel renew_model;
00898                   renew_model = this->object_reference_->operator[](i);
00899                   tmp_model->push_back(renew_model);
00900                } else {
00901                   std::cout << "\033[033m OUTDATED MODEL \033[0m" << std::endl;
00902                }
00903             }
00904             this->update_counter_ = 0;
00905             this->object_reference_->clear();
00906             this->object_reference_ = tmp_model;
00907          }       
00908      
00909       } else {
00910          ROS_WARN("TRACKING MODEL CURRENTLY SET TO STATIC\n");
00911       }
00912       template_cloud->clear();
00913       int tmp_counter = 0;
00914       float argmax_lenght = 0.0f;
00915       for (int i = 0; i < this->object_reference_->size(); i++) {
00916          Eigen::Vector4f surfel_centroid = Eigen::Vector4f();
00917          surfel_centroid = this->object_reference_->operator[](
00918             i).cluster_centroid;
00919          surfel_centroid(3) = 0.0f;
00920          float surfel_dist = static_cast<float>(
00921             pcl::distances::l2(surfel_centroid, current_pose_));
00922          if (surfel_dist > argmax_lenght) {
00923             argmax_lenght = surfel_dist;
00924          }
00925          if (surfel_dist < (this->previous_distance_ * growth_rate_)) {            
00926             float probability = 0.0f;
00927             for (int j = 0; j < this->background_reference_->size(); j++) {
00928                ReferenceModel *r_mod = new ReferenceModel;
00929                float prob = this->targetCandidateToReferenceLikelihood<float>(
00930                   this->object_reference_->operator[](i),
00931                   this->background_reference_->operator[](j).cluster_cloud,
00932                   this->background_reference_->operator[](j).cluster_normals,
00933                   this->background_reference_->operator[](j).cluster_centroid,
00934                   r_mod);
00935                if (prob > probability) {
00936                   probability = prob;
00937                }
00938             }
00939             if (probability < 0.60f) {
00940                *template_cloud = *template_cloud + *(
00941                   this->object_reference_->operator[](i).cluster_cloud);   
00942                tmp_counter++;
00943             } else {
00944                ROS_INFO("\033[35m SURFEL REMOVED AS BACKGRND \033[0m");
00945             }
00946          } else {
00947             ROS_INFO("\033[35m SURFEL REMOVED \033[0m]");
00948          }
00949       }
00950       if (argmax_lenght > (growth_rate_ * previous_distance_)) {
00951          argmax_lenght = previous_distance_ * growth_rate_;
00952       } else if (argmax_lenght < ((1 - growth_rate_) * previous_distance_)) {
00953          argmax_lenght = (1 - growth_rate_) * previous_distance_;
00954       }
00955       this->filterCloudForBoundingBoxViz(output, this->background_reference_);
00956       this->previous_distance_ = argmax_lenght;
00957     
00958       // std::cout << "\033[031m TEMPLATE SIZE:  \033[0m" << template_cloud->size()
00959       //           << std::endl;    
00960 
00961       if (tmp_counter < 1) {
00962          template_cloud->clear();
00963          pcl::copyPointCloud<PointT, PointT>(*previous_template_, *template_cloud);
00964       } else {
00965          ROS_INFO("\033[34m UPDATING INFO...\033[0m");
00966          // previous_distance_ = this->templateCloudFilterLenght(template_cloud);
00967          pcl::copyPointCloud<PointT, PointT>(*template_cloud, *previous_template_);
00968          this->object_reference_ = ModelsPtr(new Models);
00969          this->processInitCloud(template_cloud, this->object_reference_);
00970       }
00971       std::cout << "\033[038m REFERENCE INFO \033[0m"
00972                 << object_reference_->size() << std::endl;
00973       cloud->clear();
00974       pcl::copyPointCloud<PointT, PointT>(*output, *cloud);
00975       pcl::PointIndices tdp_ind;
00976       for (int i = 0; i < cloud->size(); i++) {
00977          tdp_ind.indices.push_back(i);
00978       }
00979       if (this->update_filter_template_) {
00980          sensor_msgs::PointCloud2 ros_templ;
00981          pcl::toROSMsg(*template_cloud, ros_templ);
00982          ros_templ.header = header;
00983          this->pub_templ_.publish(ros_templ);
00984       }
00985       // visualization of target surfels
00986       std::vector<pcl::PointIndices> all_indices;
00987       all_indices.push_back(tdp_ind);
00988       jsk_recognition_msgs::ClusterPointIndices tdp_indices;
00989       tdp_indices.cluster_indices = pcl_conversions::convertToROSPointIndices(
00990          all_indices, header);
00991       tdp_indices.header = header;
00992       this->pub_tdp_.publish(tdp_indices);
00993     
00994       // for visualization of supervoxel
00995       sensor_msgs::PointCloud2 ros_svcloud;
00996       jsk_recognition_msgs::ClusterPointIndices ros_svindices;
00997       this->publishSupervoxel(
00998          supervoxel_clusters, ros_svcloud, ros_svindices, header);
00999       pub_scloud_.publish(ros_svcloud);
01000       pub_sindices_.publish(ros_svindices);
01001 
01002       // for visualization of inliers
01003       sensor_msgs::PointCloud2 ros_inliers;
01004       pcl::toROSMsg(*inliers, ros_inliers);
01005       ros_inliers.header = header;
01006       this->pub_inliers_.publish(ros_inliers);
01007     
01008       // for visualization of initial centroids
01009       sensor_msgs::PointCloud2 ros_centroids;
01010       pcl::toROSMsg(*est_centroid_cloud, ros_centroids);
01011       ros_centroids.header = header;
01012       this->pub_centroids_.publish(ros_centroids);
01013     
01014       // for visualization of normal
01015       sensor_msgs::PointCloud2 rviz_normal;
01016       pcl::toROSMsg(*centroid_normal, rviz_normal);
01017       rviz_normal.header = header;
01018       this->pub_normal_.publish(rviz_normal);
01019    }
01020 
01021    void TargetAdaptiveTracking::processVoxelForReferenceModel(
01022       const std::map <uint32_t, pcl::Supervoxel<PointT>::Ptr> supervoxel_clusters,
01023       const std::multimap<uint32_t, uint32_t> supervoxel_adjacency,
01024       const uint32_t match_index,
01025       TargetAdaptiveTracking::ReferenceModel *ref_model)
01026    {
01027       if (supervoxel_clusters.empty() || supervoxel_adjacency.empty()) {
01028          ROS_ERROR("ERROR: empty data for updating voxel ref model");
01029          return;
01030       }
01031       if (supervoxel_clusters.at(
01032              match_index)->voxels_->size() > this->min_cluster_size_) {
01033          ref_model->flag = false;
01034          ref_model->cluster_cloud = supervoxel_clusters.at(
01035             match_index)->voxels_;
01036          ref_model->cluster_normals = supervoxel_clusters.at(
01037             match_index)->normals_;
01038          ref_model->cluster_centroid = supervoxel_clusters.at(
01039             match_index)->centroid_.getVector4fMap();
01040          this->computeCloudClusterRPYHistogram(
01041             ref_model->cluster_cloud,
01042             ref_model->cluster_normals,
01043             ref_model->cluster_vfh_hist);        
01044          this->computeColorHistogram(
01045             ref_model->cluster_cloud,
01046             ref_model->cluster_color_hist);
01047          std::vector<uint32_t> adjacent_voxels;
01048          for (std::multimap<uint32_t, uint32_t>::const_iterator adjacent_itr =
01049                  supervoxel_adjacency.equal_range(match_index).first;
01050               adjacent_itr != supervoxel_adjacency.equal_range(
01051                  match_index).second; ++adjacent_itr) {
01052             pcl::Supervoxel<PointT>::Ptr neighbor_supervoxel =
01053                supervoxel_clusters.at(adjacent_itr->second);
01054             if (neighbor_supervoxel->voxels_->size() >
01055                 min_cluster_size_) {
01056                adjacent_voxels.push_back(adjacent_itr->second);
01057             }
01058          }
01059          AdjacentInfo a_info;
01060          a_info.adjacent_voxel_indices[match_index] = adjacent_voxels;
01061          a_info.voxel_index = match_index;
01062          ref_model->cluster_neigbors = a_info;
01063          std::map<uint32_t, std::vector<uint32_t> > local_adj;
01064          local_adj[match_index] = adjacent_voxels;
01065          this->computeLocalPairwiseFeautures(
01066             supervoxel_clusters, local_adj, ref_model->neigbour_pfh);
01067       } else {
01068          ref_model->flag = true;
01069       }
01070    }
01071 
01072    template<class T>
01073    T TargetAdaptiveTracking::targetCandidateToReferenceLikelihood(
01074       const TargetAdaptiveTracking::ReferenceModel &reference_model,
01075       const pcl::PointCloud<PointT>::Ptr cloud,
01076       const pcl::PointCloud<pcl::Normal>::Ptr normal,
01077       const Eigen::Vector4f &centroid,
01078       ReferenceModel *voxel_model)
01079    {
01080       if (cloud->empty() || normal->empty()) {
01081          return 0.0f;
01082       }
01083       cv::Mat vfh_hist;
01084       this->computeCloudClusterRPYHistogram(cloud, normal, vfh_hist);
01085       cv::Mat color_hist;
01086       this->computeColorHistogram(cloud, color_hist);
01087       T dist_vfh = static_cast<T>(
01088          cv::compareHist(vfh_hist,
01089                          reference_model.cluster_vfh_hist,
01090                          CV_COMP_BHATTACHARYYA));
01091       T dist_col = static_cast<T>(
01092          cv::compareHist(color_hist,
01093                          reference_model.cluster_color_hist,
01094                          CV_COMP_BHATTACHARYYA));
01095       T probability = std::exp(-1 * this->vfh_scaling_ * dist_vfh) *
01096          std::exp(-1 * this->color_scaling_ * dist_col);
01097       bool convex_weight = false;
01098       if (convex_weight) {
01099          Eigen::Vector4f n_normal = this->cloudMeanNormal(normal);
01100          Eigen::Vector4f n_centroid = centroid;
01101          Eigen::Vector4f c_normal = this->cloudMeanNormal(
01102             reference_model.cluster_normals);
01103          Eigen::Vector4f c_centroid = reference_model.cluster_centroid;
01104          float convx_prob = this->localVoxelConvexityLikelihood<float>(
01105             c_centroid, c_normal, n_centroid, n_normal);
01106          probability * convx_prob;
01107       }
01108       voxel_model->cluster_vfh_hist = vfh_hist.clone();
01109       voxel_model->cluster_color_hist = color_hist.clone();
01110       return probability;
01111    }
01112 
01113    template<class T>
01114    T TargetAdaptiveTracking::localVoxelConvexityLikelihood(
01115       Eigen::Vector4f c_centroid,
01116       Eigen::Vector4f c_normal,
01117       Eigen::Vector4f n_centroid,
01118       Eigen::Vector4f n_normal) {
01119       c_centroid(3) = 0.0f;
01120       c_normal(3) = 0.0f;
01121       n_centroid(3) = 0.0f;
01122       n_normal(3) = 0.0f;
01123       T weight = 1.0f;
01124       if ((n_centroid - c_centroid).dot(n_normal) > 0) {
01125          weight = static_cast<T>(std::pow(1 - (c_normal.dot(n_normal)), 2));
01126          return 1.0f;
01127       } else {
01128          // weight = static_cast<T>(1 - (c_normal.dot(n_normal)));
01129          return 0.0f;
01130       }
01131       if (std::isnan(weight)) {
01132          return 0.0f;
01133       }
01134       T probability = std::exp(-1 * weight);
01135       return probability;
01136    }
01137 
01138    void TargetAdaptiveTracking::backgroundReferenceLikelihood(
01139       const ModelsPtr background_reference,
01140       const ModelsPtr target_voxels,
01141       std::map<uint32_t, float> max_prob)
01142    {
01143       if (background_reference->empty() || target_voxels->empty()) {
01144          ROS_ERROR("INPUT DATA IS EMPTY");
01145       }
01146       for (int j = 0; j < target_voxels->size(); j++) {
01147          float probability = 0.0f;
01148          for (int i = 0; i < background_reference->size(); i++) {
01149             ReferenceModel *mod = new ReferenceModel;
01150             float prob = this->targetCandidateToReferenceLikelihood<float>(
01151                background_reference->operator[](i),
01152                target_voxels->operator[](j).cluster_cloud,
01153                target_voxels->operator[](j).cluster_normals,
01154                target_voxels->operator[](j).cluster_centroid,
01155                mod);
01156             if (prob > probability) {
01157                probability = prob;
01158             }
01159          }
01160          max_prob[target_voxels->operator[](j).supervoxel_index] = probability;
01161       }
01162    }
01163 
01164    template<class T>
01165    void TargetAdaptiveTracking::estimatePointCloudNormals(
01166       const pcl::PointCloud<PointT>::Ptr cloud,
01167       pcl::PointCloud<pcl::Normal>::Ptr normals,
01168       const T k, bool use_knn) const {
01169       if (cloud->empty()) {
01170          ROS_ERROR("ERROR: The Input cloud is Empty.....");
01171          return;
01172       }
01173       pcl::NormalEstimationOMP<PointT, pcl::Normal> ne;
01174       ne.setInputCloud(cloud);
01175       ne.setNumberOfThreads(8);
01176       pcl::search::KdTree<PointT>::Ptr tree (new pcl::search::KdTree<PointT> ());
01177       ne.setSearchMethod(tree);
01178       if (use_knn) {
01179          ne.setKSearch(k);
01180       } else {
01181          ne.setRadiusSearch(k);
01182       }    ne.compute(*normals);
01183    }
01184 
01185    void TargetAdaptiveTracking::computeCloudClusterRPYHistogram(
01186       const pcl::PointCloud<PointT>::Ptr cloud,
01187       const pcl::PointCloud<pcl::Normal>::Ptr normal,
01188       cv::Mat &histogram) const
01189    {
01190       if (cloud->empty() || normal->empty()){
01191          ROS_ERROR("ERROR: Empty Input");
01192          return;
01193       }
01194       bool is_gfpfh = false;
01195       bool is_vfh = true;
01196       bool is_cvfh = false;
01197       if (is_gfpfh) {
01198          pcl::PointCloud<pcl::PointXYZL>::Ptr object(
01199             new pcl::PointCloud<pcl::PointXYZL>);
01200          for (int i = 0; i < cloud->size(); i++) {
01201             pcl::PointXYZL pt;
01202             pt.x = cloud->points[i].x;
01203             pt.y = cloud->points[i].y;
01204             pt.z = cloud->points[i].z;
01205             pt.label = 1;
01206             object->push_back(pt);
01207          }
01208          pcl::GFPFHEstimation<
01209             pcl::PointXYZL, pcl::PointXYZL, pcl::GFPFHSignature16> gfpfh;
01210          gfpfh.setInputCloud(object);
01211          gfpfh.setInputLabels(object);
01212          gfpfh.setOctreeLeafSize(0.01);
01213          gfpfh.setNumberOfClasses(1);
01214          pcl::PointCloud<pcl::GFPFHSignature16>::Ptr descriptor(
01215             new pcl::PointCloud<pcl::GFPFHSignature16>);
01216          gfpfh.compute(*descriptor);
01217          histogram = cv::Mat(sizeof(char), 16, CV_32F);
01218          for (int i = 0; i < histogram.cols; i++) {
01219             histogram.at<float>(0, i) = descriptor->points[0].histogram[i];
01220 
01221          }
01222       }
01223       if (is_vfh) {
01224          pcl::VFHEstimation<PointT,
01225                             pcl::Normal,
01226                             pcl::VFHSignature308> vfh;
01227          vfh.setInputCloud(cloud);
01228          vfh.setInputNormals(normal);
01229          pcl::search::KdTree<PointT>::Ptr tree(
01230             new pcl::search::KdTree<PointT>);
01231          vfh.setSearchMethod(tree);
01232          pcl::PointCloud<pcl::VFHSignature308>::Ptr vfhs(
01233             new pcl::PointCloud<pcl::VFHSignature308>());
01234          vfh.compute(*vfhs);
01235          histogram = cv::Mat(sizeof(char), 308, CV_32F);
01236          for (int i = 0; i < histogram.cols; i++) {
01237             histogram.at<float>(0, i) = vfhs->points[0].histogram[i];
01238          }
01239       }
01240       if (is_cvfh) {
01241          pcl::CVFHEstimation<PointT,
01242                              pcl::Normal,
01243                              pcl::VFHSignature308> cvfh;
01244          cvfh.setInputCloud(cloud);
01245          cvfh.setInputNormals(normal);
01246          pcl::search::KdTree<PointT>::Ptr tree(
01247             new pcl::search::KdTree<PointT>);
01248          cvfh.setSearchMethod(tree);
01249          cvfh.setEPSAngleThreshold(5.0f / 180.0f * M_PI);
01250          cvfh.setCurvatureThreshold(1.0f);
01251          cvfh.setNormalizeBins(false);
01252          pcl::PointCloud<pcl::VFHSignature308>::Ptr cvfhs(
01253             new pcl::PointCloud<pcl::VFHSignature308>());
01254          cvfh.compute(*cvfhs);
01255          histogram = cv::Mat(sizeof(char), 308, CV_32F);
01256          for (int i = 0; i < histogram.cols; i++) {
01257             histogram.at<float>(0, i) = cvfhs->points[0].histogram[i];
01258          }
01259       }
01260    }
01261 
01262    void TargetAdaptiveTracking::computeColorHistogram(
01263       const pcl::PointCloud<PointT>::Ptr cloud,
01264       cv::Mat &hist, const int hBin, const int sBin, bool is_norm) const
01265    {
01266       cv::Mat pixels = cv::Mat::zeros(
01267          sizeof(char), static_cast<int>(cloud->size()), CV_8UC3);
01268       for (int i = 0; i < cloud->size(); i++) {
01269          cv::Vec3b pix_val;
01270          pix_val[0] = cloud->points[i].b;
01271          pix_val[1] = cloud->points[i].g;
01272          pix_val[2] = cloud->points[i].r;
01273          pixels.at<cv::Vec3b>(0, i) = pix_val;
01274       }
01275       cv::Mat hsv;
01276       cv::cvtColor(pixels, hsv, CV_BGR2HSV);
01277       int histSize[] = {hBin, sBin};
01278       float h_ranges[] = {0, 180};
01279       float s_ranges[] = {0, 256};
01280       const float* ranges[] = {h_ranges, s_ranges};
01281       int channels[] = {0, 1};
01282       cv::calcHist(
01283          &hsv, 1, channels, cv::Mat(), hist, 2, histSize, ranges, true, false);
01284       if (is_norm) {
01285          cv::normalize(hist, hist, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());
01286       }
01287    }
01288 
01289    void TargetAdaptiveTracking::computePointFPFH(
01290       const pcl::PointCloud<PointT>::Ptr cloud,
01291       const pcl::PointCloud<pcl::Normal>::Ptr normals,
01292       cv::Mat &histogram, bool holistic) const
01293    {
01294       if (cloud->empty() || normals->empty()) {
01295          ROS_ERROR("-- ERROR: cannot compute FPFH");
01296          return;
01297       }
01298       pcl::FPFHEstimationOMP<PointT, pcl::Normal, pcl::FPFHSignature33> fpfh;
01299       fpfh.setInputCloud(cloud);
01300       fpfh.setInputNormals(normals);
01301       pcl::search::KdTree<PointT>::Ptr tree (new pcl::search::KdTree<PointT>);
01302       fpfh.setSearchMethod(tree);
01303       pcl::PointCloud<pcl::FPFHSignature33>::Ptr fpfhs(
01304          new pcl::PointCloud<pcl::FPFHSignature33> ());
01305       fpfh.setRadiusSearch(0.05);
01306       fpfh.compute(*fpfhs);
01307       const int hist_dim = 33;
01308       if (holistic) {
01309          histogram = cv::Mat::zeros(1, hist_dim, CV_32F);
01310          for (int i = 0; i < fpfhs->size(); i++) {
01311             for (int j = 0; j < hist_dim; j++) {
01312                histogram.at<float>(0, j) += fpfhs->points[i].histogram[j];
01313             }
01314          }
01315       } else {
01316          histogram = cv::Mat::zeros(
01317             static_cast<int>(fpfhs->size()), hist_dim, CV_32F);
01318          for (int i = 0; i < fpfhs->size(); i++) {
01319             for (int j = 0; j < hist_dim; j++) {
01320                histogram.at<float>(i, j) = fpfhs->points[i].histogram[j];
01321             }
01322          }
01323       }
01324       cv::normalize(histogram, histogram, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());
01325    }
01326 
01327    std::vector<pcl::PointIndices::Ptr>
01328    TargetAdaptiveTracking::clusterPointIndicesToPointIndices(
01329       const jsk_recognition_msgs::ClusterPointIndicesConstPtr &indices_mgs)
01330    {
01331       std::vector<pcl::PointIndices::Ptr> ret;
01332       for (int i = 0; i < indices_mgs->cluster_indices.size(); i++) {
01333          std::vector<int> indices = indices_mgs->cluster_indices[i].indices;
01334          pcl::PointIndices::Ptr pcl_indices (new pcl::PointIndices);
01335          pcl_indices->indices = indices;
01336          ret.push_back(pcl_indices);
01337       }
01338       return ret;
01339    }
01340 
01341    void TargetAdaptiveTracking::estimatedPFPose(
01342       const geometry_msgs::PoseStamped::ConstPtr &pose_msg,
01343       PointXYZRPY &motion_displacement)
01344    {
01345       PointXYZRPY current_pose;
01346       current_pose.x = pose_msg->pose.position.x;
01347       current_pose.y = pose_msg->pose.position.y;
01348       current_pose.z = pose_msg->pose.position.z;
01349       current_pose.roll = pose_msg->pose.orientation.x;
01350       current_pose.pitch = pose_msg->pose.orientation.y;
01351       current_pose.yaw = pose_msg->pose.orientation.z;
01352       current_pose.weight = pose_msg->pose.orientation.w;
01353       this->tracker_pose_ = current_pose;
01354       this->current_pose_(0) = current_pose.x;
01355       this->current_pose_(1) = current_pose.y;
01356       this->current_pose_(2) = current_pose.z;
01357       this->current_pose_(3) = 0.0f;
01358       if (!std::isnan(current_pose.x) && !std::isnan(current_pose.y) &&
01359           !std::isnan(current_pose.z)) {
01360          if (!this->motion_history_.empty()) {
01361             int last_index = static_cast<int>(
01362                this->motion_history_.size()) - 1;
01363             motion_displacement.x = current_pose.x -
01364                this->motion_history_[last_index].x;
01365             motion_displacement.y = current_pose.y -
01366                this->motion_history_[last_index].y;
01367             motion_displacement.z = current_pose.z -
01368                this->motion_history_[last_index].z;
01369             motion_displacement.roll = current_pose.roll -
01370                this->motion_history_[last_index].roll;
01371             motion_displacement.pitch = current_pose.pitch -
01372                this->motion_history_[last_index].pitch;
01373             motion_displacement.yaw = current_pose.yaw -
01374                this->motion_history_[last_index].yaw;
01375          } else {
01376             this->motion_history_.push_back(current_pose);
01377          }
01378       } else {
01379          // pertubate with history error weight
01380       }
01381    }
01382 
01383    void TargetAdaptiveTracking::compute3DCentroids(
01384       const pcl::PointCloud<PointT>::Ptr cloud,
01385       Eigen::Vector4f &centre) const
01386    {
01387       if (cloud->empty()) {
01388          ROS_ERROR("ERROR: empty cloud for centroid");
01389          centre = Eigen::Vector4f(-1, -1, -1, -1);
01390          return;
01391       }
01392       Eigen::Vector4f centroid;
01393       pcl::compute3DCentroid<PointT, float>(*cloud, centroid);
01394       if (!std::isnan(centroid(0)) && !std::isnan(centroid(1)) && !std::isnan(centroid(2))) {
01395          centre = centroid;
01396       }
01397    }
01398 
01399    Eigen::Vector4f TargetAdaptiveTracking::cloudMeanNormal(
01400       const pcl::PointCloud<pcl::Normal>::Ptr normal,
01401       bool isnorm)
01402    {
01403       if (normal->empty()) {
01404          return Eigen::Vector4f(0, 0, 0, 0);
01405       }
01406       float x = 0.0f;
01407       float y = 0.0f;
01408       float z = 0.0f;
01409       int icounter = 0;
01410       for (int i = 0; i < normal->size(); i++) {
01411          if ((!std::isnan(normal->points[i].normal_x)) &&
01412              (!std::isnan(normal->points[i].normal_y)) &&
01413              (!std::isnan(normal->points[i].normal_z))) {
01414             x += normal->points[i].normal_x;
01415             y += normal->points[i].normal_y;
01416             z += normal->points[i].normal_z;
01417             icounter++;
01418          }
01419       }
01420       Eigen::Vector4f n_mean = Eigen::Vector4f(
01421          x/static_cast<float>(icounter),
01422          y/static_cast<float>(icounter),
01423          z/static_cast<float>(icounter),
01424          0.0f);
01425       if (isnorm) {
01426          n_mean.normalize();
01427       }
01428       return n_mean;
01429    }
01430 
01431    void TargetAdaptiveTracking::computeScatterMatrix(
01432       const pcl::PointCloud<PointT>::Ptr cloud,
01433       const Eigen::Vector4f centroid)
01434    {
01435       if (cloud->empty()) {
01436          ROS_ERROR("Empty input for computing Scatter Matrix");
01437          return;
01438       }
01439       const int rows = 3;
01440       const int cols = 3;
01441       Eigen::MatrixXf scatter_matrix = Eigen::Matrix3f::Zero(cols, rows);
01442       for (int i = 0; i < cloud->size(); i++) {
01443          Eigen::Vector3f de_mean = Eigen::Vector3f();
01444          de_mean(0) = cloud->points[i].x - centroid(0);
01445          de_mean(1) = cloud->points[i].y - centroid(1);
01446          de_mean(2) = cloud->points[i].z - centroid(2);
01447          Eigen::Vector3f t_de_mean = de_mean.transpose();
01448          for (int y = 0; y < rows; y++) {
01449             for (int x = 0; x < cols; x++) {
01450                scatter_matrix(y, x) += de_mean(y) * t_de_mean(x);
01451             }
01452          }
01453       }
01454       Eigen::EigenSolver<Eigen::MatrixXf> eigen_solver(scatter_matrix, true);
01455       // Eigen::complex<float> eigen_values;
01456    }
01457 
01458    float TargetAdaptiveTracking::computeCoherency(
01459       const float dist, const float weight) {
01460       if (std::isnan(dist)) {
01461          return 0.0f;
01462       }
01463       return static_cast<float>(1/(1 + (weight * std::pow(dist, 2))));
01464    }
01465 
01466    pcl::PointXYZRGBNormal
01467    TargetAdaptiveTracking::convertVector4fToPointXyzRgbNormal(
01468       const Eigen::Vector4f &centroid,
01469       const Eigen::Vector4f &normal,
01470       const cv::Scalar color) {
01471       pcl::PointXYZRGBNormal pt;
01472       pt.x = centroid(0);
01473       pt.y = centroid(1);
01474       pt.z = centroid(2);
01475       pt.r = color.val[2];
01476       pt.g = color.val[1];
01477       pt.b = color.val[0];
01478       pt.normal_x = normal(0);
01479       pt.normal_y = normal(1);
01480       pt.normal_z = normal(2);
01481       return pt;
01482    }
01483 
01484    template<typename T>
01485    void TargetAdaptiveTracking::getRotationMatrixFromRPY(
01486       const PointXYZRPY &motion_displacement,
01487       Eigen::Matrix<T, 3, 3> &rotation)
01488    {
01489       tf::Quaternion tf_quaternion;
01490       tf_quaternion.setEulerZYX(motion_displacement.yaw,
01491                                 motion_displacement.pitch,
01492                                 motion_displacement.roll);
01493       Eigen::Quaternion<float> quaternion = Eigen::Quaternion<float>(
01494          tf_quaternion.w(), tf_quaternion.x(),
01495          tf_quaternion.y(), tf_quaternion.z());
01496       rotation.template block<3, 3>(0, 0) =
01497          quaternion.normalized().toRotationMatrix();
01498    }
01499 
01500    void TargetAdaptiveTracking::computeLocalPairwiseFeautures(
01501       const std::map <uint32_t, pcl::Supervoxel<PointT>::Ptr> &
01502       supervoxel_clusters, const std::map<uint32_t, std::vector<uint32_t> > &
01503       adjacency_list, cv::Mat &histogram, const int feature_count)
01504    {
01505       if (supervoxel_clusters.empty() || adjacency_list.empty()) {
01506          std::cout << supervoxel_clusters.size()  << "\t"
01507                    << adjacency_list.size() << std::endl;
01508          ROS_ERROR("ERROR: empty data returing no local feautures");
01509          return;
01510       }
01511       float d_pi = 1.0f / (2.0f * static_cast<float> (M_PI));
01512       histogram = cv::Mat::zeros(1, this->bin_size_ * feature_count, CV_32F);
01513       for (std::map<uint32_t, std::vector<uint32_t> >::const_iterator it =
01514               adjacency_list.begin(); it != adjacency_list.end(); it++) {
01515          pcl::Supervoxel<PointT>::Ptr supervoxel =
01516             supervoxel_clusters.at(it->first);
01517          Eigen::Vector4f c_normal = this->cloudMeanNormal(supervoxel->normals_);
01518          std::map<uint32_t, Eigen::Vector4f> cache_normals;
01519          int icounter = 0;
01520          for (std::vector<uint32_t>::const_iterator itr = it->second.begin();
01521               itr != it->second.end(); itr++) {
01522             pcl::Supervoxel<PointT>::Ptr neighbor_supervoxel =
01523                supervoxel_clusters.at(*itr);
01524             Eigen::Vector4f n_normal = this->cloudMeanNormal(
01525                neighbor_supervoxel->normals_);
01526             float alpha;
01527             float phi;
01528             float theta;
01529             float distance;
01530             pcl::computePairFeatures(
01531                supervoxel->centroid_.getVector4fMap(), c_normal,
01532                neighbor_supervoxel->centroid_.getVector4fMap(),
01533                n_normal, alpha, phi, theta, distance);
01534             int bin_index[feature_count];
01535             bin_index[0] = static_cast<int>(
01536                std::floor(this->bin_size_ * ((alpha + M_PI) * d_pi)));
01537             bin_index[1] = static_cast<int>(
01538                std::floor(this->bin_size_ * ((phi + 1.0f) * 0.5f)));
01539             bin_index[2] = static_cast<int>(
01540                std::floor(this->bin_size_ * ((theta + 1.0f) * 0.5f)));
01541             for (int i = 0; i < feature_count; i++) {
01542                if (bin_index[i] < 0) {
01543                   bin_index[i] = 0;
01544                }
01545                if (bin_index[i] >= bin_size_) {
01546                   bin_index[i] = bin_size_ - sizeof(char);
01547                }
01548                // h_index += h_p + bin_index[i];
01549                // h_p *= this->bin_size_;
01550                histogram.at<float>(
01551                   0, bin_index[i] + (i * this->bin_size_)) += 1;
01552             }
01553             cache_normals[*itr] = n_normal;
01554             icounter++;
01555          }
01556          for (std::vector<uint32_t>::const_iterator itr = it->second.begin();
01557               itr != it->second.end(); itr++) {
01558             cache_normals.find(*itr)->second;
01559             for (std::vector<uint32_t>::const_iterator itr_in =
01560                     it->second.begin(); itr_in != it->second.end(); itr_in++) {
01561                if (*itr != *itr_in) {
01562                   float alpha;
01563                   float phi;
01564                   float theta;
01565                   float distance;
01566                   pcl::computePairFeatures(
01567                      supervoxel_clusters.at(*itr)->centroid_.getVector4fMap(),
01568                      cache_normals.find(*itr)->second, supervoxel_clusters.at(
01569                         *itr_in)->centroid_.getVector4fMap(),
01570                      cache_normals.find(*itr_in)->second,
01571                      alpha, phi, theta, distance);
01572                   int bin_index[feature_count];
01573                   bin_index[0] = static_cast<int>(
01574                      std::floor(this->bin_size_ * ((alpha + M_PI) * d_pi)));
01575                   bin_index[1] = static_cast<int>(
01576                      std::floor(this->bin_size_ * ((phi + 1.0f) * 0.5f)));
01577                   bin_index[2] = static_cast<int>(
01578                      std::floor(this->bin_size_ * ((theta + 1.0f) * 0.5f)));
01579                   for (int i = 0; i < feature_count; i++) {
01580                      if (bin_index[i] < 0) {
01581                         bin_index[i] = 0;
01582                      }
01583                      if (bin_index[i] >= bin_size_) {
01584                         bin_index[i] = bin_size_ - sizeof(char);
01585                      }
01586                      histogram.at<float>(
01587                         0, bin_index[i] + (i * this->bin_size_)) += 1;
01588                   }
01589                }
01590             }
01591          }
01592          cv::normalize(
01593             histogram, histogram, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());
01594       }
01595    }
01596 
01597 
01598    float TargetAdaptiveTracking::templateCloudFilterLenght(
01599       const pcl::PointCloud<PointT>::Ptr cloud)
01600    {
01601       if (cloud->empty()) {
01602          ROS_ERROR("ERROR! Input Cloud is Empty");
01603          return -1.0f;
01604       }
01605       Eigen::Vector4f pivot_pt;
01606       pcl::compute3DCentroid<PointT, float>(*cloud, pivot_pt);
01607       Eigen::Vector4f max_pt;
01608       pcl::getMaxDistance<PointT>(*cloud, pivot_pt, max_pt);
01609       pivot_pt(3) = 0.0f;
01610       max_pt(3) = 0.0f;
01611       float dist = static_cast<float>(pcl::distances::l2(max_pt, pivot_pt));
01612       return (dist);
01613    }
01614 
01615    bool TargetAdaptiveTracking::filterPointCloud(
01616       pcl::PointCloud<PointT>::Ptr cloud,
01617       const Eigen::Vector4f tracker_position,
01618       const ModelsPtr template_model,
01619       const float scaling_factor)
01620    {
01621       if (cloud->empty() || template_model->empty()) {
01622          ROS_ERROR("ERROR! Input data is empty is Empty");
01623          return false;
01624       }
01625       pcl::PointCloud<PointT>::Ptr template_cloud(new pcl::PointCloud<PointT>);
01626       for (int i = 0; i < template_model->size(); i++) {
01627          *template_cloud = *template_cloud + *(
01628             template_model->operator[](i).cluster_cloud);
01629       }
01630       float filter_distance = this->templateCloudFilterLenght(template_cloud);
01631       filter_distance *= scaling_factor;
01632       if (filter_distance < 0.05f) {
01633          return false;
01634       }
01635       pcl::PointCloud<PointT>::Ptr cloud_filter(new pcl::PointCloud<PointT>);
01636       pcl::PassThrough<PointT> pass;
01637       pass.setInputCloud(cloud);
01638       pass.setFilterFieldName("x");
01639       float min_x = tracker_position(0) - filter_distance;
01640       float max_x = tracker_position(0) + filter_distance;
01641       pass.setFilterLimits(min_x, max_x);
01642       pass.filter(*cloud_filter);
01643       pass.setInputCloud(cloud_filter);
01644       pass.setFilterFieldName("y");
01645       float min_y = tracker_position(1) - filter_distance;
01646       float max_y = tracker_position(1) + filter_distance;
01647       pass.setFilterLimits(min_y, max_y);
01648       pass.filter(*cloud_filter);
01649       pass.setInputCloud(cloud_filter);
01650       pass.setFilterFieldName("z");
01651       float min_z = tracker_position(2) - filter_distance;
01652       float max_z = tracker_position(2) + filter_distance;
01653       pass.setFilterLimits(min_z, max_z);
01654       pass.filter(*cloud_filter);
01655       if (cloud_filter->empty()) {
01656          return false;
01657       }
01658       cloud->empty();
01659       pcl::copyPointCloud<PointT, PointT>(*cloud_filter, *cloud);
01660       return true;
01661    }
01662 
01663    void TargetAdaptiveTracking::transformModelPrimitives(
01664       const ModelsPtr &obj_ref,
01665       ModelsPtr trans_models,
01666       const Eigen::Affine3f &transform_model)
01667    {
01668       if (obj_ref->empty()) {
01669          ROS_ERROR("ERROR! No Object Model to Transform");
01670          return;
01671       }
01672       for (int i = 0; i < obj_ref->size(); i++) {
01673          pcl::PointCloud<PointT>::Ptr trans_cloud(
01674             new pcl::PointCloud<PointT>);
01675          pcl::transformPointCloud(*(obj_ref->operator[](i).cluster_cloud),
01676                                   *trans_cloud, transform_model);
01677          Eigen::Vector4f trans_centroid = Eigen::Vector4f();
01678          pcl::compute3DCentroid<PointT, float>(
01679             *trans_cloud, trans_centroid);
01680          trans_models->push_back(obj_ref->operator[](i));
01681          trans_models->operator[](i).cluster_cloud = trans_cloud;
01682          trans_models->operator[](i).cluster_centroid = trans_centroid;
01683       }
01684    }
01685 
01686    void TargetAdaptiveTracking::filterCloudForBoundingBoxViz(
01687       pcl::PointCloud<PointT>::Ptr cloud,
01688       const ModelsPtr background_reference,
01689       const float threshold)
01690    {
01691       if (cloud->empty() || background_reference->empty()) {
01692          ROS_ERROR("ERROR! EMPTY DATA FOR BOUNDING BOX CLOUD");
01693          return;
01694       }
01695       ModelsPtr tmp_model(new Models);
01696       this->processInitCloud(cloud, tmp_model);
01697       pcl::PointCloud<PointT>::Ptr tmp_cloud(new pcl::PointCloud<PointT>);
01698       for (int i = 0; i < tmp_model->size(); i++) {
01699          Eigen::Vector4f surfel_centroid = Eigen::Vector4f();
01700          surfel_centroid = tmp_model->operator[](i).cluster_centroid;
01701          surfel_centroid(3) = 0.0f;
01702          float surfel_dist = static_cast<float>(
01703             pcl::distances::l2(surfel_centroid, current_pose_));
01704          if (surfel_dist < (this->previous_distance_ * growth_rate_)) {
01705             float probability = 0.0f;
01706             for (int j = 0; j < background_reference->size(); j++) {
01707                ReferenceModel *r_mod = new ReferenceModel;
01708                float prob = this->targetCandidateToReferenceLikelihood<float>(
01709                   tmp_model->operator[](i),
01710                   background_reference->operator[](j).cluster_cloud,
01711                   background_reference->operator[](j).cluster_normals,
01712                   background_reference->operator[](j).cluster_centroid,
01713                   r_mod);
01714                if (prob > probability) {
01715                   probability = prob;
01716                }
01717             }
01718             if (probability < 0.60f) {
01719                *tmp_cloud = *tmp_cloud + *(
01720                   tmp_model->operator[](i).cluster_cloud);
01721             } else {
01722                this->object_reference_->push_back(tmp_model->operator[](i));
01723             }
01724          }
01725       }
01726       if (tmp_cloud->size() > (static_cast<int>(cloud->size() / 4))) {
01727          cloud->clear();
01728          pcl::copyPointCloud<PointT, PointT>(*tmp_cloud, *cloud);
01729       }
01730    }
01731 
01732    template<typename T, typename U, typename V>
01733    cv::Scalar TargetAdaptiveTracking::plotJetColour(
01734       T v, U vmin, V vmax)
01735    {
01736       cv::Scalar c = cv::Scalar(0.0, 0.0, 0.0);
01737       T dv;
01738       if (v < vmin)
01739          v = vmin;
01740       if (v > vmax)
01741          v = vmax;
01742       dv = vmax - vmin;
01743       if (v < (vmin + 0.25 * dv)) {
01744          c.val[0] = 0;
01745          c.val[1] = 4 * (v - vmin) / dv;
01746       } else if (v < (vmin + 0.5 * dv)) {
01747          c.val[0] = 0;
01748          c.val[2] = 1 + 4 * (vmin + 0.25 * dv - v) / dv;
01749       } else if (v < (vmin + 0.75 * dv)) {
01750          c.val[0] = 4 * (v - vmin - 0.5 * dv) / dv;
01751          c.val[2] = 0;
01752       } else {
01753          c.val[1] = 1 + 4 * (vmin + 0.75 * dv - v) / dv;
01754          c.val[2] = 0;
01755       }
01756       return(c);
01757    }
01758 
01759    void TargetAdaptiveTracking::supervoxelSegmentation(
01760       const pcl::PointCloud<PointT>::Ptr cloud,
01761       std::map<uint32_t, pcl::Supervoxel<PointT>::Ptr > &supervoxel_clusters,
01762       std::multimap<uint32_t, uint32_t> &supervoxel_adjacency,
01763       const float seed_resolution)
01764    {
01765       if (cloud->empty() || seed_resolution <= 0.0f) {
01766          ROS_ERROR("ERROR: Supervoxel input cloud empty...\n Incorrect Seed");
01767          return;
01768       } 
01769       boost::mutex::scoped_lock lock(mutex_);
01770       pcl::SupervoxelClustering<PointT> super(
01771          voxel_resolution_,
01772          static_cast<double>(seed_resolution),
01773          use_transform_);
01774       super.setInputCloud(cloud);
01775       super.setColorImportance(color_importance_);
01776       super.setSpatialImportance(spatial_importance_);
01777       super.setNormalImportance(normal_importance_);
01778       supervoxel_clusters.clear();
01779       super.extract(supervoxel_clusters);
01780       super.getSupervoxelAdjacency(supervoxel_adjacency);
01781    }
01782 
01783    void TargetAdaptiveTracking::supervoxelSegmentation(
01784       const pcl::PointCloud<PointT>::Ptr cloud,
01785       std::map<uint32_t, pcl::Supervoxel<PointT>::Ptr > &supervoxel_clusters,
01786       std::multimap<uint32_t, uint32_t> &supervoxel_adjacency)
01787    {
01788       if (cloud->empty()) {
01789          ROS_ERROR("ERROR: Supervoxel input cloud empty...");
01790          return;
01791       }
01792       boost::mutex::scoped_lock lock(mutex_);
01793       pcl::SupervoxelClustering<PointT> super(voxel_resolution_,
01794                                               seed_resolution_,
01795                                               use_transform_);
01796       super.setInputCloud(cloud);
01797       super.setColorImportance(color_importance_);
01798       super.setSpatialImportance(spatial_importance_);
01799       super.setNormalImportance(normal_importance_);
01800       supervoxel_clusters.clear();
01801       super.extract(supervoxel_clusters);
01802       super.getSupervoxelAdjacency(supervoxel_adjacency);
01803    }
01804 
01805    void TargetAdaptiveTracking::publishSupervoxel(
01806       const std::map<uint32_t, pcl::Supervoxel<PointT>::Ptr> supervoxel_clusters,
01807       sensor_msgs::PointCloud2 &ros_cloud,
01808       jsk_recognition_msgs::ClusterPointIndices &ros_indices,
01809       const std_msgs::Header &header)
01810    {
01811       pcl::PointCloud<PointT>::Ptr output (new pcl::PointCloud<PointT>);
01812       std::vector<pcl::PointIndices> all_indices;
01813       for (std::map<uint32_t, pcl::Supervoxel<PointT>::Ptr >::const_iterator
01814               it = supervoxel_clusters.begin();
01815            it != supervoxel_clusters.end();
01816            ++it) {
01817          pcl::Supervoxel<PointT>::Ptr super_voxel = it->second;
01818          pcl::PointCloud<PointT>::Ptr super_voxel_cloud = super_voxel->voxels_;
01819          pcl::PointIndices indices;
01820          for (size_t i = 0; i < super_voxel_cloud->size(); i++) {
01821             indices.indices.push_back(i + output->points.size());
01822          }
01823          all_indices.push_back(indices);
01824          *output = *output + *super_voxel_cloud;
01825       }
01826       ros_indices.cluster_indices.clear();
01827       ros_indices.cluster_indices = pcl_conversions::convertToROSPointIndices(
01828          all_indices, header);
01829       ros_cloud.data.clear();
01830       pcl::toROSMsg(*output, ros_cloud);
01831       ros_indices.header = header;
01832       ros_cloud.header = header;
01833    }
01834 
01835    void TargetAdaptiveTracking::targetDescriptiveSurfelsIndices(
01836       const jsk_recognition_msgs::ClusterPointIndices &sv_indices,
01837       const std::vector<uint32_t> &tdp_list,
01838       jsk_recognition_msgs::ClusterPointIndices &ros_indices)
01839    {
01840       ros_indices.cluster_indices.clear();
01841       for (std::vector<uint32_t>::const_iterator it = tdp_list.begin();
01842            it != tdp_list.end(); it++) {
01843          ros_indices.cluster_indices.push_back(sv_indices.cluster_indices[*it]);
01844       }
01845       ros_indices.header = sv_indices.header;
01846    }
01847    
01848    void TargetAdaptiveTracking::configCallback(
01849       Config &config, uint32_t level)
01850    {
01851       boost::mutex::scoped_lock lock(mutex_);
01852       this->color_importance_ = config.color_importance;
01853       this->spatial_importance_ = config.spatial_importance;
01854       this->normal_importance_ = config.normal_importance;
01855       this->voxel_resolution_ = config.voxel_resolution;
01856       this->seed_resolution_ = config.seed_resolution;
01857       this->use_transform_ = config.use_transform;
01858 
01859       this->min_cluster_size_ = static_cast<int>(config.min_cluster_size);
01860       this->threshold_ = static_cast<float>(config.threshold);
01861       this->bin_size_ = static_cast<int>(config.bin_size);
01862       this->eps_distance_ = static_cast<float>(config.eps_distance);
01863       this->eps_min_samples_ = static_cast<float>(config.eps_min_samples);
01864       this->vfh_scaling_ = static_cast<float>(config.vfh_scaling);
01865       this->color_scaling_ = static_cast<float>(config.color_scaling);
01866       this->structure_scaling_ = static_cast<float>(config.structure_scaling);
01867       this->update_tracker_reference_ = config.update_tracker_reference;
01868       this->update_filter_template_ = config.update_filter_template;
01869       this->history_window_size_ = static_cast<int>(config.history_window_size);
01870    }
01871 }
01872 
01873 #include <pluginlib/class_list_macros.h>
01874 PLUGINLIB_EXPORT_CLASS(jsk_pcl_ros::TargetAdaptiveTracking, nodelet::Nodelet);


jsk_pcl_ros
Author(s): Yohei Kakiuchi
autogenerated on Tue Jul 2 2019 19:41:45