利用Python搭建通信系统时,有些内置函数我们很难用Python实现,因此对于这些函数,我们可以通过MATLAB中的Python API通过Python调用这些函数,前面我们已经介绍了怎么在Python上安装MATLAB引擎。我们所需要搭建的无线通信系统框图如图1所示。
前面我们介绍了通信系统中的调制解调部分。接着,将调制后传输信号按一定的帧结构组成物理帧,在LTE协议中,物理帧中的最小单元称为“资源元素”,即为每一个调制后的符号,所有资源元素构成资源网格。资源元素映射是按一定的映射规则将数据符号和导频符号映射到资源网格中相应的位,其中数据符号为比特流调制后的信号,导频符号为接收双方知晓的参考信号,这里我们随机生成一定数量的比特信号,然后通过QPSK调制成发送的频域导频符号,其函数如下所示
数据符号和导频符号按照导频插入的规则分别映射到资源网格上,其函数为
其中idx_data表示数据符号在资源网格处的索引,idx_csr表示导频符号在资源网格处的索引。将数据符号和导频符号都映射到资源网格上后,接下来对完成映射的资源网格进行OFDM调制,由于OFDM调制的数学原理与傅里叶逆(IFFT)变换等效,因此可以直接对资源网格进行IFFT完成OFDM调制操作。信号经OFDM调制后,添加循环前缀(CP),然后通过并串转换得到发射的时域信号。加入CP的目的是消除符号间干扰(ISI),由于多径的影响,将破坏子载波间的正交性,引入ISI。其函数为
此时我们已经得到时域的发射信号,接下来是通过衰落信道和AWGN信道,衰落信道我们这里使用的是MATLAB自带的库函数comm.MIMOChannel,而这个函数很难用Python实现,因此我们直接在Python中通过MATLAB API调用该函数,其调用形式为
其中engine为Python中MATLAB的引擎接口。AWGN信道比较容易实现,其函数为
将发射的时域信号通过这两种信道就得到接收的时域信号,当接收机接收到衰落的信号后,首先去除信号中的CP,然后对去除CP后的信号进行OFDM解调,即对信号进行(FFT)操作将时域信号转换为频域信号,其函数为
接着对OFDM解调后的信号进行资源元素反映射,得到接收的符号流,其函数为
最后通过信道估计、信道均衡和解调将信号还原为比特流。这部分后面详细介绍。我们将所有函数编写成主函数为
1. import sys
2. sys.path.append(\’../\’)
3.
4. import numpy as np
5. import matlab
6. import time
7. import scipy.io as sio
8. import matlab.engine
9. import pickle as pkl
10.import matplotlib.pyplot as plt
11.from functional import REmapper_Tx, OFDM_Tx, CSRGenerator, get_Model, ChanEstimate_mTx
12.from functional import MIMOFadingChan, AWGNChannel, IdChEst, OFDM_Rx, REdemapper_Tx
13.from functional import ExtChResponse, NMSECaculator, MIMOReceiver, Model, Model_params
14.from MIMOParams import getParams
15.from QAM import Modulator
16.
17.
18.# start matlab engine
19.if \’engine\’ not in locals() and \’engine\’ not in globals():
20. try:
21. engine = matlab.engine.connect_matlab()
22. except:
23. engine = matlab.engine.start_matlab()
24.engine.clear(nargout=0)
25.
26.# simulation parameters
27.Dopplers = [130, 260, 389, 519, 648, 778]
28.Delays = [3, 6, 9, 12, 15, 18]
29.Velocity = [\’50km/h\’, \’100km/h\’, \’150km/h\’, \’200km/h\’, \’250km/h\’, \’300km/h\’]
30.dp_indices = 5
31.dl_indices = 5
32.paras = dict(Nsubframe=100,
33. BWCase=1,
34. Doppler=Dopplers[dp_indices],
35. Delay=Delays[dl_indices],
36. Separation=3)
37.p = getParams(**paras)
38.p.EqMode = 1
39.# load model
40.Model_params[\’bias\’] = False
41.strftime = \’_%d\’%p.Separation
42.model_lstm = get_Model(\’lstm\’,strftime,Model_params)
43.model_mygru = get_Model(\’mygru\’,strftime,Model_params)
44.
45.SNRs = np.arange(0,26,5).tolist()
46.#SNRs = [30]
47.
48.ber_ls = []
49.ber_lmmse = []
50.ber_cdp = []
51.ber_sta = []
52.ber_mygru = []
53.ber_lstm = []
54.ber_perfect = []
55.nmse_ls = []
56.nmse_lmmse = []
57.nmse_cdp = []
58.nmse_sta = []
59.nmse_mygru = []
60.nmse_lstm = []
61.for i, SNR in enumerate(SNRs):
62. numErrs_ls = 0
63. numErrs_lmmse = 0
64. numErrs_cdp = 0
65. numErrs_sta = 0
66. numErrs_mygru = 0
67. numErrs_lstm = 0
68. numErrs_p = 0
69. nmse_ls_tmp = 0
70. nmse_lmmse_tmp = 0
71. nmse_cdp_tmp = 0
72. nmse_sta_tmp = 0
73. nmse_mygru_tmp = 0
74. nmse_lstm_tmp = 0
75. st=time.perf_counter()
76. for n in range(p.Nsubframe):
77.# dataIn = engine.randi(matlab.double([0, 1]),p.FRM,1)
78. dataIn = np.random.randint(0,2,(p.FRM,1))
79. # Modulate
80. modOut = Modulator(dataIn,p.modType)
81. # CSR generate
82.# csrTx = pkl.load(open(\’./csrTx\’,\’rb\’))[0]
83. csrTx = CSRGenerator(p)
84. txGrid = REmapper_Tx(modOut,csrTx,p)
85. txSig = OFDM_Tx(txGrid,p)
86. # MIMO fading channel
87. txSig = matlab.double(txSig.tolist(),is_complex=True)
88. rxFade, chPathG = MIMOFadingChan(txSig, p, engine)
89. # AWGN channel
90. nVar = 10**(0.1*(-SNR))
91. rxSig = AWGNChannel(np.array(rxFade), nVar)
92. chPathG = np.array(chPathG)
93. H = IdChEst(chPathG, p)
94. rxGrid = OFDM_Rx(rxSig, p)
95. dataRx, csrRx = REdemapper_Tx(rxGrid, p)
96. # channel extimation
97. h_piolt, h_ls, h_lmmse, h_cdp, h_sta = ChanEstimate_mTx(rxGrid, csrRx, csrTx, SNR, p)
98. h_mygru = Model(model_mygru, h_piolt, dl_indices, dp_indices)
99. h_lstm = Model(model_lstm, h_piolt, dl_indices, dp_indices)
100.
101. hD_ls = ExtChResponse(h_ls, p)
102. hD_lmmse = ExtChResponse(h_lmmse, p)
103. hD_cdp = ExtChResponse(h_cdp, p)
104. hD_sta = ExtChResponse(h_sta, p)
105. hD_mygru = ExtChResponse(h_mygru, p)
106. hD_lstm = ExtChResponse(h_lstm, p)
107. hD_p = ExtChResponse(H, p)
108. # NMSE Caculate
109. nmse_ls_tmp += NMSECaculator(hD_ls, hD_p)
110. nmse_cdp_tmp += NMSECaculator(hD_cdp, hD_p)
111. nmse_sta_tmp += NMSECaculator(hD_sta, hD_p)
112. nmse_lmmse_tmp += NMSECaculator(hD_lmmse, hD_p)
113. nmse_mygru_tmp += NMSECaculator(hD_mygru, hD_p)
114. nmse_lstm_tmp += NMSECaculator(hD_lstm, hD_p)
115. # MIMOReceiver-Equalize and Demodulate
116. dataOut_cdp = MIMOReceiver(dataRx, hD_cdp, nVar, p)
117. dataOut_sta = MIMOReceiver(dataRx, hD_sta, nVar, p)
118. dataOut_ls = MIMOReceiver(dataRx, hD_ls, nVar, p)
119. dataOut_lmmse = MIMOReceiver(dataRx, hD_lmmse, nVar, p)
120. dataOut_mygru = MIMOReceiver(dataRx, hD_mygru, nVar, p)
121. dataOut_lstm = MIMOReceiver(dataRx, hD_lstm, nVar, p)
122. dataOut_perfect = MIMOReceiver(dataRx, hD_p, nVar, p)
123. # Error Statistics
124. numErrs_ls += np.sum(np.logical_not(np.equal(dataOut_ls,dataIn)))
125. numErrs_cdp += np.sum(np.logical_not(np.equal(dataOut_cdp,dataIn)))
126. numErrs_sta += np.sum(np.logical_not(np.equal(dataOut_sta,dataIn)))
127. numErrs_lmmse += np.sum(np.logical_not(np.equal(dataOut_lmmse,dataIn)))
128. numErrs_mygru += np.sum(np.logical_not(np.equal(dataOut_mygru,dataIn)))
129. numErrs_lstm += np.sum(np.logical_not(np.equal(dataOut_lstm,dataIn)))
130. numErrs_p += np.sum(np.logical_not(np.equal(dataOut_perfect,dataIn)))
131. print(\’\\r[SNR=%d] ETC: %ds, %d/%d \’%(SNR,round(time.perf_counter()-st),n+1,p.Nsubframe), end=\’\’, flush=True)
132. nmse_ls.append(nmse_ls_tmp/p.Nsubframe)
133. nmse_cdp.append(nmse_cdp_tmp/p.Nsubframe)
134. nmse_sta.append(nmse_sta_tmp/p.Nsubframe)
135. nmse_lmmse.append(nmse_lmmse_tmp/p.Nsubframe)
136. nmse_mygru.append(nmse_mygru_tmp/p.Nsubframe)
137. nmse_lstm.append(nmse_lstm_tmp/p.Nsubframe)
138. ber_ls.append(numErrs_ls/(p.FRM*p.Nsubframe))
139. ber_cdp.append(numErrs_cdp/(p.FRM*p.Nsubframe))
140. ber_sta.append(numErrs_sta/(p.FRM*p.Nsubframe))
141. ber_lmmse.append(numErrs_lmmse/(p.FRM*p.Nsubframe))
142. ber_mygru.append(numErrs_mygru/(p.FRM*p.Nsubframe))
143. ber_lstm.append(numErrs_lstm/(p.FRM*p.Nsubframe))
144. ber_perfect.append(numErrs_p/(p.FRM*p.Nsubframe))
145. print(\’ \’)
146.
147.# save variables
148.
149.variables = dict(nmse_ls=nmse_ls,
150. nmse_lmmse=nmse_lmmse,
151. nmse_mygru=nmse_mygru,
152. nmse_lstm=nmse_lstm,
153. nmse_cdp=nmse_cdp,
154. nmse_sta=nmse_sta,
155. ber_ls=ber_ls,
156. ber_sta=ber_sta,
157. ber_cdp=ber_cdp,
158. ber_lmmse=ber_lmmse,
159. ber_mygru=ber_mygru,
160. ber_lstm=ber_lstm,
161. ber_perfect=ber_perfect)
162.filepath = \’./results/saved_ber_nmse_%d_%d_%d\’%(p.Separation,Dopplers[dl_indices],Delays[dl_indices])
163.np.save(filepath, variables)
164.sio.savemat(filepath+\’.mat\’, variables)
165.
166.xIndex = SNRs
167.plt.figure(figsize=(16,5),dpi=100)
168.plt.subplot(121)
169.plt.semilogy(xIndex, nmse_ls, \’-og\’, label=\’LS\’)
170.plt.semilogy(xIndex, nmse_lmmse, \’-sg\’, label=\’LMMSE\’)
171.plt.semilogy(xIndex, nmse_mygru, \’-^r\’, label=\’CNN-CRU\’)
172.plt.semilogy(xIndex, nmse_lstm, \’-xr\’, label=\’DNN-LSTM\’)
173.plt.semilogy(xIndex, nmse_cdp, \’-*b\’, label=\’CDP\’)
174.plt.semilogy(xIndex, nmse_sta, \’-sb\’, label=\’STA\’)
175.plt.ylabel(\’NMSE\’)
176.plt.xlabel(\’SNR/dB\’)
177.#plt.xticks([])
178.plt.title(\’%s\’%Velocity[dl_indices])
179.plt.grid(linestyle=\”:\”,which=\’both\’)
180.plt.legend(prop = {\’size\’:12})
181.plt.subplot(122)
182.plt.semilogy(xIndex, ber_ls, \’-og\’, label=\’LS\’)
183.plt.semilogy(xIndex, ber_lmmse, \’-sg\’, label=\’LMMSE\’)
184.plt.semilogy(xIndex, ber_mygru, \’-^r\’, label=\’CNN-CRU\’)
185.plt.semilogy(xIndex, ber_lstm, \’-xr\’, label=\’DNN-LSTM\’)
186.plt.semilogy(xIndex, ber_cdp, \’-*b\’, label=\’CDP\’)
187.plt.semilogy(xIndex, ber_sta, \’-sb\’, label=\’STA\’)
188.plt.semilogy(xIndex, ber_perfect, \’-ok\’, label=\’perfect CSI\’)
189.plt.ylabel(\’BER\’)
190.plt.xlabel(\’SNR/dB\’)
191.plt.title(\’%s\’%Velocity[dl_indices])
192.plt.grid(linestyle=\”:\”,which=\’both\’)
193.plt.legend(prop = {\’size\’:12})
194.plt.show()
运行结果为
其中CNN-CRU,DNN-LSTM为我们实验室所提的深度学习信道估计算法。
未完待续…….