resize_points_publisher_nodelet.cpp
Go to the documentation of this file.
00001 #include <ros/ros.h>
00002 #include <sensor_msgs/PointCloud2.h>
00003 
00004 #include <pcl/pcl_base.h>
00005 #include <pcl/point_types.h>
00006 #include <pcl/ros/conversions.h>
00007 #include <pcl/filters/extract_indices.h>
00008 
00009 #include <pcl_ros/pcl_nodelet.h>
00010 #include <pluginlib/class_list_macros.h>
00011 
00012 #include <message_filters/subscriber.h>
00013 #include <message_filters/time_synchronizer.h>
00014 #include <message_filters/synchronizer.h>
00015 
00016 #include "jsk_recognition_utils/pcl_conversion_util.h"
00017 #include <jsk_topic_tools/connection_based_nodelet.h>
00018 
00019 #include <dynamic_reconfigure/server.h>
00020 #include <jsk_pcl_ros/ResizePointsPublisherConfig.h>
00021 
00022 #include <cv_bridge/cv_bridge.h>
00023 #include <sensor_msgs/image_encodings.h>
00024 
00025 namespace jsk_pcl_ros
00026 {
00027   class ResizePointsPublisher : public jsk_topic_tools::ConnectionBasedNodelet
00028   {
00029     typedef message_filters::sync_policies::ExactTime<sensor_msgs::PointCloud2,
00030                                                       PCLIndicesMsg> SyncPolicy;
00031     typedef jsk_pcl_ros::ResizePointsPublisherConfig Config;
00032 
00033   private:
00034     int step_x_, step_y_;
00035     message_filters::Subscriber<sensor_msgs::PointCloud2> sub_input_;
00036     message_filters::Subscriber<PCLIndicesMsg> sub_indices_;
00037     boost::shared_ptr <dynamic_reconfigure::Server<Config> >  srv_;
00038     ros::Subscriber sub_;
00039     ros::Subscriber resizedmask_sub_;
00040     boost::shared_ptr<message_filters::Synchronizer<SyncPolicy> >sync_;
00041     ros::Publisher pub_;
00042     bool not_use_rgb_;
00043     boost::mutex mutex_;
00044     bool use_indices_;
00045     void onInit () {
00046       ConnectionBasedNodelet::onInit();
00047       pnh_->param("use_indices", use_indices_, false);
00048       pnh_->param("not_use_rgb", not_use_rgb_, false);
00049       srv_ = boost::make_shared <dynamic_reconfigure::Server<Config> > (*pnh_);
00050       dynamic_reconfigure::Server<Config>::CallbackType f =
00051         boost::bind (
00052                      &ResizePointsPublisher::configCallback, this, _1, _2);
00053       srv_->setCallback (f);
00054       pub_ = advertise<sensor_msgs::PointCloud2>(*pnh_, "output", 1);
00055       resizedmask_sub_ = pnh_->subscribe("input/mask", 1, &ResizePointsPublisher::resizedmaskCallback, this);
00056       onInitPostProcess();
00057     }
00058 
00059     void configCallback(Config &config, uint32_t level) {
00060       boost::mutex::scoped_lock lock(mutex_);
00061       step_x_ = config.step_x;
00062       step_y_ = config.step_y;
00063     }
00064 
00065     void resizedmaskCallback (const sensor_msgs::Image::ConstPtr& msg) {
00066       boost::mutex::scoped_lock lock(mutex_);
00067       cv_bridge::CvImagePtr cv_ptr = cv_bridge::toCvCopy
00068         (msg, sensor_msgs::image_encodings::MONO8);
00069       cv::Mat mask = cv_ptr->image;
00070       int maskwidth = mask.cols;
00071       int maskheight = mask.rows;
00072       int cnt = 0;
00073       for (size_t j = 0; j < maskheight; j++){
00074         for (size_t i = 0; i < maskwidth; i++){
00075           if (mask.at<uchar>(j, i) != 0){
00076             cnt++;
00077           }
00078         }
00079       }
00080       int surface_per = ((double) cnt) / (maskwidth * maskheight) * 100;
00081       // step_x_ = surface_per /10;
00082       step_x_ = sqrt(surface_per);
00083       if (step_x_ < 1) {
00084         step_x_ = 1;
00085       }
00086       step_y_ = step_x_;
00087     }
00088 
00089     void subscribe()
00090     {
00091       
00092       if (use_indices_) {
00093         sub_input_.subscribe(*pnh_, "input", 1);
00094         sub_indices_.subscribe(*pnh_, "indices", 1);
00095         sync_ = boost::make_shared<message_filters::Synchronizer<SyncPolicy> >(10);
00096         sync_->connectInput(sub_input_, sub_indices_);
00097         if (!not_use_rgb_) {
00098           sync_->registerCallback(boost::bind(&ResizePointsPublisher::filter<pcl::PointXYZRGB>, this, _1, _2));
00099         }
00100         else {
00101           sync_->registerCallback(boost::bind(&ResizePointsPublisher::filter<pcl::PointXYZ>, this, _1, _2));
00102         }
00103       }
00104       else {
00105         if (!not_use_rgb_) {
00106           sub_ = pnh_->subscribe(
00107             "input", 1,
00108             &ResizePointsPublisher::filter<pcl::PointXYZRGB>, this);
00109         }
00110         else {
00111           sub_ = pnh_->subscribe(
00112             "input", 1,
00113             &ResizePointsPublisher::filter<pcl::PointXYZ>, this);
00114         }
00115       }
00116     }
00117 
00118     void unsubscribe()
00119     {
00120       if (use_indices_) {
00121         sub_input_.unsubscribe();
00122         sub_indices_.unsubscribe();
00123       }
00124       else {
00125         sub_.shutdown();
00126       }
00127     }
00128     
00129     ~ResizePointsPublisher() { }
00130 
00131     template<class T> void filter (const sensor_msgs::PointCloud2::ConstPtr &input) {
00132       filter<T>(input, PCLIndicesMsg::ConstPtr());
00133     }
00134     
00135     template<class T> void filter (const sensor_msgs::PointCloud2::ConstPtr &input,
00136                                    const PCLIndicesMsg::ConstPtr &indices) {
00137       pcl::PointCloud<T> pcl_input_cloud, output;
00138       fromROSMsg(*input, pcl_input_cloud);
00139       boost::mutex::scoped_lock lock (mutex_);
00140       std::vector<int> ex_indices;
00141       ex_indices.resize(0);
00142 
00143       int width = input->width;
00144       int height = input->height;
00145       int ox, oy, sx, sy;
00146 
00147       sx = step_x_;
00148       ox = sx/2;
00149       if(height == 1) {
00150         sy = 1;
00151         oy = 0;
00152       } else {
00153         sy = step_y_;
00154         oy = sy/2;
00155       }
00156 
00157       if (indices) {
00158         std::vector<int> flags;
00159         flags.resize(width*height);
00160 
00161         //std::vector<int>::iterator it;
00162         //for(it = indices->begin(); it != indices->end(); it++)
00163         //flags[*it] = 1;
00164         for(unsigned int i = 0; i < indices->indices.size(); i++) {
00165           flags[indices->indices.at(i)] = 1;
00166         }
00167         for(int y = oy; y < height; y += sy) {
00168           for(int x = ox; x < width; x += sx) {
00169             if (flags[y*width + x] == 1) {
00170               ex_indices.push_back(y*width + x); // just use points in indices
00171             }
00172           }
00173         }
00174       } else {
00175         for(int y = oy; y < height; y += sy) {
00176           for(int x = ox; x < width; x += sx) {
00177             ex_indices.push_back(y*width + x);
00178           }
00179         }
00180       }
00181       pcl::ExtractIndices<T> extract;
00182       extract.setInputCloud (pcl_input_cloud.makeShared());
00183       extract.setIndices (boost::make_shared <std::vector<int> > (ex_indices));
00184       extract.setNegative (false);
00185       extract.filter (output);
00186 
00187       if (output.points.size() > 0) {
00188         sensor_msgs::PointCloud2 ros_out;
00189         toROSMsg(output, ros_out);
00190         ros_out.header = input->header;
00191         ros_out.width = (width - ox)/sx;
00192         if((width - ox)%sx) ros_out.width += 1;
00193         ros_out.height = (height - oy)/sy;
00194         if((height - oy)%sy) ros_out.height += 1;
00195         ros_out.row_step = ros_out.point_step * ros_out.width;
00196         ros_out.is_dense = input->is_dense;
00197 #if DEBUG
00198         NODELET_INFO("%dx%d (%d %d)(%d %d) -> %dx%d %d", width,height, ox, oy, sx, sy,
00199                  ros_out.width, ros_out.height, ex_indices.size());
00200 #endif
00201         pub_.publish(ros_out);
00202         NODELET_DEBUG("%s:: input header stamp is [%f]", getName().c_str(),
00203                           input->header.stamp.toSec());
00204         NODELET_DEBUG("%s:: output header stamp is [%f]", getName().c_str(),
00205                           ros_out.header.stamp.toSec());
00206       }
00207       
00208     }
00209 
00210   };
00211 }
00212 
00213 PLUGINLIB_EXPORT_CLASS (jsk_pcl_ros::ResizePointsPublisher, nodelet::Nodelet);


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