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 __init__(self, array_type="ULA", estimator="MUSIC", **kwargs): if array_type not in self.VALID_ARRAY_TYPES: raise ValueError( "{} not a recognized array type. Must be one of ['ULA', 'UCA', 'Other']" .format(array_type)) def required_arg_check(required_args): for arg in required_args: if arg not in kwargs: raise ValueError( "Missing required argument: {}".format(arg)) required_arg_check([ 'incident_angles', ]) self.__incident_angles = kwargs['incident_angles'] if array_type == "ULA": required_args = ['array_alignment'] required_arg_check(required_args) self.__scanning_vectors = \ directionEstimation.gen_ula_scanning_vectors( kwargs['array_alignment'], kwargs['incident_angles'] ) elif array_type == "UCA": required_args = ['num_elems', 'radius'] required_arg_check(required_args) self.__scanning_vectors = \ directionEstimation.gen_uca_scanning_vectors( kwargs['num_elems'], kwargs['radius'], kwargs['incident_angles'] ) elif array_type == "Other": required_args = ['num_elems', 'x', 'y'] required_arg_check(required_args) self.__scanning_vectors = \ directionEstimation.gen_scanning_vectors( kwargs['num_elems'], kwargs['x'], kwargs['y'], kwargs['incident_angles'], ) if estimator not in self.VALID_ESTIMATORS: raise ValueError("Unrecognized estimator: {}".format(estimator)) self.__estimator = estimator
def run(self): # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx self.run_processing = True while self.run_processing: start_time = time.time() # Download samples #if(self.en_sync or self.en_spectrum): #time.sleep(0.25) # You can play with this value, but it may affect stability self.module_receiver.download_iq_samples() self.DOA_sample_size = self.module_receiver.iq_samples[0, :].size self.xcorr_sample_size = self.module_receiver.iq_samples[0, :].size self.xcorr = np.ones( (self.channel_number - 1, self.xcorr_sample_size * 2), dtype=np.complex64) # Check overdrive if self.module_receiver.overdrive_detect_flag: self.signal_overdrive.emit(1) else: self.signal_overdrive.emit(0) # Display spectrum if self.en_spectrum: self.spectrum[0, :] = np.fft.fftshift( np.fft.fftfreq(self.spectrum_sample_size, 1 / self.fs)) / 10**6 m = self.channel_number #self.spectrum[1:m+1,:] = 10*np.log10(np.fft.fftshift(np.abs(np.fft.fft(self.module_receiver.iq_samples[0:m, 0:self.spectrum_sample_size])))) for m in range(self.channel_number): self.spectrum[m + 1, :] = 10 * np.log10( np.fft.fftshift( np.abs( np.fft.fft(self.module_receiver.iq_samples[ m, 0:self.spectrum_sample_size])))) self.signal_spectrum_ready.emit() # Synchronization if self.en_sync or self.timed_sync: #print("Sync graph enabled") self.sample_delay() self.signal_sync_ready.emit() # Sample offset compensation request if self.en_sample_offset_sync: self.module_receiver.set_sample_offsets(self.delay_log[:, -1]) self.en_sample_offset_sync = False # IQ calibration request if self.en_calib_iq: # IQ correction for m in range(self.channel_number): self.module_receiver.iq_corrections[m] *= np.size( self.module_receiver.iq_samples[0, :]) / (np.dot( self.module_receiver.iq_samples[m, :], self.module_receiver.iq_samples[0, :].conj())) c = np.sqrt( np.sum(np.abs(self.module_receiver.iq_corrections)**2)) self.module_receiver.iq_corrections = np.divide( self.module_receiver.iq_corrections, c) #print("Corrections: ",self.module_receiver.iq_corrections) self.en_calib_iq = False if self.en_calib_DOA_90: #TODO: Experimental only for UCA, implement this properly! # This calibration is currently done for 0 deg not 90 x = self.DOA_inter_elem_space * np.cos( 2 * np.pi / 4 * np.arange(4)) y = self.DOA_inter_elem_space * np.sin( -2 * np.pi / 4 * np.arange(4)) # For this specific array only ref_vector = de.gen_scanning_vectors(4, x, y, np.zeros(1))[:, 0] #ref_vector = np.exp(1j*2*np.pi*0.5*np.cos(np.radians(0-np.arange(self.channel_number)*(360)/self.channel_number))) # UCA N = np.size(self.module_receiver.iq_samples[0, :]) for m in range(self.channel_number): self.module_receiver.iq_corrections[ m] *= ref_vector[m] * N / (np.dot( self.module_receiver.iq_samples[m, :], self.module_receiver.iq_samples[0, :].conj())) #print("Corrections: ",self.module_receiver.iq_corrections) self.en_calib_DOA_90 = False # Direction of Arrival estimation if self.en_DOA_estimation: # Get FFT for squelch self.spectrum[1, :] = 10 * np.log10( np.fft.fftshift( np.abs( np.fft.fft(self.module_receiver.iq_samples[ 0, 0:self.spectrum_sample_size])))) self.estimate_DOA() self.signal_DOA_ready.emit() # Passive Radar processing if self.en_PR_processing: # self.module_receiver.channel_number = 2 self.PR_processing() self.signal_PR_ready.emit() # else: # self.module_receiver.channel_number = 4 # Record IQ samples if self.en_record: np.save('hydra_samples.npy', self.module_receiver.iq_samples) # Code to maintain sync '''if self.timed_sync and not self.en_sync: if not self.noise_checked: self.module_receiver.switch_noise_source(0) self.timed_sync = False self.en_sample_offset_sync=True self.runningSync = 0 resync_on = True if(self.resync_time < 10): resync_on = False if(((start_time - self.lastTime) > self.resync_time) and not self.en_sync and resync_on): self.lastTime = start_time self.module_receiver.switch_noise_source(1) time.sleep(0.1) self.runningSync = 1 self.timed_sync = True''' stop_time = time.time() self.signal_period.emit(stop_time - start_time)