calc_leg_features.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 "opencv/cxcore.h"
38 #include "opencv/cv.h"
39 
40 using namespace laser_processor;
41 using namespace std;
42 
43 vector<float> calcLegFeatures(SampleSet* cluster, const sensor_msgs::LaserScan& scan)
44 {
45 
46  vector<float> features;
47 
48  // Number of points
49  int num_points = cluster->size();
50  // features.push_back(num_points);
51 
52  // Compute mean and median points for future use
53  float x_mean = 0.0;
54  float y_mean = 0.0;
55  vector<float> x_median_set;
56  vector<float> y_median_set;
57  for (SampleSet::iterator i = cluster->begin();
58  i != cluster->end();
59  i++)
60 
61  {
62  x_mean += ((*i)->x) / num_points;
63  y_mean += ((*i)->y) / num_points;
64  x_median_set.push_back((*i)->x);
65  y_median_set.push_back((*i)->y);
66  }
67 
68  std::sort(x_median_set.begin(), x_median_set.end());
69  std::sort(y_median_set.begin(), y_median_set.end());
70 
71  float x_median = 0.5 * (*(x_median_set.begin() + (num_points - 1) / 2) + * (x_median_set.begin() + num_points / 2));
72  float y_median = 0.5 * (*(y_median_set.begin() + (num_points - 1) / 2) + * (y_median_set.begin() + num_points / 2));
73 
74  //Compute std and avg diff from median
75 
76  double sum_std_diff = 0.0;
77  double sum_med_diff = 0.0;
78 
79 
80  for (SampleSet::iterator i = cluster->begin();
81  i != cluster->end();
82  i++)
83 
84  {
85  sum_std_diff += pow((*i)->x - x_mean, 2) + pow((*i)->y - y_mean, 2);
86  sum_med_diff += sqrt(pow((*i)->x - x_median, 2) + pow((*i)->y - y_median, 2));
87  }
88 
89  float std = sqrt(1.0 / (num_points - 1.0) * sum_std_diff);
90  float avg_median_dev = sum_med_diff / num_points;
91 
92  features.push_back(std);
93  features.push_back(avg_median_dev);
94 
95 
96  // Take first at last
97  SampleSet::iterator first = cluster->begin();
98  SampleSet::iterator last = cluster->end();
99  last--;
100 
101  // Compute Jump distance
102  int prev_ind = (*first)->index - 1;
103  int next_ind = (*last)->index + 1;
104 
105  float prev_jump = 0;
106  float next_jump = 0;
107 
108  if (prev_ind >= 0)
109  {
110  Sample* prev = Sample::Extract(prev_ind, scan);
111  if (prev)
112  {
113  prev_jump = sqrt(pow((*first)->x - prev->x, 2) + pow((*first)->y - prev->y, 2));
114  delete prev;
115  }
116 
117  }
118 
119  if (next_ind < (int)scan.ranges.size())
120  {
121  Sample* next = Sample::Extract(next_ind, scan);
122  if (next)
123  {
124  next_jump = sqrt(pow((*last)->x - next->x, 2) + pow((*last)->y - next->y, 2));
125  delete next;
126  }
127  }
128 
129  features.push_back(prev_jump);
130  features.push_back(next_jump);
131 
132  // Compute Width
133  float width = sqrt(pow((*first)->x - (*last)->x, 2) + pow((*first)->y - (*last)->y, 2));
134  features.push_back(width);
135 
136  // Compute Linearity
137 
138  CvMat* points = cvCreateMat(num_points, 2, CV_64FC1);
139  {
140  int j = 0;
141  for (SampleSet::iterator i = cluster->begin();
142  i != cluster->end();
143  i++)
144  {
145  cvmSet(points, j, 0, (*i)->x - x_mean);
146  cvmSet(points, j, 1, (*i)->y - y_mean);
147  j++;
148  }
149  }
150 
151  CvMat* W = cvCreateMat(2, 2, CV_64FC1);
152  CvMat* U = cvCreateMat(num_points, 2, CV_64FC1);
153  CvMat* V = cvCreateMat(2, 2, CV_64FC1);
154  cvSVD(points, W, U, V);
155 
156  CvMat* rot_points = cvCreateMat(num_points, 2, CV_64FC1);
157  cvMatMul(U, W, rot_points);
158 
159  float linearity = 0.0;
160  for (int i = 0; i < num_points; i++)
161  {
162  linearity += pow(cvmGet(rot_points, i, 1), 2);
163  }
164 
165  cvReleaseMat(&points);
166  points = 0;
167  cvReleaseMat(&W);
168  W = 0;
169  cvReleaseMat(&U);
170  U = 0;
171  cvReleaseMat(&V);
172  V = 0;
173  cvReleaseMat(&rot_points);
174  rot_points = 0;
175 
176  features.push_back(linearity);
177 
178  // Compute Circularity
179  CvMat* A = cvCreateMat(num_points, 3, CV_64FC1);
180  CvMat* B = cvCreateMat(num_points, 1, CV_64FC1);
181  {
182  int j = 0;
183  for (SampleSet::iterator i = cluster->begin();
184  i != cluster->end();
185  i++)
186  {
187  float x = (*i)->x;
188  float y = (*i)->y;
189 
190  cvmSet(A, j, 0, -2.0 * x);
191  cvmSet(A, j, 1, -2.0 * y);
192  cvmSet(A, j, 2, 1);
193 
194  cvmSet(B, j, 0, -pow(x, 2) - pow(y, 2));
195  j++;
196  }
197  }
198  CvMat* sol = cvCreateMat(3, 1, CV_64FC1);
199 
200  cvSolve(A, B, sol, CV_SVD);
201 
202  float xc = cvmGet(sol, 0, 0);
203  float yc = cvmGet(sol, 1, 0);
204  float rc = sqrt(pow(xc, 2) + pow(yc, 2) - cvmGet(sol, 2, 0));
205 
206  cvReleaseMat(&A);
207  A = 0;
208  cvReleaseMat(&B);
209  B = 0;
210  cvReleaseMat(&sol);
211  sol = 0;
212 
213  float circularity = 0.0;
214  for (SampleSet::iterator i = cluster->begin();
215  i != cluster->end();
216  i++)
217  {
218  circularity += pow(rc - sqrt(pow(xc - (*i)->x, 2) + pow(yc - (*i)->y, 2)), 2);
219  }
220 
221  features.push_back(circularity);
222 
223  // Radius
224  float radius = rc;
225 
226  features.push_back(radius);
227 
228  //Curvature:
229  float mean_curvature = 0.0;
230 
231  //Boundary length:
232  float boundary_length = 0.0;
233  float last_boundary_seg = 0.0;
234 
235  float boundary_regularity = 0.0;
236  double sum_boundary_reg_sq = 0.0;
237 
238  // Mean angular difference
239  SampleSet::iterator left = cluster->begin();
240  left++;
241  left++;
242  SampleSet::iterator mid = cluster->begin();
243  mid++;
244  SampleSet::iterator right = cluster->begin();
245 
246  float ang_diff = 0.0;
247 
248  while (left != cluster->end())
249  {
250  float mlx = (*left)->x - (*mid)->x;
251  float mly = (*left)->y - (*mid)->y;
252  float L_ml = sqrt(mlx * mlx + mly * mly);
253 
254  float mrx = (*right)->x - (*mid)->x;
255  float mry = (*right)->y - (*mid)->y;
256  float L_mr = sqrt(mrx * mrx + mry * mry);
257 
258  float lrx = (*left)->x - (*right)->x;
259  float lry = (*left)->y - (*right)->y;
260  float L_lr = sqrt(lrx * lrx + lry * lry);
261 
262  boundary_length += L_mr;
263  sum_boundary_reg_sq += L_mr * L_mr;
264  last_boundary_seg = L_ml;
265 
266  float A = (mlx * mrx + mly * mry) / pow(L_mr, 2);
267  float B = (mlx * mry - mly * mrx) / pow(L_mr, 2);
268 
269  float th = atan2(B, A);
270 
271  if (th < 0)
272  th += 2 * M_PI;
273 
274  ang_diff += th / num_points;
275 
276  float s = 0.5 * (L_ml + L_mr + L_lr);
277  float area = sqrt(s * (s - L_ml) * (s - L_mr) * (s - L_lr));
278 
279  if (th > 0)
280  mean_curvature += 4 * (area) / (L_ml * L_mr * L_lr * num_points);
281  else
282  mean_curvature -= 4 * (area) / (L_ml * L_mr * L_lr * num_points);
283 
284  left++;
285  mid++;
286  right++;
287  }
288 
289  boundary_length += last_boundary_seg;
290  sum_boundary_reg_sq += last_boundary_seg * last_boundary_seg;
291 
292  boundary_regularity = sqrt((sum_boundary_reg_sq - pow(boundary_length, 2) / num_points) / (num_points - 1));
293 
294  features.push_back(boundary_length);
295  features.push_back(ang_diff);
296  features.push_back(mean_curvature);
297 
298  features.push_back(boundary_regularity);
299 
300 
301  // Mean angular difference
302  first = cluster->begin();
303  mid = cluster->begin();
304  mid++;
305  last = cluster->end();
306  last--;
307 
308  double sum_iav = 0.0;
309  double sum_iav_sq = 0.0;
310 
311  while (mid != last)
312  {
313  float mlx = (*first)->x - (*mid)->x;
314  float mly = (*first)->y - (*mid)->y;
315  //float L_ml = sqrt(mlx*mlx + mly*mly);
316 
317  float mrx = (*last)->x - (*mid)->x;
318  float mry = (*last)->y - (*mid)->y;
319  float L_mr = sqrt(mrx * mrx + mry * mry);
320 
321  //float lrx = (*first)->x - (*last)->x;
322  //float lry = (*first)->y - (*last)->y;
323  //float L_lr = sqrt(lrx*lrx + lry*lry);
324 
325  float A = (mlx * mrx + mly * mry) / pow(L_mr, 2);
326  float B = (mlx * mry - mly * mrx) / pow(L_mr, 2);
327 
328  float th = atan2(B, A);
329 
330  if (th < 0)
331  th += 2 * M_PI;
332 
333  sum_iav += th;
334  sum_iav_sq += th * th;
335 
336  mid++;
337  }
338 
339  float iav = sum_iav / num_points;
340  float std_iav = sqrt((sum_iav_sq - pow(sum_iav, 2) / num_points) / (num_points - 1));
341 
342  features.push_back(iav);
343  features.push_back(std_iav);
344 
345  return features;
346 }
XmlRpcServer s
TFSIMD_FORCE_INLINE const tfScalar & y() const
vector< float > calcLegFeatures(SampleSet *cluster, const sensor_msgs::LaserScan &scan)
A namespace containing the laser processor helper classes.
An ordered set of Samples.
x
A struct representing a single sample from the laser.
static Sample * Extract(int ind, const sensor_msgs::LaserScan &scan)


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