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
00031
00032
00033
00034
00035
00036
00037 #include <ros/ros.h>
00038 #include <sensor_msgs/PointCloud.h>
00039 #include <sensor_msgs/LaserScan.h>
00040
00041 #include <float.h>
00042
00043
00044 #include <laser_geometry/laser_geometry.h>
00045
00046
00047 #include <tf/transform_listener.h>
00048 #include "tf/message_filter.h"
00049 #include "message_filters/subscriber.h"
00050
00051
00052 #include "filters/filter_chain.h"
00053
00054
00057 class ScanToCloudFilterChain
00058 {
00059 public:
00060
00061
00062 laser_geometry::LaserProjection projector_;
00063
00064 double laser_max_range_;
00065 int window_;
00066
00067 bool high_fidelity_;
00068 bool preservative_;
00069 std::string target_frame_;
00070 std::string scan_topic_, cloud_topic_;
00071 bool use_cloud_input_;
00072
00073 ros::NodeHandle nh;
00074 ros::NodeHandle private_nh;
00075
00076
00077 tf::TransformListener tf_;
00078
00079 message_filters::Subscriber<sensor_msgs::LaserScan> sub_;
00080 tf::MessageFilter<sensor_msgs::LaserScan> filter_;
00081 message_filters::Subscriber<sensor_msgs::PointCloud> cloud_sub_;
00082 tf::MessageFilter<sensor_msgs::PointCloud> cloud_filter_;
00083
00084 double tf_tolerance_;
00085 filters::FilterChain<sensor_msgs::PointCloud> cloud_filter_chain_;
00086 filters::FilterChain<sensor_msgs::LaserScan> scan_filter_chain_;
00087 ros::Publisher cloud_pub_;
00088
00089
00090 ros::Timer deprecation_timer_;
00091 bool using_preservative_deprecated_;
00092 bool using_scan_topic_deprecated_;
00093 bool using_cloud_topic_deprecated_;
00094 bool using_default_target_frame_deprecated_;
00095 bool using_laser_max_range_deprecated_;
00096 bool using_filter_window_deprecated_;
00097 bool using_scan_filters_deprecated_;
00098 bool using_cloud_filters_deprecated_;
00099 bool using_scan_filters_wrong_deprecated_;
00100 bool using_cloud_filters_wrong_deprecated_;
00101
00103 ScanToCloudFilterChain () : laser_max_range_ (DBL_MAX), private_nh("~"),
00104 filter_(tf_, "", 50), cloud_filter_(tf_, "", 50),
00105 cloud_filter_chain_("sensor_msgs::PointCloud"),
00106 scan_filter_chain_("sensor_msgs::LaserScan")
00107 {
00108 private_nh.param("high_fidelity", high_fidelity_, false);
00109 private_nh.param("notifier_tolerance", tf_tolerance_, 0.03);
00110 private_nh.param("target_frame", target_frame_, std::string ("base_link"));
00111
00112
00113 using_default_target_frame_deprecated_ = !private_nh.hasParam("target_frame");
00114
00115
00116 using_preservative_deprecated_ = private_nh.hasParam("preservative");
00117 using_scan_topic_deprecated_ = private_nh.hasParam("scan_topic");
00118 using_cloud_topic_deprecated_ = private_nh.hasParam("cloud_topic");
00119 using_laser_max_range_deprecated_ = private_nh.hasParam("laser_max_range");
00120 using_filter_window_deprecated_ = private_nh.hasParam("filter_window");
00121 using_cloud_filters_deprecated_ = private_nh.hasParam("cloud_filters/filter_chain");
00122 using_scan_filters_deprecated_ = private_nh.hasParam("scan_filters/filter_chain");
00123 using_cloud_filters_wrong_deprecated_ = private_nh.hasParam("cloud_filters/cloud_filter_chain");
00124 using_scan_filters_wrong_deprecated_ = private_nh.hasParam("scan_filters/scan_filter_chain");
00125
00126
00127 private_nh.param("filter_window", window_, 2);
00128 private_nh.param("laser_max_range", laser_max_range_, DBL_MAX);
00129 private_nh.param("preservative", preservative_, false);
00130 private_nh.param("scan_topic", scan_topic_, std::string("tilt_scan"));
00131 private_nh.param("cloud_topic", cloud_topic_, std::string("tilt_laser_cloud_filtered"));
00132 private_nh.param("use_cloud_input", use_cloud_input_, false);
00133
00134 if (use_cloud_input_) {
00135 cloud_filter_.setTargetFrame(target_frame_);
00136 cloud_filter_.registerCallback(boost::bind(&ScanToCloudFilterChain::cloudCallback, this, _1));
00137 cloud_filter_.setTolerance(ros::Duration(tf_tolerance_));
00138 cloud_sub_.subscribe(nh, "cloud", 50);
00139 cloud_filter_.connectInput(cloud_sub_);
00140 }
00141
00142 else {
00143 filter_.setTargetFrame(target_frame_);
00144 filter_.registerCallback(boost::bind(&ScanToCloudFilterChain::scanCallback, this, _1));
00145 filter_.setTolerance(ros::Duration(tf_tolerance_));
00146 if (using_scan_topic_deprecated_)
00147 sub_.subscribe(nh, scan_topic_, 50);
00148 else
00149 sub_.subscribe(nh, "scan", 50);
00150 filter_.connectInput(sub_);
00151 if (using_scan_filters_deprecated_)
00152 scan_filter_chain_.configure("scan_filter/filter_chain", private_nh);
00153 else if (using_scan_filters_wrong_deprecated_)
00154 scan_filter_chain_.configure("scan_filters/scan_filter_chain", private_nh);
00155 else
00156 scan_filter_chain_.configure("scan_filter_chain", private_nh);
00157 }
00158
00159 if (using_cloud_topic_deprecated_)
00160 cloud_pub_ = nh.advertise<sensor_msgs::PointCloud> (cloud_topic_, 10);
00161 else
00162 cloud_pub_ = nh.advertise<sensor_msgs::PointCloud> ("cloud_filtered", 10);
00163
00164 std::string cloud_filter_xml;
00165
00166 if (using_cloud_filters_deprecated_)
00167 cloud_filter_chain_.configure("cloud_filters/filter_chain", private_nh);
00168 else if (using_cloud_filters_wrong_deprecated_)
00169 cloud_filter_chain_.configure("cloud_filters/cloud_filter_chain", private_nh);
00170 else
00171 cloud_filter_chain_.configure("cloud_filter_chain", private_nh);
00172
00173 deprecation_timer_ = nh.createTimer(ros::Duration(5.0), boost::bind(&ScanToCloudFilterChain::deprecation_warn, this, _1));
00174 }
00175
00176
00177 void deprecation_warn(const ros::TimerEvent& e)
00178 {
00179 if (using_preservative_deprecated_)
00180 ROS_WARN("Use of '~preservative' parameter in scan_to_cloud_filter_chain has been deprecated.");
00181
00182 if (using_scan_topic_deprecated_)
00183 ROS_WARN("Use of '~scan_topic' parameter in scan_to_cloud_filter_chain has been deprecated.");
00184
00185 if (using_cloud_topic_deprecated_)
00186 ROS_WARN("Use of '~cloud_topic' parameter in scan_to_cloud_filter_chain has been deprecated.");
00187
00188 if (using_laser_max_range_deprecated_)
00189 ROS_WARN("Use of '~laser_max_range' parameter in scan_to_cloud_filter_chain has been deprecated.");
00190
00191 if (using_filter_window_deprecated_)
00192 ROS_WARN("Use of '~filter_window' parameter in scan_to_cloud_filter_chain has been deprecated.");
00193
00194 if (using_default_target_frame_deprecated_)
00195 ROS_WARN("Use of default '~target_frame' parameter in scan_to_cloud_filter_chain has been deprecated. Default currently set to 'base_link' please set explicitly as appropriate.");
00196
00197 if (using_cloud_filters_deprecated_)
00198 ROS_WARN("Use of '~cloud_filters/filter_chain' parameter in scan_to_cloud_filter_chain has been deprecated. Replace with '~cloud_filter_chain'");
00199
00200 if (using_scan_filters_deprecated_)
00201 ROS_WARN("Use of '~scan_filters/filter_chain' parameter in scan_to_cloud_filter_chain has been deprecated. Replace with '~scan_filter_chain'");
00202
00203 if (using_cloud_filters_wrong_deprecated_)
00204 ROS_WARN("Use of '~cloud_filters/cloud_filter_chain' parameter in scan_to_cloud_filter_chain is incorrect. Please Replace with '~cloud_filter_chain'");
00205
00206 if (using_scan_filters_wrong_deprecated_)
00207 ROS_WARN("Use of '~scan_filters/scan_filter_chain' parameter in scan_to_scan_filter_chain is incorrect. Please Replace with '~scan_filter_chain'");
00208
00209 }
00210
00212 void
00213 cloudCallback (const sensor_msgs::PointCloud::ConstPtr& cloud_msg)
00214 {
00215 sensor_msgs::PointCloud transformed_cloud, filtered_cloud;
00216 tf_.transformPointCloud(target_frame_, *cloud_msg, transformed_cloud);
00217 cloud_filter_chain_.update(transformed_cloud, filtered_cloud);
00218 cloud_pub_.publish(filtered_cloud);
00219 }
00220
00222 void
00223 scanCallback (const sensor_msgs::LaserScan::ConstPtr& scan_msg)
00224 {
00225
00226
00227 sensor_msgs::LaserScan filtered_scan;
00228 scan_filter_chain_.update (*scan_msg, filtered_scan);
00229
00230
00231 sensor_msgs::PointCloud tmp_cloud;
00232 sensor_msgs::PointCloud scan_cloud;
00233
00234
00235
00236 for (unsigned int i = 0; i < filtered_scan.ranges.size(); i++)
00237 {
00238 double angle = filtered_scan.angle_min + i * filtered_scan.angle_increment;
00239 filtered_scan.ranges[i] = filtered_scan.ranges[i] + 0.03 * exp(-fabs(sin(angle)));
00240
00241 };
00242
00243
00244 int mask = laser_geometry::channel_option::Intensity |
00245 laser_geometry::channel_option::Distance |
00246 laser_geometry::channel_option::Index |
00247 laser_geometry::channel_option::Timestamp;
00248
00249 if (high_fidelity_)
00250 {
00251 try
00252 {
00253 projector_.transformLaserScanToPointCloud (target_frame_, filtered_scan, scan_cloud, tf_, mask);
00254 }
00255 catch (tf::TransformException &ex)
00256 {
00257 ROS_WARN("High fidelity enabled, but TF returned a transform exception to frame %s: %s", target_frame_.c_str (), ex.what ());
00258 return;
00259
00260 }
00261 }
00262 else
00263 {
00264 projector_.projectLaser (filtered_scan, tmp_cloud, laser_max_range_, mask);
00265 tf_.transformPointCloud(target_frame_, tmp_cloud, scan_cloud);
00266 }
00267
00268 sensor_msgs::PointCloud filtered_cloud;
00269 cloud_filter_chain_.update (scan_cloud, filtered_cloud);
00270
00271 cloud_pub_.publish(filtered_cloud);
00272 }
00273
00274 } ;
00275
00276
00277
00278 int
00279 main (int argc, char** argv)
00280 {
00281 ros::init (argc, argv, "scan_to_cloud_filter_chain");
00282 ros::NodeHandle nh;
00283 ScanToCloudFilterChain f;
00284
00285 ros::spin();
00286
00287 return (0);
00288 }
00289
00290