laser-nav.c

00001 /*
00002  * @(#)lasernav.c       07/03/21
00003  * 
00004  * License      : GNU GPL v.2
00005  * Description  : Robot navigation using 3 passive laser reflectors.
00006  *                (pln - Passive Laser Navigaton)
00007  * Author       : Tran Duy Khanh (www.tran.cz)
00008  */
00009 
00010 #include <math.h>
00011 #include <robomath.h>
00012 #include "laser-nav.h"
00013         
00065 // /**
00066 //  * Gaussian probability density function.
00067 //  *
00068 //  * @param  val               value we are looking for
00069 //  * @param  sigma     standard deviation
00070 //  */
00071 // double evaluate_gaussian(double val, double sigma)
00072 // {
00073 //      return ((double)1.0/(sqrt((double)2.0*(double)M_PI) * sigma) *
00074 //              exp((double)(-0.5) * (val*val / (sigma*sigma))));
00075 // }
00076 
00083 void time2angle(struct pln_time_state ts, struct pln_aangle_state *aas)
00084 {
00085         aas->theta[0] = TIME2ANGLE(ts.period, ts.t_theta[0]);
00086         aas->theta[1] = TIME2ANGLE(ts.period, ts.t_theta[1]);
00087         aas->theta[2] = TIME2ANGLE(ts.period, ts.t_theta[2]);
00088 }
00089 
00096 void aangle2angle(struct pln_aangle_state aas, struct pln_angle_state *as)
00097 {
00098         as->beta = aas.theta[1] - aas.theta[0];
00099         as->gama = aas.theta[2] - aas.theta[1];
00100         as->alfa = 2*M_PI - as->beta - as->gama;
00101 }
00102 
00110 void pln_get_line(struct pln_point a, struct pln_point b,
00111                         struct pln_line *line)
00112 {
00113         line->k = (b.y - a.y)/(b.x - a.x);
00114         line->q = a.y - line->k * a.x;
00115 }
00116 
00124 void pln_get_oline(struct pln_line line, struct pln_point c,
00125                         struct pln_line *oline)
00126 {
00127         oline->k = -1 / line.k;
00128         oline->q = c.y - oline->k * c.x;
00129 }
00130 
00138 void pln_solve_quad(struct pln_fquad quad, 
00139                         struct pln_compl *sol1, struct pln_compl *sol2)
00140 {
00141         double tmp;
00142 
00143         /* normalize */
00144         /*tmp = 1/quad.a;
00145         quad.a *= tmp;
00146         quad.b *= tmp;
00147         quad.c *= tmp;*/
00148 
00149         tmp = POWER(quad.b) - 4*quad.a*quad.c;
00150         /* solution is a complex variable */
00151         if (tmp < 0) {
00152                 tmp = fabs(tmp);
00153                 sol1->real = (-quad.b)/(2*quad.a);
00154                 sol1->imag = -(sqrt(tmp)/(2*quad.a));
00155                 sol2->real = (-quad.b)/(2*quad.a);
00156                 sol2->imag = sqrt(tmp)/(2*quad.a);
00157         /* solution is a real variable */
00158         } else {
00159                 sol1->real = (-quad.b-sqrt(tmp))/(2*quad.a);
00160                 sol1->imag = 0;
00161                 sol2->real = (-quad.b+sqrt(tmp))/(2*quad.a);
00162                 sol2->imag = 0;
00163         }
00164 
00165 #if DEBUG>=2
00166         printf("pln_solve_quad(): x1.real=%f x1.imag=%f x2.real=%f x2.imag=%f\n", 
00167                 sol1->real, sol1->imag, sol2->real, sol2->imag);
00168 #endif
00169 }
00170 
00179 void pln_solve_2quad(struct pln_fquad_2var form1, 
00180                         struct pln_fquad_2var form2, 
00181                         struct pln_point *sol1, struct pln_point *sol2)
00182 {
00183         double tmp;
00184         struct pln_fquad_2var form;
00185         struct pln_fquad quad;
00186         struct pln_compl y1, y2;
00187 
00188         /* 1) merge equations */
00189         tmp = (-form1.ax)/form2.ax;
00190         form.ax = form1.ax + tmp*form2.ax;
00191         form.bx = form1.bx + tmp*form2.bx;
00192         form.ay = form1.ay + tmp*form2.ay;
00193         form.by = form1.by + tmp*form2.by;
00194         form.rs = form1.rs + tmp*form2.rs;
00195 
00196 #if DEBUG>=3
00197         printf("pln_solve_2quad(): %f*X2 %f*X %f*Y2 %f*Y  = %f\n",
00198                         form.ax, form.bx,
00199                         form.ay, form.by, form.rs);
00200 #endif
00201 
00202         /* 2) normalize */
00203         tmp = 1/form.bx;
00204         form.bx *= tmp;
00205         form.by *= tmp;
00206         form.rs *= tmp;
00207 
00208 #if DEBUG>=3
00209         printf("pln_solve_2quad(): %f*X %f*Y = %f\n", 
00210                         form.bx, form.by, form.rs);
00211 #endif
00212         
00213         /* 3) substitution for X - we get a quadratic equation */
00214         quad.a = POWER(-form.by)*form1.ax + form1.ay;
00215         quad.b = 2*(-form.by)*form.rs + form1.bx*(-form.by) + form1.by;
00216         quad.c = POWER(form.rs) + form1.bx*form.rs - form1.rs;
00217 
00218 #if DEBUG>=3
00219         printf("pln_solve_2quad(): a=%f b=%f c=%f\n", 
00220                         quad.a, quad.b, quad.c);
00221 #endif
00222 
00223         /* 4) solve the quadratic equation - find Y */
00224         pln_solve_quad(quad, &y1, &y2);
00225         
00226         /* 5) find X, the final results */
00227         sol1->y = y1.real;
00228         sol1->x = (-form.by)*y1.real + form.rs;
00229         sol2->y = y2.real;
00230         sol2->x = (-form.by)*y2.real + form.rs;
00231 }
00232 
00242 void pln_circ_line_cross(struct pln_circle circle, struct pln_line line,
00243                         struct pln_point *sol1, struct pln_point *sol2)
00244 {
00245         struct pln_compl x1, x2;
00246         struct pln_fquad quad;
00247 
00248         /* solve quadratic equation - find X */
00249         quad.a = POWER(line.k) + 1.0;
00250         quad.b = 0;
00251         quad.c = -POWER(circle.radius);
00252         pln_solve_quad(quad, &x1, &x2);
00253         /* count Y */
00254         sol1->x = x1.real;
00255         sol1->y = x1.real * line.k;
00256         sol2->x = x2.real;
00257         sol2->y = x2.real * line.k;
00258 
00259 #if DEBUG>=3
00260         printf("pln_circ_line_cross(): [x1=%f,y1=%f] [x2=%f,y2=%f]\n", 
00261                 sol1->x, sol1->y, sol2->x, sol2->y);
00262 #endif
00263 }
00264 
00273 void pln_get_circle2(struct pln_circ c, struct pln_circle *circle)
00274 {
00275         double opposite;
00276         int sgn = -1;
00277 
00278         /* get opposite side to the known angle */
00279         opposite = sqrt(POWER(c.pl.x-c.pr.x) + 
00280                         POWER(c.pl.y-c.pr.y)) / 2;
00281         /* if the angle is greater than PI/2, we have to use double angle, 
00282          * because the center of the circle will be outside */
00283         if (c.angle > M_PI/2) {
00284                 c.angle = (2*M_PI-c.angle*2)/2;
00285                 sgn = 1;
00286         }
00287 
00288         /* get circle center */
00289         if (opposite == FWIDTH/2) {
00290                 circle->x0 = opposite;
00291                 circle->y0 = FHEIGHT + 
00292                         sgn*(opposite/tan(c.angle));
00293         } else {
00294                 circle->y0 = opposite;
00295                 circle->x0 = FWIDTH + 
00296                         sgn*(opposite/tan(c.angle));
00297         }
00298         /* circle radius */
00299         circle->radius = opposite/cos(M_PI/2-c.angle);
00300 }
00301 
00308 void pln_get_circle(struct pln_circ c, struct pln_circle *circle)
00309 {
00310         struct pln_line line, oline;
00311         struct pln_circle centercirc;
00312         struct pln_point center1, center2;
00313         double opposite, cdist, angle;
00314         int sgnx=1, sgny=1;
00315 
00316         /* opposite side of the known angle */
00317         opposite = sqrt(POWER(c.pl.x-c.pr.x) + 
00318                         POWER(c.pl.y-c.pr.y)) / 2;
00319         /* if the angle is greater than PI/2, we have to use double angle, 
00320          * because the center of the circle will be outside */
00321         angle = c.angle;
00322         if (c.angle > M_PI/2)
00323                 c.angle = (2*M_PI-c.angle*2)/2;
00324 
00325         /* distance from center point to center of the circle */
00326         cdist = opposite/tan(c.angle);
00327         /* get line parameters from 2 points */
00328         pln_get_line(c.pl, c.pr, &line);
00329         /* get ortogonal line to a line if we know the cross point */
00330         pln_get_oline(line, c.pc, &oline);
00331         /* we put center to point c.pc, so dont care about the y-intercept */
00332         oline.q = 0;
00333 
00334         /* we know the distance from known point to center of our circle, so
00335          * try to find the center, which are the cross points of the line and
00336          * circle with radius equal to our distance */
00337         centercirc.x0 = c.pc.x;
00338         centercirc.y0 = c.pc.y;
00339         centercirc.radius = cdist;
00340         pln_circ_line_cross(centercirc, oline, &center1, &center2);
00341 
00342         /* ortogonal side C-L-B */
00343         if (isinf(line.k)) {
00344                 if (angle < M_PI/2) {
00345                         sgnx = -1;
00346                         sgny = -1;
00347                 } else {
00348                         sgnx = 1;
00349                         sgny = 1;
00350                 }
00351         /* side K-H-C */
00352         } else if (oline.k < 0) {
00353                 if ((angle>M_PI/2 && angle<M_PI) || (angle>3*M_PI/2 && angle<2*M_PI)) {
00354                         sgnx = -1;
00355                         sgny = 1;
00356                 } else {
00357                         sgnx = 1;
00358                         sgny = -1;
00359                 }
00360         /* side K-G-B */
00361         } else {
00362                 if ((angle>M_PI/2 && angle<M_PI) || (angle>3*M_PI/2 && angle<2*M_PI)) {
00363                         sgnx = -1;
00364                         sgny = -1;
00365                 }
00366         }
00367 #ifdef USE_RED_REFLECTORS
00368         sgnx *= -1;
00369         sgny *= -1;
00370 #endif
00371         /* center of the circle */
00372         circle->x0 = centercirc.x0 + sgnx*fabs(center1.x);
00373         circle->y0 = centercirc.y0 + sgny*fabs(center1.y);
00374         /* circle radius */
00375         circle->radius = fabs(opposite/cos(M_PI/2-c.angle));
00376 }
00377 
00384 void pln_circ2form(struct pln_circle circle, struct pln_fquad_2var *form)
00385 {
00386         form->ax = 1;
00387         form->bx = 2 * -circle.x0;
00388         form->cx = POWER(circle.x0);
00389         form->ay = 1;
00390         form->by = 2 * -circle.y0;
00391         form->cy = POWER(circle.y0);
00392         form->rs = POWER(circle.radius) - (form->cx + form->cy);
00393 #if DEBUG>=3
00394         printf("pln_circ2form(): %f*X2 %f*X (%f) %f*Y2 %f*Y (%f) = %f\n",
00395                         form->ax, form->bx, form->cx, 
00396                         form->ay, form->by, form->cy, form->rs);
00397 #endif
00398 }
00399 
00406 void pln_get_position(struct pln_angle_state as, struct pln_pos_state *pos)
00407 {
00408         struct pln_circ cir1, cir2;
00409         struct pln_circle circle1, circle2;
00410         struct pln_fquad_2var form1, form2;
00411         struct pln_point sol1, sol2, cp;
00412         double dist1, dist2;
00413 
00414         /* get circle from 1 known angles and 3 known points */
00415         cir1.pl = R3;
00416         cir1.pc = L;
00417         cir1.pr = R2;
00418         cir1.angle = as.alfa;
00419 
00420         /*cir1.pl = K;
00421         cir1.pc = H;
00422         cir1.pr = C;
00423         cir1.angle = as.beta;*/
00424 
00425         /* if the angle is close to PI, there will be many uncertainties so
00426          * use the second side to correct this error */
00427 #ifdef USE_RED_REFLECTORS
00428         if (evaluate_gaussian(as.gama-M_PI, 0.4) < 0.8) {
00429 #else
00430         if (evaluate_gaussian(as.beta-M_PI, 0.4) < 0.8) {
00431 #endif
00432                 cir2.pl = R1;
00433                 cir2.pc = H;
00434                 cir2.pr = R3;
00435                 cp = R3;
00436 #ifdef USE_RED_REFLECTORS
00437                 cir2.angle = as.gama;
00438 #else
00439                 cir2.angle = as.beta;
00440 #endif
00441         } else {
00442                 cir2.pl = R1;
00443                 cir2.pc = G;
00444                 cir2.pr = R2;
00445                 cp = R2;
00446 #ifdef USE_RED_REFLECTORS
00447                 cir2.angle = as.beta;
00448 #else
00449                 cir2.angle = as.gama;
00450 #endif
00451         }
00452 
00453         /* collective point */
00454         /*cp = C;
00455         cp = B;
00456         cp = K;*/
00457 
00458         /* get circles, those cross points intersect the position we are
00459          * looking for */
00460         pln_get_circle(cir1, &circle1);
00461         pln_get_circle(cir2, &circle2);
00462 
00463 #if DEBUG>=3
00464         printf("pln_get_position(): circle 1: angle=%f "
00465                         "center[%f,%f] radius=%f\n",
00466                         DEGREES(cir1.angle), circle1.x0, 
00467                         circle1.y0, circle1.radius);
00468         printf("pln_get_position(): circle 2: angle=%f "
00469                         "center[%f,%f] radius=%f\n",
00470                         DEGREES(cir2.angle), circle2.x0, 
00471                         circle2.y0, circle2.radius);
00472 #endif
00473 
00474         /* get quadratic formular from the circle parameters */
00475         pln_circ2form(circle1, &form1);
00476         pln_circ2form(circle2, &form2);
00477         /* solve the equation */
00478         pln_solve_2quad(form1, form2, &sol1, &sol2);
00479 
00480 #if DEBUG>=3
00481         printf("pln_get_position(): [x1=%f;y1=%f] [x2=%f;y2=%f]\n", 
00482                         sol1.x, sol1.y, sol2.x, sol2.y);
00483 #endif
00484 
00485         /* evaluate possible cross points and eliminate the known point from
00486          * two solutions */
00487         dist1 = fabs(sqrt(POWER(sol1.x-cp.x) + POWER(sol1.y-cp.y)));
00488         dist2 = fabs(sqrt(POWER(sol2.x-cp.x) + POWER(sol2.y-cp.y)));
00489 
00490         if (evaluate_gaussian(dist1, 0.4) > 0.5) {
00491                 pos->x = lround(sol2.x);
00492                 pos->y = lround(sol2.y);
00493         } else {
00494                 pos->x = lround(sol1.x);
00495                 pos->y = lround(sol1.y);
00496         }
00497 }
00498 
00502 void pln_set_points()
00503 {
00504         /* fixed known points */
00505         SET_POINT_A(A);
00506         SET_POINT_B(B);
00507         SET_POINT_C(C);
00508         SET_POINT_E(E);
00509         SET_POINT_F(F);
00510         SET_POINT_G(G);
00511         SET_POINT_H(H);
00512         SET_POINT_K(K);
00513         SET_POINT_L(L);
00514         SET_POINT_R1(R1);
00515         SET_POINT_R2(R2);
00516         SET_POINT_R3(R3);
00517 
00518 #if DEBUG>=3
00519         printf("pln_set_points():\n");
00520         printf("A.x = %f; A.y = %f\n", A.x, A.y);
00521         printf("B.x = %f; B.y = %f\n", B.x, B.y);
00522         printf("C.x = %f; C.y = %f\n", C.x, C.y);
00523         printf("E.x = %f; E.y = %f\n", E.x, E.y);
00524         printf("F.x = %f; F.y = %f\n", F.x, F.y);
00525         printf("G.x = %f; G.y = %f\n", G.x, G.y);
00526         printf("H.x = %f; H.y = %f\n", H.x, H.y);
00527         printf("K.x = %f; K.y = %f\n", K.x, K.y);
00528         printf("L.x = %f; L.y = %f\n", L.x, L.y);
00529         printf("R1.x = %f; R1.y = %f\n", R1.x, R1.y);
00530         printf("R2.x = %f; R2.y = %f\n", R2.x, R2.y);
00531         printf("R3.x = %f; R3.y = %f\n", R3.x, R3.y);
00532 #endif
00533 }
00534 
00538 int cmpi(const void *a, const void *b)
00539 {
00540         return ((int)*(int*)a > (int)*(int*)b);
00541 }
00542 
00546 int cmpd(const void *a, const void *b)
00547 {
00548         return ((double)*(double*)a > (double)*(double*)b);
00549 }
00550 
00554 int cmpang(const void *a, const void *b)
00555 {
00556         return ((double)(((struct pln_angle_eval *)a)->eval) <
00557                         (double)(((struct pln_angle_eval *)b)->eval));
00558 }
00559 
00566 void pln_pos2ang(struct pln_pos_state ps, struct pln_aangle_state *aas)
00567 {
00568         double a1, a2, a3, angles[3];
00569 
00570 #ifdef USE_RED_REFLECTORS
00571         ps.head += M_PI;
00572 #endif
00573         /* angles between 0 and reflectors (with center at robot position) */
00574         a1 = atan2(R1.y - ps.y, R1.x - ps.x);
00575         a2 = atan2(R2.y - ps.y, R2.x - ps.x);
00576         a3 = atan2(R3.y - ps.y, R3.x - ps.x);
00577 
00578         a1 = (a1 < 0) ? 2*M_PI + a1 : a1;
00579         a2 = (a2 < 0) ? 2*M_PI + a2 : a2;
00580         a3 = (a3 < 0) ? 2*M_PI + a3 : a3;
00581         ps.head = (ps.head < 0) ? 2*M_PI + ps.head : ps.head;
00582 
00583         /* offset to the head angle */
00584         angles[0] = (a1-ps.head < 0) ? 2*M_PI+a1-ps.head : a1-ps.head;
00585         angles[1] = (a2-ps.head < 0) ? 2*M_PI+a2-ps.head : a2-ps.head;
00586         angles[2] = (a3-ps.head < 0) ? 2*M_PI+a3-ps.head : a3-ps.head;
00587 
00588         /* sort and store results */
00589         qsort(angles, 3, sizeof(double), cmpd);
00590         aas->theta[0] = angles[0];
00591         aas->theta[1] = angles[1];
00592         aas->theta[2] = angles[2];
00593         aas->head = ps.head;
00594 }
00595 
00603 void test_angles(struct pln_point *positions, int *poscount)
00604 {
00605         struct pln_pos_state ps, cpos;
00606         struct pln_aangle_state aas;
00607         struct pln_angle_state as;
00608         int i, j;
00609 
00610         /* set fixed points */
00611         pln_set_points();
00612 
00613         /* range of position */
00614         for (j=1; j<FHEIGHT-1; j+=10) {
00615                 for (i=1; i<FWIDTH-1; i+=10) {
00616                         /* convert the position to angles */
00617                         ps.x = i;
00618                         ps.y = j;
00619 
00620                         ps.head = DEG2RAD(0);
00621                         pln_pos2ang(ps, &aas);
00622 
00623                         /*printf("theta[0]=%f theta[1]=%f theta[2]=%f\n", 
00624                                 DEGREES(aas.theta[0]), DEGREES(aas.theta[1]), 
00625                                 DEGREES(aas.theta[2]));*/
00626 
00627                         as.beta = aas.theta[1] - aas.theta[0];
00628                         as.gama = aas.theta[2] - aas.theta[1];
00629                         as.alfa = 2*M_PI - as.beta - as.gama;
00630                         /*printf("alfa=%f; beta=%f; gama=%f\n", 
00631                                 DEGREES(as.alfa), DEGREES(as.beta), 
00632                                 DEGREES(as.gama));*/
00633 
00634                         /* get position from measured angles */
00635                         pln_get_position(as, &cpos);
00636                         /*printf("robot=[x=%d;y=%d]\n", 
00637                                         (int)cpos.x, (int)cpos.y);*/
00638 
00639                         /*if (cpos.x != ps.x || cpos.y != ps.y) {*/
00640                         if (cpos.x == ps.x && cpos.y == ps.y) {
00641                                 /*printf("[ %f ; %f ] => [ %f ; %f ]\n\n", 
00642                                 ps.x, ps.y, cpos.x, cpos.y);*/
00643                                 positions[(*poscount)].x = ps.x;
00644                                 positions[(*poscount)].y = ps.y;
00645                                 (*poscount)++;
00646                         }
00647                 }
00648         }
00649         printf("\n");
00650 }
00651 
00661 void pln_coordinate(struct pln_pos_state estpos, struct pln_aangle_state aas, 
00662                         struct pln_angle_state *as)
00663 {
00664         struct pln_aangle_state aas0;
00665         struct pln_angle_state _as0, _as;
00666         double head;
00667         double _angles[3], __angles[3];;
00668         struct pln_angle_eval angeval[3];
00669         int i, j;
00670 
00671         /* convert the estimated position to angles with head=0. Angles are 
00672          * absolute from robot`s head */
00673         head = estpos.head;
00674         estpos.head = DEG2RAD(0);
00675         pln_pos2ang(estpos, &aas0);
00676         estpos.head = head;
00677 
00678         /* count angles between reflectors */
00679         aangle2angle(aas0, &_as0);
00680         aangle2angle(aas, &_as);
00681 
00682         /* temporary variables */
00683         _angles[0] = _as0.alfa;
00684         _angles[1] = _as0.beta;
00685         _angles[2] = _as0.gama;
00686         angeval[0].angle = _as.alfa;
00687         angeval[1].angle = _as.beta;
00688         angeval[2].angle = _as.gama;
00689 
00690         /* evaluation, select angles depending to it`s probability. Decrease
00691          * sigma value of gaussian evaluation function to decrease the 
00692          * accepted range */
00693         for (j=0; j<3; j++) {
00694                 for (i=0; i<3; i++) {
00695                         angeval[i].eval = evaluate_gaussian(
00696                                 angeval[i].angle - _angles[j], 0.1);
00697                 }
00698                 /* sort evaluated angles */
00699                 qsort(angeval, 3, sizeof(struct pln_angle_eval), cmpang);
00700                 /* if the first one has a specific probability, use it. If 
00701                  * it differentiates too much, use rather the estimated 
00702                  * value */
00703                 __angles[j] = (angeval[0].eval<0.5) ? 
00704                                 _angles[j] : angeval[0].angle;
00705         }
00706         /* the results */
00707         as->alfa = __angles[0];
00708         as->beta = __angles[1];
00709         as->gama = __angles[2];
00710 }
00711 
00716 void test_coordination()
00717 {
00718         struct pln_pos_state estpos;
00719         struct pln_aangle_state aas;
00720         struct pln_angle_state as;
00721         int i, j;
00722 
00723         /* set fixed points */
00724         pln_set_points();
00725 
00726         /* estimated position */
00727         estpos.x = 500;
00728         estpos.y = 1600;
00729         estpos.head = DEG2RAD(180);
00730         /* measured times (after selections) */
00731         /*aas.theta[0] = DEG2RAD(47.726);
00732         aas.theta[1] = DEG2RAD(147.387);
00733         aas.theta[2] = DEG2RAD(191.302);*/
00734         /* used to test if we use red reflectors */
00735         /*aas.theta[0] = DEG2RAD(72.645);
00736         aas.theta[1] = DEG2RAD(167.592);
00737         aas.theta[2] = DEG2RAD(315.000);*/
00738 
00739         /*  */
00740         for (i=0; i<360; i++) {
00741                 estpos.head = DEG2RAD(i);
00742                 pln_pos2ang(estpos, &aas);
00743                 pln_coordinate(estpos, aas, &as);
00744                 printf("head=%f alfa=%f beta=%f gama=%f\n", 
00745                         DEGREES(estpos.head), DEGREES(as.alfa), 
00746                         DEGREES(as.beta), DEGREES(as.gama));
00747         }
00748 }
00749 
00759 void pln_sel_angles(struct pln_pos_state estpos, double *angles, 
00760                         int angcount, struct pln_aangle_state *maas)
00761 {
00762         struct pln_aangle_state aas;
00763         struct pln_angle_eval angeval[angcount];
00764         double eval1, eval2, sgn;
00765         int i, j;
00766 
00767         /* convert the estimated position to angles. Angles are absolute to 
00768          * the robot`s head */
00769         pln_pos2ang(estpos, &aas);
00770         
00771 #if DEBUG>=1
00772         printf("pln_sel_angles(): estpos: %f %f %f %f\n",
00773                         DEGREES(aas.theta[0]),
00774                         DEGREES(aas.theta[1]),
00775                         DEGREES(aas.theta[2]),
00776                         DEGREES(aas.head));
00777 #endif
00778 
00779         /* evaluation, select angles depending to it`s probability. Decrease
00780          * sigma value of gaussian evaluation function to decrease the 
00781          * accepted range */
00782         for (j=0; j<3; j++) {
00783                 if ((aas.theta[j] < DEG2RAD(5)) 
00784                         || (2*M_PI-aas.theta[j] < DEG2RAD(5))) {
00785                         for (i=0; i<angcount; i++) {
00786                                 if (angles[i] < M_PI)
00787                                         sgn = 1;
00788                                 else 
00789                                         sgn = -1;
00790                                 eval1 = evaluate_gaussian(
00791                                                 aas.theta[j]-angles[i], 0.1);
00792                                 eval2 = evaluate_gaussian(
00793                                                 aas.theta[j] -
00794                                                 (angles[i] + sgn*2*M_PI), 0.1);
00795 #if DEBUG>=2
00796                                 printf("angle=%f sgn=%f %f %f %f %f\n", 
00797                                         DEGREES(angles[i]), 
00798                                         sgn,
00799                                         DEGREES(aas.theta[j]-angles[i]), 
00800                                         DEGREES(aas.theta[j]-
00801                                                 (angles[i] + sgn*2*M_PI)),
00802                                         eval1, eval2);
00803 #endif
00804                                 angeval[i].eval = (eval1>eval2) ? eval1:eval2;
00805                                 angeval[i].angle = angles[i];
00806 #if DEBUG>=2
00807                                 printf("%f %f: ", aas.theta[j], angles[i]);
00808                                 printf("%f %f\n", aas.theta[j]-angles[i], 
00809                                         evaluate_gaussian(aas.theta[j]-angles[i], 
00810                                                                 0.1));
00811                                 printf("gauss=%f %f\n", -0.006645, 
00812                                         evaluate_gaussian(-0.006645, 0.1));
00813 #endif
00814                         }
00815                 } else {
00816                         for (i=0; i<angcount; i++) {
00817                                 angeval[i].angle = angles[i];
00818                                 angeval[i].eval = 
00819                                         evaluate_gaussian(aas.theta[j]-angles[i], 
00820                                         0.1);
00821 #if DEBUG>=2
00822                                 printf("%f %f: ", aas.theta[j], angles[i]);
00823                                 printf("%f %f\n", aas.theta[j]-angles[i], 
00824                                         evaluate_gaussian(aas.theta[j]-angles[i], 
00825                                         0.1));
00826                                 printf("gauss=%f %f\n", -0.006645, 
00827                                         evaluate_gaussian(-0.006645, 0.1));
00828 #endif
00829                         }
00830                 }
00831                 /* sort evaluated angles */
00832                 qsort(angeval,angcount,sizeof(struct pln_angle_eval),cmpang);
00833                 /* if the first one has a specific probability, use it. If 
00834                  * it differentiates too much, use rather the estimated 
00835                  * value */
00836                 maas->theta[j] = (angeval[0].eval<2.7) ? 
00837                                         aas.theta[j] : angeval[0].angle;
00838         }
00839 }
00840 
00845 void test_sel_angles()
00846 {
00847         struct pln_pos_state estpos;
00848         struct pln_aangle_state maas;
00849         double angles[10] = {   DEG2RAD(  5.318970),
00850                                 DEG2RAD( 50.306396),
00851                                 DEG2RAD(101.881714),
00852                                 DEG2RAD(125.046387),
00853                                 DEG2RAD(135.726311),
00854                                 DEG2RAD(208.531494),
00855                                 DEG2RAD(354.326782),
00856                                 DEG2RAD(225.380757),
00857                                 DEG2RAD(281.309932),
00858                                 DEG2RAD(320.819946) };
00859         int i;
00860 
00861         /* set fixed points */
00862         pln_set_points();
00863 
00864         /* estimated position */
00865         estpos.x = 500;
00866         estpos.y = 1600;
00867         estpos.head = DEG2RAD(11);
00868 
00869         /*
00870         for (i=0; i<10; i++)
00871                 angles[i] = TIME2ANGLE(65536, (double)(rand() % 65536));
00872         angles[0] = DEG2RAD(135.726311);
00873         angles[5] = DEG2RAD(225.380757);
00874         angles[9] = DEG2RAD(281.309932);*/
00875         qsort(angles, 10, sizeof(double), cmpd);
00876 
00877         printf("angles: ");
00878         for (i=0; i<10; i++)
00879                 printf("%f ", DEGREES(angles[i]));
00880         printf("\n");
00881 
00882         /* select angles */
00883         pln_sel_angles(estpos, angles, 10, &maas);
00884 
00885         printf("selected angles: ");
00886         for(i=0; i<3; i++)
00887                 printf("%f ", DEGREES(maas.theta[i]));
00888         printf("\n");
00889 }
00890 
00900 void pln_cal_position(unsigned int *times, unsigned int timecnt, 
00901                         struct pln_pos_state act_pos, 
00902                         struct pln_pos_state *est_pos)
00903 {
00904         struct pln_aangle_state maas;
00905         struct pln_angle_state as;
00906         double angles[10];
00907         int i;
00908 
00909         /* convert times to angles */
00910         for (i=0; i<timecnt-1; i++)
00911                 angles[i] = TIME2ANGLE(times[0], times[i+1]);
00912 
00913 #if DEBUG>=1
00914         printf("pln_cal_position(): angles: ");
00915         for (i=0; i<timecnt-1; i++)
00916                 printf("%f ", DEGREES(angles[i]));
00917         printf("\n");
00918 #endif
00919 
00920         /* select angles */
00921         pln_sel_angles(act_pos, angles, timecnt-1, &maas);
00922 
00923 #if DEBUG>=1
00924         printf("pln_cal_position(): selected angles: ");
00925         for(i=0; i<3; i++)
00926                 printf("%f ", DEGREES(maas.theta[i]));
00927         printf("\n");
00928 #endif
00929 
00930         /* coordinate angles */
00931         pln_coordinate(act_pos, maas, &as);
00932 
00933 #if DEBUG>=1
00934         printf("pln_cal_position(): head=%f alfa=%f beta=%f gama=%f\n", 
00935                 DEGREES(act_pos.head), DEGREES(as.alfa), 
00936                 DEGREES(as.beta), DEGREES(as.gama));
00937 #endif
00938 
00939         /* calculate position */
00940         pln_get_position(as, est_pos);
00941 }
00942 
00950 void test_cal_position(struct pln_point *positions, int *poscount)
00951 {
00952         struct pln_pos_state act_pos;
00953         struct pln_pos_state est_pos;
00954         unsigned int times[] = { 54619, 1714, 12312, 34549, 41231, 49670};
00955 
00956         /* set fixed points */
00957         pln_set_points();
00958 
00959         /* actual position */
00960         act_pos.x = 500;
00961         act_pos.y = 1600;
00962         act_pos.head = DEG2RAD(0);
00963 
00964         /* calculated measured position */
00965         pln_cal_position(times, sizeof(times)/sizeof(unsigned int), 
00966                                 act_pos, &est_pos);
00967         printf("calculated posititon: [x=%f,y=%f]\n", est_pos.x, est_pos.y);
00968 
00969         positions[(*poscount)].x = est_pos.x;
00970         positions[(*poscount)].y = est_pos.y;
00971         (*poscount)++;
00972 }

Generated on Thu Sep 13 11:28:28 2007 for DCE-Eurobot by  doxygen 1.5.3