Sie sind auf Seite 1von 12

Sumber :

http://adsb-decode-guide.readthedocs.org/en/latest/introduction.html

Introduction
Mode S
Mode S is the signal carrying the ADS-B data from aircrafts. Modulation and
demodulation of Mode S signal is out of scope of this guide. From our antenna and
A/D converter, we are able to receive the encoded messages to a Linux agent. Our
focuses are from this point on; working with those data.
If you are interested on digging deeper on the Mode S signal, a good starting point is
to have a look at this Wikipedia page, and follow the references:
https://en.wikipedia.org/wiki/Secondary_surveillance_radar#Mode_S

ADS-B
An ADS-B message is 120 bits long, following is an example:
BIN format:
10001101010010000100000011010110001000000010110011000011
01110001110000110010110011100000010101110110000010011000
HEX format:
8D4840D6202CC371C32CE0576098

This table lists the key bits of a message:


Bit from

Bit to

Abbr.

Name

DF

Downlink Format

CA

Message Subtype

32

ICAO24

ICAO aircraft address

33

88

DATA

Data frame

89

112

PC

Parity check

The type of the message can be identified by checking its Downlink Format (DF), bit
1 to 5. For ADS-B message, we need: DF = 17 (in decimal), or 10001 (in binary),
Within the data frame, another import value is the Type Code. it tells what is inside of
the data frame, it is located from bit 33 to 37 (5 bits)
Bit from

Bit to

Abbr.

Name

33

37

TC

Type Code

ADS-B message types


By looking at the DF and TC we can quickly understand what kind of information is
contained in the data frame. The relations are listed as following:
DF

TC

Content

17

1 to 4

Aircraft identification

17

9 to 18

Aircraft position

17

19

Aircraft velocities

Note that within different type of the messages, the configurations of the bits in data
frame are different. In next chapter, those will be explained in detail.

Decoding
In this section we will explain how to read bits in different types of ADS-B messages,
decode and calculate information, such as aircraft ID, position, speed, and heading.

Aircraft Identification
An aircraft identification message has
For example:
8D4840D6202CC371C32CE0576098

The structure of the message is:

DF: 17 ,

and

TC: 1 to 4 .

| | ICAO24 |
DATA
|
|
|----|--------|----------------|--------|
| 8D | 4840D6 | 202CC371C32CE0 | 576098 |
| DF | CA | ICAO24 ADDRESS
| TC |
| Data
|
|-------|-----|--------------------------|-------|-----|--------------------------------------------------|--------------------------|
|
10001
|
101
|
010010000100000011010110
|
00100
|
000
001011001100001101110001110000110010110011100000 | 010101110110000010011000 |

Note that TC is inside of the DATA frame. DF and TC can be easily calculated:
DF: 10001 -> 17
TC: 00010 -> 4

Those two values confirm that the message is good for decoding aircraft
identification.
Next, we are decoding the data frame containing the aircraft callsign (identification).
In order to get the callsign, a look-up table is needed for mapping index numbers to
letters:
'#ABCDEFGHIJKLMNOPQRSTUVWXYZ#####_###############0123456789######'

In our message data frame, it is easy to decode following:


HEX: 202CC371C32CE0
BIN: 00100 000 | 001011 001100 001101 110001 110000 110010 110011 100000
DEC:
| 11
12
13
49
48
50
51
32
LTR:
| K
L
M
1
0
2
3
_

So now we have the aircraft ID here: KLM1023


Following is the calculation implemented in Python:
def hex2bin(hexstr):
length = len(hexstr)*4
binstr = bin(int(hexstr, 16))[2:]
while ((len(binstr)) < length):
binstr = '0' + binstr
return binstr
def bin2int(binstr):
return int(binstr, 2)
charset
'#ABCDEFGHIJKLMNOPQRSTUVWXYZ#####_###############0123456789######'
msg = "8D4840D6202CC371C32CE0576098"
msgbin = hex2bin(msg)
csbin = msgbin[40:96]
csbin = databin[8:] # get the callsign part
callsign = ''
callsign += charset[ bin2int(csbin[0:6]) ]
callsign += charset[ bin2int(csbin[6:12]) ]

callsign
callsign
callsign
callsign
callsign
callsign

+=
+=
+=
+=
+=
+=

charset[
charset[
charset[
charset[
charset[
charset[

bin2int(csbin[12:18])
bin2int(csbin[18:24])
bin2int(csbin[24:30])
bin2int(csbin[30:36])
bin2int(csbin[36:42])
bin2int(csbin[42:48])

]
]
]
]
]
]

# clean string, remove spaces and marks, if any.


cs = cs.replace('_', '')
cs = cs.replace('#', '')
print callsign

Aircraft Positions
Decoding the positions of the aircraft is a bit more complicated. Naturally, we would
assume to read latitude and longitude directly from the data frame. Unfortunately its
not that simple...
In fact, two different types of the position messages (odd and even frames) are
needed to find out the LAT and LON of the aircraft. The position is described in so
called Compact Position Reporting (CPR) format, which is hard to understand, and
not well documented.
The advantage of CPR is that it uses less bits to encode the position information.
The dis-advantage is obviously the complexity of calculation.
An aircraft position message has

DF: 17 ,

and

TC: from 9 to 18 .

Determine an odd and even frame


For example, two following messages are received:
8D40621D58C382D690C8AC2863A7
8D40621D58C386435CC412692AD6
| | ICAO24 |
DATA
|
|
|----|--------|----------------|--------|
| 8D | 40621D | 58C382D690C8AC | 2863A7 |
| 8D | 40621D | 58C386435CC412 | 692AD6 |

Convert both messages to binary strings:


| DF | CA | ICAO24 ADDRESS
| TC |
| Altitude
| | F | CPR Latitude
| CPR Longitude
|
|
|-------|-----|--------------------------|-------|-----|--------------|---|---|-------------------|-------------------|-------------------------|
| 10001 | 101 | 010000000110001000011101 | 01011 | 000 | 110000111000 | 0 | 0 |
10110101101001000 | 01100100010101100 | 001010000110001110100111 |
| 10001 | 101 | 010000000110001000011101 | 01011 | 000 | 110000111000 | 0 | 1 |
10010000110101110 | 01100010000010010 | 011010010010101011010110 |

In both message we can find: DF=17 and TC=11 , with the same ICAO24
address 40621D . So those two frames are valid for decoding the positions of this
aircraft.
At each frame, Bit-54 (title F) determine whether it is odd or even:
0 -> Even frame
1 -> Odd frame

Calculate latitude and longitude


There are a few documents explain in detail the math behind the CPR. for
example: A document from Eurocontrol. Our foucus is on decoding, hence the
reversing of those math equations.
Lets frist seperate the CPR latitude and longitude bits in both messages. And the
steps after will guide you to calculate LAT/LON of the aircraft.
| F | CPR Latitude
| CPR Longitude
|
|---|-------------------|-------------------|
| 0 | 10110101101001000 | 01100100010101100 | -> newest frame received
| 1 | 10010000110101110 | 01100010000010010 |

Step 1: Convert the binary string to decimal value


LAT_CPR_EVEN: 93000 / 131072 -> 0.7095
LON_CPR_EVEN: 51372 / 131072 -> 0.3919
LAT_CPR_ODD: 74158 / 131072 -> 0.5658
LON_CPR_ODD: 50194 / 131072 -> 0.3829

131072 is 2^17 since CPR latitude and longitude are encoded in 17 bits. The values
represent the percentages.
Step 2: Calculate the Latitude Index j, using following equation

j=floor(59LatCPRE60LatCPRO+0.5)
j=8

Step 3: Calculate relative latitudes


First, two constants will be used:
DLat_EVEN = 360.0 / 60
DLat_ODD = 360.0 / 59

Then we can use the following equations to compute the relative latitudes:

LatE=DLatE(mod(j,60)+LatCPRE)
LatE=LatE360if (LatE270)
LatO=DLatO(mod(j,59)+LatCPRO)
LatO=LatO360if (LatO270)
If a relative latitude results are greater than 270, it means the aircraft is at southern
hemisphere. Then a substraction of 360 is applied. 131072 is 2^17 since CPR
latitude and longitude are encoded in 17 bits.
Here, we have:
Lat_EVEN = 52.25720214843750
Lat_ODD = 52.26578017412606

Then, we need to check if Lat_EVEN and Lat_ODD are in the same latitude zone. If
not, simply make an exit here; wait for new data, the run the computation again.
There are 60 latitude zones pre-computed. You may refer to the python source code
to see how latitudes degrees are divided into different zones. We have a
function NL() retrieving the NL value In our case, both value are in latitude zone 36,
good to continue.
The final Latitude is chosen by the time stamp of the frames, the newest one is used:

Lat={LatELatOif (T0T1)else
In our case:
Lat = Lat_EVEN = 52.25720214843750

Step 5: Calculate longitude


In order to ge the longitude, we need to first compute the longitude index
and ni with N() function, which also look into the latitude zone table

ni={N(LatE,0)N(LatO,1)if (T0T1)else

m,

m={floor[LonCPRE(NL(LatE)1)LonCPRONL(LatE)
+0.5]floor[LonCPRE(NL(LatO)1)LonCPRONL(LatO)+0.5]if
(T0T1)else
Longitude is then calculated:

Lon={360.0ni(Mod(m,ni)+LonCPRE)360.0ni(Mod(m,ni)+LonCPRO)if
(T0T1)else
Lon=Lon360if (Lon180)
Step 6: So now we have the final coordinate of the aircraft
Lat: 52.25720
Lon: 3.91937

Following is the calculation implemented in Python:


def cpr2position(cprlat0, cprlat1, cprlon0, cprlon1, t0, t1):
cprlat_even = cprlat0 / 131072.0
cprlat_odd = cprlat1 / 131072.0
cprlon_even = cprlon0 / 131072.0
cprlon_odd = cprlon0 / 131072.0
air_d_lat_even = 360.0 / 60
air_d_lat_odd = 360.0 / 59
# compute latitude index 'j'
j = int(59 * cprlat_even - 60 * cprlat_odd + 0.5)
lat_even = float(air_d_lat_even * (j % 60 + cprlat_even))
lat_odd = float(air_d_lat_odd * (j % 59 + cprlat_odd))
if lat_even >= 270:
lat_even = lat_even - 360
if lat_odd >= 270:
lat_odd = lat_odd - 360
# check if both are in the same latidude zone, exit if not
if cprNL(lat_even) != cprNL(lat_odd):
return None
# compute ni, longitude index m, and longitude
if (t0 > t1):
ni = cprN(lat_even, 0)
m = math.floor( cprlon_even * (cprNL(lat_even)-1) - cprlon_odd * cprNL(lat_even) + 0.5 )
lon = (360.0 / ni) * (m % ni + cprlon_even)
lat = lat_even

else:
ni = cprN(lat_odd, 1)
m = math.floor( cprlon_even * (cprNL(lat_odd)-1) - cprlon_odd * cprNL(lat_odd) + 0.5 )
lon = (360.0 / ni) * (m % ni + cprlon_odd)
lat = lat_odd
if lon > 180:
lon = lon - 360
return [lat, lon]

Calculate altitude
Altitude of aircraft in the data frame is much easier to be computed. The bits in the
altitude field (either odd or even frame) are as following:
1100001 1 1000
^
Q-bit

This Q-bit (Bit 48) indicates whether the altitude can be decoded. If the value is zero,
we will exit the calculation. If one, then the altitude value can be computed from the
rest of the bits.
Off the topic: really dont understand why someone wanted to put this bit in the
middle...
After removing Q-bit:
N = 1100001 1000 => 1560 (in decimal)

The final altitude value will be:

Alt=N251000 (ft.)
In the example, the altitude at which aircraft is flying is:
1560 * 25 - 1000 = 38000 ft.

The position
So finally, we have all three value (LAT/LON/ALT) of the aircraft position:
LAT: 52.25720
LAT: 3.91937
ALT: 38000 ft

Aircraft speed and heading


An aircraft velocity message has

DF: 17 , TC: 19 .

For example, following message is received:

8D40621D99454F9E0004A7715C19
| | ICAO24 |
DATA
|
|
|----|--------|----------------|--------|
| 8D | 40621D | 99454F9E0004A7 | 715C19 |
| DF | CA | ICAO24 ADDRESS
| TC | ......
|-------|-----|--------------------------|-------|------| 10001 | 101 | 010000000110001000011101 | 10011 | ......

We can confirm the DF=17 and TC=19. Good to decode the velocity. Next, lets
extract the DATA frame part:
HEX: 99454F9E0004A7
| TC | ST | IC | IFR | VU | S-EW | V-EW
| S-NS | V-NS
| V-rate sign source | TI | GHD sign |
|-------|-----|----|-----|-----|------|------------|------|------------|--------------------|----|------------|
| 10011 | 001 | 0 | 1 | 000 | 1
| 0101001111 | 1
| 0011110000 | 000000000 0 1
| 00 |
1010011 1 |

There are many parameters in the the velocity message. From left to rights, the
number of bits indicate the following contents:
No. of bits

Content

Type code

Subtype

Intent change flag

IFR capability flag

Velocity uncertainty

East-West velocity sign

10

East-West velocity

North-South velocity sign

10

North-South velocity

Vertical rate

No. of bits

Content

Vertical rate sign

Vertical rate source

Turn indicator

7+1

Geometric height difference from barometric + sign

NOTE: If you are also refering an interenet document called ADS-B for Dummies
by EuroControl, be very aware, the information table in that document is NOT
correct !! The bits for velocities and sign were ordered wrong in that document.
For calculating the speed and heading we need four values, East-West
Velocity V(ew) , East-West Velocity Sign S(ew) , North-South Velocity V(ns) , NorthSouth Velocity Sign S(ns) . And pay attention on the directions (signs) in the
calculation.

V(we)={1V(ew)V(ew)if (s(ew)=1)if (s(ew)=0)

V(sn)={1V(ns)V(ns)if (s(ns)=1)if (s(ns)=0)


Speed (v) and heading (h) can be computed as following:

v=V2we+V2sn
h=arctan(VweVsn)3602(deg)
In case of an negative value here, we will simply add 360 degrees.

h=h+360(if h<0)
So, now we have the speed and heading of our example:
V(ew): 0101001111 -> 335
S(ew): 1

V(ns): 0011110000 -> 240


S(ns): 1
V(we) = -335
V(sn) = -240
v = 412.0983 (kn)
h = 234.3815 (deg)

Tips on ADS-B
If you have to write every line of code from scratch, reading and decoding ADS-B
messages can be difficult at some point. Here we have some tips for those who
might encounter the same challenges as we had.

The message structure


All the ADSB messages have a similar structure. Total of 112 bits, started 5 bits of
Downlink Format, followed by 3 bits of the Message Type, then 24 bits of unique 24
bits of ICAO address, after that, is the 56 bits of data frame, and finished by 24 bits
of parity check.
Type Code (bit 33 to 37) in located in inside, at the beginning of the data frame.
For computing the desired aircraft status, we need to have the right type of the data
frame. The type is determined by Downlink Format and Type Code.
Then you can go ahead and decode each message different into correct values.

The CPR positions


The most crazy part is to compute the lat/lon from the Compact Position Reporting
format data. Remember that we need to have two data frame (one odd, and one
even) to calculate one position. Keep timestamps of those data frames, as at one
point you will need to know the newest frame to have a better position calculation.
Withing the calculation process, an lookup table of so called Latitude Zone is used.
check out our code too see how the earth latitudes are divided into 60 zones, of
which are not equally distributed.

Aircraft Identification
After the aircraft ID (aka. Callsign) is decoded, there are sometimes spaces in the
Callsign. Each time you decode on Callsign, you may want to strip the spaces before

using it in your program. Sometimes a tailing space in a string can cause


unexceptionable behaviors.

More than just ADS-B data


Usually the ADS-B data are presented live through a stream from a server (receiver).
In order to have a good robust program, you will also need to do some low level
networking programming to make sure the date are correctly received. Python - of
course - has a great Socket library that can be used easily.

Whats next?
Our research goes far beyond the decoding the ADS-B messages. The goal of this
research of Junzi is to collect large amount of aircraft data from ADS-B signals, and
then using data mining methods to understand, improve, and maybe even create
aircraft performance models.
If you are interested, or you have any question regarding the decoding process,
please feel free to contact Junzi Sun (j.sun-1[at]tudelft.nl)

Das könnte Ihnen auch gefallen