Некоторое время назад увидел на одном из форумов обсуждение возможности пеленговать самолёты, принимая отражённые сигналы радаров. Идея казалась интересной, а цель недостижимой для использования в быту, до появления SDR приёмника на основе дешёвого DVB-T донгла на чипсете RTL2832U. С помощью донгла можно оцифровать принимаемый сигнал со скоростью, достаточной для получения разрешающей способности на местности порядка сотни метров, что вполне подходит для эксперимента.
Справедливости ради, в возможность пеленговать самолёты таким способом не очень верю, но сигнал, отражённый крупными наземными объектами должен быть хорошо виден. Второе ограничение — радар использует остронаправленную антенну для излучения и её же для приёма, со слабонаправленной телевизионной антенной, которая использовалась в ходе эксперимента, ожидать высокого разрешения не приходится.
Эксперимент: SDR донгл подключаем к телевизионной антенне, достаём из кустов радар, благо, он находится в аэропорту всего в нескольких километрах и работает в метровом телевизионном диапазоне. Сигнал записываем при помощи SDR# в wav-файл со скоростью 2М измерений в секунду, что даст теоретическое разрешение на местности около 75 метров. Фактом, что излучатель и приёмник разнесены в пространстве пренебрегаем.
После того, как сигналы записаны и выбран лучший образец, пишем скрипт, имитирующий развёртку радара и синхронизацию по первому мощному импульсу.
import os
from PIL import Image, ImageDraw
import wave
import math
dir = os.path.dirname(os.path.abspath(__file__))
image = Image.new("RGB", (1000, 1000), (0, 0, 0))
(w, h) = image.size
sync_level = 45
seconds_max = 40
px_from_center = 30
seconds_per_spin = 20
wav = wave.open(dir + "/samples/134201.wav", mode="r")
(nchannels, sampwidth, framerate, nframes, comptype, compname) = wav.getparams()
data = wav.readframes(nframes)
bytes = nframes * nchannels * sampwidth
seconds = float(nframes) / framerate
px_per_km = int(framerate / 300000.0 * 2)
print(str(bytes) + " bytes, " + str(seconds) + " seconds")
t = 0
avg = 0
synchronized = 0
i = 0
while i < bytes - 4:
l = abs(128 - ord(data[i]))
r = abs(128 - ord(data[i + 2]))
avg = avg * .9 + l * .1
level = l + r
if not synchronized and avg > sync_level:
synchronized = 1
if synchronized:
s = float(i) / bytes * seconds
if s >= seconds_max:
break
if t % (10 * px_per_km) == 0:
level += 20
if t < 400:
x = int(w/2 - (t + px_from_center) * math.cos(s / seconds_per_spin * 2 * math.pi))
y = int(h/2 - (t + px_from_center) * math.sin(s / seconds_per_spin * 2 * math.pi))
image.putpixel((x, y), (level, level, level))
t += 1
if t >= 400:
t = 0
synchronized = 0
avg = 0
i += 4
image.save(dir + "/radar.png", "PNG")
Один оборот радар делает за 20 секунд. Подбираем уровень синхронизации и получаем картинку, устойчиво повторяющуюся с каждым оборотом.
Что нам и требовалось. Картинка достаточно размытая, но ничего не мешает её улучшить, экспериментируя с параметрами и применяя лучшее оборудование.
Исходники вместе с оцифрованным сигналом — 73М