voxel_grid_downsample_manager_nodelet.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2013, Ryohei Ueda and JSK Lab
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/o2r other materials provided
16  * with the distribution.
17  * * Neither the name of the JSK Lab nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
34 
37 #include <pcl/point_types.h>
38 #include <pcl/filters/passthrough.h>
39 #include <pcl/filters/voxel_grid.h>
40 #include <pcl/io/io.h>
41 #include <pcl_ros/transforms.h>
42 #include <boost/format.hpp>
43 #include "jsk_recognition_msgs/SlicedPointCloud.h"
44 
45 namespace jsk_pcl_ros
46 {
47 
49  {
50  grid_.clear();
51  }
52 
53 
54  void VoxelGridDownsampleManager::pointCB(const sensor_msgs::PointCloud2ConstPtr &input)
55  {
56  try {
57  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZRGB>);
58  pcl::PointCloud<pcl::PointXYZRGB>::Ptr output_cloud (new pcl::PointCloud<pcl::PointXYZRGB>);
59  if (grid_.size() == 0) {
60  NODELET_DEBUG("the number of registered grids is 0, skipping");
61  return;
62  }
63  fromROSMsg(*input, *cloud);
64  for (size_t i = 0; i < grid_.size(); i++)
65  {
66  visualization_msgs::Marker::ConstPtr target_grid = grid_[i];
67  // not yet tf is supported
68  int id = target_grid->id;
69  // solve tf with ros::Time 0.0
70 
71  // transform pointcloud to the frame_id of target_grid
72  pcl::PointCloud<pcl::PointXYZRGB>::Ptr transformed_cloud (new pcl::PointCloud<pcl::PointXYZRGB>);
73  pcl_ros::transformPointCloud(target_grid->header.frame_id,
74  *cloud,
75  *transformed_cloud,
76  *tf_listener);
77  double center_x = target_grid->pose.position.x;
78  double center_y = target_grid->pose.position.y;
79  double center_z = target_grid->pose.position.z;
80  double range_x = target_grid->scale.x * 1.0; // for debug
81  double range_y = target_grid->scale.y * 1.0;
82  double range_z = target_grid->scale.z * 1.0;
83  double min_x = center_x - range_x / 2.0;
84  double max_x = center_x + range_x / 2.0;
85  double min_y = center_y - range_y / 2.0;
86  double max_y = center_y + range_y / 2.0;
87  double min_z = center_z - range_z / 2.0;
88  double max_z = center_z + range_z / 2.0;
89  double resolution = target_grid->color.r;
90  // filter order: x -> y -> z -> downsample
91  pcl::PassThrough<pcl::PointXYZRGB> pass_x;
92  pass_x.setFilterFieldName("x");
93  pass_x.setFilterLimits(min_x, max_x);
94 
95  pcl::PassThrough<pcl::PointXYZRGB> pass_y;
96  pass_y.setFilterFieldName("y");
97  pass_y.setFilterLimits(min_y, max_y);
98  pcl::PassThrough<pcl::PointXYZRGB> pass_z;
99  pass_z.setFilterFieldName("z");
100  pass_z.setFilterLimits(min_z, max_z);
101 
102  NODELET_DEBUG_STREAM(id << " filter x: " << min_x << " - " << max_x);
103  NODELET_DEBUG_STREAM(id << " filter y: " << min_y << " - " << max_y);
104  NODELET_DEBUG_STREAM(id << " filter z: " << min_z << " - " << max_z);
105 
106  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_after_x (new pcl::PointCloud<pcl::PointXYZRGB>);
107  pass_x.setInputCloud (transformed_cloud);
108  pass_x.filter(*cloud_after_x);
109 
110  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_after_y (new pcl::PointCloud<pcl::PointXYZRGB>);
111  pass_y.setInputCloud (cloud_after_x);
112  pass_y.filter(*cloud_after_y);
113 
114  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_after_z (new pcl::PointCloud<pcl::PointXYZRGB>);
115  pass_z.setInputCloud (cloud_after_y);
116  pass_z.filter(*cloud_after_z);
117 
118  // downsample
119  pcl::VoxelGrid<pcl::PointXYZRGB> sor;
120  sor.setInputCloud (cloud_after_z);
121  sor.setLeafSize (resolution, resolution, resolution);
122  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZRGB>);
123  sor.filter (*cloud_filtered);
124 
125  // reverse transform
126  pcl::PointCloud<pcl::PointXYZRGB>::Ptr reverse_transformed_cloud (new pcl::PointCloud<pcl::PointXYZRGB>);
127  pcl_ros::transformPointCloud(input->header.frame_id,
128  *cloud_filtered,
129  *reverse_transformed_cloud,
130  *tf_listener);
131 
132  // adding the output into *output_cloud
133  // tmp <- cloud_filtered + output_cloud
134  // output_cloud <- tmp
135  //pcl::PointCloud<pcl::PointXYZRGB>::Ptr tmp (new pcl::PointCloud<pcl::PointXYZRGB>);
136  //pcl::concatenatePointCloud (*cloud_filtered, *output_cloud, tmp);
137  //output_cloud = tmp;
138  NODELET_DEBUG_STREAM(id << " includes " << reverse_transformed_cloud->points.size() << " points");
139  for (size_t i = 0; i < reverse_transformed_cloud->points.size(); i++) {
140  output_cloud->points.push_back(reverse_transformed_cloud->points[i]);
141  }
142  }
143  sensor_msgs::PointCloud2 out;
144  toROSMsg(*output_cloud, out);
145  out.header = input->header;
146  pub_.publish(out); // for debugging
147 
148  // for concatenater
149  size_t cluster_num = output_cloud->points.size() / max_points_ + 1;
150  NODELET_DEBUG_STREAM("encoding into " << cluster_num << " clusters");
151  for (size_t i = 0; i < cluster_num; i++) {
152  size_t start_index = max_points_ * i;
153  size_t end_index = max_points_ * (i + 1) > output_cloud->points.size() ?
154  output_cloud->points.size(): max_points_ * (i + 1);
155  sensor_msgs::PointCloud2 cluster_out_ros;
156  pcl::PointCloud<pcl::PointXYZRGB>::Ptr
157  cluster_out_pcl(new pcl::PointCloud<pcl::PointXYZRGB>);
158  cluster_out_pcl->points.resize(end_index - start_index);
159  // build cluster_out_pcl
160  NODELET_DEBUG_STREAM("make cluster from " << start_index << " to " << end_index);
161  for (size_t j = start_index; j < end_index; j++) {
162  cluster_out_pcl->points[j - start_index] = output_cloud->points[j];
163  }
164  // conevrt cluster_out_pcl into ros msg
165  toROSMsg(*cluster_out_pcl, cluster_out_ros);
166  jsk_recognition_msgs::SlicedPointCloud publish_point_cloud;
167  cluster_out_ros.header = input->header;
168  publish_point_cloud.point_cloud = cluster_out_ros;
169  publish_point_cloud.slice_index = i;
170  publish_point_cloud.sequence_id = sequence_id_;
171  pub_encoded_.publish(publish_point_cloud);
172  ros::Duration(1.0 / rate_).sleep();
173  }
174  }
175  catch (std::runtime_error e) { // catch any error
176  NODELET_WARN_STREAM("error has occured in VoxelGridDownsampleManager but ignore it: " << e.what());
177  ros::Duration(1.0 / rate_).sleep();
178  }
179  }
180 
181  void VoxelGridDownsampleManager::addGrid(const visualization_msgs::Marker::ConstPtr &new_box)
182  {
183  ++sequence_id_;
184  // check we have new_box->id in our bounding_boxes_
185  if (new_box->id == -1) {
186  // cancel all
187  NODELET_DEBUG("clear all pointclouds");
188  clearAll();
189  }
190  else {
191  for (size_t i = 0; i < grid_.size(); i++) {
192  if (grid_[i]->id == new_box->id) {
193  NODELET_DEBUG_STREAM("updating " << new_box->id << " grid");
194  grid_[i] = new_box;
195  }
196  }
197  NODELET_DEBUG_STREAM("adding new grid: " << new_box->id);
198  grid_.push_back(new_box);
199  }
200  }
201 
203  visualization_msgs::Marker::Ptr box (new visualization_msgs::Marker);
204  box->header.stamp = ros::Time(0.0);
205  box->header.frame_id = base_frame_;
206  box->pose.position.x = 2.0;
207  box->pose.position.y = 0.0;
208  box->pose.position.z = -0.5;
209  box->scale.x = 4.0;
210  box->scale.y = 2.0;
211  box->scale.z = 3.0;
212  box->color.r = 0.05;
213  box->color.g = 0.05;
214  box->color.b = 0.05;
215  box->color.a = 1.0;
216  grid_.push_back(box);
217  }
218 
220  {
221  ConnectionBasedNodelet::onInit();
222  pnh_->param("base_frame", base_frame_, std::string("pelvis"));
224  initializeGrid();
225  sequence_id_ = 0;
226 
227  int max_points_param;
228  pnh_->param("max_points", max_points_param, 300);
229  pnh_->param("rate", rate_, 1.0);
230  max_points_ = max_points_param;
231 
232  pub_ = advertise<sensor_msgs::PointCloud2>(
233  *pnh_, "output", 1);
234  pub_encoded_ = advertise<jsk_recognition_msgs::SlicedPointCloud>(
235  *pnh_, "output_encoded", 1);
236 
238  }
239 
241  {
242  sub_ = pnh_->subscribe("input", 1, &VoxelGridDownsampleManager::pointCB,
243  this);
244  bounding_box_sub_ = pnh_->subscribe("add_grid", 1, &VoxelGridDownsampleManager::addGrid,
245  this);
246  }
247 
249  {
250  sub_.shutdown();
252  }
253 
254 }
255 
resolution
std::vector< visualization_msgs::Marker::ConstPtr > grid_
void publish(const boost::shared_ptr< M > &message) const
bool sleep() const
#define NODELET_WARN_STREAM(...)
boost::shared_ptr< ros::NodeHandle > pnh_
#define NODELET_DEBUG_STREAM(...)
PLUGINLIB_EXPORT_CLASS(jsk_pcl_ros::VoxelGridDownsampleManager, nodelet::Nodelet)
void transformPointCloud(const pcl::PointCloud< PointT > &cloud_in, pcl::PointCloud< PointT > &cloud_out, const tf::Transform &transform)
static tf::TransformListener * getInstance()
void pointCB(const sensor_msgs::PointCloud2ConstPtr &input)
cloud
#define NODELET_DEBUG(...)
void addGrid(const visualization_msgs::Marker::ConstPtr &new_box)


jsk_pcl_ros
Author(s): Yohei Kakiuchi
autogenerated on Mon May 3 2021 03:03:47