在切换到使用锯齿波之前,我使用的是正弦波,但在正弦波中高频内容并不清晰可见,但我没有任何使用锯齿波的经验。我将在 GNU Radio 中根据此代码创建一个自定义块,这样我将无法使用 scipy.signal.sawtooth 或 signal.chirp。因为有些库不能在 GNU radio 中工作。
import numpy as np
import matplotlib.pyplot as plt
from math import pi
chirp_duration = 60e-6
f0 = 1e6
f1 = 3e6
no_samp = 1001
rcs = 0.0377
f_step = (f1-f0)/no_samp
rf_axis = np.linspace(f0, f1, int(f_step))
rt_axis = np.linspace(0, chirp_duration, int(f_step))
# rchirp = np.cos(2 * np.pi * rf_axis * rt_axis)
plt.figure(figsize=(12, 3))
plt.xlabel("Time")
plt.ylabel("Frequency")
plt.title('Received Chirp')
plt.plot(rt_axis, rf_axis)
plt.show()
这是我用来生成正弦波线性调频信号的代码。该代码非常适合 f0 和 f1 的低频值。
您可以使用 SciPy 生成锯齿信号 https://docs.scipy.org/doc/scipy/reference/ generated/scipy.signal.sawtooth.html
这是他们提供的示例:
import numpy as np
from scipy import signal
import matplotlib.pyplot as plt
t = np.linspace(0, 1, 500)
plt.plot(t, signal.sawtooth(2 * np.pi * 5 * t))
plt.show()
已更新 仔细考虑一下,我认为您实际上并不是在追求锯齿信号。您只需要一个重复的线性调频信号,它会在频域中产生锯齿图案。看看这是否有帮助:
import numpy as np
from scipy import signal
import matplotlib.pyplot as plt
## Make a single chirp signal
t_chirp = np.linspace(0, 2, 500)
w_chirp = signal.chirp(t_chirp, f0=1, f1=6, t1=2, method='linear')
fs = 1/(2/500)
## Repeating the chirp signal 5 times
num_repeats = 5
t = np.linspace(0, 2*num_repeats, 500*num_repeats)
w = np.copy(w_chirp)
for i in range(num_repeats-1):
w = np.hstack((w, w_chirp))
## Finding the instantaneous frequency
analytic_signal = signal.hilbert(w)
instantaneous_phase = np.unwrap(np.angle(analytic_signal))
instantaneous_frequency = (np.diff(instantaneous_phase) / (2.0*np.pi) * fs)
fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(10,4))
ax[0].plot(t, w)
ax[0].set_title("Linear Chirp")
ax[0].set_xlabel('t (sec)')
ax[1].plot(t[:-1], instantaneous_frequency)
ax[1].set_title("Instantaneous Frequency")
ax[1].set_xlabel('t (sec)')
ax[1].set_ylabel("Frequency (Hz)")
plt.tight_layout()
plt.show()
看来您的 chirp 函数可能不正确。
检查时域线性调频信号的瞬时频率,信号频率的增加速度似乎是应有的速度的两倍。
这个网站给出了一个稍微不同的产生线性调频脉冲的公式。它最初是针对 MATLAB 的,但我们可以轻松地将其转换为 Python :
def linear_chirp(t: np.ndarray, f0, f1, p, phase_offset=0):
'''
make a linear chirp
Arguments:
* t : array of sample times
* f0 : starting frequency
* f1 : end frenquency
* p : chirp period
* phase_offset : initial phase offset
'''
return np.cos(2*np.pi*((f1-f0)/p/2*t + f0)*t + phase_offset)
以下函数,基于 astroChance 在其他答案中给出的方法,可用于检查瞬时频率:
def ifreq(t: np.ndarray, x: np.ndarray):
'''
find the instantaneous frequency of a singal
Arguments:
* t : array of evenly spaced sample times
* x : signal samples at sample times `t`
'''
# import scipy.signal because this is only for testing purposes
# it is not necessary for the final version
from scipy.signal import hilbert
fs = len(t)/t.ptp() # evenly spaced samples !!!
analytic_signal = hilbert(x)
instantaneous_phase = np.unwrap(np.angle(analytic_signal))
return (np.diff(instantaneous_phase) / (2.0*np.pi) * fs)
为了说明这一切:
import numpy as np
import matplotlib.pyplot as plt
chirp_duration = 60e-6
f0 = 1e6
f1 = 3e6
no_samp = 1001
f_step = (f1-f0)/no_samp
rf_axis = np.linspace(f0, f1, int(f_step))
rt_axis = np.linspace(0, chirp_duration, int(f_step))
rchirp = np.cos(2 * np.pi * rf_axis * rt_axis)
***
define linear_chirp and ifreq here
***
mychrip = linear_chirp(rt_axis, f0, f1, chirp_duration, 0)
fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(10, 4))
ax[0].plot(rt_axis, rchirp, 'b')
ax[0].plot(rt_axis, mychrip, 'r')
ax[0].set_title("Linear Chirp")
ax[0].set_xlabel('t (sec)')
ax[1].plot(rt_axis[:-1], ifreq(rt_axis, rchirp), 'b')
ax[1].plot(rt_axis[:-1], ifreq(rt_axis, mychrip), 'r')
ax[1].plot(rt_axis, rf_axis, 'k--')
ax[1].set_title("Instantaneous Frequency")
ax[1].set_xlabel('t (sec)')
ax[1].set_ylabel("Frequency (Hz)")
plt.tight_layout()
plt.show()
这为我们提供了以下输出,我们可以看到原始方法的频率开始正确,然后增长速度约为应有的两倍:
话虽如此,看起来您的
rf_axis
和 rt_axis
的生成也可能存在一些混乱。我认为您可能打算使用 np.arange
而不是 np.linspace
来生成频率。类似下面的内容对于您选择的变量名称会更有意义:
f_step = (f1-f0)/no_samp
rf_axis = np.arange(f0, f1, f_step)
rt_axis = np.linspace(0, chirp_duration, len(rf_axis))
通过尝试这个,您会发现您的频率折叠与当前值非常接近,这将导致一些混叠。
无论如何,希望这一切有所帮助,至少有一点帮助。