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