00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <cob_scan_unifier/scan_unifier_node.h>
00019
00020
00021 ScanUnifierNode::ScanUnifierNode()
00022 {
00023 ROS_DEBUG("Init scan_unifier");
00024
00025
00026 nh_ = ros::NodeHandle();
00027 pnh_ = ros::NodeHandle("~");
00028
00029
00030 topicPub_LaserUnified_ = nh_.advertise<sensor_msgs::LaserScan>("scan_unified", 1);
00031
00032 getParams();
00033 synchronizer2_ = NULL;
00034 synchronizer3_ = NULL;
00035 synchronizer4_ = NULL;
00036
00037
00038
00039 for(int i = 0; i < config_.number_input_scans; i++)
00040 {
00041 message_filter_subscribers_.push_back(new message_filters::Subscriber<sensor_msgs::LaserScan>(nh_, config_.input_scan_topics.at(i), 1));
00042 }
00043
00044
00045
00046
00047 switch (config_.number_input_scans)
00048 {
00049 case 2:
00050 {
00051 typedef message_filters::sync_policies::ApproximateTime<sensor_msgs::LaserScan, sensor_msgs::LaserScan> SyncPolicy;
00052 synchronizer2_ = new message_filters::Synchronizer<SyncPolicy>(SyncPolicy(2), *message_filter_subscribers_.at(0),
00053 *message_filter_subscribers_.at(1));
00054
00055 synchronizer2_->setInterMessageLowerBound(0, ros::Duration(0.167));
00056 synchronizer2_->setInterMessageLowerBound(1, ros::Duration(0.167));
00057 synchronizer2_->registerCallback(boost::bind(&ScanUnifierNode::messageFilterCallback, this, _1, _2));
00058 break;
00059 }
00060 case 3:
00061 {
00062 typedef message_filters::sync_policies::ApproximateTime<sensor_msgs::LaserScan, sensor_msgs::LaserScan, sensor_msgs::LaserScan> SyncPolicy;
00063 synchronizer3_ = new message_filters::Synchronizer<SyncPolicy>(SyncPolicy(3), *message_filter_subscribers_.at(0),
00064 *message_filter_subscribers_.at(1),
00065 *message_filter_subscribers_.at(2));
00066 synchronizer3_->setInterMessageLowerBound(0, ros::Duration(0.167));
00067 synchronizer3_->setInterMessageLowerBound(1, ros::Duration(0.167));
00068 synchronizer3_->setInterMessageLowerBound(2, ros::Duration(0.167));
00069 synchronizer3_->registerCallback(boost::bind(&ScanUnifierNode::messageFilterCallback, this, _1, _2, _3));
00070 break;
00071 }
00072 case 4:
00073 {
00074 typedef message_filters::sync_policies::ApproximateTime<sensor_msgs::LaserScan, sensor_msgs::LaserScan, sensor_msgs::LaserScan, sensor_msgs::LaserScan> SyncPolicy;
00075 synchronizer4_ = new message_filters::Synchronizer<SyncPolicy>(SyncPolicy(4), *message_filter_subscribers_.at(0),
00076 *message_filter_subscribers_.at(1),
00077 *message_filter_subscribers_.at(2),
00078 *message_filter_subscribers_.at(3));
00079 synchronizer4_->setInterMessageLowerBound(0, ros::Duration(0.167));
00080 synchronizer4_->setInterMessageLowerBound(1, ros::Duration(0.167));
00081 synchronizer4_->setInterMessageLowerBound(2, ros::Duration(0.167));
00082 synchronizer4_->setInterMessageLowerBound(3, ros::Duration(0.167));
00083 synchronizer4_->registerCallback(boost::bind(&ScanUnifierNode::messageFilterCallback, this, _1, _2, _3, _4));
00084 break;
00085 }
00086 default:
00087 ROS_ERROR_STREAM(config_.number_input_scans << " topics have been set as input, but scan_unifier doesn't support this.");
00088 return;
00089 }
00090
00091 ros::Duration(1.0).sleep();
00092 }
00093
00094
00095
00096 ScanUnifierNode::~ScanUnifierNode()
00097 {
00098 if(synchronizer2_ != NULL)
00099 delete(synchronizer2_);
00100 if(synchronizer3_ != NULL)
00101 delete(synchronizer3_);
00102 if(synchronizer4_ != NULL)
00103 delete(synchronizer4_);
00104 }
00105
00113 void ScanUnifierNode::getParams()
00114 {
00115 std::vector<std::string> topicList;
00116
00117 if (pnh_.getParam("input_scans", topicList))
00118 {
00119 config_.input_scan_topics = topicList;
00120 config_.number_input_scans = config_.input_scan_topics.size();
00121 }
00122 else
00123 {
00124 config_.number_input_scans = 0;
00125 ROS_ERROR("No parameter input_scans on parameter server!! Scan unifier can not subscribe to any scan topic!");
00126 }
00127
00128 if(!pnh_.hasParam("frame"))
00129 {
00130 ROS_WARN("No parameter frame on parameter server. Using default value [base_link].");
00131 }
00132 pnh_.param<std::string>("frame", frame_, "base_link");
00133 }
00134
00135
00136 void ScanUnifierNode::messageFilterCallback(const sensor_msgs::LaserScan::ConstPtr& scan1, const sensor_msgs::LaserScan::ConstPtr& scan2)
00137 {
00138 std::vector<sensor_msgs::LaserScan::ConstPtr> current_scans;
00139 current_scans.push_back(scan1);
00140 current_scans.push_back(scan2);
00141
00142 sensor_msgs::LaserScan unified_scan = sensor_msgs::LaserScan();
00143 if (!unifyLaserScans(current_scans, unified_scan))
00144 {
00145 return;
00146 }
00147
00148 ROS_DEBUG("Publishing unified scan.");
00149 topicPub_LaserUnified_.publish(unified_scan);
00150 }
00151
00152 void ScanUnifierNode::messageFilterCallback(const sensor_msgs::LaserScan::ConstPtr& scan1,
00153 const sensor_msgs::LaserScan::ConstPtr& scan2,
00154 const sensor_msgs::LaserScan::ConstPtr& scan3)
00155 {
00156 std::vector<sensor_msgs::LaserScan::ConstPtr> current_scans;
00157 current_scans.push_back(scan1);
00158 current_scans.push_back(scan2);
00159 current_scans.push_back(scan3);
00160
00161 sensor_msgs::LaserScan unified_scan = sensor_msgs::LaserScan();
00162 if (!unifyLaserScans(current_scans, unified_scan))
00163 {
00164 return;
00165 }
00166
00167 ROS_DEBUG("Publishing unified scan.");
00168 topicPub_LaserUnified_.publish(unified_scan);
00169 }
00170
00171 void ScanUnifierNode::messageFilterCallback(const sensor_msgs::LaserScan::ConstPtr& scan1,
00172 const sensor_msgs::LaserScan::ConstPtr& scan2,
00173 const sensor_msgs::LaserScan::ConstPtr& scan3,
00174 const sensor_msgs::LaserScan::ConstPtr& scan4)
00175 {
00176 std::vector<sensor_msgs::LaserScan::ConstPtr> current_scans;
00177 current_scans.push_back(scan1);
00178 current_scans.push_back(scan2);
00179 current_scans.push_back(scan3);
00180 current_scans.push_back(scan4);
00181
00182 sensor_msgs::LaserScan unified_scan = sensor_msgs::LaserScan();
00183 if (!unifyLaserScans(current_scans, unified_scan))
00184 {
00185 return;
00186 }
00187
00188 ROS_DEBUG("Publishing unified scan.");
00189 topicPub_LaserUnified_.publish(unified_scan);
00190 }
00191
00200 bool ScanUnifierNode::unifyLaserScans(std::vector<sensor_msgs::LaserScan::ConstPtr> current_scans, sensor_msgs::LaserScan &unified_scan)
00201 {
00202 std::vector<sensor_msgs::PointCloud> vec_cloud;
00203 vec_cloud.assign(config_.number_input_scans, sensor_msgs::PointCloud());
00204
00205 if(!current_scans.empty())
00206 {
00207 ROS_DEBUG("start converting");
00208 for(int i=0; i < config_.number_input_scans; i++)
00209 {
00210 vec_cloud.at(i).header.stamp = current_scans.at(i)->header.stamp;
00211 ROS_DEBUG_STREAM("Converting scans to point clouds at index: " << i << ", at time: " << current_scans.at(i)->header.stamp << " now: " << ros::Time::now());
00212 try
00213 {
00214 if (!listener_.waitForTransform(frame_, current_scans.at(i)->header.frame_id,
00215 current_scans.at(i)->header.stamp, ros::Duration(1.0)))
00216 {
00217 ROS_WARN_STREAM("Scan unifier skipped scan with " << current_scans.at(i)->header.stamp << " stamp, because of missing tf transform.");
00218 return false;
00219 }
00220
00221 ROS_DEBUG("now project to point_cloud");
00222 projector_.transformLaserScanToPointCloud(frame_,*current_scans.at(i), vec_cloud.at(i), listener_);
00223 }
00224 catch(tf::TransformException &ex){
00225 ROS_ERROR("%s",ex.what());
00226 }
00227 }
00228 ROS_DEBUG("Creating message header");
00229 unified_scan.header = current_scans.at(0)->header;
00230 unified_scan.header.frame_id = frame_;
00231 unified_scan.angle_increment = M_PI/180.0/2.0;
00232 unified_scan.angle_min = -M_PI + unified_scan.angle_increment*0.01;
00233 unified_scan.angle_max = M_PI - unified_scan.angle_increment*0.01;
00234 unified_scan.time_increment = 0.0;
00235 unified_scan.scan_time = current_scans.at(0)->scan_time;
00236 unified_scan.range_min = current_scans.at(0)->range_min;
00237 unified_scan.range_max = current_scans.at(0)->range_max;
00238
00239
00240
00241 unified_scan.ranges.resize(round((unified_scan.angle_max - unified_scan.angle_min) / unified_scan.angle_increment) + 1, unified_scan.range_max);
00242 unified_scan.intensities.resize(round((unified_scan.angle_max - unified_scan.angle_min) / unified_scan.angle_increment) + 1, 0.0);
00243
00244
00245 ROS_DEBUG("unify scans");
00246 for(int j = 0; j < config_.number_input_scans; j++)
00247 {
00248 for (unsigned int i = 0; i < vec_cloud.at(j).points.size(); i++)
00249 {
00250 const float &x = vec_cloud.at(j).points[i].x;
00251 const float &y = vec_cloud.at(j).points[i].y;
00252 const float &z = vec_cloud.at(j).points[i].z;
00253
00254 if ( std::isnan(x) || std::isnan(y) || std::isnan(z) )
00255 {
00256 ROS_DEBUG("rejected for nan in point(%f, %f, %f)\n", x, y, z);
00257 continue;
00258 }
00259 double angle = atan2(y, x);
00260 if (angle < unified_scan.angle_min || angle > unified_scan.angle_max)
00261 {
00262 ROS_DEBUG("rejected for angle %f not in range (%f, %f)\n", angle, unified_scan.angle_min, unified_scan.angle_max);
00263 continue;
00264 }
00265 int index = std::floor(0.5 + (angle - unified_scan.angle_min) / unified_scan.angle_increment);
00266 if(index<0 || index>=unified_scan.ranges.size()) continue;
00267
00268 double range_sq = y*y+x*x;
00269
00270 if( (sqrt(range_sq) <= unified_scan.ranges.at(index)) )
00271 {
00272
00273 unified_scan.ranges.at(index) = sqrt(range_sq);
00274
00275 unified_scan.intensities.at(index) = vec_cloud.at(j).channels.at(0).values.at(i);
00276 }
00277 }
00278 }
00279 }
00280
00281 return true;
00282 }
00283
00284 int main(int argc, char** argv)
00285 {
00286 ROS_DEBUG("scan unifier: start scan unifier node");
00287 ros::init(argc, argv, "cob_scan_unifier_node");
00288
00289 ScanUnifierNode scan_unifier_node;
00290
00291 ros::spin();
00292
00293 return 0;
00294 }