Make aircraft tracking use milliseconds everywhere.

This commit is contained in:
Oliver Jowett 2015-02-10 21:49:37 +00:00
parent 686d433b1f
commit 7053ad02da
8 changed files with 53 additions and 57 deletions

View file

@ -876,7 +876,7 @@ int main(int argc, char **argv) {
} else if (!strcmp(argv[j],"--interactive-rows") && more) { } else if (!strcmp(argv[j],"--interactive-rows") && more) {
Modes.interactive_rows = atoi(argv[++j]); Modes.interactive_rows = atoi(argv[++j]);
} else if (!strcmp(argv[j],"--interactive-ttl") && more) { } else if (!strcmp(argv[j],"--interactive-ttl") && more) {
Modes.interactive_display_ttl = atoi(argv[++j]); Modes.interactive_display_ttl = (uint64_t)(1000 * atof(argv[++j]));
} else if (!strcmp(argv[j],"--lat") && more) { } else if (!strcmp(argv[j],"--lat") && more) {
Modes.fUserLat = atof(argv[++j]); Modes.fUserLat = atof(argv[++j]);
} else if (!strcmp(argv[j],"--lon") && more) { } else if (!strcmp(argv[j],"--lon") && more) {

View file

@ -178,7 +178,7 @@
#define MODES_INTERACTIVE_REFRESH_TIME 250 // Milliseconds #define MODES_INTERACTIVE_REFRESH_TIME 250 // Milliseconds
#define MODES_INTERACTIVE_ROWS 22 // Rows on screen #define MODES_INTERACTIVE_ROWS 22 // Rows on screen
#define MODES_INTERACTIVE_DISPLAY_TTL 60 // Delete from display after 60 seconds #define MODES_INTERACTIVE_DISPLAY_TTL 60000 // Delete from display after 60 seconds
#define MODES_NET_HEARTBEAT_INTERVAL 60 // seconds #define MODES_NET_HEARTBEAT_INTERVAL 60 // seconds
@ -316,8 +316,7 @@ struct { // Internal state
int quiet; // Suppress stdout int quiet; // Suppress stdout
int interactive; // Interactive mode int interactive; // Interactive mode
int interactive_rows; // Interactive mode: max number of rows int interactive_rows; // Interactive mode: max number of rows
int interactive_display_ttl; // Interactive mode: TTL display uint64_t interactive_display_ttl;// Interactive mode: TTL display
int interactive_delete_ttl; // Interactive mode: TTL before deletion
int stats; // Print stats at exit in --ifile mode int stats; // Print stats at exit in --ifile mode
int onlyaddr; // Print only ICAO addresses int onlyaddr; // Print only ICAO addresses
int metric; // Use metric units int metric; // Use metric units
@ -342,9 +341,6 @@ struct { // Internal state
// State tracking // State tracking
struct aircraft *aircrafts; struct aircraft *aircrafts;
// Interactive mode
uint64_t interactive_last_update; // Last screen update in milliseconds
// Statistics // Statistics
struct stats stats_current; struct stats stats_current;
struct stats stats_alltime; struct stats stats_alltime;

View file

@ -60,18 +60,19 @@
// //
void interactiveShowData(void) { void interactiveShowData(void) {
struct aircraft *a = Modes.aircrafts; struct aircraft *a = Modes.aircrafts;
time_t now = time(NULL); static uint64_t next_update;
uint64_t now = mstime();
int count = 0; int count = 0;
char progress; char progress;
char spinner[4] = "|/-\\"; char spinner[4] = "|/-\\";
// Refresh screen every (MODES_INTERACTIVE_REFRESH_TIME) miliseconde // Refresh screen every (MODES_INTERACTIVE_REFRESH_TIME) miliseconde
if ((mstime() - Modes.interactive_last_update) < MODES_INTERACTIVE_REFRESH_TIME) if (now < next_update)
{return;} return;
Modes.interactive_last_update = mstime(); next_update = now + MODES_INTERACTIVE_REFRESH_TIME;
progress = spinner[time(NULL)%4]; progress = spinner[(now/1000)%4];
#ifndef _WIN32 #ifndef _WIN32
printf("\x1b[H\x1b[2J"); // Clear the screen printf("\x1b[H\x1b[2J"); // Clear the screen
@ -129,8 +130,8 @@ void interactiveShowData(void) {
if (a->bFlags & MODES_ACFLAGS_ALTITUDE_VALID) { if (a->bFlags & MODES_ACFLAGS_ALTITUDE_VALID) {
snprintf(strFl,6,"F%03d",(altitude/100)); snprintf(strFl,6,"F%03d",(altitude/100));
} }
printf("%06x %-8s %-4s %-3s %-3s %4s %-6d %-2d\n", printf("%06x %-8s %-4s %-3s %-3s %4s %-6d %-2.0f\n",
a->addr, a->flight, strFl, strGs, strTt, strSquawk, msgs, (int)(now - a->seen)); a->addr, a->flight, strFl, strGs, strTt, strSquawk, msgs, (now - a->seen)/1000.0);
} else { // Dump1090 display mode } else { // Dump1090 display mode
char strMode[5] = " "; char strMode[5] = " ";
@ -159,10 +160,10 @@ void interactiveShowData(void) {
snprintf(strFl, 6, "%5d", altitude); snprintf(strFl, 6, "%5d", altitude);
} }
printf("%s%06X %-4s %-4s %-8s %5s %3s %3s %7s %8s %5.1f %5d %2d\n", printf("%s%06X %-4s %-4s %-8s %5s %3s %3s %7s %8s %5.1f %5d %2.0f\n",
(a->addr & MODES_NON_ICAO_ADDRESS) ? "~" : " ", (a->addr & 0xffffff), (a->addr & MODES_NON_ICAO_ADDRESS) ? "~" : " ", (a->addr & 0xffffff),
strMode, strSquawk, a->flight, strFl, strGs, strTt, strMode, strSquawk, a->flight, strFl, strGs, strTt,
strLat, strLon, 10 * log10(signalAverage), msgs, (int)(now - a->seen)); strLat, strLon, 10 * log10(signalAverage), msgs, (now - a->seen)/1000.0);
} }
count++; count++;
} }

View file

@ -741,7 +741,7 @@ static const char *jsonEscapeString(const char *str) {
} }
char *generateAircraftJson(const char *url_path, int *len) { char *generateAircraftJson(const char *url_path, int *len) {
time_t now = time(NULL); uint64_t now = mstime();
struct aircraft *a; struct aircraft *a;
int buflen = 1024; // The initial buffer is incremented as needed int buflen = 1024; // The initial buffer is incremented as needed
char *buf = (char *) malloc(buflen), *p = buf, *end = buf+buflen; char *buf = (char *) malloc(buflen), *p = buf, *end = buf+buflen;
@ -750,10 +750,10 @@ char *generateAircraftJson(const char *url_path, int *len) {
MODES_NOTUSED(url_path); MODES_NOTUSED(url_path);
p += snprintf(p, end-p, p += snprintf(p, end-p,
"{ \"now\" : %d,\n" "{ \"now\" : %.1f,\n"
" \"messages\" : %u,\n" " \"messages\" : %u,\n"
" \"aircraft\" : [", " \"aircraft\" : [",
(int)now, now / 1000.0,
Modes.stats_current.messages_total + Modes.stats_alltime.messages_total); Modes.stats_current.messages_total + Modes.stats_alltime.messages_total);
for (a = Modes.aircrafts; a; a = a->next) { for (a = Modes.aircrafts; a; a = a->next) {
@ -776,7 +776,7 @@ char *generateAircraftJson(const char *url_path, int *len) {
if (a->bFlags & MODES_ACFLAGS_CALLSIGN_VALID) if (a->bFlags & MODES_ACFLAGS_CALLSIGN_VALID)
p += snprintf(p, end-p, ",\"flight\":\"%s\"", jsonEscapeString(a->flight)); p += snprintf(p, end-p, ",\"flight\":\"%s\"", jsonEscapeString(a->flight));
if (a->bFlags & MODES_ACFLAGS_LATLON_VALID) if (a->bFlags & MODES_ACFLAGS_LATLON_VALID)
p += snprintf(p, end-p, ",\"lat\":%f,\"lon\":%f,\"seen_pos\":%d", a->lat, a->lon, (int)(now - a->seenLatLon)); p += snprintf(p, end-p, ",\"lat\":%f,\"lon\":%f,\"seen_pos\":%.1f", a->lat, a->lon, (now - a->seenLatLon)/1000.0);
if ((a->bFlags & MODES_ACFLAGS_AOG_VALID) && (a->bFlags & MODES_ACFLAGS_AOG)) if ((a->bFlags & MODES_ACFLAGS_AOG_VALID) && (a->bFlags & MODES_ACFLAGS_AOG))
p += snprintf(p, end-p, ",\"altitude\":\"ground\""); p += snprintf(p, end-p, ",\"altitude\":\"ground\"");
else if (a->bFlags & MODES_ACFLAGS_ALTITUDE_VALID) else if (a->bFlags & MODES_ACFLAGS_ALTITUDE_VALID)
@ -788,8 +788,8 @@ char *generateAircraftJson(const char *url_path, int *len) {
if (a->bFlags & MODES_ACFLAGS_SPEED_VALID) if (a->bFlags & MODES_ACFLAGS_SPEED_VALID)
p += snprintf(p, end-p, ",\"speed\":%d", a->speed); p += snprintf(p, end-p, ",\"speed\":%d", a->speed);
p += snprintf(p, end-p, ",\"messages\":%ld,\"seen\":%d,\"rssi\":%.1f}", p += snprintf(p, end-p, ",\"messages\":%ld,\"seen\":%.1f,\"rssi\":%.1f}",
a->messages, (int)(now - a->seen), a->messages, (now - a->seen)/1000.0,
10 * log10((a->signalLevel[0] + a->signalLevel[1] + a->signalLevel[2] + a->signalLevel[3] + 10 * log10((a->signalLevel[0] + a->signalLevel[1] + a->signalLevel[2] + a->signalLevel[3] +
a->signalLevel[4] + a->signalLevel[5] + a->signalLevel[6] + a->signalLevel[7] + 1e-5) / 8)); a->signalLevel[4] + a->signalLevel[5] + a->signalLevel[6] + a->signalLevel[7] + 1e-5) / 8));
@ -1378,20 +1378,20 @@ void modesReadFromClient(struct client *c, char *sep,
static void writeFATSV() { static void writeFATSV() {
struct aircraft *a; struct aircraft *a;
time_t now; uint64_t now;
static time_t lastTime = 0; static uint64_t next_update;
if (!Modes.fatsv_out.connections) { if (!Modes.fatsv_out.connections) {
return; // no active connections return; // no active connections
} }
now = time(NULL); now = mstime();
if (now <= lastTime) { if (now < next_update) {
// scan once a second at most
return; return;
} }
lastTime = now; // scan once a second at most
next_update = now + 1000;
for (a = Modes.aircrafts; a; a = a->next) { for (a = Modes.aircrafts; a; a = a->next) {
int altValid = 0; int altValid = 0;
@ -1400,7 +1400,7 @@ static void writeFATSV() {
int ground = 0; int ground = 0;
int latlonValid = 0; int latlonValid = 0;
int useful = 0; int useful = 0;
int emittedSecondsAgo; uint64_t emittedMillisAgo;
char *p, *end; char *p, *end;
// skip non-ICAO // skip non-ICAO
@ -1415,10 +1415,10 @@ static void writeFATSV() {
continue; continue;
} }
emittedSecondsAgo = (int)(now - a->fatsv_last_emitted); emittedMillisAgo = (now - a->fatsv_last_emitted);
// don't emit more than once every five seconds // don't emit more than once every five seconds
if (emittedSecondsAgo < 5) { if (emittedMillisAgo < 5000) {
continue; continue;
} }
@ -1441,14 +1441,14 @@ static void writeFATSV() {
} }
// if it's over 10,000 feet, don't emit more than once every 10 seconds // if it's over 10,000 feet, don't emit more than once every 10 seconds
if (alt > 10000 && emittedSecondsAgo < 10) { if (alt > 10000 && emittedMillisAgo < 10000) {
continue; continue;
} }
// disable if you want only ads-b // disable if you want only ads-b
// also don't send mode S very often // also don't send mode S very often
if (!latlonValid) { if (!latlonValid) {
if (emittedSecondsAgo < 30) { if (emittedMillisAgo < 30000) {
continue; continue;
} }
} else { } else {
@ -1458,13 +1458,13 @@ static void writeFATSV() {
if (alt < 10000) { if (alt < 10000) {
// it hasn't changed much but we're below 10,000 feet // it hasn't changed much but we're below 10,000 feet
// so update more frequently // so update more frequently
if (emittedSecondsAgo < 10) { if (emittedMillisAgo < 10000) {
continue; continue;
} }
} else { } else {
// above 10,000 feet, don't update so often when it // above 10,000 feet, don't update so often when it
// hasn't changed much // hasn't changed much
if (emittedSecondsAgo < 30) { if (emittedMillisAgo < 30000) {
continue; continue;
} }
} }
@ -1477,7 +1477,7 @@ static void writeFATSV() {
end = p + TSV_MAX_PACKET_SIZE; end = p + TSV_MAX_PACKET_SIZE;
# define bufsize(_p,_e) ((_p) >= (_e) ? (size_t)0 : (size_t)((_e) - (_p))) # define bufsize(_p,_e) ((_p) >= (_e) ? (size_t)0 : (size_t)((_e) - (_p)))
p += snprintf(p, bufsize(p,end), "clock\t%ld\thexid\t%06X", a->seen, a->addr); p += snprintf(p, bufsize(p,end), "clock\t%ld\thexid\t%06X", (long)(a->seen / 1000), a->addr);
if (*a->flight != '\0') { if (*a->flight != '\0') {
p += snprintf(p, bufsize(p,end), "\tident\t%s", a->flight); p += snprintf(p, bufsize(p,end), "\tident\t%s", a->flight);

View file

@ -664,7 +664,7 @@ function refreshSelected() {
if (selected.seen <= 1) { if (selected.seen <= 1) {
$('#selected_seen').text('now'); $('#selected_seen').text('now');
} else { } else {
$('#selected_seen').text(selected.seen + 's'); $('#selected_seen').text(selected.seen.toFixed(1) + 's');
} }
if (selected.position === null) { if (selected.position === null) {
@ -672,7 +672,7 @@ function refreshSelected() {
$('#selected_follow').addClass('hidden'); $('#selected_follow').addClass('hidden');
} else { } else {
if (selected.seen_pos > 1) { if (selected.seen_pos > 1) {
$('#selected_position').text(format_latlng(selected.position) + " (" + selected.seen_pos + "s)"); $('#selected_position').text(format_latlng(selected.position) + " (" + selected.seen_pos.toFixed(1) + "s)");
} else { } else {
$('#selected_position').text(format_latlng(selected.position)); $('#selected_position').text(format_latlng(selected.position));
} }
@ -728,7 +728,7 @@ function refreshTableInfo() {
tableplane.tr.cells[5].textContent = format_distance_brief(tableplane.sitedist); tableplane.tr.cells[5].textContent = format_distance_brief(tableplane.sitedist);
tableplane.tr.cells[6].textContent = format_track_brief(tableplane.track); tableplane.tr.cells[6].textContent = format_track_brief(tableplane.track);
tableplane.tr.cells[7].textContent = tableplane.messages; tableplane.tr.cells[7].textContent = tableplane.messages;
tableplane.tr.cells[8].textContent = tableplane.seen; tableplane.tr.cells[8].textContent = tableplane.seen.toFixed(0);
tableplane.tr.className = classes; tableplane.tr.className = classes;

19
track.c
View file

@ -170,7 +170,7 @@ static int doGlobalCPR(struct aircraft *a, int fflag, int surface)
return 0; return 0;
} }
static int doLocalCPR(struct aircraft *a, int fflag, int surface, time_t now) static int doLocalCPR(struct aircraft *a, int fflag, int surface, uint64_t now)
{ {
// relative CPR // relative CPR
// find reference location // find reference location
@ -179,14 +179,13 @@ static int doLocalCPR(struct aircraft *a, int fflag, int surface, time_t now)
int result; int result;
if (a->bFlags & MODES_ACFLAGS_LATLON_REL_OK) { if (a->bFlags & MODES_ACFLAGS_LATLON_REL_OK) {
int elapsed = (int)(now - a->seenLatLon); uint64_t elapsed = (now - a->seenLatLon);
if (elapsed < 0) elapsed = 0;
reflat = a->lat; reflat = a->lat;
reflon = a->lon; reflon = a->lon;
// impose a range limit based on 2000km/h speed // impose a range limit based on 2000km/h speed
range_limit = 5e3 + (2000e3 * elapsed / 3600); // 5km + 2000km/h range_limit = 5e3 + (2000e3 * elapsed / 3600 / 1000); // 5km + 2000km/h
} else if (!surface && (Modes.bUserFlags & MODES_USER_LATLON_VALID)) { } else if (!surface && (Modes.bUserFlags & MODES_USER_LATLON_VALID)) {
reflat = Modes.fUserLat; reflat = Modes.fUserLat;
reflon = Modes.fUserLon; reflon = Modes.fUserLon;
@ -232,7 +231,7 @@ static int doLocalCPR(struct aircraft *a, int fflag, int surface, time_t now)
return 0; return 0;
} }
static void updatePosition(struct aircraft *a, struct modesMessage *mm, time_t now) static void updatePosition(struct aircraft *a, struct modesMessage *mm, uint64_t now)
{ {
int location_result = -1; int location_result = -1;
int max_elapsed; int max_elapsed;
@ -312,7 +311,7 @@ static void updatePosition(struct aircraft *a, struct modesMessage *mm, time_t n
struct aircraft *trackUpdateFromMessage(struct modesMessage *mm) struct aircraft *trackUpdateFromMessage(struct modesMessage *mm)
{ {
struct aircraft *a; struct aircraft *a;
time_t now = time(NULL); uint64_t now = mstime();
// Lookup our aircraft or create a new one // Lookup our aircraft or create a new one
a = trackFindAircraft(mm->addr); a = trackFindAircraft(mm->addr);
@ -495,7 +494,7 @@ static void trackUpdateAircraftModeS()
// If we don't receive new nessages within TRACK_AIRCRAFT_TTL // If we don't receive new nessages within TRACK_AIRCRAFT_TTL
// we remove the aircraft from the list. // we remove the aircraft from the list.
// //
static void trackRemoveStaleAircraft(time_t now) static void trackRemoveStaleAircraft(uint64_t now)
{ {
struct aircraft *a = Modes.aircrafts; struct aircraft *a = Modes.aircrafts;
struct aircraft *prev = NULL; struct aircraft *prev = NULL;
@ -528,12 +527,12 @@ static void trackRemoveStaleAircraft(time_t now)
void trackPeriodicUpdate() void trackPeriodicUpdate()
{ {
static time_t next_update; static uint64_t next_update;
time_t now = time(NULL); uint64_t now = mstime();
// Only do updates once per second // Only do updates once per second
if (now >= next_update) { if (now >= next_update) {
next_update = now; next_update = now + 1000;
trackRemoveStaleAircraft(now); trackRemoveStaleAircraft(now);
trackUpdateAircraftModeS(); trackUpdateAircraftModeS();
} }

14
track.h
View file

@ -50,11 +50,11 @@
#ifndef DUMP1090_TRACK_H #ifndef DUMP1090_TRACK_H
#define DUMP1090_TRACK_H #define DUMP1090_TRACK_H
/* Maximum age of tracked aircraft in seconds */ /* Maximum age of tracked aircraft in milliseconds */
#define TRACK_AIRCRAFT_TTL 300 #define TRACK_AIRCRAFT_TTL 300000
/* Maximum age of a tracked aircraft with only 1 message received, in seconds */ /* Maximum age of a tracked aircraft with only 1 message received, in milliseconds */
#define TRACK_AIRCRAFT_ONEHIT_TTL 60 #define TRACK_AIRCRAFT_ONEHIT_TTL 60000
/* Structure used to describe the state of one tracked aircraft */ /* Structure used to describe the state of one tracked aircraft */
struct aircraft { struct aircraft {
@ -65,8 +65,8 @@ struct aircraft {
int speed; // Velocity int speed; // Velocity
int track; // Angle of flight int track; // Angle of flight
int vert_rate; // Vertical rate. int vert_rate; // Vertical rate.
time_t seen; // Time at which the last packet was received uint64_t seen; // Time (millis) at which the last packet was received
time_t seenLatLon; // Time at which the last lat long was calculated uint64_t seenLatLon; // Time (millis) at which the last lat long was calculated
long messages; // Number of Mode S messages received long messages; // Number of Mode S messages received
int modeA; // Squawk int modeA; // Squawk
int modeC; // Altitude int modeC; // Altitude
@ -76,7 +76,7 @@ struct aircraft {
int fatsv_emitted_altitude; // last FA emitted altitude int fatsv_emitted_altitude; // last FA emitted altitude
int fatsv_emitted_track; // last FA emitted angle of flight int fatsv_emitted_track; // last FA emitted angle of flight
time_t fatsv_last_emitted; // time aircraft was last FA emitted uint64_t fatsv_last_emitted; // time (millis) aircraft was last FA emitted
// Encoded latitude and longitude as extracted by odd and even CPR encoded messages // Encoded latitude and longitude as extracted by odd and even CPR encoded messages
int odd_cprlat; int odd_cprlat;

View file

@ -233,7 +233,7 @@ int main(int argc, char **argv) {
} else if (!strcmp(argv[j],"--interactive")) { } else if (!strcmp(argv[j],"--interactive")) {
Modes.interactive = 1; Modes.interactive = 1;
} else if (!strcmp(argv[j],"--interactive-ttl") && more) { } else if (!strcmp(argv[j],"--interactive-ttl") && more) {
Modes.interactive_display_ttl = atoi(argv[++j]); Modes.interactive_display_ttl = (uint64_t)(1000 * atof(argv[++j]));
} else if (!strcmp(argv[j],"--interactive-rtl1090")) { } else if (!strcmp(argv[j],"--interactive-rtl1090")) {
Modes.interactive = 1; Modes.interactive = 1;
Modes.interactive_rtl1090 = 1; Modes.interactive_rtl1090 = 1;