Pull to refresh

Хак радара

Reading time 2 min
Views 62K


Некоторое время назад увидел на одном из форумов обсуждение возможности пеленговать самолёты, принимая отражённые сигналы радаров. Идея казалась интересной, а цель недостижимой для использования в быту, до появления 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М
Tags:
Hubs:
+64
Comments 51
Comments Comments 51

Articles