衛星回線設計 — リンクバジェットの計算と設計マージン

衛星放送(BS/CS)を受信するためのパラボラアンテナは、なぜ直径45 cmなのでしょうか。30 cmではだめなのか、60 cmなら画質は良くなるのか — この問いに答えるには、「送信側の電力からアンテナを通って受信機に届くまでの電力収支(パワーバジェット)」を定量的に計算する必要があります。この電力収支の計算がリンクバジェット(link budget)です。

リンクバジェットは衛星通信に限らず、全ての無線通信システムの設計基盤です。5Gの基地局設計、Wi-Fiのアクセスポイント配置、レーダーの探知距離計算に至るまで、無線システムエンジニアが日常的に行う最も基本的な設計作業がリンクバジェットの計算です。衛星通信では地上-宇宙間の膨大な伝搬損失を扱うため、dB計算の威力を実感でき、リンクバジェットの考え方を深く理解するのに最適な題材です。

本記事の内容

  • リンクバジェットの基本概念と全体構造
  • EIRP(等価等方放射電力)の定義と意味
  • G/T(受信性能指数)の定義と雑音温度の計算
  • C/N比と$E_b/N_0$の関係
  • 各種損失(大気、降雨、偏波不整合、ポインティング)の見積もり
  • 設計マージンの考え方と稼働率設計
  • PythonによるGEO/LEO衛星のリンクバジェット計算と感度解析

前提知識

この記事を読む前に、以下の記事を読んでおくと理解が深まります。

また、以下の概念に馴染みがあることを前提とします。

  • デシベル(dB、dBm、dBW)の定義と加減算
  • 自由空間伝搬損失(FSPL)の計算
  • 熱雑音の基本概念

リンクバジェットの全体像

家計簿としてのリンクバジェット

リンクバジェットは、文字通り「リンク(通信回線)のバジェット(予算)」です。家計簿で収入から支出を差し引いて残高を確認するのと同じように、送信電力(収入)から各種損失(支出)を差し引き、受信機に届く信号の品質(残高)が必要最小限以上かどうかを確認します。

家計簿の残高がマイナスになれば生活できないように、リンクバジェットの残高(マージン)がマイナスになれば通信ができません。逆に、残高が必要以上に大きければ、送信電力を下げたり、アンテナを小さくしたりしてコストを削減する余地があります。

リンクバジェットの基本方程式

リンクバジェットの最も基本的な形は、フリスの伝達公式をdB表記したものです。

$$ \frac{C}{N} = \text{EIRP} – L_{\text{path}} – L_{\text{other}} + \frac{G}{T} – 10\log_{10}(k_B \cdot B) $$

ここで、各項の意味は以下の通りです。

  • $C/N$ [dB]: 搬送波対雑音電力比(通信品質の指標)
  • $\text{EIRP}$ [dBW]: 等価等方放射電力(送信側の能力)
  • $L_{\text{path}}$ [dB]: 自由空間伝搬損失
  • $L_{\text{other}}$ [dB]: その他の損失(大気、降雨、ポインティング等)
  • $G/T$ [dB/K]: 受信系の性能指数
  • $k_B$ [W/(Hz・K)]: ボルツマン定数 = $1.38 \times 10^{-23}$
  • $B$ [Hz]: 帯域幅

この式はdBの世界で書かれているため、全ての項が加減算で扱えます。これがdBの最大の利点です。各項を順に詳しく見ていきましょう。

EIRP — 送信側の能力

EIRPの定義

EIRP(Equivalent Isotropically Radiated Power, 等価等方放射電力)は、「もし等方性アンテナで全方向に均等にこのEIRP値の電力を放射したら、実際のアンテナがビーム方向に放射しているのと同じ電力密度が得られる」という仮想的な電力です。

もう少し身近に言えば、懐中電灯のビームの明るさを「もし全方向に同じ明るさで光る電球だとしたら何ワットに相当するか」で表したようなものです。懐中電灯は実際には数ワットの電力しか消費しませんが、光を一方向に集中させているため、ビーム方向の照度は電球よりはるかに明るくなります。

数式で表すと、EIRPは送信電力とアンテナ利得の積です。

$$ \text{EIRP} = P_t \cdot G_t $$

dB表記では:

$$ \text{EIRP [dBW]} = P_t \text{[dBW]} + G_t \text{[dBi]} $$

ここで $P_t$ は送信機の出力電力(アンテナ入力端)、$G_t$ はアンテナの利得(等方性アンテナ基準、dBi)です。

パラボラアンテナの利得

衛星通信で最も一般的なパラボラアンテナの利得は、開口面積と効率から計算できます。

$$ G = \eta \left(\frac{\pi D}{\lambda}\right)^2 $$

dBで表すと次のようになります。

$$ G \text{[dBi]} = 10\log_{10}\left[\eta\left(\frac{\pi D}{\lambda}\right)^2\right] $$

ここで $D$ はアンテナの直径、$\lambda$ は波長、$\eta$ は開口効率(典型的には0.55〜0.70)です。

たとえば、直径1.2 m、開口効率0.6のアンテナを周波数12 GHz($\lambda = 0.025$ m)で使う場合、利得は次のようになります。

$G = 0.6 \times (\pi \times 1.2 / 0.025)^2 = 0.6 \times (150.8)^2 = 0.6 \times 22,741 = 13,645$ (真数)

$G = 10\log_{10}(13,645) = 41.4$ dBi

この利得は「アンテナビームの方向に、等方性アンテナの13,645倍の電力密度を集中させている」ことを意味します。

EIRPの具体例

典型的な衛星通信システムのEIRPを見てみましょう。

システム 送信電力 $P_t$ アンテナ利得 $G_t$ EIRP
GEO衛星(Kuバンド、スポットビーム) 100 W (20 dBW) 36 dBi 56 dBW
地上VSAT局(Kuバンド、1.2 m) 4 W (6 dBW) 41 dBi 47 dBW
Starlink衛星 数W程度 約38 dBi 約44 dBW
Starlink端末(Ku帯) 約2 W (3 dBW) 約35 dBi 約38 dBW

EIRPはリンクバジェットの「収入」に相当する最初の項です。次に、この電力が宇宙を旅する間にどれだけ「支出」されるかを見ていきましょう。

伝搬損失と各種損失

自由空間伝搬損失(FSPL)

リンクバジェットにおいて最も大きな「支出」項目が自由空間伝搬損失です。GEO衛星のKu帯ダウンリンクの場合、次のようになります。

$$ L_{\text{FSPL}} = 32.44 + 20\log_{10}(d_{\text{km}}) + 20\log_{10}(f_{\text{MHz}}) $$

GEO衛星($d = 35,786$ km)、Ku帯ダウンリンク($f = 12$ GHz = 12,000 MHz)の場合:

$$ L_{\text{FSPL}} = 32.44 + 20\log_{10}(35786) + 20\log_{10}(12000) = 32.44 + 91.07 + 81.58 = 205.1 \text{ dB} $$

205 dBという損失は途方もない値です。真数に直すと $10^{20.5} \approx 3.2 \times 10^{20}$ 倍、つまり信号は $3200$ 億の1億倍も弱くなります。しかし、これは電波が球面状に広がることの当然の帰結であり、高い利得のアンテナで「集光」することで実用的な通信が成立します。

大気吸収損失

地球の大気を通過する際に、酸素と水蒸気による吸収損失が加わります。仰角 $\theta$ で衛星を見る場合、大気の見かけの厚さが $1/\sin\theta$ 倍になるため、低仰角ほど損失が大きくなります。

$$ L_{\text{atm}} \approx \frac{A_{\text{zenith}}}{\sin\theta} $$

ここで $A_{\text{zenith}}$ は天頂方向($\theta = 90°$)の大気吸収損失です。Ku帯(12 GHz)では約0.05〜0.1 dB、Ka帯(20 GHz)では約0.2〜0.5 dBの天頂損失が典型的です。仰角10度では $1/\sin(10°) \approx 5.8$ 倍となるため、Ku帯で約0.3〜0.6 dB、Ka帯で約1.2〜3 dBに増大します。

降雨減衰

衛星回線設計で最も大きな変動要因が降雨減衰です。降雨減衰の大きさは周波数、降雨強度、電波の経路長(仰角と降雨高度に依存)で決まります。

衛星リンクにおける降雨減衰の経路長は、降雨が存在する高度(降雨高度 $h_R$、日本では約4〜5 km)と仰角 $\theta$ から次のように求められます。

$$ L_s = \frac{h_R – h_s}{\sin\theta} $$

ここで $h_s$ は地上局の標高です。比減衰 $\gamma_R$(dB/km)を用いて、降雨減衰は次のようになります。

$$ A_{\text{rain}} = \gamma_R \cdot L_s \cdot r $$

$r$ は距離低減係数(降雨が経路全体に一様でないことの補正)です。

日本(東京、$R_{0.01} = 63$ mm/h)でのKu帯GEO衛星回線(仰角38度)の降雨減衰は、年間0.01%超過確率で約3〜5 dBが典型的です。Ka帯では10〜20 dBに達し、大きな設計マージンが必要になります。

偏波不整合損失

送信アンテナと受信アンテナの偏波が完全に一致していない場合、偏波不整合損失が生じます。円偏波を使う衛星通信では、アンテナの軸比(axial ratio)が有限であることによる損失が含まれます。典型的には0.1〜0.5 dBです。

ポインティング損失

アンテナのビームが衛星の方向から若干ずれている場合、ビームパターンの主ローブの端を使うことになり、利得が低下します。これがポインティング損失です。

$$ L_{\text{point}} \approx 12\left(\frac{\Delta\theta}{\theta_{3\text{dB}}}\right)^2 \quad \text{[dB]} $$

ここで $\Delta\theta$ はポインティング誤差角、$\theta_{3\text{dB}}$ は半値幅(3 dBビーム幅)です。GEO衛星からの固定受信では追尾精度が高いため0.1 dB程度ですが、LEO衛星の高速追尾では0.5〜1 dBに達することがあります。

その他の損失

実際のリンクバジェットでは、さらに以下の損失を考慮します。

  • フィーダー損失: アンテナとトランシーバーをつなぐ導波管やケーブルでの損失。0.5〜2 dB
  • 走査損失(scan loss): フェーズドアレイアンテナでビームを走査した際の利得低下
  • 散乱損失: 雨滴や大気の乱れによる散乱。通常は降雨減衰に含まれる

伝搬損失と各種損失が「支出」側の項目です。次に、受信側の能力を表すG/Tについて見ていきましょう。

G/T — 受信系の性能指数

雑音温度の概念

受信系の性能を理解するには、まず「雑音温度」の概念を押さえる必要があります。全ての電子回路は熱雑音を発生させます。抵抗値 $R$ の抵抗器が温度 $T$(ケルビン)にあるとき、帯域幅 $B$ の中で発生する雑音電力は次のようになります。

$$ N = k_B T B $$

ここで $k_B = 1.38 \times 10^{-23}$ W/(Hz・K)はボルツマン定数です。この式から、雑音電力は温度に比例することが分かります。そこで、任意の雑音源の雑音電力を「等価な温度」で表すのが雑音温度の考え方です。

システム雑音温度

衛星通信の受信系全体のシステム雑音温度 $T_{\text{sys}}$ は、主に3つの成分の和です。

$$ T_{\text{sys}} = T_a + T_{\text{LNB}} + T_{\text{other}} $$

  • $T_a$(アンテナ雑音温度): アンテナが「見ている」方向からの雑音。宇宙空間は約3 K(宇宙背景放射)ですが、大気を通して見ると20〜50 K程度。地面を見ると290 K。サイドローブから入る地面の放射も寄与する
  • $T_{\text{LNB}}$(低雑音増幅器の雑音温度): LNB(Low Noise Block Converter)や低雑音増幅器(LNA)が発生する雑音。高品質なLNBでは30〜60 K、汎用品では70〜150 K
  • $T_{\text{other}}$: フィーダー損失による雑音寄与、後段の受信機の雑音(LNBの利得で割った値)

受信系の設計では、最初の増幅段(LNB/LNA)の雑音温度が最も重要です。カスケード接続された受信系の雑音温度は、フリスの雑音公式で計算されます。

$$ T_{\text{sys}} = T_a + T_1 + \frac{T_2}{G_1} + \frac{T_3}{G_1 G_2} + \cdots $$

ここで $T_i$ と $G_i$ は各段の雑音温度と利得です。最初の段の利得 $G_1$ が十分に大きければ、2段目以降の雑音寄与は無視できるほど小さくなります。これが「低雑音増幅器を最初に置く」ことの物理的な根拠です。

G/Tの定義

受信系の性能指数 $G/T$ は、受信アンテナの利得 $G_r$ とシステム雑音温度 $T_{\text{sys}}$ の比です。

$$ \frac{G}{T} \text{[dB/K]} = G_r \text{[dBi]} – 10\log_{10}(T_{\text{sys}} \text{[K]}) $$

$G/T$ は受信系が「微弱な信号をどれだけ効率的に検出できるか」を表す単一の指標です。$G/T$ が大きいほど受信性能が高く、同じ送信条件でより遠い距離からの、あるいはより微弱な信号を受信できます。

たとえば、直径45 cmのBSアンテナ(利得約33 dBi)にシステム雑音温度120 Kの受信系を使う場合:

$$ \frac{G}{T} = 33 – 10\log_{10}(120) = 33 – 20.8 = 12.2 \text{ dB/K} $$

$G/T$ の値は、アンテナを大きくするか($G$ を増やす)、受信系の雑音を下げるか($T$ を減らす)で改善できます。コスト面では、アンテナの大型化より低雑音LNBの採用のほうが安価なことが多いです。

リンクバジェットの「収入」(EIRP)と「支出」(各種損失)、そして「受信能力」($G/T$)を理解したところで、これらを組み合わせて通信品質の指標であるC/N比を求めましょう。

C/N比と$E_b/N_0$

C/N比の計算

搬送波対雑音電力比 $C/N$ は、受信した信号電力と受信機内部の雑音電力の比です。リンクバジェットの最終的な「残高」に相当します。

$$ \frac{C}{N} \text{[dB]} = \text{EIRP [dBW]} – L_{\text{total}} \text{[dB]} + \frac{G}{T} \text{[dB/K]} – 10\log_{10}(k_B) – 10\log_{10}(B) $$

ここで $L_{\text{total}} = L_{\text{FSPL}} + L_{\text{atm}} + L_{\text{rain}} + L_{\text{point}} + L_{\text{feeder}} + \cdots$ は全損失の合計です。ボルツマン定数のdB値は次のようになります。

$$ 10\log_{10}(k_B) = 10\log_{10}(1.38 \times 10^{-23}) = -228.6 \text{ dB(W/Hz/K)} $$

この $-228.6$ という値は衛星通信で頻繁に登場する定数です。マイナスの損失は「利得」として加算されるため、$C/N$ の式は次のように整理されます。

$$ \frac{C}{N} = \text{EIRP} + 228.6 – L_{\text{total}} + \frac{G}{T} – 10\log_{10}(B) $$

$E_b/N_0$ との関係

デジタル通信では、$C/N$ よりも$E_b/N_0$(ビットあたりのエネルギー対雑音電力密度比)が性能指標として使われます。$E_b/N_0$ はビットレート $R_b$ と帯域幅 $B$ を通じて $C/N$ と関係します。

$$ \frac{E_b}{N_0} = \frac{C}{N} \cdot \frac{B}{R_b} $$

dB表記では次のようになります。

$$ \frac{E_b}{N_0} \text{[dB]} = \frac{C}{N} \text{[dB]} + 10\log_{10}\left(\frac{B}{R_b}\right) $$

$B/R_b$ は帯域利用効率の逆数に対応し、使用する変調方式と符号化率によって決まります。

たとえば、QPSK変調でFEC符号化率3/4の場合、スペクトル効率は約1.5 bit/s/Hzなので $B/R_b \approx 1/1.5$。したがって:

$$ \frac{E_b}{N_0} = \frac{C}{N} – 10\log_{10}(1.5) = \frac{C}{N} – 1.8 \text{ dB} $$

DVB-S2X(衛星放送のデジタル標準規格)では、変調方式と符号化率の組み合わせ(ModCod)ごとに必要な $E_b/N_0$(または $C/N$)が規定されています。適応変調(ACM: Adaptive Coding and Modulation)では、リンク品質に応じてModCodをリアルタイムに切り替えることで、スループットを最大化しつつ回線断を防ぎます。

アップリンクとダウンリンクの合成C/N

衛星通信はアップリンクとダウンリンクの2つのリンクで構成されます。ベントパイプトランスポンダの場合、衛星はアップリンクの雑音をそのまま増幅して中継するため、全体のC/Nは各リンクのC/Nの「調和平均」に近い形で合成されます。

$$ \left(\frac{C}{N}\right)_{\text{total}}^{-1} = \left(\frac{C}{N}\right)_{\text{up}}^{-1} + \left(\frac{C}{N}\right)_{\text{down}}^{-1} + \left(\frac{C}{N}\right)_{\text{IM}}^{-1} $$

dB表記では直接計算できないため、真数に変換してから計算します。

$$ \left(\frac{C}{N}\right)_{\text{total}} = \frac{1}{\frac{1}{(C/N)_{\text{up}}} + \frac{1}{(C/N)_{\text{down}}} + \frac{1}{(C/N)_{\text{IM}}}} $$

ここで $(C/N)_{\text{IM}}$ はトランスポンダの相互変調雑音成分です。この式から、全体のC/Nは最も低いリンクのC/Nに支配されることが分かります。アップリンクのC/Nが30 dBでダウンリンクが10 dBなら、全体はほぼ10 dB程度にしかなりません。

設計マージンの考え方

なぜマージンが必要か

リンクバジェットの計算で求めたC/N比が、通信に必要なC/N比ちょうどであれば、それは「晴天で全てが完璧な条件」での計算値です。しかし実際には、降雨による追加損失、アンテナのポインティング誤差、機器の経年劣化、太陽との合(太陽雑音の増加)など、多くの変動要因が存在します。

これらの変動要因に対する余裕が設計マージン(link margin)です。

$$ \text{Margin} = \left(\frac{C}{N}\right)_{\text{calculated}} – \left(\frac{C}{N}\right)_{\text{required}} $$

降雨マージンと稼働率設計

降雨減衰は最も大きな変動要因であり、特にKa帯以上で設計の制約となります。降雨マージンの大きさは、目標とする稼働率(availability)によって決まります。

稼働率 年間停止時間 降雨超過確率 典型的な降雨マージン(Ku帯、東京)
99.5% 43.8時間 0.5% 約1〜2 dB
99.9% 8.8時間 0.1% 約2〜4 dB
99.99% 52.6分 0.01% 約5〜8 dB
99.999% 5.3分 0.001% 約10〜15 dB

99.99%の稼働率(年間約53分の停止を許容)を目標とする場合、東京のKu帯GEO回線では約5〜8 dBの降雨マージンが必要です。Ka帯では15〜20 dBに跳ね上がるため、サイトダイバーシティ(地理的に離れた2箇所の地上局を使い、片方が降雨でも他方で通信を維持する)や適応変調が不可欠になります。

その他のマージン

降雨以外にも以下のマージンが考慮されます。

  • 実装マージン(implementation margin): 変復調器の理論性能と実際の性能の差。1〜2 dB
  • 経年劣化マージン: 衛星の太陽電池パネルの劣化、送信管の劣化。15年の設計寿命で2〜3 dB
  • ポインティング劣化マージン: アンテナの追尾誤差。0.5〜1 dB
  • 干渉マージン: 隣接衛星からの干渉。0.5〜1 dB

これらのマージンの合計が、リンクバジェットの「安全余裕」として確保されます。

理論的な枠組みを理解したところで、次にPythonで具体的なリンクバジェット計算を実装し、各パラメータの感度を可視化してみましょう。

Pythonで学ぶリンクバジェット

リンクバジェット計算ツール

まず、汎用的なリンクバジェット計算関数を実装し、GEO衛星のKu帯ダウンリンクの具体例を計算します。

import numpy as np
import matplotlib.pyplot as plt

# 物理定数
Re = 6371         # 地球半径 [km]
c = 3e8           # 光速 [m/s]
kB = 1.38e-23     # ボルツマン定数 [W/(Hz*K)]
kB_dB = -228.6    # dB(W/Hz/K)

def antenna_gain(diameter_m, freq_ghz, efficiency=0.6):
    """パラボラアンテナの利得 [dBi]"""
    lam = c / (freq_ghz * 1e9)
    G = efficiency * (np.pi * diameter_m / lam)**2
    return 10 * np.log10(G)

def slant_range(altitude_km, elev_deg):
    """衛星までのスラント距離 [km]"""
    elev = np.radians(elev_deg)
    h = altitude_km
    d = -Re * np.sin(elev) + np.sqrt((Re * np.sin(elev))**2 +
         2 * Re * h + h**2)
    return d

def fspl(distance_km, freq_ghz):
    """自由空間伝搬損失 [dB]"""
    return 20 * np.log10(distance_km * 1e3) + 20 * np.log10(freq_ghz * 1e9) + \
           20 * np.log10(4 * np.pi / c)

def link_budget(eirp_dbw, freq_ghz, distance_km, gt_dbk, bandwidth_hz,
                atm_loss_db=0.3, rain_loss_db=0, point_loss_db=0.3,
                feeder_loss_db=0.5, misc_loss_db=0.5):
    """
    リンクバジェットを計算する
    返り値: dict with all parameters
    """
    # 自由空間損失
    L_fspl = fspl(distance_km, freq_ghz)

    # 全損失
    L_total = L_fspl + atm_loss_db + rain_loss_db + point_loss_db + \
              feeder_loss_db + misc_loss_db

    # C/N計算
    cn = eirp_dbw + kB_dB - L_total + gt_dbk - 10 * np.log10(bandwidth_hz)

    # C/N0 (帯域幅正規化)
    cn0 = cn + 10 * np.log10(bandwidth_hz)

    return {
        'EIRP': eirp_dbw,
        'FSPL': L_fspl,
        'Atm_loss': atm_loss_db,
        'Rain_loss': rain_loss_db,
        'Point_loss': point_loss_db,
        'Feeder_loss': feeder_loss_db,
        'Misc_loss': misc_loss_db,
        'L_total': L_total,
        'G/T': gt_dbk,
        'Bandwidth': bandwidth_hz,
        'C/N': cn,
        'C/N0': cn0,
    }

# === GEO Ku帯ダウンリンクの例 ===
print("=" * 60)
print("GEO Ku-Band Downlink Budget (BSat-like)")
print("=" * 60)

# パラメータ
sat_alt = 35786       # km
elev = 38             # 度(東京からBSat方向)
freq_dl = 12.0        # GHz
sat_tx_power = 20     # dBW (100 W)
sat_ant_gain = 36     # dBi
eirp = sat_tx_power + sat_ant_gain  # = 56 dBW

# 受信側
rx_ant_dia = 0.45     # m
rx_ant_gain = antenna_gain(rx_ant_dia, freq_dl)
sys_noise_temp = 120  # K
gt = rx_ant_gain - 10 * np.log10(sys_noise_temp)

# 距離
dist = slant_range(sat_alt, elev)

# 帯域幅(1トランスポンダ 36 MHz)
bw = 36e6

# 計算
result = link_budget(
    eirp_dbw=eirp,
    freq_ghz=freq_dl,
    distance_km=dist,
    gt_dbk=gt,
    bandwidth_hz=bw,
    atm_loss_db=0.3,
    rain_loss_db=0,     # 晴天時
    point_loss_db=0.2,
    feeder_loss_db=0.3,
    misc_loss_db=0.5
)

print(f"\n--- 送信側 ---")
print(f"  衛星送信電力: {sat_tx_power} dBW ({10**(sat_tx_power/10):.0f} W)")
print(f"  衛星アンテナ利得: {sat_ant_gain} dBi")
print(f"  EIRP: {eirp} dBW")
print(f"\n--- 伝搬 ---")
print(f"  スラント距離: {dist:.0f} km")
print(f"  仰角: {elev}°")
print(f"  FSPL: {result['FSPL']:.1f} dB")
print(f"  大気損失: {result['Atm_loss']:.1f} dB")
print(f"  降雨損失: {result['Rain_loss']:.1f} dB (晴天)")
print(f"  ポインティング損失: {result['Point_loss']:.1f} dB")
print(f"  フィーダー損失: {result['Feeder_loss']:.1f} dB")
print(f"  その他損失: {result['Misc_loss']:.1f} dB")
print(f"  全損失: {result['L_total']:.1f} dB")
print(f"\n--- 受信側 ---")
print(f"  受信アンテナ直径: {rx_ant_dia} m")
print(f"  受信アンテナ利得: {rx_ant_gain:.1f} dBi")
print(f"  システム雑音温度: {sys_noise_temp} K ({10*np.log10(sys_noise_temp):.1f} dBK)")
print(f"  G/T: {gt:.1f} dB/K")
print(f"\n--- 結果 ---")
print(f"  帯域幅: {bw/1e6:.0f} MHz")
print(f"  C/N: {result['C/N']:.1f} dB")
print(f"  C/N0: {result['C/N0']:.1f} dB·Hz")

# DVB-S2の必要C/N(QPSK 3/4で約4.7 dB)
cn_required = 4.7
margin = result['C/N'] - cn_required
print(f"\n  必要C/N (QPSK 3/4): {cn_required} dB")
print(f"  マージン: {margin:.1f} dB")

この計算結果から、BSat型のGEO Ku帯ダウンリンクの実際のバランスが具体的に分かります。晴天時にはQPSK 3/4で十分なマージンが確保できています。このマージンの一部が降雨時の減衰を吸収するための「備え」として機能します。

GEO vs LEOのリンクバジェット比較

次に、GEO衛星とLEO衛星のリンクバジェットを直接比較してみましょう。

import numpy as np
import matplotlib.pyplot as plt

# GEO vs LEO の比較
print("\n" + "=" * 70)
print("GEO vs LEO Link Budget Comparison (Ka-Band Downlink)")
print("=" * 70)

configs = {
    'GEO Ka-band': {
        'altitude': 35786, 'elev': 38, 'freq': 20.0,
        'sat_power_dbw': 20, 'sat_gain_dbi': 42,
        'rx_diameter': 0.60, 'sys_temp': 200,
        'atm': 0.5, 'rain': 0, 'point': 0.3,
        'feeder': 0.3, 'misc': 0.5
    },
    'LEO Ka-band\n(Starlink-like)': {
        'altitude': 550, 'elev': 40, 'freq': 20.0,
        'sat_power_dbw': 7, 'sat_gain_dbi': 38,
        'rx_diameter': 0.50, 'sys_temp': 250,
        'atm': 0.5, 'rain': 0, 'point': 0.8,
        'feeder': 0.3, 'misc': 0.5
    }
}

fig, axes = plt.subplots(1, 2, figsize=(14, 7))

for idx, (name, cfg) in enumerate(configs.items()):
    dist = slant_range(cfg['altitude'], cfg['elev'])
    eirp = cfg['sat_power_dbw'] + cfg['sat_gain_dbi']
    rx_gain = antenna_gain(cfg['rx_diameter'], cfg['freq'])
    gt = rx_gain - 10 * np.log10(cfg['sys_temp'])

    result = link_budget(
        eirp_dbw=eirp, freq_ghz=cfg['freq'], distance_km=dist,
        gt_dbk=gt, bandwidth_hz=500e6,
        atm_loss_db=cfg['atm'], rain_loss_db=cfg['rain'],
        point_loss_db=cfg['point'], feeder_loss_db=cfg['feeder'],
        misc_loss_db=cfg['misc']
    )

    # ウォーターフォールチャート(段階的な積み上げ)
    items = [
        ('EIRP', eirp, '#4CAF50'),
        ('FSPL', -result['FSPL'], '#F44336'),
        ('Atm Loss', -cfg['atm'], '#FF9800'),
        ('Rain Loss', -cfg['rain'], '#FFEB3B'),
        ('Point Loss', -cfg['point'], '#FF5722'),
        ('Feeder Loss', -cfg['feeder'], '#795548'),
        ('Misc Loss', -cfg['misc'], '#9E9E9E'),
        ('G/T', gt, '#2196F3'),
        ('-kB', 228.6, '#00BCD4'),
        ('-10log(B)', -10*np.log10(500e6), '#673AB7'),
    ]

    cumulative = 0
    labels = []
    values = []
    colors = []
    bottoms = []

    for label, val, color in items:
        labels.append(label)
        values.append(val)
        colors.append(color)
        bottoms.append(cumulative if val > 0 else cumulative + val)
        cumulative += val

    bars = axes[idx].barh(labels, [abs(v) for v in values],
                            left=bottoms, color=colors, alpha=0.8, height=0.6)

    # C/N値を表示
    axes[idx].axvline(x=cumulative, color='red', linewidth=2, linestyle='--')
    axes[idx].text(cumulative + 1, -0.5, f'C/N = {cumulative:.1f} dB',
                    fontsize=12, color='red', fontweight='bold')

    axes[idx].set_xlabel('Cumulative [dB]', fontsize=12)
    axes[idx].set_title(name.replace('\n', ' '), fontsize=13)
    axes[idx].grid(True, alpha=0.3, axis='x')
    axes[idx].invert_yaxis()

plt.tight_layout()
plt.savefig('link_budget_waterfall.png', dpi=150, bbox_inches='tight')
plt.show()

ウォーターフォールチャートから、GEOとLEOのリンクバジェットの構造的な違いが一目で分かります。

  1. FSPLの差が最も顕著: GEO Ka帯のFSPLは約213 dBに達するのに対し、LEO(550 km)では約177 dBと、約36 dBの差があります。この差はLEO衛星の最大の利点であり、低い送信電力でも高いC/Nを実現できる根拠です。

  2. LEOの送信電力はGEOより13 dB低い: GEO衛星のEIRP(62 dBW)に対しLEO衛星は45 dBW程度ですが、FSPLの差が大きいため最終的なC/Nは同等かそれ以上になり得ます。LEO衛星は小型・軽量にできるため、大量生産と低コスト打上げに適しています。

  3. LEOのポインティング損失がやや大きい: LEO衛星は高速で移動するため、端末のフェーズドアレイアンテナの追尾精度に起因するポインティング損失(0.8 dB)がGEO(0.3 dB)より大きくなります。

パラメータ感度解析

リンクバジェットの各パラメータを変化させたときのC/Nへの影響を感度解析で確認します。

import numpy as np
import matplotlib.pyplot as plt

# ベースラインパラメータ(GEO Ku帯ダウンリンク)
baseline = {
    'eirp': 56, 'freq': 12.0, 'altitude': 35786, 'elev': 38,
    'rx_dia': 0.45, 'sys_temp': 120, 'bandwidth': 36e6,
    'atm': 0.3, 'rain': 0, 'point': 0.2, 'feeder': 0.3, 'misc': 0.5
}

def compute_cn(params):
    """ベースラインからC/Nを計算"""
    dist = slant_range(params['altitude'], params['elev'])
    rx_gain = antenna_gain(params['rx_dia'], params['freq'])
    gt = rx_gain - 10 * np.log10(params['sys_temp'])
    result = link_budget(
        eirp_dbw=params['eirp'], freq_ghz=params['freq'],
        distance_km=dist, gt_dbk=gt, bandwidth_hz=params['bandwidth'],
        atm_loss_db=params['atm'], rain_loss_db=params['rain'],
        point_loss_db=params['point'], feeder_loss_db=params['feeder'],
        misc_loss_db=params['misc']
    )
    return result['C/N']

cn_baseline = compute_cn(baseline)

fig, axes = plt.subplots(2, 3, figsize=(16, 10))

# 1. 受信アンテナ直径の影響
dias = np.linspace(0.3, 1.5, 50)
cn_dia = []
for d in dias:
    p = baseline.copy()
    p['rx_dia'] = d
    cn_dia.append(compute_cn(p))

axes[0, 0].plot(dias * 100, cn_dia, 'b-', linewidth=2)
axes[0, 0].axhline(y=cn_baseline, color='gray', linestyle=':', alpha=0.5)
axes[0, 0].axhline(y=4.7, color='red', linestyle='--', label='Required C/N (QPSK 3/4)')
axes[0, 0].axvline(x=45, color='green', linestyle='--', alpha=0.5, label='BS antenna (45cm)')
axes[0, 0].set_xlabel('Antenna Diameter [cm]', fontsize=11)
axes[0, 0].set_ylabel('C/N [dB]', fontsize=11)
axes[0, 0].set_title('Effect of Rx Antenna Size', fontsize=12)
axes[0, 0].legend(fontsize=9)
axes[0, 0].grid(True, alpha=0.3)

# 2. 降雨減衰の影響
rain = np.linspace(0, 15, 50)
cn_rain = []
for r in rain:
    p = baseline.copy()
    p['rain'] = r
    cn_rain.append(compute_cn(p))

axes[0, 1].plot(rain, cn_rain, 'r-', linewidth=2)
axes[0, 1].axhline(y=4.7, color='red', linestyle='--', label='Required C/N')
axes[0, 1].set_xlabel('Rain Attenuation [dB]', fontsize=11)
axes[0, 1].set_ylabel('C/N [dB]', fontsize=11)
axes[0, 1].set_title('Effect of Rain Attenuation', fontsize=12)
axes[0, 1].legend(fontsize=9)
axes[0, 1].grid(True, alpha=0.3)

# 降雨で通信断に至る閾値
cn_threshold = 4.7
rain_max = rain[np.argmin(np.abs(np.array(cn_rain) - cn_threshold))]
axes[0, 1].axvline(x=rain_max, color='orange', linestyle=':', alpha=0.7)
axes[0, 1].text(rain_max + 0.5, cn_baseline - 2,
                 f'Max rain: {rain_max:.1f} dB', fontsize=10, color='orange')

# 3. システム雑音温度の影響
temps = np.linspace(50, 500, 50)
cn_temp = []
for t in temps:
    p = baseline.copy()
    p['sys_temp'] = t
    cn_temp.append(compute_cn(p))

axes[0, 2].plot(temps, cn_temp, 'g-', linewidth=2)
axes[0, 2].axhline(y=4.7, color='red', linestyle='--', label='Required C/N')
axes[0, 2].axvline(x=120, color='green', linestyle='--', alpha=0.5, label='Typical LNB')
axes[0, 2].set_xlabel('System Noise Temperature [K]', fontsize=11)
axes[0, 2].set_ylabel('C/N [dB]', fontsize=11)
axes[0, 2].set_title('Effect of System Noise Temperature', fontsize=12)
axes[0, 2].legend(fontsize=9)
axes[0, 2].grid(True, alpha=0.3)

# 4. 仰角の影響
elevs = np.linspace(5, 90, 50)
cn_elev = []
for e in elevs:
    p = baseline.copy()
    p['elev'] = e
    # 仰角が低いと大気損失も増加
    p['atm'] = 0.1 / np.sin(np.radians(e))
    cn_elev.append(compute_cn(p))

axes[1, 0].plot(elevs, cn_elev, 'm-', linewidth=2)
axes[1, 0].axhline(y=4.7, color='red', linestyle='--', label='Required C/N')
axes[1, 0].set_xlabel('Elevation Angle [deg]', fontsize=11)
axes[1, 0].set_ylabel('C/N [dB]', fontsize=11)
axes[1, 0].set_title('Effect of Elevation Angle', fontsize=12)
axes[1, 0].legend(fontsize=9)
axes[1, 0].grid(True, alpha=0.3)

# 5. EIRP の影響
eirps = np.linspace(40, 70, 50)
cn_eirp = []
for e in eirps:
    p = baseline.copy()
    p['eirp'] = e
    cn_eirp.append(compute_cn(p))

axes[1, 1].plot(eirps, cn_eirp, 'c-', linewidth=2)
axes[1, 1].axhline(y=4.7, color='red', linestyle='--', label='Required C/N')
axes[1, 1].set_xlabel('EIRP [dBW]', fontsize=11)
axes[1, 1].set_ylabel('C/N [dB]', fontsize=11)
axes[1, 1].set_title('Effect of EIRP', fontsize=12)
axes[1, 1].legend(fontsize=9)
axes[1, 1].grid(True, alpha=0.3)

# 6. 帯域幅 vs C/N(スループットとのトレードオフ)
bws = np.logspace(6, 9, 50)  # 1 MHz〜1 GHz
cn_bw = []
for b in bws:
    p = baseline.copy()
    p['bandwidth'] = b
    cn_bw.append(compute_cn(p))

axes[1, 2].semilogx(bws / 1e6, cn_bw, 'k-', linewidth=2)
axes[1, 2].axhline(y=4.7, color='red', linestyle='--', label='Required C/N')
axes[1, 2].axvline(x=36, color='green', linestyle='--', alpha=0.5,
                     label='Standard (36 MHz)')
axes[1, 2].set_xlabel('Bandwidth [MHz]', fontsize=11)
axes[1, 2].set_ylabel('C/N [dB]', fontsize=11)
axes[1, 2].set_title('Effect of Bandwidth', fontsize=12)
axes[1, 2].legend(fontsize=9)
axes[1, 2].grid(True, alpha=0.3)

plt.suptitle('Link Budget Sensitivity Analysis\n(GEO Ku-Band Downlink)',
              fontsize=14, fontweight='bold', y=1.02)
plt.tight_layout()
plt.savefig('link_budget_sensitivity.png', dpi=150, bbox_inches='tight')
plt.show()

6つの感度解析グラフから、リンクバジェットの設計上の重要な知見が得られます。

  1. 受信アンテナ直径(左上): アンテナ直径は利得に2乗で効くため、C/Nへの影響が大きいです。45 cm(BSアンテナ)から60 cmに変えると約2.5 dBの改善が得られます。逆に30 cmに小型化すると約3.5 dBの劣化で、降雨マージンがほぼ消失します。

  2. 降雨減衰(上中央): C/Nは降雨減衰に対して1対1(1 dBの降雨減衰で1 dBのC/N低下)で感応します。このシステムでは約7〜8 dBの降雨まで通信を維持でき、これが降雨マージンに直結します。

  3. システム雑音温度(右上): 雑音温度120 KのLNBから200 Kの安価なLNBに変えると約2 dBのC/N低下。高品質LNB(50 K)を使えば約4 dBの改善。しかし、温度を下げるコストは指数的に増えるため、実用的には80〜150 K程度が選ばれます。

  4. 帯域幅(右下): 帯域幅を広げるとC/Nは低下します(雑音電力が帯域に比例するため)。36 MHzのトランスポンダを2倍の72 MHzに広げると3 dBのC/N低下。帯域幅拡大によるスループット増加とC/N低下のトレードオフが、変調方式の選択を決定します。

アップリンクとダウンリンクの合成C/N

最後に、アップリンクとダウンリンクを含めた全体のリンクバジェットと、合成C/Nの計算を行います。

import numpy as np
import matplotlib.pyplot as plt

def combined_cn(cn_up_db, cn_down_db, cn_im_db=25):
    """アップリンクとダウンリンクの合成C/N [dB]"""
    cn_up = 10**(cn_up_db / 10)
    cn_down = 10**(cn_down_db / 10)
    cn_im = 10**(cn_im_db / 10)
    cn_total = 1 / (1/cn_up + 1/cn_down + 1/cn_im)
    return 10 * np.log10(cn_total)

# 合成C/Nの特性
cn_up_range = np.linspace(5, 35, 200)
cn_down_values = [8, 12, 16, 20]

fig, axes = plt.subplots(1, 2, figsize=(14, 6))

for cn_down in cn_down_values:
    cn_total = [combined_cn(cu, cn_down) for cu in cn_up_range]
    axes[0].plot(cn_up_range, cn_total, linewidth=2,
                  label=f'$C/N_{{down}}$ = {cn_down} dB')

# 対角線(上限)
axes[0].plot(cn_up_range, cn_up_range, 'k:', alpha=0.3, label='C/N = C/N_up')
axes[0].set_xlabel('Uplink C/N [dB]', fontsize=12)
axes[0].set_ylabel('Total C/N [dB]', fontsize=12)
axes[0].set_title('Combined C/N vs Uplink C/N', fontsize=13)
axes[0].legend(fontsize=10)
axes[0].grid(True, alpha=0.3)
axes[0].set_xlim([5, 35])
axes[0].set_ylim([5, 22])

# 降雨時のリンクバジェット変化
rain_atten_values = np.linspace(0, 15, 100)

# GEO Ku帯の例
cn_up_clear = 25   # dB (晴天時アップリンクC/N)
cn_down_clear = 14  # dB (晴天時ダウンリンクC/N)

# 降雨がダウンリンクに影響
cn_down_rain = cn_down_clear - rain_atten_values
cn_total_rain = [combined_cn(cn_up_clear, cd) for cd in cn_down_rain]

axes[1].plot(rain_atten_values, cn_down_rain, 'b-', linewidth=2,
              label='Downlink C/N')
axes[1].plot(rain_atten_values, cn_total_rain, 'r-', linewidth=2.5,
              label='Total C/N')
axes[1].axhline(y=cn_up_clear, color='green', linestyle='--', alpha=0.5,
                 label=f'Uplink C/N = {cn_up_clear} dB')

# 必要C/Nと降雨マージン
cn_req = 4.7
axes[1].axhline(y=cn_req, color='red', linestyle=':', linewidth=2,
                 label=f'Required C/N = {cn_req} dB')

# 降雨マージンを計算
cn_total_arr = np.array(cn_total_rain)
rain_max = rain_atten_values[np.argmin(np.abs(cn_total_arr - cn_req))]
axes[1].axvline(x=rain_max, color='orange', linestyle='--', alpha=0.7)
axes[1].fill_between(rain_atten_values, cn_req,
                       cn_total_arr, where=cn_total_arr >= cn_req,
                       alpha=0.15, color='green', label='Available margin')

axes[1].set_xlabel('Rain Attenuation on Downlink [dB]', fontsize=12)
axes[1].set_ylabel('C/N [dB]', fontsize=12)
axes[1].set_title(f'C/N Degradation with Rain\n'
                    f'(Rain margin: {rain_max:.1f} dB)', fontsize=13)
axes[1].legend(fontsize=9)
axes[1].grid(True, alpha=0.3)
axes[1].set_xlim([0, 15])
axes[1].set_ylim([-5, 30])

plt.tight_layout()
plt.savefig('combined_cn_analysis.png', dpi=150, bbox_inches='tight')
plt.show()

print(f"\n--- 合成C/N解析 ---")
print(f"晴天時アップリンクC/N: {cn_up_clear} dB")
print(f"晴天時ダウンリンクC/N: {cn_down_clear} dB")
cn_total_clear = combined_cn(cn_up_clear, cn_down_clear)
print(f"晴天時合成C/N: {cn_total_clear:.1f} dB")
print(f"必要C/N: {cn_req} dB")
print(f"降雨マージン: {rain_max:.1f} dB")
print(f"(この降雨減衰までダウンリンクが耐えられる)")

合成C/Nの解析から、衛星回線設計の重要な原則が読み取れます。

  1. 合成C/Nは弱いリンクに支配される(左図): ダウンリンクC/Nが12 dBの場合、アップリンクC/Nをいくら上げても合成C/Nは12 dBを超えません(実際には相互変調のため約11 dB程度が上限)。これは「鎖の強さは最も弱い環(リンク)で決まる」という原則の表れです。

  2. 降雨マージンはダウンリンクで消費される(右図): 晴天時の合成C/Nは約13 dBですが、降雨により減衰が増えるとダウンリンクC/Nが急速に低下し、約8〜9 dBの降雨減衰で必要C/N(4.7 dB)に達します。これが「降雨マージン約8〜9 dB」に対応します。緑色の領域が利用可能なマージンを示しています。

  3. アップリンクは晴天時に十分なマージンを持つ: アップリンクC/N = 25 dBは合成C/Nに対して十分な余裕があります。しかし、地上局側でも降雨が生じる場合(アップリンクにも降雨減衰が加わる場合)は、両方のリンクの劣化を考慮する必要があります。

まとめ

本記事では、衛星回線のリンクバジェット計算を体系的に解説しました。

  • リンクバジェットの構造: EIRP(送信能力)からFSPLと各種損失を差し引き、G/T(受信能力)を加えてC/N比を算出する。全てdBの加減算で計算できる
  • EIRP: 送信電力とアンテナ利得の積。パラボラアンテナの利得は $(\pi D/\lambda)^2$ に比例
  • G/T: 受信アンテナ利得とシステム雑音温度の比。低雑音LNBの選定が重要で、最初段の雑音温度が全体を支配する
  • C/N比と$E_b/N_0$: C/Nは帯域幅依存、$E_b/N_0$はビットレート依存。変調方式と符号化率でリンクされる
  • 各種損失: FSPL(最大項)、大気吸収、降雨減衰、偏波不整合、ポインティング、フィーダー損失
  • 設計マージン: 降雨マージンが最も重要。稼働率要件から降雨超過確率を決め、必要マージンを算出する
  • 合成C/N: アップ・ダウン両リンクの合成は調和平均に近く、弱いリンクが全体を支配する

リンクバジェットは無線通信設計の最も基本的なツールであり、この計算を自在に扱えることが衛星通信エンジニアの第一歩です。

次のステップとして、以下の記事も参考にしてください。