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
00030 #include "ros/ros.h"
00031 #include "pluginlib/class_list_macros.h"
00032 #include "nodelet/nodelet.h"
00033 #include "sensor_msgs/LaserScan.h"
00034 #include "pcl/point_cloud.h"
00035 #include "pcl_ros/point_cloud.h"
00036 #include "pcl/point_types.h"
00037 #include "pcl/ros/conversions.h"
00038 #include "dynamic_reconfigure/server.h"
00039 #include "pointcloud_to_laserscan/CloudScanConfig.h"
00040
00041
00042 namespace pointcloud_to_laserscan
00043 {
00044 typedef pcl::PointCloud<pcl::PointXYZ> PointCloud;
00045
00046 class CloudToScan : public nodelet::Nodelet
00047 {
00048 public:
00049
00050 CloudToScan(): min_height_(0.10),
00051 max_height_(0.15),
00052 angle_min_(-M_PI/2),
00053 angle_max_(M_PI/2),
00054 angle_increment_(M_PI/180.0/2.0),
00055 scan_time_(1.0/30.0),
00056 range_min_(0.45),
00057 range_max_(10.0),
00058 output_frame_id_("/openi_depth_frame")
00059 {
00060 };
00061
00062 ~CloudToScan()
00063 {
00064 delete srv_;
00065 }
00066
00067
00068 private:
00069
00070 dynamic_reconfigure::Server<pointcloud_to_laserscan::CloudScanConfig>* srv_;
00071
00072 virtual void onInit()
00073 {
00074 ros::NodeHandle& nh = getNodeHandle();
00075 ros::NodeHandle& private_nh = getPrivateNodeHandle();
00076
00077 private_nh.getParam("min_height", min_height_);
00078 private_nh.getParam("max_height", max_height_);
00079
00080 private_nh.getParam("angle_min", angle_min_);
00081 private_nh.getParam("angle_max", angle_max_);
00082 private_nh.getParam("angle_increment", angle_increment_);
00083 private_nh.getParam("scan_time", scan_time_);
00084 private_nh.getParam("range_min", range_min_);
00085 private_nh.getParam("range_max", range_max_);
00086
00087
00088
00089
00090 private_nh.getParam("output_frame_id", output_frame_id_);
00091 pub_ = nh.advertise<sensor_msgs::LaserScan>("scan", 10);
00092 sub_ = nh.subscribe<PointCloud>("cloud", 10, &CloudToScan::callback, this);
00093
00094 srv_ = new dynamic_reconfigure::Server<pointcloud_to_laserscan::CloudScanConfig>(private_nh);
00095 dynamic_reconfigure::Server<pointcloud_to_laserscan::CloudScanConfig>::CallbackType f = boost::bind(&CloudToScan::reconfigure, this, _1, _2);
00096 srv_->setCallback(f);
00097 };
00098
00099 void reconfigure(pointcloud_to_laserscan::CloudScanConfig &config, uint32_t level)
00100 {
00101
00102 min_height_ = config.min_height;
00103 max_height_ = config.max_height;
00104 angle_min_ = config.angle_min;
00105 angle_max_ = config.angle_max;
00106 angle_increment_ = config.angle_increment;
00107 scan_time_ = config.scan_time;
00108 range_min_ = config.range_min;
00109 range_max_ = config.range_max;
00110
00111 }
00112
00113 void callback(const PointCloud::ConstPtr& cloud)
00114 {
00115 sensor_msgs::LaserScanPtr output(new sensor_msgs::LaserScan());
00116 NODELET_DEBUG("Got cloud");
00117
00118 output->header = cloud->header;
00119 output->header.frame_id = output_frame_id_;
00120 output->angle_min = angle_min_;
00121 output->angle_max = angle_max_;
00122 output->angle_increment = angle_increment_;
00123 output->time_increment = 0.0;
00124 output->scan_time = scan_time_;
00125 output->range_min = range_min_;
00126 output->range_max = range_max_;
00127
00128 uint32_t ranges_size = std::ceil((output->angle_max - output->angle_min) / output->angle_increment);
00129 output->ranges.assign(ranges_size, output->range_max + 1.0);
00130
00131
00132
00133
00134 for (PointCloud::const_iterator it = cloud->begin(); it != cloud->end(); ++it)
00135 {
00136 const float &x = it->x;
00137 const float &y = it->y;
00138 const float &z = it->z;
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 if ( std::isnan(x) || std::isnan(y) || std::isnan(z) )
00151 {
00152 NODELET_DEBUG("rejected for nan in point(%f, %f, %f)\n", x, y, z);
00153 continue;
00154 }
00155 if (-y > max_height_ || -y < min_height_)
00156 {
00157 NODELET_DEBUG("rejected for height %f not in range (%f, %f)\n", x, min_height_, max_height_);
00158 continue;
00159 }
00160 double angle = -atan2(x, z);
00161 if (angle < output->angle_min || angle > output->angle_max)
00162 {
00163 NODELET_DEBUG("rejected for angle %f not in range (%f, %f)\n", angle, output->angle_min, output->angle_max);
00164 continue;
00165 }
00166 int index = (angle - output->angle_min) / output->angle_increment;
00167
00168 double range_sq = z*z+x*x;
00169 if (output->ranges[index] * output->ranges[index] > range_sq)
00170 output->ranges[index] = sqrt(range_sq);
00171 }
00172
00173 pub_.publish(output);
00174 }
00175
00176
00177 double min_height_, max_height_, angle_min_, angle_max_, angle_increment_, scan_time_, range_min_, range_max_;
00178
00179 std::string output_frame_id_;
00180
00181 ros::Publisher pub_;
00182 ros::Subscriber sub_;
00183
00184 };
00185
00186
00187 PLUGINLIB_DECLARE_CLASS(pointcloud_to_laserscan, CloudToScan, pointcloud_to_laserscan::CloudToScan, nodelet::Nodelet);
00188 }