particle_filter_tracking_nodelet.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2013, Yuto Inagaki and JSK Lab
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/o2r other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of the JSK Lab nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *********************************************************************/
00034 
00035 #define BOOST_PARAMETER_MAX_ARITY 7
00036 
00037 #include <jsk_topic_tools/log_utils.h>
00038 #include "jsk_pcl_ros/particle_filter_tracking.h"
00039 #include <pcl/tracking/impl/distance_coherence.hpp>
00040 #include <pcl/tracking/impl/approx_nearest_pair_point_cloud_coherence.hpp>
00041 #include <pluginlib/class_list_macros.h>
00042 #include <jsk_topic_tools/rosparam_utils.h>
00043 #include <geometry_msgs/TwistStamped.h>
00044 #include <std_msgs/Bool.h>
00045 #include <pcl/kdtree/kdtree_flann.h>
00046 
00047 using namespace pcl::tracking;
00048 
00049 namespace jsk_pcl_ros
00050 {
00051   
00052   void ParticleFilterTracking::onInit(void)
00053   {
00054     pcl::console::setVerbosityLevel(pcl::console::L_ERROR);
00055     // not implemented yet
00056     ConnectionBasedNodelet::onInit();
00057     
00058     track_target_set_ = false;
00059     new_cloud_ = false;
00060     
00061     default_step_covariance_.resize(6);
00062     
00063     srv_ = boost::make_shared <dynamic_reconfigure::Server<Config> >(*pnh_);
00064     dynamic_reconfigure::Server<Config>::CallbackType f =
00065       boost::bind(&ParticleFilterTracking::config_callback, this, _1, _2);
00066     srv_->setCallback(f);
00067 
00068     int particle_num;
00069     pnh_->param("particle_num", particle_num, max_particle_num_ - 1);
00070     bool use_normal;
00071     pnh_->param("use_normal", use_normal, false);
00072     bool use_hsv;
00073     pnh_->param("use_hsv", use_hsv, true);
00074     pnh_->param("track_target_name", track_target_name_,
00075                 std::string("track_result"));
00076     std::vector<double> initial_noise_covariance(6, 0.00001);
00077     jsk_topic_tools::readVectorParameter(
00078       *pnh_, "initial_noise_covariance",
00079       initial_noise_covariance);
00080     std::vector<double> default_initial_mean(6, 0.0);
00081     jsk_topic_tools::readVectorParameter(
00082       *pnh_, "default_initial_mean", default_initial_mean);
00083     
00084     //First the track target is not set
00085     double octree_resolution = 0.01;
00086     pnh_->getParam("octree_resolution", octree_resolution);
00087     pnh_->param("align_box", align_box_, false);
00088     pnh_->param("BASE_FRAME_ID", base_frame_id_, std::string("NONE"));
00089     if (base_frame_id_.compare("NONE") != 0) {
00090       listener_ = jsk_recognition_utils::TfListenerSingleton::getInstance();
00091     }
00092     target_cloud_.reset(new pcl::PointCloud<PointT>());
00093     pnh_->param("not_use_reference_centroid", not_use_reference_centroid_,
00094                 false);
00095     pnh_->param("not_publish_tf", not_publish_tf_, false);
00096     pnh_->param("reversed", reversed_, false);
00097     
00098     int thread_nr;
00099     pnh_->param("thread_nr", thread_nr, omp_get_num_procs());
00100 
00101     if (!reversed_) {
00102       boost::shared_ptr<KLDAdaptiveParticleFilterOMPTracker<PointT, ParticleXYZRPY> > tracker
00103         (new KLDAdaptiveParticleFilterOMPTracker<PointT, ParticleXYZRPY>(thread_nr));
00104       tracker->setMaximumParticleNum(max_particle_num_);
00105       tracker->setDelta(delta_);
00106       tracker->setEpsilon(epsilon_);
00107       tracker->setBinSize(bin_size_);
00108       tracker_ = tracker;
00109     }
00110     else {
00111       boost::shared_ptr<ReversedParticleFilterOMPTracker<PointT, ParticleXYZRPY> > tracker
00112         (new ReversedParticleFilterOMPTracker<PointT, ParticleXYZRPY>(thread_nr));
00113       // boost::shared_ptr<ReversedParticleFilterTracker<PointT, ParticleXYZRPY> > tracker
00114       //   (new ReversedParticleFilterTracker<PointT, ParticleXYZRPY>());
00115       reversed_tracker_ = tracker;
00116     }
00117     tracker_set_trans(Eigen::Affine3f::Identity());
00118     tracker_set_step_noise_covariance(default_step_covariance_);
00119     tracker_set_initial_noise_covariance(initial_noise_covariance);
00120     tracker_set_initial_noise_mean(default_initial_mean);
00121     tracker_set_iteration_num(iteration_num_);
00122     tracker_set_particle_num(particle_num);
00123     tracker_set_resample_likelihood_thr(resample_likelihood_thr_);
00124     tracker_set_use_normal(use_normal);
00125     
00126     //Setup coherence object for tracking
00127     bool enable_cache;
00128     bool enable_organized;
00129     pnh_->param("enable_cache", enable_cache, false);
00130     pnh_->param("enable_organized", enable_organized, false);
00131     ApproxNearestPairPointCloudCoherence<PointT>::Ptr coherence;
00132     if (enable_cache) {
00133       double cache_bin_size_x, cache_bin_size_y, cache_bin_size_z;
00134       pnh_->param("cache_size_x", cache_bin_size_x, 0.01);
00135       pnh_->param("cache_size_y", cache_bin_size_y, 0.01);
00136       pnh_->param("cache_size_z", cache_bin_size_z, 0.01);
00137       coherence.reset(new CachedApproxNearestPairPointCloudCoherence<PointT>(
00138                         cache_bin_size_x, cache_bin_size_y, cache_bin_size_z));
00139     }else if(enable_organized){
00140       coherence.reset(new OrganizedNearestPairPointCloudCoherence<PointT>());
00141     }
00142     else {
00143       coherence.reset(new ApproxNearestPairPointCloudCoherence<PointT>());
00144     }
00145     
00146 
00147     boost::shared_ptr<DistanceCoherence<PointT> >
00148       distance_coherence(new DistanceCoherence<PointT>);
00149     coherence->addPointCoherence(distance_coherence);
00150 
00151     //add HSV coherence
00152     if (use_hsv) {
00153         boost::shared_ptr<HSVColorCoherence<PointT> > hsv_color_coherence
00154           = boost::shared_ptr<HSVColorCoherence<PointT> >(new HSVColorCoherence<PointT>());
00155         coherence->addPointCoherence(hsv_color_coherence);
00156     }
00157     
00158      boost::shared_ptr<pcl::search::Octree<PointT> > search
00159        (new pcl::search::Octree<PointT>(octree_resolution));
00160     //boost::shared_ptr<pcl::search::KdTree<PointT> > search(new pcl::search::KdTree<PointT>());
00161     coherence->setSearchMethod(search);
00162     double max_distance;
00163     pnh_->param("max_distance", max_distance, 0.01);
00164     coherence->setMaximumDistance(max_distance);
00165     pnh_->param("use_change_detection", use_change_detection_, false);
00166     tracker_set_cloud_coherence(coherence);
00167 
00168     //Set publish setting
00169     particle_publisher_ = pnh_->advertise<sensor_msgs::PointCloud2>(
00170       "particle", 1);
00171     track_result_publisher_ = pnh_->advertise<sensor_msgs::PointCloud2>(
00172       "track_result", 1);
00173     pose_stamped_publisher_ = pnh_->advertise<geometry_msgs::PoseStamped>(
00174       "track_result_pose", 1);
00175     pub_latest_time_ = pnh_->advertise<std_msgs::Float32>(
00176       "output/latest_time", 1);
00177     pub_average_time_ = pnh_->advertise<std_msgs::Float32>(
00178       "output/average_time", 1);
00179     pub_rms_angle_ = pnh_->advertise<std_msgs::Float32>(
00180       "output/rms_angle_error", 1);
00181     pub_rms_distance_ = pnh_->advertise<std_msgs::Float32>(
00182       "output/rms_distance_error", 1);
00183     pub_velocity_ = pnh_->advertise<geometry_msgs::TwistStamped>(
00184       "output/velocity", 1);
00185     pub_velocity_norm_ = pnh_->advertise<std_msgs::Float32>(
00186       "output/velocity_norm", 1);
00187     pub_no_move_raw_ = pnh_->advertise<std_msgs::Bool>(
00188       "output/no_move_raw", 1);
00189     pub_no_move_ = pnh_->advertise<std_msgs::Bool>(
00190       "output/no_move", 1);
00191     pub_skipped_ = pnh_->advertise<std_msgs::Bool>(
00192       "output/skipped", 1);
00193     //Set subscribe setting
00194     if (use_change_detection_) {
00195       pub_change_cloud_marker_ = pnh_->advertise<visualization_msgs::MarkerArray>(
00196         "output/change_marker", 1);
00197       pub_tracker_status_ = pnh_->advertise<jsk_recognition_msgs::TrackerStatus>(
00198         "output/tracker_status", 1);
00199       sub_input_cloud_.subscribe(*pnh_, "input", 4);
00200       sub_change_cloud_.subscribe(*pnh_, "input_change", 4);
00201       change_sync_ = boost::make_shared<message_filters::Synchronizer<SyncChangePolicy> >(100);
00202       change_sync_->connectInput(sub_input_cloud_, sub_change_cloud_);
00203       change_sync_->registerCallback(
00204         boost::bind(
00205           &ParticleFilterTracking::cloud_change_cb,
00206           this, _1, _2));
00207     }
00208     else {
00209       sub_ = pnh_->subscribe("input", 1, &ParticleFilterTracking::cloud_cb,this);
00210     }
00211     if (align_box_) {
00212       sub_input_.subscribe(*pnh_, "renew_model", 1);
00213       sub_box_.subscribe(*pnh_, "renew_box", 1);
00214       sync_ = boost::make_shared<message_filters::Synchronizer<SyncPolicy> >(100);
00215       sync_->connectInput(sub_input_, sub_box_);
00216       sync_->registerCallback(
00217         boost::bind(
00218           &ParticleFilterTracking::renew_model_with_box_topic_cb,
00219           this, _1, _2));
00220     }
00221     else {
00222       sub_update_model_ = pnh_->subscribe(
00223         "renew_model", 1, &ParticleFilterTracking::renew_model_topic_cb,this);
00224       sub_update_with_marker_model_
00225         = pnh_->subscribe("renew_model_with_marker", 1, &ParticleFilterTracking::renew_model_with_marker_topic_cb, this);
00226     }
00227 
00228     pnh_->param("marker_to_pointcloud_sampling_nums", marker_to_pointcloud_sampling_nums_, 10000);
00229     renew_model_srv_
00230       = pnh_->advertiseService(
00231         "renew_model", &ParticleFilterTracking::renew_model_cb, this);
00232 
00233     onInitPostProcess();
00234   }
00235 
00236   void ParticleFilterTracking::config_callback(Config &config, uint32_t level)
00237   {
00238     boost::mutex::scoped_lock lock(mtx_);
00239     max_particle_num_ = config.max_particle_num;
00240     iteration_num_ = config.iteration_num;
00241     resample_likelihood_thr_ = config.resample_likelihood_thr;
00242     delta_ = config.delta;
00243     epsilon_ = config.epsilon;
00244     bin_size_.x = config.bin_size_x;
00245     bin_size_.y = config.bin_size_y;
00246     bin_size_.z = config.bin_size_z;
00247     bin_size_.roll = config.bin_size_roll;
00248     bin_size_.pitch = config.bin_size_pitch;
00249     bin_size_.yaw = config.bin_size_yaw;
00250     default_step_covariance_[0] = config.default_step_covariance_x;
00251     default_step_covariance_[1] = config.default_step_covariance_y;
00252     default_step_covariance_[2] = config.default_step_covariance_z;
00253     default_step_covariance_[3] = config.default_step_covariance_roll;
00254     default_step_covariance_[4] = config.default_step_covariance_pitch;
00255     default_step_covariance_[5] = config.default_step_covariance_yaw;
00256     static_velocity_thr_ = config.static_velocity_thr;
00257     change_cloud_near_threshold_ = config.change_cloud_near_thr;
00258     if (tracker_ || reversed_tracker_) 
00259     {
00260       NODELET_INFO("update tracker parameter");
00261       tracker_set_step_noise_covariance(default_step_covariance_);
00262       tracker_set_iteration_num(iteration_num_);
00263       tracker_set_resample_likelihood_thr(resample_likelihood_thr_);
00264       tracker_set_maximum_particle_num(max_particle_num_);
00265       tracker_set_delta(delta_);
00266       tracker_set_epsilon(epsilon_);
00267       tracker_set_bin_size(bin_size_);
00268     }
00269   }
00270   
00271   //Publish the current particles
00272   void ParticleFilterTracking::publish_particles()
00273   {
00274     PointCloudStatePtr particles = tracker_get_particles();
00275     if (particles && new_cloud_ && particle_publisher_.getNumSubscribers()) {
00276       //Set pointCloud with particle's points
00277       pcl::PointCloud<pcl::PointXYZ>::Ptr particle_cloud
00278         (new pcl::PointCloud<pcl::PointXYZ>());
00279       for (size_t i = 0; i < particles->points.size(); i++)
00280       {
00281         pcl::PointXYZ point;
00282         point.x = particles->points[i].x;
00283         point.y = particles->points[i].y;
00284         point.z = particles->points[i].z;
00285         particle_cloud->points.push_back(point);
00286       }
00287       //publish particle_cloud
00288       sensor_msgs::PointCloud2 particle_pointcloud2;
00289       pcl::toROSMsg(*particle_cloud, particle_pointcloud2);
00290       particle_pointcloud2.header.frame_id = reference_frame_id();
00291       particle_pointcloud2.header.stamp = stamp_;
00292       particle_publisher_.publish(particle_pointcloud2);
00293     }
00294   }
00295   //Publish model reference point cloud
00296   void ParticleFilterTracking::publish_result()
00297   {
00298     ParticleXYZRPY result = tracker_get_result();
00299     Eigen::Affine3f transformation = tracker_to_eigen_matrix(result);
00300 
00301     //Publisher object transformation
00302     tf::Transform tfTransformation;
00303     tf::transformEigenToTF((Eigen::Affine3d) transformation, tfTransformation);
00304 
00305     if (!not_publish_tf_) {
00306       static tf::TransformBroadcaster tfBroadcaster;
00307       tfBroadcaster.sendTransform(tf::StampedTransform(
00308                                     tfTransformation, stamp_,
00309                                     reference_frame_id(), track_target_name_));
00310     }
00311     //Publish Pose
00312     geometry_msgs::PoseStamped result_pose_stamped;
00313     result_pose_stamped.header.frame_id = reference_frame_id();
00314     result_pose_stamped.header.stamp = stamp_;
00315     tf::Quaternion q;
00316     tf::poseTFToMsg(tfTransformation, result_pose_stamped.pose);
00317     pose_stamped_publisher_.publish(result_pose_stamped);
00318     //Publish model reference point cloud
00319     pcl::PointCloud<PointT>::Ptr result_cloud
00320       (new pcl::PointCloud<PointT>());
00321     pcl::transformPointCloud<PointT>(
00322       *(tracker_get_reference_cloud()), *result_cloud, transformation);
00323     sensor_msgs::PointCloud2 result_pointcloud2;
00324     pcl::toROSMsg(*result_cloud, result_pointcloud2);
00325     result_pointcloud2.header.frame_id = reference_frame_id();
00326     result_pointcloud2.header.stamp = stamp_;
00327     track_result_publisher_.publish(result_pointcloud2);
00328 
00329     if (counter_ > 0) {         // publish velocity
00330       geometry_msgs::TwistStamped twist;
00331       twist.header.frame_id = reference_frame_id();
00332       twist.header.stamp = stamp_;
00333       double dt = (stamp_ - prev_stamp_).toSec();
00334       twist.twist.linear.x = (result.x - prev_result_.x) / dt;
00335       twist.twist.linear.y = (result.y - prev_result_.y) / dt;
00336       twist.twist.linear.z = (result.z - prev_result_.z) / dt;
00337       twist.twist.angular.x = (result.roll - prev_result_.roll) / dt;
00338       twist.twist.angular.y = (result.pitch - prev_result_.pitch) / dt;
00339       twist.twist.angular.z = (result.yaw - prev_result_.yaw) / dt;
00340       pub_velocity_.publish(twist);
00341       Eigen::Vector3f vel(twist.twist.linear.x, twist.twist.linear.y, twist.twist.linear.z);
00342       std_msgs::Float32 velocity_norm;
00343       velocity_norm.data = vel.norm();
00344       pub_velocity_norm_.publish(velocity_norm);
00345       bool is_static = vel.norm() < static_velocity_thr_;
00346       no_move_buffer_.addValue(is_static);
00347       std_msgs::Bool no_move_raw, no_move;
00348       no_move_raw.data = is_static;
00349       no_move.data = no_move_buffer_.isAllTrueFilled();
00350       pub_no_move_.publish(no_move);
00351       pub_no_move_raw_.publish(no_move_raw);
00352     }
00353     
00354     Eigen::Affine3f diff_trans = transformation.inverse() * initial_pose_;
00355     double distance_error = Eigen::Vector3f(diff_trans.translation()).norm();
00356     double angle_error = Eigen::AngleAxisf(diff_trans.rotation()).angle();
00357     distance_error_buffer_.push_back(distance_error);
00358     angle_error_buffer_.push_back(angle_error);
00359     double distance_rms = rms(distance_error_buffer_);
00360     double angle_rms = rms(angle_error_buffer_);
00361     std_msgs::Float32 ros_distance_rms, ros_angle_rms;
00362     ros_distance_rms.data = distance_rms;
00363     ros_angle_rms.data = angle_rms;
00364     pub_rms_distance_.publish(ros_distance_rms);
00365     pub_rms_angle_.publish(ros_angle_rms);
00366     prev_result_ = result;
00367     prev_stamp_ = stamp_;
00368     ++counter_;
00369   }
00370   
00371   std::string ParticleFilterTracking::reference_frame_id()
00372   {
00373     if (base_frame_id_.compare("NONE") == 0) {
00374       return frame_id_;
00375     }
00376     else {
00377       return base_frame_id_;
00378     }
00379   }
00380   
00381   void ParticleFilterTracking::reset_tracking_target_model(
00382     const pcl::PointCloud<PointT>::ConstPtr &recieved_target_cloud)
00383   {
00384     pcl::PointCloud<PointT>::Ptr new_target_cloud(new pcl::PointCloud<PointT>);
00385     std::vector<int> indices;
00386     new_target_cloud->is_dense = false;
00387     pcl::removeNaNFromPointCloud(
00388       *recieved_target_cloud, *new_target_cloud, indices);
00389     
00390     if (base_frame_id_.compare("NONE") != 0) {
00391       tf::Transform transform_result
00392         = change_pointcloud_frame(new_target_cloud);
00393       reference_transform_ = transform_result * reference_transform_;;
00394     }
00395 
00396     if (!recieved_target_cloud->points.empty()) {
00397       //prepare the model of tracker's target
00398       Eigen::Affine3f trans = Eigen::Affine3f::Identity(); 
00399       pcl::PointCloud<PointT>::Ptr transed_ref(new pcl::PointCloud<PointT>);
00400       if (!align_box_) {
00401         if (!not_use_reference_centroid_) {
00402           Eigen::Vector4f c;
00403           pcl::compute3DCentroid(*new_target_cloud, c);
00404           trans.translation().matrix() = Eigen::Vector3f(c[0], c[1], c[2]);
00405         }
00406       }
00407       else {
00408         Eigen::Affine3d trans_3d = Eigen::Affine3d::Identity();
00409         tf::transformTFToEigen(reference_transform_, trans_3d);
00410         trans = (Eigen::Affine3f) trans_3d;
00411       }
00412       pcl::transformPointCloud(*new_target_cloud, *transed_ref, trans.inverse());
00413       //set reference model and trans
00414       {
00415         boost::mutex::scoped_lock lock(mtx_);
00416         tracker_set_reference_cloud(transed_ref);
00417         tracker_set_trans(trans);
00418         tracker_reset_tracking();
00419         initial_pose_ = Eigen::Affine3f(trans);
00420       }
00421       track_target_set_ = true;
00422       NODELET_INFO("RESET TARGET MODEL");
00423     }
00424     else {
00425       track_target_set_ = false;
00426       NODELET_ERROR("TARGET MODEL POINTS SIZE IS 0 !! Stop TRACKING");
00427     }
00428   } 
00429   
00430   tf::Transform ParticleFilterTracking::change_pointcloud_frame(
00431     pcl::PointCloud<PointT>::Ptr cloud)
00432   {
00433     tf::Transform tfTransformation;
00434     tf::StampedTransform tfTransformationStamped;
00435     ros::Time now = ros::Time::now();
00436     try {
00437       listener_->waitForTransform(base_frame_id_, frame_id_, now,
00438                                   ros::Duration(2.0));
00439       listener_->lookupTransform(base_frame_id_, frame_id_, now,
00440                                  tfTransformationStamped);
00441       //frame_id_ = base_frame_id_;
00442     }
00443     catch(tf::TransformException ex) {
00444       NODELET_ERROR("%s",ex.what());
00445       tfTransformation = tf::Transform(tf::Quaternion(0, 0, 0, 1));
00446     }
00447     tfTransformation = tf::Transform(tfTransformationStamped.getBasis(),
00448                                      tfTransformationStamped.getOrigin());
00449     Eigen::Affine3f trans; Eigen::Affine3d trans_3d;
00450     tf::transformTFToEigen(tfTransformation, trans_3d);
00451     trans = (Eigen::Affine3f) trans_3d;
00452     pcl::transformPointCloud(*cloud, *cloud, trans);
00453     return tfTransformation;
00454   }
00455 
00456   void ParticleFilterTracking::publish_tracker_status(const std_msgs::Header& header,
00457                                                       const bool is_tracking)
00458   {
00459     jsk_recognition_msgs::TrackerStatus tracker_status;
00460     tracker_status.header = header;
00461     tracker_status.is_tracking = is_tracking;
00462     pub_tracker_status_.publish(tracker_status);
00463   }
00464   
00465   void ParticleFilterTracking::cloud_change_cb(const sensor_msgs::PointCloud2::ConstPtr &pc_msg,
00466                                                const sensor_msgs::PointCloud2::ConstPtr &change_cloud_msg)
00467   {
00468     if (no_move_buffer_.isAllTrueFilled()) {
00469       jsk_recognition_utils::ScopedWallDurationReporter r
00470         = timer_.reporter(pub_latest_time_, pub_average_time_);
00471       // change change_cloud
00472       pcl::PointCloud<pcl::PointXYZRGB>::Ptr change_cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
00473       pcl::fromROSMsg(*change_cloud_msg, *change_cloud);
00474       if (change_cloud->points.size() == 0) {
00475         stamp_ = pc_msg->header.stamp;
00476         publish_result();
00477         publish_tracker_status(pc_msg->header, false);
00478         return;
00479       }
00480       pcl::KdTreeFLANN<pcl::PointXYZRGB> kdtree;
00481       kdtree.setInputCloud(change_cloud);
00482       std::vector<int> k_indices;
00483       std::vector<float> k_sqr_distances;
00484       pcl::PointXYZRGB p;
00485       p.x = prev_result_.x;
00486       p.y = prev_result_.y;
00487       p.z = prev_result_.z;
00488       if (kdtree.radiusSearch(p, change_cloud_near_threshold_, k_indices, k_sqr_distances, 1) > 0) {
00489         NODELET_INFO("change detection triggered!");
00490         // there is near pointcloud
00491         cloud_cb(*pc_msg);
00492         r.setIsEnabled(false);
00493         no_move_buffer_.clear();
00494         publish_tracker_status(pc_msg->header, true);
00495       }
00496       else {
00497         // publish previous result
00498         stamp_ = pc_msg->header.stamp;
00499         publish_result();
00500         publish_tracker_status(pc_msg->header, false);
00501       }
00502     }
00503     else {
00504       publish_tracker_status(pc_msg->header, true);
00505       cloud_cb(*pc_msg);
00506     }
00507   }
00508   
00509   //OpenNI Grabber's cloud Callback function
00510   void ParticleFilterTracking::cloud_cb(const sensor_msgs::PointCloud2 &pc)
00511   {
00512     if (track_target_set_) {
00513       pcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>());
00514       frame_id_ = pc.header.frame_id;
00515       stamp_ = pc.header.stamp;
00516       std::vector<int> indices;
00517       pcl::fromROSMsg(pc, *cloud);
00518       cloud->is_dense = false;
00519       {
00520         jsk_recognition_utils::ScopedWallDurationReporter r
00521           = timer_.reporter(pub_latest_time_, pub_average_time_);
00522         pcl::removeNaNFromPointCloud(*cloud, *cloud, indices);
00523         if (base_frame_id_.compare("NONE")!=0) {
00524           change_pointcloud_frame(cloud);
00525         }
00526         cloud_pass_downsampled_.reset(new pcl::PointCloud<PointT>);
00527         pcl::copyPointCloud(*cloud, *cloud_pass_downsampled_);
00528         if (!cloud_pass_downsampled_->points.empty()) {
00529           boost::mutex::scoped_lock lock(mtx_);
00530           tracker_set_input_cloud(cloud_pass_downsampled_);
00531           tracker_compute();
00532           publish_particles();
00533           publish_result();
00534         }
00535         new_cloud_ = true;
00536       }
00537     }
00538   }
00539 
00540   void ParticleFilterTracking::renew_model_topic_cb(
00541     const sensor_msgs::PointCloud2 &pc)
00542   {
00543     pcl::PointCloud<PointT>::Ptr new_target_cloud
00544       (new pcl::PointCloud<PointT>());
00545     pcl::fromROSMsg(pc, *new_target_cloud);
00546     frame_id_ = pc.header.frame_id;
00547     reset_tracking_target_model(new_target_cloud);
00548   }
00549 
00550   void ParticleFilterTracking::renew_model_with_marker_topic_cb(const visualization_msgs::Marker &marker)
00551   {
00552     if(marker.type == visualization_msgs::Marker::TRIANGLE_LIST && !marker.points.empty()){
00553       ROS_INFO("Reset Tracker Model with renew_model_with_marker_topic_cb");
00554       pcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>);
00555       jsk_recognition_utils::markerMsgToPointCloud(marker,
00556                             marker_to_pointcloud_sampling_nums_,
00557                             *cloud
00558                             );
00559 
00560       Eigen::Affine3f trans;
00561       tf::poseMsgToEigen(marker.pose, trans);
00562       pcl::transformPointCloud(*cloud, *cloud, trans);
00563 
00564       frame_id_ = marker.header.frame_id;
00565       reset_tracking_target_model(cloud);
00566     }else{
00567       ROS_ERROR(" Marker Models type is not TRIANGLE ");
00568       ROS_ERROR("   OR   ");
00569       ROS_ERROR(" Marker Points is empty ");
00570     }
00571   }
00572 
00573   void ParticleFilterTracking::renew_model_with_box_topic_cb(
00574     const sensor_msgs::PointCloud2::ConstPtr &pc_ptr,
00575     const jsk_recognition_msgs::BoundingBox::ConstPtr &bb_ptr)
00576   {
00577     pcl::PointCloud<PointT>::Ptr new_target_cloud
00578       (new pcl::PointCloud<PointT>());
00579     pcl::fromROSMsg(*pc_ptr, *new_target_cloud);
00580     frame_id_ = pc_ptr->header.frame_id;
00581     tf::poseMsgToTF(bb_ptr->pose, reference_transform_);
00582     reset_tracking_target_model(new_target_cloud);
00583   }
00584   
00585   bool ParticleFilterTracking::renew_model_cb(
00586     jsk_recognition_msgs::SetPointCloud2::Request &req,
00587     jsk_recognition_msgs::SetPointCloud2::Response &res)
00588   {
00589     pcl::PointCloud<PointT>::Ptr new_target_cloud(new pcl::PointCloud<PointT>());
00590     pcl::fromROSMsg(req.cloud, *new_target_cloud);
00591     frame_id_ = req.cloud.header.frame_id;
00592     reset_tracking_target_model(new_target_cloud);
00593     return true;
00594   }
00595 
00596   void ParticleFilterTracking::tracker_set_trans(
00597     const Eigen::Affine3f& trans)
00598   {
00599     Eigen::Vector3f pos = trans.translation();
00600     NODELET_INFO("trans: [%f, %f, %f]", pos[0], pos[1], pos[2]);
00601     if (reversed_) {
00602       reversed_tracker_->setTrans(trans);
00603     }
00604     else {
00605       tracker_->setTrans(trans);
00606     }
00607   }
00608 
00609   void ParticleFilterTracking::tracker_set_step_noise_covariance(
00610     const std::vector<double>& covariance)
00611   {
00612     if (reversed_) {
00613       reversed_tracker_->setStepNoiseCovariance(covariance);
00614     }
00615     else {
00616       tracker_->setStepNoiseCovariance(covariance);
00617     }
00618   }
00619 
00620   void ParticleFilterTracking::tracker_set_initial_noise_covariance(
00621     const std::vector<double>& covariance)
00622   {
00623     if (reversed_) {
00624       reversed_tracker_->setInitialNoiseCovariance(covariance);
00625     }
00626     else {
00627       tracker_->setInitialNoiseCovariance(covariance);
00628     }
00629   }
00630 
00631   void ParticleFilterTracking::tracker_set_initial_noise_mean(
00632     const std::vector<double>& mean)
00633   {
00634     if (reversed_) {
00635       reversed_tracker_->setInitialNoiseMean(mean);
00636     }
00637     else {
00638       tracker_->setInitialNoiseMean(mean);
00639     }
00640   }
00641 
00642   void ParticleFilterTracking::tracker_set_iteration_num(const int num)
00643   {
00644     if (reversed_) {
00645       reversed_tracker_->setIterationNum(num);
00646     }
00647     else {
00648       tracker_->setIterationNum(num);
00649     }
00650   }
00651 
00652   void ParticleFilterTracking::tracker_set_particle_num(const int num)
00653   {
00654     if (reversed_) {
00655       reversed_tracker_->setParticleNum(num);
00656     }
00657     else {
00658       tracker_->setParticleNum(num);
00659     }
00660   }
00661 
00662   void ParticleFilterTracking::tracker_set_resample_likelihood_thr(double thr)
00663   {
00664     if (reversed_) {
00665       reversed_tracker_->setResampleLikelihoodThr(thr);
00666     }
00667     else {
00668       tracker_->setResampleLikelihoodThr(thr);
00669     }
00670   }
00671 
00672   void ParticleFilterTracking::tracker_set_use_normal(bool use_normal)
00673   {
00674     if (reversed_) {
00675       reversed_tracker_->setUseNormal(use_normal);
00676     }
00677     else {
00678       tracker_->setUseNormal(use_normal);
00679     }
00680   }
00681   
00682   void ParticleFilterTracking::tracker_set_cloud_coherence(
00683     ApproxNearestPairPointCloudCoherence<PointT>::Ptr coherence)
00684   {
00685     if (reversed_) {
00686       reversed_tracker_->setCloudCoherence(coherence);
00687     }
00688     else {
00689       tracker_->setCloudCoherence(coherence);
00690     }
00691   }
00692 
00693   void ParticleFilterTracking::tracker_set_maximum_particle_num(int num)
00694   {
00695     if (!reversed_) {
00696       tracker_->setMaximumParticleNum(num);
00697     }
00698   }
00699   
00700   void ParticleFilterTracking::tracker_set_delta(double delta)
00701   {
00702     if (!reversed_) {
00703       tracker_->setDelta(delta);
00704     }
00705   }
00706   
00707   void ParticleFilterTracking::tracker_set_epsilon(double epsilon)
00708   {
00709     if (!reversed_) {
00710       tracker_->setEpsilon(epsilon);
00711     }
00712   }
00713   
00714   void ParticleFilterTracking::tracker_set_bin_size(
00715     const ParticleXYZRPY bin_size)
00716   {
00717     if (!reversed_) {
00718       tracker_->setBinSize(bin_size);
00719     }
00720   }
00721 
00722   ParticleFilterTracking::PointCloudStatePtr
00723   ParticleFilterTracking::tracker_get_particles()
00724   {
00725     if (!reversed_) {
00726       return tracker_->getParticles();
00727     }
00728     else {
00729       return reversed_tracker_->getParticles();
00730     }
00731   }
00732 
00733   ParticleXYZRPY ParticleFilterTracking::tracker_get_result()
00734   {
00735     if (!reversed_) {
00736       return tracker_->getResult();
00737     }
00738     else {
00739       return reversed_tracker_->getResult();
00740     }
00741   }
00742 
00743   Eigen::Affine3f ParticleFilterTracking::tracker_to_eigen_matrix(
00744     const ParticleXYZRPY& result)
00745   {
00746     if (!reversed_) {
00747       return tracker_->toEigenMatrix(result);
00748     }
00749     else {
00750       return reversed_tracker_->toEigenMatrix(result);
00751     }
00752   }
00753 
00754   pcl::PointCloud<ParticleFilterTracking::PointT>::ConstPtr
00755   ParticleFilterTracking::tracker_get_reference_cloud()
00756   {
00757     if (!reversed_) {
00758       return tracker_->getReferenceCloud();
00759     }
00760     else {
00761       return reversed_tracker_->getReferenceCloud();
00762     }
00763   }
00764 
00765   void ParticleFilterTracking::tracker_set_reference_cloud(
00766     pcl::PointCloud<PointT>::Ptr ref)
00767   {
00768     if (!reversed_) {
00769       tracker_->setReferenceCloud(ref);
00770     }
00771     else {
00772       reversed_tracker_->setReferenceCloud(ref);
00773     }
00774     counter_ = 0;
00775     no_move_buffer_.clear();
00776   }
00777 
00778   void ParticleFilterTracking::tracker_reset_tracking()
00779   {
00780     if (!reversed_) {
00781       tracker_->resetTracking();
00782     }
00783     else {
00784       reversed_tracker_->resetTracking();
00785     }
00786   }
00787 
00788   void ParticleFilterTracking::tracker_set_input_cloud(
00789     pcl::PointCloud<PointT>::Ptr input)
00790   {
00791     if (!reversed_) {
00792       tracker_->setInputCloud(input);
00793     }
00794     else {
00795       reversed_tracker_->setInputCloud(input);
00796     }
00797   }
00798   void ParticleFilterTracking::tracker_compute()
00799   {
00800     if (!reversed_) {
00801       tracker_->compute();
00802     }
00803     else {
00804       reversed_tracker_->compute();
00805     }
00806   }
00807 }
00808 
00809 PLUGINLIB_EXPORT_CLASS (jsk_pcl_ros::ParticleFilterTracking, nodelet::Nodelet);


jsk_pcl_ros
Author(s): Yohei Kakiuchi
autogenerated on Sun Oct 8 2017 02:43:50