#include "control.h" #include #include #include struct angle { double a; int c; }; typedef struct angle angle; gint cmp_angle(gconstpointer _a, gconstpointer _b, gpointer p) { const angle *a = (const angle*) _a, *b = (const angle*) _b; UNUSED(p); return (a->a == b->a) ? 0 : (a->a < b->a) ? -1 : 1; } void angle_free(angle* a) { g_slice_free(angle, a); } angle* angle_new(double a, int c) { angle *x = g_slice_new(angle); x->a = a; x->c = c; return x; } static double fixangle(double a) { while (a < -180) a += 360; while (a > 180) a -= 360; return a; } void goradar(trial *t) { vehicle v; telemetry *tm; GSequence *angles = g_sequence_new((GDestroyNotify) angle_free); GSequenceIter *prev, *cur, *end; angle *acur, *aprev; double hang, ang = 1000, weight = 0; int c; guint i; v = t->sim.tm.vehicle; hang = atan2(-v.y, -v.x)*180/M_PI; tm = &t->sim.tm; g_sequence_insert_sorted(angles, angle_new(-45, 0), cmp_angle, NULL); g_sequence_insert_sorted(angles, angle_new(45, 0), cmp_angle, NULL); for (i = 0; i < tm->objects->len; i++) { object *o = &g_array_index(tm->objects, object, i); double phi, phi2, avoid = 0, oangle; double distance = sqrt((o->y - v.y) * (o->y - v.y) + (o->x - v.x) * (o->x - v.x)); oangle = fixangle(atan2(-o->y, -o->x)*180/M_PI - hang); if (fabs(oangle) > 180) continue; // if (distance > 100) continue; phi = fixangle(atan2(o->y - v.y, o->x - v.x)*180/M_PI - hang); if (fabs(phi) > 45) continue; switch (o->type) { case BOLDER: avoid = 1.2 * o->rad + VEHICLE_RADIUS; break; case CRATER: avoid = 1.2 * o->rad + VEHICLE_RADIUS + 1; break; case MARTIAN: avoid = o->rad + VEHICLE_RADIUS + 5; break; } phi2 = atan(avoid / distance )*180/M_PI; g_sequence_insert_sorted(angles, angle_new(phi - phi2, 1), cmp_angle, NULL); g_sequence_insert_sorted(angles, angle_new(phi + phi2, -1), cmp_angle, NULL); } prev = g_sequence_get_begin_iter(angles), end = g_sequence_get_end_iter(angles); if (prev != end) { aprev = (angle*) g_sequence_get(prev); c = aprev->c; while ((cur = g_sequence_iter_next(prev)) != end) { acur = (angle*) g_sequence_get(cur); assert(aprev->a <= acur->a); if (!c) { // fprintf(stderr, "Gap between %f and %f\n", aprev->a, acur->a); if (acur->a - aprev->a > 1) { double ax, ad, w1 = 1E20, w2 = 1E20, w; if (aprev->a <= 0) { if (acur->a <= 0) { ax = acur->a; } else { ax = 0; } } else { ax = aprev->a; } if (ax != 0) w1 = 1/fabs(ax); ad = fixangle(ax - v.dir + hang); if (ad != 0) w2 = 1/fabs(ad); w = w1+w2; if (w > weight) { fprintf(stderr, "Selected %f\n", ax); ang = ax; weight = w; } } } c += acur->c; prev = cur; aprev = acur; } } if (weight == 0) { fprintf(stderr, "Potential\n"); godown(t); return; } ang = fixangle(ang - v.dir + hang); fprintf(stderr, "Angle: %f, objects: %u\n", ang, tm->objects->len); if (ang < 1) { if (ang < -50) { vehicle_hard_right(t); } else { vehicle_right(t); } } else if (ang > 1) { if (ang > 50) { vehicle_hard_left(t); } else { vehicle_left(t); } } ang = fabs(ang); if (ang > 90) { vehicle_break(t); } else if (ang > 45) { vehicle_roll(t); } else { vehicle_accel(t); } }