Hybrid A* Planner
 All Classes Namespaces Files Functions Variables Friends Pages
lookup.h
1 #ifndef COLLISIONLOOKUP
2 #define COLLISIONLOOKUP
3 
4 #include "dubins.h"
5 #include "constants.h"
6 
7 namespace HybridAStar {
8 namespace Lookup {
9 
10 //###################################################
11 // DUBINS LOOKUP
12 //###################################################
13 inline void dubinsLookup(float* lookup) {
14  bool DEBUG = false;
15  std::cout << "I am building the Dubin's lookup table...";
16 
17  DubinsPath path;
18 
19  int width = Constants::dubinsWidth / Constants::cellSize;
20 
21  // // increase the width by one to make it square
22  // if (width % 2 != 0) {
23  // width++;
24  // }
25 
26  const int headings = Constants::headings;
27 
28  // start and goal vector
29  double start[3];
30  double goal[] = {0, 0, 0};
31 
32  // iterate over the X index of a grid cell
33  for (int X = 0; X < width; ++X) {
34  start[0] = X;
35 
36  // iterate over the Y index of a grid cell
37  for (int Y = 0; Y < width; ++Y) {
38  start[1] = Y;
39 
40  // iterate over the start headings
41  for (int h0 = 0; h0 < headings; ++h0) {
42  start[2] = Constants::deltaHeadingRad * h0;
43 
44  // iterate over the goal headings
45  for (int h1 = 0; h1 < headings; ++h1) {
46  goal[2] = Constants::deltaHeadingRad * h1;
47 
48  // calculate the actual cost
49  dubins_init(start, goal, Constants::r, &path);
50  lookup[X * headings * headings * width + Y * headings * headings + h0 * headings + h1] = dubins_path_length(&path);
51 
52  if (DEBUG && lookup[X * headings * headings * width + Y * headings * headings + h0 * headings + h1] < sqrt(X * X + Y * Y) * 1.000001) {
53  std::cout << X << " | " << Y << " | "
54  << Constants::deltaHeadingDeg* h0 << " | "
55  << Constants::deltaHeadingDeg* h1 << " length: "
56  << lookup[X * headings * headings * width + Y * headings * headings + h0 * headings + h1] << "\n";
57 
58  }
59  }
60  }
61  }
62  }
63 
64  std::cout << " done!" << std::endl;
65 }
66 
67 //###################################################
68 // COLLISION LOOKUP
69 //###################################################
70 
71 // _____________
72 // SIGN FUNCTION
73 inline int sign(double x) {
74  if (x >= 0) { return 1; }
75  else { return -1; }
76 }
77 
78 // _________________________
79 // COLLISION LOOKUP CREATION
80 inline void collisionLookup(Constants::config* lookup) {
81  bool DEBUG = false;
82  std::cout << "I am building the collision lookup table...";
83  // cell size
84  const float cSize = Constants::cellSize;
85  // bounding box size length/width
86  const int size = Constants::bbSize;
87 
88  struct point {
89  double x;
90  double y;
91  };
92 
93  // ______________________
94  // VARIABLES FOR ROTATION
95  //center of the rectangle
96  point c;
97  point temp;
98  // points of the rectangle
99  point p[4];
100  point nP[4];
101 
102  // turning angle
103  double theta;
104 
105  // ____________________________
106  // VARIABLES FOR GRID TRAVERSAL
107  // vector for grid traversal
108  point t;
109  point start;
110  point end;
111  // cell index
112  int X;
113  int Y;
114  // t value for crossing vertical and horizontal boundary
115  double tMaxX;
116  double tMaxY;
117  // t value for width/heigth of cell
118  double tDeltaX;
119  double tDeltaY;
120  // positive or negative step direction
121  int stepX;
122  int stepY;
123  // grid
124  bool cSpace[size * size];
125  bool inside = false;
126  int hcross1 = 0;
127  int hcross2 = 0;
128 
129  // _____________________________
130  // VARIABLES FOR LOOKUP CREATION
131  int count = 0;
132  const int positionResolution = Constants::positionResolution;
133  const int positions = Constants::positions;
134  point points[positions];
135 
136  // generate all discrete positions within one cell
137  for (int i = 0; i < positionResolution; ++i) {
138  for (int j = 0; j < positionResolution; ++j) {
139  points[positionResolution * i + j].x = 1.f / positionResolution * j;
140  points[positionResolution * i + j].y = 1.f / positionResolution * i;
141  }
142  }
143 
144 
145  for (int q = 0; q < positions; ++q) {
146  // set the starting angle to zero;
147  theta = 0;
148 
149  // set points of rectangle
150  c.x = (double)size / 2 + points[q].x;
151  c.y = (double)size / 2 + points[q].y;
152 
153  p[0].x = c.x - Constants::length / 2 / cSize;
154  p[0].y = c.y - Constants::width / 2 / cSize;
155 
156  p[1].x = c.x - Constants::length / 2 / cSize;
157  p[1].y = c.y + Constants::width / 2 / cSize;
158 
159  p[2].x = c.x + Constants::length / 2 / cSize;
160  p[2].y = c.y + Constants::width / 2 / cSize;
161 
162  p[3].x = c.x + Constants::length / 2 / cSize;
163  p[3].y = c.y - Constants::width / 2 / cSize;
164 
165  for (int o = 0; o < Constants::headings; ++o) {
166  if (DEBUG) { std::cout << "\ndegrees: " << theta * 180.f / M_PI << std::endl; }
167 
168  // initialize cSpace
169  for (int i = 0; i < size; ++i) {
170  for (int j = 0; j < size; ++j) {
171  cSpace[i * size + j] = false;
172  }
173  }
174 
175  // shape rotation
176  for (int j = 0; j < 4; ++j) {
177  // translate point to origin
178  temp.x = p[j].x - c.x;
179  temp.y = p[j].y - c.y;
180 
181  // rotate and shift back
182  nP[j].x = temp.x * cos(theta) - temp.y * sin(theta) + c.x;
183  nP[j].y = temp.x * sin(theta) + temp.y * cos(theta) + c.y;
184  }
185 
186  // create the next angle
187  theta += Constants::deltaHeadingRad;
188 
189  // cell traversal clockwise
190  for (int k = 0; k < 4; ++k) {
191  // create the vectors clockwise
192  if (k < 3) {
193  start = nP[k];
194  end = nP[k + 1];
195  } else {
196  start = nP[k];
197  end = nP[0];
198  }
199 
200  //set indexes
201  X = (int)start.x;
202  Y = (int)start.y;
203  // std::cout << "StartCell: " << X << "," << Y << std::endl;
204  cSpace[Y * size + X] = true;
205  t.x = end.x - start.x;
206  t.y = end.y - start.y;
207  stepX = sign(t.x);
208  stepY = sign(t.y);
209 
210  // width and height normalized by t
211  if (t.x != 0) {
212  tDeltaX = 1.f / std::abs(t.x);
213  } else {
214  tDeltaX = 1000;
215  }
216 
217  if (t.y != 0) {
218  tDeltaY = 1.f / std::abs(t.y);
219  } else {
220  tDeltaY = 1000;
221  }
222 
223  // set maximum traversal values
224  if (stepX > 0) {
225  tMaxX = tDeltaX * (1 - (start.x - (long)start.x));
226  } else {
227  tMaxX = tDeltaX * (start.x - (long)start.x);
228  }
229 
230  if (stepY > 0) {
231  tMaxY = tDeltaY * (1 - (start.y - (long)start.y));
232  } else {
233  tMaxY = tDeltaY * (start.y - (long)start.y);
234  }
235 
236  while ((int)end.x != X || (int)end.y != Y) {
237  // only increment x if the t length is smaller and the result will be closer to the goal
238  if (tMaxX < tMaxY && std::abs(X + stepX - (int)end.x) < std::abs(X - (int)end.x)) {
239  tMaxX = tMaxX + tDeltaX;
240  X = X + stepX;
241  cSpace[Y * size + X] = true;
242  // only increment y if the t length is smaller and the result will be closer to the goal
243  } else if (tMaxY < tMaxX && std::abs(Y + stepY - (int)end.y) < std::abs(Y - (int)end.y)) {
244  tMaxY = tMaxY + tDeltaY;
245  Y = Y + stepY;
246  cSpace[Y * size + X] = true;
247  } else if (2 >= std::abs(X - (int)end.x) + std::abs(Y - (int)end.y)) {
248  if (std::abs(X - (int)end.x) > std::abs(Y - (int)end.y)) {
249  X = X + stepX;
250  cSpace[Y * size + X] = true;
251  } else {
252  Y = Y + stepY;
253  cSpace[Y * size + X] = true;
254  }
255  } else {
256  // this SHOULD NOT happen
257  std::cout << "\n--->tie occured, please check for error in script\n";
258  break;
259  }
260  }
261  }
262 
263  // FILL THE SHAPE
264  for (int i = 0; i < size; ++i) {
265  // set inside to false
266  inside = false;
267 
268  for (int j = 0; j < size; ++j) {
269 
270  // determine horizontal crossings
271  for (int k = 0; k < size; ++k) {
272  if (cSpace[i * size + k] && !inside) {
273  hcross1 = k;
274  inside = true;
275  }
276 
277  if (cSpace[i * size + k] && inside) {
278  hcross2 = k;
279  }
280  }
281 
282  // if inside fill
283  if (j > hcross1 && j < hcross2 && inside) {
284  cSpace[i * size + j] = true;
285  }
286  }
287  }
288 
289  // GENERATE THE ACTUAL LOOKUP
290  count = 0;
291 
292  for (int i = 0; i < size; ++i) {
293  for (int j = 0; j < size; ++j) {
294  if (cSpace[i * size + j]) {
295  // compute the relative position of the car cells
296  lookup[q * Constants::headings + o].pos[count].x = j - (int)c.x;
297  lookup[q * Constants::headings + o].pos[count].y = i - (int)c.y;
298  // add one for the length of the current list
299  count++;
300  }
301  }
302  }
303 
304  lookup[q * Constants::headings + o].length = count;
305 
306  if (DEBUG) {
307  //DEBUG
308  for (int i = 0; i < size; ++i) {
309  std::cout << "\n";
310 
311  for (int j = 0; j < size; ++j) {
312  if (cSpace[i * size + j]) {
313  std::cout << "#";
314  } else {
315  std::cout << ".";
316  }
317  }
318  }
319 
320  //TESTING
321  std::cout << "\n\nthe center of " << q* Constants::headings + o << " is at " << c.x << " | " << c.y << std::endl;
322 
323  for (int i = 0; i < lookup[q * Constants::headings + o].length; ++i) {
324  std::cout << "[" << i << "]\t" << lookup[q * Constants::headings + o].pos[i].x << " | " << lookup[q * Constants::headings + o].pos[i].y << std::endl;
325  }
326  }
327  }
328  }
329 
330  std::cout << " done!" << std::endl;
331 }
332 
333 }
334 }
335 #endif // LOOKUP
336 
This is a collection of constants that are used throughout the project.