$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: converter.cpp 33249 2010-03-11 02:09:24Z rusu $ 00035 * 00036 */ 00037 00046 #include <ros/ros.h> 00047 #include <boost/thread.hpp> 00048 #include <sensor_msgs/PointCloud.h> 00049 #include <sensor_msgs/PointCloud2.h> 00050 #include <sensor_msgs/point_cloud_conversion.h> 00051 00052 using namespace std; 00053 00054 class PointCloudConverter 00055 { 00056 private: 00057 boost::mutex m_mutex_; 00058 // ROS 00059 ros::NodeHandle nh_; 00060 ros::Subscriber sub_points_, sub_points2_; 00061 ros::Publisher pub_points_, pub_points2_; 00062 00063 int queue_size_; 00064 string points_in_, points2_in_, points_out_, points2_out_; 00065 int num_subs; 00066 00067 public: 00069 PointCloudConverter () : nh_ ("~"), queue_size_ (100), 00070 points_in_ ("/points_in"), points2_in_ ("/points2_in"), 00071 points_out_ ("/points_out"), points2_out_ ("/points2_out"), num_subs(0) 00072 { 00073 // Subscribe to the cloud topic using both the old message format and the new 00074 sub_points_ = nh_.subscribe (points_in_, queue_size_, &PointCloudConverter::cloud_cb_points, this); 00075 //sub_points2_ = nh_.subscribe (points2_in_, queue_size_, &PointCloudConverter::cloud_cb_points2, this); 00076 pub_points_ = nh_.advertise<sensor_msgs::PointCloud> (points_out_, queue_size_, boost::bind(&PointCloudConverter::connectCb, this), boost::bind(&PointCloudConverter::disconnectCb, this)); 00077 pub_points2_ = nh_.advertise<sensor_msgs::PointCloud2> (points2_out_, queue_size_); 00078 ROS_INFO ("PointCloudConverter initialized to transform from PointCloud (%s) to PointCloud2 (%s).", nh_.resolveName (points_in_).c_str (), nh_.resolveName (points2_out_).c_str ()); 00079 ROS_INFO ("PointCloudConverter initialized to transform from PointCloud2 (%s) to PointCloud (%s).", nh_.resolveName (points2_in_).c_str (), nh_.resolveName (points_out_).c_str ()); 00080 } 00081 00083 00086 inline std::string 00087 getFieldsList (const sensor_msgs::PointCloud2 &cloud) 00088 { 00089 std::string result; 00090 for (size_t i = 0; i < cloud.fields.size () - 1; ++i) 00091 result += cloud.fields[i].name + " "; 00092 result += cloud.fields[cloud.fields.size () - 1].name; 00093 return (result); 00094 } 00095 00097 00100 inline std::string 00101 getFieldsList (const sensor_msgs::PointCloud &points) 00102 { 00103 std::string result = "x y z"; 00104 for (size_t i = 0; i < points.channels.size (); i++) 00105 result = result + " " + points.channels[i].name; 00106 return (result); 00107 } 00108 00109 void connectCb() 00110 { 00111 num_subs++; 00112 if(num_subs > 0) 00113 { 00114 sub_points2_ = nh_.subscribe (points2_in_, queue_size_, &PointCloudConverter::cloud_cb_points2, this); 00115 } 00116 } 00117 00118 void disconnectCb() 00119 { 00120 num_subs--; 00121 if(num_subs <= 0) 00122 { 00123 sub_points2_.shutdown(); 00124 } 00125 } 00126 00127 00129 00130 void 00131 cloud_cb_points2 (const sensor_msgs::PointCloud2ConstPtr &msg) 00132 { 00133 if (pub_points_.getNumSubscribers () <= 0) 00134 { 00135 //ROS_DEBUG ("[point_cloud_converter] Got a PointCloud2 with %d points on %s, but no subscribers.", msg->width * msg->height, nh_.resolveName (points2_in_).c_str ()); 00136 return; 00137 } 00138 00139 ROS_DEBUG ("[point_cloud_converter] Got a PointCloud2 with %d points (%s) on %s.", msg->width * msg->height, getFieldsList (*msg).c_str (), nh_.resolveName (points2_in_).c_str ()); 00140 00141 sensor_msgs::PointCloud output; 00142 // Convert to the new PointCloud format 00143 if (!sensor_msgs::convertPointCloud2ToPointCloud (*msg, output)) 00144 { 00145 ROS_ERROR ("[point_cloud_converter] Conversion from sensor_msgs::PointCloud2 to sensor_msgs::PointCloud failed!"); 00146 return; 00147 } 00148 ROS_DEBUG ("[point_cloud_converter] Publishing a PointCloud with %d points on %s.", (int)output.points.size (), nh_.resolveName (points_out_).c_str ()); 00149 pub_points_.publish (output); 00150 } 00151 00153 00154 void 00155 cloud_cb_points (const sensor_msgs::PointCloudConstPtr &msg) 00156 { 00157 if (pub_points2_.getNumSubscribers () <= 0) 00158 { 00159 //ROS_DEBUG ("[point_cloud_converter] Got a PointCloud with %d points on %s, but no subscribers.", (int)msg->points.size (), nh_.resolveName (points_in_).c_str ()); 00160 return; 00161 } 00162 00163 ROS_DEBUG ("[point_cloud_converter] Got a PointCloud with %d points (%s) on %s.", (int)msg->points.size (), getFieldsList (*msg).c_str (), nh_.resolveName (points_in_).c_str ()); 00164 00165 sensor_msgs::PointCloud2 output; 00166 // Convert to the old point cloud format 00167 if (!sensor_msgs::convertPointCloudToPointCloud2 (*msg, output)) 00168 { 00169 ROS_ERROR ("[point_cloud_converter] Conversion from sensor_msgs::PointCloud to sensor_msgs::PointCloud2 failed!"); 00170 return; 00171 } 00172 ROS_DEBUG ("[point_cloud_converter] Publishing a PointCloud2 with %d points on %s.", output.height * output.width, nh_.resolveName (points2_out_).c_str ()); 00173 pub_points2_.publish (output); 00174 } 00175 00176 }; 00177 00178 /* ---[ */ 00179 int 00180 main (int argc, char** argv) 00181 { 00182 // ROS init 00183 ros::init (argc, argv, "point_cloud_converter", ros::init_options::AnonymousName); 00184 00185 PointCloudConverter p; 00186 ros::spin (); 00187 00188 return (0); 00189 } 00190