Flightradar24 — как это работает? Часть 2, ADS-B протокол
15 марта 2019, 00:02
Привет Хабр.

Наверное каждый, кто хоть раз встречал или провожал родственников или друзей на самолет, пользовался бесплатным сервисом Flightradar24. Это весьма удобный способ отслеживания положения самолета в реальном времени.

В первой части был описан принцип работы такого онлайн-сервиса. Сейчас мы пойдем дальше, и выясним, какие данные передаются и принимаются от воздушного судна к приемной станции, и декодируем их самостоятельно с помощью Python.

История

Очевидно, что данные о самолетах передаются не для того, чтобы пользователи видели их на своих смартфонах. Система называется ADS–B (Automatic dependent surveillance—broadcast), и служит для автоматической передачи информации о воздушном судне в диспетчерский центр — передаются его идентификатор, координаты, направление, скорость, высота и прочие данные. Ранее, до появления таких систем, диспетчер мог видеть лишь точку на радаре. Этого стало недостаточно, когда самолетов стало слишком много.

Технически, ADS-B состоит из передатчика на воздушном судне, который периодически посылает пакеты с информацией на достаточно высокой частоте 1090 МГц (есть и другие режимы, но нам они не так интересены, т.к. координаты передаются только здесь). Разумеется, кроме передатчика, есть и приемник где-то в аэропорту, но для нас, как для пользователей, интересен приемник наш собственный.

Кстати, для сравнения, первая такая система, Airnav Radarbox, расчитанная на обычных пользователей, появилась в 2007 году, и стоила около 900$, еще около 250$ в год стоила подписка на сетевые сервисы.

Отзывы тех первых российских владельцев можно почитать на форуме radioscanner. Сейчас, когда массово стали доступны RTL-SDR приемники, аналогичный девайс можно собрать за 30$, подробнее об этом было в первой части. Мы же перейдем собственно, к протоколу — посмотрим как это работает.

Прием сигналов

Для начала, сигнал нужно записать. Весь сигнал имеет длительность всего лишь 120 микросекунд, поэтому чтобы комфортно разобрать его компоненты, желателен SDR-приемник с частотой дискретизации не менее 5МГц.

После записи мы получаем WAV-файл с частотой дискретизации 5000000 семплов/сек, 30 секунд такой записи "весят" около 500Мб. Слушать её медиаплеером разумеется, бесполезно — файл содержит не звук, а непосредственно оцифрованный радиосигнал — именно так работает Software Defined Radio.

Открывать и обрабатывать файл мы будем с помощью Python. Желающие поэкспериментировать самостоятельно, могут скачать пример записи по ссылке.

Загрузим файл, и посмотрим что внутри.

from scipy.io import wavfile import matplotlib.pyplot as plt import numpy as np fs, data = wavfile.read("adsb_20190311_191728Z_1090000kHz_RF.wav") data = data.astype(float) I, Q = data[:, 0], data[:, 1] A = np.sqrt(I*I + Q*Q) plt.plot(A) plt.show()

Результат: мы видим явные "импульсы" на фоне шума.

Каждый "импульс" — это и есть сигнал, структуру которого хорошо видно, если увеличить разрешение на графике.

Как можно видеть, картинка вполне соответствует тому, что приведено в описании выше. Можно приступать к обработке данных.

Декодирование

Для начала, нужно получить битовый поток. Сам сигнал закодирован с помощью manchester encoding:

Из разницы уровней в полубайтах легко получить реальные "0" и "1".

bits_str = "" for p in range(8): pos = start_data + bit_len*p p1, p2 = A[pos: pos + bit_len/2], A[pos + bit_len/2: pos + bit_len] avg1, avg2 = np.average(p1), np.average(p2) if avg1 avg2: bits_str += "1"

Структура самого сигнала имеет следующий вид:

Рассмотрим поля более подробно.

DF (Downlink Format, 5 бит) — определяет тип сообщения. Их несколько типов:

(источник таблицы — bibliotheek.knmi.nl/knmipubTR/TR336.pdf)

Нас интересует только тип DF17, т.к. именно он содержит координаты воздушного судна.

ICAO (24 бита) — международный уникальный код воздушного судна. Проверить самолет по его коду можно на сайте junzis.com/adb (к сожалению, автор перестал обновлять базу, но она еще актуальна). К примеру, для кода 3c5ee2 имеем следующую информацию:

DATA (56 или 112 бит) — собственно данные, которые мы и будем декодировать. Первые 5 бит данных — поле Type Code, содержащее описание хранящихся данных. Их также довольно много.

(источник таблицы — mode-s.org/decode/adsb/introduction.html)

Разберем несколько примеров пакетов.

Aircraft identification

Пример в бинарном виде:

00100 011 000101 010111 000111 110111 110001 111000

Поля данных:

+------+------+------+------+------+------+------+------+------+------+ | TC,5 | EC,3 | C1,6 | C2,6 | C3,6 | C4,6 | C5,6 | C6,6 | C7,6 | C8,6 | +------+------+------+------+------+------+------+------+------+------+

TC = 00100b = 4, каждый символ C1-C8 содержит коды, соответствующие индексам в строке:

#ABCDEFGHIJKLMNOPQRSTUVWXYZ#####_###############0123456789######

Раскодировав строку, несложно получить код самолета: EWG7184

symbols = "#ABCDEFGHIJKLMNOPQRSTUVWXYZ#####_###############0123456789######" code_str = "" for p in range(8): c = int(bits_str[8 + 6*p:8 + 6*(p + 1)], 2) code_str += symbols[c] print("Aircraft Identification:", code_str.replace('#', ''))

Airborne position

Если с названием все просто, то с координатами посложнее. Они передаются в виде 2х, четных и нечетных фреймов. Код поля TC = 01011b = 11.

Пример четного и нечетного пакетов:

01011 000 000101110110 00 10111000111001000 10000110101111001 01011 000 000110010000 01 10010011110000110 10000011110001000

Само вычисление координат происходит по достаточно хитрой формуле:

(источник — mode-s.org/decode/adsb/airborne-position.html)

Я не специалист по ГИС, так что откуда оно выводится, не знаю. Кто в курсе, напишите в комментариях.

Высота считается проще — в зависимости от определенного бита, она может представляться либо кратной 25, либо 100 футам.

Airborne Velocity

Пакет с TC=19. Интересно тут то, что скорость может быть как точная, относительно земли (Ground Speed), так и воздушная, измеряемая датчиком самолета (Airspeed). Еще передается множество разных полей:

(источник — mode-s.org/decode/adsb/airborne-velocity.html)

Заключение

Как можно видеть, технология ADS-B стала интересным симбиозом, когда какой-либо стандарт пригождается не только профессионалам, но и обычным пользователям. Но разумеется, ключевую роль в этом сыграло удешевление технологии цифровых SDR-приемников, позволяющим на девайсе буквально "за копейки" принимать сигналы с частотой выше гигагерца.

В самом стандарте разумеется, гораздо больше всего. Желающие могут посмотреть PDF на странице ICAO или посетить уже упомянутый выше сайт https://mode-s.org/decode/.

Вряд ли многим пригодится все вышенаписанное, но по крайней мере общая идея того, как это работает, надеюсь, осталась.

Кстати, готовый декодер на Python уже существует, его можно изучить здесь: https://github.com/junzis/pyModeS. А владельцы SDR-приемников могут собрать и запустить готовый ADS-B декодер со страницы https://github.com/antirez/dump1090.git, подробнее об этом рассказывалось в первой части.

Надеюсь, кому-то было интересно, спасибо за внимание.
habr.com
© ФГУП «ГосНИИПП», 1989-2018