Skip to content

Commit eeefc19

Browse files
committed
Experimental use of even/odd DF17 airborne positions and use global or local calculation depending on prior received data.
1 parent 17aab20 commit eeefc19

File tree

3 files changed

+136
-76
lines changed

3 files changed

+136
-76
lines changed

src/main/java/aero/t2s/modes/CprPosition.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,23 @@
33
public class CprPosition {
44
private double lat;
55
private double lon;
6+
private boolean valid;
67
private int time;
78

9+
public CprPosition() {
10+
this.lat = 0.0;
11+
this.lon = 0.0;
12+
this.valid = false;
13+
}
14+
public CprPosition(double lat, double lon) {
15+
setLatLon(lat ,lon);
16+
}
17+
public void setLatLon(double lat, double lon) {
18+
this.lat = lat;
19+
this.lon = lon;
20+
this.valid = true;
21+
}
22+
823
public void setLat(double lat) {
924
this.lat = lat;
1025
}
@@ -30,6 +45,6 @@ public int getTime() {
3045
}
3146

3247
public boolean isValid() {
33-
return lat != 0d && lon != 0;
48+
return valid;
3449
}
3550
}

src/main/java/aero/t2s/modes/Track.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,12 @@ public class Track {
99
private String icao;
1010
private String callsign;
1111
private Altitude altitude = new Altitude();
12+
private boolean cprEvenValid = false;
13+
private CprPosition cprEven = new CprPosition();
14+
private CprPosition cprOdd = new CprPosition();
1215
private double lat;
1316
private double lon;
17+
private boolean positionAvailable = false;
1418
private int vx;
1519
private int vy;
1620
private double gs;
@@ -172,7 +176,13 @@ public boolean isGroundBit() {
172176
return groundBit;
173177
}
174178

179+
public void setLatLon(double lat, double lon) {
180+
this.lon = lat;
181+
this.lon = lon;
182+
this.positionAvailable = true;
183+
}
175184
public void setLat(double lat) {
185+
//TODO How do we know if position really is available if we only set the lat? Can we remove this method?
176186
this.lat = lat;
177187
}
178188

@@ -181,13 +191,30 @@ public double getLat() {
181191
}
182192

183193
public void setLon(double lon) {
194+
//TODO How do we know if position really is available if we only set the lon? Can we remove this method?
184195
this.lon = lon;
185196
}
186197

187198
public double getLon() {
188199
return lon;
189200
}
190201

202+
public CprPosition getCprEven() {
203+
return cprEven;
204+
}
205+
206+
public void setCprEven(CprPosition cprEven) {
207+
this.cprEven = cprEven;
208+
}
209+
210+
public CprPosition getCprOdd() {
211+
return cprOdd;
212+
}
213+
214+
public void setCprOdd(CprPosition cprOdd) {
215+
this.cprOdd = cprOdd;
216+
}
217+
191218
public Version getVersion() {
192219
return version;
193220
}
@@ -245,7 +272,7 @@ public int getModeA() {
245272
}
246273

247274
public boolean isPositionAvailable() {
248-
return lat != 0 & lon != 0;
275+
return positionAvailable;
249276
}
250277

251278
public void setGeometricHeightOffset(int geometricHeightOffset) {

src/main/java/aero/t2s/modes/decoder/df/df17/AirbornePosition.java

Lines changed: 92 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package aero.t2s.modes.decoder.df.df17;
22

33
import aero.t2s.modes.Track;
4+
import aero.t2s.modes.CprPosition;
45
import aero.t2s.modes.constants.*;
56
import aero.t2s.modes.registers.Register05;
67
import aero.t2s.modes.registers.Register05V0;
@@ -17,6 +18,10 @@ public class AirbornePosition extends ExtendedSquitter {
1718
private int altitude;
1819

1920
private boolean positionAvailable;
21+
22+
private CprPosition cprEven = new CprPosition();
23+
private CprPosition cprOdd = new CprPosition();
24+
2025
private double lat;
2126
private double lon;
2227

@@ -43,10 +48,8 @@ public AirbornePosition decode() {
4348
return this;
4449
}
4550

46-
positionAvailable = true;
47-
4851
int time = (data[6] >>> 3) & 0x1;
49-
boolean cprEven = ((data[6] >>> 2) & 0x1) == 0;
52+
boolean isCprEven = ((data[6] >>> 2) & 0x1) == 0;
5053

5154
int cprLat = (data[6] & 0x3) << 15;
5255
cprLat = cprLat | (data[7] << 7);
@@ -56,7 +59,14 @@ public AirbornePosition decode() {
5659
cprLon = cprLon | (data[9] << 8);
5760
cprLon = cprLon | data[10];
5861

59-
calculatePosition(cprEven, ((double)cprLat) / ((double)(1 << 17)), ((double)cprLon) / ((double)(1 << 17)), time);
62+
if (isCprEven) {
63+
this.cprEven.setLatLon(cprLat/(double)(1 << 17), cprLon/(double)(1 << 17));
64+
}
65+
else {
66+
this.cprOdd.setLatLon(cprLat, cprLon);
67+
}
68+
69+
calculatePosition(isCprEven);
6070

6171
return this;
6272
}
@@ -67,8 +77,9 @@ public void apply(Track track) {
6777
track.setSpi(surveillanceStatus == SurveillanceStatus.SPI);
6878
track.setTempAlert(surveillanceStatus == SurveillanceStatus.TEMPORARY_ALERT);
6979
track.setEmergency(surveillanceStatus == SurveillanceStatus.PERMANENT_ALERT);
70-
track.setLat(lat);
71-
track.setLon(lon);
80+
track.setCprEven(cprEven);
81+
track.setCprOdd(cprOdd);
82+
track.setLatLon(lat, lon);
7283

7384
if (versionChanged(track)) {
7485
switch (track.getVersion()) {
@@ -204,88 +215,95 @@ private AltitudeSource determineAltitudeSource() {
204215
return AltitudeSource.GNSS_HAE;
205216
}
206217

207-
private void calculatePosition(boolean isEven, double lat, double lon, double time) {
208-
// CprPosition cprEven = track.getCprPosition(true);
209-
// CprPosition cprOdd = track.getCprPosition(false);
210-
211-
// if (! (cprEven.isValid() && cprOdd.isValid())) {
212-
calculateLocal(isEven, lat, lon, time);
213-
// return;
214-
// }
215-
216-
// calculateGlobal(track, cprEven, cprOdd);
218+
private void calculatePosition(boolean isEven) {
219+
if (!positionAvailable) {
220+
//TODO Could be other cases where we need to do global calculation, such as too much time elapsed since last position update
221+
calculateGlobal(cprEven, cprOdd);
222+
positionAvailable = true;
223+
}
224+
else {
225+
if (isEven) {
226+
if (cprOdd.isValid()) {
227+
calculateLocal(cprEven, false, this.lat, this.lon);
228+
}
229+
} else {
230+
if (cprEven.isValid()) {
231+
calculateLocal(cprOdd, true, this.lat, this.lon);
232+
}
233+
}
234+
}
217235
}
218236

219-
private void calculateLocal(boolean isEven, double lat, double lon, double time) {
220-
boolean isOdd = !isEven;
221-
// CprPosition cpr = track.getCprPosition(isEven);
237+
private void calculateLocal(CprPosition cpr, boolean isOdd, double previousLat, double previousLon) {
222238

223239
double dlat = isOdd ? 360.0 / 59.0 : 360.0 / 60.0;
224240

225-
double j = Math.floor(originLat / dlat) + Math.floor((originLat % dlat) / dlat - lat + 0.5);
241+
double j = Math.floor(previousLat / dlat) + Math.floor((previousLat % dlat) / dlat - cpr.getLat() + 0.5);
226242

227-
lat = dlat * (j + lat);
243+
double newLat = dlat * (j + previousLat);
228244

229-
double nl = NL(lat) - (isOdd ? 1.0 : 0.0);
245+
double nl = NL(newLat) - (isOdd ? 1.0 : 0.0);
230246
double dlon = nl > 0 ? 360.0 / nl : 360;
231247

232-
double m = Math.floor(originLon / dlon) + Math.floor((originLon % dlon) / dlon - lon + 0.5);
233-
lon = dlon * (m + lon);
248+
double m = Math.floor(previousLon / dlon) + Math.floor((previousLon % dlon) / dlon - cpr.getLon() + 0.5);
249+
double newLon = dlon * (m + lon);
250+
251+
//TODO Should be a sanity-check here to make sure the calculated position isn't outside receiver origin range
252+
//TODO Should be a sanity-check here to see if the calculated movement since the last update is too far
253+
this.lat = newLat;
254+
this.lon = newLon;
255+
}
256+
257+
private void calculateGlobal(CprPosition cprEven, CprPosition cprOdd) {
258+
double dLat0 = 360.0 / 60.0;
259+
double dLat1 = 360.0 / 59.0;
234260

261+
double j = Math.floor(59.0 * cprEven.getLat() - 60.0 * cprOdd.getLat() + 0.5);
262+
263+
double latEven = dLat0 * (j % 60.0 + cprEven.getLat());
264+
double latOdd = dLat1 * (j % 59.0 + cprOdd.getLat());
265+
266+
if (latEven >= 270.0 && latEven <= 360.0) {
267+
latEven -= 360.0;
268+
}
269+
270+
if (latOdd >= 270.0 && latOdd <= 360.0) {
271+
latOdd -= 360.0;
272+
}
273+
274+
if (NL(latEven) != NL(latOdd)) {
275+
return;
276+
}
277+
278+
double lat;
279+
double lon;
280+
if (cprEven.getTime() > cprOdd.getTime()) {
281+
double ni = cprN(latEven, 0);
282+
double m = Math.floor(cprEven.getLon() * (NL(latEven) - 1) - cprOdd.getLon() * NL(latEven) + 0.5);
283+
284+
lat = latEven;
285+
lon = (360d / ni) * (m % ni + cprEven.getLon());
286+
} else {
287+
double ni = cprN(latOdd, 1);
288+
double m = Math.floor(cprEven.getLon() * (NL(latOdd) - 1) - cprOdd.getLon() * NL(latOdd) + 0.5);
289+
290+
lat = latOdd;
291+
lon = (360d / ni) * (m % ni + cprOdd.getLon());
292+
}
293+
294+
if (lon > 180d) {
295+
lon -= 360d;
296+
}
297+
298+
//TODO Should be a sanity-check here to make sure the calculated position isn't outside receiver origin range,
235299
this.lat = lat;
236300
this.lon = lon;
237301
}
302+
private double cprN(double lat, double isOdd) {
303+
double nl = NL(lat) - isOdd;
238304

239-
// private void calculateGlobal(Track track, CprPosition cprEven, CprPosition cprOdd) {
240-
// double dLat0 = 360.0 / 60.0;
241-
// double dLat1 = 360.0 / 59.0;
242-
//
243-
// double j = Math.floor(59.0 * cprEven.getLat() - 60.0 * cprOdd.getLat() + 0.5);
244-
//
245-
// double latEven = dLat0 * (j % 60.0 + cprEven.getLat());
246-
// double latOdd = dLat1 * (j % 59.0 + cprOdd.getLat());
247-
//
248-
// if (latEven >= 270.0 && latEven <= 360.0) {
249-
// latEven -= 360.0;
250-
// }
251-
//
252-
// if (latOdd >= 270.0 && latOdd <= 360.0) {
253-
// latOdd -= 360.0;
254-
// }
255-
//
256-
// if (NL(latEven) != NL(latOdd)) {
257-
// return;
258-
// }
259-
//
260-
// double lat;
261-
// double lon;
262-
// if (cprEven.getTime() > cprOdd.getTime()) {
263-
// double ni = cprN(latEven, 0);
264-
// double m = Math.floor(cprEven.getLon() * (NL(latEven) - 1) - cprOdd.getLon() * NL(latEven) + 0.5);
265-
//
266-
// lat = latEven;
267-
// lon = (360d / ni) * (m % ni + cprEven.getLon());
268-
// } else {
269-
// double ni = cprN(latOdd, 1);
270-
// double m = Math.floor(cprEven.getLon() * (NL(latOdd) - 1) - cprOdd.getLon() * NL(latOdd) + 0.5);
271-
//
272-
// lat = latOdd;
273-
// lon = (360d / ni) * (m % ni + cprOdd.getLon());
274-
// }
275-
//
276-
// if (lon > 180d) {
277-
// lon -= 360d;
278-
// }
279-
//
280-
// track.setLat(lat);
281-
// track.setLon(lon);
282-
// }
283-
284-
// private double cprN(double lat, double isOdd) {
285-
// double nl = NL(lat) - isOdd;
286-
//
287-
// return nl > 1 ? nl : 1;
288-
// }
305+
return nl > 1 ? nl : 1;
306+
}
289307

290308
private double NL(double lat) {
291309
if (lat == 0) return 59;

0 commit comments

Comments
 (0)