diff --git a/dump1090.c b/dump1090.c index 32e567b..781fc2d 100644 --- a/dump1090.c +++ b/dump1090.c @@ -702,6 +702,7 @@ void showHelp(void) { "--aggressive More CPU for more messages (two bits fixes, ...)\n" "--mlat display raw messages in Beast ascii mode\n" "--stats With --ifile print stats at exit. No other output\n" +"--stats-range Collect/show range histogram\n" "--stats-every Show and reset stats every seconds\n" "--onlyaddr Show only ICAO addresses (testing purposes)\n" "--metric Use metric units (meters, km/h, ...)\n" @@ -1032,6 +1033,8 @@ int main(int argc, char **argv) { } else if (!strcmp(argv[j],"--stats")) { if (!Modes.stats) Modes.stats = (uint64_t)1 << 60; // "never" + } else if (!strcmp(argv[j],"--stats-range")) { + Modes.stats_range_histo = 1; } else if (!strcmp(argv[j],"--stats-every") && more) { Modes.stats = (uint64_t) (1000 * atof(argv[++j])); } else if (!strcmp(argv[j],"--snip") && more) { diff --git a/dump1090.h b/dump1090.h index 12701f8..fc81eb0 100644 --- a/dump1090.h +++ b/dump1090.h @@ -332,6 +332,7 @@ struct { // Internal state int interactive_rows; // Interactive mode: max number of rows uint64_t interactive_display_ttl;// Interactive mode: TTL display uint64_t stats; // Interval (millis) between stats dumps, + int stats_range_histo; // Collect/show a range histogram? int onlyaddr; // Print only ICAO addresses int metric; // Use metric units int mlat; // Use Beast ascii format for raw data output, i.e. @...; iso *...; diff --git a/stats.c b/stats.c index 8c47732..92f0dfa 100644 --- a/stats.c +++ b/stats.c @@ -57,6 +57,8 @@ void add_timespecs(const struct timespec *x, const struct timespec *y, struct ti z->tv_nsec = z->tv_nsec % 1000000000L; } +static void display_range_histogram(struct stats *st); + void display_stats(struct stats *st) { int j; time_t tt_start, tt_end; @@ -172,10 +174,79 @@ void display_stats(struct stats *st) { (unsigned long long) background_cpu_millis); } + if (Modes.stats_range_histo) + display_range_histogram(st); fflush(stdout); } +static void display_range_histogram(struct stats *st) +{ + uint32_t peak; + int i, j; + int heights[RANGE_BUCKET_COUNT]; + +#if 0 +#define NPIXELS 4 + char *pixels[NPIXELS] = { ".", "o", "O", "|" }; +#else + // UTF-8 bar symbols +#define NPIXELS 8 + char *pixels[NPIXELS] = { + "\xE2\x96\x81", + "\xE2\x96\x82", + "\xE2\x96\x83", + "\xE2\x96\x84", + "\xE2\x96\x85", + "\xE2\x96\x86", + "\xE2\x96\x87", + "\xE2\x96\x88" + }; +#endif + + printf ("Range histogram:\n\n"); + + for (i = 0, peak = 0; i < RANGE_BUCKET_COUNT; ++i) { + if (st->range_histogram[i] > peak) + peak = st->range_histogram[i]; + } + + for (i = 0; i < RANGE_BUCKET_COUNT; ++i) { + heights[i] = st->range_histogram[i] * 20.0 * NPIXELS / peak; + if (st->range_histogram[i] > 0 && heights[i] == 0) + heights[i] = 1; + } + + for (j = 0; j < 20; ++j) { + for (i = 0; i < RANGE_BUCKET_COUNT; ++i) { + int pheight = heights[i] - ((19 - j) * NPIXELS); + if (pheight <= 0) + printf(" "); + else if (pheight >= NPIXELS) + printf("%s", pixels[NPIXELS-1]); + else + printf("%s", pixels[pheight]); + } + printf("\n"); + } + + for (i = 0; i < RANGE_BUCKET_COUNT/4; ++i) { + printf("----"); + } + printf("\n"); + + for (i = 0; i < RANGE_BUCKET_COUNT/4; ++i) { + printf(" ' "); + } + printf("\n"); + + for (i = 0; i < RANGE_BUCKET_COUNT/4; ++i) { + int midpoint = round((i*4+1.5) * Modes.maxRange / RANGE_BUCKET_COUNT / 1000); + printf("%03d ", midpoint); + } + printf("km\n"); +} + void reset_stats(struct stats *st) { static struct stats st_zero; *st = st_zero; @@ -259,5 +330,8 @@ void add_stats(const struct stats *st1, const struct stats *st2, struct stats *t // aircraft target->unique_aircraft = st1->unique_aircraft + st2->unique_aircraft; target->single_message_aircraft = st1->single_message_aircraft + st2->single_message_aircraft; -} + // range histogram + for (i = 0; i < RANGE_BUCKET_COUNT; ++i) + target->range_histogram[i] = st1->range_histogram[i] + st2->range_histogram[i]; +} diff --git a/stats.h b/stats.h index 5692d08..5a5d71c 100644 --- a/stats.h +++ b/stats.h @@ -119,6 +119,10 @@ struct stats { unsigned int unique_aircraft; // we saw only a single message unsigned int single_message_aircraft; + + // range histogram +#define RANGE_BUCKET_COUNT 76 + uint32_t range_histogram[RANGE_BUCKET_COUNT]; }; void add_stats(const struct stats *st1, const struct stats *st2, struct stats *target); diff --git a/track.c b/track.c index 52896dc..efedde3 100644 --- a/track.c +++ b/track.c @@ -128,6 +128,21 @@ static double greatcircle(double lat0, double lon0, double lat1, double lon1) return 6371e3 * acos(sin(lat0) * sin(lat1) + cos(lat0) * cos(lat1) * cos(fabs(lon0 - lon1))); } +static void update_range_histogram(double lat, double lon) +{ + if (Modes.stats_range_histo && (Modes.bUserFlags & MODES_USER_LATLON_VALID)) { + double range = greatcircle(Modes.fUserLat, Modes.fUserLon, lat, lon); + int bucket = round(range / Modes.maxRange * RANGE_BUCKET_COUNT); + + if (bucket < 0) + bucket = 0; + else if (bucket >= RANGE_BUCKET_COUNT) + bucket = RANGE_BUCKET_COUNT-1; + + ++Modes.stats_current.range_histogram[bucket]; + } +} + // return true if it's OK for the aircraft to have travelled from its last known position // to a new position at (lat,lon,surface) at a time of now. static int speed_check(struct aircraft *a, struct modesMessage *mm, double lat, double lon, uint64_t now, int surface) @@ -416,6 +431,7 @@ static void updatePosition(struct aircraft *a, struct modesMessage *mm, uint64_t a->pos_nuc = new_nuc; a->seenLatLon = a->seen; + update_range_histogram(new_lat, new_lon); } }