00001
00002
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
00035
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
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
00438
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 ;
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
00603
00604
00605
00606
00607
00608
00609 pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr centroid_normal(
00610 new pcl::PointCloud<pcl::PointXYZRGBNormal>);
00611
00612
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
00710
00711
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
00881
00882
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
00959
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
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
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
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
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
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
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 ¢roid,
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
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
01380 }
01381 }
01382
01383 void TargetAdaptiveTracking::compute3DCentroids(
01384 const pcl::PointCloud<PointT>::Ptr cloud,
01385 Eigen::Vector4f ¢re) 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
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 ¢roid,
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
01549
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);