利用ソフト:dump1090-faとpysynscan + 自作のpythonスクリプト
ADSB受信用SDR:RTL-SDR RTL2832U
カメラ制御用経緯台: SkyWatcherのAz-GTi
カメラ:ASI1600MC-COOL + カメラ用レンズ
撮影画像例:距離 10000m程度
おまけ
スマホで航空機を撮影:距離500m程度??
撮影場所、時刻、方向:スマホのGPS情報、加速度センサー等から取得
アメダスは:降水量を観測する観測所は全国に約1,300か所
問題点:
(1)経緯台の回転速度が比較的遅いので、カメラの指向が間に合わないことがある。
(2)航空機までの距離が遠いことが多く、200mm程度の望遠レンズでは、画像から機種の判別は困難
STEP1:ADSBの電波を受信し、航空機のICAOコードと位置(緯度、経度、高度)を取得。
STEP2:航空機の位置(緯度、経度、高度)と、観測場所の緯度、経度から航空機が見える方位と見上げ角度を計算。
STEP3:経緯台のモータを、航空機の方向に向ける。
STEP4:画像を撮影
# -*- coding: utf-8 -*-
from math import *
import time,datetime
import os
import socket
import logging
import synscan
from optparse import OptionParser
PORT = 30003 # Running dump1090-fa
host = '192.168.68.61' #
BUFFER_SIZE = 1024
R_EARTH = 6378137
RAD = 3.14159265 / 180
LAT0,LON0=35.7973, 139.4462
parser = OptionParser()
parser.add_option("-r","--range",action="store",dest="MAX", default=0,type="int",help="Max range")
parser.add_option("-t","--tilt",action="store",dest="TILT_MIN", default=1,type="float",help="Min tilt")
(opts, args) = parser.parse_args()
MAX=opts.MAX
TILT_MIN=opts.TILT_MIN
#MAX = 20000
if MAX == 0:
TEST = True
pH,pT = 0,0
MAX = 50000
print("Test mode")
else:
TEST = False
smc=synscan.motors(udp_ip='192.168.68.200', udp_port=11880)
pH,pT = smc.axis_get_pos(1),smc.axis_get_pos(2)
print('Last PAN,TILT:',pH,pT)
H_MIN ,T_MIN = 0.1, 0.1
def distance(lat1,lon1,lat2,lon2):
lat1,lat2 = lat1*RAD, lat2*RAD
lon1,lon2 = lon1*RAD, lon2*RAD
lat_c = (lat1 + lat2) / 2
try:
dx = R_EARTH*(lon2-lon1)*cos(lat_c)
dy = R_EARTH*(lat2-lat1)
except:
dx,dy = 100000, 100000
pass
return sqrt(dx*dx + dy*dy)
def azimuth(y1,x1,y2,x2):
x1=radians(x1)
y1=radians(y1)
x2=radians(x2)
y2=radians(y2)
deltax = x2 - x1
ans = degrees(atan2(sin(deltax),(cos(y1)*tan(y2)-sin(y1)*cos(deltax))))%360
return ans
Buf = {}
dBuf= {}
T_MAX, L_MAX = 0.5,10
dH, dT = 0, 0
start=time.time()
TGT=None
seq = 0
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((host, PORT))
while True:
str = s.recv(BUFFER_SIZE).decode()
if 'MSG,3' in str:
t = str.split(',')
try:
ID, Lat, Lon, Alt = t[4],t[14],t[15],t[11]
LAT=float(Lat)
LON=float(Lon)
ALT=float(Alt)
except:
LAT, ALT = 0, 0
pass
if LAT>0 and ALT>0:
dist = round(distance(LAT0, LON0, LAT, LON),1)
if dist<MAX:
houi = round(azimuth(LAT0, LON0, LAT, LON),1) + 5 + dH
tilt = round(degrees(atan(ALT*0.3048/dist)),1) + 3 + dT
Buf[ID] ={'TIME':round(time.time(),0),'DIST':dist,'PAN':houi,'TILT':tilt}
dBuf[ID]=dist
else:
pass
if time.time()-start > T_MAX:
now = time.time()
start = time.time()
os.system('clear')
print('---',datetime.datetime.now(),'---','ICAO:',TGT,' PAN:',pH,' TILT:',pT)
for k,v in list(Buf.items()):
last = Buf[k]['TIME']
if now - last > L_MAX:
print('deleted..',k)
del Buf[k]
if k == TGT:
TGT = None
print('TGT:',TGT)
for k,v in Buf.items():
if (TGT is None) or (TGT not in Buf):
TGT = k
print('New target:',TGT)
seq = 1
dH, dT = 0,0
print(k,v)
if TGT is not None and TGT in Buf:
houi, tilt = Buf[TGT]['PAN'], Buf[TGT]['TILT']
#pH,pT = smc.axis_get_pos(1),smc.axis_get_pos(2)
dH, dT = round(pH - houi,1), round(pT - tilt,1)
if (abs(dH)>H_MIN or abs(dT)>T_MIN) and tilt>TILT_MIN and (houi<200 and tilt<80):
pH, pT = houi, tilt
print('*',TGT, houi,'(',dH,')', tilt,'(',dT,')','SEQ:',seq)
seq = seq + 1
if not TEST :
smc.goto(houi,tilt,syncronous=False)
else:
pass