見出し画像

無料のAISデータで東京湾の船舶をリアルタイム追跡してみた(コード付き)

前回はSentinel-2の衛星画像から東京湾の船を数えた。358隻と320隻。10mピクセルの画像に映る「明るい点」を統計的に拾い上げる方法で、それなりの数字が出た。

しかし衛星画像だけでは、その船がコンテナ船なのかタンカーなのか漁船なのかわからない。サイズは推定できても、積荷も船籍も目的地も見えない。
AISデータにはその情報がある ── はずだった。


AISとは何か

AIS(Automatic Identification System)は、船舶が自動で発信する位置情報のシステムだ。SOLAS条約で300トン以上の国際航海船舶に搭載が義務づけられている。

船のGPSのようなもの、と思ってもらえればいい。ただしGPSが「自分の位置を知る」ための仕組みなのに対して、AISは「自分の位置を周囲に伝える」ための仕組みだ。VHF無線で数秒〜数分ごとに、自船のMMSI(固有ID)、緯度経度、速度、針路、船名、船種、目的地を自動送信する。

このAIS信号を地上局や衛星で受信すれば、海上交通を丸ごとリアルタイムで追跡できる。MarineTrafficやVesselFinderのような船舶追跡サービスは、このAISデータを可視化したものだ。


AISStream.ioで東京湾のデータを取る

AISデータの入手方法はいくつかある。MarineTraffic APIは高機能だが有料で、個人利用のハードルが高い。AISHubは受信局を持つユーザー間でデータを相互提供する仕組みだが、自前の受信局が必要になる。

今回はAISStream.ioを使った。無料のWebSocket APIで、GitHubアカウントがあればAPIキーを取得できる。BoundingBox(緯度経度の矩形)を指定して接続すると、そのエリア内の船舶データがリアルタイムで流れてくる。

東京湾のBoundingBox:
南端: 35.2°N(浦賀水道入口)
北端: 35.7°N(東京港)
西端: 139.5°E(横浜)
東端: 140.1°E(千葉・木更津)

subscribe_message = {
    "APIKey": api_key,
    "BoundingBoxes": [[[35.2, 139.5], [35.7, 140.1]]],
    "FilterMessageTypes": ["PositionReport", "ShipStaticData"],
}
async with websockets.connect(ws_url) as ws:
    await ws.send(json.dumps(subscribe_message))
    # ここからAISデータがリアルタイムで流れてくる

コードの全文はGitHub(satlens/satlens)で公開している。


5分間のテスト:34隻を検知

まず小さく試す。2026年3月15日の朝8:52(JST)、AISStream.ioに接続して5分間データを受信した。

結果:

AIS船舶位置マップ(49隻)収集時間: 5分間受信メッセージ数: 51ユニーク船舶数: 34隻ShipStaticData受信: 5隻分港湾アプローチ内: 5隻

34隻の中から、いくつかの船を拾ってみる:

YM INAUGURATION(MMSI: 416487000 / 台湾 / 16.1kn)— 陽明海運のコンテナ船。浦賀水道を北上中

DONGJIN VENUS(MMSI: 441805000 / 韓国 / 0kn)— 停泊中。東京港付近
COMET ACE(MMSI: 351757000 / パナマ / 0kn)— 便宜置籍。横須賀付近に係留

REI MARU(MMSI: 431001046 / 日本 / 7.6kn)— 内航船。湾内を航行中
FUKUWAMARU NO.5(MMSI: 431600647 / 日本 / 0.4kn)— 微速。横須賀エリアで作業中か

ShipStaticDataからは船体寸法も取れた。APOLLON HIGHWAY(MMSI: 353013000)は全長200m、喫水9.3m、目的地はオーストラリア。パナマ船籍の大型自動車運搬船だ。


この数字は妥当なのか

34隻という数字は多いのか少ないのか。

MDPI論文 "High-Resolution Mapping of Port Dynamics from Open-Access AIS Data in Tokyo Bay" が参考になる。この研究はAISStream.ioの無料データで東京湾を91日間観測している。その結果、移動中の船舶は瞬間的に平均35±17隻。日次の入出港数は293±22隻。

自分の5分間テストで得た34隻は、91日間の平均値35隻にほぼ一致する。
前回の記事でSentinel-2から検知した358隻(3月7日)とも整理しておく。

Sentinel-2は移動中も停泊中も検知する。AISの34隻は「移動中+AIS発信中」の船だけだ。国交省統計からの瞬間在湾推定(270〜560隻)とSentinel-2の358隻は整合しているし、AISの34隻はその一部を捉えている。


無料データの壁:ship_typeが取れない

AISStream.ioの無料プランでは、MetaData.ShipTypeフィールドが全て0を返す。34隻を検知したが、そのうち何隻がコンテナ船で何隻がタンカーかは、このフィールドからはわからない。

これが無料の対価だ。ただし、打つ手がないわけではない。

MMSI国コードからの推定。 MMSI番号の先頭3桁は船籍国を示す。リベリア(636)、パナマ(370-379)、マーシャル諸島(538)であれば便宜置籍船──つまり大型商船である確率が高い。

船名パターンからの推定。 "YM"は陽明海運、"EVER"は長栄海運のコンテナ船に多い。"MARU"を含む船名は日本の内航船。

航行パターンからの推定。 14ノット以上で直線航行していればコンテナ船の可能性が高い。10ノット前後の中速はタンカーやバルク船。停泊位置も手がかりになる。


5分から7日へ:定期観測の設計

設計はシンプルにした:
収集間隔: 1時間ごと
収集時間: 5分間(300秒)
期間: 7日間
出力: JSON(1収集1ファイル)+ 日次サマリー(JSONL)

# 収集間隔の合間に10秒ごとにシグナルをチェック
while time.time() < wait_end and not shutdown_requested:
    await asyncio.sleep(min(10, wait_end - time.time()))

この定期収集は、記事を書いている時点で既に動いている。結果は次回以降に掲載する予定だ。


Sentinel-2とAISを組み合わせる

ここまでで、東京湾の船舶を見る方法が2つ揃った。

Sentinel-2(衛星画像)
長所: 全船舶が映る。AIS非搭載船も見える
短所: 5日に1回。雲があれば見えない。船種不明

AIS
長所: リアルタイム。船名・速度・目的地がわかる
短所: 小型船が見えない。ship_typeに制限あり
補完関係にある。

Sentinel-2


理想は、Sentinel-2が東京湾を撮影する瞬間(日本時間10:27頃)にAISデータを同時取得して、両者を突き合わせることだ。


考察:何がわかって、何がわからないか

わかったこと:

  • AISStream.ioの無料APIで、東京湾のリアルタイム船舶データは取得可能

  • 5分間で34隻。先行研究(91日間平均35隻)と整合的

  • 船名、MMSI、速度、位置は正確に取得できる

わからないこと:

  • 船種分類(ship_typeフィールドが無料プランでは取得不可)

  • 東京湾の船舶数の日変動・週変動パターン(7日間データ待ち)

  • Sentinel-2との位置照合精度(次回パス待ち)

  • 海運3社の業績との定量的な関係(データ蓄積が足りない)

次回は、VIIRSの夜間光データで、また別の角度から東京湾の経済活動を見てみる。


コード:github.com/satlens/satlens
前回:「Sentinel-2で東京湾の船を数えてみた」
次回:「無料のNASA夜間光データで東京湾の経済活動を可視化してみた」


※ 本記事は個人の技術的な実験の記録であり、特定銘柄の投資推奨ではありません。投資に関する判断はご自身の責任において行ってください。

いいなと思ったら応援しよう!