ラズパイとADS-B受信機でミニ飛行機レーダーを作ろう

【PR】この記事には広告が含まれています。

ラズパイとADS-B受信機でミニ飛行機レーダーを作ろう

飛行機の音が聞こえたとき、「この機体はどこへ行くのだろう?」と気になったことはありませんか?

この記事では、Raspberry Piで航空機信号用の受信機を使う方法と「レーダー風表示装置」の作り方を紹介します。リアルタイムで頭上を飛ぶ航空機の位置情報を画面に表示し、自宅で小さな管制塔気分が楽しめます。

ラズパイで飛行機の信号を受信

多くの飛行機は、現在位置・高度・速度・機体番号などの情報を送信しています。そうした通信手段の中でも、旅客機をはじめとする多くの航空機で使われているのが、ADS-B(Automatic Dependent Surveillance–Broadcast) という仕組みです。

そぞら
そぞら

ADS-Bの信号は、受信機を使えばRaspberry Piでも受信できます。

ADS-B受信機を使用

NESDR Mini

今回はNooelec社のNESDR MiniというUSBスティック型のADS-B受信機を使用します。Raspberry Piに接続し、専用のソフトウェアをインストールすることで、航空機が発信する1090MHz帯の信号を受信できます。

そぞら
そぞら

アンテナを室内に置いた状態で、約50km離れた航空機の信号を受信できました。

専用アンテナも付属しているため、すぐに使い始められます。ただし、Raspberry Pi Zeroシリーズを使う場合は、別売りのUSB microBコネクタ用のOTGケーブルが必要です。

Flightradar24にデータ提供も可能

世界中の航空機をリアルタイムで表示するサービスFlightradar24も、ADS-B信号をもとにしています。

Flightradar24

Flightradar24は基本機能を無料で使えますが、30分で自動的にセッションが終了する制限があります。一方、ADS-B受信機を設置すれば、設置場所の周辺に限定されますが、航空機の情報を制限なく受信・表示できます。

チェックポイント

Raspberry PiとADS-B受信機を使ってFlightradar24にデータを提供することで、通常は年間499.99ドル(約7万5千円)かかるBusinessプランを無償で利用できます。Flightradar24へのデータ提供方法については、記事の後半で紹介しています。

ADS-B受信機の使用準備

今回使用したADS-B受信機は、以下のモデルで動作を確認しました。

Raspberry Pi OSについては、ADS-B受信機だけを使う場合は最新のBookwormでも動作します。僕はHyperPixel 2.1 Round(円形ディスプレイ)を使いたかったので、前世代のOSであるBullseye(Legacy版)を使用しました。

OSをインストールする方法は以下の記事で詳しく解説しています。
≫【2025年最新版】OSインストールから初期設定まで|セットアップ手順のすべて

ラズパイとADS-B受信機の接続

ADS-B受信機をRaspberry PiのUSBポートに挿すだけで接続できます。Raspberry Pi Zeroシリーズを使う場合は、別売りのUSB microBコネクタ用のOTGケーブルが必要です。

ソフトウェアの設定

ここからはRaspberry Piを起動して、ADS-B受信機を使える状態にします。

航空機の発信するADS-B信号を受信・表示するために、FlightAwareが提供するdump1090-faというソフトを使います。

dump1090-faを使うために、FlightAwareのパッケージリポジトリをRaspberry Piに追加します。

そぞら
そぞら

リポジトリは、データを管理する「インターネット上の倉庫」のようなイメージです。その倉庫の場所をRaspberry Piに教える作業をします。

ターミナルを開いて、次のコマンドを実行します。これによりFlightAwareが提供するリポジトリ登録用の.debパッケージ(設定ファイル)をインターネットからダウンロードします。

wget https://www.flightaware.com/adsb/piaware/files/packages/pool/piaware/f/flightaware-apt-repository/flightaware-apt-repository_1.2_all.deb

次のコマンドで、先ほどダウンロードした .debパッケージをインストールします。

sudo dpkg -i flightaware-apt-repository_1.2_all.deb

Raspberry Piのパッケージリストを更新します。これにより、dump1090-faがインストール候補として認識されるようになります。

そぞら
そぞら

パッケージリストとは、利用可能なソフトウェアの一覧情報のことです。

sudo apt update

dump1090-faをインストールします。-y オプションは「続行しますか? [Y/n]」の確認をスキップして、自動的に「yes」と答えるためのものです。

sudo apt install -y dump1090-fa

以下はRaspberry Piの起動時に dump1090-fa を自動で起動するよう設定するコマンドです。

sudo systemctl enable dump1090-fa

レーダー表示を自作するために、Pythonで画像や映像を扱えるOpenCVライブラリをインストールします。

sudo apt install -y python3-opencv

Raspberry Piを再起動します。

sudo reboot

再起動後にdump1090-faが自動で起動します。

ADS-B信号の受信を確認

dump1090-faが正常に動作しているかを確認します。Raspberry Piのブラウザを開いて、「http://localhost:8080/」をアドレスバーに入力します。すると、dump1090のリアルタイム航空機マップが表示されます。自宅周辺のマップを確認すると、航空機の情報がキャッチされていることがわかります。

画面の右側には、受信した航空機のリアルタイムデータが表形式で表示されます。各列の意味は以下のとおりです。

ICAO航空機ごとに割り当てられた識別コード(16進数形式)
Ident航空会社名と便名(例:ANA536)
Squawk航空機が送信している4桁の識別コード(航空交通管制で使用)
Altitude (ft)高度(フィート単位)
Speed (kt)速度(ノット単位=海里/時)
Heading進行方向(度)
Msgs受信したメッセージの回数
Age最新データを受信してからの経過時間(秒)

この画面は同じネットワークに接続されたPCやスマホからも閲覧可能です。もしRaspberry PiのIPアドレスが 192.168.1.100 であれば、「http://192.168.1.100:8080/」にアクセスすることで確認できます。

航空機の動きをリアルタイムで見るだけでもワクワクします。ですが、せっかくRaspberry Piを使っているので、受信したデータを活用して、さらに面白いことに挑戦したくなるものです。

Pythonで受信データを処理する

ADS-B信号を活用して何かを作りたいとき、Pythonでデータを取得できると便利です。dump1090-faは受信した航空機の情報を http://localhost:8080/data/aircraft.json というURLでJSON形式として公開しています。このJSONには航空機ごとの緯度・経度・高度・速度・方位などのデータが含まれており、Pythonからアクセスできます。

Thonnyを使ってPythonプログラムを実行する

Raspberry Piでは「Thonny(ソニー)」という初心者向けのPython開発環境が標準でインストールされています。以下の手順でプログラムを実行できます。

デスクトップ画面左上の「ラズベリーメニュー」から「プログラミング」→「Thonny」を開く。

画面中央のエリアに、プログラムをコピー&ペーストして、「実行」ボタンを押す。

下部の「シェル」エリアに、実行結果(航空機の情報)が表示されます。

航空機データの取得テスト

以下のプログラムを実行して、航空機のデータが表示されるかを確認します。

import time
import requests

# 航空機データを取得する関数
def get_aircraft_positions():
    try:
        res = requests.get("http://localhost:8080/data/aircraft.json", timeout=1)
        return [a for a in res.json().get("aircraft", []) if 'lat' in a and 'lon' in a]
    except:
        return []

# 10秒ごとに航空機データを表示
while True:
    aircraft_list = get_aircraft_positions()

    print(f"現在受信中の航空機数: {len(aircraft_list)} 機")
    for a in aircraft_list:
        hex_id = a.get('hex', '不明')
        flight = a.get('flight', hex_id).strip()
        lat = a.get('lat')
        lon = a.get('lon')
        alt = a.get('alt_baro', '不明')
        speed = a.get('gs', '不明')
        track = a.get('track', '不明')

        print(f"便名: {flight} | 緯度: {lat} | 経度: {lon} | 高度: {alt} ft | 速度: {speed} kt | 方位: {track}°")

    # 10秒待機
    time.sleep(10)

このプログラムでは、まずURLにアクセスして航空機データを取得し、位置情報(緯度・経度)を持つものだけを抽出しています。そして、10秒ごとにその情報をシェルに表示します。表示される内容には、便名、緯度・経度、高度(フィート)、速度(ノット)、進行方向(度)が含まれており、上空を飛ぶ航空機の状況がリアルタイムに確認できます。

「シェル」エリアに表示された航空機の情報

これでPythonでデータを取得できることが確認できました。ここからは、このデータを処理するプログラムを作成していきます。

航空機と測定地点の距離を計算

緯度や経度の数値だけを見ても、近いのか遠いのかを判断できません。航空機と測定地点との距離を計算すると、接近しているのか遠ざかっているのかがわかります。

そぞら
そぞら

緯度・経度から距離を計算する方法については、ChatGPTに相談しながらアルゴリズムを作成しました。

以下のプログラムは自宅と航空機の緯度・経度をもとに直線距離を計算し、最も近い航空機の便名とその距離を表示します。この距離は測定地点と航空機の水平距離であり、高度は考慮していません。

import time
import requests
import math

# 自宅の緯度・経度に変更してください(例:東京駅付近)
HOME_LAT = 35.681236
HOME_LON = 139.767125

# 航空機データを取得する関数
def get_aircraft_positions():
    try:
        res = requests.get("http://localhost:8080/data/aircraft.json", timeout=1)
        return [a for a in res.json().get("aircraft", []) if 'lat' in a and 'lon' in a]
    except:
        return []

# ハーサイン距離計算(地球上の2点間の距離をkmで返す)
def haversine(lat1, lon1, lat2, lon2):
    R = 6371.0  # 地球の半径 (km)
    lat1_rad = math.radians(lat1)
    lon1_rad = math.radians(lon1)
    lat2_rad = math.radians(lat2)
    lon2_rad = math.radians(lon2)
    dlat = lat2_rad - lat1_rad
    dlon = lon2_rad - lon1_rad
    a = math.sin(dlat/2)**2 + math.cos(lat1_rad) * math.cos(lat2_rad) * math.sin(dlon/2)**2
    c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
    return R * c

# 10秒ごとに一番近い航空機を表示
while True:
    aircraft_list = get_aircraft_positions()
    closest = None
    min_distance = float('inf')

    for a in aircraft_list:
        lat = a.get('lat')
        lon = a.get('lon')
        if lat is not None and lon is not None:
            distance = haversine(HOME_LAT, HOME_LON, lat, lon)
            if distance < min_distance:
                min_distance = distance
                closest = a

    if closest:
        flight = closest.get('flight', closest.get('hex', '不明')).strip()
        print(f"最も近い便名: {flight} | 自宅からの距離: {min_distance:.2f} km")
    else:
        print("航空機データが取得できませんでした。")

    time.sleep(10)

測定地点の座標は、プログラム内6行目の HOME_LAT(緯度)と HOME_LON(経度)という変数に設定されています。東京駅の座標が入力されていますが、この値は自由に変更できます。

チェックポイント

緯度と経度はGoogleマップで調べることができます。地図上で自宅などの位置を右クリックすると、小さなメニューが表示されます。その一番上に、「35.○○○○○○, 139.○○○○○○」のような緯度と経度の数値が出てきます。

このプログラムは10秒ごとに航空機のデータを取得し、各機体との距離を順に計算。その中でもっとも距離が近い機体を特定し、便名と距離を表示します。

コードを応用すれば、以下のようなディスプレイ表示も可能です。

距離の数値が少しずつ縮まっていくのを見ると、ワクワクして思わず窓を開け、飛行機の音に耳を澄ませてしまいます。

簡易的なレーダー風表示の作成

航空機の緯度経度情報をもとに、他の機体や測定地点との位置関係をプロットする方法を模索します。以下のコードは取得した航空機の位置データをリアルタイムで画面に可視化するものです。

import cv2
import requests
import numpy as np
import math
import time

# 自宅の緯度経度(例:東京駅周辺)
HOME_LAT = 35.6812
HOME_LON = 139.7671

# ウィンドウサイズと中心座標
WIDTH = 480
HEIGHT = 480
CENTER_X = WIDTH // 2
CENTER_Y = HEIGHT // 2

# 縮尺(緯度経度 → ピクセル)
SCALE = 400

# 航空機データ取得関数
def get_aircraft_positions():
    try:
        res = requests.get("http://localhost:8080/data/aircraft.json", timeout=1)
        return [a for a in res.json().get("aircraft", []) if 'lat' in a and 'lon' in a]
    except:
        return []

# 点線円を描く関数    
def draw_dotted_circle(img, center, radius, color=(0, 255, 0), spacing=2, dot_length=1):
    cx, cy = center
    circumference = 2 * math.pi * radius
    steps = int(circumference / (spacing + dot_length))

    for i in range(steps):
        angle_start = 2 * math.pi * (i * (spacing + dot_length)) / circumference
        angle_end = angle_start + (dot_length / radius)

        x1 = int(cx + radius * math.cos(angle_start))
        y1 = int(cy + radius * math.sin(angle_start))
        x2 = int(cx + radius * math.cos(angle_end))
        y2 = int(cy + radius * math.sin(angle_end))

        cv2.line(img, (x1, y1), (x2, y2), color, 1)

# 三角形で航空機を描画する関数
def draw_triangle(img, center, angle_deg, color=(0, 255, 0)):
    x, y = center
    length = 15
    width = 5
    angle_rad = math.radians(angle_deg)

    tip = (int(x + length * math.sin(angle_rad)), int(y - length * math.cos(angle_rad)))
    left = (int(x - width * math.cos(angle_rad)), int(y - width * math.sin(angle_rad)))
    right = (int(x + width * math.cos(angle_rad)), int(y + width * math.sin(angle_rad)))

    points = np.array([tip, left, right], dtype=np.int32)
    cv2.fillPoly(img, [points], color)

cv2.namedWindow("Radar Display")
cv2.resizeWindow("Radar Display", WIDTH, HEIGHT)

last_update = 0
aircraft_list = []

while True:
    frame = np.zeros((HEIGHT, WIDTH, 3), dtype=np.uint8)

    # 中心(自宅)のマーカー
    cv2.circle(frame, (CENTER_X, CENTER_Y), 2, (0, 255, 0), -1)
    
    # 緑の点線の中央縦線
    for y in range(0, HEIGHT, 10):
        if (y // 10) % 2 == 0:
            cv2.line(frame, (CENTER_X, y), (CENTER_X, y + 5), (0, 255, 0), 1)

    # 緑の点線の中央横線
    for x in range(0, WIDTH, 10):
        if (x // 10) % 2 == 0:
            cv2.line(frame, (x, CENTER_Y), (x + 5, CENTER_Y), (0, 255, 0), 1)

    # 点線円を3本描く
    for r in [60, 140, 220]:
        draw_dotted_circle(frame, (CENTER_X, CENTER_Y), r)


    # 1秒ごとにデータ更新
    if time.time() - last_update > 1.0:
        aircraft_list = get_aircraft_positions()
        last_update = time.time()

    # 各航空機を描画
    for a in aircraft_list:
        dx = (a['lon'] - HOME_LON) * SCALE
        dy = (a['lat'] - HOME_LAT) * SCALE
        x = int(CENTER_X + dx)
        y = int(CENTER_Y - dy)

        if 0 <= x < WIDTH and 0 <= y < HEIGHT:
            if 'track' in a and isinstance(a['track'], (int, float)):
                draw_triangle(frame, (x, y), a['track'])
            else:
                cv2.circle(frame, (x, y), 5, (0, 255, 0), -1)

    cv2.imshow("Radar Display", frame)

    if cv2.waitKey(30) & 0xFF == 27:  # ESCキーで終了
        break

cv2.destroyAllWindows()

まず、自宅の緯度経度を基準としてウィンドウの中心に固定し、各航空機の緯度・経度の差をピクセル換算(SCALE)して、画面上に位置を描画します。

そぞら
そぞら

この部分も、自分の環境に応じた緯度経度に変更してください。

18行目のSCALE = 400 は、緯度・経度の差を画面上のピクセルに変換するための倍率です。この値を大きくすると表示範囲が狭くなり、航空機が大きく動くように見えます。逆に小さくすると広範囲を表示できます。表示範囲や航空機の密度に応じて、SCALE の数値は適宜調整してください。

進行中の機体には「track」と呼ばれる方位情報が含まれており、これは航空機がどの方角へ向かっているか(真北を0度として時計回り)を示します。

この方位情報をもとに、航空機のアイコンを進行方向に向かって回転させて表示します。アイコンは三角形を使って機体の向きを表現しており、先端が進行方向を指すように描画します。trackの値が取得できない場合には、代わりに緑色の円で機体の位置を示します。

1秒ごとにデータ取得・描画を繰り返すことで、リアルタイムな位置関係を描き出しています。

飛行機がどの方向へ向かっているか、測定地点から見てどこに位置しているかを、視覚的に把握することが可能になりました。

ミニレーダー風表示装置の作り方

いよいよミニレーダーの作成に着手します。ここからの内容は、以下の構成で作成しています。

モデルRaspberry Pi Zero 2 W
OSRaspberry Pi OS Bullseye (Legacy, 32-bit)
ディスプレイHyperPixel 2.1 Round

HyperPixel 2.1 Roundの設定

出典:Pimoroni

ディスプレイはHyperPixel 2.1 Roundを使用しました。小型の円形ディスプレイで、ミニレーダーにはぴったりなアイテムです。GPIOに接続し、設定を行うことで、Raspberry Piのデスクトップ画面をそのまま表示できます。

ラズパイはディスプレイの裏側にすっきり収まるサイズのRaspberry Pi Zero 2 Wを使用しました。

HyperPixel 2.1 RoundとZero 2 W

Raspberry Piとディスプレイを接続します。40本のピンヘッダーをまるごと差し込みます。

HyperPixel 2.1 RoundでRaspberry Piの画面を表示するには、カーネルドライバを有効にする必要があります。

ターミナルを開いて以下のコマンドを1行ずつ順に実行します。

git clone https://github.com/pimoroni/hyperpixel2r
cd hyperpixel2r
sudo ./install.sh

ディスプレイを正しく動作させるために、/boot/config.txtの中にある「dtoverlay=vc4-kms-v3d」の行を無効化します。

sudo nano /boot/config.txt

開いたファイルの中で、「dtoverlay=vc4-kms-v3d」の行を探して、先頭に # を追加します。

編集が終わったら、Ctrl + O で保存し、Ctrl + X でエディタを終了します。

以下のコマンドでI2Cを無効化します。

sudo raspi-config nonint do_i2c 1

再起動すると、画面が表示されます。ディスプレイは円形のため、画面の四隅にあるスタートメニューなどは表示されません。

タッチ操作にも対応していますが、このサイズではGUI操作が難しいため、基本的にはVNCでの操作をおすすめします。

画面の自動暗転機能を無効化する

「Raspberry Piの設定」を開いて「画面のブランク」という項目をオフにします。これは、一定時間何も操作しないと画面が暗くなる機能です。この機能が有効になっていると、レーダーを長時間表示し続けることができません。

スタンドの作成

機器を設置するためのスタンドを、Tinkercadで設計して3Dプリンターで作りました。

デザインは、戦闘機のコックピットにある計器をイメージしています。

設計が完成したらプリント開始。およそ2時間で印刷が終わりました。

スタンドに機器を取り付けた様子。

デザインやサイズを調整しながら、5回ほど試作を重ねました。

レーダー画像と飛行機アイコンの準備

回転するレーダーの動画は、Pixabayで公開されているものをダウンロードして使用します。Pixabayは著作権フリーの画像、動画、音声などを共有するサイトです。サイズは640×360のものをダウンロードしました。

Pixabay

飛行機の位置を示すためのアイコン画像を作成しました。透過PNG形式の飛行機アイコン画像は、ChatGPTに作ってもらい、サイズはパソコンで48ピクセルに調整しました。

plane_icon.png

動画とアイコンはファイル名をradar.mp4とplane_icon.pngに変更して、Raspberry Piの「/home/pi」ディレクトリ、または実行するプログラムを保存するディレクトリに保存します。WindowsパソコンからRaspberry Piにファイルを移動する場合は、WinSCPを利用すると便利です。

そぞら
そぞら

ファイル名や保存場所が正しくないと、プログラムから呼び出せなくなります。

ミニレーダー風ディスプレイのプログラム

以下のプログラムでは、先ほど保存した radar.mp4 を背景動画として表示し、plane_icon.png の飛行機アイコンを航空機の位置に合わせて画面上に描画します。

import cv2
import requests
import numpy as np
import math
import time

# 自宅の緯度経度に変更してください(以下は東京駅周辺)
HOME_LAT = 35.6812
HOME_LON = 139.7671

# 画面サイズと中心座標
WIDTH = 480
HEIGHT = 480
CENTER_X = WIDTH // 2
CENTER_Y = HEIGHT // 2

# 緯度経度→ピクセル変換倍率
SCALE = 300

# 飛行機アイコンの読み込み(アルファチャンネル付き)
icon = cv2.imread("plane_icon.png", cv2.IMREAD_UNCHANGED)
icon_h, icon_w = icon.shape[:2]

# 背景レーダー動画の読み込み
cap = cv2.VideoCapture("radar.mp4")
fps = cap.get(cv2.CAP_PROP_FPS)
delay = int(1000 / fps) if fps > 0 else 33  # フレーム遅延時間(ms)

# 航空機データ取得関数
def get_aircraft_positions():
    try:
        res = requests.get("http://localhost:8080/data/aircraft.json", timeout=1)
        return [a for a in res.json().get("aircraft", []) if 'lat' in a and 'lon' in a]
    except:
        return []

# 飛行機アイコンを回転描画する関数
def draw_icon_rotated(img, icon, center, angle_deg):
    x, y = center
    M = cv2.getRotationMatrix2D((icon_w // 2, icon_h // 2), -angle_deg, 1.0)
    rotated = cv2.warpAffine(
        icon, M, (icon_w, icon_h),
        flags=cv2.INTER_NEAREST,
        borderMode=cv2.BORDER_CONSTANT,
        borderValue=(0, 0, 0, 0)
    )

    # アイコン貼り付け位置の計算
    x1 = x - icon_w // 2
    y1 = y - icon_h // 2
    x2 = x1 + icon_w
    y2 = y1 + icon_h

    # 画面外ならスキップ
    if x1 < 0 or y1 < 0 or x2 > img.shape[1] or y2 > img.shape[0]:
        return

    # ROI合成(アルファブレンド)
    roi = img[y1:y2, x1:x2]
    if rotated.shape[2] == 4:
        alpha = rotated[:, :, 3] / 255.0
        for c in range(3):
            roi[:, :, c] = (1 - alpha) * roi[:, :, c] + alpha * rotated[:, :, c]

# ウィンドウを全画面表示
cv2.namedWindow("Radar Display", cv2.WINDOW_NORMAL)
cv2.setWindowProperty("Radar Display", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)

# 初期化
aircraft_list = []
last_update = 0

while True:
    now = time.time()
    if now - last_update >= 1.0:
        aircraft_list = get_aircraft_positions()
        last_update = now    
    
    # 動画フレームの読み込み
    ret, video_frame = cap.read()
    if not ret:
        cap.set(cv2.CAP_PROP_POS_FRAMES, 0)  # 動画を最初に戻す
        continue

    # 動画のリサイズ(1.8倍ズーム+アスペクト比維持)
    video_h, video_w = video_frame.shape[:2]
    scale = min(WIDTH / video_w, HEIGHT / video_h) * 1.8
    new_w = int(video_w * scale)
    new_h = int(video_h * scale)
    resized = cv2.resize(video_frame, (new_w, new_h), interpolation=cv2.INTER_NEAREST)
    resized = cv2.convertScaleAbs(resized, alpha=0.6, beta=0)  # 薄く表示

    # 最終描画フレーム(黒背景)
    frame = np.zeros((HEIGHT, WIDTH, 3), dtype=np.uint8)

    # 動画の貼り付け位置計算(中央寄せ)
    x_offset = (WIDTH - new_w) // 2
    y_offset = (HEIGHT - new_h) // 2
    x1_dst = max(x_offset, 0)
    y1_dst = max(y_offset, 0)
    x1_src = max(-x_offset, 0)
    y1_src = max(-y_offset, 0)
    x2_dst = min(x_offset + new_w, WIDTH)
    y2_dst = min(y_offset + new_h, HEIGHT)
    x2_src = x1_src + (x2_dst - x1_dst)
    y2_src = y1_src + (y2_dst - y1_dst)

    # 動画フレームを合成
    frame[y1_dst:y2_dst, x1_dst:x2_dst] = resized[y1_src:y2_src, x1_src:x2_src]

    # 航空機データ取得
    aircraft_list = get_aircraft_positions()

    # 航空機ごとにアイコンを描画
    for a in aircraft_list:
        dx = (a['lon'] - HOME_LON) * SCALE
        dy = (a['lat'] - HOME_LAT) * SCALE
        x = int(CENTER_X + dx)
        y = int(CENTER_Y - dy)

        # 画面内に収まっているか判定
        if 0 <= x < WIDTH and 0 <= y < HEIGHT:
            if 'track' in a and isinstance(a['track'], (int, float)):
                draw_icon_rotated(frame, icon, (x, y), a['track'])
            else:
                cv2.circle(frame, (x, y), 5, (0, 255, 0), -1)

    # フレーム表示
    cv2.imshow("Radar Display", frame)

    # ESCキーで終了
    key = cv2.waitKey(delay) & 0xFF
    if key == 27:
        break

# 終了処理
cap.release()
cv2.destroyAllWindows()

HOME_LATHOME_LON は、レーダー画面の中心となる自宅の位置を表す緯度・経度です(この例では東京駅付近を指定しています)。航空機の位置は、この基準点からの相対的な距離をもとに計算され、画面上に配置されます。

そぞら
そぞら

自分の環境に応じた緯度と経度に変更してください。

SCALE = 300 は、緯度・経度の差を画面上のピクセルに変換するための倍率です。この値を大きくすると表示範囲が狭くなり、航空機が大きく動くように見えます。逆に小さくすると広範囲を表示できます。表示範囲や航空機の密度に応じて、SCALE の数値は適宜調整してください。

プログラムの終了は、ESCキーを押すことでウィンドウが閉じられ、処理が終了します。画面はフルスクリーンで表示されるため、実際のレーダー装置のような見た目に仕上がります。

ESCキーでプログラムを終了できます。

レーダー画面の表示例

無事にミニレーダーが完成しました。飛行機の動きを眺めているだけでも飽きません。

Flightradar24へデータ提供する

自宅で受信した航空機のADS-B信号をFlightradar24に提供することで、航空ネットワークに貢献できます。その見返りとして、通常は有料のプレミアム機能が無料で使えるようになります。
ここでは、データ提供するメリットとデメリットを整理します。

メリット

  • Flightradar24のBusinessプランが無料になる
  • いつでもやめられる(データ送信を停止しても金銭的・法的な不利益なし)

デメリット

  • Raspberry Piのリソースを使用(低スペック機では他の作業に影響)
  • ラズパイの位置情報をFlightradar24に提供する必要あり

Flightradar24のアカウントを作成する

データを提供するには、Flightradar24のアカウントが必要です。

Flightradar24のウェブサイトにアクセスし、画面右上の「Login」をクリックします。

表示されたウィンドウの下部にある “Learn more | Create account” をクリックします。

表示されたこのプラン比較画面で、左端の「Free」プランの下にある「Create account」ボタンをクリックします。

メールアドレス・パスワードを入力し、アカウントを作成します。

登録したメールアドレスに確認メールが届くので、リンクをクリックして認証します。

fr24feed(フィーダーソフト)をインストールする

次に、Flightradar24にデータを送るためのソフト「fr24feed」をRaspberry Piにインストールします。

そぞら
そぞら

このソフトを使うには、dump1090-faがインストールされていて、起動している必要があります。

dump1090-faのインストールや起動がまだの場合は、この記事の前半にある「ソフトウェアの設定」パートの手順を先に行ってください。

ターミナルで以下のコマンドを実行

sudo bash -c "$(wget -O - https://repo-feed.flightradar24.com/install_fr24_rpi.sh)"

このコマンドは、Flightradar24のデータ送信ソフト「fr24feed」をRaspberry Piにダウンロードしてインストールするためのものです。

インストール後、自動的に設定ウィザードが始まります。ターミナルにいくつかの質問が表示されるので、それぞれに答えてエンターキーを押してください。以下のように回答します。

Step質問内容回答の例
1.1Flightradar24アカウントのメールアドレス登録したメールアドレスを入力
1.2Sharing keyの入力以前使用したキーがあれば入力
なければそのままEnter
1.3MLAT(Multilateration)に参加するか?
※複数の受信機が同時に受け取った信号の到達時間差からADS-B信号のない航空機の位置を推定する技術

yes または no を入力してEnter
(基本は yes でOK)
3.Aアンテナ設置位置の緯度例:35.6812
Googleマップ等で調査可
3.Bアンテナ設置位置の経度例:139.7671
3.Cアンテナ設置位置の高度(フィート)例: 108
地面の標高+アンテナ設置位置までの高さ(m)× 3.28084(フィート換算)
標高は国土地理院地図で調査可
入力内容の確認yes または no を入力してEnter
「autoconfig 機能」を使うかどうかの確認基本は yes でOK

すべて正常に完了すると、「Installation and configuration completed!」と表示されます。

データ提供の確認

以下のコマンドでfr24feedの動作状況を確認します。

fr24feed-status

最下行の「FR24 MLAT: not running … failed!」は、MLAT(複数の受信機で航空機の位置を推定する機能)が正常に動作していないことを示しています。

申し訳ありません

「FR24 MLAT: not running … failed!」について、以下の記事を参考に設定を見直しましたが、解決には至っていません。https://intaa.net/archives/21762 

Flightradar24(FR24)の公式フォーラムによると、MLATが動作するには、同じ航空機の信号を複数の受信局が同時に受信している必要があります。今回はMLATだけが停止しているため、この受信条件が満たされていない可能性があると推測されますが、現時点で断定はできません。

なお、ADS-B信号の受信とFlightradar24へのデータ提供は正常に行われており、Businessプランの適用にも影響はありません。

そぞら
そぞら

今後、MLATが正常に動作する方法が分かり次第、この記事に追記します。

Raspberry Piのブラウザで http://localhost:8754 にアクセスすると、fr24feedの動作状況(受信状態、送信状態、MLATの状態など)をリアルタイムで確認できます。

Flightradar24のウェブサイトにアクセスし、画面右上のユーザーアイコンに「Business」と表示されていれば、Businessプランが適用済みです。

Flightradar24へのデータ提供を中止する

データ提供はいつでも停止することができます。中止しても料金が発生することはありません。

データ提供を中止するには、以下を1行ずつ実行します。

sudo systemctl stop fr24feed
sudo systemctl disable fr24feed

これにより、fr24feedが停止し、次回以降の起動時にも自動実行されなくなります。

まとめ

ADS-B受信機は買って大正解のアイテムでした。Raspberry Piとの相性も抜群で、ラズパイユーザーには特におすすめです。

受信したデータを自動で処理したり、リアルタイムに表示したりといった処理を、小型で省電力なRaspberry Piだけで完結できるからです。

そぞら
そぞら

本記事で紹介したプログラムは、ChatGPTの力を借りながら作成しました。

初心者の方でも、AIを活用すれば比較的ハードルを感じずに取り組めると思います。

ADS-B受信機はほかにもいろいろな活用ができそうなので、試行錯誤を楽しんでいるところです。新しいものを作ったらまた紹介します。

コメント一覧

川上龍也

RaspberryPI 学び始めた高齢者ですが、夢ある学びです。
是非、実現できるよう関連記事も拝読して学びの深掘りします。
ユメをありがとうございました。

返信する
とおりすがり

すばらしいです!!
部屋に置きたくなりました。
公開してくださりありがとうございます。

MLATのエラーはこちらが参考になるかもです
https://intaa.net/archives/21762

返信する
とおりすがり2

ワクワクする記事、ありがとうございます!raspberry piって何かやったら次何に使おうか悩むんっですよね~これからも楽しみにしています!

返信する

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です