scan_unifier_node.cpp
Go to the documentation of this file.
00001 
00059 #include <scan_unifier_node.h>
00060 
00061 // constructor
00062 scan_unifier_node::scan_unifier_node()
00063 {
00064   ROS_DEBUG("init laser unification");
00065   // create node handles
00066   nh_ = ros::NodeHandle();
00067   pnh_ = ros::NodeHandle("~");
00068 
00069   // publisher
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 // destructor
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     // now unifie all Scans
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         //ROS_INFO("Point %f %f %f", x, y, z);
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);// + M_PI/2;
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         //printf ("index xyz( %f %f %f) angle %f index %d range %f\n", x, y, z, angle, index, sqrt(range_sq));
00294         if( (unified_scan.ranges.at(index) == 0) || (sqrt(range_sq) <= unified_scan.ranges.at(index)) )
00295         {
00296           // use the nearest reflection point of all scans for unified scan
00297           unified_scan.ranges.at(index) = sqrt(range_sq);
00298           // get respective intensity from point cloud intensity-channel (index 0)
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       // if one scan-struct did not receive a new msg all_scans_received is set to false and we do nothing
00325       //all_scans_received = vec_laser_struct_.at(ind).new_msg_received;
00326       all_scans_received = get_new_msg_received(ind);
00327       ind++;
00328     }
00329   }
00330 
00331   if(all_scans_received)
00332   {
00333     // all scan-structs received a new msg so now unifie all of them
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   // store initialization time of the node 
00353   ros::Time start = ros::Time::now();
00354 
00355   ros::Rate rate(my_scan_unifier_node.getLoopRate());
00356 
00357   // actual calculation step with given frequency
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 }


cob_scan_unifier
Author(s): Florian Mirus
autogenerated on Wed Sep 2 2015 01:39:22