Skip to content

Commit

Permalink
Improve global position updating
Browse files Browse the repository at this point in the history
  • Loading branch information
Douglasdc3 committed Feb 21, 2023
1 parent eeefc19 commit 48b9f12
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 76 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
GROUP=aero.t2s
VERSION_NAME=0.2.5-SNAPSHOT
VERSION_NAME=0.2.6-SNAPSHOT

POM_ARTIFACT_ID=mode-s
POM_NAME=Mode-S/ADS-B (1090Mhz)
Expand Down
14 changes: 11 additions & 3 deletions src/main/java/aero/t2s/modes/CprPosition.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package aero.t2s.modes;

import java.time.Instant;

public class CprPosition {
private double lat;
private double lon;
private boolean valid;
private int time;
private long time;

public CprPosition() {
this.lat = 0.0;
Expand All @@ -14,9 +16,11 @@ public CprPosition() {
public CprPosition(double lat, double lon) {
setLatLon(lat ,lon);
}

public void setLatLon(double lat, double lon) {
this.lat = lat;
this.lon = lon;
this.time = Instant.now().toEpochMilli();
this.valid = true;
}

Expand All @@ -36,15 +40,19 @@ public double getLon() {
return lon;
}

public void setTime(int time) {
public void setTime(long time) {
this.time = time;
}

public int getTime() {
public long getTime() {
return time;
}

public boolean isValid() {
return valid;
}

public boolean isExpired() {
return time < Instant.now().minusSeconds(10).toEpochMilli();
}
}
5 changes: 3 additions & 2 deletions src/main/java/aero/t2s/modes/ModeSHandler.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package aero.t2s.modes;

import aero.t2s.modes.decoder.df.DownlinkFormat;
import aero.t2s.modes.decoder.df.df17.AirbornePosition;

import java.util.function.Consumer;

Expand Down Expand Up @@ -42,10 +43,10 @@ protected short[] toData(final String input) throws EmptyMessageException, ModeA
}

public void start() {

AirbornePosition.start();
}

public void stop() {

AirbornePosition.stop();
}
}
19 changes: 0 additions & 19 deletions src/main/java/aero/t2s/modes/Track.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ public class Track {
private String icao;
private String callsign;
private Altitude altitude = new Altitude();
private boolean cprEvenValid = false;
private CprPosition cprEven = new CprPosition();
private CprPosition cprOdd = new CprPosition();
private double lat;
private double lon;
private boolean positionAvailable = false;
Expand Down Expand Up @@ -199,22 +196,6 @@ public double getLon() {
return lon;
}

public CprPosition getCprEven() {
return cprEven;
}

public void setCprEven(CprPosition cprEven) {
this.cprEven = cprEven;
}

public CprPosition getCprOdd() {
return cprOdd;
}

public void setCprOdd(CprPosition cprOdd) {
this.cprOdd = cprOdd;
}

public Version getVersion() {
return version;
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/aero/t2s/modes/decoder/Decoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public DownlinkFormat decode(short[] data) throws UnknownDownlinkFormatException
df = new DF16(data);
break;
case 17:
df = new DF17(data, originLat, originLon);
df = new DF17(data);
break;
case 18:
df = new DF18(data);
Expand Down
9 changes: 2 additions & 7 deletions src/main/java/aero/t2s/modes/decoder/df/DF17.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,10 @@
import aero.t2s.modes.decoder.df.df17.*;

public class DF17 extends DownlinkFormat {
private final double originLat;
private final double originLon;

private ExtendedSquitter extendedSquitter;

public DF17(short[] data, double originLat, double originLon) {
public DF17(short[] data) {
super(data, IcaoAddress.FROM_MESSAGE);
this.originLat = originLat;
this.originLon = originLon;
}

@Override
Expand All @@ -34,7 +29,7 @@ public DF17 decode() {
case 20:
case 21:
case 22:
extendedSquitter = new AirbornePosition(data, originLat, originLon);
extendedSquitter = new AirbornePosition(data, getIcao());
break;
case 1:
case 2:
Expand Down
145 changes: 102 additions & 43 deletions src/main/java/aero/t2s/modes/decoder/df/df17/AirbornePosition.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
import aero.t2s.modes.Track;
import aero.t2s.modes.CprPosition;
import aero.t2s.modes.constants.*;
import aero.t2s.modes.decoder.Common;
import aero.t2s.modes.registers.Register05;
import aero.t2s.modes.registers.Register05V0;
import aero.t2s.modes.registers.Register05V2;

public class AirbornePosition extends ExtendedSquitter {
private final double originLat;
private final double originLon;
import java.util.*;

public class AirbornePosition extends ExtendedSquitter {
private final String address;
private SurveillanceStatus surveillanceStatus;
private int singleAntennaFlag;

Expand All @@ -19,16 +20,14 @@ public class AirbornePosition extends ExtendedSquitter {

private boolean positionAvailable;

private CprPosition cprEven = new CprPosition();
private CprPosition cprOdd = new CprPosition();

private double lat;
private double lon;
private static Map<String, PositionUpdate> cache = new HashMap<>();
private static Timer cacheCleanup;

public AirbornePosition(short[] data, final double originLat, final double originLon) {
public AirbornePosition(short[] data, String address) {
super(data);
this.originLat = originLat;
this.originLon = originLon;
this.address = address;
}

@Override
Expand Down Expand Up @@ -59,14 +58,38 @@ public AirbornePosition decode() {
cprLon = cprLon | (data[9] << 8);
cprLon = cprLon | data[10];


if (!cache.containsKey(address)) {
if (!isCprEven) {
return this;
}

synchronized (cache) {
cache.putIfAbsent(address, new PositionUpdate(
new CprPosition(cprLat / (double)(1 << 17), cprLon / (double)(1 << 17))
));
}
}

PositionUpdate positionUpdate;
synchronized (cache) {
positionUpdate = cache.get(address);
}
if (isCprEven) {
this.cprEven.setLatLon(cprLat/(double)(1 << 17), cprLon/(double)(1 << 17));
positionUpdate.setEven(new CprPosition(cprLat / (double) (1 << 17), cprLon / (double) (1 << 17)));
} else {
positionUpdate.setOdd(new CprPosition(cprLat, cprLon));
}
else {
this.cprOdd.setLatLon(cprLat, cprLon);

if (positionUpdate.isComplete()) {
calculateGlobal(positionUpdate.even, positionUpdate.odd);
} else if (positionUpdate.isPreviousPositionAvailable() && positionUpdate.isPreviousPositionAvailable()) {
calculateLocal(positionUpdate.odd, true, positionUpdate.previousLat, positionUpdate.previousLon);
}

calculatePosition(isCprEven);
if (positionAvailable) {
positionUpdate.setPreviousPosition(this.lat, this.lon);
}

return this;
}
Expand All @@ -77,9 +100,9 @@ public void apply(Track track) {
track.setSpi(surveillanceStatus == SurveillanceStatus.SPI);
track.setTempAlert(surveillanceStatus == SurveillanceStatus.TEMPORARY_ALERT);
track.setEmergency(surveillanceStatus == SurveillanceStatus.PERMANENT_ALERT);
track.setCprEven(cprEven);
track.setCprOdd(cprOdd);
track.setLatLon(lat, lon);
if (positionAvailable) {
track.setLatLon(lat, lon);
}

if (versionChanged(track)) {
switch (track.getVersion()) {
Expand Down Expand Up @@ -130,14 +153,6 @@ public BarometricAltitudeIntegrityCode getNICbaro() {
}
}

public double getOriginLat() {
return originLat;
}

public double getOriginLon() {
return originLon;
}

public SurveillanceStatus getSurveillanceStatus() {
return surveillanceStatus;
}
Expand Down Expand Up @@ -215,25 +230,6 @@ private AltitudeSource determineAltitudeSource() {
return AltitudeSource.GNSS_HAE;
}

private void calculatePosition(boolean isEven) {
if (!positionAvailable) {
//TODO Could be other cases where we need to do global calculation, such as too much time elapsed since last position update
calculateGlobal(cprEven, cprOdd);
positionAvailable = true;
}
else {
if (isEven) {
if (cprOdd.isValid()) {
calculateLocal(cprEven, false, this.lat, this.lon);
}
} else {
if (cprEven.isValid()) {
calculateLocal(cprOdd, true, this.lat, this.lon);
}
}
}
}

private void calculateLocal(CprPosition cpr, boolean isOdd, double previousLat, double previousLon) {

double dlat = isOdd ? 360.0 / 59.0 : 360.0 / 60.0;
Expand Down Expand Up @@ -298,6 +294,7 @@ private void calculateGlobal(CprPosition cprEven, CprPosition cprOdd) {
//TODO Should be a sanity-check here to make sure the calculated position isn't outside receiver origin range,
this.lat = lat;
this.lon = lon;
this.positionAvailable = true;
}
private double cprN(double lat, double isOdd) {
double nl = NL(lat) - isOdd;
Expand All @@ -323,4 +320,66 @@ private int calculateAltitude(short[] data, int typeCode) {

return (n * qBit) - 1000;
}

public static void start() {
AirbornePosition.cache.clear();
AirbornePosition.cacheCleanup.schedule(new TimerTask() {
@Override
public void run() {
List<String> expired = new LinkedList<>();

synchronized (cache) {
cache.entrySet().stream().filter(entry -> entry.getValue().isExpired()).forEach(entry -> expired.add(entry.getKey()));
expired.forEach(cache::remove);
}
}
}, 0, 10_000);
}

public static void stop() {
AirbornePosition.cacheCleanup.cancel();
AirbornePosition.cacheCleanup = null;

AirbornePosition.cache.clear();
}

class PositionUpdate {
private CprPosition even;
private CprPosition odd;


private boolean previousPositionAvailable = false;
private double previousLat;
private double previousLon;

public PositionUpdate(CprPosition even) {
this.even = even;
}

public void setEven(CprPosition even) {
this.even = even;
this.odd = null;
}

public void setOdd(CprPosition odd) {
this.odd = odd;
}

public void setPreviousPosition(double lat, double lon) {
this.previousLat = lat;
this.previousLon = lon;
}

public boolean isPreviousPositionAvailable() {
return this.previousPositionAvailable;
}

public boolean isComplete() {
return even != null && odd != null;
}

public boolean isExpired() {
return even.isExpired() || odd.isExpired();
}
}
}

0 comments on commit 48b9f12

Please sign in to comment.