def test_doa_estimate_bartlett(self): M = 4 N = 2**12 d = 0.5 theta = 60 ula_alignment = np.arange(0, 4, 1) * 0.5 incident_angles = np.arange(0, 181, 1) scan_vecs = directionEstimation.gen_ula_scanning_vectors( ula_alignment, incident_angles ) doa_est = ettusdf.DOAEstimator( array_type='ULA', array_alignment=ula_alignment, incident_angles=incident_angles, estimator='Bartlett' ) a = np.exp(np.arange(0, M, 1)*1j*2*np.pi*d*np.cos(np.deg2rad(theta))) soi = np.random.normal(0, 1, N) soi_matrix = np.outer(soi, a).T noise = np.random.normal(0, np.sqrt(10**-1), (M,N)) rx_signal = soi_matrix R = directionEstimation.corr_matrix_estimate(rx_signal.T, imp="mem_eff") Bartlett = directionEstimation.DOA_Bartlett(R, scan_vecs) np.testing.assert_array_equal(Bartlett, doa_est.estimate_doa(rx_signal))
def estimate_DOA(self): #print("[ INFO ] Python DSP: Estimating DOA") iq_samples = self.module_receiver.iq_samples[:, 0:self.DOA_sample_size] # Calculating spatial correlation matrix R = de.corr_matrix_estimate(iq_samples.T, imp="fast") if self.en_DOA_FB_avg: R = de.forward_backward_avg(R) M = np.size(iq_samples, 0) if self.DOA_ant_alignment == "UCA": self.DOA_theta = np.linspace(0, 360, 361) #scanning_vectors = de.gen_uca_scanning_vectors(M, self.DOA_inter_elem_space, self.DOA_theta) x = self.DOA_inter_elem_space * np.cos( 2 * np.pi / M * np.arange(M)) y = self.DOA_inter_elem_space * np.sin( -2 * np.pi / M * np.arange(M)) # For this specific array only scanning_vectors = de.gen_scanning_vectors(M, x, y, self.DOA_theta) # DOA estimation if self.en_DOA_Bartlett: self.DOA_Bartlett_res = de.DOA_Bartlett(R, scanning_vectors) if self.en_DOA_Capon: self.DOA_Capon_res = de.DOA_Capon(R, scanning_vectors) if self.en_DOA_MEM: self.DOA_MEM_res = de.DOA_MEM(R, scanning_vectors, column_select=0) if self.en_DOA_MUSIC: self.DOA_MUSIC_res = de.DOA_MUSIC(R, scanning_vectors, signal_dimension=1) elif self.DOA_ant_alignment == "ULA": self.DOA_theta = np.linspace(-90, 90, 181) x = np.zeros(M) y = np.arange(M) * self.DOA_inter_elem_space scanning_vectors = de.gen_scanning_vectors(M, x, y, self.DOA_theta) # DOA estimation if self.en_DOA_Bartlett: self.DOA_Bartlett_res = de.DOA_Bartlett(R, scanning_vectors) if self.en_DOA_Capon: self.DOA_Capon_res = de.DOA_Capon(R, scanning_vectors) if self.en_DOA_MEM: self.DOA_MEM_res = de.DOA_MEM(R, scanning_vectors, column_select=0) if self.en_DOA_MUSIC: self.DOA_MUSIC_res = de.DOA_MUSIC(R, scanning_vectors, signal_dimension=1) print(self.DOA_MUSIC_res)
def get_doa_estimate(self): self.spectrum[1, :] = 10 * np.log10( np.fft.fftshift( np.abs( np.fft.fft(self.receiver.iq_samples[ 0, 0:self.spectrum_sample_size])))) iq_samples = self.receiver.iq_samples[:, 0:self.doa_sample_size] R = de.corr_matrix_estimate(iq_samples.T, imp="fast") M = np.size(iq_samples, 0) self.doa_theta = np.linspace(0, 360, 361) x = DOA_INTER_ELEM_SPACE * np.cos(2 * np.pi / M * np.arange(M)) y = DOA_INTER_ELEM_SPACE * np.sin( -2 * np.pi / M * np.arange(M)) # For this specific array only scanning_vectors = de.gen_scanning_vectors(M, x, y, self.doa_theta) self.doa_bartlett_res = de.DOA_Bartlett(R, scanning_vectors) thetas = self.doa_theta bartlett = self.doa_bartlett_res doa = 0 doa_results = [] combined = np.zeros_like(thetas, dtype=np.complex) plt = self.doa_plot_helper(bartlett, thetas) combined += np.divide(np.abs(bartlett), np.max(np.abs(bartlett))) doa_results.append(thetas[np.argmax(bartlett)]) if len(doa_results) != 0: combined_log = self.doa_plot_helper(combined, thetas) confidence = scipy.signal.find_peaks_cwt(combined_log, np.arange(10, 30), min_snr=1) maxIndex = confidence[np.argmax(combined_log[confidence])] confidence_sum = 0 for val in confidence: if (val != maxIndex and np.abs(combined_log[val] - min(combined_log)) > np.abs(min(combined_log)) * 0.25): confidence_sum += 1 / (np.abs(combined_log[val])) elif val == maxIndex: confidence_sum += 1 / np.abs(min(combined_log)) max_power_level = np.max(self.spectrum[1, :]) confidence_sum = 10 / confidence_sum doa_results = np.array(doa_results) doa_results_c = np.exp(1j * np.deg2rad(doa_results)) doa_avg_c = np.average(doa_results_c) doa = np.rad2deg(np.angle(doa_avg_c)) if doa < 0: doa += 360 print("---------- DOA Estimate ----------") print(str(int(doa))) print(str(int(confidence_sum))) print(str(np.maximum(0, max_power_level)))
def estimate_doa(self, rx_signal): R = directionEstimation.corr_matrix_estimate(rx_signal.T, imp="mem_eff") if self.__estimator == "Bartlett": estimate = directionEstimation.DOA_Bartlett( R, self.__scanning_vectors) elif self.__estimator == "Capon": estimate = directionEstimation.DOA_Capon(R, self.__scanning_vectors) elif self.__estimator == "MEM": estimate = directionEstimation.DOA_MEM(R, self.__scanning_vectors, column_select=0) logging.warning( "Column select is not yet implemented. Set to default (0)") elif self.__estimator == "MUSIC": raise NotImplementedError elif self.__estimator == "MD-MUSIC": raise NotImplementedError return estimate
def DOA_demo(self): self.logger.debug("-> Running simulation <-") soi_theta = self.horizontalSlider_source_DOA.value() M = self.spinBox_noa.value() # Number of antenna elements N = 2**self.spinBox_sample_size.value() r = self.doubleSpinBox_UCA_r.value() d = self.doubleSpinBox_ULA_d.value() K = 1 + self.spinBox_multipath_components.value() alphas = [1.0] thetas = [soi_theta] phases = [0] try: multipath_alphas_str= self.lineEdit_multipath_amplitudes.text().split(',') if self.checkBox_multipath_random_angles.isChecked(): multipath_angles_str = "" for k in range(K-1): theta_rnd=np.random.uniform(0,360) multipath_angles_str += "{:3.1f},".format(theta_rnd) if self.checkBox_multipath_random_phases.isChecked(): multipath_phases_str = "" for k in range(K-1): phase_rnd=np.random.uniform(0,360) multipath_phases_str += "{:3.1f},".format(phase_rnd) self.lineEdit_multipath_phases.setText(multipath_phases_str[:len(multipath_phases_str)-1]) multipath_angles_str= self.lineEdit_multipath_angles.text().split(',') multipath_phases_str= self.lineEdit_multipath_phases.text().split(',') # Add multipath parameters for k in range(K-1): alphas.append(float(multipath_alphas_str[k])) thetas.append(float(multipath_angles_str[k])) phases.append(float(multipath_phases_str[k])) logging.debug("k: {:d}, alpha:{:f} phi:{:f} theta:{:f}".format(k,alphas[k+1],phases[k+1], thetas[k+1])) self.label_status.setText("<span style=\" font-size:8pt; font-weight:600; color:#01df01;\" >Running simulation</span>") except: K=1 alphas = [1.0] phases = [0] thetas = [soi_theta] self.label_status.setText("<span style=\" font-size:8pt; font-weight:600; color:#ff0000;\" >Improper multipath parameters</span>") alphas = 10**(np.array(alphas)/10) * np.exp(1j*np.deg2rad(np.array(phases))) noise_pow = 10**(-1*self.spinBox_snr_dB.value()/10) # Generate the signal of interest soi = np.random.normal(0,1,N) +1j* np.random.normal(0,1,N) # Generate multichannel uncorrelated noise noise = np.random.normal(0, np.sqrt(noise_pow), (M,N) ) +1j* np.random.normal(0, np.sqrt(noise_pow), (M,N) ) """ SNR debug display pn = np.average(np.abs(noise**2)) ps = np.average(np.abs(soi**2)) logging.info("SNR: {:.2f}".format(10*np.log10(ps/pn))) """ self.axes_DOA.clear() legend=[] if self.checkBox_en_UCA.checkState(): #---------------- U C A------------------- A = np.zeros((M, K), dtype=complex) for k in range(K): A[:,k] = np.exp(1j*2*np.pi*r*np.cos(np.radians(thetas[k]-np.arange(0,M,1)*(360)/M))) # UCA soi_matrix = (np.outer( soi, np.inner(A, alphas))).T # Create received signal rec_signal = soi_matrix + noise # Calulcate cross-correlation matrix R = de.corr_matrix_estimate(rec_signal.T, imp="fast") #R = forward_backward_avg(R) # Generate array alignment vector array_alignment = np.arange(0, M, 1) * d scanning_vectors = de.gen_uca_scanning_vectors(M, r, self.thetas) # DOA estimation alias_highlight = False # Track thaht aliase regions are already shown if self.checkBox_en_Bartlett.checkState(): Bartlett = de.DOA_Bartlett(R, scanning_vectors) de.DOA_plot(Bartlett, self.thetas, log_scale_min = -50, axes=self.axes_DOA) legend.append("UCA - Bartlett") self.label_Bartlett_UCA_res.setText("{:.1f}".format(np.argmax(Bartlett))) else: self.label_Bartlett_UCA_res.setText("-") if self.checkBox_en_Capon.checkState(): Capon = de.DOA_Capon(R, scanning_vectors) de.DOA_plot(Capon, self.thetas, log_scale_min = -50, axes=self.axes_DOA) legend.append("UCA - Capon") self.label_Capon_UCA_res.setText("{:.1f}".format(np.argmax(Capon))) else: self.label_Capon_UCA_res.setText("-") if self.checkBox_en_MEM.checkState(): MEM = de.DOA_MEM(R, scanning_vectors, column_select = 0) de.DOA_plot(MEM, self.thetas, log_scale_min = -50, axes=self.axes_DOA) legend.append("MEM") self.label_MEM_UCA_res.setText("{:.1f}".format(np.argmax(MEM))) else: self.label_MEM_UCA_res.setText("-") if self.checkBox_en_MUSIC.checkState(): MUSIC = de.DOA_MUSIC(R, scanning_vectors, signal_dimension = 1) de.DOA_plot(MUSIC, self.thetas, log_scale_min = -50, axes=self.axes_DOA) legend.append("MUSIC") self.label_MUSIC_UCA_res.setText("{:.1f}".format(np.argmax(MUSIC))) else: self.label_MUSIC_UCA_res.setText("-") if self.checkBox_en_ULA.checkState(): #---------------- U L A------------------- # Prepare Array-response matrix A = np.zeros((M, K), dtype=complex) for k in range(K): A[:,k] = np.exp(np.arange(0,M,1)*1j*2*np.pi*d*np.cos(np.deg2rad(thetas[k]))) soi_matrix = (np.outer( soi, np.inner(A, alphas))).T # Create received signal rec_signal = soi_matrix + noise ## R matrix calculation R = de.corr_matrix_estimate(rec_signal.T, imp="fast") if self.checkBox_en_FBavg.isChecked(): R = de.forward_backward_avg(R) # Generate array alignment vector array_alignment = np.arange(0, M, 1) * d scanning_vectors = de.gen_ula_scanning_vectors(array_alignment, self.thetas) # DOA estimation alias_highlight = True # Track thaht aliase regions are already shown if self.checkBox_en_Bartlett.checkState(): Bartlett = de.DOA_Bartlett(R, scanning_vectors) de.DOA_plot(Bartlett, self.thetas, log_scale_min = -50, axes=self.axes_DOA, alias_highlight=alias_highlight, d=d) legend.append("ULA - Bartlett") alias_highlight = False self.label_Bartlett_ULA_res.setText("{:.1f}".format(np.argmax(Bartlett[0:180]))) else: self.label_Bartlett_ULA_res.setText("-") if self.checkBox_en_Capon.checkState(): Capon = de.DOA_Capon(R, scanning_vectors) de.DOA_plot(Capon, self.thetas, log_scale_min = -50, axes=self.axes_DOA, alias_highlight=alias_highlight, d=d) legend.append("ULA - Capon") alias_highlight = False self.label_Capon_ULA_res.setText("{:.1f}".format(np.argmax(Capon[0:180]))) else: self.label_Capon_ULA_res.setText("-") if self.checkBox_en_MEM.checkState(): MEM = de.DOA_MEM(R, scanning_vectors, column_select = 0) de.DOA_plot(MEM, self.thetas, log_scale_min = -50, axes=self.axes_DOA, alias_highlight=alias_highlight, d=d) legend.append("ULA - MEM") alias_highlight = False self.label_MEM_ULA_res.setText("{:.1f}".format(np.argmax(MEM[0:180]))) else: self.label_MEM_ULA_res.setText("-") if self.checkBox_en_MUSIC.checkState(): MUSIC = de.DOA_MUSIC(R, scanning_vectors, signal_dimension = 1) de.DOA_plot(MUSIC, self.thetas, log_scale_min = -50, axes=self.axes_DOA, alias_highlight=alias_highlight, d=d) legend.append("ULA - MUSIC") alias_highlight = False self.label_MUSIC_ULA_res.setText("{:.1f}".format(np.argmax(MUSIC[0:180]))) else: self.label_MUSIC_ULA_res.setText("-") self.axes_DOA.legend(legend) self.canvas_DOA.draw()