Go to the documentation of this file.00001
00059 #include <scan_unifier_node.h>
00060
00061
00062 scan_unifier_node::scan_unifier_node()
00063 {
00064 ROS_DEBUG("init laser unification");
00065
00066 nh_ = ros::NodeHandle();
00067 pnh_ = ros::NodeHandle("~");
00068
00069
00070 topicPub_LaserUnified_ = nh_.advertise<sensor_msgs::LaserScan>("scan_unified", 1);
00071
00072 getParams();
00073
00074 ROS_DEBUG("scan unifier: now init laser structs");
00075
00076 pthread_mutex_init(&m_mutex, NULL);
00077
00078 initLaserScanStructs();
00079
00080
00081 }
00082
00083
00084 scan_unifier_node::~scan_unifier_node(){}
00085
00093 void scan_unifier_node::getParams()
00094 {
00095
00096 if(!pnh_.hasParam("loop_rate"))
00097 {
00098 ROS_WARN("No parameter loop_rate on parameter server. Using default value [100.0].");
00099 }
00100 pnh_.param("loop_rate", config_.loop_rate, (double)100.0);
00101
00102 XmlRpc::XmlRpcValue topicList;
00103
00104 if (pnh_.getParam("input_scans", topicList))
00105 {
00106 ROS_ASSERT(topicList.getType() == XmlRpc::XmlRpcValue::TypeArray);
00107
00108 if(topicList.getType() == XmlRpc::XmlRpcValue::TypeArray)
00109 {
00110 for (int32_t i = 0; i < topicList.size(); ++i)
00111 {
00112 ROS_ASSERT(topicList[i].getType() == XmlRpc::XmlRpcValue::TypeString);
00113 config_.input_scan_topics.push_back(static_cast<std::string>(topicList[i]));
00114
00115 ROS_DEBUG_STREAM("Parsed the scan topic: " << config_.input_scan_topics.back());
00116 }
00117
00118 config_.number_input_scans = config_.input_scan_topics.size();
00119 }
00120 }
00121 else
00122 {
00123 config_.number_input_scans = 0;
00124 ROS_ERROR("No parameter input_scans on parameter server!! Scan unifier can not subscribe to any scan topic!");
00125 }
00126 }
00127
00136 double scan_unifier_node::getLoopRate()
00137 {
00138 return config_.loop_rate;
00139 }
00140
00150 void scan_unifier_node::set_new_msg_received(bool received, int scan_id)
00151 {
00152 pthread_mutex_lock(&m_mutex);
00153 vec_laser_struct_.at(scan_id).new_msg_received = received;
00154 pthread_mutex_unlock(&m_mutex);
00155 }
00156
00166 bool scan_unifier_node::get_new_msg_received(int scan_id)
00167 {
00168 pthread_mutex_lock(&m_mutex);
00169 bool ret_val = vec_laser_struct_.at(scan_id).new_msg_received;
00170 pthread_mutex_unlock(&m_mutex);
00171 return ret_val;
00172 }
00173
00182 void scan_unifier_node::initLaserScanStructs()
00183 {
00184 laser_scan_struct dummy_struct;
00185 vec_laser_struct_.assign(config_.number_input_scans, dummy_struct);
00186
00187 for(int i = 0; i < config_.number_input_scans; i++)
00188 {
00189 set_new_msg_received(false, i);
00190 vec_laser_struct_.at(i).scan_id = i;
00191 vec_laser_struct_.at(i).scan_topic = config_.input_scan_topics.at(i);
00192 vec_laser_struct_.at(i).current_scan_msg = sensor_msgs::LaserScan();
00193 vec_laser_struct_.at(i).laser_sub = nh_.subscribe<sensor_msgs::LaserScan>
00194 (vec_laser_struct_.at(i).scan_topic , 1, boost::bind(&scan_unifier_node::topicCallbackLaserScan, this, _1, i));
00195 }
00196 }
00197
00207 void scan_unifier_node::topicCallbackLaserScan(const sensor_msgs::LaserScan::ConstPtr& scan_in, int scan_id)
00208 {
00209 ROS_DEBUG_STREAM("scan-unifier: Laser-callback!");
00210 if(!get_new_msg_received(scan_id))
00211 {
00212 vec_laser_struct_.at(scan_id).current_scan_msg = *scan_in;
00213 ROS_DEBUG_STREAM("received msg from scan_id: " << scan_id);
00214 set_new_msg_received(true, scan_id);
00215 }
00216 else
00217 {
00218 ROS_DEBUG_STREAM("received msg from scan_id: " << scan_id << "but storage blocked by mutex");
00219 }
00220 }
00221
00230 sensor_msgs::LaserScan scan_unifier_node::unifieLaserScans()
00231 {
00232 sensor_msgs::LaserScan unified_scan = sensor_msgs::LaserScan();
00233 std::vector<sensor_msgs::PointCloud> vec_cloud;
00234 vec_cloud.assign(config_.number_input_scans, sensor_msgs::PointCloud());
00235
00236 if(!vec_laser_struct_.empty())
00237 {
00238 ROS_DEBUG("start converting");
00239 for(int i=0; i < config_.number_input_scans; i++)
00240 {
00241 vec_cloud.at(i).header.stamp = vec_laser_struct_.at(i).current_scan_msg.header.stamp;
00242 ROS_DEBUG_STREAM("Converting scans to point clouds at index: " << i << ", at time: " << vec_laser_struct_.at(i).current_scan_msg.header.stamp << " now: " << ros::Time::now());
00243 try
00244 {
00245 listener_.waitForTransform("/base_link", vec_laser_struct_.at(i).current_scan_msg.header.frame_id,
00246 vec_laser_struct_.at(i).current_scan_msg.header.stamp, ros::Duration(3.0));
00247
00248 ROS_DEBUG("now project to point_cloud");
00249 projector_.transformLaserScanToPointCloud("/base_link",vec_laser_struct_.at(i).current_scan_msg, vec_cloud.at(i), listener_);
00250 }
00251 catch(tf::TransformException ex){
00252 ROS_ERROR("%s",ex.what());
00253 }
00254 }
00255 ROS_DEBUG("Creating message header");
00256 unified_scan.header = vec_laser_struct_.at(0).current_scan_msg.header;
00257 unified_scan.header.frame_id = "base_link";
00258 unified_scan.angle_increment = M_PI/180.0/2.0;
00259 unified_scan.angle_min = -M_PI + unified_scan.angle_increment*0.01;
00260 unified_scan.angle_max = M_PI - unified_scan.angle_increment*0.01;
00261 unified_scan.time_increment = 0.0;
00262 unified_scan.scan_time = vec_laser_struct_.at(0).current_scan_msg.scan_time;
00263 unified_scan.range_min = vec_laser_struct_.at(0).current_scan_msg.range_min;
00264 unified_scan.range_max = vec_laser_struct_.at(0).current_scan_msg.range_max;
00265 unified_scan.ranges.resize(round((unified_scan.angle_max - unified_scan.angle_min) / unified_scan.angle_increment) + 1);
00266 unified_scan.intensities.resize(round((unified_scan.angle_max - unified_scan.angle_min) / unified_scan.angle_increment) + 1);
00267
00268
00269 ROS_DEBUG("unifie scans");
00270 for(int j = 0; j < config_.number_input_scans; j++)
00271 {
00272 for (unsigned int i = 0; i < vec_cloud.at(j).points.size(); i++)
00273 {
00274 const float &x = vec_cloud.at(j).points[i].x;
00275 const float &y = vec_cloud.at(j).points[i].y;
00276 const float &z = vec_cloud.at(j).points[i].z;
00277
00278 if ( std::isnan(x) || std::isnan(y) || std::isnan(z) )
00279 {
00280 ROS_DEBUG("rejected for nan in point(%f, %f, %f)\n", x, y, z);
00281 continue;
00282 }
00283 double angle = atan2(y, x);
00284 if (angle < unified_scan.angle_min || angle > unified_scan.angle_max)
00285 {
00286 ROS_DEBUG("rejected for angle %f not in range (%f, %f)\n", angle, unified_scan.angle_min, unified_scan.angle_max);
00287 continue;
00288 }
00289 int index = std::floor(0.5 + (angle - unified_scan.angle_min) / unified_scan.angle_increment);
00290 if(index<0 || index>=unified_scan.ranges.size()) continue;
00291
00292 double range_sq = y*y+x*x;
00293
00294 if( (unified_scan.ranges.at(index) == 0) || (sqrt(range_sq) <= unified_scan.ranges.at(index)) )
00295 {
00296
00297 unified_scan.ranges.at(index) = sqrt(range_sq);
00298
00299 unified_scan.intensities.at(index) = vec_cloud.at(j).channels.at(0).values.at(i);
00300 }
00301 }
00302 }
00303 }
00304
00305 return unified_scan;
00306 }
00307
00316 void scan_unifier_node::checkUnifieCondition()
00317 {
00318 bool all_scans_received = true;
00319 if(!vec_laser_struct_.empty())
00320 {
00321 int ind = 0;
00322 while(ind < config_.number_input_scans && all_scans_received)
00323 {
00324
00325
00326 all_scans_received = get_new_msg_received(ind);
00327 ind++;
00328 }
00329 }
00330
00331 if(all_scans_received)
00332 {
00333
00334 ROS_DEBUG("all_scans_received");
00335 sensor_msgs::LaserScan unified_scan = unifieLaserScans();
00336 ROS_DEBUG("now publish");
00337 topicPub_LaserUnified_.publish(unified_scan);
00338 for(int i=0; i < config_.number_input_scans; i++)
00339 {
00340 set_new_msg_received(false, i);
00341 }
00342 }
00343 }
00344
00345 int main(int argc, char** argv)
00346 {
00347 ROS_DEBUG("scan unifier: start scan unifier node");
00348 ros::init(argc, argv, "cob_scan_unifier_node");
00349
00350 scan_unifier_node my_scan_unifier_node;
00351
00352
00353 ros::Time start = ros::Time::now();
00354
00355 ros::Rate rate(my_scan_unifier_node.getLoopRate());
00356
00357
00358 while(my_scan_unifier_node.nh_.ok())
00359 {
00360
00361 my_scan_unifier_node.checkUnifieCondition();
00362
00363 ros::spinOnce();
00364 rate.sleep();
00365 }
00366
00367 return 0;
00368 }