cloud_to_scan.cpp
Go to the documentation of this file.
00001 /*                                                                                                                       
00002  * Copyright (c) 2010, Willow Garage, Inc.                                                                               
00003  * All rights reserved.                                                                                                  
00004  *                                                                                                                       
00005  * Redistribution and use in source and binary forms, with or without                                                    
00006  * modification, are permitted provided that the following conditions are met:                                           
00007  *                                                                                                                       
00008  *     * Redistributions of source code must retain the above copyright                                                  
00009  *       notice, this list of conditions and the following disclaimer.                                                   
00010  *     * Redistributions in binary form must reproduce the above copyright                                               
00011  *       notice, this list of conditions and the following disclaimer in the                                             
00012  *       documentation and/or other materials provided with the distribution.                                            
00013  *     * Neither the name of the Willow Garage, Inc. nor the names of its                                                
00014  *       contributors may be used to endorse or promote products derived from                                            
00015  *       this software without specific prior written permission.                                                        
00016  *                                                                                                                       
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"                                           
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE                                             
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE                                            
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE                                              
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR                                                   
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF                                                  
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS                                              
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN                                               
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)                                               
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE                                            
00027  * POSSIBILITY OF SUCH DAMAGE.                                                                                           
00028  */
00029 #include "ros/ros.h"
00030 #include "pluginlib/class_list_macros.h"
00031 #include "nodelet/nodelet.h"
00032 
00033 #include "sensor_msgs/LaserScan.h"
00034 
00035 #include "pcl/point_cloud.h"
00036 #include "pcl_ros/point_cloud.h"
00037 #include "pcl/point_types.h"
00038 #include "pcl/ros/conversions.h"
00039 
00040 #include <visualization_msgs/Marker.h>
00041 
00042 // Dynamic reconfigure includes.
00043 #include <dynamic_reconfigure/server.h>
00044 // Auto-generated from cfg/ directory.
00045 #include <pcl_to_scan/cloud_to_scan_paramsConfig.h>
00046 
00047 namespace pcl_to_scan {
00048 typedef pcl::PointCloud<pcl::PointXYZ> PointCloud;
00049 
00050 class CloudToScan: public nodelet::Nodelet {
00051 public:
00052         //Constructor
00053         CloudToScan() :
00054                 min_height_(0.10), max_height_(0.15), u_min_(100), u_max_(150),
00055                                 output_frame_id_("/openi_depth_frame") {
00056         }
00057 
00058 private:
00059         virtual void onInit() {
00060                 ros::NodeHandle& nh = getNodeHandle();
00061                 ros::NodeHandle& private_nh = getPrivateNodeHandle();
00062 
00063                 dynamic_set = false;
00064 
00065                 private_nh.getParam("min_height", min_height_);
00066                 private_nh.getParam("max_height", max_height_);
00067 
00068                 private_nh.getParam("row_min", u_min_);
00069                 private_nh.getParam("row_max", u_max_);
00070 
00071                 private_nh.getParam("output_frame_id", output_frame_id_);
00072                 pub_ = nh.advertise<sensor_msgs::LaserScan> ("scan", 10);
00073                 sub_ = nh.subscribe<PointCloud> ("cloud", 10, &CloudToScan::callback,
00074                                 this);
00075 
00076                 marker_pub = nh.advertise<visualization_msgs::Marker> (
00077                                 "visualization_marker", 10);
00078 
00079                 pcl_to_scan::cloud_to_scan_paramsConfig config;
00080                 config.max_height = max_height_;
00081                 config.min_height = min_height_;
00082 
00083                 // Set up a dynamic reconfigure server.
00084                 dr_srv = new dynamic_reconfigure::Server < pcl_to_scan::cloud_to_scan_paramsConfig > ();
00085 
00086 
00087                 cb = boost::bind(&CloudToScan::configCallback, this, _1, _2);
00088                 dr_srv->updateConfig(config);
00089                 dr_srv->setCallback(cb);
00090         }
00091 
00092 
00093         void configCallback(pcl_to_scan::cloud_to_scan_paramsConfig &config, uint32_t level) {
00094                 // Set class variables to new values. They should match what is input at the dynamic reconfigure GUI.
00095                 min_height_ = config.min_height;
00096                 max_height_ = config.max_height;
00097         } // end configCallback()
00098 
00099         void callback(const PointCloud::ConstPtr& cloud) {
00100                 sensor_msgs::LaserScanPtr output(new sensor_msgs::LaserScan());
00101                 NODELET_DEBUG("Got cloud");
00102                 //Copy Header
00103                 output->header = cloud->header;
00104                 output->header.frame_id = output_frame_id_;
00105                 output->angle_min = -M_PI / 6;
00106                 output->angle_max = M_PI / 6;
00107                 output->angle_increment = M_PI / 180.0 / 2.0;
00108                 output->time_increment = 0.0;
00109                 output->scan_time = 1.0 / 30.0;
00110                 output->range_min = 0.1;
00111                 output->range_max = 10.0;
00112 
00113                 uint32_t ranges_size = std::ceil(
00114                                 (output->angle_max - output->angle_min)
00115                                                 / output->angle_increment);
00116                 output->ranges.assign(ranges_size, output->range_max + 1.0);
00117 
00118                 //pcl::PointCloud<pcl::PointXYZ> cloud;
00119                 //pcl::fromROSMsg(*input, cloud);
00120 
00121                 visualization_msgs::Marker line_list;
00122 
00123                 float min_z = 100;
00124                 float max_z = -100;
00125                 float min_y = 100;
00126                 float max_y = -100;
00127 
00128                 //    NODELET_INFO("New scan...");
00129                 for (PointCloud::const_iterator it = cloud->begin(); it != cloud->end(); ++it) {
00130                         const float &x = it->x;
00131                         const float &y = it->y;
00132                         const float &z = it->z;
00133 
00134                         if (z < min_z)
00135                                 min_z = z;
00136                         if (z > max_z)
00137                                 max_z = z;
00138 
00139                         if (y < min_y)
00140                                 min_y = y;
00141                         if (y > max_y)
00142                                 max_y = y;
00143 
00144                         /*    for (uint32_t u = std::max((uint32_t)u_min_, 0U); u < std::min((uint32_t)u_max_, cloud.height - 1); u++)
00145                          for (uint32_t v = 0; v < cloud.width -1; v++)
00146                          {
00147                          //NODELET_ERROR("%d %d,  %d %d", u, v, cloud.height, cloud.width);
00148                          pcl::PointXYZ point = cloud.at(v,u); ///WTF Column major?
00149                          const float &x = point.x;
00150                          const float &y = point.y;
00151                          const float &z = point.z;
00152                          */
00153 
00154                         if (std::isnan(x) || std::isnan(y) || std::isnan(z)) {
00155                                 NODELET_DEBUG("rejected for nan in point(%f, %f, %f)\n", x, y,
00156                                                 z);
00157                                 continue;
00158                         }
00159 
00160                         if (z > max_height_ || z < min_height_) {
00161                                 NODELET_DEBUG("rejected for height %f not in range (%f, %f)\n",
00162                                                 z, min_height_, max_height_);
00163                                 continue;
00164                         }
00165                         double angle = atan2(y, x);
00166                         if (angle < output->angle_min || angle > output->angle_max) {
00167                                 NODELET_DEBUG("rejected for angle %f not in range (%f, %f)\n",
00168                                                 angle, output->angle_min, output->angle_max);
00169                                 continue;
00170                         }
00171 
00172                         int index = (angle - output->angle_min) / output->angle_increment;
00173                         //    NODELET_INFO("index xyz( %f %f %f) angle %f index %d", x, y, z, angle, index);
00174                         double range_sq = y * y + x * x;
00175                         if (output->ranges[index] * output->ranges[index] > range_sq)
00176                                 output->ranges[index] = sqrt(range_sq);
00177 
00178                 }
00179 
00180                 NODELET_INFO("Y: %f %f, Z: %f %f", min_y, max_y, min_z, max_z);
00181 
00182                 line_list.header = cloud->header;
00183                 line_list.header.frame_id = output_frame_id_;
00184                 line_list.ns = "points_and_lines";
00185                 line_list.action = visualization_msgs::Marker::ADD;
00186                 line_list.pose.orientation.w = 1.0;
00187 
00188                 line_list.id = 0;
00189 
00190                 line_list.type = visualization_msgs::Marker::LINE_LIST;
00191 
00192                 line_list.scale.x = 0.1;
00193                 //    line_list.color.r = 1.0;
00194                 line_list.color.a = 1.0;
00195 
00196                 // Create the vertices for the points and lines
00197                 for (uint32_t i = 0; i < ranges_size; ++i) {
00198                         float rng = output->ranges[i];
00199                         float a = output->angle_min + i * output->angle_increment;
00200                         float x = rng * cos(a);
00201                         float y = rng * sin(a);
00202 
00203                         geometry_msgs::Point p;
00204                         std_msgs::ColorRGBA col;
00205                         p.x = x;
00206                         p.y = y;
00207                         p.z = min_height_;
00208 
00209                         col.g = rng / (output->range_max);
00210                         col.r = 1.0 - col.g;
00211                         line_list.colors.push_back(col);
00212                         line_list.colors.push_back(col);
00213 
00214                         // The line list needs two points for each line
00215                         line_list.points.push_back(p);
00216                         p.z = max_height_;
00217                         line_list.points.push_back(p);
00218                 }
00219 
00220                 marker_pub.publish(line_list);
00221                 pub_.publish(output);
00222         }
00223 
00224         double min_height_, max_height_;
00225         int32_t u_min_, u_max_;
00226         std::string output_frame_id_;
00227 
00228         bool dynamic_set;
00229 
00230         ros::Publisher pub_;
00231         ros::Subscriber sub_;
00232         ros::Publisher marker_pub;
00233 
00234         dynamic_reconfigure::Server < pcl_to_scan::cloud_to_scan_paramsConfig > * dr_srv;
00235         dynamic_reconfigure::Server<pcl_to_scan::cloud_to_scan_paramsConfig>::CallbackType cb;
00236 };
00237 
00238 PLUGINLIB_DECLARE_CLASS(pcl_to_scan, CloudToScan, pcl_to_scan::CloudToScan, nodelet::Nodelet);
00239 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Friends


pcl_to_scan
Author(s): Maciej Stefanczyk
autogenerated on Thu Nov 14 2013 11:56:50