如何使用Python生成正弦、余弦、锯齿波信号并检测信号正交性
Python 信号生成与正交性检验实现
前置依赖
你需要提前安装三个科学计算库,执行以下命令安装:pip install numpy scipy matplotlib
完整实现代码
import numpy as np from scipy.signal import sawtooth import matplotlib.pyplot as plt # 信号参数设置:采样率1000Hz,采样时长1s(刚好覆盖整数个周期,保证正交检验准确性) fs = 1000 duration = 1 t = np.linspace(0, duration, int(fs * duration), endpoint=False) # 生成目标信号 sin_1hz = np.sin(2 * np.pi * 1 * t) # 1Hz正弦波 cos_1hz = np.cos(2 * np.pi * 1 * t) # 1Hz余弦波 saw_1hz = sawtooth(2 * np.pi * 1 * t) # 1Hz锯齿波 sin_2hz = np.sin(2 * np.pi * 2 * t) # 2Hz正弦波 # 信号打包,方便批量计算 signal_list = [sin_1hz, cos_1hz, saw_1hz, sin_2hz] signal_names = ["1Hz正弦波", "1Hz余弦波", "1Hz锯齿波", "2Hz正弦波"] signal_num = len(signal_list) # 两两正交性检验:离散信号正交判定标准为归一化内积绝对值小于1e-6(抵消浮点计算误差) print("===== 两两信号正交性检验结果 =====") for i in range(signal_num): for j in range(i+1, signal_num): # 归一化内积,等价于连续信号单周期积分的离散近似 norm_dot = np.sum(signal_list[i] * signal_list[j]) / len(t) is_orthogonal = abs(norm_dot) < 1e-6 print(f"{signal_names[i]} & {signal_names[j]} | 归一化内积:{norm_dot:.8f} | 是否正交:{'是' if is_orthogonal else '否'}") # 可选:绘制所有信号波形 plt.figure(figsize=(12, 8)) for idx in range(signal_num): plt.subplot(signal_num, 1, idx+1) plt.plot(t, signal_list[idx], linewidth=1) plt.title(signal_names[idx], fontsize=10) plt.xlabel("时间(s)", fontsize=9) plt.ylabel("幅值", fontsize=9) plt.grid(alpha=0.3) plt.tight_layout() plt.show()
关键说明
- 正交性检验的前提是采样时长覆盖所有信号的整数个周期,否则内积结果会有偏差,本示例取1s刚好是1Hz、2Hz信号的整数倍周期
- 运行后你会得到以下符合信号理论的结果:
- 1Hz正弦波 & 1Hz余弦波:正交
- 1Hz正弦波 & 2Hz正弦波:正交
- 1Hz余弦波 & 2Hz正弦波:正交
- 其余包含1Hz锯齿波的组合均不正交,因为锯齿波含有1Hz基波分量,和同频单频信号内积不为0
Matlab语法对应参考
| Matlab语法 | Python对应语法 | 说明 |
|---|---|---|
linspace(a,b,n) | np.linspace(a,b,n) | 用法基本一致,注意Python要先导入numpy |
sin(2*pi*f*t) | np.sin(2*np.pi*f*t) | 三角函数、圆周率均在numpy包下 |
sawtooth(2*pi*f*t) | 从scipy.signal导入sawtooth后调用sawtooth(2*np.pi*f*t) | 锯齿波生成函数在scipy的signal模块 |
dot(x,y)/sum(x.*y) | np.dot(x,y)/np.sum(x*y) | 点积、逐元素乘的用法和Matlab逻辑一致 |
内容的提问来源于stack exchange,提问作者mahoaga
相关产品推荐
相关产品推荐

