merge_clouds.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2008, Willow Garage, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of the Willow Garage nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
34 
44 #include <ros/ros.h>
45 #include <sensor_msgs/PointCloud.h>
46 #include <tf/message_filter.h>
47 #include <tf/transform_listener.h>
48 
49 #include <boost/thread/mutex.hpp>
50 #include <boost/shared_ptr.hpp>
51 #include <boost/bind.hpp>
52 
54 
56 {
57 public:
58 
59  MergeClouds(void) :
60  sub1_(nh_, "cloud_in1", 1),
61  sub2_(nh_, "cloud_in1", 1)
62  {
63  cloudOut_ = nh_.advertise<sensor_msgs::PointCloud>("cloud_out", 1);
64  nh_.param<std::string>("~output_frame", output_frame_, std::string());
65  nh_.param<double>("~max_frequency", max_freq_, 0.0);
66  newCloud1_ = newCloud2_ = false;
67 
68  if (output_frame_.empty())
69  ROS_ERROR("No output frame specified for merging pointclouds");
70 
71  // make sure we don't publish too fast
72  if (max_freq_ > 1000.0 || max_freq_ < 0.0)
73  max_freq_ = 0.0;
74 
75  if (max_freq_ > 0.0)
76  {
77  timer_ = nh_.createTimer(ros::Duration(1.0/max_freq_), boost::bind(&MergeClouds::onTimer, this, _1));
78  haveTimer_ = true;
79  }
80  else
81  haveTimer_ = false;
82 
83  tf_filter1_.reset(new tf::MessageFilter<sensor_msgs::PointCloud>(sub1_, tf_, output_frame_, 1));
84  tf_filter2_.reset(new tf::MessageFilter<sensor_msgs::PointCloud>(sub2_, tf_, output_frame_, 1));
85 
86  tf_filter1_->registerCallback(boost::bind(&MergeClouds::receiveCloud1, this, _1));
87  tf_filter2_->registerCallback(boost::bind(&MergeClouds::receiveCloud2, this, _1));
88  }
89 
91  {
92 
93  }
94 
95 private:
96 
97  void onTimer(const ros::TimerEvent &e)
98  {
99  if (newCloud1_ && newCloud2_)
100  publishClouds();
101  }
102 
103  void publishClouds(void)
104  {
105  lock1_.lock();
106  lock2_.lock();
107 
108  newCloud1_ = false;
109  newCloud2_ = false;
110 
111  sensor_msgs::PointCloud out;
112  if (cloud1_.header.stamp > cloud2_.header.stamp)
113  out.header = cloud1_.header;
114  else
115  out.header = cloud2_.header;
116 
117  out.points.resize(cloud1_.points.size() + cloud2_.points.size());
118 
119  // copy points
120  std::copy(cloud1_.points.begin(), cloud1_.points.end(), out.points.begin());
121  std::copy(cloud2_.points.begin(), cloud2_.points.end(), out.points.begin() + cloud1_.points.size());
122 
123  // copy common channels
124  for (unsigned int i = 0 ; i < cloud1_.channels.size() ; ++i)
125  for (unsigned int j = 0 ; j < cloud2_.channels.size() ; ++j)
126  if (cloud1_.channels[i].name == cloud2_.channels[j].name)
127  {
128  ROS_ASSERT(cloud1_.channels[i].values.size() == cloud1_.points.size());
129  ROS_ASSERT(cloud2_.channels[j].values.size() == cloud2_.points.size());
130  unsigned int oc = out.channels.size();
131  out.channels.resize(oc + 1);
132  out.channels[oc].name = cloud1_.channels[i].name;
133  out.channels[oc].values.resize(cloud1_.channels[i].values.size() + cloud2_.channels[j].values.size());
134  std::copy(cloud1_.channels[i].values.begin(), cloud1_.channels[i].values.end(), out.channels[oc].values.begin());
135  std::copy(cloud2_.channels[j].values.begin(), cloud2_.channels[j].values.end(), out.channels[oc].values.begin() + cloud1_.channels[i].values.size());
136  break;
137  }
138 
139  lock1_.unlock();
140  lock2_.unlock();
141 
142  cloudOut_.publish(out);
143  }
144 
145  void receiveCloud1(const sensor_msgs::PointCloudConstPtr &cloud)
146  {
147  lock1_.lock();
148  processCloud(cloud, cloud1_);
149  lock1_.unlock();
150  newCloud1_ = true;
151  if (!haveTimer_ && newCloud2_)
152  publishClouds();
153  }
154 
155  void receiveCloud2(const sensor_msgs::PointCloudConstPtr &cloud)
156  {
157  lock2_.lock();
158  processCloud(cloud, cloud2_);
159  lock2_.unlock();
160  newCloud2_ = true;
161  if (!haveTimer_ && newCloud1_)
162  publishClouds();
163  }
164 
165  void processCloud(const sensor_msgs::PointCloudConstPtr &cloud, sensor_msgs::PointCloud &cloudOut)
166  {
167  if (output_frame_ != cloud->header.frame_id)
168  tf_.transformPointCloud(output_frame_, *cloud, cloudOut);
169  else
170  cloudOut = *cloud;
171  }
172 
175 
178 
180  double max_freq_;
181  std::string output_frame_;
182 
187 
190  sensor_msgs::PointCloud cloud1_;
191  sensor_msgs::PointCloud cloud2_;
192  boost::mutex lock1_;
193  boost::mutex lock2_;
194 
195 };
196 
197 
198 int main(int argc, char **argv)
199 {
200  ros::init(argc, argv, "merge_clouds", ros::init_options::AnonymousName);
201 
202  ROS_WARN("laser_assembler/merge_clouds is deprecated. You should instead be using 3dnav_pr2/merge_clouds");
203 
204  MergeClouds mc;
205  ros::spin();
206 
207  return 0;
208 }
~MergeClouds(void)
void publish(const boost::shared_ptr< M > &message) const
boost::mutex lock1_
sensor_msgs::PointCloud cloud2_
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
boost::shared_ptr< tf::MessageFilter< sensor_msgs::PointCloud > > tf_filter2_
#define ROS_WARN(...)
ROSCPP_DECL void spin(Spinner &spinner)
ros::NodeHandle nh_
void processCloud(const sensor_msgs::PointCloudConstPtr &cloud, sensor_msgs::PointCloud &cloudOut)
std::string output_frame_
ros::Publisher cloudOut_
void transformPointCloud(const std::string &target_frame, const sensor_msgs::PointCloud &pcin, sensor_msgs::PointCloud &pcout) const
bool param(const std::string &param_name, T &param_val, const T &default_val) const
Timer createTimer(Rate r, Handler h, Obj o, bool oneshot=false, bool autostart=true) const
void receiveCloud1(const sensor_msgs::PointCloudConstPtr &cloud)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
tf::TransformListener tf_
void receiveCloud2(const sensor_msgs::PointCloudConstPtr &cloud)
sensor_msgs::PointCloud cloud1_
int main(int argc, char **argv)
ros::Timer timer_
message_filters::Subscriber< sensor_msgs::PointCloud > sub2_
void onTimer(const ros::TimerEvent &e)
boost::shared_ptr< tf::MessageFilter< sensor_msgs::PointCloud > > tf_filter1_
double max_freq_
message_filters::Subscriber< sensor_msgs::PointCloud > sub1_
#define ROS_ASSERT(cond)
void publishClouds(void)
boost::mutex lock2_
#define ROS_ERROR(...)
MergeClouds(void)


laser_assembler
Author(s): Vijay Pradeep
autogenerated on Thu Jun 27 2019 19:56:21