3
3
import aero .t2s .modes .Track ;
4
4
import aero .t2s .modes .CprPosition ;
5
5
import aero .t2s .modes .constants .*;
6
- import aero .t2s .modes .decoder .Common ;
7
6
import aero .t2s .modes .registers .Register05 ;
8
7
import aero .t2s .modes .registers .Register05V0 ;
9
8
import aero .t2s .modes .registers .Register05V2 ;
@@ -18,12 +17,9 @@ public class AirbornePosition extends ExtendedSquitter {
18
17
private boolean altitudeSourceBaro ;
19
18
private int altitude ;
20
19
21
- private boolean positionAvailable ;
22
-
23
20
private double lat ;
24
21
private double lon ;
25
- private static Map <String , PositionUpdate > cache = new HashMap <>();
26
- private static Timer cacheCleanup ;
22
+ private boolean positionAvailable ;
27
23
28
24
public AirbornePosition (short [] data , String address ) {
29
25
super (data );
@@ -58,39 +54,14 @@ public AirbornePosition decode() {
58
54
cprLon = cprLon | (data [9 ] << 8 );
59
55
cprLon = cprLon | data [10 ];
60
56
61
-
62
- if (!cache .containsKey (address )) {
63
- if (!isCprEven ) {
64
- return this ;
65
- }
66
-
67
- synchronized (cache ) {
68
- cache .putIfAbsent (address , new PositionUpdate (
69
- new CprPosition (cprLat / (double )(1 << 17 ), cprLon / (double )(1 << 17 ))
70
- ));
71
- }
72
- }
73
-
74
- PositionUpdate positionUpdate ;
75
- synchronized (cache ) {
76
- positionUpdate = cache .get (address );
77
- }
78
- if (isCprEven ) {
79
- positionUpdate .setEven (new CprPosition (cprLat / (double ) (1 << 17 ), cprLon / (double ) (1 << 17 )));
80
- } else {
81
- positionUpdate .setOdd (new CprPosition (cprLat / (double ) (1 << 17 ), cprLon / (double ) (1 << 17 )));
82
- }
83
-
84
- if (positionUpdate .isComplete ()) {
85
- calculateGlobal (positionUpdate .even , positionUpdate .odd );
86
- } else if (positionUpdate .isPreviousPositionAvailable () && positionUpdate .isPreviousPositionAvailable ()) {
87
- calculateLocal (positionUpdate .odd , true , positionUpdate .previousLat , positionUpdate .previousLon );
88
- }
89
-
90
- if (positionAvailable ) {
91
- positionUpdate .setPreviousPosition (this .lat , this .lon );
57
+ CprPosition newPosition = PositionUpdate .calculate (address , isCprEven , new CprPosition (cprLat , cprLon , false ));
58
+ if (newPosition != null ) {
59
+ this .lat = newPosition .getLat ();
60
+ this .lon = newPosition .getLon ();
61
+ this .positionAvailable = true ;
62
+ } else {
63
+ this .positionAvailable = false ;
92
64
}
93
-
94
65
return this ;
95
66
}
96
67
@@ -230,88 +201,6 @@ private AltitudeSource determineAltitudeSource() {
230
201
return AltitudeSource .GNSS_HAE ;
231
202
}
232
203
233
- private void calculateLocal (CprPosition cpr , boolean isOdd , double previousLat , double previousLon ) {
234
-
235
- double dlat = isOdd ? 360.0 / 59.0 : 360.0 / 60.0 ;
236
-
237
- double j = Math .floor (previousLat / dlat ) + Math .floor ((previousLat % dlat ) / dlat - cpr .getLat () + 0.5 );
238
-
239
- double newLat = dlat * (j + previousLat );
240
-
241
- double nl = NL (newLat ) - (isOdd ? 1.0 : 0.0 );
242
- double dlon = nl > 0 ? 360.0 / nl : 360 ;
243
-
244
- double m = Math .floor (previousLon / dlon ) + Math .floor ((previousLon % dlon ) / dlon - cpr .getLon () + 0.5 );
245
- double newLon = dlon * (m + lon );
246
-
247
- //TODO Should be a sanity-check here to make sure the calculated position isn't outside receiver origin range
248
- //TODO Should be a sanity-check here to see if the calculated movement since the last update is too far
249
- this .lat = newLat ;
250
- this .lon = newLon ;
251
- this .positionAvailable = true ;
252
- }
253
-
254
- private void calculateGlobal (CprPosition cprEven , CprPosition cprOdd ) {
255
- double dLat0 = 360.0 / 60.0 ;
256
- double dLat1 = 360.0 / 59.0 ;
257
-
258
- double j = Math .floor (59.0 * cprEven .getLat () - 60.0 * cprOdd .getLat () + 0.5 );
259
-
260
- double latEven = dLat0 * (j % 60.0 + cprEven .getLat ());
261
- double latOdd = dLat1 * (j % 59.0 + cprOdd .getLat ());
262
-
263
- if (latEven >= 270.0 && latEven <= 360.0 ) {
264
- latEven -= 360.0 ;
265
- }
266
-
267
- if (latOdd >= 270.0 && latOdd <= 360.0 ) {
268
- latOdd -= 360.0 ;
269
- }
270
-
271
- if (NL (latEven ) != NL (latOdd )) {
272
- return ;
273
- }
274
-
275
- double lat ;
276
- double lon ;
277
- if (cprEven .getTime () > cprOdd .getTime ()) {
278
- double ni = cprN (latEven , 0 );
279
- double m = Math .floor (cprEven .getLon () * (NL (latEven ) - 1 ) - cprOdd .getLon () * NL (latEven ) + 0.5 );
280
-
281
- lat = latEven ;
282
- lon = (360d / ni ) * (m % ni + cprEven .getLon ());
283
- } else {
284
- double ni = cprN (latOdd , 1 );
285
- double m = Math .floor (cprEven .getLon () * (NL (latOdd ) - 1 ) - cprOdd .getLon () * NL (latOdd ) + 0.5 );
286
-
287
- lat = latOdd ;
288
- lon = (360d / ni ) * (m % ni + cprOdd .getLon ());
289
- }
290
-
291
- if (lon > 180d ) {
292
- lon -= 360d ;
293
- }
294
-
295
- //TODO Should be a sanity-check here to make sure the calculated position isn't outside receiver origin range,
296
- this .lat = lat ;
297
- this .lon = lon ;
298
- this .positionAvailable = true ;
299
- }
300
- private double cprN (double lat , double isOdd ) {
301
- double nl = NL (lat ) - isOdd ;
302
-
303
- return nl > 1 ? nl : 1 ;
304
- }
305
-
306
- private double NL (double lat ) {
307
- if (lat == 0 ) return 59 ;
308
- else if (Math .abs (lat ) == 87 ) return 2 ;
309
- else if (Math .abs (lat ) > 87 ) return 1 ;
310
-
311
- double tmp = 1 - (1 - Math .cos (Math .PI / (2.0 * 15.0 ))) / Math .pow (Math .cos (Math .PI / 180.0 * Math .abs (lat )), 2 );
312
- return Math .floor (2 * Math .PI / Math .acos (tmp ));
313
- }
314
-
315
204
private int calculateAltitude (short [] data , int typeCode ) {
316
205
// TODO this should use AltitudeEncoding class flagged with mBit false feature.
317
206
int n = (data [5 ] >>> 1 ) << 4 ;
@@ -321,66 +210,4 @@ private int calculateAltitude(short[] data, int typeCode) {
321
210
322
211
return (n * qBit ) - 1000 ;
323
212
}
324
-
325
- public static void start () {
326
- AirbornePosition .cache .clear ();
327
- AirbornePosition .cacheCleanup .schedule (new TimerTask () {
328
- @ Override
329
- public void run () {
330
- List <String > expired = new LinkedList <>();
331
-
332
- synchronized (cache ) {
333
- cache .entrySet ().stream ().filter (entry -> entry .getValue ().isExpired ()).forEach (entry -> expired .add (entry .getKey ()));
334
- expired .forEach (cache ::remove );
335
- }
336
- }
337
- }, 0 , 10_000 );
338
- }
339
-
340
- public static void stop () {
341
- AirbornePosition .cacheCleanup .cancel ();
342
- AirbornePosition .cacheCleanup = null ;
343
-
344
- AirbornePosition .cache .clear ();
345
- }
346
-
347
- class PositionUpdate {
348
- private CprPosition even ;
349
- private CprPosition odd ;
350
-
351
-
352
- private boolean previousPositionAvailable = false ;
353
- private double previousLat ;
354
- private double previousLon ;
355
-
356
- public PositionUpdate (CprPosition even ) {
357
- this .even = even ;
358
- }
359
-
360
- public void setEven (CprPosition even ) {
361
- this .even = even ;
362
- this .odd = null ;
363
- }
364
-
365
- public void setOdd (CprPosition odd ) {
366
- this .odd = odd ;
367
- }
368
-
369
- public void setPreviousPosition (double lat , double lon ) {
370
- this .previousLat = lat ;
371
- this .previousLon = lon ;
372
- }
373
-
374
- public boolean isPreviousPositionAvailable () {
375
- return this .previousPositionAvailable ;
376
- }
377
-
378
- public boolean isComplete () {
379
- return even != null && odd != null ;
380
- }
381
-
382
- public boolean isExpired () {
383
- return even .isExpired () || odd .isExpired ();
384
- }
385
- }
386
213
}
0 commit comments