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 }