00001 #include <stdio.h> 00002 #include <stdlib.h> 00003 #include <math.h> 00004 #include <vector> 00005 #include <fftw3.h> 00006 00007 //#include "cheetah.h" 00008 //#include "RealData_nopinger.H" 00009 #include "RealData_pinger.H" 00010 //#include "DummyData256.H" 00011 #include "FFTBinPrediction.H" 00012 00013 double sign(double val) { 00014 if (val < 0) 00015 return -1.0; 00016 else if (val > 0) 00017 return 1.0; 00018 return 0.0; 00019 } 00020 00021 // Globals 00022 const double SPEED_SOUND_WATER = 1482; // [m/s] 00023 const double SENSOR_SPACING_2_1 = 0.024; // [m] 00024 const double SENSOR_SPACING_3_2 = 0.024; // [m] 00025 const double SENSOR_SPACING_1_3 = 0.024; // [m] 00026 const int DATA_RETENTION_LENGTH = 1024; 00027 00028 // Declare Cheetah Variables 00029 //Cheetah handle; 00030 int port, bitrate; 00031 //uint8_t mode = 0; 00032 //int ret, input, ready_bit, valid_data_point; 00033 00034 // FFT & Bin Prediction 00035 const int FP_FFT_LENGTH = 32; // First-pass FFT length 00036 double BIN_PREDICTION_M = 10.59; 00037 double BIN_PREDICTION_B = -1193.82; 00038 int target_frequency1, target_frequency2; 00039 double target_wavelength1, target_wavelength2; 00040 double angle_estimate1, angle_estimate2; 00041 double bin_current_mag_sq_1; 00042 double bin_current_mag_sq_2; 00043 double bin_current_mag_sq_3; 00044 double adc1_bin_mean, adc2_bin_mean, adc3_bin_mean; 00045 std::vector<bool> FP_bin_indicator; 00046 00047 // Raw Data 00048 //const int TX_LENGTH = FP_FFT_LENGTH * 3 * 2; 00049 const int TX_LENGTH = 512 * 3 * 2; 00050 uint8_t data_in[TX_LENGTH]; 00051 uint8_t data_out[2]; 00052 00053 // Hysterisis Vars 00054 const int FP_BIN_HISTORY_LENGTH = 10;//10; 00055 const double MEAN_SCALE_FACTOR = 8.0; 00056 const int FP_MIN_SAMPLE_LENGTH = 128; 00057 int FP_bin_mean_idx = 1; 00058 double FP_adc1_bin_history[FP_BIN_HISTORY_LENGTH]; 00059 double FP_adc2_bin_history[FP_BIN_HISTORY_LENGTH]; 00060 double FP_adc3_bin_history[FP_BIN_HISTORY_LENGTH]; 00061 int FP_bin_history_fill = 0; 00062 std::vector<double> *adc1_data_history, *adc2_data_history, *adc3_data_history, *tmp_data_buffer; 00063 00064 00065 int main (int argc, char const *argv[]) { 00066 port = 0; 00067 bitrate = 10000; 00068 00069 // Assign Target Frequencies 00070 target_frequency1 = 30000; //atoi(argv[2]); 00071 target_frequency2 = 27000; //atoi(argv[3]); 00072 target_wavelength1 = (double)SPEED_SOUND_WATER / (double)target_frequency1; 00073 target_wavelength2 = (double)SPEED_SOUND_WATER / (double)target_frequency2; 00074 00075 // Calculate Sampling Frequency and Target Bin 00076 // For affine bin prediction, use m = 10.59, b = -1193.82 and a 00077 // window-HALFWIDTH of 5. 00078 FFTBinAffinePrediction FP_f1_bin(bitrate, 00079 FP_FFT_LENGTH, 00080 target_frequency1, 00081 BIN_PREDICTION_M, 00082 BIN_PREDICTION_B, 00083 3); 00084 FFTBinAffinePrediction FP_f2_bin(bitrate, 00085 FP_FFT_LENGTH, 00086 target_frequency2, 00087 BIN_PREDICTION_M, 00088 BIN_PREDICTION_B, 00089 3); 00090 printf("Sonar: First-pass Target Bin 1: %d\n", FP_f1_bin.getTargetBin()); 00091 printf("Sonar: First-pass Target Bin 2: %d\n", FP_f2_bin.getTargetBin()); 00092 00093 // Declare Data Vectors 00094 //double *FP_adc1_samples, *FP_adc2_samples, *FP_adc3_samples; 00095 double FP_adc1_samples[FP_FFT_LENGTH], FP_adc2_samples[FP_FFT_LENGTH], FP_adc3_samples[FP_FFT_LENGTH]; 00096 fftw_complex *FP_fft1, *FP_fft2, *FP_fft3; 00097 fftw_complex *SP_fft1, *SP_fft2, *SP_fft3; 00098 fftw_plan FP_fft_plan1, FP_fft_plan2, FP_fft_plan3; 00099 fftw_plan SP_fft_plan1, SP_fft_plan2, SP_fft_plan3; 00100 00101 // Allocate Memory for Data Vectors 00102 FP_fft1 = (double (*)[2]) fftw_malloc ( sizeof ( fftw_complex ) * (( FP_FFT_LENGTH / 2 ) + 1) ); 00103 FP_fft2 = (double (*)[2]) fftw_malloc ( sizeof ( fftw_complex ) * (( FP_FFT_LENGTH / 2 ) + 1) ); 00104 FP_fft3 = (double (*)[2]) fftw_malloc ( sizeof ( fftw_complex ) * (( FP_FFT_LENGTH / 2 ) + 1) ); 00105 00106 adc1_data_history = new std::vector<double>; 00107 adc2_data_history = new std::vector<double>; 00108 adc3_data_history = new std::vector<double>; 00109 00110 FP_fft_plan1 = fftw_plan_dft_r2c_1d(FP_FFT_LENGTH, FP_adc1_samples, FP_fft1, FFTW_ESTIMATE); 00111 FP_fft_plan2 = fftw_plan_dft_r2c_1d(FP_FFT_LENGTH, FP_adc2_samples, FP_fft2, FFTW_ESTIMATE); 00112 FP_fft_plan3 = fftw_plan_dft_r2c_1d(FP_FFT_LENGTH, FP_adc3_samples, FP_fft3, FFTW_ESTIMATE); 00113 00114 int z = 0; 00115 while (z++ < 700) { 00116 // Append current data to history vectors 00117 adc1_data_history->insert(adc1_data_history->end(), data1 + z * 256, data1 + (z + 1) * 256); 00118 adc2_data_history->insert(adc2_data_history->end(), data2 + z * 256, data2 + (z + 1) * 256); 00119 adc3_data_history->insert(adc3_data_history->end(), data3 + z * 256, data3 + (z + 1) * 256); 00120 00121 // Check data history vector length constraints 00122 if (adc1_data_history->size() > DATA_RETENTION_LENGTH) { 00123 //printf("Data history is too long, reducing vector sizes\n"); 00124 tmp_data_buffer = new std::vector<double> (adc1_data_history->begin() + adc1_data_history->size() - DATA_RETENTION_LENGTH, adc1_data_history->end()); 00125 delete adc1_data_history; 00126 adc1_data_history = tmp_data_buffer; 00127 tmp_data_buffer = NULL; 00128 } 00129 if (adc2_data_history->size() > DATA_RETENTION_LENGTH) { 00130 tmp_data_buffer = new std::vector<double> (adc2_data_history->begin() + adc2_data_history->size() - DATA_RETENTION_LENGTH, adc2_data_history->end()); 00131 delete adc2_data_history; 00132 adc2_data_history = tmp_data_buffer; 00133 tmp_data_buffer = NULL; 00134 } 00135 if (adc3_data_history->size() > DATA_RETENTION_LENGTH) { 00136 tmp_data_buffer = new std::vector<double> (adc3_data_history->begin() + adc3_data_history->size() - DATA_RETENTION_LENGTH, adc3_data_history->end()); 00137 delete adc3_data_history; 00138 adc3_data_history = tmp_data_buffer; 00139 tmp_data_buffer = NULL; 00140 } 00141 00142 for (int vector_idx = 0; vector_idx <= adc1_data_history->size() - FP_FFT_LENGTH; vector_idx += FP_FFT_LENGTH) { 00143 //fprintf(stderr, "Copying vector memory\n"); 00144 std::copy(adc1_data_history->begin() + vector_idx, adc1_data_history->begin() + vector_idx + FP_FFT_LENGTH, FP_adc1_samples); 00145 std::copy(adc2_data_history->begin() + vector_idx, adc2_data_history->begin() + vector_idx + FP_FFT_LENGTH, FP_adc2_samples); 00146 std::copy(adc3_data_history->begin() + vector_idx, adc3_data_history->begin() + vector_idx + FP_FFT_LENGTH, FP_adc3_samples); 00147 //fprintf(stderr, "Done copying vector memory\n"); 00148 //FP_adc1_samples = data1 + z * FP_FFT_LENGTH; 00149 //FP_adc2_samples = data2 + z * FP_FFT_LENGTH; 00150 //FP_adc3_samples = data3 + z * FP_FFT_LENGTH; 00151 00152 /*for (int m = 0; m < FP_FFT_LENGTH; ++m) 00153 printf("%5.0f ", FP_adc1_samples[m]); 00154 printf("\n");*/ 00155 00156 FP_fft_plan1 = fftw_plan_dft_r2c_1d(FP_FFT_LENGTH, FP_adc1_samples, FP_fft1, FFTW_ESTIMATE); 00157 FP_fft_plan2 = fftw_plan_dft_r2c_1d(FP_FFT_LENGTH, FP_adc2_samples, FP_fft2, FFTW_ESTIMATE); 00158 FP_fft_plan3 = fftw_plan_dft_r2c_1d(FP_FFT_LENGTH, FP_adc3_samples, FP_fft3, FFTW_ESTIMATE); 00159 //FP_fft_plan1 = fftw_plan_dft_r2c_1d(FP_FFT_LENGTH, (double *)&adc1_data_history[vector_idx], FP_fft1, FFTW_ESTIMATE); 00160 //FP_fft_plan2 = fftw_plan_dft_r2c_1d(FP_FFT_LENGTH, (double *)&adc2_data_history[vector_idx], FP_fft2, FFTW_ESTIMATE); 00161 //FP_fft_plan3 = fftw_plan_dft_r2c_1d(FP_FFT_LENGTH, (double *)&adc3_data_history[vector_idx], FP_fft3, FFTW_ESTIMATE); 00162 00163 // Perform FFT on current input data 00164 //fprintf(stderr, "Pre-FFT Notice\n"); 00165 fftw_execute(FP_fft_plan1); 00166 fftw_execute(FP_fft_plan2); 00167 fftw_execute(FP_fft_plan3); 00168 //fprintf(stderr, "FFT Complete\n"); 00169 00170 // Calculate Gaussian weighted sums surrounding predicted bin 00171 int FP_target_bin = FP_f1_bin.getTargetBin(); 00172 00173 // Populate current bin magnitude array 00174 bin_current_mag_sq_1 = FP_fft1[FP_target_bin][0] * FP_fft1[FP_target_bin][0] + FP_fft1[FP_target_bin][1] * FP_fft1[FP_target_bin][1]; 00175 bin_current_mag_sq_2 = FP_fft2[FP_target_bin][0] * FP_fft2[FP_target_bin][0] + FP_fft2[FP_target_bin][1] * FP_fft2[FP_target_bin][1]; 00176 bin_current_mag_sq_3 = FP_fft3[FP_target_bin][0] * FP_fft3[FP_target_bin][0] + FP_fft3[FP_target_bin][1] * FP_fft3[FP_target_bin][1]; 00177 //fprintf(stderr, "Bin Magnitudes Selected\n"); 00178 00179 // Index Check 00180 if (FP_bin_mean_idx >= FP_BIN_HISTORY_LENGTH) 00181 FP_bin_mean_idx = 0; 00182 00183 // Initilize Mean Array 00184 if (FP_bin_history_fill < FP_BIN_HISTORY_LENGTH) { 00185 FP_adc1_bin_history[FP_bin_mean_idx] = bin_current_mag_sq_1; 00186 FP_adc2_bin_history[FP_bin_mean_idx] = bin_current_mag_sq_2; 00187 FP_adc3_bin_history[FP_bin_mean_idx] = bin_current_mag_sq_3; 00188 ++FP_bin_mean_idx; 00189 00190 fftw_destroy_plan(FP_fft_plan1); 00191 fftw_destroy_plan(FP_fft_plan2); 00192 fftw_destroy_plan(FP_fft_plan3); 00193 ++FP_bin_history_fill; 00194 continue; 00195 } 00196 00197 adc1_bin_mean = 0; 00198 adc2_bin_mean = 0; 00199 adc3_bin_mean = 0; 00200 00201 for (int i = 0; i < FP_BIN_HISTORY_LENGTH; ++i) { 00202 adc1_bin_mean += FP_adc1_bin_history[i]; 00203 adc2_bin_mean += FP_adc2_bin_history[i]; 00204 adc3_bin_mean += FP_adc3_bin_history[i]; 00205 } 00206 adc1_bin_mean /= (double)FP_BIN_HISTORY_LENGTH; 00207 adc2_bin_mean /= (double)FP_BIN_HISTORY_LENGTH; 00208 adc3_bin_mean /= (double)FP_BIN_HISTORY_LENGTH; 00209 00210 if (bin_current_mag_sq_1 > MEAN_SCALE_FACTOR * adc1_bin_mean && 00211 bin_current_mag_sq_2 > MEAN_SCALE_FACTOR * adc2_bin_mean && 00212 bin_current_mag_sq_3 > MEAN_SCALE_FACTOR * adc3_bin_mean) { 00213 FP_bin_indicator.push_back(true); 00214 printf("1 "); 00215 printf("%15.0f\n", bin_current_mag_sq_3); 00216 } else { 00217 FP_bin_indicator.push_back(false); 00218 //printf("0 "); 00219 //printf("%15.0f\n", bin_current_mag_sq_3); 00220 FP_adc1_bin_history[FP_bin_mean_idx] = bin_current_mag_sq_1; 00221 FP_adc2_bin_history[FP_bin_mean_idx] = bin_current_mag_sq_2; 00222 FP_adc3_bin_history[FP_bin_mean_idx] = bin_current_mag_sq_3; 00223 //printf("%10.0f, %10.0f, %10.0f\n", adc1_bin_mean, adc2_bin_mean, adc3_bin_mean); 00224 ++FP_bin_mean_idx; 00225 } 00226 00227 00228 00229 if (FP_bin_indicator[0] == 0 && FP_bin_indicator[1] == 1) { 00230 printf("Just had a pulse!\n"); 00231 00232 int SP_bin_count = 0; 00233 while (FP_bin_indicator[SP_bin_count + 1] != 0) 00234 ++SP_bin_count; 00235 printf("Signal Bin Count of %d\n", SP_bin_count); 00236 00237 if (SP_bin_count * FP_FFT_LENGTH >= FP_MIN_SAMPLE_LENGTH) { 00238 int SP_fft_length = SP_bin_count * FP_FFT_LENGTH; 00239 00240 // Copy the sample data into new double array 00241 double *SP_adc1_samples = new double[SP_fft_length]; 00242 double *SP_adc2_samples = new double[SP_fft_length]; 00243 double *SP_adc3_samples = new double[SP_fft_length]; 00244 //std::copy(adc1_data_history->end() - (SP_bin_count + 1) * FP_FFT_LENGTH, adc1_data_history->end() - FP_FFT_LENGTH, SP_adc1_samples); 00245 std::copy(adc1_data_history->begin() + vector_idx - (SP_bin_count) * FP_FFT_LENGTH, adc1_data_history->begin() + vector_idx, SP_adc1_samples); 00246 std::copy(adc2_data_history->begin() + vector_idx - (SP_bin_count) * FP_FFT_LENGTH, adc2_data_history->begin() + vector_idx, SP_adc2_samples); 00247 std::copy(adc3_data_history->begin() + vector_idx - (SP_bin_count) * FP_FFT_LENGTH, adc3_data_history->begin() + vector_idx, SP_adc3_samples); 00248 00249 // Allocate Memory for Data Arrays 00250 SP_fft1 = (double (*)[2]) fftw_malloc ( sizeof ( fftw_complex ) * (( (SP_fft_length) / 2 ) + 1) ); 00251 SP_fft2 = (double (*)[2]) fftw_malloc ( sizeof ( fftw_complex ) * (( (SP_fft_length) / 2 ) + 1) ); 00252 SP_fft3 = (double (*)[2]) fftw_malloc ( sizeof ( fftw_complex ) * (( (SP_fft_length) / 2 ) + 1) ); 00253 00254 SP_fft_plan1 = fftw_plan_dft_r2c_1d(FP_FFT_LENGTH, SP_adc1_samples, SP_fft1, FFTW_ESTIMATE); 00255 SP_fft_plan2 = fftw_plan_dft_r2c_1d(FP_FFT_LENGTH, SP_adc1_samples, SP_fft2, FFTW_ESTIMATE); 00256 SP_fft_plan3 = fftw_plan_dft_r2c_1d(FP_FFT_LENGTH, SP_adc1_samples, SP_fft3, FFTW_ESTIMATE); 00257 00258 // Perform FFT on current input data 00259 fftw_execute(SP_fft_plan1); 00260 fftw_execute(SP_fft_plan2); 00261 fftw_execute(SP_fft_plan3); 00262 00263 FFTBinAffinePrediction SP_f1_bin(bitrate, 00264 SP_fft_length, 00265 target_frequency1, 00266 BIN_PREDICTION_M, 00267 BIN_PREDICTION_B, 00268 3); 00269 /*FFTBinAffinePrediction SP_f2_bin(bitrate, 00270 SP_fft_length, 00271 target_frequency2, 00272 BIN_PREDICTION_M, 00273 BIN_PREDICTION_B, 00274 3);*/ 00275 00276 int SP_target_bin = SP_f1_bin.getTargetBin(); 00277 00278 fprintf(stderr, "SP Target Bin: %d\n", SP_target_bin); 00279 00280 // Calculate Phase of each signal found on each ADC 00281 double phase1 = atan2((double)SP_fft1[(int)SP_target_bin][1], (double)SP_fft1[(int)SP_target_bin][0]); 00282 double phase2 = atan2((double)SP_fft2[(int)SP_target_bin][1], (double)SP_fft2[(int)SP_target_bin][0]); 00283 double phase3 = atan2((double)SP_fft3[(int)SP_target_bin][1], (double)SP_fft3[(int)SP_target_bin][0]); 00284 00285 // Calculate usable phase differences 00286 double delta1 = phase2 - phase1; 00287 double delta2 = phase3 - phase2; 00288 double delta3 = phase1 - phase3; 00289 00290 fprintf(stderr, "Phase: %5.5f %5.5f %5.5f\n", phase1, phase2, phase3); 00291 fprintf(stderr, "Deltas: %5.5f %5.5f %5.5f\n", delta1, delta2, delta3); 00292 00293 // Free Data Array Memory 00294 fftw_free(SP_fft1); 00295 fftw_free(SP_fft2); 00296 fftw_free(SP_fft3); 00297 00298 // Determine minimum phase difference for pair selection 00299 int min_index = 3; 00300 if (fabs(delta2) < fabs(delta1) && fabs(delta2) < fabs(delta3)) 00301 min_index = 2; 00302 if (fabs(delta1) < fabs(delta2) && fabs(delta1) < fabs(delta3)) 00303 min_index = 1; 00304 00305 double delta_tmp; 00306 switch (min_index) { 00307 case 1: 00308 delta_tmp = delta1; 00309 if (delta3 > delta2) 00310 delta_tmp = -1.0 * delta1 + sign(delta_tmp) * 2.0 * M_PI; 00311 angle_estimate1 = delta_tmp * (double)(((double)target_wavelength1 / 2.0) / SENSOR_SPACING_2_1) * 180.0 / M_PI / 2.0; 00312 break; 00313 case 2: 00314 delta_tmp = delta2; 00315 if (delta1 > delta3) 00316 delta_tmp = -1.0 * delta2 + 2.0 * M_PI; 00317 angle_estimate1 = (delta_tmp - 4.0 / 3.0 * M_PI) * ((target_wavelength1 / 2.0) / SENSOR_SPACING_3_2) * 180.0 / M_PI / 2.0; 00318 break; 00319 case 3: 00320 delta_tmp = delta3; 00321 if (delta2 > delta1) 00322 delta_tmp = -1.0 * delta3 - 2.0 * M_PI; 00323 angle_estimate1 = (delta_tmp + 4.0 / 3.0 * M_PI ) * (((double)target_wavelength1 / 2.0) / SENSOR_SPACING_1_3) * 180.0 / M_PI / 2.0; 00324 break; 00325 default: 00326 fprintf(stderr, "Sonar: Invalid min_index for phase difference."); 00327 } 00328 fprintf(stderr, "Min Index: %d\n", min_index); 00329 fprintf(stderr, "Angle Estimate (1): %3.2f\n", angle_estimate1); 00330 00331 // DEBUG 00332 for (int blah = 0; blah < SP_bin_count * FP_FFT_LENGTH; ++blah) 00333 printf("%5.0f", SP_adc1_samples[blah]); 00334 printf("\n"); 00335 00336 } 00337 } 00338 00339 if (FP_bin_indicator.size() > FP_BIN_HISTORY_LENGTH) 00340 FP_bin_indicator.erase(FP_bin_indicator.begin()); 00341 } 00342 } 00343 fftw_destroy_plan(FP_fft_plan1); 00344 fftw_destroy_plan(FP_fft_plan2); 00345 fftw_destroy_plan(FP_fft_plan3); 00346 fftw_destroy_plan(SP_fft_plan1); 00347 fftw_destroy_plan(SP_fft_plan2); 00348 fftw_destroy_plan(SP_fft_plan3); 00349 00350 return 0; 00351 } 00352