sonar_fft.cpp

00001 #include "sonar_fft.h"
00002 #include <stdio.h>
00003 #include <math.h>
00004 
00005 namespace SeaBee3_Sonar {
00006 
00007 bool isValidADCNumber(int adc_number) {
00008   if (adc_number == 1 || adc_number == 2 || adc_number == 3)
00009     return true;
00010   //fprintf(stderr, "ERROR: %d is not a valid ADC\n", adc_number);
00011   return false;
00012 }
00013 
00014 DataToFFT::DataToFFT(double *data1, double *data2, double *data3, const int len, const double sampling_frequency, const double target_frequency)
00015 : p_data1(data1), p_data2(data2), p_data3(data3), m_fft_length(len),
00016   m_sampling_frequency(sampling_frequency), m_target_frequency(target_frequency),
00017   m_target_bin(m_target_frequency / m_sampling_frequency * m_fft_length) {
00018   p_fft1_output = (double (*)[2]) fftw_malloc(sizeof(fftw_complex) * ( ((len)/2)+1) );
00019   p_fft2_output = (double (*)[2]) fftw_malloc(sizeof(fftw_complex) * ( ((len)/2)+1) );
00020   p_fft3_output = (double (*)[2]) fftw_malloc(sizeof(fftw_complex) * ( ((len)/2)+1) );
00021   
00022   p_adc1_bin_magnitude = NULL;
00023   p_adc2_bin_magnitude = NULL;
00024   p_adc3_bin_magnitude = NULL;
00025   p_adc1_bin_phase = NULL;
00026   p_adc2_bin_phase = NULL;
00027   p_adc3_bin_phase = NULL;
00028   
00029   m_fft_plan1 = fftw_plan_dft_r2c_1d(m_fft_length, p_data1, p_fft1_output, FFTW_ESTIMATE);
00030   m_fft_plan2 = fftw_plan_dft_r2c_1d(m_fft_length, p_data2, p_fft2_output, FFTW_ESTIMATE);
00031   m_fft_plan3 = fftw_plan_dft_r2c_1d(m_fft_length, p_data3, p_fft3_output, FFTW_ESTIMATE);
00032   
00033   fftw_execute(m_fft_plan1);
00034   fftw_execute(m_fft_plan2);
00035   fftw_execute(m_fft_plan3);
00036 }
00037 
00038 DataToFFT::~DataToFFT() {
00039   if (p_fft1_output != NULL)
00040     fftw_free(p_fft1_output);
00041   if (p_fft2_output != NULL)
00042     fftw_free(p_fft2_output);
00043   if (p_fft3_output != NULL)
00044     fftw_free(p_fft3_output);
00045   
00046   if (p_adc1_bin_magnitude != NULL) {
00047     delete p_adc1_bin_magnitude;
00048     p_adc1_bin_magnitude = NULL;
00049   }
00050   if (p_adc2_bin_magnitude != NULL) {
00051     delete p_adc2_bin_magnitude;
00052     p_adc2_bin_magnitude = NULL;
00053   }
00054   if (p_adc3_bin_magnitude != NULL) {
00055     delete p_adc3_bin_magnitude;
00056     p_adc3_bin_magnitude = NULL;
00057   }
00058   
00059   if (p_adc1_bin_phase != NULL) {
00060     delete p_adc1_bin_phase;
00061     p_adc1_bin_phase = NULL;
00062   }
00063   if (p_adc2_bin_phase != NULL) {
00064     delete p_adc2_bin_phase;
00065     p_adc2_bin_phase = NULL;
00066   }
00067   if (p_adc3_bin_phase != NULL) {
00068     delete p_adc3_bin_phase;
00069     p_adc3_bin_phase = NULL;
00070   }
00071   
00072   fftw_destroy_plan(m_fft_plan1);
00073   fftw_destroy_plan(m_fft_plan2);
00074   fftw_destroy_plan(m_fft_plan3);
00075 }
00076 
00077 double DataToFFT::getPhase(int adc_number) {
00078   if (!isValidADCNumber(adc_number))
00079     return -10.0;
00080   
00081   switch (adc_number) {
00082     case 1:
00083       if (p_adc1_bin_phase == NULL) {
00084         p_adc1_bin_phase = new double(0.0);
00085         fprintf(stderr, "Target Bin: %d\n", m_target_bin);
00086         fprintf(stderr, "%10.5f, %10.5f\n", p_fft1_output[m_target_bin][1], p_fft1_output[m_target_bin][0]);
00087         *p_adc1_bin_phase = atan2(p_fft1_output[m_target_bin][1], p_fft1_output[m_target_bin][0]);
00088       }
00089       return *p_adc1_bin_phase;
00090       break;
00091     case 2:
00092       if (p_adc2_bin_phase == NULL) {
00093         p_adc2_bin_phase = new double(0.0);
00094         fprintf(stderr, "%10.5f, %10.5f\n", p_fft2_output[m_target_bin][1], p_fft2_output[m_target_bin][0]);
00095         *p_adc2_bin_phase = atan2(p_fft2_output[m_target_bin][1], p_fft2_output[m_target_bin][0]);
00096       }
00097       return *p_adc2_bin_phase;
00098       break;
00099     case 3:
00100       if (p_adc3_bin_phase == NULL) {
00101         p_adc3_bin_phase = new double(0.0);
00102         fprintf(stderr, "%10.5f, %10.5f\n", p_fft3_output[m_target_bin][1], p_fft3_output[m_target_bin][0]);
00103         *p_adc3_bin_phase = atan2(p_fft3_output[m_target_bin][1], p_fft3_output[m_target_bin][0]);
00104       }
00105       return *p_adc3_bin_phase;
00106       break;
00107   }
00108   
00109   // Values outside of [-M_PI, M_PI) are not possible, thus -10 signals an error
00110   return -10.0;
00111 }
00112 
00113 double DataToFFT::getMagnitude(int adc_number) {
00114   if (!isValidADCNumber(adc_number))
00115     return -1.0;
00116   
00117   switch (adc_number) {
00118     case 1:
00119       if (p_adc1_bin_magnitude == NULL) {
00120         p_adc1_bin_magnitude = new double(0.0);
00121         *p_adc1_bin_magnitude = p_fft1_output[m_target_bin][0] * p_fft1_output[m_target_bin][0] +
00122                                 p_fft1_output[m_target_bin][1] * p_fft1_output[m_target_bin][1];
00123       }
00124       return *p_adc1_bin_magnitude;
00125       break;
00126     case 2:
00127       if (p_adc2_bin_magnitude == NULL) {
00128         p_adc2_bin_magnitude = new double(0.0);
00129         *p_adc2_bin_magnitude = p_fft2_output[m_target_bin][0] * p_fft2_output[m_target_bin][0] +
00130                                 p_fft2_output[m_target_bin][1] * p_fft2_output[m_target_bin][1];
00131       }
00132       return *p_adc2_bin_magnitude;
00133       break;
00134     case 3:
00135       if (p_adc3_bin_magnitude == NULL) {
00136         p_adc3_bin_magnitude = new double(0.0);
00137         *p_adc3_bin_magnitude = p_fft3_output[m_target_bin][0] * p_fft3_output[m_target_bin][0] +
00138                                 p_fft3_output[m_target_bin][1] * p_fft3_output[m_target_bin][1];
00139       }
00140       return *p_adc1_bin_magnitude;
00141       break;
00142   }
00143   
00144   // Negative values are not possible, thus used as error signal
00145   return -1.0;
00146 }
00147 
00148 int DataToFFT::getTargetBin() {
00149   return m_target_bin;
00150 }
00151 
00152 void DataToFFT::Reset() {
00153   fftw_execute(m_fft_plan1);
00154   fftw_execute(m_fft_plan2);
00155   fftw_execute(m_fft_plan3);
00156   
00157   if (p_adc1_bin_magnitude != NULL) {
00158     delete p_adc1_bin_magnitude;
00159     p_adc1_bin_magnitude = NULL;
00160   }
00161   if (p_adc2_bin_magnitude != NULL) {
00162     delete p_adc2_bin_magnitude;
00163     p_adc2_bin_magnitude = NULL;
00164   }
00165   if (p_adc3_bin_magnitude != NULL) {
00166     delete p_adc3_bin_magnitude;
00167     p_adc3_bin_magnitude = NULL;
00168   }
00169   
00170   if (p_adc1_bin_phase != NULL) {
00171     delete p_adc1_bin_phase;
00172     p_adc1_bin_phase = NULL;
00173   }
00174   if (p_adc2_bin_phase != NULL) {
00175     delete p_adc2_bin_phase;
00176     p_adc2_bin_phase = NULL;
00177   }
00178   if (p_adc3_bin_phase != NULL) {
00179     delete p_adc3_bin_phase;
00180     p_adc3_bin_phase = NULL;
00181   }
00182 }
00183 
00184 
00185 } // End namespace SeaBee3_sonar
00186 
Generated on Sun May 8 08:06:36 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3