def main(): code_1 = ca_code.generate(prn=1) | np.roll(ca_code.generate(prn=2), 100) code_2 = ca_code.generate(prn=1) # code_2 = np.roll(code_2, 100) # fftshift(ifft(fft(a,corrLength).*conj(fft(b,corrLength)))) q = 2 code_1 = sfft_aliasing.execute(code_1, q) code_2 = sfft_aliasing.execute(code_2, q) code_1_fft = fourier_transforms.fft(code_1) code_2_fft = fourier_transforms.fft(code_2) multiplied = code_1_fft * np.conj(code_2_fft) print multiplied.size params = Parameters( n=multiplied.size/2, k=1, B_k_location=2, B_k_estimation=2, estimation_loops=8, location_loops=5, loop_threshold=4, tolerance_location=1e-8, tolerance_estimation=1e-8 ) result = sfft_inverse.execute(params=params, x=multiplied) result = fourier_transforms.fftshift(result) result_actual = fourier_transforms.ifft(multiplied) result_actual = fourier_transforms.fftshift(result_actual) print 'sfft size', result.size print 'original size', result_actual.size fig = plt.figure() ax = fig.gca() ax.plot(np.linspace(-1, 1, result.size), np.abs(result)) ax.plot(np.linspace(-1, 1, result_actual.size), np.abs(result_actual)) plt.show()
def acquisition(x, settings, plot_graphs=False, plot_3d_graphs=False, performance_counter=PerformanceCounter()): # Calculate number of samples per spreading code (corresponding to 1ms of data) samples_per_code = int(round(settings['sampling_frequency'] * settings['code_length'] / settings['code_frequency'])) print 'samples_per_code = %s' % repr(samples_per_code) # p = int(np.round(np.sqrt(np.log(samples_per_code)))) # print 'p = ', p p = settings['sfft_subsampling_factor'] n__samples_to_alias = samples_per_code * p x_1 = x[0:n__samples_to_alias] x_2 = x[n__samples_to_alias:n__samples_to_alias*2] x_1 = sfft_aliasing.execute(x_1, p) x_2 = sfft_aliasing.execute(x_2, p) # print n__samples_to_alias # print x_1.shape print 'x_1.shape = %s' % repr(x_1.shape) print 'x_2.shape = %s' % repr(x_2.shape) # Calculate sampling period sampling_period = 1.0 / settings['sampling_frequency'] print 'sampling_period = %s' % repr(sampling_period) # Generate phase points of the local carrier phases = np.arange(0, samples_per_code) * 2 * np.pi * sampling_period print 'phases(%s) = %s' % (repr(phases.shape), repr(phases)) # Calculate number of frequency bins depending on search frequency band and frequency step assert settings['acquisition_search_frequency_band'] % settings['acquisition_search_frequency_step'] == 0, \ 'acquisition_search_frequency_band should be divisible by acquisition_search_frequency_step' n_frequency_bins = int(settings['acquisition_search_frequency_band'] / settings['acquisition_search_frequency_step']) + 1 print 'n_frequency_bins = %s' % repr(n_frequency_bins) # Generate and store C/A lookup table ca_codes__time = ca_code.generate_table(settings) # SFFT ca_codes__freq = np.conjugate(fft(ca_codes__time)) print 'ca_codes__time(%s) = %s' % (repr(ca_codes__time.shape), repr(ca_codes__time)) # Allocate memory for the 2D search all_results = np.empty(shape=(n_frequency_bins, samples_per_code)) # Generate all frequency bins frequency_bins = ( settings['intermediate_frequency'] - \ (settings['acquisition_search_frequency_band'] / 2) + \ settings['acquisition_search_frequency_step'] * np.arange(n_frequency_bins) ).astype(int) print 'frequency_bins(%s) = %s' % (repr(frequency_bins.shape), repr(frequency_bins)) # Allocate memory for output dictionary satellites_to_search__shape = settings['satellites_to_search'].shape output = { 'frequency_shifts': np.zeros(satellites_to_search__shape), 'code_shifts': np.zeros(satellites_to_search__shape), 'peak_ratios': np.zeros(satellites_to_search__shape), 'found': np.zeros(satellites_to_search__shape, dtype=np.bool), } for idx, prn in enumerate(settings['satellites_to_search']): print '* searching PRN = %s' % (repr(prn),) # # Scan all Doppler shifts # for freq_bin_i in xrange(n_frequency_bins): # Generate local sine and cosine carriers carrier_sin = np.sin(frequency_bins[freq_bin_i] * phases) carrier_cos = np.cos(frequency_bins[freq_bin_i] * phases) # Demodulation I1 = carrier_sin * x_1 Q1 = carrier_cos * x_1 I2 = carrier_sin * x_2 Q2 = carrier_cos * x_2 # Reconstruct baseband signal IQ1 = I1 + 1j*Q1 IQ2 = I2 + 1j*Q2 # if settings['use_sfft']: # IQ1 = sfft_aliasing.execute(IQ1, settings['sfft_subsampling_factor']) # IQ2 = sfft_aliasing.execute(IQ2, settings['sfft_subsampling_factor']) # performance_counter.increase(additions=IQ1.size * settings['sfft_subsampling_factor']) # performance_counter.increase(additions=IQ2.size * settings['sfft_subsampling_factor']) # Convert to frequency domain IQ1_freq = fft(IQ1) IQ2_freq = fft(IQ2) performance_counter.fft(IQ1.size) performance_counter.fft(IQ2.size) # Multiplication in the frequency domain corresponds to convolution in the time domain conv_code_IQ1 = IQ1_freq * ca_codes__freq[prn-1] conv_code_IQ2 = IQ2_freq * ca_codes__freq[prn-1] performance_counter.increase(multiplications=IQ1_freq.size) performance_counter.increase(multiplications=IQ2_freq.size) # IFFT to obtain correlation corr_result_1 = np.abs(ifft(conv_code_IQ1)) ** 2 corr_result_2 = np.abs(ifft(conv_code_IQ2)) ** 2 # assert all_results[freq_bin_i, :].shape == corr_result_1.shape == corr_result_2.shape if np.max(corr_result_1) > np.max(corr_result_2): all_results[freq_bin_i, :] = corr_result_1 else: all_results[freq_bin_i, :] = corr_result_2 # Get the peak location for every frequency bins peak_values = all_results.max(axis=1) assert all_results.max() in peak_values # Find the Doppler shift index frequency_shift_idx = peak_values.argmax() print 'frequency_shift_idx = %s' % repr(frequency_shift_idx) # Select the frequency bin that corresponds to this frequency shift index located_frequency_bin = all_results[frequency_shift_idx] # Find the code shift in the correct frequency bin code_shift = located_frequency_bin.argmax() output['code_shifts'][idx] = code_shift print 'code_shift = %s' % repr(code_shift) peak_value = all_results[frequency_shift_idx][code_shift] assert all_results.max() == peak_value print 'peak_value = %s' % repr(peak_value) if plot_3d_graphs: fig = plt.figure() doppler_shifts__khz = ( (settings['acquisition_search_frequency_step'] * np.arange(n_frequency_bins)) - (settings['acquisition_search_frequency_band'] / 2) ) / 1000 ax = fig.gca(projection='3d') surf = ax.plot_surface( X=np.arange(samples_per_code).reshape((1, -1)), Y=doppler_shifts__khz.reshape((-1, 1)), Z=all_results, rstride=1, cstride=1, cmap=matplotlib.cm.coolwarm, linewidth=0, antialiased=False, ) ax.set_xlabel('Code shift') ax.set_ylabel('Doppler shift (kHz)') ax.set_zlabel('Magnitude') # Calculate code phase range samples_per_code_chip = int(round(settings['sampling_frequency'] / settings['code_frequency'])) print 'samples_per_code_chip = %s' % repr(samples_per_code_chip) # # Get second largest peak value outside the chip where the maximum peak is located # # Calculate excluded range excluded_range_1 = code_shift - samples_per_code_chip excluded_range_2 = code_shift + samples_per_code_chip print 'excluded_range_1 = %s' % repr(excluded_range_1) print 'excluded_range_2 = %s' % repr(excluded_range_2) # Excluded range boundary correction if excluded_range_1 < 1: print 'excluded_range_1 < 1' code_phase_range = np.arange(excluded_range_2, samples_per_code + excluded_range_1) elif excluded_range_2 >= samples_per_code: print 'excluded_range_2 >= samples_per_code' code_phase_range = np.arange(excluded_range_2 - samples_per_code, excluded_range_1) else: code_phase_range = np.concatenate(( np.arange(0, excluded_range_1), np.arange(excluded_range_2, samples_per_code) )) assert code_shift not in code_phase_range print 'code_phase_range(%s) = %s' % (repr(code_phase_range.shape), repr(code_phase_range)) # Get second largest peak value second_peak_value = all_results[frequency_shift_idx, code_phase_range].max() print 'second_peak_value = %s' % repr(second_peak_value) # Calculate ratio between the largest peak value and the second largest peak value peak_ratio = peak_value / second_peak_value print 'peak_ratio = %s' % repr(peak_ratio) output['peak_ratios'][idx] = peak_ratio # # Thresholding # if peak_ratio > settings['acquisition_threshold']: output['found'][idx] = True print '-> %s FOUND' % repr(prn) else: output['found'][idx] = False print '-> %s NOT FOUND' % repr(prn) if plot_graphs: plt.figure() colors = ['r' if found else 'b' for found in output['found']] plt.bar(settings['satellites_to_search'], output['peak_ratios'], color=colors, align='center') plt.ylabel('Acquisition quality') plt.xlabel('PRN number') artist__not_acquired = plt.Rectangle((0, 0), 1, 1, fc='b') artist__acquired = plt.Rectangle((0, 0), 1, 1, fc='r') plt.legend(( artist__not_acquired, artist__acquired ), ( 'Not acquired', 'Acquired' )) plt.xlim(0, settings['satellites_total'] + 1) plt.grid() plt.tight_layout() return output, performance_counter
def acquisition(x, settings, plot_graphs=False, plot_3d_graphs=False, performance_counter=PerformanceCounter()): # Calculate number of samples per spreading code (corresponding to 1ms of data) samples_per_code = int(round(settings["sampling_frequency"] * settings["code_length"] / settings["code_frequency"])) print "samples_per_code = %s" % repr(samples_per_code) # SFFT aliased_samples_per_code = int(samples_per_code / settings["sfft_subsampling_factor"]) if settings["use_sfft"]: actual_samples_per_code = aliased_samples_per_code else: actual_samples_per_code = samples_per_code # Two consecutive 2ms reading # x_1 = x[(settings['code_offset']*samples_per_code):(settings['code_offset']*samples_per_code + samples_per_code)] # x_2 = x[(settings['code_offset']*samples_per_code + samples_per_code):(settings['code_offset']*samples_per_code + 2*samples_per_code)] x_1 = x[0:samples_per_code] x_2 = x[samples_per_code : 2 * samples_per_code] print "x_1.shape = %s" % repr(x_1.shape) print "x_2.shape = %s" % repr(x_2.shape) assert x_1.shape == x_2.shape # Calculate sampling period sampling_period = 1.0 / settings["sampling_frequency"] print "sampling_period = %s" % repr(sampling_period) # Generate phase points of the local carrier phases = np.arange(0, samples_per_code) * 2 * np.pi * sampling_period print "phases(%s) = %s" % (repr(phases.shape), repr(phases)) # Calculate number of frequency bins depending on search frequency band and frequency step assert ( settings["acquisition_search_frequency_band"] % settings["acquisition_search_frequency_step"] == 0 ), "acquisition_search_frequency_band should be divisible by acquisition_search_frequency_step" n_frequency_bins = ( int(settings["acquisition_search_frequency_band"] / settings["acquisition_search_frequency_step"]) + 1 ) print "n_frequency_bins = %s" % repr(n_frequency_bins) # Generate and store C/A lookup table ca_codes__time = ca_code.generate_table(settings) # SFFT if settings["use_sfft"]: aliased_ca_codes__time = np.empty(shape=(settings["satellites_total"], aliased_samples_per_code)) for i in xrange(ca_codes__time.shape[0]): aliased_ca_codes__time[i] = sfft_aliasing.execute(ca_codes__time[i], settings["sfft_subsampling_factor"]) ca_codes__time = aliased_ca_codes__time ca_codes__freq = np.conjugate(fft(ca_codes__time)) print "ca_codes__time(%s) = %s" % (repr(ca_codes__time.shape), repr(ca_codes__time)) # Allocate memory for the 2D search all_results = np.empty(shape=(n_frequency_bins, actual_samples_per_code)) # Generate all frequency bins frequency_bins = ( settings["intermediate_frequency"] - (settings["acquisition_search_frequency_band"] / 2) + settings["acquisition_search_frequency_step"] * np.arange(n_frequency_bins) ).astype(int) print "frequency_bins(%s) = %s" % (repr(frequency_bins.shape), repr(frequency_bins)) # Allocate memory for output dictionary satellites_to_search__shape = settings["satellites_to_search"].shape output = { "frequency_shifts": np.zeros(satellites_to_search__shape), "frequency_offsets": np.zeros(satellites_to_search__shape), "code_shifts": np.zeros(satellites_to_search__shape), "peak_ratios": np.zeros(satellites_to_search__shape), "found": np.zeros(satellites_to_search__shape, dtype=np.bool), } for idx, prn in enumerate(settings["satellites_to_search"]): print "* searching PRN = %s" % (repr(prn),) # # Scan all Doppler shifts # for freq_bin_i in xrange(n_frequency_bins): # Generate local sine and cosine carriers carrier_sin = np.sin(frequency_bins[freq_bin_i] * phases) carrier_cos = np.cos(frequency_bins[freq_bin_i] * phases) # Demodulation I1 = carrier_sin * x_1 Q1 = carrier_cos * x_1 I2 = carrier_sin * x_2 Q2 = carrier_cos * x_2 # Reconstruct baseband signal IQ1 = I1 + 1j * Q1 IQ2 = I2 + 1j * Q2 if settings["use_sfft"]: IQ1 = sfft_aliasing.execute(IQ1, settings["sfft_subsampling_factor"]) IQ2 = sfft_aliasing.execute(IQ2, settings["sfft_subsampling_factor"]) performance_counter.increase(additions=IQ1.size * settings["sfft_subsampling_factor"]) performance_counter.increase(additions=IQ2.size * settings["sfft_subsampling_factor"]) # Convert to frequency domain IQ1_freq = fft(IQ1) IQ2_freq = fft(IQ2) performance_counter.fft(IQ1.size) performance_counter.fft(IQ2.size) # Multiplication in the frequency domain corresponds to convolution in the time domain conv_code_IQ1 = IQ1_freq * ca_codes__freq[prn - 1] conv_code_IQ2 = IQ2_freq * ca_codes__freq[prn - 1] performance_counter.increase(multiplications=IQ1_freq.size) performance_counter.increase(multiplications=IQ2_freq.size) # IFFT to obtain correlation corr_result_1 = np.abs(ifft(conv_code_IQ1)) ** 2 corr_result_2 = np.abs(ifft(conv_code_IQ2)) ** 2 # assert all_results[freq_bin_i, :].shape == corr_result_1.shape == corr_result_2.shape if np.max(corr_result_1) > np.max(corr_result_2): all_results[freq_bin_i, :] = corr_result_1 else: all_results[freq_bin_i, :] = corr_result_2 # Get the peak location for every frequency bins peak_values = all_results.max(axis=1) assert all_results.max() in peak_values # Find the Doppler shift index frequency_shift_idx = peak_values.argmax() print "frequency_shift_idx = %s" % repr(frequency_shift_idx) # Select the frequency bin that corresponds to this frequency shift index located_frequency_bin = all_results[frequency_shift_idx] # Find the code shift in the correct frequency bin code_shift = located_frequency_bin.argmax() output["code_shifts"][idx] = code_shift print "code_shift = %s" % repr(code_shift) peak_value = all_results[frequency_shift_idx][code_shift] assert all_results.max() == peak_value print "peak_value = %s" % repr(peak_value) # Doppler shifts doppler_shifts__khz = (settings["acquisition_search_frequency_step"] * np.arange(n_frequency_bins)) - ( settings["acquisition_search_frequency_band"] / 2 ) output["frequency_shifts"][idx] = frequency_bins[frequency_shift_idx] output["frequency_offsets"][idx] = doppler_shifts__khz[frequency_shift_idx] if plot_3d_graphs: fig = plt.figure() ax = fig.gca(projection="3d") surf = ax.plot_surface( X=np.arange(actual_samples_per_code).reshape((1, -1)), Y=doppler_shifts__khz.reshape((-1, 1)) / 1000, Z=all_results, rstride=1, cstride=1, cmap=matplotlib.cm.coolwarm, linewidth=0, antialiased=False, ) ax.set_xlabel("Code shift") ax.set_ylabel("Doppler shift (kHz)") ax.set_zlabel("Magnitude") # Calculate code phase range samples_per_code_chip = int(round(settings["sampling_frequency"] / settings["code_frequency"])) # SFFT if settings["use_sfft"]: samples_per_code_chip = int(samples_per_code_chip / settings["sfft_subsampling_factor"]) print "samples_per_code_chip = %s" % repr(samples_per_code_chip) # # Get second largest peak value outside the chip where the maximum peak is located # # Calculate excluded range excluded_range_1 = code_shift - samples_per_code_chip excluded_range_2 = code_shift + samples_per_code_chip print "excluded_range_1 = %s" % repr(excluded_range_1) print "excluded_range_2 = %s" % repr(excluded_range_2) # Excluded range boundary correction if excluded_range_1 < 1: print "excluded_range_1 < 1" code_phase_range = np.arange(excluded_range_2, actual_samples_per_code + excluded_range_1) elif excluded_range_2 >= actual_samples_per_code: print "excluded_range_2 >= samples_per_code" code_phase_range = np.arange(excluded_range_2 - actual_samples_per_code, excluded_range_1) else: code_phase_range = np.concatenate( (np.arange(0, excluded_range_1), np.arange(excluded_range_2, actual_samples_per_code)) ) assert code_shift not in code_phase_range print "code_phase_range(%s) = %s" % (repr(code_phase_range.shape), repr(code_phase_range)) # Get second largest peak value second_peak_value = all_results[frequency_shift_idx, code_phase_range].max() print "second_peak_value = %s" % repr(second_peak_value) # Calculate ratio between the largest peak value and the second largest peak value peak_ratio = peak_value / second_peak_value print "peak_ratio = %s" % repr(peak_ratio) output["peak_ratios"][idx] = peak_ratio # # Thresholding # if peak_ratio > settings["acquisition_threshold"]: output["found"][idx] = True print "-> %s FOUND" % repr(prn) else: output["found"][idx] = False print "-> %s NOT FOUND" % repr(prn) if plot_graphs: plt.figure() colors = ["r" if found else "b" for found in output["found"]] plt.bar(settings["satellites_to_search"], output["peak_ratios"], color=colors, align="center") plt.ylabel("Acquisition quality") plt.xlabel("PRN number") artist__not_acquired = plt.Rectangle((0, 0), 1, 1, fc="b") artist__acquired = plt.Rectangle((0, 0), 1, 1, fc="r") plt.legend((artist__not_acquired, artist__acquired), ("Signal not acquired", "Signal acquired")) plt.xlim(0, settings["satellites_total"] + 1) plt.tight_layout() return output, performance_counter
def acquisition(x, settings, plot_graphs=False, plot_3d_graphs=False, performance_counter=PerformanceCounter()): # Calculate number of samples per spreading code (corresponding to 1ms of data) samples_per_code = int( round(settings['sampling_frequency'] * settings['code_length'] / settings['code_frequency'])) # print 'samples_per_code = %s' % repr(samples_per_code) # SFFT aliased_samples_per_code = int(samples_per_code / settings['sfft_subsampling_factor']) if settings['use_sfft']: actual_samples_per_code = aliased_samples_per_code else: actual_samples_per_code = samples_per_code # Calculate sampling period sampling_period = 1.0 / settings['sampling_frequency'] # print 'sampling_period = %s' % repr(sampling_period) # Generate phase points of the local carrier phases = np.arange(0, samples_per_code) * 2 * np.pi * sampling_period # print 'phases(%s) = %s' % (repr(phases.shape), repr(phases)) # Calculate number of frequency bins depending on search frequency band and frequency step assert settings['acquisition_search_frequency_band'] % settings['acquisition_search_frequency_step'] == 0, \ 'acquisition_search_frequency_band should be divisible by acquisition_search_frequency_step' n_frequency_bins = int(settings['acquisition_search_frequency_band'] / settings['acquisition_search_frequency_step']) + 1 # print 'n_frequency_bins = %s' % repr(n_frequency_bins) # Generate and store C/A lookup table ca_codes__time = ca_code.generate_table(settings) # SFFT if settings['use_sfft']: aliased_ca_codes__time = np.empty(shape=(settings['satellites_total'], aliased_samples_per_code)) for i in xrange(ca_codes__time.shape[0]): aliased_ca_codes__time[i] = sfft_aliasing.execute( ca_codes__time[i], settings['sfft_subsampling_factor']) ca_codes__time = aliased_ca_codes__time ca_codes__freq = np.conjugate(fft(ca_codes__time)) # print 'ca_codes__time(%s) = %s' % (repr(ca_codes__time.shape), repr(ca_codes__time)) # Allocate memory for the 2D search all_results = np.empty(shape=(n_frequency_bins, actual_samples_per_code)) # Generate all frequency bins frequency_bins = ( settings['intermediate_frequency'] - \ (settings['acquisition_search_frequency_band'] / 2) + \ settings['acquisition_search_frequency_step'] * np.arange(n_frequency_bins) ).astype(int) # print 'frequency_bins(%s) = %s' % (repr(frequency_bins.shape), repr(frequency_bins)) # Allocate memory for output dictionary satellites_to_search__shape = settings['satellites_to_search'].shape output = { 'frequency_shifts': np.zeros(satellites_to_search__shape, dtype=int), 'code_shifts': np.zeros(satellites_to_search__shape, dtype=int), 'peak_ratios': np.zeros(satellites_to_search__shape), 'found': np.zeros(satellites_to_search__shape, dtype=np.bool), } correct_runs = 0 run_number = 0 for idx, prn in enumerate(settings['satellites_to_search']): print '* searching PRN = %s' % (repr(prn), ) # correct_runs = 0 # run_number = 0 summed_corr_result_magnitudes = np.zeros(actual_samples_per_code) counter = 10 while counter > 0: counter -= 1 # Two consecutive 2ms reading # x_1 = x[(settings['code_offset']*samples_per_code):(settings['code_offset']*samples_per_code + samples_per_code)] # x_2 = x[(settings['code_offset']*samples_per_code + samples_per_code):(settings['code_offset']*samples_per_code + 2*samples_per_code)] x_1 = x[run_number * samples_per_code:(run_number * samples_per_code + samples_per_code)] # print 'x_1.shape = %s' % repr(x_1.shape) run_number += 1 print 'run_number = %s' % repr(run_number) # # Scan all Doppler shifts # for freq_bin_i in xrange(n_frequency_bins): # Generate local sine and cosine carriers carrier_sin = np.sin(frequency_bins[freq_bin_i] * phases) carrier_cos = np.cos(frequency_bins[freq_bin_i] * phases) # Demodulation I1 = carrier_sin * x_1 Q1 = carrier_cos * x_1 # I2 = carrier_sin * x_2 # Q2 = carrier_cos * x_2 # Reconstruct baseband signal IQ1 = I1 + 1j * Q1 # IQ2 = I2 + 1j*Q2 if settings['use_sfft']: IQ1 = sfft_aliasing.execute( IQ1, settings['sfft_subsampling_factor']) # IQ2 = sfft_aliasing.execute(IQ2, settings['sfft_subsampling_factor']) performance_counter.increase( additions=IQ1.size * settings['sfft_subsampling_factor']) # performance_counter.increase(additions=IQ2.size * settings['sfft_subsampling_factor']) # Convert to frequency domain IQ1_freq = fft(IQ1) # IQ2_freq = fft(IQ2) performance_counter.fft(IQ1.size) # performance_counter.fft(IQ2.size) # Multiplication in the frequency domain corresponds to convolution in the time domain conv_code_IQ1 = IQ1_freq * ca_codes__freq[prn - 1] # conv_code_IQ2 = IQ2_freq * ca_codes__freq[prn-1] performance_counter.increase(multiplications=IQ1_freq.size) # performance_counter.increase(multiplications=IQ2_freq.size) # IFFT to obtain correlation corr_result = np.abs(ifft(conv_code_IQ1))**2 # corr_result_2 = np.abs(ifft(conv_code_IQ2)) ** 2 # assert all_results[freq_bin_i, :].shape == corr_result_1.shape == corr_result_2.shape # if np.max(corr_result_1) > np.max(corr_result_2): all_results[freq_bin_i, :] = corr_result # else: # all_results[freq_bin_i, :] = corr_result_2 # Get the peak location for every frequency bins peak_values = all_results.max(axis=1) assert all_results.max() in peak_values # Find the Doppler shift index frequency_shift_idx = peak_values.argmax() # print 'frequency_shift_idx = %s' % repr(frequency_shift_idx) # Select the frequency bin that corresponds to this frequency shift index located_frequency_bin = all_results[frequency_shift_idx] # Find the code shift in the correct frequency bin code_shift = located_frequency_bin.argmax() # output['code_shifts'][idx] = code_shift # print 'code_shift = %s' % repr(code_shift) peak_value = located_frequency_bin[code_shift] assert all_results.max() == peak_value # print 'peak_value = %s' % repr(peak_value) print np.abs(code_shift - settings['actual_satellite_shifts'][idx]) if np.abs(code_shift - settings['actual_satellite_shifts'][idx]) < 40: correct_runs += 1 print 'CORRECT RUN!' # # New Threshold calculation # summed_corr_result_magnitudes += np.abs(located_frequency_bin) # # print 'here', summed_corr_result_magnitudes.argmax() # snr = get_snr(summed_corr_result_magnitudes) # print 'snr', snr # if snr > settings['snr_threshold']: # output['found'][idx] = True # print 'summed_corr_result_magnitudes', summed_corr_result_magnitudes # output['code_shifts'][idx] = summed_corr_result_magnitudes.argmax() # break # # if plot_3d_graphs: # fig = plt.figure() # doppler_shifts__khz = ( # (settings['acquisition_search_frequency_step'] * np.arange(n_frequency_bins)) - # (settings['acquisition_search_frequency_band'] / 2) # ) / 1000 # # ax = fig.gca(projection='3d') # surf = ax.plot_surface( # X=np.arange(actual_samples_per_code).reshape((1, -1)), # Y=doppler_shifts__khz.reshape((-1, 1)), # Z=all_results, # rstride=1, # cstride=1, # cmap=matplotlib.cm.coolwarm, # linewidth=0, # antialiased=False, # ) # ax.set_xlabel('Code shift') # ax.set_ylabel('Doppler shift (kHz)') # # # Calculate code phase range # samples_per_code_chip = int(round(settings['sampling_frequency'] / settings['code_frequency'])) # # # SFFT # if settings['use_sfft']: # samples_per_code_chip = int(samples_per_code_chip / settings['sfft_subsampling_factor']) # # print 'samples_per_code_chip = %s' % repr(samples_per_code_chip) # # # # # Get second largest peak value outside the chip where the maximum peak is located # # # # # Calculate excluded range # excluded_range_1 = code_shift - samples_per_code_chip # excluded_range_2 = code_shift + samples_per_code_chip # print 'excluded_range_1 = %s' % repr(excluded_range_1) # print 'excluded_range_2 = %s' % repr(excluded_range_2) # # # Excluded range boundary correction # if excluded_range_1 < 1: # print 'excluded_range_1 < 1' # code_phase_range = np.arange(excluded_range_2, actual_samples_per_code + excluded_range_1) # elif excluded_range_2 >= actual_samples_per_code: # print 'excluded_range_2 >= samples_per_code' # code_phase_range = np.arange(excluded_range_2 - actual_samples_per_code, excluded_range_1) # else: # code_phase_range = np.concatenate(( # np.arange(0, excluded_range_1), # np.arange(excluded_range_2, actual_samples_per_code) # )) # # assert code_shift not in code_phase_range # print 'code_phase_range(%s) = %s' % (repr(code_phase_range.shape), repr(code_phase_range)) # # # Get second largest peak value # second_peak_value = all_results[frequency_shift_idx, code_phase_range].max() # print 'second_peak_value = %s' % repr(second_peak_value) # # # Calculate ratio between the largest peak value and the second largest peak value # peak_ratio = peak_value / second_peak_value # print 'peak_ratio = %s' % repr(peak_ratio) # output['peak_ratios'][idx] = peak_ratio # # # # # Thresholding # # # # if peak_ratio > settings['acquisition_threshold']: # output['found'][idx] = True # print '-> %s FOUND' % repr(prn) # else: # output['found'][idx] = False # print '-> %s NOT FOUND' % repr(prn) if plot_graphs: plt.figure() colors = ['r' if found else 'b' for found in output['found']] plt.bar(settings['satellites_to_search'], output['peak_ratios'], color=colors, align='center') plt.ylabel('Acquisition quality') plt.xlabel('PRN number') artist__not_acquired = plt.Rectangle((0, 0), 1, 1, fc='b') artist__acquired = plt.Rectangle((0, 0), 1, 1, fc='r') plt.legend((artist__not_acquired, artist__acquired), ('Signal not acquired', 'Signal acquired')) plt.xlim(0, settings['satellites_total'] + 1) plt.tight_layout() if run_number == 0: output['success_probability'] = 0 else: output['success_probability'] = correct_runs / run_number print output['success_probability'] return output, performance_counter
def main(): # (a) Input code = ca_code.generate(prn=1, repeats=10) # rx = np.roll(ca_code.generate(prn=1, repeats=10), -10230/6*1) | ca_code.generate(prn=2, repeats=10) rx = np.roll(ca_code.generate(prn=1, repeats=10), 1000) | ca_code.generate(prn=2, repeats=10) noise_std = 1 noise = np.random.normal( scale=noise_std, size=code.size, ) rx = np.add(rx, noise) # (b) Aliasing q = 2 code_aliased = sfft_aliasing.execute(code, q) rx_aliased = sfft_aliasing.execute(rx, q) # (c) FFT code_f = fft(code_aliased) rx_f = fft(rx_aliased) # (d) Multiply code_rx_f = np.multiply(np.conjugate(code_f), rx_f) # (e) IFFT code_rx = np.real(ifft(code_rx_f)) print 'arg max is', np.argmax(code_rx) plt.figure('Local C/A code') plt.step(np.arange(code.size), code) plt.xlim(0, code.size-1) plt.title('Local C/A code') plt.xlabel('Time') plt.setp(plt.gca().get_xticklabels(), visible=False) plt.setp(plt.gca().get_yticklabels(), visible=False) plt.figure('Received signal') plt.plot(rx) plt.xlim(0, code.size-1) plt.title('Received signal') plt.xlabel('Time') plt.setp(plt.gca().get_xticklabels(), visible=False) plt.setp(plt.gca().get_yticklabels(), visible=False) plt.figure('Aliased Local C/A code') plt.step(np.arange(code_aliased.size), code_aliased) plt.xlim(0, code_aliased.size-1) plt.title('Local C/A code (Aliased)') plt.xlabel('Time') plt.setp(plt.gca().get_xticklabels(), visible=False) plt.setp(plt.gca().get_yticklabels(), visible=False) plt.figure('Aliased Received signal') plt.plot(rx_aliased) plt.xlim(0, rx_aliased.size-1) plt.title('Received signal (Aliased)') plt.xlabel('Time') plt.setp(plt.gca().get_xticklabels(), visible=False) plt.setp(plt.gca().get_yticklabels(), visible=False) plt.figure('FFT of Local CA code') plt.plot(np.abs(fftshift(code_f))) plt.title('FFT of Local C/A code') plt.xlabel('Frequency') plt.xlim(1000, 4000) plt.ylim(0, 500) plt.setp(plt.gca().get_xticklabels(), visible=False) plt.setp(plt.gca().get_yticklabels(), visible=False) plt.figure('FFT of Received signal') plt.plot(np.abs(fftshift(rx_f))) plt.title('FFT of Received signal') plt.xlabel('Frequency') plt.xlim(1000, 4000) plt.ylim(0, 500) plt.setp(plt.gca().get_xticklabels(), visible=False) plt.setp(plt.gca().get_yticklabels(), visible=False) plt.figure('Multiply') plt.plot(np.abs(fftshift(code_rx_f))) plt.title('Multiply') plt.xlabel('Frequency') plt.xlim(1500, 3500) plt.ylim(0, 100000) plt.setp(plt.gca().get_xticklabels(), visible=False) plt.setp(plt.gca().get_yticklabels(), visible=False) plt.figure('IFFT') plt.plot(code_rx) plt.title('IFFT') plt.xlim(0, code_rx.size-1) plt.setp(plt.gca().get_xticklabels(), visible=False) plt.setp(plt.gca().get_yticklabels(), visible=False) plt.show()
def acquisition(x, settings, plot_graphs=False, plot_3d_graphs=False, performance_counter=PerformanceCounter()): # Calculate number of samples per spreading code (corresponding to 1ms of data) samples_per_code = int( round(settings['sampling_frequency'] * settings['code_length'] / settings['code_frequency'])) print 'samples_per_code = %s' % repr(samples_per_code) assert samples_per_code % settings['sfft_subsampling_factor'] == 0 aliased_samples_per_code = int(samples_per_code / settings['sfft_subsampling_factor']) # Calculate sampling period sampling_period = 1.0 / settings['sampling_frequency'] print 'sampling_period = %s' % repr(sampling_period) # Generate phase points of the local carrier phases = np.arange(0, aliased_samples_per_code) * 2 * np.pi * sampling_period print 'phases(%s) = %s' % (repr(phases.shape), repr(phases)) # Calculate number of frequency bins depending on search frequency band and frequency step assert settings['acquisition_search_frequency_band'] % settings['acquisition_search_frequency_step'] == 0, \ 'acquisition_search_frequency_band should be divisible by acquisition_search_frequency_step' n_frequency_bins = int(settings['acquisition_search_frequency_band'] / settings['acquisition_search_frequency_step']) + 1 print 'n_frequency_bins = %s' % repr(n_frequency_bins) # Generate and store C/A lookup table ca_codes__time = ca_code.generate_table(settings) # SFFT # ca_codes__freq = np.conjugate(fft(ca_codes__time)) # print 'ca_codes__time(%s) = %s' % (repr(ca_codes__time.shape), repr(ca_codes__time)) # Allocate memory for the 2D search all_results = np.empty(shape=(n_frequency_bins, aliased_samples_per_code)) # Generate all frequency bins frequency_bins = ( settings['intermediate_frequency'] - \ (settings['acquisition_search_frequency_band'] / 2) + \ settings['acquisition_search_frequency_step'] * np.arange(n_frequency_bins) ).astype(int) print 'frequency_bins(%s) = %s' % (repr( frequency_bins.shape), repr(frequency_bins)) # Allocate memory for output dictionary satellites_to_search__shape = settings['satellites_to_search'].shape output = { 'frequency_shifts': np.zeros(satellites_to_search__shape), 'code_shifts': np.zeros(satellites_to_search__shape), 'peak_ratios': np.zeros(satellites_to_search__shape), 'found': np.zeros(satellites_to_search__shape, dtype=np.bool), } for idx, prn in enumerate(settings['satellites_to_search']): print '* searching PRN = %s' % (repr(prn), ) result_summation = np.zeros(aliased_samples_per_code) for sum_idx in xrange(settings['sfft_sum_results']): # Get data x_1 = x[sum_idx * samples_per_code:sum_idx * samples_per_code + samples_per_code] assert x_1.size == samples_per_code x_1 = sfft_aliasing.execute(x_1, settings['sfft_subsampling_factor']) assert x_1.size == aliased_samples_per_code x_2 = x[sum_idx * samples_per_code + samples_per_code:sum_idx * samples_per_code + 2 * samples_per_code] assert x_2.size == samples_per_code x_2 = sfft_aliasing.execute(x_2, settings['sfft_subsampling_factor']) assert x_2.size == aliased_samples_per_code # # Scan all Doppler shifts # for freq_bin_i in xrange(n_frequency_bins): # Generate local sine and cosine carriers carrier_sin = np.sin(frequency_bins[freq_bin_i] * phases) carrier_cos = np.cos(frequency_bins[freq_bin_i] * phases) # Demodulation I1 = carrier_sin * x_1 Q1 = carrier_cos * x_1 I2 = carrier_sin * x_2 Q2 = carrier_cos * x_2 # Reconstruct baseband signal IQ1 = I1 + 1j * Q1 IQ2 = I2 + 1j * Q2 # if settings['use_sfft']: # IQ1 = sfft_aliasing.execute(IQ1, settings['sfft_subsampling_factor']) # IQ2 = sfft_aliasing.execute(IQ2, settings['sfft_subsampling_factor']) # performance_counter.increase(additions=IQ1.size * settings['sfft_subsampling_factor']) # performance_counter.increase(additions=IQ2.size * settings['sfft_subsampling_factor']) # Convert to frequency domain IQ1_freq = fft(IQ1) IQ2_freq = fft(IQ2) performance_counter.fft(IQ1.size) performance_counter.fft(IQ2.size) # Multiplication in the frequency domain corresponds to convolution in the time domain aliased_ca_code__time = sfft_aliasing.execute( ca_codes__time[prn - 1], settings['sfft_subsampling_factor']) assert aliased_ca_code__time.size == aliased_samples_per_code aliased_ca_code__freq = fft(aliased_ca_code__time) conv_code_IQ1 = IQ1_freq * aliased_ca_code__freq conv_code_IQ2 = IQ2_freq * aliased_ca_code__freq performance_counter.increase(multiplications=IQ1_freq.size) performance_counter.increase(multiplications=IQ2_freq.size) # IFFT to obtain correlation corr_result_1 = np.abs(ifft(conv_code_IQ1))**2 corr_result_2 = np.abs(ifft(conv_code_IQ2))**2 # assert all_results[freq_bin_i, :].shape == corr_result_1.shape == corr_result_2.shape if np.max(corr_result_1) > np.max(corr_result_2): all_results[freq_bin_i, :] = corr_result_1 else: all_results[freq_bin_i, :] = corr_result_2 # Get the peak location for every frequency bins peak_values = all_results.max(axis=1) assert all_results.max() in peak_values # Find the Doppler shift index frequency_shift_idx = peak_values.argmax() print 'frequency_shift_idx = %s' % repr(frequency_shift_idx) # Select the frequency bin that corresponds to this frequency shift index located_frequency_bin = all_results[frequency_shift_idx] result_summation += located_frequency_bin plt.figure() plt.plot(result_summation / result_summation.max()) plt.ylabel('Normalised magnitude') plt.xlabel('Code shift (chips)') plt.title('Summing %d results' % settings['sfft_sum_results']) plt.show() exit() # Find the code shift in the correct frequency bin code_shift = result_summation.argmax() output['code_shifts'][idx] = code_shift print 'code_shift = %s' % repr(code_shift) peak_value = result_summation[code_shift] assert result_summation.max() == peak_value print 'peak_value = %s' % repr(peak_value) if plot_3d_graphs: fig = plt.figure() doppler_shifts__khz = ( (settings['acquisition_search_frequency_step'] * np.arange(n_frequency_bins)) - (settings['acquisition_search_frequency_band'] / 2)) / 1000 ax = fig.gca(projection='3d') surf = ax.plot_surface( X=np.arange(samples_per_code).reshape((1, -1)), Y=doppler_shifts__khz.reshape((-1, 1)), Z=all_results, rstride=1, cstride=1, cmap=matplotlib.cm.coolwarm, linewidth=0, antialiased=False, ) ax.set_xlabel('Code shift') ax.set_ylabel('Doppler shift (kHz)') # Calculate code phase range samples_per_code_chip = int( round(settings['sampling_frequency'] / settings['code_frequency'])) print 'samples_per_code_chip = %s' % repr(samples_per_code_chip) # # Get second largest peak value outside the chip where the maximum peak is located # # Calculate excluded range excluded_range_1 = code_shift - samples_per_code_chip excluded_range_2 = code_shift + samples_per_code_chip print 'excluded_range_1 = %s' % repr(excluded_range_1) print 'excluded_range_2 = %s' % repr(excluded_range_2) # Excluded range boundary correction if excluded_range_1 < 1: print 'excluded_range_1 < 1' code_phase_range = np.arange( excluded_range_2, aliased_samples_per_code + excluded_range_1) elif excluded_range_2 >= aliased_samples_per_code: print 'excluded_range_2 >= samples_per_code' code_phase_range = np.arange( excluded_range_2 - aliased_samples_per_code, excluded_range_1) else: code_phase_range = np.concatenate( (np.arange(0, excluded_range_1), np.arange(excluded_range_2, aliased_samples_per_code))) assert code_shift not in code_phase_range print 'code_phase_range(%s) = %s' % (repr( code_phase_range.shape), repr(code_phase_range)) # Get second largest peak value second_peak_value = all_results[frequency_shift_idx, code_phase_range].max() print 'second_peak_value = %s' % repr(second_peak_value) # Calculate ratio between the largest peak value and the second largest peak value peak_ratio = peak_value / second_peak_value print 'peak_ratio = %s' % repr(peak_ratio) output['peak_ratios'][idx] = peak_ratio # # Thresholding # if peak_ratio > settings['acquisition_threshold']: output['found'][idx] = True print '-> %s FOUND' % repr(prn) else: output['found'][idx] = False print '-> %s NOT FOUND' % repr(prn) if plot_graphs: plt.figure() colors = ['r' if found else 'b' for found in output['found']] plt.bar(settings['satellites_to_search'], output['peak_ratios'], color=colors, align='center') plt.ylabel('Acquisition quality') plt.xlabel('PRN number') artist__not_acquired = plt.Rectangle((0, 0), 1, 1, fc='b') artist__acquired = plt.Rectangle((0, 0), 1, 1, fc='r') plt.legend((artist__not_acquired, artist__acquired), ('Not acquired', 'Acquired')) plt.xlim(0, settings['satellites_total'] + 1) plt.grid() plt.tight_layout() return output, performance_counter
def single_acquisition(x, prn, settings, plot_3d_graphs=False, performance_counter=PerformanceCounter()): # Calculate number of samples per spreading code (corresponding to 1ms of data) samples_per_code = int( round(settings['sampling_frequency'] * settings['code_length'] / settings['code_frequency'])) print 'samples_per_code = %s' % repr(samples_per_code) # SFFT aliased_samples_per_code = int(samples_per_code / settings['sfft_subsampling_factor']) if settings['use_sfft']: actual_samples_per_code = aliased_samples_per_code else: actual_samples_per_code = samples_per_code # Two consecutive 2ms reading x_1 = x[(settings['code_offset'] * samples_per_code):((settings['code_offset'] * samples_per_code) + samples_per_code)] x_2 = x[(settings['code_offset'] * samples_per_code + samples_per_code):(settings['code_offset'] * samples_per_code + 2 * samples_per_code)] if x_1.size != samples_per_code: return False, performance_counter print 'x_1.shape = %s' % repr(x_1.shape) print 'x_2.shape = %s' % repr(x_2.shape) # Calculate sampling period sampling_period = 1.0 / settings['sampling_frequency'] print 'sampling_period = %s' % repr(sampling_period) # Generate phase points of the local carrier phases = np.arange(0, samples_per_code) * 2 * np.pi * sampling_period print 'phases(%s) = %s' % (repr(phases.shape), repr(phases)) # Calculate number of frequency bins depending on search frequency band and frequency step assert settings['acquisition_search_frequency_band'] % settings['acquisition_search_frequency_step'] == 0, \ 'acquisition_search_frequency_band should be divisible by acquisition_search_frequency_step' n_frequency_bins = int(settings['acquisition_search_frequency_band'] / settings['acquisition_search_frequency_step']) + 1 print 'n_frequency_bins = %s' % repr(n_frequency_bins) # Generate C/A code ca_code__time = ca_code.generate_from_settings(settings, prn=prn) # SFFT if settings['use_sfft']: ca_code__time = sfft_aliasing.execute( ca_code__time, settings['sfft_subsampling_factor']) ca_codes__freq = np.conjugate(fft(ca_code__time)) print 'ca_codes__time(%s) = %s' % (repr( ca_code__time.shape), repr(ca_code__time)) # Allocate memory for the 2D search all_results = np.empty(shape=(n_frequency_bins, actual_samples_per_code)) # Generate all frequency bins frequency_bins = ( settings['intermediate_frequency'] - \ (settings['acquisition_search_frequency_band'] / 2) + \ settings['acquisition_search_frequency_step'] * np.arange(n_frequency_bins) ).astype(int) print 'frequency_bins(%s) = %s' % (repr( frequency_bins.shape), repr(frequency_bins)) # Allocate memory for output dictionary output = { 'frequency_shift': None, 'code_shift': None, 'peak_value': None, 'peak_ratio': None, 'corr_result': None, 'found': None, } print '* searching PRN = %s' % (repr(prn), ) # # Scan all Doppler shifts # for freq_bin_i in xrange(n_frequency_bins): # Generate local sine and cosine carriers carrier_sin = np.sin(frequency_bins[freq_bin_i] * phases) carrier_cos = np.cos(frequency_bins[freq_bin_i] * phases) # Demodulation I1 = carrier_sin * x_1 Q1 = carrier_cos * x_1 # I2 = carrier_sin * x_2 # Q2 = carrier_cos * x_2 # Reconstruct baseband signal IQ1 = I1 + 1j * Q1 # IQ2 = I2 + 1j*Q2 if settings['use_sfft']: IQ1 = sfft_aliasing.execute(IQ1, settings['sfft_subsampling_factor']) # IQ2 = sfft_aliasing.execute(IQ2, settings['sfft_subsampling_factor']) performance_counter.increase(additions=IQ1.size * settings['sfft_subsampling_factor']) # performance_counter.increase(additions=IQ2.size * settings['sfft_subsampling_factor']) # Convert to frequency domain IQ1_freq = fft(IQ1) # IQ2_freq = fft(IQ2) performance_counter.fft(IQ1.size) # performance_counter.fft(IQ2.size) # Multiplication in the frequency domain corresponds to convolution in the time domain conv_code_IQ1 = IQ1_freq * ca_codes__freq # conv_code_IQ2 = IQ2_freq * ca_codes__freq[prn-1] performance_counter.increase(multiplications=IQ1_freq.size) # performance_counter.increase(multiplications=IQ2_freq.size) # IFFT to obtain correlation corr_result_1 = np.abs(ifft(conv_code_IQ1))**2 # corr_result_2 = np.abs(ifft(conv_code_IQ2)) ** 2 # assert all_results[freq_bin_i, :].shape == corr_result_1.shape == corr_result_2.shape # if np.max(corr_result_1) > np.max(corr_result_2): all_results[freq_bin_i, :] = corr_result_1 # else: # all_results[freq_bin_i, :] = corr_result_2 # Get the peak location for every frequency bins peak_values = all_results.max(axis=1) assert all_results.max() in peak_values # Find the Doppler shift index frequency_shift_idx = peak_values.argmax() print 'frequency_shift_idx = %s' % repr(frequency_shift_idx) # Select the frequency bin that corresponds to this frequency shift index located_frequency_bin = all_results[frequency_shift_idx] output['corr_result'] = located_frequency_bin # Find the code shift in the correct frequency bin code_shift = located_frequency_bin.argmax() output['code_shift'] = code_shift print 'code_shift = %s' % repr(code_shift) peak_value = all_results[frequency_shift_idx][code_shift] output['peak_value'] = peak_value assert all_results.max() == peak_value print 'peak_value = %s' % repr(peak_value) if plot_3d_graphs: fig = plt.figure() doppler_shifts__khz = ( (settings['acquisition_search_frequency_step'] * np.arange(n_frequency_bins)) - (settings['acquisition_search_frequency_band'] / 2)) / 1000 ax = fig.gca(projection='3d') surf = ax.plot_surface( X=np.arange(samples_per_code).reshape((1, -1)), Y=doppler_shifts__khz.reshape((-1, 1)), Z=all_results, rstride=1, cstride=1, cmap=matplotlib.cm.coolwarm, linewidth=0, antialiased=False, ) ax.set_xlabel('Code shift') ax.set_ylabel('Doppler shift (kHz)') # Calculate code phase range samples_per_code_chip = int( round(settings['sampling_frequency'] / settings['code_frequency'])) # SFFT if settings['use_sfft']: samples_per_code_chip = int(samples_per_code_chip / settings['sfft_subsampling_factor']) print 'samples_per_code_chip = %s' % repr(samples_per_code_chip) # # Threshold calculation 2 # # located_frequency_bin__without_peak = np.delete(located_frequency_bin, code_shift) # assert peak_value.max() not in located_frequency_bin__without_peak # output['noise_var'] = (located_frequency_bin__without_peak - located_frequency_bin__without_peak.mean()).var() # output['snr'] = peak_value**2 / output['noise_var'] # # Get second largest peak value outside the chip where the maximum peak is located # # Calculate excluded range excluded_range_1 = code_shift - samples_per_code_chip excluded_range_2 = code_shift + samples_per_code_chip print 'excluded_range_1 = %s' % repr(excluded_range_1) print 'excluded_range_2 = %s' % repr(excluded_range_2) # Excluded range boundary correction if excluded_range_1 < 1: print 'excluded_range_1 < 1' code_phase_range = np.arange( excluded_range_2, actual_samples_per_code + excluded_range_1) elif excluded_range_2 >= actual_samples_per_code: print 'excluded_range_2 >= samples_per_code' code_phase_range = np.arange( excluded_range_2 - actual_samples_per_code, excluded_range_1) else: code_phase_range = np.concatenate((np.arange(0, excluded_range_1), np.arange(excluded_range_2, actual_samples_per_code))) assert code_shift not in code_phase_range print 'code_phase_range(%s) = %s' % (repr( code_phase_range.shape), repr(code_phase_range)) # Get second largest peak value second_peak_value = all_results[frequency_shift_idx, code_phase_range].max() print 'second_peak_value = %s' % repr(second_peak_value) # # TEST # sorted = np.sort(located_frequency_bin)[::-1] # assert sorted[0] == peak_value # assert sorted[1] == second_peak_value # Calculate ratio between the largest peak value and the second largest peak value peak_ratio = peak_value / second_peak_value print 'peak_ratio = %s' % repr(peak_ratio) output['peak_ratio'] = peak_ratio # # Thresholding # if peak_ratio > settings['acquisition_threshold']: output['found'] = True print '-> %s FOUND' % repr(prn) else: output['found'] = False print '-> %s NOT FOUND' % repr(prn) return output, performance_counter
def acquisition(x, settings, plot_graphs=False, plot_3d_graphs=False, plot_corr_graphs_for=None, performance_counter=PerformanceCounter()): # Calculate number of samples per spreading code (corresponding to 1ms of data) samples_per_code = int(round(settings['sampling_frequency'] * settings['code_length'] / settings['code_frequency'])) print 'samples_per_code = %s' % repr(samples_per_code) # SFFT aliased_samples_per_code = int(samples_per_code / settings['sfft_subsampling_factor']) if settings['use_sfft']: actual_samples_per_code = aliased_samples_per_code else: actual_samples_per_code = samples_per_code # Calculate sampling period sampling_period = 1.0 / settings['sampling_frequency'] print 'sampling_period = %s' % repr(sampling_period) # Generate phase points of the local carrier phases = np.arange(0, samples_per_code) * 2 * np.pi * sampling_period print 'phases(%s) = %s' % (repr(phases.shape), repr(phases)) # Calculate number of frequency bins depending on search frequency band and frequency step assert settings['acquisition_search_frequency_band'] % settings['acquisition_search_frequency_step'] == 0, \ 'acquisition_search_frequency_band should be divisible by acquisition_search_frequency_step' n_frequency_bins = int(settings['acquisition_search_frequency_band'] / settings['acquisition_search_frequency_step']) + 1 print 'n_frequency_bins = %s' % repr(n_frequency_bins) # Generate and store C/A lookup table ca_codes__time = ca_code.generate_table(settings) original_ca_codes__time = ca_code.generate_table(settings) # SFFT if settings['use_sfft']: aliased_ca_codes__time = np.empty(shape=(settings['satellites_total'], aliased_samples_per_code)) for i in xrange(ca_codes__time.shape[0]): aliased_ca_codes__time[i] = sfft_aliasing.execute(ca_codes__time[i], settings['sfft_subsampling_factor']) ca_codes__time = aliased_ca_codes__time ca_codes__freq = np.conjugate(fft(ca_codes__time)) print 'ca_codes__time(%s) = %s' % (repr(ca_codes__time.shape), repr(ca_codes__time)) # Allocate memory for the 2D search all_results = np.empty(shape=(n_frequency_bins, actual_samples_per_code)) # Generate all frequency bins frequency_bins = ( settings['intermediate_frequency'] - \ (settings['acquisition_search_frequency_band'] / 2) + \ settings['acquisition_search_frequency_step'] * np.arange(n_frequency_bins) ).astype(int) print 'frequency_bins(%s) = %s' % (repr(frequency_bins.shape), repr(frequency_bins)) # Allocate memory for output dictionary satellites_to_search__size = settings['satellites_to_search'].size output = { 'frequency_shifts': np.zeros(satellites_to_search__size), 'frequency_offsets': np.zeros(satellites_to_search__size), 'code_shift_candidates': np.zeros(shape=(satellites_to_search__size, settings['sfft_subsampling_factor'])), 'code_shift_candidate_metrics': np.zeros(shape=(satellites_to_search__size, settings['sfft_subsampling_factor'])), 'code_shifts': np.zeros(satellites_to_search__size), 'peak_ratios': np.zeros(satellites_to_search__size), 'found': np.zeros(satellites_to_search__size, dtype=np.bool), } for idx, prn in enumerate(settings['satellites_to_search']): print '* searching PRN = %s' % (repr(prn),) result_summation = np.zeros(actual_samples_per_code) for sum_idx in xrange(settings['sum_results']): # Two consecutive 2ms reading # x_1 = x[(settings['code_offset']*samples_per_code):(settings['code_offset']*samples_per_code + samples_per_code)] # x_2 = x[(settings['code_offset']*samples_per_code + samples_per_code):(settings['code_offset']*samples_per_code + 2*samples_per_code)] x_1 = x[sum_idx*samples_per_code:sum_idx*samples_per_code+samples_per_code] x_2 = x[sum_idx*samples_per_code+samples_per_code:sum_idx*samples_per_code+2*samples_per_code] print 'x_1.shape = %s' % repr(x_1.shape) print 'x_2.shape = %s' % repr(x_2.shape) assert x_1.shape == x_2.shape # # Scan all Doppler shifts # for freq_bin_i in xrange(n_frequency_bins): # Generate local sine and cosine carriers carrier_sin = np.sin(frequency_bins[freq_bin_i] * phases) carrier_cos = np.cos(frequency_bins[freq_bin_i] * phases) # Demodulation I1 = carrier_sin * x_1 Q1 = carrier_cos * x_1 I2 = carrier_sin * x_2 Q2 = carrier_cos * x_2 # Reconstruct baseband signal IQ1 = I1 + 1j*Q1 IQ2 = I2 + 1j*Q2 if settings['use_sfft']: IQ1 = sfft_aliasing.execute(IQ1, settings['sfft_subsampling_factor']) IQ2 = sfft_aliasing.execute(IQ2, settings['sfft_subsampling_factor']) performance_counter.increase(additions=IQ1.size * settings['sfft_subsampling_factor']) performance_counter.increase(additions=IQ2.size * settings['sfft_subsampling_factor']) # Convert to frequency domain IQ1_freq = fft(IQ1) IQ2_freq = fft(IQ2) performance_counter.fft(IQ1.size) performance_counter.fft(IQ2.size) # Multiplication in the frequency domain corresponds to convolution in the time domain conv_code_IQ1 = IQ1_freq * ca_codes__freq[prn-1] conv_code_IQ2 = IQ2_freq * ca_codes__freq[prn-1] performance_counter.increase(multiplications=IQ1_freq.size) performance_counter.increase(multiplications=IQ2_freq.size) # IFFT to obtain correlation corr_result_1 = np.abs(ifft(conv_code_IQ1)) ** 2 corr_result_2 = np.abs(ifft(conv_code_IQ2)) ** 2 # assert all_results[freq_bin_i, :].shape == corr_result_1.shape == corr_result_2.shape if np.max(corr_result_1) > np.max(corr_result_2): all_results[freq_bin_i, :] = corr_result_1 else: all_results[freq_bin_i, :] = corr_result_2 # Get the peak location for every frequency bins peak_values = all_results.max(axis=1) assert all_results.max() in peak_values # Find the Doppler shift index frequency_shift_idx = peak_values.argmax() print 'frequency_shift_idx = %s' % repr(frequency_shift_idx) # Select the frequency bin that corresponds to this frequency shift index located_frequency_bin = all_results[frequency_shift_idx] result_summation += located_frequency_bin # Find the code shift in the correct frequency bin code_shift = result_summation.argmax() output['code_shifts'][idx] = code_shift print 'code_shift = %s' % repr(code_shift) peak_value = result_summation[code_shift] assert result_summation.max() == peak_value print 'peak_value = %s' % repr(peak_value) if prn in plot_corr_graphs_for: plt.figure() plt.plot(result_summation / result_summation.max()) plt.ylabel('Normalised magnitude') plt.xlabel('Code shift (chips)') title_parts = ['PRN=%d' % prn] if settings['use_sfft']: title_parts.append('q=%d (Sparse)' % settings['sfft_subsampling_factor']) else: title_parts.append('(Baseline)' % settings['sfft_subsampling_factor']) if settings['sum_results']: title_parts.append('Summing %d' % settings['sum_results']) plt.title(', '.join(title_parts)) plt.grid() if settings['use_sfft']: t_candidates = output['code_shift_candidate_metrics'][idx] for p in xrange(settings['sfft_subsampling_factor']): # print original_ca_codes__time[prn-1].shape candidate_t = code_shift + p * aliased_samples_per_code output['code_shift_candidates'][idx][p] = candidate_t ca_code__aligned = np.roll(original_ca_codes__time[prn-1], candidate_t) x__start = x[0:samples_per_code] print ca_code__aligned assert ca_code__aligned.shape == x__start.shape t_candidates[p] = np.sum( ca_code__aligned * x__start # np.abs( # ifft(np.conj(fft(ca_code__aligned)) * fft(x__start)) # ) ** 2 ) print 'candidate_t[%s] = %s, sum = %s' % (repr(p), repr(candidate_t), repr(t_candidates[p])) correct_p = t_candidates.argmax() correct_code_shift = code_shift + correct_p * aliased_samples_per_code output['code_shifts'][idx] = correct_code_shift print 'correct_code_shift', correct_code_shift # Doppler shifts doppler_shifts__khz = ( (settings['acquisition_search_frequency_step'] * np.arange(n_frequency_bins)) - (settings['acquisition_search_frequency_band'] / 2) ) output['frequency_shifts'][idx] = frequency_bins[frequency_shift_idx] output['frequency_offsets'][idx] = doppler_shifts__khz[frequency_shift_idx] if plot_3d_graphs: fig = plt.figure() ax = fig.gca(projection='3d') surf = ax.plot_surface( X=np.arange(actual_samples_per_code).reshape((1, -1)), Y=doppler_shifts__khz.reshape((-1, 1)) / 1000, Z=all_results, rstride=1, cstride=1, cmap=matplotlib.cm.coolwarm, linewidth=0, antialiased=False, ) ax.set_xlabel('Code shift (chips)') ax.set_ylabel('Doppler shift (kHz)') ax.set_zlabel('Magnitude') # Calculate code phase range samples_per_code_chip = int(round(settings['sampling_frequency'] / settings['code_frequency'])) # SFFT if settings['use_sfft']: samples_per_code_chip = int(samples_per_code_chip / settings['sfft_subsampling_factor']) print 'samples_per_code_chip = %s' % repr(samples_per_code_chip) # # Get second largest peak value outside the chip where the maximum peak is located # # Calculate excluded range excluded_range_1 = code_shift - samples_per_code_chip excluded_range_2 = code_shift + samples_per_code_chip print 'excluded_range_1 = %s' % repr(excluded_range_1) print 'excluded_range_2 = %s' % repr(excluded_range_2) # Excluded range boundary correction if excluded_range_1 < 1: print 'excluded_range_1 < 1' code_phase_range = np.arange(excluded_range_2, actual_samples_per_code + excluded_range_1) elif excluded_range_2 >= actual_samples_per_code: print 'excluded_range_2 >= samples_per_code' code_phase_range = np.arange(excluded_range_2 - actual_samples_per_code, excluded_range_1) else: code_phase_range = np.concatenate(( np.arange(0, excluded_range_1), np.arange(excluded_range_2, actual_samples_per_code) )) assert code_shift not in code_phase_range print 'code_phase_range(%s) = %s' % (repr(code_phase_range.shape), repr(code_phase_range)) # Get second largest peak value second_peak_value = all_results[frequency_shift_idx, code_phase_range].max() print 'second_peak_value = %s' % repr(second_peak_value) # Calculate ratio between the largest peak value and the second largest peak value peak_ratio = peak_value / second_peak_value print 'peak_ratio = %s' % repr(peak_ratio) output['peak_ratios'][idx] = peak_ratio # # Thresholding # if peak_ratio > settings['acquisition_threshold']: output['found'][idx] = True print '-> %s FOUND' % repr(prn) else: output['found'][idx] = False print '-> %s NOT FOUND' % repr(prn) if plot_graphs: plt.figure() colors = ['r' if found else 'b' for found in output['found']] plt.bar(settings['satellites_to_search'], output['peak_ratios'], color=colors, align='center') plt.ylabel('Acquisition quality') plt.xlabel('PRN number') artist__not_acquired = plt.Rectangle((0, 0), 1, 1, fc='b') artist__acquired = plt.Rectangle((0, 0), 1, 1, fc='r') plt.legend(( artist__not_acquired, artist__acquired ), ( 'Signal not acquired', 'Signal acquired' )) plt.xlim(0, settings['satellites_total'] + 1) plt.tight_layout() return output, performance_counter
def acquisition(x, settings, plot_graphs=False): # Calculate number of samples per spreading code (corresponding to 1ms of data) samples_per_code = int(round(settings['sampling_frequency'] * settings['code_length'] / float(settings['code_frequency']))) subsamples_per_code = samples_per_code / settings['subsampling_factor'] print 'There are %d samples per code' % samples_per_code x_1 = x[0:samples_per_code] x_2 = x[samples_per_code:2*samples_per_code] x_0dc = x - np.mean(x) # Calculate sampling period sampling_period = 1.0 / settings['sampling_frequency'] phases = np.arange(0, samples_per_code) * 2 * np.pi * sampling_period # Calculate number of frequency bins assert settings['acquisition_search_frequency_band'] % settings['acquisition_search_frequency_step'] == 0, \ 'acquisition_search_frequency_band should be divisible by acquisition_search_frequency_step' n_frequency_bins = settings['acquisition_search_frequency_band'] / settings['acquisition_search_frequency_step'] print 'There are %d frequency bins' % n_frequency_bins # todo generate ca table # SFFT: Aliasing all_results = np.zeros(shape=(n_frequency_bins, samples_per_code / settings['subsampling_factor'])) # all_results = np.zeros(shape=(n_frequency_bins, samples_per_code)) # Generate all frequency bins frequency_bins = settings['intermediate_frequency'] - \ (settings['acquisition_search_frequency_band'] / 2) + \ settings['acquisition_search_frequency_step'] * np.arange(n_frequency_bins) # Allocate output dictionary output = { 'frequency_shifts': np.zeros(settings['satellites_to_search'].size), 'code_shifts': np.zeros(settings['satellites_to_search'].size), 'peak_ratios': np.zeros(settings['satellites_to_search'].size), 'found': np.zeros(settings['satellites_to_search'].size, dtype=np.bool), } for idx, prn in enumerate(settings['satellites_to_search']): print 'Acquiring satellite PRN = %d' % prn ca_code_t = ca_code.generate(prn=prn).repeat(samples_per_code/1023) # SFFT: Aliasing ca_code_t = sfft_aliasing.execute(ca_code_t, settings['subsampling_factor']) ca_code_f = np.conj(np.fft.fft(ca_code_t)) # Scan Doppler frequencies for freq_bin_i in range(n_frequency_bins): # Generate local sine and cosine carriers carrier_sin = np.sin(frequency_bins[freq_bin_i] * phases) carrier_cos = np.cos(frequency_bins[freq_bin_i] * phases) # Demodulation IQ_1 = carrier_sin*x_1 + 1j*carrier_cos*x_1 IQ_2 = carrier_sin*x_2 + 1j*carrier_cos*x_2 # SFFT: Aliasing IQ_1 = sfft_aliasing.execute(IQ_1, settings['subsampling_factor']) IQ_2 = sfft_aliasing.execute(IQ_2, settings['subsampling_factor']) # Baseband signal to frequency domain IQ_1_freq = np.fft.fft(IQ_1) IQ_2_freq = np.fft.fft(IQ_2) # Convolve conv_code_IQ_1 = IQ_1_freq * ca_code_f conv_code_IQ_2 = IQ_2_freq * ca_code_f # IFFT to obtain correlation corr_result_1 = np.abs(np.fft.ifft(conv_code_IQ_1)) ** 2 corr_result_2 = np.abs(np.fft.ifft(conv_code_IQ_2)) ** 2 # assert all_results[freq_bin_i, :].shape == corr_result_1.shape == corr_result_2.shape if np.max(corr_result_1) > np.max(corr_result_2): all_results[freq_bin_i, :] = corr_result_1 else: all_results[freq_bin_i, :] = corr_result_2 # Peak location for each Doppler shift peak_values = all_results.max(axis=1) assert all_results.max() in peak_values frequency_shift = peak_values.argmax() print 'Frequency shift is %d' % frequency_shift correct_frequency_result = all_results[frequency_shift] code_shift = correct_frequency_result.argmax() print 'Code shift is %d' % code_shift assert all_results.max() == all_results[frequency_shift][code_shift] peak_value = all_results[frequency_shift][code_shift] print 'Peak value = %f' % peak_value # if plot_graphs: # print np.arange(1023*16/settings['subsampling_factor']).reshape((1, -1)).shape, frequency_bins.shape, all_results.shape # # fig = plt.figure() # ax = fig.gca(projection='3d') # surf = ax.plot_surface( # X=np.arange(1023*16/settings['subsampling_factor']).reshape((1, -1)), # Y=frequency_bins.reshape((-1, 1)), # Z=all_results, # rstride=1, # cstride=1, # cmap=matplotlib.cm.coolwarm, # linewidth=0, # antialiased=False, # ) # plt.show() # Calculate code phase range samples_per_code_chip = int(round(settings['sampling_frequency'] / settings['code_frequency'] / 2)) excluded_range_1 = code_shift - samples_per_code_chip excluded_range_2 = code_shift + samples_per_code_chip print 'code_shift', code_shift print 'samples_per_code', samples_per_code print 'samples_per_code_chip', samples_per_code_chip print 'excluded_range_1', excluded_range_1 print 'excluded_range_2', excluded_range_2 if excluded_range_1 < 1: code_phase_range = np.arange(excluded_range_2, subsamples_per_code + excluded_range_1) elif excluded_range_2 >= subsamples_per_code: code_phase_range = np.arange(excluded_range_2 - subsamples_per_code, excluded_range_1) else: code_phase_range = np.concatenate(( np.arange(0, excluded_range_1 - 1), np.arange(excluded_range_2, subsamples_per_code) )) print 'code_phase_range', code_phase_range.shape, code_phase_range assert code_shift not in code_phase_range second_peak_value = all_results[frequency_shift, code_phase_range].max() print 'Second peak value = %f' % second_peak_value peak_ratio = peak_value / float(second_peak_value) print 'peak_ratio = %f' % peak_ratio output['peak_ratios'][idx] = peak_ratio if peak_ratio > settings['acquisition_threshold']: output['found'][idx] = True print '* FOUND' else: output['found'][idx] = False print '* NOT FOUND' return output
def main(): # (a) Input code = ca_code.generate(prn=1, repeats=10) # rx = np.roll(ca_code.generate(prn=1, repeats=10), -10230/6*1) | ca_code.generate(prn=2, repeats=10) rx = np.roll(ca_code.generate(prn=1, repeats=10), 1000) | ca_code.generate( prn=2, repeats=10) noise_std = 1 noise = np.random.normal( scale=noise_std, size=code.size, ) rx = np.add(rx, noise) # (b) Aliasing q = 2 code_aliased = sfft_aliasing.execute(code, q) rx_aliased = sfft_aliasing.execute(rx, q) # (c) FFT code_f = fft(code_aliased) rx_f = fft(rx_aliased) # (d) Multiply code_rx_f = np.multiply(np.conjugate(code_f), rx_f) # (e) IFFT code_rx = np.real(ifft(code_rx_f)) print 'arg max is', np.argmax(code_rx) plt.figure('Local C/A code') plt.step(np.arange(code.size), code) plt.xlim(0, code.size - 1) plt.title('Local C/A code') plt.xlabel('Time') plt.setp(plt.gca().get_xticklabels(), visible=False) plt.setp(plt.gca().get_yticklabels(), visible=False) plt.figure('Received signal') plt.plot(rx) plt.xlim(0, code.size - 1) plt.title('Received signal') plt.xlabel('Time') plt.setp(plt.gca().get_xticklabels(), visible=False) plt.setp(plt.gca().get_yticklabels(), visible=False) plt.figure('Aliased Local C/A code') plt.step(np.arange(code_aliased.size), code_aliased) plt.xlim(0, code_aliased.size - 1) plt.title('Local C/A code (Aliased)') plt.xlabel('Time') plt.setp(plt.gca().get_xticklabels(), visible=False) plt.setp(plt.gca().get_yticklabels(), visible=False) plt.figure('Aliased Received signal') plt.plot(rx_aliased) plt.xlim(0, rx_aliased.size - 1) plt.title('Received signal (Aliased)') plt.xlabel('Time') plt.setp(plt.gca().get_xticklabels(), visible=False) plt.setp(plt.gca().get_yticklabels(), visible=False) plt.figure('FFT of Local CA code') plt.plot(np.abs(fftshift(code_f))) plt.title('FFT of Local C/A code') plt.xlabel('Frequency') plt.xlim(1000, 4000) plt.ylim(0, 500) plt.setp(plt.gca().get_xticklabels(), visible=False) plt.setp(plt.gca().get_yticklabels(), visible=False) plt.figure('FFT of Received signal') plt.plot(np.abs(fftshift(rx_f))) plt.title('FFT of Received signal') plt.xlabel('Frequency') plt.xlim(1000, 4000) plt.ylim(0, 500) plt.setp(plt.gca().get_xticklabels(), visible=False) plt.setp(plt.gca().get_yticklabels(), visible=False) plt.figure('Multiply') plt.plot(np.abs(fftshift(code_rx_f))) plt.title('Multiply') plt.xlabel('Frequency') plt.xlim(1500, 3500) plt.ylim(0, 100000) plt.setp(plt.gca().get_xticklabels(), visible=False) plt.setp(plt.gca().get_yticklabels(), visible=False) plt.figure('IFFT') plt.plot(code_rx) plt.title('IFFT') plt.xlim(0, code_rx.size - 1) plt.setp(plt.gca().get_xticklabels(), visible=False) plt.setp(plt.gca().get_yticklabels(), visible=False) plt.show()
def acquisition(x, settings, plot_graphs=False, plot_3d_graphs=False, performance_counter=PerformanceCounter()): # Calculate number of samples per spreading code (corresponding to 1ms of data) samples_per_code = int(round(settings['sampling_frequency'] * settings['code_length'] / settings['code_frequency'])) # print 'samples_per_code = %s' % repr(samples_per_code) # SFFT aliased_samples_per_code = int(samples_per_code / settings['sfft_subsampling_factor']) if settings['use_sfft']: actual_samples_per_code = aliased_samples_per_code else: actual_samples_per_code = samples_per_code # Calculate sampling period sampling_period = 1.0 / settings['sampling_frequency'] # print 'sampling_period = %s' % repr(sampling_period) # Generate phase points of the local carrier phases = np.arange(0, samples_per_code) * 2 * np.pi * sampling_period # print 'phases(%s) = %s' % (repr(phases.shape), repr(phases)) # Calculate number of frequency bins depending on search frequency band and frequency step assert settings['acquisition_search_frequency_band'] % settings['acquisition_search_frequency_step'] == 0, \ 'acquisition_search_frequency_band should be divisible by acquisition_search_frequency_step' n_frequency_bins = int(settings['acquisition_search_frequency_band'] / settings['acquisition_search_frequency_step']) + 1 # print 'n_frequency_bins = %s' % repr(n_frequency_bins) # Generate and store C/A lookup table ca_codes__time = ca_code.generate_table(settings) # SFFT if settings['use_sfft']: aliased_ca_codes__time = np.empty(shape=(settings['satellites_total'], aliased_samples_per_code)) for i in xrange(ca_codes__time.shape[0]): aliased_ca_codes__time[i] = sfft_aliasing.execute(ca_codes__time[i], settings['sfft_subsampling_factor']) ca_codes__time = aliased_ca_codes__time ca_codes__freq = np.conjugate(fft(ca_codes__time)) # print 'ca_codes__time(%s) = %s' % (repr(ca_codes__time.shape), repr(ca_codes__time)) # Allocate memory for the 2D search all_results = np.empty(shape=(n_frequency_bins, actual_samples_per_code)) # Generate all frequency bins frequency_bins = ( settings['intermediate_frequency'] - \ (settings['acquisition_search_frequency_band'] / 2) + \ settings['acquisition_search_frequency_step'] * np.arange(n_frequency_bins) ).astype(int) # print 'frequency_bins(%s) = %s' % (repr(frequency_bins.shape), repr(frequency_bins)) # Allocate memory for output dictionary satellites_to_search__shape = settings['satellites_to_search'].shape output = { 'frequency_shifts': np.zeros(satellites_to_search__shape, dtype=int), 'code_shifts': np.zeros(satellites_to_search__shape, dtype=int), 'peak_ratios': np.zeros(satellites_to_search__shape), 'found': np.zeros(satellites_to_search__shape, dtype=np.bool), } correct_runs = 0 run_number = 0 for idx, prn in enumerate(settings['satellites_to_search']): print '* searching PRN = %s' % (repr(prn),) # correct_runs = 0 # run_number = 0 summed_corr_result_magnitudes = np.zeros(actual_samples_per_code) counter = 10 while counter > 0: counter -= 1 # Two consecutive 2ms reading # x_1 = x[(settings['code_offset']*samples_per_code):(settings['code_offset']*samples_per_code + samples_per_code)] # x_2 = x[(settings['code_offset']*samples_per_code + samples_per_code):(settings['code_offset']*samples_per_code + 2*samples_per_code)] x_1 = x[run_number*samples_per_code:(run_number*samples_per_code + samples_per_code)] # print 'x_1.shape = %s' % repr(x_1.shape) run_number += 1 print 'run_number = %s' % repr(run_number) # # Scan all Doppler shifts # for freq_bin_i in xrange(n_frequency_bins): # Generate local sine and cosine carriers carrier_sin = np.sin(frequency_bins[freq_bin_i] * phases) carrier_cos = np.cos(frequency_bins[freq_bin_i] * phases) # Demodulation I1 = carrier_sin * x_1 Q1 = carrier_cos * x_1 # I2 = carrier_sin * x_2 # Q2 = carrier_cos * x_2 # Reconstruct baseband signal IQ1 = I1 + 1j*Q1 # IQ2 = I2 + 1j*Q2 if settings['use_sfft']: IQ1 = sfft_aliasing.execute(IQ1, settings['sfft_subsampling_factor']) # IQ2 = sfft_aliasing.execute(IQ2, settings['sfft_subsampling_factor']) performance_counter.increase(additions=IQ1.size * settings['sfft_subsampling_factor']) # performance_counter.increase(additions=IQ2.size * settings['sfft_subsampling_factor']) # Convert to frequency domain IQ1_freq = fft(IQ1) # IQ2_freq = fft(IQ2) performance_counter.fft(IQ1.size) # performance_counter.fft(IQ2.size) # Multiplication in the frequency domain corresponds to convolution in the time domain conv_code_IQ1 = IQ1_freq * ca_codes__freq[prn-1] # conv_code_IQ2 = IQ2_freq * ca_codes__freq[prn-1] performance_counter.increase(multiplications=IQ1_freq.size) # performance_counter.increase(multiplications=IQ2_freq.size) # IFFT to obtain correlation corr_result = np.abs(ifft(conv_code_IQ1)) ** 2 # corr_result_2 = np.abs(ifft(conv_code_IQ2)) ** 2 # assert all_results[freq_bin_i, :].shape == corr_result_1.shape == corr_result_2.shape # if np.max(corr_result_1) > np.max(corr_result_2): all_results[freq_bin_i, :] = corr_result # else: # all_results[freq_bin_i, :] = corr_result_2 # Get the peak location for every frequency bins peak_values = all_results.max(axis=1) assert all_results.max() in peak_values # Find the Doppler shift index frequency_shift_idx = peak_values.argmax() # print 'frequency_shift_idx = %s' % repr(frequency_shift_idx) # Select the frequency bin that corresponds to this frequency shift index located_frequency_bin = all_results[frequency_shift_idx] # Find the code shift in the correct frequency bin code_shift = located_frequency_bin.argmax() # output['code_shifts'][idx] = code_shift # print 'code_shift = %s' % repr(code_shift) peak_value = located_frequency_bin[code_shift] assert all_results.max() == peak_value # print 'peak_value = %s' % repr(peak_value) print np.abs(code_shift - settings['actual_satellite_shifts'][idx]) if np.abs(code_shift - settings['actual_satellite_shifts'][idx]) < 40: correct_runs += 1 print 'CORRECT RUN!' # # New Threshold calculation # summed_corr_result_magnitudes += np.abs(located_frequency_bin) # # print 'here', summed_corr_result_magnitudes.argmax() # snr = get_snr(summed_corr_result_magnitudes) # print 'snr', snr # if snr > settings['snr_threshold']: # output['found'][idx] = True # print 'summed_corr_result_magnitudes', summed_corr_result_magnitudes # output['code_shifts'][idx] = summed_corr_result_magnitudes.argmax() # break # # if plot_3d_graphs: # fig = plt.figure() # doppler_shifts__khz = ( # (settings['acquisition_search_frequency_step'] * np.arange(n_frequency_bins)) - # (settings['acquisition_search_frequency_band'] / 2) # ) / 1000 # # ax = fig.gca(projection='3d') # surf = ax.plot_surface( # X=np.arange(actual_samples_per_code).reshape((1, -1)), # Y=doppler_shifts__khz.reshape((-1, 1)), # Z=all_results, # rstride=1, # cstride=1, # cmap=matplotlib.cm.coolwarm, # linewidth=0, # antialiased=False, # ) # ax.set_xlabel('Code shift') # ax.set_ylabel('Doppler shift (kHz)') # # # Calculate code phase range # samples_per_code_chip = int(round(settings['sampling_frequency'] / settings['code_frequency'])) # # # SFFT # if settings['use_sfft']: # samples_per_code_chip = int(samples_per_code_chip / settings['sfft_subsampling_factor']) # # print 'samples_per_code_chip = %s' % repr(samples_per_code_chip) # # # # # Get second largest peak value outside the chip where the maximum peak is located # # # # # Calculate excluded range # excluded_range_1 = code_shift - samples_per_code_chip # excluded_range_2 = code_shift + samples_per_code_chip # print 'excluded_range_1 = %s' % repr(excluded_range_1) # print 'excluded_range_2 = %s' % repr(excluded_range_2) # # # Excluded range boundary correction # if excluded_range_1 < 1: # print 'excluded_range_1 < 1' # code_phase_range = np.arange(excluded_range_2, actual_samples_per_code + excluded_range_1) # elif excluded_range_2 >= actual_samples_per_code: # print 'excluded_range_2 >= samples_per_code' # code_phase_range = np.arange(excluded_range_2 - actual_samples_per_code, excluded_range_1) # else: # code_phase_range = np.concatenate(( # np.arange(0, excluded_range_1), # np.arange(excluded_range_2, actual_samples_per_code) # )) # # assert code_shift not in code_phase_range # print 'code_phase_range(%s) = %s' % (repr(code_phase_range.shape), repr(code_phase_range)) # # # Get second largest peak value # second_peak_value = all_results[frequency_shift_idx, code_phase_range].max() # print 'second_peak_value = %s' % repr(second_peak_value) # # # Calculate ratio between the largest peak value and the second largest peak value # peak_ratio = peak_value / second_peak_value # print 'peak_ratio = %s' % repr(peak_ratio) # output['peak_ratios'][idx] = peak_ratio # # # # # Thresholding # # # # if peak_ratio > settings['acquisition_threshold']: # output['found'][idx] = True # print '-> %s FOUND' % repr(prn) # else: # output['found'][idx] = False # print '-> %s NOT FOUND' % repr(prn) if plot_graphs: plt.figure() colors = ['r' if found else 'b' for found in output['found']] plt.bar(settings['satellites_to_search'], output['peak_ratios'], color=colors, align='center') plt.ylabel('Acquisition quality') plt.xlabel('PRN number') artist__not_acquired = plt.Rectangle((0, 0), 1, 1, fc='b') artist__acquired = plt.Rectangle((0, 0), 1, 1, fc='r') plt.legend(( artist__not_acquired, artist__acquired ), ( 'Signal not acquired', 'Signal acquired' )) plt.xlim(0, settings['satellites_total'] + 1) plt.tight_layout() if run_number == 0: output['success_probability'] = 0 else: output['success_probability'] = correct_runs / run_number print output['success_probability'] return output, performance_counter
def single_acquisition(x, prn, settings, plot_3d_graphs=False, performance_counter=PerformanceCounter()): # Calculate number of samples per spreading code (corresponding to 1ms of data) samples_per_code = int(round(settings['sampling_frequency'] * settings['code_length'] / settings['code_frequency'])) print 'samples_per_code = %s' % repr(samples_per_code) # SFFT aliased_samples_per_code = int(samples_per_code / settings['sfft_subsampling_factor']) if settings['use_sfft']: actual_samples_per_code = aliased_samples_per_code else: actual_samples_per_code = samples_per_code # Two consecutive 2ms reading x_1 = x[(settings['code_offset'] * samples_per_code):((settings['code_offset'] * samples_per_code) + samples_per_code)] x_2 = x[(settings['code_offset']*samples_per_code + samples_per_code):(settings['code_offset']*samples_per_code + 2*samples_per_code)] if x_1.size != samples_per_code: return False, performance_counter print 'x_1.shape = %s' % repr(x_1.shape) print 'x_2.shape = %s' % repr(x_2.shape) # Calculate sampling period sampling_period = 1.0 / settings['sampling_frequency'] print 'sampling_period = %s' % repr(sampling_period) # Generate phase points of the local carrier phases = np.arange(0, samples_per_code) * 2 * np.pi * sampling_period print 'phases(%s) = %s' % (repr(phases.shape), repr(phases)) # Calculate number of frequency bins depending on search frequency band and frequency step assert settings['acquisition_search_frequency_band'] % settings['acquisition_search_frequency_step'] == 0, \ 'acquisition_search_frequency_band should be divisible by acquisition_search_frequency_step' n_frequency_bins = int(settings['acquisition_search_frequency_band'] / settings['acquisition_search_frequency_step']) + 1 print 'n_frequency_bins = %s' % repr(n_frequency_bins) # Generate C/A code ca_code__time = ca_code.generate_from_settings(settings, prn=prn) # SFFT if settings['use_sfft']: ca_code__time = sfft_aliasing.execute(ca_code__time, settings['sfft_subsampling_factor']) ca_codes__freq = np.conjugate(fft(ca_code__time)) print 'ca_codes__time(%s) = %s' % (repr(ca_code__time.shape), repr(ca_code__time)) # Allocate memory for the 2D search all_results = np.empty(shape=(n_frequency_bins, actual_samples_per_code)) # Generate all frequency bins frequency_bins = ( settings['intermediate_frequency'] - \ (settings['acquisition_search_frequency_band'] / 2) + \ settings['acquisition_search_frequency_step'] * np.arange(n_frequency_bins) ).astype(int) print 'frequency_bins(%s) = %s' % (repr(frequency_bins.shape), repr(frequency_bins)) # Allocate memory for output dictionary output = { 'frequency_shift': None, 'code_shift': None, 'peak_value': None, 'peak_ratio': None, 'corr_result': None, 'found': None, } print '* searching PRN = %s' % (repr(prn),) # # Scan all Doppler shifts # for freq_bin_i in xrange(n_frequency_bins): # Generate local sine and cosine carriers carrier_sin = np.sin(frequency_bins[freq_bin_i] * phases) carrier_cos = np.cos(frequency_bins[freq_bin_i] * phases) # Demodulation I1 = carrier_sin * x_1 Q1 = carrier_cos * x_1 # I2 = carrier_sin * x_2 # Q2 = carrier_cos * x_2 # Reconstruct baseband signal IQ1 = I1 + 1j*Q1 # IQ2 = I2 + 1j*Q2 if settings['use_sfft']: IQ1 = sfft_aliasing.execute(IQ1, settings['sfft_subsampling_factor']) # IQ2 = sfft_aliasing.execute(IQ2, settings['sfft_subsampling_factor']) performance_counter.increase(additions=IQ1.size * settings['sfft_subsampling_factor']) # performance_counter.increase(additions=IQ2.size * settings['sfft_subsampling_factor']) # Convert to frequency domain IQ1_freq = fft(IQ1) # IQ2_freq = fft(IQ2) performance_counter.fft(IQ1.size) # performance_counter.fft(IQ2.size) # Multiplication in the frequency domain corresponds to convolution in the time domain conv_code_IQ1 = IQ1_freq * ca_codes__freq # conv_code_IQ2 = IQ2_freq * ca_codes__freq[prn-1] performance_counter.increase(multiplications=IQ1_freq.size) # performance_counter.increase(multiplications=IQ2_freq.size) # IFFT to obtain correlation corr_result_1 = np.abs(ifft(conv_code_IQ1)) ** 2 # corr_result_2 = np.abs(ifft(conv_code_IQ2)) ** 2 # assert all_results[freq_bin_i, :].shape == corr_result_1.shape == corr_result_2.shape # if np.max(corr_result_1) > np.max(corr_result_2): all_results[freq_bin_i, :] = corr_result_1 # else: # all_results[freq_bin_i, :] = corr_result_2 # Get the peak location for every frequency bins peak_values = all_results.max(axis=1) assert all_results.max() in peak_values # Find the Doppler shift index frequency_shift_idx = peak_values.argmax() print 'frequency_shift_idx = %s' % repr(frequency_shift_idx) # Select the frequency bin that corresponds to this frequency shift index located_frequency_bin = all_results[frequency_shift_idx] output['corr_result'] = located_frequency_bin # Find the code shift in the correct frequency bin code_shift = located_frequency_bin.argmax() output['code_shift'] = code_shift print 'code_shift = %s' % repr(code_shift) peak_value = all_results[frequency_shift_idx][code_shift] output['peak_value'] = peak_value assert all_results.max() == peak_value print 'peak_value = %s' % repr(peak_value) if plot_3d_graphs: fig = plt.figure() doppler_shifts__khz = ( (settings['acquisition_search_frequency_step'] * np.arange(n_frequency_bins)) - (settings['acquisition_search_frequency_band'] / 2) ) / 1000 ax = fig.gca(projection='3d') surf = ax.plot_surface( X=np.arange(samples_per_code).reshape((1, -1)), Y=doppler_shifts__khz.reshape((-1, 1)), Z=all_results, rstride=1, cstride=1, cmap=matplotlib.cm.coolwarm, linewidth=0, antialiased=False, ) ax.set_xlabel('Code shift') ax.set_ylabel('Doppler shift (kHz)') # Calculate code phase range samples_per_code_chip = int(round(settings['sampling_frequency'] / settings['code_frequency'])) # SFFT if settings['use_sfft']: samples_per_code_chip = int(samples_per_code_chip / settings['sfft_subsampling_factor']) print 'samples_per_code_chip = %s' % repr(samples_per_code_chip) # # Threshold calculation 2 # # located_frequency_bin__without_peak = np.delete(located_frequency_bin, code_shift) # assert peak_value.max() not in located_frequency_bin__without_peak # output['noise_var'] = (located_frequency_bin__without_peak - located_frequency_bin__without_peak.mean()).var() # output['snr'] = peak_value**2 / output['noise_var'] # # Get second largest peak value outside the chip where the maximum peak is located # # Calculate excluded range excluded_range_1 = code_shift - samples_per_code_chip excluded_range_2 = code_shift + samples_per_code_chip print 'excluded_range_1 = %s' % repr(excluded_range_1) print 'excluded_range_2 = %s' % repr(excluded_range_2) # Excluded range boundary correction if excluded_range_1 < 1: print 'excluded_range_1 < 1' code_phase_range = np.arange(excluded_range_2, actual_samples_per_code + excluded_range_1) elif excluded_range_2 >= actual_samples_per_code: print 'excluded_range_2 >= samples_per_code' code_phase_range = np.arange(excluded_range_2 - actual_samples_per_code, excluded_range_1) else: code_phase_range = np.concatenate(( np.arange(0, excluded_range_1), np.arange(excluded_range_2, actual_samples_per_code) )) assert code_shift not in code_phase_range print 'code_phase_range(%s) = %s' % (repr(code_phase_range.shape), repr(code_phase_range)) # Get second largest peak value second_peak_value = all_results[frequency_shift_idx, code_phase_range].max() print 'second_peak_value = %s' % repr(second_peak_value) # # TEST # sorted = np.sort(located_frequency_bin)[::-1] # assert sorted[0] == peak_value # assert sorted[1] == second_peak_value # Calculate ratio between the largest peak value and the second largest peak value peak_ratio = peak_value / second_peak_value print 'peak_ratio = %s' % repr(peak_ratio) output['peak_ratio'] = peak_ratio # # Thresholding # if peak_ratio > settings['acquisition_threshold']: output['found'] = True print '-> %s FOUND' % repr(prn) else: output['found'] = False print '-> %s NOT FOUND' % repr(prn) return output, performance_counter