Add --max-range parameter. Use it for relative position limits, and to discard bad position results.
(cherry picked from commit 0d725508f78cb2fd7759efbb66b45b867d6f7722)
This commit is contained in:
parent
8b56cd104f
commit
fefce7b4bd
5
debian/config-template
vendored
5
debian/config-template
vendored
|
@ -52,6 +52,11 @@ AGGRESSIVE=
|
|||
LAT=
|
||||
LON=
|
||||
|
||||
# If set, provides the absolute maximum receiver range used to
|
||||
# filter bad position reports, and to determine when local position
|
||||
# decoding is safe to use. Specify this in nautical miles (NM).
|
||||
MAX_RANGE=
|
||||
|
||||
#
|
||||
# Networking options
|
||||
#
|
||||
|
|
2
debian/dump1090-mutability.config
vendored
2
debian/dump1090-mutability.config
vendored
|
@ -30,6 +30,7 @@ if [ -e $CONFIGFILE ]; then
|
|||
db_set_yn $NAME/decode-aggressive "$AGGRESSIVE"
|
||||
db_set $NAME/decode-lat "$LAT"
|
||||
db_set $NAME/decode-lon "$LON"
|
||||
db_set $NAME/decode-max-range "$MAX_RANGE"
|
||||
|
||||
db_set $NAME/net-http-port "$HTTP_PORT"
|
||||
db_set $NAME/net-ri-port "$RAW_INPUT_PORT"
|
||||
|
@ -178,6 +179,7 @@ db_go || true; db_get $NAME/auto-start; if [ "$RET" = "true" ]; then
|
|||
|
||||
db_input low $NAME/decode-fix-crc || true
|
||||
db_input low $NAME/decode-aggressive || true
|
||||
db_input_verify medium $NAME/decode-max-range is_number || true
|
||||
db_input_verify medium $NAME/decode-lat is_number_or_empty || true
|
||||
|
||||
db_go || true; db_get $NAME/decode-lat; if [ -n "$RET" ]; then
|
||||
|
|
2
debian/dump1090-mutability.init
vendored
2
debian/dump1090-mutability.init
vendored
|
@ -42,6 +42,7 @@ SCRIPTNAME=/etc/init.d/$NAME
|
|||
[ -z "$FATSV_OUTPUT_PORT" ] && FATSV_OUTPUT_PORT=0
|
||||
[ -z "$NET_BUFFER" ] && NET_BUFFER=0
|
||||
[ -z "$JSON_INTERVAL" ] && JSON_INTERVAL=0
|
||||
[ -z "$MAX_RANGE" ] && MAX_RANGE=300
|
||||
|
||||
# receiver:
|
||||
case "x$DEVICE" in
|
||||
|
@ -63,6 +64,7 @@ if [ "x$PHASE_ENHANCE" = "xyes" ]; then ARGS="$ARGS --phase-enhance"; fi
|
|||
if [ "x$AGGRESSIVE" = "xyes" ]; then ARGS="$ARGS --aggressive"; fi
|
||||
if [ -n "$LAT" ]; then ARGS="$ARGS --lat $LAT"; fi
|
||||
if [ -n "$LON" ]; then ARGS="$ARGS --lon $LON"; fi
|
||||
ARGS="$ARGS --max-range $MAX_RANGE"; fi
|
||||
|
||||
# net:
|
||||
|
||||
|
|
1
debian/dump1090-mutability.postinst
vendored
1
debian/dump1090-mutability.postinst
vendored
|
@ -69,6 +69,7 @@ case "$1" in
|
|||
subvar_yn decode-aggressive AGGRESSIVE
|
||||
subvar decode-lat LAT
|
||||
subvar decode-lon LON
|
||||
subvar decode-max-range MAX_RANGE
|
||||
subvar net-http-port HTTP_PORT
|
||||
subvar net-ri-port RAW_INPUT_PORT
|
||||
subvar net-ro-port RAW_OUTPUT_PORT
|
||||
|
|
17
debian/dump1090-mutability.templates
vendored
17
debian/dump1090-mutability.templates
vendored
|
@ -102,6 +102,23 @@ Description: Longitude of receiver, in decimal degrees:
|
|||
Type: string
|
||||
Default:
|
||||
|
||||
Template: dump1090-mutability/decode-max-range
|
||||
Description: Absolute maximum range of receiver, in nautical miles:
|
||||
If the maximum range of the receiver is provided, dump1090 can filter
|
||||
out impossible position reports that are due to aircraft that transmit
|
||||
bad data.
|
||||
.
|
||||
Additionally, if the maximum range is larger than 180NM, when local
|
||||
position decoding is used (when insufficient position messages
|
||||
have been received for global position decoding), it is limited to
|
||||
only those positions that would unambiguously decode to a single
|
||||
position within the given receiver range.
|
||||
.
|
||||
This range should be the absolute maximum range - any position data
|
||||
from further away will be entirely discarded!
|
||||
Type: string
|
||||
Default: 300
|
||||
|
||||
Template: dump1090-mutability/net-http-port
|
||||
Description: Port for internal webserver (0 disables):
|
||||
dump1090 can provide an internal webserver that serves a basic "virtual
|
||||
|
|
|
@ -87,6 +87,7 @@ void modesInitConfig(void) {
|
|||
Modes.fUserLon = MODES_USER_LONGITUDE_DFLT;
|
||||
Modes.json_interval = 1;
|
||||
Modes.json_location_accuracy = 1;
|
||||
Modes.maxRange = 1852 * 300; // 300NM default max range
|
||||
}
|
||||
//
|
||||
//=========================================================================
|
||||
|
@ -460,6 +461,7 @@ void showHelp(void) {
|
|||
"--net-buffer <n> TCP buffer size 64Kb * (2^n) (default: n=0, 64Kb)\n"
|
||||
"--lat <latitude> Reference/receiver latitude for surface posn (opt)\n"
|
||||
"--lon <longitude> Reference/receiver longitude for surface posn (opt)\n"
|
||||
"--max-range <distance> Absolute maximum range for position decoding (in nm, default: 300)\n"
|
||||
"--fix Enable single-bits error correction using CRC\n"
|
||||
"--no-fix Disable single-bits error correction using CRC\n"
|
||||
"--no-crc-check Disable messages with broken CRC (discouraged)\n"
|
||||
|
@ -822,6 +824,8 @@ int main(int argc, char **argv) {
|
|||
Modes.fUserLat = atof(argv[++j]);
|
||||
} else if (!strcmp(argv[j],"--lon") && more) {
|
||||
Modes.fUserLon = atof(argv[++j]);
|
||||
} else if (!strcmp(argv[j],"--max-range") && more) {
|
||||
Modes.maxRange = atof(argv[++j]) * 1852.0; // convert to metres
|
||||
} else if (!strcmp(argv[j],"--debug") && more) {
|
||||
char *f = argv[++j];
|
||||
while(*f) {
|
||||
|
|
|
@ -367,6 +367,7 @@ struct { // Internal state
|
|||
double fUserLat; // Users receiver/antenna lat/lon needed for initial surface location
|
||||
double fUserLon; // Users receiver/antenna lat/lon needed for initial surface location
|
||||
int bUserFlags; // Flags relating to the user details
|
||||
double maxRange; // Absolute maximum decoding range, in *metres*
|
||||
|
||||
// Interactive mode
|
||||
struct aircraft *aircrafts;
|
||||
|
|
71
mode_s.c
71
mode_s.c
|
@ -2490,6 +2490,19 @@ int cprNFunction(double lat, int fflag) {
|
|||
double cprDlonFunction(double lat, int fflag, int surface) {
|
||||
return (surface ? 90.0 : 360.0) / cprNFunction(lat, fflag);
|
||||
}
|
||||
|
||||
// Distance between points on a spherical earth.
|
||||
// This has up to 0.5% error because the earth isn't actually spherical
|
||||
// (but we don't use it in situations where that matters)
|
||||
static double greatcircle(double lat0, double lon0, double lat1, double lon1)
|
||||
{
|
||||
lat0 = lat0 * M_PI / 180.0;
|
||||
lon0 = lon0 * M_PI / 180.0;
|
||||
lat1 = lat1 * M_PI / 180.0;
|
||||
lon1 = lon1 * M_PI / 180.0;
|
||||
return 6371e3 * acos(sin(lat0) * sin(lat1) + cos(lat0) * cos(lat1) * cos(fabs(lon0 - lon1)));
|
||||
}
|
||||
|
||||
//
|
||||
//=========================================================================
|
||||
//
|
||||
|
@ -2516,6 +2529,8 @@ int decodeCPR(struct aircraft *a, int fflag, int surface) {
|
|||
double surface_rlat = MODES_USER_LATITUDE_DFLT;
|
||||
double surface_rlon = MODES_USER_LONGITUDE_DFLT;
|
||||
|
||||
double rlat, rlon;
|
||||
|
||||
if (surface) {
|
||||
// If we're on the ground, make sure we have a (likely) valid Lat/Lon
|
||||
if ((a->bFlags & MODES_ACFLAGS_LATLON_VALID) && (((int)(now - a->seenLatLon)) < Modes.interactive_display_ttl)) {
|
||||
|
@ -2553,26 +2568,35 @@ int decodeCPR(struct aircraft *a, int fflag, int surface) {
|
|||
int ni = cprNFunction(rlat1,1);
|
||||
int m = (int) floor((((lon0 * (cprNLFunction(rlat1)-1)) -
|
||||
(lon1 * cprNLFunction(rlat1))) / 131072.0) + 0.5);
|
||||
a->lon = cprDlonFunction(rlat1, 1, surface) * (cprModInt(m, ni)+lon1/131072);
|
||||
a->lat = rlat1;
|
||||
rlon = cprDlonFunction(rlat1, 1, surface) * (cprModInt(m, ni)+lon1/131072);
|
||||
rlat = rlat1;
|
||||
} else { // Use even packet.
|
||||
int ni = cprNFunction(rlat0,0);
|
||||
int m = (int) floor((((lon0 * (cprNLFunction(rlat0)-1)) -
|
||||
(lon1 * cprNLFunction(rlat0))) / 131072) + 0.5);
|
||||
a->lon = cprDlonFunction(rlat0, 0, surface) * (cprModInt(m, ni)+lon0/131072);
|
||||
a->lat = rlat0;
|
||||
rlon = cprDlonFunction(rlat0, 0, surface) * (cprModInt(m, ni)+lon0/131072);
|
||||
rlat = rlat0;
|
||||
}
|
||||
|
||||
if (surface) {
|
||||
// Pick the quadrant that's closest to the reference location -
|
||||
// this is not necessarily the same quadrant that contains the
|
||||
// reference location.
|
||||
a->lon += floor( (surface_rlon - a->lon + 45) / 90 ) * 90; // if we are >45 degrees away, move towards the reference position
|
||||
a->lon -= floor( (a->lon + 180) / 360 ) * 360; // normalize to (-180..+180)
|
||||
} else if (a->lon > 180) {
|
||||
a->lon -= 360;
|
||||
rlon += floor( (surface_rlon - rlon + 45) / 90 ) * 90; // if we are >45 degrees away, move towards the reference position
|
||||
rlon -= floor( (rlon + 180) / 360 ) * 360; // normalize to (-180..+180)
|
||||
} else if (rlon > 180) {
|
||||
rlon -= 360;
|
||||
}
|
||||
|
||||
// check max range
|
||||
if (Modes.maxRange > 0 && (Modes.bUserFlags & MODES_USER_LATLON_VALID)) {
|
||||
double range = greatcircle(Modes.fUserLat, Modes.fUserLon, rlat, rlon);
|
||||
if (range > Modes.maxRange)
|
||||
return (-2); // we consider an out-of-range value to be bad data
|
||||
}
|
||||
|
||||
a->lat = rlat;
|
||||
a->lon = rlon;
|
||||
a->seenLatLon = a->seen;
|
||||
a->timestampLatLon = a->timestamp;
|
||||
a->bFlags |= (MODES_ACFLAGS_LATLON_VALID | MODES_ACFLAGS_LATLON_REL_OK);
|
||||
|
@ -2595,14 +2619,31 @@ int decodeCPRrelative(struct aircraft *a, int fflag, int surface) {
|
|||
double lon;
|
||||
double lonr, latr;
|
||||
double rlon, rlat;
|
||||
double range_limit = 0;
|
||||
int j,m;
|
||||
|
||||
if (a->bFlags & MODES_ACFLAGS_LATLON_REL_OK) { // Ok to try aircraft relative first
|
||||
int elapsed = (int)(time(NULL) - a->seenLatLon);
|
||||
|
||||
latr = a->lat;
|
||||
lonr = a->lon;
|
||||
|
||||
// impose a range limit based on 2000km/h speed
|
||||
range_limit = 5e3 + (2000e3 * elapsed / 3600); // 5km + 2000km/h
|
||||
} else if (Modes.bUserFlags & MODES_USER_LATLON_VALID) { // Try ground station relative next
|
||||
latr = Modes.fUserLat;
|
||||
lonr = Modes.fUserLon;
|
||||
|
||||
// The cell size is at least 360NM, giving a nominal
|
||||
// max range of 180NM (half a cell).
|
||||
//
|
||||
// If the receiver range is more than half a cell
|
||||
// then we must limit this range further to avoid
|
||||
// ambiguity. (e.g. if we receive a position report
|
||||
// at 200NM distance, this may resolve to a position
|
||||
// at (200-360) = 160NM in the wrong direction)
|
||||
if (Modes.maxRange > 1852*180)
|
||||
range_limit = (1852*360) - Modes.maxRange;
|
||||
} else {
|
||||
return (-1); // Exit with error - can't do relative if we don't have ref.
|
||||
}
|
||||
|
@ -2648,6 +2689,20 @@ int decodeCPRrelative(struct aircraft *a, int fflag, int surface) {
|
|||
return (-1); // Time to give up - Longitude error
|
||||
}
|
||||
|
||||
// check range limit
|
||||
if (range_limit > 0) {
|
||||
double range = greatcircle(latr, lonr, rlat, rlon);
|
||||
if (range > range_limit)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
// check max range
|
||||
if (Modes.maxRange > 0 && (Modes.bUserFlags & MODES_USER_LATLON_VALID)) {
|
||||
double range = greatcircle(Modes.fUserLat, Modes.fUserLon, rlat, rlon);
|
||||
if (range > Modes.maxRange)
|
||||
return (-2); // we consider an out-of-range value to be bad data
|
||||
}
|
||||
|
||||
a->lat = rlat;
|
||||
a->lon = rlon;
|
||||
|
||||
|
|
Loading…
Reference in a new issue