laser_processor.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 
36 
37 #include <stdexcept>
38 
39 using namespace ros;
40 using namespace std;
41 using namespace laser_processor;
42 
43 Sample* Sample::Extract(int ind, const sensor_msgs::LaserScan& scan)
44 {
45  Sample* s = new Sample();
46 
47  s->index = ind;
48  s->range = scan.ranges[ind];
49  s->x = cos(scan.angle_min + ind * scan.angle_increment) * s->range;
50  s->y = sin(scan.angle_min + ind * scan.angle_increment) * s->range;
51  if (s->range > scan.range_min && s->range < scan.range_max)
52  return s;
53  else
54  {
55  delete s;
56  return NULL;
57  }
58 }
59 
60 void SampleSet::clear()
61 {
62  for (SampleSet::iterator i = begin();
63  i != end();
64  i++)
65  {
66  delete(*i);
67  }
68  set<Sample*, CompareSample>::clear();
69 }
70 
71 void SampleSet::appendToCloud(sensor_msgs::PointCloud& cloud, int r, int g, int b)
72 {
73  float color_val = 0;
74 
75  int rgb = (r << 16) | (g << 8) | b;
76  color_val = *(float*) & (rgb);
77 
78  for (iterator sample_iter = begin();
79  sample_iter != end();
80  sample_iter++)
81  {
82  geometry_msgs::Point32 point;
83  point.x = (*sample_iter)->x;
84  point.y = (*sample_iter)->y;
85  point.z = 0;
86 
87  cloud.points.push_back(point);
88 
89  if (cloud.channels[0].name == "rgb")
90  cloud.channels[0].values.push_back(color_val);
91  }
92 }
93 
94 tf::Point SampleSet::center()
95 {
96  float x_mean = 0.0;
97  float y_mean = 0.0;
98  for (iterator i = begin();
99  i != end();
100  i++)
101 
102  {
103  x_mean += ((*i)->x) / size();
104  y_mean += ((*i)->y) / size();
105  }
106 
107  return tf::Point(x_mean, y_mean, 0.0);
108 }
109 
110 
111 void ScanMask::addScan(sensor_msgs::LaserScan& scan)
112 {
113  if (!filled)
114  {
115  angle_min = scan.angle_min;
116  angle_max = scan.angle_max;
117  size = scan.ranges.size();
118  filled = true;
119  }
120  else if (angle_min != scan.angle_min ||
121  angle_max != scan.angle_max ||
122  size != scan.ranges.size())
123  {
124  throw std::runtime_error("laser_scan::ScanMask::addScan: inconsistantly sized scans added to mask");
125  }
126 
127  for (uint32_t i = 0; i < scan.ranges.size(); i++)
128  {
129  Sample* s = Sample::Extract(i, scan);
130 
131  if (s != NULL)
132  {
133  SampleSet::iterator m = mask_.find(s);
134 
135  if (m != mask_.end())
136  {
137  if ((*m)->range > s->range)
138  {
139  delete(*m);
140  mask_.erase(m);
141  mask_.insert(s);
142  }
143  else
144  {
145  delete s;
146  }
147  }
148  else
149  {
150  mask_.insert(s);
151  }
152  }
153  }
154 }
155 
156 
157 bool ScanMask::hasSample(Sample* s, float thresh)
158 {
159  if (s != NULL)
160  {
161  SampleSet::iterator m = mask_.find(s);
162  if (m != mask_.end())
163  if (((*m)->range - thresh) < s->range)
164  return true;
165  }
166  return false;
167 }
168 
169 
170 
171 ScanProcessor::ScanProcessor(const sensor_msgs::LaserScan& scan, ScanMask& mask_, float mask_threshold)
172 {
173  scan_ = scan;
174 
175  SampleSet* cluster = new SampleSet;
176 
177  for (uint32_t i = 0; i < scan.ranges.size(); i++)
178  {
179  Sample* s = Sample::Extract(i, scan);
180 
181  if (s != NULL)
182  {
183  if (!mask_.hasSample(s, mask_threshold))
184  {
185  cluster->insert(s);
186  }
187  else
188  {
189  delete s;
190  }
191  }
192  }
193 
194  clusters_.push_back(cluster);
195 
196 }
197 
198 ScanProcessor::~ScanProcessor()
199 {
200  for (list<SampleSet*>::iterator c = clusters_.begin();
201  c != clusters_.end();
202  c++)
203  delete(*c);
204 }
205 
206 void
207 ScanProcessor::removeLessThan(uint32_t num)
208 {
209  list<SampleSet*>::iterator c_iter = clusters_.begin();
210  while (c_iter != clusters_.end())
211  {
212  if ((*c_iter)->size() < num)
213  {
214  delete(*c_iter);
215  clusters_.erase(c_iter++);
216  }
217  else
218  {
219  ++c_iter;
220  }
221  }
222 }
223 
224 
225 void
226 ScanProcessor::splitConnected(float thresh)
227 {
228  list<SampleSet*> tmp_clusters;
229 
230  list<SampleSet*>::iterator c_iter = clusters_.begin();
231 
232  // For each cluster
233  while (c_iter != clusters_.end())
234  {
235  // Go through the entire list
236  while ((*c_iter)->size() > 0)
237  {
238  // Take the first element
239  SampleSet::iterator s_first = (*c_iter)->begin();
240 
241  // Start a new queue
242  list<Sample*> sample_queue;
243  sample_queue.push_back(*s_first);
244 
245  (*c_iter)->erase(s_first);
246 
247  // Grow until we get to the end of the queue
248  list<Sample*>::iterator s_q = sample_queue.begin();
249  while (s_q != sample_queue.end())
250  {
251  int expand = (int)(asin(thresh / (*s_q)->range) / std::abs(scan_.angle_increment));
252 
253  SampleSet::iterator s_rest = (*c_iter)->begin();
254 
255  while ((s_rest != (*c_iter)->end() &&
256  (*s_rest)->index < (*s_q)->index + expand))
257  {
258  if ((*s_rest)->range - (*s_q)->range > thresh)
259  {
260  break;
261  }
262  else if (sqrt(pow((*s_q)->x - (*s_rest)->x, 2.0f) + pow((*s_q)->y - (*s_rest)->y, 2.0f)) < thresh)
263  {
264  sample_queue.push_back(*s_rest);
265  (*c_iter)->erase(s_rest++);
266  break;
267  }
268  else
269  {
270  ++s_rest;
271  }
272  }
273  s_q++;
274  }
275 
276  // Move all the samples into the new cluster
277  SampleSet* c = new SampleSet;
278  for (s_q = sample_queue.begin(); s_q != sample_queue.end(); s_q++)
279  c->insert(*s_q);
280 
281  // Store the temporary clusters
282  tmp_clusters.push_back(c);
283  }
284 
285  //Now that c_iter is empty, we can delete
286  delete(*c_iter);
287 
288  //And remove from the map
289  clusters_.erase(c_iter++);
290  }
291 
292  clusters_.insert(clusters_.begin(), tmp_clusters.begin(), tmp_clusters.end());
293 }
XmlRpcServer s
tf::Vector3 Point
A namespace containing the laser processor helper classes.
An ordered set of Samples.
A struct representing a single sample from the laser.
bool hasSample(Sample *s, float thresh)
A mask for filtering out Samples based on range.


leg_detector
Author(s): Caroline Pantofaru
autogenerated on Fri Jun 7 2019 22:07:52