// // tracker.c // pete february 2006 // a first pass at code to implement the tracking filter described in Essay 2- Radar Autotracking // #include #include #include #include typedef struct { float r, // measured range theta, // measured angle t, // time of measurement e_r; // std dev of error at range 1 } Measure; typedef struct { int id, // target number init; // state 0, 1, 2 long measurements; // number of measurements on this target float x, // estimated position y, t, // at time s, // estimated speed phi, // course v_x, // error in along-track position ('std dev') v_y, // in across v_s, // in speed v_phi, // in course t0; // time of first measurement } Track; FILE * logfile; float speed, course; // globals holding current real speed and course // ------------------------- get_alpha ------------------------ static float get_alpha(float v_e, float v_m, float ta, float p, float m) { // v_e is the std deviation of the estimate, v_m of the measurement // ta is the ratio of this measurement interval to the average // p is predicted position, m is measured position // compute the weighting factor // when the error is within one nominal std deviation of the sensor's accuracy // we do simple variance-combining. // when it's bigger, we first compute alpha normally, and then jack it up by an amount // dependent on the error size float alpha, err, a; // first compute alpha, the weighting factor // a bigger alpha indicates a larger confidence in the measurement v_e = v_e * ta; // shrink v_e if shorter interval than usual alpha = v_e/sqrt((v_e * v_e) + (v_m * v_m)); // now compute err, the relative positional error err = (m - p)/(1.25 * v_m); if (err < 0) err = -err; printf("\n\talpha=%.2f; m=%.2f p=%.2f v_e=%.2f v_m=%.2f; error is %.2f sensor bars", alpha, m, p, v_e, v_m, err); if (err > 1.0) { // our measurement is further away than we can account for by sensor accuracy... alpha = 1.0 - ((1.0 - alpha)/err); // move alpha closer to 1 as error gets larger printf("\n\t::alpha corrected to %.2f", alpha); } return alpha; } // ------------------------- tracker -------------------------- static void tracker(Track * t, Measure * m) { // updates the provided Track with the provided Measurements float xm, ym, tm, dx, dy, dt, s, phi, e_x; float ta, psi, delta, D, Xm, Ym, Xp, Yp, Xe, Ye, Sm, Phi_m, Se, Phi_e, dPhi, De, alpha_x, alpha_y, beta_x, beta_y; // first transform from polar to cartesian xm = (m->r * cos(m->theta)); ym = (m->r * sin(m->theta)); tm = m->t; e_x = m->e_r; // measurement error scaled already printf("\n\nmeasure:r=%.2f theta=%.2f", m->r, m->theta); printf("\n\tcart:xm=%.2f y=%.2f t=%.2f", xm, ym, tm); switch (t->init) { case 0: // new track printf("\n\t**new track."); t->init = 1; t->x = xm; // start off at measured position t->y = ym; t->t = tm; t->s = 0; t->phi = 0; t->v_x = 0; // set initial variances to be large t->v_y = 0; t->v_s = 0; t->v_phi = 0; t->t0 = tm; break; case 1: // second measurement - compute initial course and speed printf("\n\t**estimate velocity."); t->init = 2; (t->measurements)++; dx = xm - t->x; dy = ym - t->y; dt = tm - t->t; // course = arctan dy/dx t->x = xm; t->y = ym; t->phi = atan(dy/dx); t->s= dx/(cos(t->phi) * dt); t->t = tm; t->v_x= e_x; t->v_y = e_x; t->v_s = e_x/dt; t->v_phi = e_x/dt; t->measurements=2; break; case 2: // declare simply - compiler sorts it out.. dx = xm - t->x; dy = ym - t->y; dt = tm - t->t; printf("\n\tdx=%.2f dy=%.2f dt=%.2f", dx, dy, dt); psi = atan(dy/dx); // apparent course since last measurement delta = psi - t->phi; // difference in course printf("\n\tpsi=%.2f old_phi=%.2f delta=%.2f", psi, t->phi, delta); D = sqrt((dx * dx) + (dy * dy));// distance gone between measurements Xm = D * cos(delta); // distance gone along track Ym = D * sin(delta); // distance gone across track printf("\n\tXm=%.2f Ym=%.2f", Xm, Ym); Xp = t->s * dt; // predicted distance along track // compute ratio of this measurement interval to average time between measurements ta = ((tm - t->t0)/t->measurements); ta = (tm - t->t)/ta; // compute new estimate of along-track position Xe // (we'll do the adpative stuff later) alpha_x = get_alpha(t->v_x, e_x, ta, Xp, Xm); Xe = (1.0 - alpha_x) * Xp + (alpha_x * Xm); printf("\n\talpha_x=%.3f Xp=%.2f Xe=%.2f ta=%.2f", alpha_x, Xp, Xe, ta); t->v_x = alpha_x * e_x; // compute new estimate of along-track positional error // compute new estimate of across-track position Ye alpha_y = get_alpha(t->v_y, e_x, ta, 0, Ym); Ye = alpha_y * Ym; printf("\n\talpha_y=%.3f Ye=%.2f", alpha_y, Ye); t->v_y = (1.0 - alpha_y) * e_x; // compute new estimate of across-track positional error // compute 'measured' course from Ye, Xe dPhi = atan(Ye/Xe); Phi_m = t->phi + dPhi; // course = old course + error in course printf("\n\tdPhi=%.2f phi=%2.f Phi_m= %.2f", dPhi, t->phi, Phi_m); // compute 'measured' speed from Xe and course error Sm = (Xe/cos(dPhi))/dt; printf("\n\tphi_m=%.2f s_m=%.2f", Phi_m, Sm); // compute weighting factors for speed, course beta_x = alpha_x * sqrt(alpha_x); beta_y = alpha_y * sqrt(alpha_y); t->s = (1.0 - beta_x) * t->s + beta_x * Sm; t->phi = ((1.0 - beta_y) * t->phi) + beta_y * Phi_m; t->v_s = beta_x * (e_x/dt); t->v_phi = beta_y * (e_x/dt); // compute new cartesian coordinates of target De = sqrt((Xe * Xe) + (Ye * Ye)); // estimated distance gone t->x = t->x + De * cos(Phi_m); t->y = t->y + De * sin(Phi_m); t->t = tm; printf("\n\tDe=%.2f, X=%.2f Y=%.2f", De, t->x, t->y); (t->measurements)++; break; } printf("\n%.1f::t[%d] (%.2f, %.2f) s=%.2f c=%.2f\n\t\tdX=%.2f dY=%.2f dS=%.2f dC=%.2f", t->t, t->id, t->x, t->y, t->s, t->phi, t->v_x, t->v_y, t -> v_s, t->v_phi); } // -------------------------- init_target ------------------------- static void init_target(Track * target, int id) { target -> id = id; target -> init = 0; target -> x = 0; target -> y = 0; target -> t = 0; target -> s = 0; target -> phi = 0; target -> v_x = 0; target -> v_y = 0; target -> v_s = 0; target -> v_phi = 0; } typedef struct { float x, y, s, c, t, dt, v_e; } Sense; // -------------------------- position ------------------------- static void position(int n, Track * t, Measure * m, Sense * s) { // compute n measurements for track t starting with given position and velocity float x, y, sp, c, xm, ym, xdot, ydot, r, theta, T, dt, end, v_e; x = s -> x; y = s -> y; sp = s -> s; c = s -> c; xdot = sp * cos(c); ydot = sp * sin(c); T = s -> t; dt = s -> dt; v_e = s -> v_e; while (n-- > 0) { float ex = 0.0, ey= 0.0; // error fractions // compute new position x = x + (xdot * dt); y = y + (ydot * dt); T = T + dt; r = sqrt((x * x) + (y * y)); m->e_r = r * v_e; // ok, we have an error square; perturb the measurements within that chunk ex = ((rand() % 100) - 50)/100.0; // a signed fraction of the errbox ey = ((rand() % 100) - 50)/100.0; xm = x + (ex * m->e_r); ym = y + (ey * m->e_r); printf("\n\t::T=%.2f x=%.2f y=%.2f", T, x, y); // write the measurements m->r = sqrt((xm * xm) + (ym * ym)); m->theta = atan(ym/xm); m->t = T; fprintf(logfile, "\n%0.2f\t%.2f\t%.2f\t%.2f\t%0.2f\t%.2f\t%.2f\t%.2f\t%0.2f\t%.2f\t%.2f\t%.2f\t", T, xm, T, ym, T, t->s, T, t->phi, T, speed, T, course); tracker(t, m); } // update sensor with current data s -> x = xm; s -> y = ym; s -> t = T; } // ------------------------- main ------------------------------- int main(void) { Track target; Measure m; Sense s; float x, y, sp, c; printf ("\n autotracker 1.0"); logfile = fopen("1.track", "w"); fprintf(logfile, "xm\t\tym\t\tspeed est\t\tcourse est\t\tspeed\t\tcourse"); init_target(&target, 0); speed = 10; course = 1.3; s.t = 0; s.x = 100; s.y = 50; s.c = course; s.s = speed; s.dt = 5; s.v_e = 0.0003; // measurement error of 0.03 at range 1 printf("\nnow at x=%.2f y=%.2f time = %.2f", s.x, s.y, s.t); printf("\n\n********** speed=%.2f course=%.2f ******************\n\n", s.s, s.c); position(10, &target, &m, &s); printf("\nnow at x=%.2f y=%.2f time = %.2f", s.x, s.y, s.t); // ok, now change his course while keeping speed the same course = .90; s.c = course; printf("\n\n********** speed=%.2f course=%.2f ******************\n\n", s.s, s.c); position(5, &target, &m, &s); printf("\nnow at x=%.2f y=%.2f time = %.2f", s.x, s.y, s.t); course = .75; s.c = course; printf("\n\n********** speed=%.2f course=%.2f ******************\n\n", s.s, s.c); position(5, &target, &m, &s); printf("\nnow at x=%.2f y=%.2f time = %.2f", s.x, s.y, s.t); course = 0.95; s.c = course; printf("\n\n********** speed=%.2f course=%.2f ******************\n\n", s.s, s.c); position(5, &target, &m, &s); // ok, now change his speed while keeping course the same printf("\nnow at x=%.2f y=%.2f time = %.2f", s.x, s.y, s.t); speed = 12; s.s = speed; printf("\n\n********** speed=%.2f course=%.2f ******************\n\n", s.s, s.c); position(5, &target, &m, &s); // ok, now change his speed while keeping course the same printf("\nnow at x=%.2f y=%.2f time = %.2f", s.x, s.y, s.t); speed = 15; s.s = speed; printf("\n\n********** speed=%.2f course=%.2f ******************\n\n", s.s, s.c); position(5, &target, &m, &s); // ok, now change his speed and course printf("\nnow at x=%.2f y=%.2f time = %.2f", s.x, s.y, s.t); speed = 10; course = 1.25; s.s = speed; s.c = course; printf("\n\n********** speed=%.2f course=%.2f ******************\n\n", s.s, s.c); position(5, &target, &m, &s); fclose(logfile); printf("\n\n************ autotracker done ****************\n"); return 0; }