電波は光と同じ電磁波ですが、波長が長い(数mm~数km)ため、回折現象が顕著に現れます。送信アンテナと受信アンテナの間に山や建物などの障害物があっても、電波は障害物の背後に回り込んで到達できます。これが 回折(diffraction) です。
フレネルゾーン(Fresnel zone) は、電波伝搬における回折現象を理解するための基本的な幾何学的概念です。送受信点間の見通し線(LOS: Line of Sight)の周囲にどれだけの空間的余裕が必要かを定量的に示し、通信回線設計における障害物クリアランスの判定基準として使われます。
本記事の内容
- フレネルゾーンの幾何学的定義
- 第1フレネルゾーン半径の導出
- フレネルゾーンクリアランスの重要性(60%ルール)
- ナイフエッジ回折モデル
- フレネル積分による回折損失の計算
- ITU-R勧告のモデルとの関係
- Pythonでの可視化と回折損失の計算
前提知識
この記事を読む前に、以下の記事を読んでおくと理解が深まります。
フレネルゾーンの幾何学的定義
ホイヘンス・フレネルの原理
波動の伝搬は ホイヘンス・フレネルの原理 で説明されます。波面上の各点が新たな2次波源となり、これらの2次波の重ね合わせが次の時刻の波面を形成します。
送信点 T から受信点 R へ電波が伝搬する場合、直接波(T→R)以外にも、T→P→R のような迂回経路を通る波が存在します。点 P が TR の直線(見通し線)の近傍にあれば、この迂回波は直接波と干渉します。
フレネルゾーンの定義
送信点 T と受信点 R の間の任意の点 P を考えます。直接経路の長さは $d = d_1 + d_2$(ここで $d_1 = \overline{TP}$ の水平距離、$d_2 = \overline{PR}$ の水平距離)です。
点 P を通る迂回経路 T→P→R の長さが、直接経路の長さより $n\lambda/2$ だけ長いような点 P の集合を 第 $n$ フレネルゾーン と呼びます。
$$ \begin{equation} \overline{TP} + \overline{PR} – (\overline{TR}) = \frac{n\lambda}{2} \end{equation} $$
ここで $\overline{TP}$, $\overline{PR}$, $\overline{TR}$ は実際の距離です。
なぜ $n\lambda/2$ なのか
迂回経路の余分な長さが $\lambda/2$ のとき、迂回波は直接波に対して位相が $\pi$(180度)ずれます。
- 第1フレネルゾーン($n = 1$): 余分な経路長 $\leq \lambda/2$ → 迂回波と直接波の位相差 $\leq \pi$ → 強め合いに寄与
- 第2フレネルゾーン($n = 2$): 余分な経路長が $\lambda/2$ ~ $\lambda$ → 位相差 $\pi$ ~ $2\pi$ → 弱め合いに寄与
- 奇数ゾーン: 強め合い
- 偶数ゾーン: 弱め合い
第1フレネルゾーン内の迂回波は直接波と強め合うため、第1フレネルゾーンが遮蔽されないことが良好な通信品質の条件 です。
第1フレネルゾーン半径の導出
幾何学的設定
送信点 T を原点、受信点 R を距離 $d$ の位置とし、T と R の間の点 Q(TQ = $d_1$, QR = $d_2$, $d_1 + d_2 = d$)で見通し線に垂直な面を考えます。
この面上で、見通し線から距離 $r_n$ だけ離れた点 P について、迂回経路 TPR の長さを計算します。
距離の計算
点 P は見通し線から $r_n$ だけ離れているので、
$$ \overline{TP} = \sqrt{d_1^2 + r_n^2} $$
$$ \overline{PR} = \sqrt{d_2^2 + r_n^2} $$
$r_n \ll d_1, d_2$(フレネルゾーン半径が伝搬距離よりはるかに小さい)という近似を使います。テイラー展開 $\sqrt{a^2 + b^2} \approx a + \frac{b^2}{2a}$($b \ll a$)を適用すると、
$$ \overline{TP} \approx d_1 + \frac{r_n^2}{2d_1} $$
$$ \overline{PR} \approx d_2 + \frac{r_n^2}{2d_2} $$
余分な経路長
$$ \begin{align} \overline{TP} + \overline{PR} – d &\approx \left(d_1 + \frac{r_n^2}{2d_1}\right) + \left(d_2 + \frac{r_n^2}{2d_2}\right) – (d_1 + d_2) \\ &= \frac{r_n^2}{2d_1} + \frac{r_n^2}{2d_2} \\ &= \frac{r_n^2}{2}\left(\frac{1}{d_1} + \frac{1}{d_2}\right) \\ &= \frac{r_n^2}{2} \cdot \frac{d_1 + d_2}{d_1 d_2} \\ &= \frac{r_n^2 d}{2 d_1 d_2} \end{align} $$
フレネルゾーン半径の公式
余分な経路長を $n\lambda/2$ とおくと、
$$ \frac{r_n^2 d}{2d_1 d_2} = \frac{n\lambda}{2} $$
$$ r_n^2 = \frac{n\lambda d_1 d_2}{d} $$
$$ \begin{equation} \boxed{r_n = \sqrt{\frac{n\lambda d_1 d_2}{d_1 + d_2}}} \end{equation} $$
特に 第1フレネルゾーン半径 は、
$$ \begin{equation} r_1 = \sqrt{\frac{\lambda d_1 d_2}{d_1 + d_2}} \end{equation} $$
パス中央での最大値
$d_1 = d_2 = d/2$ のとき(パスの中央)、フレネルゾーン半径は最大になります。
$$ r_1^{\max} = \sqrt{\frac{\lambda \cdot (d/2) \cdot (d/2)}{d}} = \frac{1}{2}\sqrt{\lambda d} $$
$$ \begin{equation} r_1^{\max} = \frac{1}{2}\sqrt{\lambda d} \end{equation} $$
数値例
距離 $d = 10$ km、周波数 $f = 1$ GHz($\lambda = 0.3$ m)の場合、
$$ r_1^{\max} = \frac{1}{2}\sqrt{0.3 \times 10000} = \frac{1}{2}\sqrt{3000} = \frac{54.77}{2} \approx 27.4 \text{ m} $$
パス中央で約27 mの空間的余裕が必要です。
距離 $d = 50$ km、周波数 $f = 6$ GHz($\lambda = 0.05$ m)の場合、
$$ r_1^{\max} = \frac{1}{2}\sqrt{0.05 \times 50000} = \frac{1}{2}\sqrt{2500} = 25 \text{ m} $$
フレネルゾーンクリアランス
60%ルール
実用上、第1フレネルゾーンの 60%以上 が障害物で遮蔽されなければ、回折損失はほぼ無視できます(自由空間損失 + 0~1 dB 程度)。
これが 60%ルール です。すなわち、必要なクリアランス高さは、
$$ h_{\text{clearance}} \geq 0.6 \times r_1 $$
多くの通信回線設計では、この60%クリアランスを確保することが目標になります。
クリアランスと損失の関係
| クリアランス / $r_1$ | 回折損失 [dB] | 状態 |
|---|---|---|
| $\geq 1.0$ | 0 | 完全クリアランス |
| $0.6$ | $\approx 0$ | 実質的にクリア |
| $0.0$(見通し線上) | $-6$ | 6 dB の損失 |
| $-0.6$ | $\approx -12$ | 第1ゾーンの40%が遮蔽 |
| $-1.0$ | $\approx -16$ | 第1ゾーン完全遮蔽 |
見通し線がぎりぎり確保されている($h = 0$)場合でも、約6 dBの損失が生じる点は直感に反するかもしれません。これは第1フレネルゾーンの下半分が遮蔽されるためです。
ナイフエッジ回折モデル
モデルの概要
障害物を無限に薄い半平面(ナイフの刃)で近似するモデルが ナイフエッジ回折 です。これはフレネル回折の最も基本的なモデルであり、ITU-R勧告でも基礎として用いられます。
フレネル・キルヒホフ回折パラメータ
ナイフエッジの高さ $h$(見通し線からの超過高さ、障害物が見通し線を遮る場合が正)に対して、フレネル回折パラメータ $\nu$ を定義します。
$$ \begin{equation} \nu = h\sqrt{\frac{2(d_1 + d_2)}{\lambda d_1 d_2}} = h \sqrt{\frac{2}{\lambda}\left(\frac{1}{d_1} + \frac{1}{d_2}\right)} \end{equation} $$
$h$ と第1フレネルゾーン半径 $r_1$ の関係を使うと、
$$ \nu = h \cdot \frac{\sqrt{2}}{r_1} \cdot \sqrt{\frac{d}{d_1 + d_2}} = \frac{h\sqrt{2}}{r_1} $$
つまり $\nu$ は「障害物の高さを第1フレネルゾーン半径で正規化した量」です。
- $\nu < 0$: 障害物が見通し線より下(クリアランスあり)
- $\nu = 0$: 障害物がちょうど見通し線上
- $\nu > 0$: 障害物が見通し線を遮蔽
フレネル積分
ナイフエッジによる回折界は、フレネル積分を用いて表されます。
遮蔽されていない場合の電場を $E_0$ とすると、回折後の電場は、
$$ \begin{equation} \frac{E}{E_0} = \frac{1+j}{2}\int_{\nu}^{\infty}\exp\left(-j\frac{\pi t^2}{2}\right)dt \end{equation} $$
ここで、フレネル積分(コサインおよびサイン積分)は、
$$ C(x) = \int_0^x \cos\left(\frac{\pi t^2}{2}\right)dt, \qquad S(x) = \int_0^x \sin\left(\frac{\pi t^2}{2}\right)dt $$
フレネル積分の性質として $\int_0^{\infty} \exp(-j\pi t^2/2)dt = \frac{1-j}{2}$ を用いると、
$$ \int_{\nu}^{\infty}\exp\left(-j\frac{\pi t^2}{2}\right)dt = \left[\frac{1}{2} – C(\nu)\right] – j\left[\frac{1}{2} – S(\nu)\right] $$
回折損失
回折損失(自由空間に対する損失)は電場の比の絶対値の2乗です。
$$ \begin{equation} L_{\text{diff}} = -20\log_{10}\left|\frac{E}{E_0}\right| \quad \text{[dB]} \end{equation} $$
$$ \left|\frac{E}{E_0}\right|^2 = \frac{1}{2}\left\{\left[\frac{1}{2} – C(\nu)\right]^2 + \left[\frac{1}{2} – S(\nu)\right]^2\right\} $$
特殊な値の確認
$\nu = 0$(見通し線上)の場合、$C(0) = S(0) = 0$ なので、
$$ \left|\frac{E}{E_0}\right|^2 = \frac{1}{2}\left(\frac{1}{4} + \frac{1}{4}\right) = \frac{1}{4} $$
$$ \left|\frac{E}{E_0}\right| = \frac{1}{2} $$
$$ L_{\text{diff}} = -20\log_{10}(0.5) = 6.02 \text{ dB} $$
これは「見通し線がぎりぎり確保されている場合に6 dBの損失がある」という前述の結果と一致します。
$\nu \to -\infty$(クリアランスが十分大きい)の場合、$C(-\infty) = -1/2$, $S(-\infty) = -1/2$ なので、
$$ \left|\frac{E}{E_0}\right|^2 = \frac{1}{2}(1^2 + 1^2) = 1 $$
損失は0 dBであり、自由空間と同等です。
近似式
実用上、以下の近似式がよく使われます。
$\nu > -0.7$ のとき(ITU-R P.526):
$$ \begin{equation} L_{\text{diff}} \approx 6.9 + 20\log_{10}\left(\sqrt{(\nu – 0.1)^2 + 1} + \nu – 0.1\right) \quad \text{[dB]} \end{equation} $$
この近似式は $\nu \geq -0.7$ で精度が良く、フレネル積分を計算する必要がないため回線設計で頻繁に使われます。
ITU-R勧告との関係
ITU-R P.526
ITU-R勧告 P.526(Propagation by diffraction)は、回折損失の計算方法を規定しています。主なモデルは以下の通りです。
- 単一ナイフエッジ: 本記事で扱ったモデル
- 複数ナイフエッジ(Deygout法): 主要な障害物を順に処理
- 球面大地上の回折: 地球の曲率を考慮
- 一般的な地形プロファイル: 数値計算による精密計算
ITU-R P.530
ITU-R勧告 P.530(Propagation data and prediction methods required for the design of terrestrial line-of-sight systems)では、マイクロ波見通し回線の設計に必要なクリアランス基準を定めています。
第1フレネルゾーンの少なくとも60%のクリアランスを確保することが推奨されています。さらに、大気の屈折を考慮して等価地球半径係数 $K$ を用いた補正が必要です。
Pythonでの実装
フレネルゾーンの可視化
import numpy as np
import matplotlib.pyplot as plt
# --- フレネルゾーンの可視化 ---
def fresnel_radius(n, lam, d1, d2):
"""第nフレネルゾーン半径 [m]"""
return np.sqrt(n * lam * d1 * d2 / (d1 + d2))
# パラメータ
d = 10e3 # 伝搬距離 10 km
f = 1e9 # 周波数 1 GHz
c = 3e8
lam = c / f # 波長 0.3 m
fig, axes = plt.subplots(2, 2, figsize=(16, 10))
# --- (1) フレネルゾーンの断面図 ---
ax = axes[0, 0]
x = np.linspace(0, d, 500) # T→R方向の位置
d1 = x
d2 = d - x
d1 = np.clip(d1, 1, None) # ゼロ除算回避
d2 = np.clip(d2, 1, None)
for n in [1, 2, 3, 4]:
r_n = fresnel_radius(n, lam, d1, d2)
ax.fill_between(x / 1e3, -r_n, r_n, alpha=0.15, label=f'n = {n}')
ax.plot(x / 1e3, r_n, linewidth=1.5)
ax.plot(x / 1e3, -r_n, linewidth=1.5)
# 見通し線
ax.plot([0, d/1e3], [0, 0], 'k--', linewidth=1, label='LOS')
# 障害物の例
h_obs = 15 # 障害物高さ [m]
x_obs = 5 # 障害物位置 [km]
ax.fill_between([x_obs - 0.1, x_obs + 0.1], [-30, -30], [h_obs, h_obs],
color='brown', alpha=0.7, label='Obstacle')
ax.set_xlabel('Distance from Tx [km]', fontsize=11)
ax.set_ylabel('Height from LOS [m]', fontsize=11)
ax.set_title(f'Fresnel Zones (d = {d/1e3:.0f} km, f = {f/1e9:.1f} GHz)', fontsize=13)
ax.legend(fontsize=9, loc='upper right')
ax.grid(True, alpha=0.3)
ax.set_ylim([-60, 60])
# --- (2) 第1フレネルゾーン半径 vs 位置 ---
ax = axes[0, 1]
freqs = [400e6, 1e9, 2.4e9, 6e9, 12e9, 28e9]
colors = plt.cm.tab10(np.linspace(0, 1, len(freqs)))
for f_val, color in zip(freqs, colors):
lam_val = c / f_val
r1 = fresnel_radius(1, lam_val, d1, d2)
if f_val >= 1e9:
label = f'f = {f_val/1e9:.1f} GHz'
else:
label = f'f = {f_val/1e6:.0f} MHz'
ax.plot(x / 1e3, r1, color=color, linewidth=2, label=label)
ax.set_xlabel('Distance from Tx [km]', fontsize=11)
ax.set_ylabel('1st Fresnel Zone Radius [m]', fontsize=11)
ax.set_title(f'First Fresnel Zone Radius (d = {d/1e3:.0f} km)', fontsize=13)
ax.legend(fontsize=9)
ax.grid(True, alpha=0.3)
# --- (3) パス中央での第1フレネルゾーン半径 vs 距離 ---
ax = axes[1, 0]
d_range = np.linspace(100, 100e3, 500) # 100 m ~ 100 km
for f_val, color in zip(freqs, colors):
lam_val = c / f_val
r1_max = 0.5 * np.sqrt(lam_val * d_range)
if f_val >= 1e9:
label = f'f = {f_val/1e9:.1f} GHz'
else:
label = f'f = {f_val/1e6:.0f} MHz'
ax.plot(d_range / 1e3, r1_max, color=color, linewidth=2, label=label)
ax.axhline(y=10, color='gray', linestyle=':', linewidth=1, label='10 m tower height')
ax.set_xlabel('Path Length [km]', fontsize=11)
ax.set_ylabel('Max 1st Fresnel Zone Radius [m]', fontsize=11)
ax.set_title('Max r$_1$ at Path Center vs Distance', fontsize=13)
ax.legend(fontsize=9)
ax.grid(True, alpha=0.3)
ax.set_xscale('log')
ax.set_yscale('log')
# --- (4) 60%クリアランスの断面 ---
ax = axes[1, 1]
f_val = 6e9
lam_val = c / f_val
d_val = 20e3
x_vals = np.linspace(0, d_val, 500)
d1_vals = np.clip(x_vals, 1, None)
d2_vals = np.clip(d_val - x_vals, 1, None)
r1 = fresnel_radius(1, lam_val, d1_vals, d2_vals)
r_60 = 0.6 * r1
# 地形プロファイルの例(丘)
terrain = 8 * np.exp(-((x_vals/1e3 - 12)**2) / (2 * 2**2))
ax.fill_between(x_vals / 1e3, 0, terrain, color='saddlebrown', alpha=0.5, label='Terrain')
ax.plot(x_vals / 1e3, r1, 'b-', linewidth=2, label='$r_1$ (100%)')
ax.plot(x_vals / 1e3, r_60, 'r--', linewidth=2, label='$0.6 r_1$ (60% clearance)')
ax.plot([0, d_val / 1e3], [0, 0], 'k--', linewidth=1, label='LOS')
# クリアランス不足の領域を強調
clearance_issue = terrain > r_60
if np.any(clearance_issue):
ax.fill_between(x_vals / 1e3, r_60, terrain,
where=clearance_issue, color='red', alpha=0.3,
label='Clearance violation')
ax.set_xlabel('Distance from Tx [km]', fontsize=11)
ax.set_ylabel('Height from LOS [m]', fontsize=11)
ax.set_title(f'60% Clearance Rule (d = {d_val/1e3:.0f} km, f = {f_val/1e9:.0f} GHz)',
fontsize=13)
ax.legend(fontsize=9)
ax.grid(True, alpha=0.3)
ax.set_ylim([-5, max(r1) * 1.1])
plt.tight_layout()
plt.savefig('fresnel_zones.png', dpi=150, bbox_inches='tight')
plt.show()
ナイフエッジ回折損失の計算
import numpy as np
import matplotlib.pyplot as plt
from scipy.special import fresnel
# --- ナイフエッジ回折損失 ---
def knife_edge_loss_exact(nu):
"""
ナイフエッジ回折損失(フレネル積分を使った厳密計算)
Parameters
----------
nu : float or array
フレネル回折パラメータ
Returns
-------
loss_dB : float or array
回折損失 [dB](正値が損失)
"""
nu = np.atleast_1d(np.asarray(nu, dtype=float))
# scipy.special.fresnel は S(x), C(x) を返す
# 引数の変換: scipy の fresnel(x) は ∫cos(πt²/2)dt, ∫sin(πt²/2)dt
S_nu, C_nu = fresnel(nu)
# |E/E0|²
E_ratio_sq = 0.5 * ((0.5 - C_nu)**2 + (0.5 - S_nu)**2)
E_ratio = np.sqrt(E_ratio_sq)
# 損失 [dB]
loss_dB = -20 * np.log10(E_ratio)
return loss_dB
def knife_edge_loss_approx(nu):
"""
ナイフエッジ回折損失(ITU-R近似式)
Parameters
----------
nu : float or array
フレネル回折パラメータ
Returns
-------
loss_dB : float or array
回折損失 [dB]
"""
nu = np.atleast_1d(np.asarray(nu, dtype=float))
loss_dB = np.zeros_like(nu)
mask = nu > -0.7
loss_dB[mask] = 6.9 + 20 * np.log10(
np.sqrt((nu[mask] - 0.1)**2 + 1) + nu[mask] - 0.1
)
# nu <= -0.7 のとき損失は0に近い
loss_dB[~mask] = 0.0
return loss_dB
# --- プロット ---
nu = np.linspace(-3, 5, 500)
loss_exact = knife_edge_loss_exact(nu)
loss_approx = knife_edge_loss_approx(nu)
fig, axes = plt.subplots(1, 3, figsize=(18, 6))
# (1) 回折損失 vs ν
ax = axes[0]
ax.plot(nu, loss_exact, 'b-', linewidth=2.5, label='Exact (Fresnel integral)')
ax.plot(nu, loss_approx, 'r--', linewidth=2, label='ITU-R approx.')
ax.axvline(x=0, color='gray', linestyle=':', linewidth=1, label='$\\nu = 0$ (LOS grazing)')
ax.axhline(y=6.02, color='green', linestyle=':', linewidth=1, label='6 dB (at $\\nu = 0$)')
ax.set_xlabel('Fresnel diffraction parameter $\\nu$', fontsize=12)
ax.set_ylabel('Diffraction Loss [dB]', fontsize=12)
ax.set_title('Knife-Edge Diffraction Loss', fontsize=13)
ax.legend(fontsize=9)
ax.grid(True, alpha=0.3)
ax.set_ylim([-2, 25])
ax.invert_yaxis()
# (2) E/E0 の振幅と位相
ax = axes[1]
S_nu, C_nu = fresnel(nu)
E_ratio = np.sqrt(0.5 * ((0.5 - C_nu)**2 + (0.5 - S_nu)**2))
# 複素電場比
E_complex = 0.5 * (1 + 1j) * ((0.5 - C_nu) - 1j * (0.5 - S_nu))
E_phase = np.angle(E_complex) * 180 / np.pi
ax.plot(nu, E_ratio, 'b-', linewidth=2, label='|E/E$_0$|')
ax_twin = ax.twinx()
ax_twin.plot(nu, E_phase, 'r--', linewidth=1.5, label='Phase [deg]')
ax.set_xlabel('$\\nu$', fontsize=12)
ax.set_ylabel('|E/E$_0$|', fontsize=12, color='blue')
ax_twin.set_ylabel('Phase [deg]', fontsize=12, color='red')
ax.set_title('Diffracted Field Amplitude and Phase', fontsize=13)
ax.grid(True, alpha=0.3)
lines1, labels1 = ax.get_legend_handles_labels()
lines2, labels2 = ax_twin.get_legend_handles_labels()
ax.legend(lines1 + lines2, labels1 + labels2, fontsize=10, loc='upper right')
# (3) クリアランス比と損失の関係
ax = axes[2]
# h/r1 とν の関係: ν = h√2/r1 → h/r1 = ν/√2
h_over_r1 = nu / np.sqrt(2)
ax.plot(h_over_r1, loss_exact, 'b-', linewidth=2.5)
# 主要ポイント
points = {
'Full clearance\n(h/r₁ = -1)': -1,
'60% clearance\n(h/r₁ = -0.6)': -0.6,
'LOS grazing\n(h/r₁ = 0)': 0,
'Partial block\n(h/r₁ = 0.5)': 0.5,
'Full block\n(h/r₁ = 1)': 1,
}
for label, h_r1 in points.items():
nu_pt = h_r1 * np.sqrt(2)
loss_pt = knife_edge_loss_exact(nu_pt)
ax.plot(h_r1, loss_pt, 'ro', markersize=8)
ax.annotate(f'{label}\n{loss_pt[0]:.1f} dB', xy=(h_r1, loss_pt),
xytext=(h_r1 + 0.3, loss_pt + 1.5), fontsize=8,
arrowprops=dict(arrowstyle='->', color='red'))
ax.set_xlabel('Obstacle height / $r_1$ (h/$r_1$)', fontsize=12)
ax.set_ylabel('Diffraction Loss [dB]', fontsize=12)
ax.set_title('Loss vs Clearance Ratio', fontsize=13)
ax.grid(True, alpha=0.3)
ax.set_ylim([-2, 25])
ax.invert_yaxis()
ax.axvline(x=0, color='gray', linestyle=':', linewidth=1)
ax.axvline(x=-0.6, color='green', linestyle='--', linewidth=1.5,
label='60% clearance rule')
ax.legend(fontsize=10)
plt.tight_layout()
plt.savefig('knife_edge_diffraction.png', dpi=150, bbox_inches='tight')
plt.show()
# 主要な点の数値出力
print("=== 主要なνと回折損失 ===")
for nu_val in [-3, -2, -1, -0.7, 0, 0.5, 1, 2, 3, 5]:
loss = knife_edge_loss_exact(nu_val)[0]
print(f" ν = {nu_val:>5.1f} → Loss = {loss:>6.2f} dB")
実際の地形プロファイルに対する回折計算
import numpy as np
import matplotlib.pyplot as plt
from scipy.special import fresnel
def knife_edge_loss_exact(nu):
"""ナイフエッジ回折損失 [dB]"""
nu = np.atleast_1d(np.asarray(nu, dtype=float))
S_nu, C_nu = fresnel(nu)
E_ratio_sq = 0.5 * ((0.5 - C_nu)**2 + (0.5 - S_nu)**2)
return -20 * np.log10(np.sqrt(E_ratio_sq))
def fresnel_radius_1(lam, d1, d2):
"""第1フレネルゾーン半径"""
return np.sqrt(lam * d1 * d2 / (d1 + d2))
# --- 地形プロファイルの例 ---
c = 3e8
f = 2e9 # 2 GHz
lam = c / f
# 送受信局の位置
d_total = 30e3 # 30 km
h_tx = 50 # 送信アンテナ高 [m]
h_rx = 30 # 受信アンテナ高 [m]
# 地形プロファイル(合成データ)
x_terrain = np.linspace(0, d_total, 1000)
np.random.seed(42)
# 山と丘の地形
terrain = (80 * np.exp(-((x_terrain/1e3 - 12)**2) / (2 * 3**2)) +
40 * np.exp(-((x_terrain/1e3 - 20)**2) / (2 * 1.5**2)) +
20 * np.exp(-((x_terrain/1e3 - 7)**2) / (2 * 2**2)))
# 見通し線の高さ
los_height = h_tx + (h_rx - h_tx) * x_terrain / d_total
# 第1フレネルゾーン
d1 = np.clip(x_terrain, 1, None)
d2 = np.clip(d_total - x_terrain, 1, None)
r1 = fresnel_radius_1(lam, d1, d2)
r1_60 = 0.6 * r1
# 最大障害物の特定(LOSからの超過高さが最大の点)
excess_height = terrain - los_height
max_idx = np.argmax(excess_height)
h_max = excess_height[max_idx]
d1_max = x_terrain[max_idx]
d2_max = d_total - d1_max
# ナイフエッジ回折パラメータ
nu = h_max * np.sqrt(2 * (d1_max + d2_max) / (lam * d1_max * d2_max))
loss = knife_edge_loss_exact(nu)[0]
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(14, 10), height_ratios=[3, 1])
# (1) 地形プロファイルとフレネルゾーン
ax1.fill_between(x_terrain / 1e3, 0, terrain, color='saddlebrown',
alpha=0.5, label='Terrain')
ax1.plot(x_terrain / 1e3, los_height, 'k--', linewidth=1.5, label='LOS')
ax1.plot(x_terrain / 1e3, los_height + r1, 'b-', linewidth=1.5,
label='1st Fresnel zone')
ax1.plot(x_terrain / 1e3, los_height - r1, 'b-', linewidth=1.5)
ax1.fill_between(x_terrain / 1e3, los_height - r1, los_height + r1,
alpha=0.1, color='blue')
ax1.plot(x_terrain / 1e3, los_height + r1_60, 'r:', linewidth=1.5,
label='60% clearance')
ax1.plot(x_terrain / 1e3, los_height - r1_60, 'r:', linewidth=1.5)
# アンテナ位置
ax1.plot(0, h_tx, 'r^', markersize=15, label=f'Tx (h={h_tx}m)')
ax1.plot(d_total / 1e3, h_rx, 'bs', markersize=12, label=f'Rx (h={h_rx}m)')
# 最大障害物
ax1.plot(x_terrain[max_idx] / 1e3, terrain[max_idx], 'rv', markersize=12)
ax1.annotate(f'Max obstacle\nh_excess = {h_max:.1f} m\n$\\nu$ = {nu:.2f}\n'
f'Loss = {loss:.1f} dB',
xy=(x_terrain[max_idx] / 1e3, terrain[max_idx]),
xytext=(x_terrain[max_idx] / 1e3 + 3, terrain[max_idx] + 15),
fontsize=10, fontweight='bold',
arrowprops=dict(arrowstyle='->', color='red', lw=2),
bbox=dict(boxstyle='round,pad=0.3', facecolor='yellow', alpha=0.8))
ax1.set_xlabel('Distance [km]', fontsize=12)
ax1.set_ylabel('Height [m]', fontsize=12)
ax1.set_title(f'Terrain Profile with Fresnel Zone (f = {f/1e9:.0f} GHz, d = {d_total/1e3:.0f} km)',
fontsize=14)
ax1.legend(fontsize=9, loc='upper right')
ax1.grid(True, alpha=0.3)
ax1.set_ylim([0, max(los_height + r1) * 1.2])
# (2) クリアランス比 h/r1 のプロファイル
clearance_ratio = (los_height - terrain) / r1
ax2.plot(x_terrain / 1e3, clearance_ratio, 'b-', linewidth=2)
ax2.axhline(y=0.6, color='green', linestyle='--', linewidth=1.5,
label='60% clearance')
ax2.axhline(y=0, color='red', linestyle=':', linewidth=1.5,
label='LOS grazing')
ax2.fill_between(x_terrain / 1e3, clearance_ratio, 0.6,
where=clearance_ratio < 0.6, color='red', alpha=0.2)
ax2.set_xlabel('Distance [km]', fontsize=12)
ax2.set_ylabel('Clearance / $r_1$', fontsize=12)
ax2.set_title('Fresnel Zone Clearance Ratio', fontsize=13)
ax2.legend(fontsize=10)
ax2.grid(True, alpha=0.3)
ax2.set_ylim([-2, 3])
plt.tight_layout()
plt.savefig('terrain_diffraction.png', dpi=150, bbox_inches='tight')
plt.show()
print(f"\n=== 回折解析結果 ===")
print(f" 周波数: {f/1e9:.0f} GHz (λ = {lam:.3f} m)")
print(f" 距離: {d_total/1e3:.0f} km")
print(f" 最大障害物位置: {x_terrain[max_idx]/1e3:.1f} km")
print(f" 超過高さ: {h_max:.1f} m")
print(f" 第1フレネルゾーン半径(障害物位置): {r1[max_idx]:.1f} m")
print(f" フレネル回折パラメータ ν: {nu:.3f}")
print(f" 回折損失: {loss:.1f} dB")
まとめ
本記事では、フレネルゾーンと回折損失について基礎から丁寧に解説しました。
- フレネルゾーン: 迂回経路の余分な長さが $n\lambda/2$ となる点の集合が第 $n$ フレネルゾーンです。第1フレネルゾーン内の波は直接波を強めます
- 第1フレネルゾーン半径: $r_1 = \sqrt{\lambda d_1 d_2/(d_1 + d_2)}$ で、パス中央で最大値 $r_1^{\max} = \frac{1}{2}\sqrt{\lambda d}$ をとります
- 60%ルール: 第1フレネルゾーンの60%以上のクリアランスがあれば、回折損失はほぼ無視できます
- ナイフエッジ回折: フレネル回折パラメータ $\nu$ とフレネル積分を用いて回折損失を計算します
- 見通し線上での損失: $\nu = 0$ でも6 dBの回折損失が生じます
- ITU-R近似式: $L = 6.9 + 20\log_{10}(\sqrt{(\nu-0.1)^2+1} + \nu-0.1)$ dB
次のステップとして、以下の記事も参考にしてください。