def main(): # session = bp.Session(load_from_config=False) # bp.output_server(docname='simple_precoded_srs_AN1', session=session) bp.output_file('simple_precoded_srs.html', title="Simple Precoded SRS") # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # xxxxxxxxxxxxxxx Scenario Description xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # 3 Base Stations, each sending data to its own user while interfering # with the other users. # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # xxxxxxxxxxxxxxx Configuration xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx num_prbs = 25 # Number of PRBs to simulate Nsc = 12 * num_prbs # Number of subcarriers Nzc = 149 # Size of the sequence u1 = 1 # Root sequence index of the first user u2 = 2 # Root sequence index of the first user u3 = 3 # Root sequence index of the first user numAnAnt = 4 # Number of Base station antennas numUeAnt = 2 # Number of UE antennas num_samples = 1 # Number of simulated channel samples (from # Jakes process) # Channel configuration speedTerminal = 0 / 3.6 # Speed in m/s fcDbl = 2.6e9 # Central carrier frequency (in Hz) timeTTIDbl = 1e-3 # Time of a single TTI subcarrierBandDbl = 15e3 # Subcarrier bandwidth (in Hz) numOfSubcarriersPRBInt = 12 # Number of subcarriers in each PRB L = 16 # The number of rays for the Jakes model. # Dependent parameters lambdaDbl = 3e8 / fcDbl # Carrier wave length Fd = speedTerminal / lambdaDbl # Doppler Frequency Ts = 1. / (Nsc * subcarrierBandDbl) # Sampling time # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # xxxxxxxxxxxxxxx Generate the root sequence xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx a_u1 = get_extended_ZF(calcBaseZC(Nzc, u1), Nsc / 2) a_u2 = get_extended_ZF(calcBaseZC(Nzc, u2), Nsc / 2) a_u3 = get_extended_ZF(calcBaseZC(Nzc, u3), Nsc / 2) print("Nsc: {0}".format(Nsc)) print("a_u.shape: {0}".format(a_u1.shape)) # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # xxxxxxxxxxxxxxx Create shifted sequences for 3 users xxxxxxxxxxxxxxxxxxxx # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # We arbitrarily choose some cyclic shift index and then we call # zadoffchu.get_srs_seq to get the shifted sequence. shift_index = 4 r1 = get_srs_seq(a_u1, shift_index) r2 = get_srs_seq(a_u2, shift_index) r3 = get_srs_seq(a_u3, shift_index) # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # xxxxxxxxxxxxxxx Generate channels from users to the BS xxxxxxxxxxxxxx # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx jakes_all_links = np.empty([3, 3], dtype=object) tdlchannels_all_links = np.empty([3, 3], dtype=object) impulse_responses = np.empty([3, 3], dtype=object) # Dimension: `UEs x ANs x num_subcarriers x numUeAnt x numAnAnt` freq_responses = np.empty([3, 3, Nsc, numUeAnt, numAnAnt], dtype=complex) for ueIdx in range(3): for anIdx in range(3): jakes_all_links[ueIdx, anIdx] = JakesSampleGenerator(Fd, Ts, L, shape=(numUeAnt, numAnAnt)) tdlchannels_all_links[ueIdx, anIdx] = TdlChannel( jakes_all_links[ueIdx, anIdx], tap_powers_dB=COST259_TUx.tap_powers_dB, tap_delays=COST259_TUx.tap_delays) tdlchannels_all_links[ueIdx, anIdx].generate_impulse_response(num_samples) impulse_responses[ueIdx, anIdx] \ = tdlchannels_all_links[ ueIdx, anIdx].get_last_impulse_response() freq_responses[ueIdx, anIdx] = \ impulse_responses[ueIdx, anIdx].get_freq_response(Nsc)[:, :, :, 0] # xxxxxxxxxx Channels in downlink direction xxxxxxxxxxxxxxxxxxxxxxxxxxx # Dimension: `Nsc x numUeAnt x numAnAnt` dH11 = freq_responses[0, 0] dH12 = freq_responses[0, 1] dH13 = freq_responses[0, 2] dH21 = freq_responses[1, 0] dH22 = freq_responses[1, 1] dH23 = freq_responses[1, 2] dH31 = freq_responses[2, 0] dH32 = freq_responses[2, 1] dH33 = freq_responses[2, 2] # xxxxxxxxxx Principal dimension in downlink direction xxxxxxxxxxxxxxxx sc_idx = 124 # Index of the subcarrier we are interested in [dU11, _, _] = np.linalg.svd(dH11[sc_idx]) [dU22, _, _] = np.linalg.svd(dH22[sc_idx]) [dU33, _, _] = np.linalg.svd(dH33[sc_idx]) # xxxxxxxxxx Users precoders xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # Users' precoders are the main column of the U matrix F11 = dU11[:, 0].conj() F22 = dU22[:, 0].conj() F33 = dU33[:, 0].conj() # xxxxxxxxxx Channels in uplink direction xxxxxxxxxxxxxxxxxxxxxxxxxxxxx # int_path_loss = 0.05 # Path loss of the interfering links # int_g = math.sqrt(int_path_loss) # Gain of interfering links # dir_d = 1.0 # Gain of direct links pl = np.array([[2.21e-08, 2.14e-09, 1.88e-08], [3.45e-10, 2.17e-08, 4.53e-10], [4.38e-10, 8.04e-10, 4.75e-08]]) # pl = np.array([[ 1, 0.1, 0.1], # [ 0.1, 1, 0.1], # [ 0.1, 0.1, 1]]) # Dimension: `Nsc x numAnAnt x numUeAnt` uH11 = math.sqrt(pl[0, 0]) * np.transpose(dH11, axes=[0, 2, 1]) uH12 = math.sqrt(pl[0, 1]) * np.transpose(dH12, axes=[0, 2, 1]) uH13 = math.sqrt(pl[0, 2]) * np.transpose(dH13, axes=[0, 2, 1]) uH21 = math.sqrt(pl[1, 0]) * np.transpose(dH21, axes=[0, 2, 1]) uH22 = math.sqrt(pl[1, 1]) * np.transpose(dH22, axes=[0, 2, 1]) uH23 = math.sqrt(pl[1, 2]) * np.transpose(dH23, axes=[0, 2, 1]) uH31 = math.sqrt(pl[2, 0]) * np.transpose(dH31, axes=[0, 2, 1]) uH32 = math.sqrt(pl[2, 1]) * np.transpose(dH32, axes=[0, 2, 1]) uH33 = math.sqrt(pl[2, 2]) * np.transpose(dH33, axes=[0, 2, 1]) # Compute the equivalent uplink channels uH11_eq = uH11.dot(F11) uH12_eq = uH12.dot(F22) uH13_eq = uH13.dot(F33) uH21_eq = uH21.dot(F11) uH22_eq = uH22.dot(F22) uH23_eq = uH23.dot(F33) uH31_eq = uH31.dot(F11) uH32_eq = uH32.dot(F22) uH33_eq = uH33.dot(F33) # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # xxxxxxxxxxxxxxx Compute Received Signals xxxxxxxxxxxxxxxxxxxxxxxxxxxx # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # Calculate the received signals comb_indexes = np.r_[0:Nsc:2] Y1_term11 = uH11_eq[comb_indexes] * r1[:, np.newaxis] Y1_term12 = uH12_eq[comb_indexes] * r2[:, np.newaxis] Y1_term13 = uH13_eq[comb_indexes] * r3[:, np.newaxis] Y1 = Y1_term11 + Y1_term12 + Y1_term13 Y2_term21 = uH21_eq[comb_indexes] * r1[:, np.newaxis] Y2_term22 = uH22_eq[comb_indexes] * r2[:, np.newaxis] Y2_term23 = uH23_eq[comb_indexes] * r3[:, np.newaxis] Y2 = Y2_term21 + Y2_term22 + Y2_term23 Y3_term31 = uH31_eq[comb_indexes] * r1[:, np.newaxis] Y3_term32 = uH32_eq[comb_indexes] * r2[:, np.newaxis] Y3_term33 = uH33_eq[comb_indexes] * r3[:, np.newaxis] Y3 = Y3_term31 + Y3_term32 + Y3_term33 # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # xxxxxxxxxxxxxxx Estimate the equivalent channel xxxxxxxxxxxxxxxxxxxxx # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (uH11_eq_est, uH12_eq_est, uH13_eq_est, uH21_eq_est, uH22_eq_est, uH23_eq_est, uH31_eq_est, uH32_eq_est, uH33_eq_est) = estimate_channels_remove_only_direct( Y1, Y2, Y3, r1, r2, r3, Nsc, comb_indexes) (uH11_eq_est_SIC, uH12_eq_est_SIC, uH13_eq_est_SIC, uH21_eq_est_SIC, uH22_eq_est_SIC, uH23_eq_est_SIC, uH31_eq_est_SIC, uH32_eq_est_SIC, uH33_eq_est_SIC) = estimate_channels_remove_direct_and_perform_SIC( Y1, Y2, Y3, r1, r2, r3, Nsc, comb_indexes) # Compute the MSE reduction due to SIC improve11 = compute_channel_estimation_error_dB( uH11_eq, uH11_eq_est) - compute_channel_estimation_error_dB( uH11_eq, uH11_eq_est_SIC) improve12 = compute_channel_estimation_error_dB( uH12_eq, uH12_eq_est) - compute_channel_estimation_error_dB( uH12_eq, uH12_eq_est_SIC) improve13 = compute_channel_estimation_error_dB( uH13_eq, uH13_eq_est) - compute_channel_estimation_error_dB( uH13_eq, uH13_eq_est_SIC) improve21 = compute_channel_estimation_error_dB( uH21_eq, uH21_eq_est) - compute_channel_estimation_error_dB( uH21_eq, uH21_eq_est_SIC) improve22 = compute_channel_estimation_error_dB( uH22_eq, uH22_eq_est) - compute_channel_estimation_error_dB( uH22_eq, uH22_eq_est_SIC) improve23 = compute_channel_estimation_error_dB( uH23_eq, uH23_eq_est) - compute_channel_estimation_error_dB( uH23_eq, uH23_eq_est_SIC) improve31 = compute_channel_estimation_error_dB( uH31_eq, uH31_eq_est) - compute_channel_estimation_error_dB( uH31_eq, uH31_eq_est_SIC) improve32 = compute_channel_estimation_error_dB( uH32_eq, uH32_eq_est) - compute_channel_estimation_error_dB( uH32_eq, uH32_eq_est_SIC) improve33 = compute_channel_estimation_error_dB( uH33_eq, uH33_eq_est) - compute_channel_estimation_error_dB( uH33_eq, uH33_eq_est_SIC) print(improve11) print(improve12) print(improve13) print(improve21) print(improve22) print(improve23) print(improve31) print(improve32) print(improve33) # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # xxxxxxxxxxxxxxx Plot the true and estimated channels xxxxxxxxxxxxxxxx # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx p1 = plot_true_and_estimated_channel_with_bokeh_all_antennas( uH11_eq, uH11_eq_est, title='Direct Channel from UE1 to AN1') p2 = plot_true_and_estimated_channel_with_bokeh_all_antennas( uH12_eq, uH12_eq_est, title='Interfering Channel from UE2 to AN1') p3 = plot_true_and_estimated_channel_with_bokeh_all_antennas( uH13_eq, uH13_eq_est, title='Interfering Channel from UE3 to AN1') tab1 = bw.Panel(child=p1, title="UE1 to AN1") tab2 = bw.Panel(child=p2, title="UE2 to AN1") tab3 = bw.Panel(child=p3, title="UE3 to AN1") tabs_an1 = bw.Tabs(tabs=[tab1, tab2, tab3]) p1 = plot_true_and_estimated_channel_with_bokeh_all_antennas( uH21_eq, uH21_eq_est, title='Interfering Channel from UE1 to AN2') p2 = plot_true_and_estimated_channel_with_bokeh_all_antennas( uH22_eq, uH22_eq_est, title='Direct Channel from UE2 to AN2') p3 = plot_true_and_estimated_channel_with_bokeh_all_antennas( uH23_eq, uH23_eq_est, title='Interfering Channel from UE3 to AN2') tab1 = bw.Panel(child=p1, title="UE1 to AN2") tab2 = bw.Panel(child=p2, title="UE2 to AN2") tab3 = bw.Panel(child=p3, title="UE3 to AN2") tabs_an2 = bw.Tabs(tabs=[tab1, tab2, tab3]) p1 = plot_true_and_estimated_channel_with_bokeh_all_antennas( uH31_eq, uH31_eq_est, title='Interfering Channel from UE1 to AN3') p2 = plot_true_and_estimated_channel_with_bokeh_all_antennas( uH32_eq, uH32_eq_est, title='Interfering Channel from UE2 to AN3') p3 = plot_true_and_estimated_channel_with_bokeh_all_antennas( uH33_eq, uH33_eq_est, title='Direct Channel from UE3 to AN3') tab1 = bw.Panel(child=p1, title="UE1 to AN3") tab2 = bw.Panel(child=p2, title="UE2 to AN3") tab3 = bw.Panel(child=p3, title="UE3 to AN3") tabs_an3 = bw.Tabs(tabs=[tab1, tab2, tab3]) # Put each AN tab as a panel of an "ANs tab" and show it tabs1 = bw.Panel(child=tabs_an1, title="AN1") tabs2 = bw.Panel(child=tabs_an2, title="AN2") tabs3 = bw.Panel(child=tabs_an3, title="AN3") tabs_all = bw.Tabs(tabs=[tabs1, tabs2, tabs3]) bp.show(tabs_all)
input_data = np.random.random_integers(0, 4 - 1, num_symbols) # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # xxxxxxxxxx QPSK and OFDM Modulators xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx qpsk_obj = QPSK() ofdm_obj = OFDM(fft_size=fft_size, cp_size=cp_size, num_used_subcarriers=num_used_subcarriers) # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # xxxxxxxxxx Modulate data xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx modulated_data = qpsk_obj.modulate(input_data) transmit_data = ofdm_obj.modulate(modulated_data) # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # xxxxxxxxxx Transmit data through the channel xxxxxxxxxxxxxxxxxxxxxxxx jakes = JakesSampleGenerator(Fd, Ts, L) channel = SuChannel(jakes, channel_profile) channel_memory = channel.num_taps_with_padding - 1 received_data = channel.corrupt_data(transmit_data) # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # xxxxxxxxxx OFDM Demodulate data xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ofdm_received_data = ofdm_obj.demodulate(received_data[:-channel_memory]) # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # xxxxxxxxxx One-Tap Equalization xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # First we need to get the frequency response impulse_response = channel.get_last_impulse_response() freq_response = impulse_response.get_freq_response(fft_size) # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
def test_estimate_channel_multiple_rx(self): Nsc = 24 size = Nsc Nr = 3 # Number of receive antennas num_taps_to_keep = 15 cover_codes = [np.array([-1, 1]), np.array([1, 1])] user1_seq = DmrsUeSequence(RootSequence(root_index=25, size=size), 1, cover_code=cover_codes[0]) user2_seq = DmrsUeSequence(RootSequence(root_index=25, size=size), 4, cover_code=cover_codes[0]) ue1_channel_estimator = CazacBasedWithOCCChannelEstimator(user1_seq) speed_terminal = 3 / 3.6 # Speed in m/s fcDbl = 2.6e9 # Central carrier frequency (in Hz) subcarrier_bandwidth = 15e3 # Subcarrier bandwidth (in Hz) wave_length = 3e8 / fcDbl # Carrier wave length Fd = speed_terminal / wave_length # Doppler Frequency Ts = 1. / (Nsc * subcarrier_bandwidth) # Sampling interval L = 16 # Number of jakes taps # Create the fading generators and set multiple receive antennas jakes1 = JakesSampleGenerator(Fd, Ts, L, shape=(Nr, 1)) jakes2 = JakesSampleGenerator(Fd, Ts, L, shape=(Nr, 1)) # Create a TDL channel object for each user tdlchannel1 = TdlChannel(jakes1, channel_profile=COST259_TUx) tdlchannel2 = TdlChannel(jakes2, channel_profile=COST259_TUx) # Generate channel that would corrupt the transmit signal. tdlchannel1.generate_impulse_response(1) tdlchannel2.generate_impulse_response(1) # Get the generated impulse response impulse_response1 = tdlchannel1.get_last_impulse_response() impulse_response2 = tdlchannel2.get_last_impulse_response() # Get the corresponding frequency response freq_resp_1 = impulse_response1.get_freq_response(Nsc) H1 = freq_resp_1[:, :, 0, 0].T freq_resp_2 = impulse_response2.get_freq_response(Nsc) H2 = freq_resp_2[:, :, 0, 0].T # Sequence of the users r1 = user1_seq.seq_array() r2 = user2_seq.seq_array() # Received signal (in frequency domain) of user 1 Y1 = H1[:, np.newaxis, :] * r1[np.newaxis, :, :] Y2 = H2[:, np.newaxis, :] * r2[np.newaxis, :, :] Y = Y1 + Y2 # Dimension: `Nr x cover_code_size x num_elements` # Calculate expected estimated channel for user 1 cover_code1 = cover_codes[0] Y_with_cover_code = \ (cover_code1[0] * Y[:,0,:] + cover_code1[1] * Y[:,1,:]) / 2.0 ":type: np.ndarray" r1_no_cover_code = r1[0] * cover_code1[0] y1 = np.fft.ifft(np.conj(r1_no_cover_code[np.newaxis]) * Y_with_cover_code, size, axis=1) tilde_h1_espected = y1[:, 0:(num_taps_to_keep + 1)] tilde_H1_espected = np.fft.fft(tilde_h1_espected, Nsc, axis=1) # Test the CazacBasedWithOCCChannelEstimator estimation H1_estimated = ue1_channel_estimator.estimate_channel_freq_domain( Y, num_taps_to_keep, extra_dimension=True) np.testing.assert_array_almost_equal(H1_estimated, tilde_H1_espected) # Test if true channel and estimated channel are similar. Since the # channel estimation error is higher at the first and last # subcarriers we will test only the inner 200 subcarriers error = np.abs(H1 - tilde_H1_espected) ":type: np.ndarray" np.testing.assert_almost_equal(error / 2., np.zeros(error.shape), decimal=2)
def test_estimate_channel_with_dmrs(self): Nsc = 24 size = Nsc cover_codes = [np.array([-1, 1]), np.array([1, 1])] user1_seq = DmrsUeSequence(root_seq=RootSequence(root_index=17, size=size), n_cs=1, cover_code=cover_codes[0]) user2_seq = DmrsUeSequence(root_seq=RootSequence(root_index=17, size=size), n_cs=4, cover_code=cover_codes[1]) ue1_channel_estimator = CazacBasedWithOCCChannelEstimator(user1_seq) speed_terminal = 3 / 3.6 # Speed in m/s fcDbl = 2.6e9 # Central carrier frequency (in Hz) subcarrier_bandwidth = 15e3 # Subcarrier bandwidth (in Hz) wave_length = 3e8 / fcDbl # Carrier wave length Fd = speed_terminal / wave_length # Doppler Frequency Ts = 1. / (Nsc * subcarrier_bandwidth) # Sampling interval L = 16 # Number of jakes taps jakes1 = JakesSampleGenerator(Fd, Ts, L) jakes2 = JakesSampleGenerator(Fd, Ts, L) # Create a TDL channel object for each user tdlchannel1 = TdlChannel(jakes1, channel_profile=COST259_TUx) tdlchannel2 = TdlChannel(jakes2, channel_profile=COST259_TUx) # Generate channel that would corrupt the transmit signal. tdlchannel1.generate_impulse_response(1) tdlchannel2.generate_impulse_response(1) # Get the generated impulse response impulse_response1 = tdlchannel1.get_last_impulse_response() impulse_response2 = tdlchannel2.get_last_impulse_response() # Get the corresponding frequency response freq_resp_1 = impulse_response1.get_freq_response(Nsc) H1 = freq_resp_1[:, 0] freq_resp_2 = impulse_response2.get_freq_response(Nsc) H2 = freq_resp_2[:, 0] # Sequence of the users r1 = user1_seq.seq_array() r2 = user2_seq.seq_array() # Received signal (in frequency domain) of user 1 Y1 = H1 * r1 Y2 = H2 * r2 Y = Y1 + Y2 # Calculate expected estimated channel for user 1 cover_code1 = cover_codes[0] Y_with_cover_code = \ (cover_code1[0] * Y[0] + cover_code1[1] * Y[1]) / 2.0 ":type: np.ndarray" r1_no_cover_code = r1[0] * cover_code1[0] y1 = np.fft.ifft(np.conj(r1_no_cover_code) * Y_with_cover_code, size) tilde_h1 = y1[0:4] tilde_H1 = np.fft.fft(tilde_h1, Nsc) # Test the CazacBasedWithOCCChannelEstimator estimation np.testing.assert_array_almost_equal( ue1_channel_estimator.estimate_channel_freq_domain( Y, 3, extra_dimension=True), tilde_H1) # Test if true channel and estimated channel are similar. Since the # channel estimation error is higher at the first and last # subcarriers we will test only the inner 200 subcarriers error = np.abs(H1 - tilde_H1) ":type: np.ndarray" np.testing.assert_almost_equal(error / 2., np.zeros(error.size), decimal=2)
def test_estimate_channel_multiple_rx(self): Nsc = 300 # 300 subcarriers size = Nsc // 2 Nzc = 139 user1_seq = SrsUeSequence(RootSequence(root_index=25, size=size, Nzc=Nzc), 1, normalize=True) user2_seq = SrsUeSequence(RootSequence(root_index=25, size=size, Nzc=Nzc), 4, normalize=True) ue1_channel_estimator = CazacBasedChannelEstimator(user1_seq) speed_terminal = 3 / 3.6 # Speed in m/s fcDbl = 2.6e9 # Central carrier frequency (in Hz) subcarrier_bandwidth = 15e3 # Subcarrier bandwidth (in Hz) wave_length = 3e8 / fcDbl # Carrier wave length Fd = speed_terminal / wave_length # Doppler Frequency Ts = 1. / (Nsc * subcarrier_bandwidth) # Sampling interval L = 16 # Number of jakes taps # Create the fading generators and set multiple receive antennas jakes1 = JakesSampleGenerator(Fd, Ts, L, shape=(3, 1)) jakes2 = JakesSampleGenerator(Fd, Ts, L, shape=(3, 1)) # Create a TDL channel object for each user tdlchannel1 = TdlChannel(jakes1, channel_profile=COST259_TUx) tdlchannel2 = TdlChannel(jakes2, channel_profile=COST259_TUx) # Generate channel that would corrupt the transmit signal. tdlchannel1.generate_impulse_response(1) tdlchannel2.generate_impulse_response(1) # Get the generated impulse response impulse_response1 = tdlchannel1.get_last_impulse_response() impulse_response2 = tdlchannel2.get_last_impulse_response() # Get the corresponding frequency response freq_resp_1 = impulse_response1.get_freq_response(Nsc) H1 = freq_resp_1[:, :, 0, 0] freq_resp_2 = impulse_response2.get_freq_response(Nsc) H2 = freq_resp_2[:, :, 0, 0] # Sequence of the users r1 = user1_seq.seq_array() r2 = user2_seq.seq_array() # Received signal (in frequency domain) of user 1 comb_indexes = np.arange(0, Nsc, 2) Y1 = H1[comb_indexes, :] * r1[:, np.newaxis] Y2 = H2[comb_indexes, :] * r2[:, np.newaxis] Y = Y1 + Y2 # Calculate expected estimated channel for user 1 y1 = np.fft.ifft(r1.size * np.conj(r1[:, np.newaxis]) * Y, size, axis=0) tilde_h1_espected = y1[0:16] tilde_H1_espected = np.fft.fft(tilde_h1_espected, Nsc, axis=0) # Test the CazacBasedChannelEstimator estimation H1_estimated = ue1_channel_estimator.estimate_channel_freq_domain( Y.T, 15) np.testing.assert_array_almost_equal(H1_estimated, tilde_H1_espected.T) # Test if true channel and estimated channel are similar. Since the # channel estimation error is higher at the first and last # subcarriers we will test only the inner 200 subcarriers error = np.abs(H1[50:-50, :] - tilde_H1_espected[50:-50, :]) ":type: np.ndarray" np.testing.assert_almost_equal(error / 2., np.zeros(error.shape), decimal=2)
def test_estimate_channel_without_comb_pattern(self): Nsc = 300 # 300 subcarriers size = Nsc # The size is also 300, since there is no comb pattern Nzc = 139 user1_seq = SrsUeSequence( RootSequence(root_index=25, size=size, Nzc=Nzc), 1) user2_seq = SrsUeSequence( RootSequence(root_index=25, size=size, Nzc=Nzc), 4) # Set size_multiplier to 1, since we won't use the comb pattern ue1_channel_estimator = CazacBasedChannelEstimator(user1_seq, size_multiplier=1) speed_terminal = 3 / 3.6 # Speed in m/s fcDbl = 2.6e9 # Central carrier frequency (in Hz) subcarrier_bandwidth = 15e3 # Subcarrier bandwidth (in Hz) wave_length = 3e8 / fcDbl # Carrier wave length Fd = speed_terminal / wave_length # Doppler Frequency Ts = 1. / (Nsc * subcarrier_bandwidth) # Sampling interval L = 16 # Number of jakes taps jakes1 = JakesSampleGenerator(Fd, Ts, L) jakes2 = JakesSampleGenerator(Fd, Ts, L) # Create a TDL channel object for each user tdlchannel1 = TdlChannel(jakes1, channel_profile=COST259_TUx) tdlchannel2 = TdlChannel(jakes2, channel_profile=COST259_TUx) # Generate channel that would corrupt the transmit signal. tdlchannel1.generate_impulse_response(1) tdlchannel2.generate_impulse_response(1) # Get the generated impulse response impulse_response1 = tdlchannel1.get_last_impulse_response() impulse_response2 = tdlchannel2.get_last_impulse_response() # Get the corresponding frequency response freq_resp_1 = impulse_response1.get_freq_response(Nsc) H1 = freq_resp_1[:, 0] freq_resp_2 = impulse_response2.get_freq_response(Nsc) H2 = freq_resp_2[:, 0] # Sequence of the users r1 = user1_seq.seq_array() r2 = user2_seq.seq_array() # Received signal (in frequency domain) of user 1 Y1 = H1 * r1 Y2 = H2 * r2 Y = Y1 + Y2 # Calculate expected estimated channel for user 1 y1 = np.fft.ifft(np.conj(r1) * Y, size) tilde_h1 = y1[0:16] tilde_H1 = np.fft.fft(tilde_h1, Nsc) # Test the CazacBasedChannelEstimator estimation np.testing.assert_array_almost_equal( ue1_channel_estimator.estimate_channel_freq_domain(Y, 15), tilde_H1) # Test if true channel and estimated channel are similar. Since the # channel estimation error is higher at the first and last # subcarriers we will test only the inner 200 subcarriers error = np.abs(H1[50:-50] - tilde_H1[50:-50]) ":type: np.ndarray" np.testing.assert_almost_equal(error / 2., np.zeros(error.size), decimal=2)
def test_estimate_channel_with_srs(self): Nsc = 300 # 300 subcarriers size = Nsc // 2 Nzc = 139 user1_seq = SrsUeSequence(RootSequence(root_index=25, size=size, Nzc=Nzc), 1, normalize=True) user2_seq = SrsUeSequence(RootSequence(root_index=25, size=size, Nzc=Nzc), 4, normalize=True) ue1_channel_estimator = CazacBasedChannelEstimator(user1_seq) ue2_channel_estimator = CazacBasedChannelEstimator(user2_seq) speed_terminal = 3 / 3.6 # Speed in m/s fcDbl = 2.6e9 # Central carrier frequency (in Hz) subcarrier_bandwidth = 15e3 # Subcarrier bandwidth (in Hz) wave_length = 3e8 / fcDbl # Carrier wave length Fd = speed_terminal / wave_length # Doppler Frequency Ts = 1. / (Nsc * subcarrier_bandwidth) # Sampling interval L = 16 # Number of jakes taps jakes1 = JakesSampleGenerator(Fd, Ts, L) jakes2 = JakesSampleGenerator(Fd, Ts, L) # Create a TDL channel object for each user tdlchannel1 = TdlChannel(jakes1, channel_profile=COST259_TUx) tdlchannel2 = TdlChannel(jakes2, channel_profile=COST259_TUx) # Generate channel that would corrupt the transmit signal. tdlchannel1.generate_impulse_response(1) tdlchannel2.generate_impulse_response(1) # Get the generated impulse response impulse_response1 = tdlchannel1.get_last_impulse_response() impulse_response2 = tdlchannel2.get_last_impulse_response() # Get the corresponding frequency response freq_resp_1 = impulse_response1.get_freq_response(Nsc) H1 = freq_resp_1[:, 0] freq_resp_2 = impulse_response2.get_freq_response(Nsc) H2 = freq_resp_2[:, 0] # Sequence of the users r1 = user1_seq.seq_array() r2 = user2_seq.seq_array() # Received signal (in frequency domain) of user 1 comb_indexes = np.arange(0, Nsc, 2) Y1 = H1[comb_indexes] * r1 Y2 = H2[comb_indexes] * r2 Y = Y1 + Y2 # xxxxxxxxxx USER 1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # Calculate expected estimated channel for user 1 y1 = np.fft.ifft(r1.size * np.conj(r1) * Y, size) tilde_h1 = y1[0:16] tilde_H1 = np.fft.fft(tilde_h1, Nsc) # Test the CazacBasedChannelEstimator estimation np.testing.assert_array_almost_equal( ue1_channel_estimator.estimate_channel_freq_domain(Y, 15), tilde_H1) # Check that the estimated channel and the True channel have similar # norms self.assertAlmostEqual(np.linalg.norm( ue1_channel_estimator.estimate_channel_freq_domain(Y, 15)), np.linalg.norm(H1), delta=0.5) # Test if true channel and estimated channel are similar. Since the # channel estimation error is higher at the first and last # subcarriers we will test only the inner 200 subcarriers error = np.abs(H1[50:-50] - tilde_H1[50:-50]) ":type: np.ndarray" np.testing.assert_almost_equal(error / 2., np.zeros(error.size), decimal=2) # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # xxxxxxxxxx USER 2 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # Calculate expected estimated channel for user 2 y2 = np.fft.ifft(r2.size * np.conj(r2) * Y, size) tilde_h2 = y2[0:16] tilde_H2 = np.fft.fft(tilde_h2, Nsc) # Test the CazacBasedChannelEstimator estimation np.testing.assert_array_almost_equal( ue2_channel_estimator.estimate_channel_freq_domain(Y, 15), tilde_H2) # Check that the estimated channel and the True channel have similar # norms self.assertAlmostEqual(np.linalg.norm( ue2_channel_estimator.estimate_channel_freq_domain(Y, 15)), np.linalg.norm(H2), delta=0.5) # Test if true channel and estimated channel are similar. Since the # channel estimation error is higher at the first and last # subcarriers we will test only the inner 200 subcarriers error = np.abs(H2[50:-50] - tilde_H2[50:-50]) ":type: np.ndarray" np.testing.assert_almost_equal(error / 2., np.zeros(error.size), decimal=2)