laser_data_bbox.c
Go to the documentation of this file.
1 /* This algorithm was created by Cyrill Stachniss
2  http://www.informatik.uni-freiburg.de/~stachnis/ */
3 #include "laser_data_drawing.h"
4 #include "math_utils.h"
5 #include "logging.h"
6 
7 // the 2d-point structure for the input
8 typedef struct {
9  double x;
10  double y;
11 } BB_Point;
12 
13 // computes the area of minimal bounding box for a set of 2d-points
14 double getBoundingBoxArea(BB_Point* p, int nOfPoints);
15 
16 // computes the minimal bounding box for a set of 2d-points
17 // ul = upper left point, ll = lower left point,
18 // ur = upper right point, ul = upper left point
19 int getBoundingBox(BB_Point* p, int nOfPoints,
20  double ul[2], double ur[2], double ll[2], double lr[2]);
21 
22 struct bbfind_imp {
23  int num;
24 
25  int buf_size;
27 };
28 
29 /* Initialize structure */
30 bbfind * bbfind_new(void);
31 
32 /* -------------------------------------- */
33 
35  bbfind * bbf = malloc(sizeof(bbfind));
36  bbf->buf_size = 1000;
37  bbf->buf = malloc(sizeof(BB_Point)*bbf->buf_size);
38  bbf->num = 0;
39  return bbf;
40 }
41 
42 int bbfind_add_point(bbfind*bbf, double point[2]) {
43  return bbfind_add_point2(bbf, point[0], point[1]);
44 }
45 
46 int bbfind_add_point2(bbfind*bbf, double x, double y) {
47  if(bbf->num > bbf->buf_size - 2) {
48  bbf->buf_size *= 2;
49  if(! (bbf->buf = (BB_Point*) realloc(bbf->buf, sizeof(BB_Point)*bbf->buf_size)) ) {
50  sm_error("Cannot allocate (size=%d)\n", bbf->buf_size);
51  return 0;
52  }
53  }
54  bbf->buf[bbf->num].x = x;
55  bbf->buf[bbf->num].y = y;
56  bbf->num++;
57  return 1;
58 }
59 
61  double ul[2], double ur[2], double ll[2], double lr[2]) {
62 
63  ll[0] = obbox->pose[0];
64  ll[1] = obbox->pose[1];
65  lr[0] = obbox->pose[0] + obbox->size[0] * cos(obbox->pose[2]);
66  lr[1] = obbox->pose[1] + obbox->size[0] * sin(obbox->pose[2]);
67  ul[0] = obbox->pose[0] + obbox->size[1] * cos(obbox->pose[2] + M_PI/2);
68  ul[1] = obbox->pose[1] + obbox->size[1] * sin(obbox->pose[2] + M_PI/2);
69  ur[0] = ul[0] + obbox->size[0] * cos(obbox->pose[2]);
70  ur[1] = ul[1] + obbox->size[0] * sin(obbox->pose[2]);
71 
72 }
73 
74 int bbfind_add_bbox(bbfind*bbf, const BB2 bbox) {
75  double ul[2], ur[2], ll[2], lr[2];
76  oriented_bbox_compute_corners(bbox, ul, ur, ll, lr);
77  return
78  bbfind_add_point(bbf, ul) &&
79  bbfind_add_point(bbf, ur) &&
80  bbfind_add_point(bbf, ll) &&
81  bbfind_add_point(bbf, lr);
82 }
83 
84 
85 int bbfind_compute(bbfind*bbf, BB2 bbox) {
86  double ul[2], ur[2], ll[2], lr[2];
87 
88  if(1) {
89  if(!getBoundingBox(bbf->buf, bbf->num, ul, ur, ll, lr)) {
90  sm_error("Could not compute bounding box.\n");
91  return 0;
92  }
93  bbox->pose[0] = ll[0];
94  bbox->pose[1] = ll[1];
95  bbox->pose[2] = atan2(lr[1]-ll[1], lr[0]-ll[0]);
96  bbox->size[0] = distance_d(lr, ll);
97  bbox->size[1] = distance_d(ll, ul);
98  } else {
99  double bb_min[2] = {bbf->buf[0].x,bbf->buf[0].y},
100  bb_max[2] = {bbf->buf[0].x,bbf->buf[0].y};
101  int i; for(i=0;i<bbf->num; i++) {
102  bb_min[0] = GSL_MIN(bb_min[0], bbf->buf[i].x);
103  bb_min[1] = GSL_MIN(bb_min[1], bbf->buf[i].y);
104  bb_max[0] = GSL_MAX(bb_max[0], bbf->buf[i].x);
105  bb_max[1] = GSL_MAX(bb_max[1], bbf->buf[i].y);
106  }
107  bbox->pose[0] = bb_min[0];
108  bbox->pose[1] = bb_min[1];
109  bbox->pose[2] = 0;
110  bbox->size[0] = bb_max[0] - bb_min[0];
111  bbox->size[1] = bb_max[1] - bb_min[1];
112  }
113  return 1;
114 }
115 
116 void bbfind_free(bbfind* bbf) {
117  free(bbf->buf);
118  free(bbf);
119 }
120 
121 void ld_get_oriented_bbox(LDP ld, double horizon, oriented_bbox*obbox) {
122  bbfind * bbf = bbfind_new();
123  int i; for(i=0;i<ld->nrays;i++) {
124  if(!ld->valid[i]) continue;
125  if(ld->readings[i]>horizon) continue;
126 
127  double p0[2] = {
128  cos(ld->theta[i]) * ld->readings[i],
129  sin(ld->theta[i]) * ld->readings[i]
130  };
131 
132  bbfind_add_point(bbf, p0);
133  }
134  bbfind_compute(bbf, obbox);
135  bbfind_free(bbf);
136 }
137 
138 // computes the area of minimal bounding box for a set of 2d-points
139 double getBoundingBoxArea(BB_Point* p, int nOfPoints) {
140  double ul[2], ur[2], ll[2], lr[2];
141 
142  int wasOk = getBoundingBox(p, nOfPoints, ul, ur, ll, lr);
143  double vol = (!wasOk) ? -1.0 : distance_d(ul,ll)*distance_d(ul,ur);
144  return vol;
145 }
146 
147 // computes the minimal bounding box for a set of 2d-points
148 // ul = upper left point, ll = lower left point,
149 // ur = upper right point, ul = upper left point
150 int getBoundingBox(BB_Point* p, int nOfPoints,
151  double ul[2], double ur[2], double ll[2], double lr[2]) {
152 
153  // calculate the center of all points (schwerpunkt)
154  // -------------------------------------------------
155  double centerx = 0;
156  double centery = 0;
157  for (int i=0; i < nOfPoints; i++) {
158  centerx += p[i].x;
159  centery += p[i].y;
160  }
161  centerx /= (double) nOfPoints;
162  centery /= (double) nOfPoints;
163 
164 
165 
166  // calcutae the covariance matrix
167  // -------------------------------
168  // covariance matrix (x1 x2, x3 x4)
169  double x1 = 0.0;
170  double x2 = 0.0;
171  double x3 = 0.0;
172  double x4 = 0.0;
173 
174  for (int i=0; i < nOfPoints; i++) {
175  double cix = p[i].x - centerx;
176  double ciy = p[i].y - centery;
177 
178  x1 += cix*cix;
179  x2 += cix*ciy;
180  x4 += ciy*ciy;
181  }
182  x1 /= (double) nOfPoints;
183  x2 /= (double) nOfPoints;
184  x3 = x2;
185  x4 /= (double) nOfPoints;
186  // covariance & center done
187 
188 
189  // calculate the eigenvectors
190  // ---------------------------
191  // catch 1/0 or sqrt(<0)
192  if ((x3 == 0) || (x2 == 0)|| (x4*x4-2*x1*x4+x1*x1+4*x2*x3 < 0 )) {
193  sm_error("Cyrill: Could not compute bounding box.\n");
194  return 0;
195 }
196 
197  // eigenvalues
198  double lamda1 = 0.5* (x4 + x1 + sqrt(x4*x4 - 2.0*x1*x4 + x1*x1 + 4.0*x2*x3));
199  double lamda2 = 0.5* (x4 + x1 - sqrt(x4*x4 - 2.0*x1*x4 + x1*x1 + 4.0*x2*x3));
200 
201  // eigenvector 1 with (x,y)
202  double v1x = - (x4-lamda1) * (x4-lamda1) * (x1-lamda1) / (x2 * x3 * x3);
203  double v1y = (x4-lamda1) * (x1-lamda1) / (x2 * x3);
204  // eigenvector 2 with (x,y)
205  double v2x = - (x4-lamda2) * (x4-lamda2) * (x1-lamda2) / (x2 * x3 * x3);
206  double v2y = (x4-lamda2) * (x1-lamda2) / (x2 * x3);
207 
208  // norm the eigenvectors
209  double lv1 = sqrt ( (v1x*v1x) + (v1y*v1y) );
210  double lv2 = sqrt ( (v2x*v2x) + (v2y*v2y) );
211  v1x /= lv1;
212  v1y /= lv1;
213  v2x /= lv2;
214  v2y /= lv2;
215  // eigenvectors done
216 
217  // get the points with maximal dot-product
218  double x = 0.0;
219  double y = 0.0;
220  double xmin = 1e20;
221  double xmax = -1e20;
222  double ymin = 1e20;
223  double ymax = -1e20;
224  for(int i = 0; i< nOfPoints; i++) {
225  // dot-product of relativ coordinates of every point
226  x = (p[i].x - centerx) * v1x + (p[i].y - centery) * v1y;
227  y = (p[i].x - centerx) * v2x + (p[i].y - centery) * v2y;
228 
229  if( x > xmax) xmax = x;
230  if( x < xmin) xmin = x;
231  if( y > ymax) ymax = y;
232  if( y < ymin) ymin = y;
233  }
234 
235  // now we can compute the corners of the bounding box
236  if(ul) {
237  ul[0] = centerx + xmin * v1x + ymin * v2x;
238  ul[1] = centery + xmin * v1y + ymin * v2y;
239  }
240 
241  if(ur) {
242  ur[0] = centerx + xmax * v1x + ymin * v2x;
243  ur[1] = centery + xmax * v1y + ymin * v2y;
244  }
245 
246  if(ll) {
247  ll[0] = centerx + xmin * v1x + ymax * v2x;
248  ll[1] = centery + xmin * v1y + ymax * v2y;
249  }
250 
251  if(lr) {
252  lr[0] = centerx + xmax * v1x + ymax * v2x;
253  lr[1] = centery + xmax * v1y + ymax * v2y;
254  }
255  return 1;
256 }
257 
258 
259 
260 
int *restrict valid
Definition: laser_data.h:23
int bbfind_add_point(bbfind *bbf, double point[2])
double *restrict theta
Definition: laser_data.h:21
int bbfind_add_point2(bbfind *bbf, double x, double y)
#define M_PI
Definition: math_utils.h:7
BB_Point * buf
void ld_get_oriented_bbox(LDP ld, double horizon, oriented_bbox *obbox)
double *restrict readings
Definition: laser_data.h:24
int bbfind_add_bbox(bbfind *bbf, const BB2 bbox)
void bbfind_free(bbfind *bbf)
struct @0 p
double getBoundingBoxArea(BB_Point *p, int nOfPoints)
double distance_d(const double a[2], const double b[2])
Definition: math_utils.c:55
bbfind * bbfind_new(void)
int getBoundingBox(BB_Point *p, int nOfPoints, double ul[2], double ur[2], double ll[2], double lr[2])
double x
void oriented_bbox_compute_corners(const BB2 obbox, double ul[2], double ur[2], double ll[2], double lr[2])
int bbfind_compute(bbfind *bbf, BB2 bbox)
void sm_error(const char *msg,...)
Definition: logging.c:49


csm
Author(s): Andrea Censi
autogenerated on Tue May 11 2021 02:18:23