11package aero .t2s .modes .decoder .df .df17 ;
22
33import aero .t2s .modes .Track ;
4+ import aero .t2s .modes .CprPosition ;
45import aero .t2s .modes .constants .*;
56import aero .t2s .modes .registers .Register05 ;
67import 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