6 #include <pcl/conversions.h> 7 #include <pcl/point_cloud.h> 8 #include <pcl/point_types.h> 9 #include <pcl/io/pcd_io.h> 10 #include <sensor_msgs/PointCloud.h> 11 #include <sensor_msgs/PointCloud2.h> 13 #include "sensor_msgs/LaserScan.h" 15 #include <Eigen/Dense> 16 #include <dynamic_reconfigure/server.h> 17 #include <ira_laser_tools/laserscan_multi_mergerConfig.h> 27 void scanCallback(
const sensor_msgs::LaserScan::ConstPtr& scan, std::string topic);
28 void pointcloud_to_laserscan(Eigen::MatrixXf points, pcl::PCLPointCloud2 *merged_cloud);
29 void reconfigureCallback(laserscan_multi_mergerConfig &config, uint32_t level);
44 void laserscan_topic_parser();
62 this->angle_min = config.angle_min;
63 this->angle_max = config.angle_max;
64 this->angle_increment = config.angle_increment;
65 this->time_increment = config.time_increment;
66 this->scan_time = config.scan_time;
67 this->range_min = config.range_min;
68 this->range_max = config.range_max;
77 istringstream iss(laserscan_topics);
78 vector<string> tokens;
79 copy(istream_iterator<string>(iss), istream_iterator<string>(), back_inserter<vector<string> >(tokens));
81 vector<string> tmp_input_topics;
83 for(
int i=0;i<tokens.size();++i)
85 for(
int j=0;j<topics.size();++j)
87 if( (tokens[i].compare(topics[j].name) == 0) && (topics[j].datatype.compare(
"sensor_msgs/LaserScan") == 0) )
89 tmp_input_topics.push_back(topics[j].name);
94 sort(tmp_input_topics.begin(),tmp_input_topics.end());
95 std::vector<string>::iterator last = std::unique(tmp_input_topics.begin(), tmp_input_topics.end());
96 tmp_input_topics.erase(last, tmp_input_topics.end());
100 if( (tmp_input_topics.size() != input_topics.size()) || !equal(tmp_input_topics.begin(),tmp_input_topics.end(),input_topics.begin()))
104 for(
int i=0; i<scan_subscribers.size(); ++i)
105 scan_subscribers[i].shutdown();
107 input_topics = tmp_input_topics;
108 if(input_topics.size() > 0)
110 scan_subscribers.resize(input_topics.size());
111 clouds_modified.resize(input_topics.size());
112 clouds.resize(input_topics.size());
113 ROS_INFO(
"Subscribing to topics\t%ld", scan_subscribers.size());
114 for(
int i=0; i<input_topics.size(); ++i)
116 scan_subscribers[i] = node_.subscribe<sensor_msgs::LaserScan> (input_topics[i].c_str(), 1, boost::bind(&
LaserscanMerger::scanCallback,
this, _1, input_topics[i]));
117 clouds_modified[i] =
false;
118 cout << input_topics[i] <<
" ";
122 ROS_INFO(
"Not subscribed to any topic.");
130 nh.
getParam(
"destination_frame", destination_frame);
131 nh.
getParam(
"cloud_destination_topic", cloud_destination_topic);
132 nh.
getParam(
"scan_destination_topic", scan_destination_topic);
133 nh.
getParam(
"laserscan_topics", laserscan_topics);
135 nh.
param(
"angle_min", angle_min, -2.36);
136 nh.
param(
"angle_max", angle_max, 2.36);
137 nh.
param(
"angle_increment", angle_increment, 0.0058);
138 nh.
param(
"scan_time", scan_time, 0.0333333);
139 nh.
param(
"range_min", range_min, 0.45);
140 nh.
param(
"range_max", range_max, 25.0);
142 this->laserscan_topic_parser();
144 point_cloud_publisher_ = node_.advertise<sensor_msgs::PointCloud2> (cloud_destination_topic.c_str(), 1,
false);
145 laser_scan_publisher_ = node_.advertise<sensor_msgs::LaserScan> (scan_destination_topic.c_str(), 1,
false);
151 sensor_msgs::PointCloud tmpCloud1,tmpCloud2;
152 sensor_msgs::PointCloud2 tmpCloud3;
155 tfListener_.waitForTransform(scan->header.frame_id.c_str(), destination_frame.c_str(), scan->header.stamp,
ros::Duration(1));
159 tfListener_.transformPointCloud(destination_frame.c_str(), tmpCloud1, tmpCloud2);
162 for(
int i=0; i<input_topics.size(); ++i)
164 if(topic.compare(input_topics[i]) == 0)
168 clouds_modified[i] =
true;
174 for(
int i=0; i<clouds_modified.size(); ++i)
175 if(clouds_modified[i])
179 if(totalClouds == clouds_modified.size())
181 pcl::PCLPointCloud2 merged_cloud = clouds[0];
182 clouds_modified[0] =
false;
184 for(
int i=1; i<clouds_modified.size(); ++i)
187 clouds_modified[i] =
false;
190 point_cloud_publisher_.publish(merged_cloud);
192 Eigen::MatrixXf points;
193 getPointCloudAsEigen(merged_cloud,points);
195 pointcloud_to_laserscan(points, &merged_cloud);
201 sensor_msgs::LaserScanPtr output(
new sensor_msgs::LaserScan());
203 output->header.frame_id = destination_frame.c_str();
205 output->angle_min = this->angle_min;
206 output->angle_max = this->angle_max;
207 output->angle_increment = this->angle_increment;
208 output->time_increment = this->time_increment;
209 output->scan_time = this->scan_time;
210 output->range_min = this->range_min;
211 output->range_max = this->range_max;
213 uint32_t ranges_size = std::ceil((output->angle_max - output->angle_min) / output->angle_increment);
214 output->ranges.assign(ranges_size, output->range_max + 1.0);
216 for(
int i=0; i<points.cols(); i++)
218 const float &
x = points(0,i);
219 const float &
y = points(1,i);
220 const float &
z = points(2,i);
222 if ( std::isnan(x) || std::isnan(y) || std::isnan(z) )
224 ROS_DEBUG(
"rejected for nan in point(%f, %f, %f)\n", x, y, z);
228 double range_sq = y*y+x*x;
229 double range_min_sq_ = output->range_min * output->range_min;
230 if (range_sq < range_min_sq_) {
231 ROS_DEBUG(
"rejected for range %f below minimum value %f. Point: (%f, %f, %f)", range_sq, range_min_sq_, x, y, z);
235 double angle = atan2(y, x);
236 if (angle < output->angle_min || angle > output->angle_max)
238 ROS_DEBUG(
"rejected for angle %f not in range (%f, %f)\n", angle, output->angle_min, output->angle_max);
241 int index = (angle - output->angle_min) / output->angle_increment;
244 if (output->ranges[index] * output->ranges[index] > range_sq)
245 output->ranges[index] = sqrt(range_sq);
248 laser_scan_publisher_.publish(output);
251 int main(
int argc,
char** argv)
253 ros::init(argc, argv,
"laser_multi_merger");
257 dynamic_reconfigure::Server<laserscan_multi_mergerConfig> server;
258 dynamic_reconfigure::Server<laserscan_multi_mergerConfig>::CallbackType
f;
261 server.setCallback(f);
vector< bool > clouds_modified
tf::TransformListener tfListener_
void laserscan_topic_parser()
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
laser_geometry::LaserProjection projector_
ROSCPP_DECL bool getTopics(V_TopicInfo &topics)
vector< ros::Subscriber > scan_subscribers
std::vector< TopicInfo > V_TopicInfo
TFSIMD_FORCE_INLINE const tfScalar & y() const
TFSIMD_FORCE_INLINE tfScalar angle(const Quaternion &q1, const Quaternion &q2)
ROSCPP_DECL void spin(Spinner &spinner)
string cloud_destination_topic
void fromPCL(const pcl::uint64_t &pcl_stamp, ros::Time &stamp)
int main(int argc, char **argv)
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
TFSIMD_FORCE_INLINE const tfScalar & x() const
vector< string > input_topics
TFSIMD_FORCE_INLINE const tfScalar & z() const
bool concatenatePointCloud(const sensor_msgs::PointCloud2 &cloud1, const sensor_msgs::PointCloud2 &cloud2, sensor_msgs::PointCloud2 &cloud_out)
void reconfigureCallback(laserscan_multi_mergerConfig &config, uint32_t level)
static bool convertPointCloudToPointCloud2(const sensor_msgs::PointCloud &input, sensor_msgs::PointCloud2 &output)
bool getParam(const std::string &key, std::string &s) const
void scanCallback(const sensor_msgs::LaserScan::ConstPtr &scan, std::string topic)
string scan_destination_topic
void pointcloud_to_laserscan(Eigen::MatrixXf points, pcl::PCLPointCloud2 *merged_cloud)
ros::Publisher point_cloud_publisher_
ros::Publisher laser_scan_publisher_
vector< pcl::PCLPointCloud2 > clouds
void toPCL(const ros::Time &stamp, pcl::uint64_t &pcl_stamp)