$search
00001 /* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Copyright (c) 2009, Willow Garage, Inc. 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/or other materials provided 00016 * with the distribution. 00017 * * Neither the name of Willow Garage, Inc. 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 * $Id: concatenate_data.cpp 35231 2011-01-14 05:33:20Z rusu $ 00035 * 00036 */ 00037 00038 #include <pluginlib/class_list_macros.h> 00039 #include <pcl/io/io.h> 00040 #include "pcl_ros/transforms.h" 00041 #include "pcl_ros/io/concatenate_data.h" 00042 00044 void 00045 pcl_ros::PointCloudConcatenateDataSynchronizer::onInit () 00046 { 00047 private_nh_ = getMTPrivateNodeHandle (); 00048 // ---[ Mandatory parameters 00049 private_nh_.getParam ("output_frame", output_frame_); 00050 private_nh_.getParam ("approximate_sync", approximate_sync_); 00051 00052 if (output_frame_.empty ()) 00053 { 00054 NODELET_ERROR ("[onInit] Need an 'output_frame' parameter to be set before continuing!"); 00055 return; 00056 } 00057 00058 // ---[ Optional parameters 00059 private_nh_.getParam ("max_queue_size", maximum_queue_size_); 00060 00061 // Output 00062 pub_output_ = private_nh_.advertise<PointCloud2> ("output", maximum_queue_size_); 00063 00064 XmlRpc::XmlRpcValue input_topics; 00065 if (!private_nh_.getParam ("input_topics", input_topics)) 00066 { 00067 NODELET_ERROR ("[onInit] Need a 'input_topics' parameter to be set before continuing!"); 00068 return; 00069 } 00070 // Check the type 00071 switch (input_topics.getType ()) 00072 { 00073 case XmlRpc::XmlRpcValue::TypeArray: 00074 { 00075 if (input_topics.size () == 1) 00076 { 00077 NODELET_ERROR ("[onInit] Only one topic given. Need at least two topics to continue."); 00078 return; 00079 } 00080 00081 if (input_topics.size () > 8) 00082 { 00083 NODELET_ERROR ("[onInit] More than 8 topics passed!"); 00084 return; 00085 } 00086 00087 ROS_INFO_STREAM ("[onInit] Subscribing to " << input_topics.size () << " user given topics as inputs:"); 00088 for (int d = 0; d < input_topics.size (); ++d) 00089 ROS_INFO_STREAM (" - " << (std::string)(input_topics[d])); 00090 00091 // Subscribe to the filters 00092 filters_.resize (input_topics.size ()); 00093 00094 // 8 topics 00095 if (approximate_sync_) 00096 ts_a_.reset (new message_filters::Synchronizer<sync_policies::ApproximateTime<PointCloud2, PointCloud2, PointCloud2, 00097 PointCloud2, PointCloud2, PointCloud2, 00098 PointCloud2, PointCloud2> 00099 > (maximum_queue_size_)); 00100 else 00101 ts_e_.reset (new message_filters::Synchronizer<sync_policies::ExactTime<PointCloud2, PointCloud2, PointCloud2, 00102 PointCloud2, PointCloud2, PointCloud2, 00103 PointCloud2, PointCloud2> 00104 > (maximum_queue_size_)); 00105 00106 // First input_topics.size () filters are valid 00107 for (int d = 0; d < input_topics.size (); ++d) 00108 { 00109 filters_[d].reset (new message_filters::Subscriber<PointCloud2> ()); 00110 filters_[d]->subscribe (private_nh_, (std::string)(input_topics[d]), maximum_queue_size_); 00111 } 00112 00113 // Bogus null filter 00114 filters_[0]->registerCallback (bind (&PointCloudConcatenateDataSynchronizer::input_callback, this, _1)); 00115 00116 switch (input_topics.size ()) 00117 { 00118 case 2: 00119 { 00120 if (approximate_sync_) 00121 ts_a_->connectInput (*filters_[0], *filters_[1], nf_, nf_, nf_, nf_, nf_, nf_); 00122 else 00123 ts_e_->connectInput (*filters_[0], *filters_[1], nf_, nf_, nf_, nf_, nf_, nf_); 00124 break; 00125 } 00126 case 3: 00127 { 00128 if (approximate_sync_) 00129 ts_a_->connectInput (*filters_[0], *filters_[1], *filters_[2], nf_, nf_, nf_, nf_, nf_); 00130 else 00131 ts_e_->connectInput (*filters_[0], *filters_[1], *filters_[2], nf_, nf_, nf_, nf_, nf_); 00132 break; 00133 } 00134 case 4: 00135 { 00136 if (approximate_sync_) 00137 ts_a_->connectInput (*filters_[0], *filters_[1], *filters_[2], *filters_[3], nf_, nf_, nf_, nf_); 00138 else 00139 ts_e_->connectInput (*filters_[0], *filters_[1], *filters_[2], *filters_[3], nf_, nf_, nf_, nf_); 00140 break; 00141 } 00142 case 5: 00143 { 00144 if (approximate_sync_) 00145 ts_a_->connectInput (*filters_[0], *filters_[1], *filters_[2], *filters_[3], *filters_[4], nf_, nf_, nf_); 00146 else 00147 ts_e_->connectInput (*filters_[0], *filters_[1], *filters_[2], *filters_[3], *filters_[4], nf_, nf_, nf_); 00148 break; 00149 } 00150 case 6: 00151 { 00152 if (approximate_sync_) 00153 ts_a_->connectInput (*filters_[0], *filters_[1], *filters_[2], *filters_[3], *filters_[4], *filters_[5], nf_, nf_); 00154 else 00155 ts_e_->connectInput (*filters_[0], *filters_[1], *filters_[2], *filters_[3], *filters_[4], *filters_[5], nf_, nf_); 00156 break; 00157 } 00158 case 7: 00159 { 00160 if (approximate_sync_) 00161 ts_a_->connectInput (*filters_[0], *filters_[1], *filters_[2], *filters_[3], *filters_[4], *filters_[5], *filters_[6], nf_); 00162 else 00163 ts_e_->connectInput (*filters_[0], *filters_[1], *filters_[2], *filters_[3], *filters_[4], *filters_[5], *filters_[6], nf_); 00164 break; 00165 } 00166 case 8: 00167 { 00168 if (approximate_sync_) 00169 ts_a_->connectInput (*filters_[0], *filters_[1], *filters_[2], *filters_[3], *filters_[4], *filters_[5], *filters_[6], *filters_[7]); 00170 else 00171 ts_e_->connectInput (*filters_[0], *filters_[1], *filters_[2], *filters_[3], *filters_[4], *filters_[5], *filters_[6], *filters_[7]); 00172 break; 00173 } 00174 default: 00175 { 00176 NODELET_ERROR ("[onInit] Invalid 'input_topics' parameter given!"); 00177 return; 00178 } 00179 } 00180 break; 00181 } 00182 default: 00183 { 00184 NODELET_ERROR ("[onInit] Invalid 'input_topics' parameter given!"); 00185 return; 00186 } 00187 } 00188 00189 if (approximate_sync_) 00190 ts_a_->registerCallback (boost::bind (&PointCloudConcatenateDataSynchronizer::input, this, _1, _2, _3, _4, _5, _6, _7, _8)); 00191 else 00192 ts_e_->registerCallback (boost::bind (&PointCloudConcatenateDataSynchronizer::input, this, _1, _2, _3, _4, _5, _6, _7, _8)); 00193 } 00194 00196 void 00197 pcl_ros::PointCloudConcatenateDataSynchronizer::combineClouds (const PointCloud2 &in1, const PointCloud2 &in2, PointCloud2 &out) 00198 { 00199 //ROS_INFO ("Two pointclouds received: %zu and %zu.", in1.data.size (), in2.data.size ()); 00200 PointCloud2::Ptr in1_t (new PointCloud2 ()); 00201 PointCloud2::Ptr in2_t (new PointCloud2 ()); 00202 00203 // Transform the point clouds into the specified output frame 00204 if (output_frame_ != in1.header.frame_id) 00205 pcl_ros::transformPointCloud (output_frame_, in1, *in1_t, tf_); 00206 else 00207 in1_t = boost::make_shared<PointCloud2> (in1); 00208 00209 if (output_frame_ != in2.header.frame_id) 00210 pcl_ros::transformPointCloud (output_frame_, in2, *in2_t, tf_); 00211 else 00212 in2_t = boost::make_shared<PointCloud2> (in2); 00213 00214 // Concatenate the results 00215 pcl::concatenatePointCloud (*in1_t, *in2_t, out); 00216 } 00217 00219 void 00220 pcl_ros::PointCloudConcatenateDataSynchronizer::input ( 00221 const PointCloud2::ConstPtr &in1, const PointCloud2::ConstPtr &in2, 00222 const PointCloud2::ConstPtr &in3, const PointCloud2::ConstPtr &in4, 00223 const PointCloud2::ConstPtr &in5, const PointCloud2::ConstPtr &in6, 00224 const PointCloud2::ConstPtr &in7, const PointCloud2::ConstPtr &in8) 00225 { 00226 PointCloud2::Ptr out1 (new PointCloud2 ()); 00227 PointCloud2::Ptr out2 (new PointCloud2 ()); 00228 pcl_ros::PointCloudConcatenateDataSynchronizer::combineClouds (*in1, *in2, *out1); 00229 if (in3) 00230 { 00231 pcl_ros::PointCloudConcatenateDataSynchronizer::combineClouds (*out1, *in3, *out2); 00232 out1 = out2; 00233 if (in4) 00234 { 00235 pcl_ros::PointCloudConcatenateDataSynchronizer::combineClouds (*out2, *in4, *out1); 00236 if (in5) 00237 { 00238 pcl_ros::PointCloudConcatenateDataSynchronizer::combineClouds (*out1, *in5, *out2); 00239 out1 = out2; 00240 if (in6) 00241 { 00242 pcl_ros::PointCloudConcatenateDataSynchronizer::combineClouds (*out2, *in6, *out1); 00243 if (in7) 00244 { 00245 pcl_ros::PointCloudConcatenateDataSynchronizer::combineClouds (*out1, *in7, *out2); 00246 out1 = out2; 00247 } 00248 } 00249 } 00250 } 00251 } 00252 pub_output_.publish (boost::make_shared<PointCloud2> (*out1)); 00253 } 00254 00255 typedef pcl_ros::PointCloudConcatenateDataSynchronizer PointCloudConcatenateDataSynchronizer; 00256 PLUGINLIB_DECLARE_CLASS (pcl, PointCloudConcatenateDataSynchronizer, PointCloudConcatenateDataSynchronizer, nodelet::Nodelet); 00257