Главная | Декодирование координат из четных и нечетных ADS-B пакетов

Декодирование координат из четных и нечетных ADS-B пакетов

Тэги: 
Тэги: 

Источник: http://www.lll.lu/~edward/edward/adsb/DecodingADSBposition.html

 

Как же декодировать координаты самолета из пакетов ADS-B?

 

Представим что вы приняли два пакета данных:

8D 75 80 4B 58 0F F2 CF 7E 9B A6 F7 01 D0
8D 75 80 4B 58 0F F6 B2 83 EB 7A 15 71 17

 

Байты со 2 по 4 дают ICAO адрес самолета, в данном случае 75804B

 

Для него данные:
CEB [5J] Cebu Pacific Air
Registration RP-C3191
Airbus A319

 

Первые 5 бит пакета содержат формат пакета (Downlink Format (DF)).

 

1-ый байт 8D это 10001-101 что является DF=17 и CA=5

DF 17 указывает нам, что этот пакет является расширенным сквиттером 112 бит длиной.

Не все расширенные сквиттеры содержат координаты. Мы еще должны проверить тип кода (Type Code (TC)).

 

5-ый байт - это первый байт расширенного сквитттера, который содержит на 56 бит (7 байт) больше чем в коротком сквиттере (short squitter).

 

Последние 3 байта не входят в сквиттер и сами по себе не что иное как проверочные коды на ошибку CRC.

 

Тип кода (Type Code - TC) содержится в первых 5 битах пакета.

В примере - Байт 5 = 58hex = 01011-000bin
В обоих пакетах TC = 01011bin = 11dec.

Этот TC является координатами самолета (Airborne Position) с барометрической высотой (Barometric Altitude):

Координаты с погрешностью (Horizontal protection limit): (HPL) 25 m ≤ HPL < 185.2 m (0.1 NM)
95% Containment radius, μ и v, on horizontal and vertical position error: 10 m ≤ μ < 92.6 m (0.05 NM)

 

Navigational uncertainty category: 7

 

Этого по прежнему недостаточно - чтобы начать декодировать координаты нам необходимы нечетные (ODD) и четные (EVEN) пакеты.

Эти пакеты (фреймы frames) содержат координаты в формате CPR (Compact Position Reporting).

 

Четный или нечетный у нас пакет мы может определить по 22 биту расширенного сквиттера.

Переведем данные в двоичную систему:

1 пакет:
580FF2CF7E9BA6
[TC-]     [-Altitude-] T F [----Latitude---] [---Longitutde--]
01011 000 000011111111 0 0 10110011110111111 01001101110100110

 

2 пакет:
580FF6B283EB7A
[TC-]     [-Altitude-] T F [----Latitude---] [---Longitutde--]
01011 000 000011111111 0 1 10101100101000001 11110101101111010

 

В первом байте:
Первые 5 бит это TC =  11.

TC = 11 устанавливает следующие правила декодирования:

Биты 6 и 7 это Surveillance Status.
Бит 8 индицирует antennas used.
Биты с 9 (MSB) по 20-ый (LSB) содержит высоту.
Бит 21 это флаг T (Time). T в этом случае = 0 и указывает, что мы не синхронизированы с UTC.
Бит 22 содержит флаг F индицирующий какой формат CPR используется (четный/нечетный).
Биты с 23 (MSB) по 39-ый (LSB) содержит закодированную latitude.
Биты 40 (MSB) по 56-ой (LSB) содержат закодированную longitude.

 

Так как 1-ый пакет имеет F = 0 то это четный пакет, 2-ой пакет имеет F flag = 1 т.е. он нечетный.

 

Далее рассмотрим как мы можем использовать эту информацию для определения координат самолета.

 

CPR использует некоторые функции, которые лучше изучить заранее:

Nb это количество бит для кодирования.

Координаты в воздушном пространстве используют Nb = 17. Для наземных координат Nb = 19.

 

CPR декодирует координаты по зонам (Zones) Nz. Количество возможных зон для координат в воздухе - Nz = 15 giving an unambiguous airborne range for decoding of 360 NM.

 

Функция floor(x) дает значение k, равное ближайшему целому числу, которое меньше x.

В языках программирования она обозначается как INT.

 

Модуль Modulus MOD(x,y) всегда положителен.
Function modulo(val, modval As Double) As Double
  modulo = val Mod modval
  If val < 0 Then modulo = modulo + modval
End Function

 

Функция NL(x) больше 1, но всегда в пределах от 1 до 59.

В моей программе я использовал lookup-таблицу как описано в PDF документе 1090-WP-9-14.

 

Начнем со следующих шагов:

Lat(0) = 10110011110111111 или 92095 dec
Lat(1) = 10101100101000001 или 88385 dec
Lon(0) = 01001101110100110 или 39846 dec
Lon(1) = 11110101101111010 или 125818 dec

 

1. Вычисляем latitude индекс j lookup-таблицы:
Вот алгоритм:
j = Int(((59 * Lat(0) - 60 * Lat(1)) / 131072) + 0.5)
это дает
j = 1

 

2. Вычисляем значение Rlat(0) и Rlat(1):
rlat(0) = AirDlat0 * (modulo(j, 60) + Lat(0) / 131072)
rlat(1) = AirDlat1 * (modulo(j, 59) + Lat(1) / 131072)
где константы
Const AirDlat0 As Double = 6
Const AirDlat1 As Double = 360 / 59

 

это дает:
rlat(0) =  10.2157745361328
rlat(1) =  10.2162144547802
Примечание: Южноеполушарные значения (hemisphere values) имеют значение от 270° до 360°. Вычитайте 360°.

 

3. NL для Rlat(0) и Rlat(1): NL(0) и NL(1) оба равны 59. Не продолжайте далее если NL(0) не равно NL(1).
NL(0) =  59
NL(1) =  59
Обя NL равны так как rlat(0) и rlat(1) наши latitudes.

 

4. последний пакет нечетный, i = 1, вычисляем n(i) которое больше 1 и NL(i) - i
ni = 58

 

5. Далее Dlon(i) = 360 / n(i)
dlon(1) =  6.20689655172414

 

6.Находим M, индекс для longitude. Вы должны знать, что в этом случае T = 1 (нечетный).
M = Int((((Lon(0) * (nl(T) - 1)) - (Lon(1) * nl(T))) / 131072) + 0.5)
дает
M = -39

 

7. Вычисляем global longitude, Lon
Lon = dlon(T) * (modulo(M, ni) + Lon(T) / 131072)
дает
Lon =  123.889128586342

 

Вот и все!

Второй пакет дал

Lon =  123.889128586342
Lat =  10.2162144547802

 

Также во 2-ом пакете для примера: высота (Altitude) равна 2175 feet

но это уже другая история...

 
 
 

Комментарии

Clicky

Яндекс.Метрика