SonarDetectTest.C

00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <math.h>
00004 #include <fftw3.h>
00005 
00006 //#include "cheetah.h"
00007 #include "TestData.H"
00008 #include "FFTBinPrediction.H"
00009 
00010 double sign(double val) {
00011   if (val < 0)
00012     return -1.0;
00013   else if (val > 0)
00014     return 1.0;
00015   return 0.0;
00016 }
00017 
00018 // Globals
00019 const double SPEED_SOUND_WATER = 1482; // [m/s]
00020 const double SENSOR_SPACING = 0.024;    // [m]
00021 
00022 // Cheetah Settings
00023 //Cheetah handle;
00024 int  port, bitrate;
00025 //uint8_t  mode  = 0;
00026 
00027 // Peak Detection
00028 double maxIndex1, maxValue1;
00029 double maxIndex2, maxValue2;
00030 double maxIndex3, maxValue3;
00031 
00032 // FFT
00033 const int N_FFT = 512;
00034 
00035 // Data
00036 //uint8_t  data_in[N_FFT * 3];
00037 //uint8_t  data_out[2];
00038 short  data_in[N_FFT * 3];
00039 short  data_out[2];
00040 int  ret;
00041 int  input, ready_bit, valid_data_point;
00042 int  target_frequency, halfwidth;
00043 double weighted_sum;
00044 double angle_estimate;
00045 
00046 int main (int argc, char const *argv[]) {
00047   if (argc < 3) {
00048     fprintf(stderr, "usage: async PORT BITRATE [Target Freq. in Hz] [halfwidth]\n");
00049     return 1;
00050   }
00051 
00052   port    = atoi(argv[1]);
00053   bitrate = atoi(argv[2]);
00054 
00055   if (argc >= 4)
00056     target_frequency = atoi(argv[3]);
00057   else
00058     target_frequency = 30000;
00059   double target_wavelength = (double)SPEED_SOUND_WATER / (double)target_frequency;
00060 
00061   //if (argc >= 5)
00062   //  halfwidth = atoi(argv[4]);
00063   //else
00064     halfwidth = 3;
00065   //double *gaussian_weights;
00066   //gaussian_weights = new double[2 * halfwidth + 1];
00067 //  double gaussian_weights[] = {0.006, 0.061, 0.242, 0.383, 0.242, 0.061, 0.006};
00068 
00069 //  // Open the device
00070 //  handle = ch_open(port);
00071 //
00072 //  if (handle <= 0) {
00073 //    fprintf(stderr, "Unable to open Cheetah device on port %d\n", port);
00074 //    fprintf(stderr, "Error code = %d (%s)\n", handle, ch_status_string(handle));
00075 //    exit(1);
00076 //  }
00077 //  fprintf(stderr, "Opened Cheetah device on port %d\n", port);
00078 //
00079 //  fprintf(stderr, "Host interface is %s\n",
00080 //      (ch_host_ifce_speed(handle)) ? "high speed" : "full speed");
00081 //
00082 //  // Ensure that the SPI subsystem is configured.
00083 //  ch_spi_configure(handle, CheetahSpiPolarity(mode >> 1), CheetahSpiPhase(mode & 1), CH_SPI_BITORDER_MSB, 0x0);
00084 //  fprintf(stderr, "SPI configuration set to mode %d, %s shift, SS[2:0] active low\n", mode, "MSB");
00085 //
00086 //  // Power the target using the Cheetah adapter's power supply.
00087 //  ch_target_power(handle, CH_TARGET_POWER_ON);
00088 //  ch_sleep_ms(100);
00089 //
00090 //  // Set the bitrate.
00091 //  bitrate = ch_spi_bitrate(handle, bitrate);
00092 //  fprintf(stderr, "Bitrate set to %d kHz\n", bitrate);
00093 //
00094 //  // Make a simple queue to just assert OE.
00095 //  ch_spi_queue_clear(handle);
00096 //  ch_spi_queue_oe(handle, 1);
00097 //  ch_spi_batch_shift(handle, 0, 0);
00098 
00099   // Queue the batch, which is a sequence of SPI packets (back-to-back) each of length 2.
00100   fprintf(stderr, "Beginning to queue SPI packets...");
00101   data_out[0] = 0xff;
00102   data_out[1] = 0xff;
00103 //  ch_spi_queue_clear(handle);
00104 //  
00105 //  for (int i = 0; i < N_FFT * 3; ++i) {
00106 //    // Convert Slave 1
00107 //    ch_spi_queue_ss(handle, 0xF);
00108 //    ch_spi_queue_array(handle, 2, data_out);
00109 //    ch_spi_queue_ss(handle, 0xE);
00110 //    
00111 //    // Convert Slave 2
00112 //    ch_spi_queue_ss(handle, 0xF);
00113 //    ch_spi_queue_array(handle, 2, data_out);
00114 //    ch_spi_queue_ss(handle, 0xD);
00115 //
00116 //    // Convert Slave 3
00117 //    ch_spi_queue_ss(handle, 0xF);
00118 //    ch_spi_queue_array(handle, 2, data_out);
00119 //    ch_spi_queue_ss(handle, 0xB);
00120 //  }
00121   fprintf(stderr, " Done\n");
00122 
00123   // Calculate Sampling Frequency and Target Bin
00124   // For affine bin prediction, use m = 10.59, b = -1193.82 and a
00125   // window-halfwidth of 5.
00126   FFTBinAffinePrediction bin_predictor(bitrate, N_FFT, target_frequency, 10.59, -1193.82, halfwidth);
00127   fprintf(stderr, "Target Bin: %d\n", bin_predictor.getTargetBin());
00128 
00129   // Define the Data Vectors
00130   //double *data1, *data2, *data3;
00131   fftw_complex *fft1, *fft2, *fft3;
00132   fftw_plan fft_plan1, fft_plan2, fft_plan3;
00133 
00134   // Allocate Memory for the Data Vectors
00135   //data1 = (double *) fftw_malloc ( sizeof ( double ) * N_FFT );
00136   //data2 = (double *) fftw_malloc ( sizeof ( double ) * N_FFT );
00137   //data3 = (double *) fftw_malloc ( sizeof ( double ) * N_FFT );
00138   fft1 = (double (*)[2]) fftw_malloc ( sizeof ( fftw_complex ) * (( N_FFT / 2 ) + 1) );
00139   fft2 = (double (*)[2]) fftw_malloc ( sizeof ( fftw_complex ) * (( N_FFT / 2 ) + 1) );
00140   fft3 = (double (*)[2]) fftw_malloc ( sizeof ( fftw_complex ) * (( N_FFT / 2 ) + 1) );
00141   fft_plan1 = fftw_plan_dft_r2c_1d(N_FFT, data1, fft1, FFTW_ESTIMATE);
00142   fft_plan2 = fftw_plan_dft_r2c_1d(N_FFT, data2, fft2, FFTW_ESTIMATE);
00143   fft_plan3 = fftw_plan_dft_r2c_1d(N_FFT, data3, fft3, FFTW_ESTIMATE);
00144 
00145 //  // Submit the first batch
00146 //  ch_spi_async_submit(handle);
00147 
00148 //  while (1) {
00149     // Submit another batch, while the previous one is in
00150     // progress.  The application may even clear the current
00151     // batch queue and queue a different set of SPI
00152     // transactions before submitting this batch
00153     // asynchronously.
00154 //    ch_spi_async_submit(handle);
00155     
00156     // The application can now perform some other functions
00157     // while the Cheetah is both finishing the previous batch
00158     // and shifting the current batch as well.  In order to
00159     // keep the Cheetah's pipe full, this entire loop must
00160     // complete AND another batch must be submitted
00161     // before the current batch completes.
00162     //ch_sleep_ms(1);
00163     
00164     // Collect the previous batch
00165     // The length of the batch, N_FFT * 6, come from the fact that 3 ADCs
00166     // are batched and the return data requires 2 bytes.  (2 * 3 = 6)
00167 //    ret = ch_spi_async_collect(handle, N_FFT * 6, data_in);
00168 
00169 //    for (int j = 0; j < N_FFT * 6; j += 6) {
00170 //      // SS2 Data
00171 //      input = (data_in[j] << 8) + data_in[j+1];
00172 //      ready_bit = input & 0x4000;
00173 //      valid_data_point = (input & 0x3ffc) >> 2;
00174 //      data2[j/6] = valid_data_point;
00175 //
00176 //      // SS3 Data
00177 //      input = (data_in[j+2] << 8) + data_in[j+3];
00178 //      ready_bit = input & 0x4000;
00179 //      valid_data_point = (input & 0x3ffc) >> 2;
00180 //      data3[j/6] = valid_data_point;
00181 //
00182 //      // SS1 Data
00183 //      input = (data_in[j+4] << 8) + data_in[j+5];
00184 //      ready_bit = input & 0x4000;
00185 //      valid_data_point = (input & 0x3ffc) >> 2;
00186 //      data1[j/6] = valid_data_point;
00187 //    }
00188 
00189     // Perform FFT on current input data
00190     fftw_execute(fft_plan1);
00191     fftw_execute(fft_plan2);
00192     fftw_execute(fft_plan3);
00193 
00194 //    // Check the ADC on SS0 for a peak.
00195 //    weighted_sum = 0;
00196     maxValue1 = 0;
00197     maxIndex1 = 0;
00198     maxValue2 = 0;
00199     maxIndex2 = 0;
00200     maxValue3 = 0;
00201     maxIndex3 = 0;
00202 //    for (int i = bin_predictor.getTargetBin() - bin_predictor.getHalfwidth(); i < bin_predictor.getTargetBin() + bin_predictor.getHalfwidth() + 1; ++i) {
00203     for (int i = 10; i < N_FFT / 2; ++i) {
00204 //      /*fprintf(stderr, "%1.3f * %10.2f + \n", gaussian_weights[i - (bin_predictor.getTargetBin() - bin_predictor.getHalfwidth())], sqrt(
00205 //          pow(fft1[i][0],2.0) +
00206 //          pow(fft1[i][1],2.0)));*/
00207 //      weighted_sum += gaussian_weights[i - (bin_predictor.getTargetBin() - bin_predictor.getHalfwidth())] *
00208 //                      sqrt(pow(fft1[i][0],2.0) + pow(fft1[i][1],2.0));
00209 
00210       if (fft1[i][0] * fft1[i][0] + fft1[i][1] * fft1[i][1] > maxValue1) {
00211         maxValue1 = fft1[i][0] * fft1[i][0] + fft1[i][1] * fft1[i][1]; //sqrt(pow(fft1[i][0],2.0) + pow(fft1[i][1],2.0));
00212         maxIndex1 = i;
00213         }
00214       if (fft2[i][0] * fft2[i][0] + fft2[i][1] * fft2[i][1] > maxValue2) {
00215         maxValue2 = fft2[i][0] * fft2[i][0] + fft2[i][1] * fft2[i][1]; //sqrt(pow(fft2[i][0],2.0) + pow(fft2[i][1],2.0));
00216         maxIndex2 = i;
00217       }
00218       if (fft3[i][0] * fft3[i][0] + fft3[i][1] * fft3[i][1] > maxValue3) {
00219         maxValue3 = fft3[i][0] * fft3[i][0] + fft3[i][1] * fft3[i][1]; //sqrt(pow(fft3[i][0],2.0) + pow(fft3[i][1],2.0));
00220         maxIndex3 = i;
00221       }
00222     }
00223     fprintf(stderr, "Signal 1 Peak: %1.0f, %10.2f\n", maxIndex1, maxValue1);
00224     fprintf(stderr, "Signal 2 Peak: %1.0f, %10.2f\n", maxIndex2, maxValue2);
00225     fprintf(stderr, "Signal 3 Peak: %1.0f, %10.2f\n", maxIndex3, maxValue3);
00226     double phase1 = atan2((double)fft1[(int)maxIndex1][1], (double)fft1[(int)maxIndex1][0]);
00227     double phase2 = atan2((double)fft2[(int)maxIndex2][1], (double)fft2[(int)maxIndex2][0]);
00228     double phase3 = atan2((double)fft3[(int)maxIndex3][1], (double)fft3[(int)maxIndex3][0]);
00229     
00230     double delta1 = phase2 - phase1;
00231     double delta2 = phase3 - phase2;
00232     double delta3 = phase1 - phase3;
00233     
00234     fprintf(stderr, "Deltas: %4.4f, %4.4f, %4.4f\n", delta1, delta2, delta3);
00235     
00236     int min_index = 3;
00237     if (fabs(delta2) < fabs(delta1) && fabs(delta2) < fabs(delta3))
00238       min_index = 2;
00239     if (fabs(delta1) < fabs(delta2) && fabs(delta1) < fabs(delta3))
00240       min_index = 1;
00241     
00242     fprintf(stderr, "Min Index: %d\n", min_index);
00243     
00244     // testing case
00245     //min_index = 1;
00246     double delta_tmp;
00247     switch (min_index) {
00248       case 1:
00249         delta_tmp = delta1;
00250         if (delta3 > delta2)
00251           delta_tmp = -1.0 * delta1 + sign(delta_tmp) * 2.0 * M_PI;
00252         angle_estimate = delta_tmp * (double)(((double)target_wavelength / 2.0) / SENSOR_SPACING) * 180.0 / M_PI / 2.0;
00253         break;
00254       case 2:
00255         delta_tmp = delta2;
00256         if (delta1 > delta3)
00257           delta_tmp = -1.0 * delta2 + 2.0 * M_PI;
00258         angle_estimate = (delta_tmp - 5.0 / 6.0 * M_PI) * ((target_wavelength / 2.0) / SENSOR_SPACING) * 180.0 / M_PI / 2.0;
00259         break;
00260       case 3:
00261         delta_tmp = delta3;
00262         if (delta2 > delta1)
00263           delta_tmp = -1.0 * delta3 - 2.0 * M_PI;
00264         //fprintf(stderr, "%4.8f\n", (double)SPEED_SOUND_WATER);
00265         //fprintf(stderr, "%4.8f\n", (double)target_frequency);
00266         //fprintf(stderr, "%4.8f\n", (double)SPEED_SOUND_WATER / (double)target_frequency);
00267         //fprintf(stderr, "%4.8f\n", (double)target_wavelength);
00268         //fprintf(stderr, "%4.8f\n", ((double)target_wavelength / 2.0));
00269         //fprintf(stderr, "%4.8f\n", (((double)target_wavelength / 2.0) / SENSOR_SPACING));
00270         //fprintf(stderr, "%4.8f\n", 180.0 / M_PI / 2.0);
00271         //fprintf(stderr, "%4.8f\n", (((double)target_wavelength / 2.0) / SENSOR_SPACING) * 180.0 / M_PI / 2.0);
00272         angle_estimate = (delta_tmp + 5.0 / 6.0 * M_PI ) * (((double)target_wavelength / 2.0) / SENSOR_SPACING) * 180.0 / M_PI / 2.0;
00273         break;
00274       default:
00275         fprintf(stderr, "ERROR: Invalid min_index for phase difference.\n");
00276     }
00277   
00278     //phase_difference *= ((target_wavelength / 2.0) / SENSOR_SPACING) * 180.0 / M_PI / 2.0;
00279     fprintf(stderr, "Detected Angle: %4.4f degrees\n", angle_estimate);
00280 //    weighted_sum *= 2 * bin_predictor.getHalfwidth() + 1;
00281 
00282     //fprintf(stderr, "%8.2f\n", weighted_sum);
00283     //fprintf(stderr, "DC: %10.2f\n", sqrt(pow(fft1[0][0],2.0) + pow(fft1[0][1],2.0)));
00284 
00285 //    // Weighted Gaussian Test
00286 //    if (weighted_sum >= 0.01 * sqrt(pow(fft1[0][0],2.0) + pow(fft1[0][1],2.0)))
00287 //      fprintf(stderr, "Peak detected!\n");
00288 
00289 //    // Ensures communication is successful
00290 //    if (ret < 0)  fprintf(stderr, "status error: %s\n", ch_status_string(ret));
00291 //    fflush(stderr);
00292 
00293     // The current batch is now shifting out on the SPI
00294     // interface. The application can again do some more tasks
00295     // here but this entire loop must finish so that a new
00296     // batch is armed before the current batch completes.
00297     //ch_sleep_ms(1);
00298 //  }
00299 
00300   // Clean up allocated memory
00301   fftw_destroy_plan(fft_plan1);
00302   fftw_destroy_plan(fft_plan2);
00303   fftw_destroy_plan(fft_plan3);
00304 //  fftw_free(data1);
00305 //  fftw_free(data2);
00306 //  fftw_free(data3);
00307   fftw_free(fft1);
00308   fftw_free(fft2);
00309   fftw_free(fft3);
00310   //delete gaussian_weights;
00311 
00312   return 0;
00313 }
Generated on Sun May 8 08:06:37 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3