了解しました。同期信号(例えば既知の正弦波やチャープ)を先頭に付加しておき、それを使って受信波形の時間ずれ・位相ずれを補正する方法を Python で実装してみます。
以下では簡単のために
同期信号: 周波数
𝑓
0
f
0
の正弦波(数周期分)
信号部: 同じ周波数の正弦波(位相シフトと時間シフトを加える)
として例を作ります。
import numpy as np
import matplotlib.pyplot as plt
--- パラメータ設定 ---
fs = 1000 # サンプリング周波数 [Hz]
f0 = 50 # 基本周波数 [Hz]
Tsync = 0.1 # 同期信号の長さ [s]
Tsig = 0.2 # 信号部の長さ [s]
Nsync = int(Tsync * fs)
Nsig = int(Tsig * fs)
t_sync = np.arange(Nsync) / fs
t_sig = np.arange(Nsig) / fs
--- 送信波形の生成 ---
sync_tx = np.sin(2np.pif0t_sync) # 同期信号
sig_tx = np.sin(2np.pif0t_sig) # 信号部
wave_tx = np.concatenate([sync_tx, sig_tx])
--- 受信波形の生成(遅延+位相シフト付与) ---
delay_samples = 30 # サンプル遅延
phase_shift = np.pi/4 # 45度の位相シフト
sig_rx = np.sin(2np.pif0*t_sig + phase_shift)
wave_rx = np.concatenate([np.zeros(delay_samples), sync_tx, sig_rx])
--- 周波数領域相関で同期信号を検出 ---
長さを合わせてFFT
L = max(len(wave_tx), len(wave_rx))
SyncF = np.fft.fft(sync_tx, L)
RxF = np.fft.fft(wave_rx, L)
相互相関 (周波数領域で計算)
corr = np.fft.ifft(RxF * np.conj(SyncF))
shift = np.argmax(np.abs(corr)) # 最大の相関を持つシフト
print(f"検出された遅延 = {shift} サンプル (理論値: {delay_samples})")
--- 位相補正(同期信号の周波数成分を比較) ---
freqs = np.fft.fftfreq(L, 1/fs)
k0 = np.argmin(np.abs(freqs - f0)) # f0のインデックス
phase_rx = np.angle(RxF[k0])
phase_ref = np.angle(SyncF[k0])
phase_diff = phase_rx - phase_ref
phase_diff = np.arctan2(np.sin(phase_diff), np.cos(phase_diff)) # [-pi,pi]に正規化
print(f"検出された位相差 = {np.degrees(phase_diff):.2f}° (理論値: {np.degrees(phase_shift):.2f}°)")
--- 補正後の信号を作成 ---
wave_rx_aligned = np.roll(wave_rx, -shift) # 時間シフト補正
SigF = np.fft.fft(wave_rx_aligned, L)
SigF[k0] *= np.exp(-1j * phase_diff) # 位相補正
wave_rx_corrected = np.fft.ifft(SigF).real
--- プロット ---
plt.figure(figsize=(12,6))
plt.subplot(3,1,1)
plt.plot(wave_tx, label="送信波形")
plt.plot(wave_rx, label="受信波形", alpha=0.7)
plt.legend(); plt.title("送信波形と受信波形(ずれあり)")
plt.subplot(3,1,2)
plt.plot(wave_tx, label="送信波形")
plt.plot(wave_rx_aligned, label="受信波形(時間補正後)", alpha=0.7)
plt.legend(); plt.title("時間補正後")
plt.subplot(3,1,3)
plt.plot(wave_tx, label="送信波形")
plt.plot(wave_rx_corrected, label="受信波形(時間+位相補正後)", alpha=0.7)
plt.legend(); plt.title("時間+位相補正後")
plt.tight_layout()
plt.show()
このコードでは:
**相互相関(FFTベース)**で同期信号の位置を見つけて時間ずれを補正
周波数成分を比較して 位相差を推定
周波数領域でその位相差を補正
結果を送信波形と重ねて描画
という流れになります。