Decoding ADS-B position
How to decode the position of the aircraft from an Odd and an Even CPR ADS-B Frame?
Say you receive the following two frames:
8D75804B580FF2CF7E9BA6F701D08D75804B580FF6B283EB7A157117Bytes 2 to 4 give ICAO address
75804B which is
CEB [5J] Cebu Pacific Air
Registration RP-C3191
Airbus A319
The first 5 bits contain the Downlink Format (DF).
First byte 8D is
10001-101 so DF=17 and CA=5
DF
17 means we have an extended 112 bit squitter. Not all extended
squitters have the position. We need to check the Type Code (TC).
Byte 5 is the first byte of the extended squitter as such, which is an extra 56 bits compared to a short squitter.
This makes up to the last 3 bytes not included. These last 3 bytes are an error check.
The Type Code is contained in the first 5 bits which is in Byte 5 of the whole frame: 58hex is
01011-000bin
Both TC are
01011bin which is 11dec.
This TC is Airborne Position with Barometric Altitude as follows:
Airborne position with Horizontal protection limit: (HPL) 25 m ≤ HPL < 185.2 m (0.1 NM)
95% Containment radius, μ and v, on horizontal and vertical position error: 10 m ≤ μ < 92.6 m (0.05 NM)
Navigational uncertainty category: 7
This is still not sufficient, as to start decoding positions we need an ODD and an EVEN frame.
These frames contain the position in CPR (Compact Position Reporting) format.
Whether a frame is odd or even is indicated in bit 22 of the extended squitter.
As we need more binary data lets change the extended squitters into binary.
The first frame:
580FF2CF7E9BA6[TC-] [-Altitude-] T F [----Latitude---] [---Longitutde--]01011 000 000011111111 0 0 10110011110111111 01001101110100110The second frame:
580FF6B283EB7A[TC-] [-Altitude-] T F [----Latitude---] [---Longitutde--]01011 000 000011111111 0 1 10101100101000001 11110101101111010In the first byte:
First 5 bits are the TC which is 11.
A TC 11 decodes to the following fields:
Bits 6 and 7 are the Surveillance Status.
Bit 8 indicates the antennas used.
Bits 9 (MSB) to 20 (LSB) contain the altitude.
Bit 21 contains the T (Time) bit. T in this case is 0 which means we are not synchronized to UTC.
Bit 22 contains the F flag which indicates which CPR format is used (odd or even).
Bits 23 (MSB) to 39 (LSB) contain the encoded latitude.
Bits 40 (MSB) to 56 (LSB) contain the encoded longitude.
So our first frame has F flag = 0 so is even and the second frame has F flag = 1 so odd.
So we finaly know that we can use our information to find the position of this aircraft.
CPR uses several functions which are good to know before we start:
Nb is the number of bits for encoding. Airborne positions use
Nb = 17 as we can confirm from above. Note
Nb = 19 for surface positions.
CPR decodes positions to Zones
Nz. The number of possible zones for airborne positions is
Nz = 15 giving an unambiguous airborne range for decoding of 360 NM.
The floor notation
floor(x) denotes which is the greatest integer k such that k<x. In VB6 this is done by the function
INT.
Modulus
MOD(x,y) is always positive. In VB6 I have written it as follows:
Function modulo(val, modval As Double) As Double
modulo = val Mod modval
If val < 0 Then modulo = modulo + modval
End Function
The
NL(x)
is a big one but only returns a number between 1 and 59. In my VB6
progam I use a lookup table as described in the PDF document
1090-WP-9-14.
So our starting point is:
Lat(0) = 10110011110111111 or 92095 decLat(1) = 10101100101000001 or 88385 decLon(0) = 01001101110100110 or 39846 decLon(1) = 11110101101111010 or 125818 dec1. Compute the latitude index
j:
Under VB6 that is done as follows:
j = Int(((59 * Lat(0) - 60 * Lat(1)) / 131072) + 0.5)gives
j = 12. Compute the values of
Rlat(0) and
Rlat(1):
rlat(0) = AirDlat0 * (modulo(j, 60) + Lat(0) / 131072)
rlat(1) = AirDlat1 * (modulo(j, 59) + Lat(1) / 131072)
where
Const AirDlat0 As Double = 6
Const AirDlat1 As Double = 360 / 59
This gives
rlat(0) = 10.2157745361328
rlat(1) = 10.2162144547802
Note: Southern hemisphere values are 270ー to 360ー. Subtract 360ー.
3.
NL for
Rlat(0) and
Rlat(1) ,
NL(0) and
NL(1) are both equal to 59. Do not proceed from here if
NL(0) not equal to
NL(1).
NL(0) = 59
NL(1) = 59
Both NL are equal so rlat(0) and rlat(1) are our latitudes.
4.
i being the frame to decode, the last frame is odd,
i = 1, compute
n(i) which is the greater of 1 and
NL(
i) -
ini = 58
5. Next
Dlon(i) = 360 /
n(i)dlon(1) = 6.20689655172414
6.Find M, the longitude index. You need to know that in this case T = 1 (odd).
M = Int((((Lon(0) * (nl(T) - 1)) - (Lon(1) * nl(T))) / 131072) + 0.5)gives
M = -39 7. Compute the global longitude, Lon
Lon = dlon(T) * (modulo(M, ni) + Lon(T) / 131072)gives
Lon = 123.889128586342 So there you have it!
On the second frame our aircraft was at
Lon = 123.889128586342
Lat = 10.2162144547802
Also on 2nd frame for example: Altitude is 2175 feet but that is a different story ...