Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
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 
00043 #include <dynamic_reconfigure/server.h>
00044 
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         
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                 
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                 
00095                 min_height_ = config.min_height;
00096                 max_height_ = config.max_height;
00097         } 
00098 
00099         void callback(const PointCloud::ConstPtr& cloud) {
00100                 sensor_msgs::LaserScanPtr output(new sensor_msgs::LaserScan());
00101                 NODELET_DEBUG("Got cloud");
00102                 
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                 
00119                 
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                 
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                         
00145 
00146 
00147 
00148 
00149 
00150 
00151 
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                         
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                 
00194                 line_list.color.a = 1.0;
00195 
00196                 
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                         
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 }