00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <aversive.h>
00025 #include <aversive/error.h>
00026
00027 #include <math.h>
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include <string.h>
00031
00032 #include <obstacle_avoidance.h>
00033
00034 #define debug_printf(args...)
00035
00036
00037 static struct obstacle_avoidance oa;
00038
00042 void oa_init(void)
00043 {
00044 memset(&oa, 0, sizeof(oa));
00045
00046
00047
00048 oa.polys[0].pts = oa.points;
00049 oa.polys[0].l = 2;
00050 oa_start_end_points(0, 0, 100, 100);
00051 }
00052
00056 void oa_start_end_points(int32_t st_x, int32_t st_y, int32_t en_x, int32_t en_y)
00057 {
00058
00059 oa.points[0].x = en_x;
00060 oa.points[0].y = en_y;
00061
00062
00063
00064
00065
00066
00067
00068 oa.points[0].valid = 0;
00069
00070 oa.points[0].weight = 1;
00071
00072 oa.points[1].x = st_x;
00073 oa.points[1].y = st_y;
00074 oa.points[1].valid = 0;
00075 oa.points[1].weight = 0;
00076
00077 oa.cur_pt_idx = 2;
00078 oa.cur_poly_idx = 1;
00079 }
00080
00084 oa_poly_t *oa_new_poly(uint8_t size)
00085 {
00086 if (oa.cur_pt_idx + size > MAX_PTS)
00087 return NULL;
00088 if (oa.cur_poly_idx + 1 > MAX_POLY)
00089 return NULL;
00090
00091 oa.polys[oa.cur_poly_idx].l = size;
00092 oa.polys[oa.cur_poly_idx].pts = &oa.points[oa.cur_pt_idx];
00093 oa.cur_pt_idx += size;
00094
00095 return &oa.polys[oa.cur_poly_idx++];
00096 }
00097
00101 void oa_poly_set_point(oa_poly_t *pol,
00102 int32_t x, int32_t y, uint8_t i)
00103 {
00104 DEBUG(E_OA, "%s() (%ld,%ld)", __FUNCTION__, x, y);
00105
00106 pol->pts[i].x = x;
00107 pol->pts[i].y = y;
00108 pol->pts[i].valid = 0;
00109 pol->pts[i].weight = 0;
00110 }
00111
00112 oa_point_t * oa_get_path(void)
00113 {
00114 return oa.u.res;
00115 }
00116
00117
00118
00119
00120 static int32_t
00121 prod_scal(int32_t x1, int32_t y1, int32_t x2, int32_t y2)
00122 {
00123 return x1 * x2 + y1 * y2;
00124 }
00125
00126
00127 static int32_t
00128 prod_vect(int32_t x1, int32_t y1, int32_t x2, int32_t y2)
00129 {
00130 return x1*y2 - y1*x2;
00131 }
00132
00133
00134 static int8_t prod_scal_sign(int32_t x1, int32_t y1, int32_t x2, int32_t y2)
00135 {
00136 int32_t z;
00137 z = prod_scal(x1, y1, x2, y2);
00138 if (z==0)
00139 return 0;
00140 return z>0?1:-1;
00141 }
00142
00143
00144 static int8_t prod_vect_sign(int32_t x1, int32_t y1, int32_t x2, int32_t y2)
00145 {
00146 int32_t z;
00147 z = prod_vect(x1, y1, x2, y2);
00148 if (z==0)
00149 return 0;
00150 return z>0?1:-1;
00151 }
00152
00153
00154 static int32_t
00155 norm_vect(int32_t x, int32_t y)
00156 {
00157 return sqrt(x*x+y*y);
00158 }
00159
00160 #if 0
00161
00162 static int32_t
00163 quick_norm_vect(int32_t x, int32_t y)
00164 {
00165 return x*x+y*y;
00166 }
00167 #endif
00168
00169
00170 #define MAX_COEF 5000
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 void
00183 pts2line(const oa_ext_point_t *p1, const oa_ext_point_t *p2, oa_line_t *l)
00184 {
00185 int32_t max;
00186
00187 l->a = -(p2->y-p1->y);
00188 l->b = (p2->x-p1->x);
00189 l->c = -(l->a * p1->x + l->b * p1->y);
00190
00191 max = (ABS(l->a) > ABS(l->b) ? ABS(l->a) : ABS(l->b));
00192 max = (max > ABS(l->c) ? max : ABS(l->c));
00193
00194 l->a = (l->a * MAX_COEF) / max;
00195 l->b = (l->b * MAX_COEF) / max;
00196 l->c = (l->c * MAX_COEF) / max;
00197 }
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207 uint8_t
00208 intersect_line(const oa_line_t *l1, const oa_line_t *l2, oa_ext_point_t *p)
00209 {
00210 debug_printf("l1:%" PRIi32 ",%" PRIi32 ",%" PRIi32 " l2:%" PRIi32 ",%" PRIi32 ",%" PRIi32 "\n",
00211 l1->a, l1->b, l1->c, l2->a, l2->b, l2->c);
00212
00213
00214 if ((l1->a == 0 && l1->b == 0) || (l2->a == 0 && l2->b == 0))
00215 return 0;
00216
00217 if (l1->a == 0) {
00218 if (l2->a == 0) {
00219 if (l1->b*l2->c == l2->b*l1->c)
00220 return 2;
00221 return 0;
00222 }
00223
00224
00225
00226 p->y = -l1->c/l1->b;
00227 p->x = -(l2->b*p->y + l2->c)/l2->a;
00228 return 1;
00229 }
00230
00231 if (l1->b == 0) {
00232 if (l2->b == 0) {
00233 if (l1->a*l2->c == l2->a*l1->c)
00234 return 2;
00235 return 0;
00236 }
00237
00238
00239 p->x = -l1->c/l1->a;
00240 p->y = -(l2->a*p->x + l2->c)/l2->b;
00241 return 1;
00242 }
00243
00244
00245 if (l2->a*l1->b-l1->a*l2->b == 0) {
00246 if (l1->a*l2->c == l2->a*l1->c)
00247 return 2;
00248 return 0;
00249 }
00250
00251 p->y = (l1->a*l2->c-l1->c*l2->a)/(l2->a*l1->b-l1->a*l2->b);
00252 p->x = -(l1->b*p->y+l1->c)/l1->a;
00253
00254 return 1;
00255 }
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268 uint8_t
00269 intersect_segment(const oa_ext_point_t *s1, const oa_ext_point_t *s2,
00270 const oa_ext_point_t *t1, const oa_ext_point_t *t2,
00271 oa_ext_point_t *p)
00272 {
00273 oa_line_t l1, l2;
00274 uint8_t ret;
00275 int8_t u1, u2;
00276
00277 pts2line(s1, s2, &l1);
00278 pts2line(t1, t2, &l2);
00279
00280 ret = intersect_line(&l1, &l2, p);
00281 if (!ret)
00282 return 0;
00283 if (ret==2) {
00284 if (prod_scal_sign(t1->x-s1->x, t1->y-s1->y, t1->x-s2->x, t1->y-s2->y )<=0)
00285 return 3;
00286 if (prod_scal_sign(t2->x-s1->x, t2->y-s1->y, t2->x-s2->x, t2->y-s2->y )<=0)
00287 return 3;
00288 return 0;
00289 }
00290
00291
00292
00293 if (s1->x == t1->x && s1->y == t1->y) {
00294 *p = *s1;
00295 return 2;
00296 }
00297 if (s1->x == t2->x && s1->y == t2->y) {
00298 *p = *s1;
00299 return 2;
00300 }
00301 if (s2->x == t1->x && s2->y == t1->y) {
00302 *p = *s2;
00303 return 2;
00304 }
00305 if (s2->x == t2->x && s2->y == t2->y) {
00306 *p = *s2;
00307 return 2;
00308 }
00309
00310 debug_printf("px=%" PRIi32 " py=%" PRIi32 "\n", p->x, p->y);
00311
00312
00313
00314 u1 = prod_scal_sign(p->x-s1->x, p->y-s1->y, p->x-s2->x, p->y-s2->y);
00315 u2 = prod_scal_sign(p->x-t1->x, p->y-t1->y, p->x-t2->x, p->y-t2->y);
00316
00317 if (u1>0 || u2>0)
00318 return 0;
00319
00320 if (u1==0 || u2==0)
00321 return 2;
00322
00323 return 1;
00324
00325 }
00326
00327
00328
00329
00330
00331
00332 static uint8_t
00333 is_in_poly(const oa_ext_point_t *p, oa_poly_t *pol)
00334 {
00335 uint8_t i;
00336 uint8_t ii;
00337 int8_t z;
00338 uint8_t ret=1;
00339
00340 for (i=0;i<pol->l;i++) {
00341
00342 if (p->x == pol->pts[i].x && p->y == pol->pts[i].y)
00343 return 2;
00344 }
00345
00346 for (i=0;i<pol->l;i++) {
00347
00348 ii = (i+1)%pol->l;
00349 z = prod_vect_sign(pol->pts[ii].x-p->x, pol->pts[ii].y-p->y,
00350 pol->pts[i].x-p->x, pol->pts[i].y-p->y);
00351 if (z>0)
00352 return 0;
00353 if (z==0)
00354 ret=2;
00355 }
00356
00357 return ret;
00358 }
00359
00360
00361 uint8_t is_point_in_poly(oa_poly_t *pol, int16_t x, int16_t y)
00362 {
00363 oa_ext_point_t p;
00364 p.x = x;
00365 p.y = y;
00366 return is_in_poly(&p, pol);
00367 }
00368
00369
00370
00371
00372
00373
00374
00375
00376 uint8_t
00377 is_crossing_poly(oa_ext_point_t p1, oa_ext_point_t p2, oa_poly_t *pol)
00378 {
00379 uint8_t i;
00380 uint8_t ret;
00381 oa_ext_point_t p;
00382 uint8_t ret1, ret2;
00383 uint8_t cpt=0;
00384
00385 debug_printf("%" PRIi32 " %" PRIi32 " -> %" PRIi32 " %" PRIi32 " crossing poly %p ?\n",
00386 p1.x, p1.y, p2.x, p2.y, pol);
00387 debug_printf("poly is : ");
00388 for (i=0; i<pol->l; i++) {
00389 debug_printf("%" PRIi32 ",%" PRIi32 " ", pol->pts[i].x, pol->pts[i].y);
00390 }
00391 debug_printf("\n");
00392
00393 for (i=0;i<pol->l;i++) {
00394 ret = intersect_segment(&p1, &p2, &pol->pts[i], &pol->pts[(i+1)%pol->l], &p);
00395 debug_printf("%" PRIi32 ",%" PRIi32 " -> %" PRIi32 ",%" PRIi32
00396 " return %d\n", pol->pts[i].x, pol->pts[i].y,
00397 pol->pts[(i+1)%pol->l].x, pol->pts[(i+1)%pol->l].y, ret);
00398 switch(ret) {
00399 case 0:
00400 break;
00401 case 1:
00402 return 1;
00403 break;
00404 case 2:
00405 cpt++;
00406 break;
00407 case 3:
00408 return 2;
00409 break;
00410 }
00411 }
00412
00413 if (cpt==3 ||cpt==4)
00414 return 1;
00415
00416 ret1 = is_in_poly(&p1, pol);
00417
00418 ret2 = is_in_poly(&p2, pol);
00419
00420 if (cpt==0) {
00421 if (ret1==1 || ret2==1)
00422 return 1;
00423 return 0;
00424 }
00425
00426
00427 if (cpt==1) {
00428 if (ret1==1 || ret2==1)
00429 return 1;
00430 return 3;
00431 }
00432 if (cpt==2) {
00433 if (ret1==1 || ret2==1)
00434 return 1;
00435 if (ret1==0 || ret2==0)
00436 return 3;
00437 return 1;
00438 }
00439
00440 return 1;
00441 }
00442
00443 #define IS_IN_PLAYGROUND(pt) ( (pt).x >= PLAYGROUND_X_MIN && \
00444 (pt).x<=PLAYGROUND_X_MAX && \
00445 (pt).y >= PLAYGROUND_Y_MIN && (pt).y<=PLAYGROUND_Y_MAX )
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464 uint8_t
00465 calc_rays(oa_poly_t *polys, uint8_t npolys, uint8_t *rays)
00466 {
00467 uint8_t i, ii, index;
00468 uint8_t ray_n=0;
00469 uint8_t is_ok;
00470 uint8_t n;
00471 uint8_t pt1, pt2;
00472
00473
00474
00475
00476
00477
00478
00479
00480 for (i=0; i<npolys; i++) {
00481 debug_printf("%d/%d\n", i, npolys);
00482 for (ii=0; ii<polys[i].l; ii++) {
00483 debug_printf("%d/%d\n", ii, polys[i].l);
00484 if (! IS_IN_PLAYGROUND(polys[i].pts[ii]))
00485 continue;
00486 is_ok = 1;
00487 n = (ii+1)%polys[i].l;
00488
00489 if (!(IS_IN_PLAYGROUND(polys[i].pts[n])))
00490 continue;
00491
00492
00493
00494 for (index=1; index<npolys; index++) {
00495
00496
00497 if (index == i) continue;
00498
00499 if (is_crossing_poly(polys[i].pts[ii], polys[i].pts[n],
00500 &polys[index]) == 1) {
00501 is_ok = 0;
00502 debug_printf("ret 1\n");
00503 break;
00504 }
00505 }
00506
00507 if (is_ok) {
00508 rays[ray_n++] = i;
00509 rays[ray_n++] = ii;
00510 rays[ray_n++] = i;
00511 rays[ray_n++] = n;
00512 }
00513 }
00514 }
00515
00516
00517
00518
00519
00520
00521 for (i=0; i<npolys-1; i++) {
00522 for (pt1=0;pt1<polys[i].l;pt1++) {
00523
00524 if (!(IS_IN_PLAYGROUND(polys[i].pts[pt1])))
00525 continue;
00526
00527
00528 for (ii=i+1; ii<npolys; ii++) {
00529 for (pt2=0;pt2<polys[ii].l;pt2++) {
00530
00531 if (!(IS_IN_PLAYGROUND(polys[ii].pts[pt2])))
00532 continue;
00533
00534 is_ok=1;
00535
00536 for (index=1;index<npolys;index++) {
00537 if (is_crossing_poly(polys[i].pts[pt1], polys[ii].pts[pt2], &polys[index])==1) {
00538 is_ok=0;
00539 break;
00540 }
00541 }
00542
00543 if (is_ok) {
00544 rays[ray_n++] = i;
00545 rays[ray_n++] = pt1;
00546 rays[ray_n++] = ii;
00547 rays[ray_n++] = pt2;
00548 }
00549 }
00550 }
00551 }
00552 }
00553
00554
00555 return ray_n;
00556 }
00557
00558
00559
00560
00561
00562
00563
00564 void
00565 calc_rays_weight(oa_poly_t *polys, uint8_t npolys, uint8_t *rays,
00566 uint8_t ray_n, uint16_t *weight)
00567 {
00568 uint8_t i;
00569 for (i=0;i<ray_n;i+=4) {
00570 weight[i/4] = norm_vect(polys[rays[i]].pts[rays[i+1]].x - polys[rays[i+2]].pts[rays[i+3]].x,
00571 polys[rays[i]].pts[rays[i+1]].y - polys[rays[i+2]].pts[rays[i+3]].y) + 1;
00572 }
00573 }
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592 void
00593 dijkstra(uint8_t start_p, uint8_t start)
00594 {
00595 uint8_t i;
00596 int8_t add;
00597 int8_t finish = 0;
00598
00599
00600
00601
00602
00603 oa.polys[start_p].pts[start].valid = 2;
00604
00605 while (!finish){
00606 finish = 1;
00607
00608 for (start_p = 0;start_p<MAX_POLY;start_p++)
00609 for (start = 0;start<oa.polys[start_p].l;start++){
00610 if (oa.polys[start_p].pts[start].valid != 2)
00611 continue;
00612 add = -2;
00613
00614
00615
00616
00617
00618
00619 for (i=0 ; i<oa.ray_n ; i+=2) {
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629 add = -add;
00630
00631 if (start_p == oa.u.rays[i] && start == oa.u.rays[i+1]) {
00632 if ((oa.polys[oa.u.rays[i+add]].pts[oa.u.rays[i+add+1]].weight == 0) ||
00633 (oa.polys[start_p].pts[start].weight+oa.weight[i/4] <
00634 oa.polys[oa.u.rays[i+add]].pts[oa.u.rays[i+add+1]].weight)) {
00635
00636 oa.polys[oa.u.rays[i+add]].pts[oa.u.rays[i+add+1]].p = start_p;
00637 oa.polys[oa.u.rays[i+add]].pts[oa.u.rays[i+add+1]].pt = start;
00638 oa.polys[oa.u.rays[i+add]].pts[oa.u.rays[i+add+1]].valid=2;
00639 oa.polys[oa.u.rays[i+add]].pts[oa.u.rays[i+add+1]].weight =
00640 oa.polys[start_p].pts[start].weight+oa.weight[i/4];
00641
00642 oa.polys[start_p].pts[start].valid = 1;
00643 finish = 0;
00644 }
00645 }
00646 }
00647 }
00648 }
00649 }
00650
00651
00652
00653 int8_t
00654 get_path(oa_poly_t *polys, uint8_t *rays)
00655 {
00656 uint8_t p, pt, p1, pt1, i;
00657
00658 p=0;
00659 pt=1;
00660 i=0;
00661
00662
00663
00664 while (!(p==0 && pt==0)) {
00665
00666 if (i>=MAX_CHKPOINTS)
00667 return -1;
00668
00669 if (polys[p].pts[pt].valid==0) {
00670 DEBUG(E_OA, "invalid path!");
00671 return -1;
00672 }
00673
00674 p1 = polys[p].pts[pt].p;
00675 pt1 = polys[p].pts[pt].pt;
00676 p = p1; pt = pt1;
00677 oa.u.res[i].x = polys[p].pts[pt].x;
00678 oa.u.res[i].y = polys[p].pts[pt].y;
00679 DEBUG(E_OA, "result[%d]: %d, %d", i, oa.u.res[i].x, oa.u.res[i].y);
00680 i++;
00681 }
00682
00683 return i;
00684 }
00685
00686 int8_t
00687 oa_process(void)
00688 {
00689 uint8_t ret;
00690 uint8_t i;
00691
00692
00693 ret = calc_rays(oa.polys, oa.cur_poly_idx, oa.u.rays);
00694 DEBUG(E_OA, "nb_rays = %d", ret);
00695
00696 DEBUG(E_OA, "Ray list");
00697 for (i=0;i<ret;i+=4) {
00698 DEBUG(E_OA, "%d,%d -> %d,%d", oa.u.rays[i], oa.u.rays[i+1],
00699 oa.u.rays[i+2], oa.u.rays[i+3]);
00700 }
00701
00702
00703 calc_rays_weight(oa.polys, oa.cur_poly_idx,
00704 oa.u.rays, ret, oa.weight);
00705
00706 DEBUG(E_OA, "Ray weights");
00707 for (i=0;i<ret;i+=4) {
00708 DEBUG(E_OA, "%d,%d -> %d,%d (%d)",
00709 (int)oa.polys[oa.u.rays[i]].pts[oa.u.rays[i+1]].x,
00710 (int)oa.polys[oa.u.rays[i]].pts[oa.u.rays[i+1]].y,
00711 (int)oa.polys[oa.u.rays[i+2]].pts[oa.u.rays[i+3]].x,
00712 (int)oa.polys[oa.u.rays[i+2]].pts[oa.u.rays[i+3]].y,
00713 oa.weight[i/4]);
00714 }
00715
00716
00717
00718 oa.ray_n = ret;
00719 DEBUG(E_OA, "dijkstra ray_n = %d", ret);
00720 dijkstra(0, 0);
00721
00722
00723
00724 return get_path(oa.polys, oa.u.rays);
00725 }