40 #include "sensor_msgs/PointCloud.h" 46 #include "laser_assembler/AssembleScans.h" 48 #include "boost/thread.hpp" 102 virtual void ConvertToCloud(
const std::string& fixed_frame_id,
const T& scan_in, sensor_msgs::PointCloud& cloud_out) = 0 ;
122 bool buildCloud(AssembleScans::Request& req, AssembleScans::Response& resp) ;
150 double tf_cache_time_secs ;
152 if (tf_cache_time_secs < 0)
153 ROS_ERROR(
"Parameter tf_cache_time_secs<0 (%f)", tf_cache_time_secs) ;
156 ROS_INFO(
"TF Cache Time: %f Seconds", tf_cache_time_secs) ;
159 const int default_max_scans = 400 ;
162 if (tmp_max_scans < 0)
164 ROS_ERROR(
"Parameter max_scans<0 (%i)", tmp_max_scans) ;
165 tmp_max_scans = default_max_scans ;
175 ROS_ERROR(
"Need to set parameter fixed_frame") ;
178 int tmp_downsample_factor ;
180 if (tmp_downsample_factor < 1)
182 ROS_ERROR(
"Parameter downsample_factor<1: %i", tmp_downsample_factor) ;
183 tmp_downsample_factor = 1 ;
206 ROS_INFO(
"Starting to listen on the input stream") ;
208 ROS_ERROR(
"assembler::start() was called twice!. This is bad, and could leak memory") ;
230 const T scan = *scan_ptr ;
232 sensor_msgs::PointCloud cur_cloud ;
241 ROS_WARN(
"Transform Exception %s", ex.what()) ;
275 unsigned int start_index = i ;
277 unsigned int req_pts = 0 ;
285 unsigned int past_end_index = i ;
287 if (start_index == past_end_index)
290 resp.cloud.header.stamp = req.end ;
291 resp.cloud.points.resize(0) ;
292 resp.cloud.channels.resize(0) ;
298 resp.cloud.points.resize( req_pts ) ;
299 const unsigned int num_channels =
scan_hist_[start_index].channels.size() ;
300 resp.cloud.channels.resize(num_channels) ;
301 for (i = 0; i<num_channels; i++)
303 resp.cloud.channels[i].name =
scan_hist_[start_index].channels[i].name ;
304 resp.cloud.channels[i].values.resize(req_pts) ;
308 unsigned int cloud_count = 0 ;
313 resp.cloud.points[cloud_count].x =
scan_hist_[i].points[j].x ;
314 resp.cloud.points[cloud_count].y =
scan_hist_[i].points[j].y ;
315 resp.cloud.points[cloud_count].z =
scan_hist_[i].points[j].z ;
316 for (
unsigned int k=0; k<num_channels; k++)
317 resp.cloud.channels[k].values[cloud_count] =
scan_hist_[i].channels[k].values[j] ;
321 resp.cloud.header.stamp =
scan_hist_[i].header.stamp;
326 ROS_DEBUG(
"Point Cloud Results: Aggregated from index %u->%u. BufferSize: %lu. Points in cloud: %lu", start_index, past_end_index,
scan_hist_.size(), resp.cloud.points.size()) ;
virtual unsigned int GetPointsInScan(const T &scan)=0
Returns the number of points in the current scan.
unsigned int total_pts_
The number points currently in the scan history.
void scansCallback(const boost::shared_ptr< const T > &scan_ptr)
Callback function for every time we receive a new scan.
Maintains a history of point clouds and generates an aggregate point cloud upon request.
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
virtual void ConvertToCloud(const std::string &fixed_frame_id, const T &scan_in, sensor_msgs::PointCloud &cloud_out)=0
Converts the current scan into a cloud in the specified fixed frame.
std::deque< sensor_msgs::PointCloud > scan_hist_
Stores history of scans.
ros::NodeHandle private_ns_
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
unsigned int max_scans_
The max number of scans to store in the scan history.
boost::mutex scan_hist_mutex_
void subscribe(ros::NodeHandle &nh, const std::string &topic, uint32_t queue_size, const ros::TransportHints &transport_hints=ros::TransportHints(), ros::CallbackQueueInterface *callback_queue=0)
bool buildCloud(AssembleScans::Request &req, AssembleScans::Response &resp)
Service Callback function called whenever we need to build a cloud.
message_filters::Subscriber< T > scan_sub_
ros::ServiceServer cloud_srv_server_
std::string fixed_frame_
The frame to transform data into upon receipt.
unsigned int downsample_factor_
Specify how much to downsample the data. A value of 1 preserves all the data. 3 would keep 1/3 of the...
double tf_tolerance_secs_
How long we should wait before processing the input data. Very useful for laser scans.
void setTolerance(const ros::Duration &tolerance)
message_filters::Connection tf_filter_connection_
tf::MessageFilter< T > * tf_filter_
void start()
Tells the assembler to start listening to input data It is possible that a derived class needs to ini...
tf::TransformListener * tf_
Connection registerCallback(const C &callback)