From 7447edc62bca13e828676293cda9003835d7cb94 Mon Sep 17 00:00:00 2001 From: 30hours Date: Sat, 4 May 2024 02:41:33 +0000 Subject: [PATCH] Amend code style in Ambiguity and refactor ambiguity tests --- CMakeLists.txt | 33 ++- src/blah2.cpp | 2 +- src/process/ambiguity/Ambiguity.cpp | 199 +++++++++--------- src/process/ambiguity/Ambiguity.h | 76 +++---- src/process/meta/HammingNumber.cpp | 56 ++--- src/process/meta/HammingNumber.h | 4 +- test/README.md | 5 +- test/data/README.md | 9 + test/unit/process/ambiguity/TestAmbiguity.cpp | 38 ++-- test/unit/process/meta/TestHammingNumber.cpp | 18 ++ 10 files changed, 236 insertions(+), 204 deletions(-) create mode 100644 test/data/README.md create mode 100644 test/unit/process/meta/TestHammingNumber.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ff09b07..1482a5f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,13 +18,12 @@ find_package(Catch2 CONFIG REQUIRED) set(CMAKE_PREFIX_PATH "/opt/uhd" ${CMAKE_PREFIX_PATH}) find_package(UHD "4.6.0.0" CONFIG REQUIRED) -# TODO: when release CI is finished, don't use these dirs, install target should go to prod SET (PROJECT_ROOT "${PROJECT_SOURCE_DIR}") SET (CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_ROOT}/bin") SET (PROJECT_BINARY_TEST_DIR "${PROJECT_ROOT}/bin/test") SET (PROJECT_BINARY_TEST_UNIT_DIR "${PROJECT_BINARY_TEST_DIR}/unit") -SET (PROJECT_BINARY_TEST_UNIT_DIR "${PROJECT_BINARY_TEST_DIR}/functional") -SET (PROJECT_BINARY_TEST_UNIT_DIR "${PROJECT_BINARY_TEST_DIR}/comparison") +SET (PROJECT_BINARY_TEST_FUNCTIONAL_DIR "${PROJECT_BINARY_TEST_DIR}/functional") +SET (PROJECT_BINARY_TEST_COMPARISON_DIR "${PROJECT_BINARY_TEST_DIR}/comparison") MESSAGE ("Binary path: ${PROJECT_BINARY_DIR}") MESSAGE ("Binary test path: ${PROJECT_BINARY_TEST_DIR}") @@ -37,6 +36,7 @@ add_library(sdrplay /usr/local/include/sdrplay_api.h) set_target_properties(sdrplay PROPERTIES LINKER_LANGUAGE C) target_link_libraries(sdrplay PUBLIC /usr/local/lib/libsdrplay_api.so.3.14) +# TODO: Move to separate src/CMakeLists.txt add_executable(blah2 src/blah2.cpp src/capture/Capture.cpp @@ -80,8 +80,13 @@ add_executable(testAmbiguity src/data/IqData.cpp src/data/Map.cpp src/process/ambiguity/Ambiguity.cpp - src/process/meta/HammingNumber.cpp) -target_link_libraries(testAmbiguity PRIVATE Catch2::Catch2WithMain fftw3 fftw3_threads) + src/process/meta/HammingNumber.cpp +) +target_link_libraries(testAmbiguity PRIVATE + Catch2::Catch2WithMain + fftw3 + fftw3_threads +) set_target_properties(testAmbiguity PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_TEST_UNIT_DIR}") @@ -89,10 +94,24 @@ add_executable(testTracker test/unit/process/tracker/TestTracker.cpp src/data/Detection.cpp src/data/Track.cpp - src/process/tracker/Tracker.cpp) -target_link_libraries(testTracker PRIVATE Catch2::Catch2WithMain) + src/process/tracker/Tracker.cpp +) +target_link_libraries(testTracker PRIVATE + Catch2::Catch2WithMain +) set_target_properties(testTracker PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_TEST_UNIT_DIR}") +add_executable(testHammingNumber + test/unit/process/meta/TestHammingNumber.cpp + src/process/meta/HammingNumber.cpp +) +target_link_libraries(testHammingNumber PRIVATE + Catch2::Catch2WithMain +) +set_target_properties(testHammingNumber PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_TEST_UNIT_DIR}") + +# TODO: Unsure if will be using CTest. add_test(NAME testAmbiguity COMMAND testAmbiguity) add_test(NAME testTracker COMMAND testTracker) diff --git a/src/blah2.cpp b/src/blah2.cpp index fd2245f..affa499 100644 --- a/src/blah2.cpp +++ b/src/blah2.cpp @@ -178,7 +178,7 @@ int main(int argc, char **argv) tree["process"]["tracker"]["initiate"]["maxAcc"] >> maxAcc; rangeRes = (double)Constants::c/fs; lambda = (double)Constants::c/fc; - Tracker *tracker = new Tracker(m, n, nDelete, ambiguity->cpi_length_seconds(), maxAcc, rangeRes, lambda); + Tracker *tracker = new Tracker(m, n, nDelete, ambiguity->get_cpi(), maxAcc, rangeRes, lambda); // setup process spectrum analyser double spectrumBandwidth = 2000; diff --git a/src/process/ambiguity/Ambiguity.cpp b/src/process/ambiguity/Ambiguity.cpp index 6a3d683..2d1a4a7 100644 --- a/src/process/ambiguity/Ambiguity.cpp +++ b/src/process/ambiguity/Ambiguity.cpp @@ -8,183 +8,184 @@ #include // constructor -Ambiguity::Ambiguity(int32_t delayMin, int32_t delayMax, int32_t dopplerMin, int32_t dopplerMax, uint32_t fs, uint32_t n, bool roundHamming) - : delayMin_{delayMin} - , delayMax_{delayMax} - , dopplerMin_{dopplerMin} - , dopplerMax_{dopplerMax} - , fs_{fs} - , nSamples_{n} - , nDelayBins_{static_cast(delayMax - delayMin + 1)} // If delayMin > delayMax = trouble, what's the exception policy? - , dopplerMiddle_{(dopplerMin_ + dopplerMax_) / 2.0} +Ambiguity::Ambiguity(int32_t _delayMin, int32_t _delayMax, int32_t _dopplerMin, int32_t _dopplerMax, uint32_t _fs, uint32_t _n, bool _roundHamming) + : delayMin{_delayMin} + , delayMax{_delayMax} + , dopplerMin{_dopplerMin} + , dopplerMax{_dopplerMax} + , fs{_fs} + , nSamples{_n} + , nDelayBins{static_cast(_delayMax - _delayMin + 1)} // If delayMin > delayMax = trouble, what's the exception policy? + , dopplerMiddle{(_dopplerMin + _dopplerMax) / 2.0} { // doppler calculations std::deque doppler; - double resolutionDoppler = 1.0 / (static_cast(n) / static_cast(fs)); - doppler.push_back(dopplerMiddle_); + double resolutionDoppler = 1.0 / (static_cast(_n) / static_cast(_fs)); + doppler.push_back(dopplerMiddle); int i = 1; - while (dopplerMiddle_ + (i * resolutionDoppler) <= dopplerMax) + while (dopplerMiddle + (i * resolutionDoppler) <= dopplerMax) { - doppler.push_back(dopplerMiddle_ + (i * resolutionDoppler)); - doppler.push_front(dopplerMiddle_ - (i * resolutionDoppler)); + doppler.push_back(dopplerMiddle + (i * resolutionDoppler)); + doppler.push_front(dopplerMiddle - (i * resolutionDoppler)); i++; } - nDopplerBins_ = doppler.size(); + nDopplerBins = doppler.size(); // batches constants - nCorr_ = n / nDopplerBins_; - cpi_ = (static_cast(nCorr_) * nDopplerBins_) / fs; + nCorr = _n / nDopplerBins; + cpi = (static_cast(nCorr) * nDopplerBins) / fs; // update doppler bins to true cpi time - resolutionDoppler = 1.0 / cpi_; + resolutionDoppler = 1.0 / cpi; // create ambiguity map - map_ = std::make_unique>(nDopplerBins_, nDelayBins_); + map = std::make_unique>(nDopplerBins, nDelayBins); // delay calculations - map_->delay.resize(nDelayBins_); - std::iota(map_->delay.begin(), map_->delay.end(), delayMin_); + map->delay.resize(nDelayBins); + std::iota(map->delay.begin(), map->delay.end(), delayMin); - map_->doppler.push_front(dopplerMiddle_); + map->doppler.push_front(dopplerMiddle); i = 1; - while (map_->doppler.size() < nDopplerBins_) + while (map->doppler.size() < nDopplerBins) { - map_->doppler.push_back(dopplerMiddle_ + (i * resolutionDoppler)); - map_->doppler.push_front(dopplerMiddle_ - (i * resolutionDoppler)); + map->doppler.push_back(dopplerMiddle + (i * resolutionDoppler)); + map->doppler.push_front(dopplerMiddle - (i * resolutionDoppler)); i++; } // other setup - nfft_ = 2 * nCorr_ - 1; - if (roundHamming) { - nfft_ = next_hamming(nfft_); + nfft = 2 * nCorr - 1; + if (_roundHamming) { + nfft = next_hamming(nfft); } - dataCorr_.resize(2 * nDelayBins_ + 1); + dataCorr.resize(2 * nDelayBins + 1); // compute FFTW plans in constructor - dataXi_.resize(nfft_); - dataYi_.resize(nfft_); - dataZi_.resize(nfft_); - dataDoppler_.resize(nfft_); - fftXi_ = fftw_plan_dft_1d(nfft_, reinterpret_cast(dataXi_.data()), - reinterpret_cast(dataXi_.data()), FFTW_FORWARD, FFTW_ESTIMATE); - fftYi_ = fftw_plan_dft_1d(nfft_, reinterpret_cast(dataYi_.data()), - reinterpret_cast(dataYi_.data()), FFTW_FORWARD, FFTW_ESTIMATE); - fftZi_ = fftw_plan_dft_1d(nfft_, reinterpret_cast(dataZi_.data()), - reinterpret_cast(dataZi_.data()), FFTW_BACKWARD, FFTW_ESTIMATE); - fftDoppler_ = fftw_plan_dft_1d(nDopplerBins_, reinterpret_cast(dataDoppler_.data()), - reinterpret_cast(dataDoppler_.data()), FFTW_FORWARD, FFTW_ESTIMATE); + dataXi.resize(nfft); + dataYi.resize(nfft); + dataZi.resize(nfft); + dataDoppler.resize(nfft); + fftXi = fftw_plan_dft_1d(nfft, reinterpret_cast(dataXi.data()), + reinterpret_cast(dataXi.data()), FFTW_FORWARD, FFTW_ESTIMATE); + fftYi = fftw_plan_dft_1d(nfft, reinterpret_cast(dataYi.data()), + reinterpret_cast(dataYi.data()), FFTW_FORWARD, FFTW_ESTIMATE); + fftZi = fftw_plan_dft_1d(nfft, reinterpret_cast(dataZi.data()), + reinterpret_cast(dataZi.data()), FFTW_BACKWARD, FFTW_ESTIMATE); + fftDoppler = fftw_plan_dft_1d(nDopplerBins, reinterpret_cast(dataDoppler.data()), + reinterpret_cast(dataDoppler.data()), FFTW_FORWARD, FFTW_ESTIMATE); } Ambiguity::~Ambiguity() { - fftw_destroy_plan(fftXi_); - fftw_destroy_plan(fftYi_); - fftw_destroy_plan(fftZi_); - fftw_destroy_plan(fftDoppler_); + fftw_destroy_plan(fftXi); + fftw_destroy_plan(fftYi); + fftw_destroy_plan(fftZi); + fftw_destroy_plan(fftDoppler); } Map> *Ambiguity::process(IqData *x, IqData *y) { - using Timer = std::chrono::steady_clock; - auto t0{Timer::now()}; - Timer::duration range_fft_dur{}; - // shift reference if not 0 centered - if (dopplerMiddle_ != 0) + if (dopplerMiddle != 0) { std::complex j = {0, 1}; for (int i = 0; i < x->get_length(); i++) { - x->push_back(x->pop_front() * std::exp(1.0 * j * 2.0 * M_PI * dopplerMiddle_ * ((double)i / fs_))); + x->push_back(x->pop_front() * std::exp(1.0 * j * 2.0 * M_PI * dopplerMiddle * ((double)i / fs))); } } // range processing - for (int i = 0; i < nDopplerBins_; i++) + for (int i = 0; i < nDopplerBins; i++) { - for (int j = 0; j < nCorr_; j++) + for (int j = 0; j < nCorr; j++) { - dataXi_[j] = x->pop_front(); - dataYi_[j] = y->pop_front(); + dataXi[j] = x->pop_front(); + dataYi[j] = y->pop_front(); } - for (int j = nCorr_; j < nfft_; j++) + for (int j = nCorr; j < nfft; j++) { - dataXi_[j] = {0, 0}; - dataYi_[j] = {0, 0}; + dataXi[j] = {0, 0}; + dataYi[j] = {0, 0}; } - auto t1{Timer::now()}; - fftw_execute(fftXi_); - fftw_execute(fftYi_); - range_fft_dur += Timer::now() - t1; + fftw_execute(fftXi); + fftw_execute(fftYi); // compute correlation - for (int j = 0; j < nfft_; j++) + for (int j = 0; j < nfft; j++) { - dataZi_[j] = (dataYi_[j] * std::conj(dataXi_[j])) / (double)nfft_; + dataZi[j] = (dataYi[j] * std::conj(dataXi[j])) / (double)nfft; } - t1 = Timer::now(); - fftw_execute(fftZi_); - range_fft_dur += Timer::now() - t1; + fftw_execute(fftZi); // extract center of corr - for (int j = 0; j < nDelayBins_; j++) + for (int j = 0; j < nDelayBins; j++) { - dataCorr_[j] = dataZi_[nfft_ - nDelayBins_ + j]; + dataCorr[j] = dataZi[nfft - nDelayBins + j]; } - for (int j = 0; j < nDelayBins_ + 1; j++) + for (int j = 0; j < nDelayBins + 1; j++) { - dataCorr_[j + nDelayBins_] = dataZi_[j]; + dataCorr[j + nDelayBins] = dataZi[j]; } // cast from std::complex to std::vector - corr_.clear(); - for (int j = 0; j < nDelayBins_; j++) + corr.clear(); + for (int j = 0; j < nDelayBins; j++) { - corr_.push_back(dataCorr_[nDelayBins_ + delayMin_ + j - 1 + 1]); + corr.push_back(dataCorr[nDelayBins + delayMin + j - 1 + 1]); } - map_->set_row(i, corr_); + map->set_row(i, corr); } // doppler processing - auto t1{Timer::now()}; - for (int i = 0; i < nDelayBins_; i++) + for (int i = 0; i < nDelayBins; i++) { - delayProfile_ = map_->get_col(i); - for (int j = 0; j < nDopplerBins_; j++) + delayProfile = map->get_col(i); + for (int j = 0; j < nDopplerBins; j++) { - dataDoppler_[j] = {delayProfile_[j].real(), delayProfile_[j].imag()}; + dataDoppler[j] = {delayProfile[j].real(), delayProfile[j].imag()}; } - fftw_execute(fftDoppler_); + fftw_execute(fftDoppler); - corr_.clear(); - for (int j = 0; j < nDopplerBins_; j++) + corr.clear(); + for (int j = 0; j < nDopplerBins; j++) { - corr_.push_back(dataDoppler_[(j + int(nDopplerBins_ / 2) + 1) % nDopplerBins_]); + corr.push_back(dataDoppler[(j + int(nDopplerBins / 2) + 1) % nDopplerBins]); } - map_->set_col(i, corr_); + map->set_col(i, corr); } - auto to_ms = [] (const Timer::duration& dur) { - return std::chrono::duration_cast>(dur).count(); - }; - - latest_performance_.process_time_ms = to_ms(Timer::now() - t0); - latest_performance_.doppler_fft_time_ms = to_ms(Timer::now() - t1); - latest_performance_.range_fft_time_ms = to_ms(range_fft_dur); - - return map_.get(); + return map.get(); } -std::ostream& operator<<(std::ostream& str, const Ambiguity::PerformanceStats& stats) { - return str << "Total time: " << stats.process_time_ms << "ms\n" << - "Range FFT time: " << stats.range_fft_time_ms << "ms\n" << - "Doppler FFT time: " << stats.doppler_fft_time_ms << "ms"; -} \ No newline at end of file +double Ambiguity::get_doppler_middle() const { + return dopplerMiddle; +} + +uint16_t Ambiguity::get_n_delay_bins() const { + return nDelayBins; +} + +uint16_t Ambiguity::get_n_doppler_bins() const { + return nDopplerBins; +} + +uint16_t Ambiguity::get_n_corr() const { + return nCorr; +} + +double Ambiguity::get_cpi() const { + return cpi; +} + +uint32_t Ambiguity::get_nfft() const { + return nfft; +} diff --git a/src/process/ambiguity/Ambiguity.h b/src/process/ambiguity/Ambiguity.h index 86ddcad..d520b09 100644 --- a/src/process/ambiguity/Ambiguity.h +++ b/src/process/ambiguity/Ambiguity.h @@ -5,8 +5,7 @@ /// See Fundamentals of Radar Signal Processing (Richards) for more on the pulse-Doppler processing method. /// @author 30hours /// @todo Ambiguity maps are still offset by 1 bin. - -#pragma once +/// @todo Write a performance test for hamming assisted ambiguity processing. #include "data/IqData.h" #include "data/Map.h" @@ -22,13 +21,6 @@ public: using Complex = std::complex; - struct PerformanceStats { - double process_time_ms{0}; - double range_fft_time_ms{0}; - double doppler_fft_time_ms{0}; - }; - - /// @brief Constructor. /// @param delayMin Minimum delay (bins). /// @param delayMax Maximum delay (bins). @@ -36,7 +28,7 @@ public: /// @param dopplerMax Maximum Doppler (Hz). /// @param fs Sampling frequency (Hz). /// @param n Number of samples. - /// @param roundHamming Round the correlation FFT length to a Hamming number for performance + /// @param roundHamming Round the correlation FFT length to a Hamming number for performance. /// @return The object. Ambiguity(int32_t delayMin, int32_t delayMax, int32_t dopplerMin, int32_t dopplerMax, uint32_t fs, uint32_t n, bool roundHamming = false); @@ -50,81 +42,77 @@ public: /// @return Ambiguity map data of IQ samples. Map *process(IqData *x, IqData *y); - double doppler_middle() const { return dopplerMiddle_; } + double get_doppler_middle() const; - uint16_t delay_bin_count() const { return nDelayBins_; } + uint16_t get_n_delay_bins() const; - uint16_t doppler_bin_count() const { return nDopplerBins_; } + uint16_t get_n_doppler_bins() const; - uint16_t corr_samples_per_pulse() const { return nCorr_; } + uint16_t get_n_corr() const; - double cpi_length_seconds() const { return cpi_; } + double get_cpi() const; - uint32_t fft_bin_count() const { return nfft_; } + uint32_t get_nfft() const; - PerformanceStats get_latest_performance() const { return latest_performance_; } private: /// @brief Minimum delay (bins). - int32_t delayMin_; + int32_t delayMin; /// @brief Maximum delay (bins). - int32_t delayMax_; + int32_t delayMax; /// @brief Minimum Doppler (Hz). - int32_t dopplerMin_; + int32_t dopplerMin; /// @brief Maximum Doppler (Hz). - int32_t dopplerMax_; + int32_t dopplerMax; /// @brief Sampling frequency (Hz). - uint32_t fs_; + uint32_t fs; /// @brief Number of samples. - uint32_t nSamples_; + uint32_t nSamples; /// @brief Center of Doppler bins (Hz). - double dopplerMiddle_; + double dopplerMiddle; /// @brief Number of delay bins. - uint16_t nDelayBins_; + uint16_t nDelayBins; /// @brief Number of Doppler bins. - uint16_t nDopplerBins_; + uint16_t nDopplerBins; /// @brief Number of correlation samples per pulse. - uint16_t nCorr_; + uint16_t nCorr; /// @brief True CPI time (s). - double cpi_; + double cpi; /// @brief FFTW plans for ambiguity processing. - fftw_plan fftXi_; - fftw_plan fftYi_; - fftw_plan fftZi_; - fftw_plan fftDoppler_; + fftw_plan fftXi; + fftw_plan fftYi; + fftw_plan fftZi; + fftw_plan fftDoppler; /// @brief FFTW storage for ambiguity processing. /// @{ - std::vector dataXi_; - std::vector dataYi_; - std::vector dataZi_; - std::vector dataCorr_; - std::vector dataDoppler_; + std::vector dataXi; + std::vector dataYi; + std::vector dataZi; + std::vector dataCorr; + std::vector dataDoppler; /// @} /// @brief Number of samples to perform FFT per pulse. - uint32_t nfft_; + uint32_t nfft; /// @brief Vector storage for ambiguity processing /// @{ - std::vector corr_; - std::vector delayProfile_; + std::vector corr; + std::vector delayProfile; /// @} /// @brief Map to store result. - std::unique_ptr> map_; + std::unique_ptr> map; - PerformanceStats latest_performance_; }; - -std::ostream& operator<<(std::ostream& str, const Ambiguity::PerformanceStats& stats); \ No newline at end of file diff --git a/src/process/meta/HammingNumber.cpp b/src/process/meta/HammingNumber.cpp index 5621159..a67adb4 100644 --- a/src/process/meta/HammingNumber.cpp +++ b/src/process/meta/HammingNumber.cpp @@ -1,40 +1,48 @@ #include "HammingNumber.h" -bool HammingNumber::operator!=(const HammingNumber &other) const { - return true; +bool HammingNumber::operator!=(const HammingNumber &other) const +{ + return true; } -HammingNumber HammingNumber::begin() const { - return *this; +HammingNumber HammingNumber::begin() const +{ + return *this; } -HammingNumber HammingNumber::end() const { - return *this; +HammingNumber HammingNumber::end() const +{ + return *this; } -unsigned int HammingNumber::operator*() const { - return _x.back(); +unsigned int HammingNumber::operator*() const +{ + return x.back(); } HammingNumber::HammingNumber(const std::vector &pfs) - : _H(pfs), _hp(pfs.size(), 0), _hv({pfs}), _x({1}) {} + : H(pfs), hp(pfs.size(), 0), hv({pfs}), x({1}) {} -const HammingNumber &HammingNumber::operator++() { - for (int i = 0; i < _H.size(); i++) - for (; _hv[i] <= _x.back(); _hv[i] = _x[++_hp[i]] * _H[i]) - ; - _x.push_back(_hv[0]); - for (int i = 1; i < _H.size(); i++) - if (_hv[i] < _x.back()) - _x.back() = _hv[i]; - return *this; +const HammingNumber &HammingNumber::operator++() +{ + for (int i = 0; i < H.size(); i++) + for (; hv[i] <= x.back(); hv[i] = x[++hp[i]] * H[i]) + ; + x.push_back(hv[0]); + for (int i = 1; i < H.size(); i++) + if (hv[i] < x.back()) + x.back() = hv[i]; + return *this; } -uint32_t next_hamming(uint32_t value) { - for (auto i : HammingNumber({2, 3, 5})) { - if (i > value) { - return i; - } +uint32_t next_hamming(uint32_t value) +{ + for (auto i : HammingNumber({2, 3, 5})) + { + if (i > value) + { + return i; } - return 0; + } + return 0; } diff --git a/src/process/meta/HammingNumber.h b/src/process/meta/HammingNumber.h index 9f511ac..9002515 100644 --- a/src/process/meta/HammingNumber.h +++ b/src/process/meta/HammingNumber.h @@ -3,7 +3,6 @@ /// @brief Hamming number generator /// @author Nigel Galloway /// @cite https://rosettacode.org/wiki/Hamming_numbers -/// @todo Can this be done with constexpr??? #ifndef HAMMING_GENERATOR_H #define HAMMING_GENERATOR_H @@ -15,7 +14,7 @@ class HammingNumber { private: - std::vector _H, _hp, _hv, _x; + std::vector H, hp, hv, x; public: bool operator!=(const HammingNumber &other) const; @@ -24,6 +23,7 @@ class HammingNumber unsigned int operator*() const; HammingNumber(const std::vector &pfs); const HammingNumber &operator++(); + }; /// @brief Calculate the next 5-smooth Hamming Number larger than value diff --git a/test/README.md b/test/README.md index 9767541..1073daa 100644 --- a/test/README.md +++ b/test/README.md @@ -12,7 +12,7 @@ The test files are split across directories defined by the type of test. - **Unit tests** will test the class in isolation. The directory structure mirrors *src*. - **Functional tests** will test that expected outputs are achieved from defined inputs. An example would be checking the program turns a specific IQ data set to a specific delay-Doppler map. This test category will rely on golden data. -- **Comparison tests** will compare different methods of performing the same task. An example would be comparing 2 methods of clutter filtering. Metrics to be compared may include time and performance. Note there is no pass/fail criteria for comparison tests - this is purely for information. +- **Comparison tests** will compare different methods of performing the same task. An example would be comparing 2 methods of clutter filtering. Metrics to be compared may include time and performance. Note there is no specific pass/fail criteria for comparison tests - this is purely for information. A comparison test will pass if executed successfully. Any comparison testing on input parameters for a single class will be handled in the unit test. ## Usage @@ -40,4 +40,7 @@ sudo docker exec -it blah2 /blah2/bin/test/comparison/testComparison ``` sudo docker exec -it blah2 /blah2/bin/test/runall.sh +sudo docker exec -it blah2 /blah2/bin/test/unit/runall.sh +sudo docker exec -it blah2 /blah2/bin/test/functional/runall.sh +sudo docker exec -it blah2 /blah2/bin/test/comparison/runall.sh ``` \ No newline at end of file diff --git a/test/data/README.md b/test/data/README.md new file mode 100644 index 0000000..f824d8a --- /dev/null +++ b/test/data/README.md @@ -0,0 +1,9 @@ +# blah2 Test Data + +A set of golden data used for testing. + +## Log + +| File | Description | +| ------------- | ------------- | +| `todo.rspduo.iq` | Stores 1 CPI of IQ data for the SDRPlay RspDuo. | diff --git a/test/unit/process/ambiguity/TestAmbiguity.cpp b/test/unit/process/ambiguity/TestAmbiguity.cpp index 8de6d0d..8e6af49 100644 --- a/test/unit/process/ambiguity/TestAmbiguity.cpp +++ b/test/unit/process/ambiguity/TestAmbiguity.cpp @@ -84,12 +84,12 @@ TEST_CASE("Constructor", "[constructor]") Ambiguity ambiguity(delayMin, delayMax, dopplerMin, dopplerMax, fs, nSamples); - CHECK_THAT(ambiguity.cpi_length_seconds(), Catch::Matchers::WithinAbs(tCpi, 0.02)); - CHECK(ambiguity.doppler_middle() == 0); - CHECK(ambiguity.corr_samples_per_pulse() == 3322); - CHECK(ambiguity.delay_bin_count() == delayMax + std::abs(delayMin) + 1); - CHECK(ambiguity.doppler_bin_count() == 301); - CHECK(ambiguity.fft_bin_count() == 6643); + CHECK_THAT(ambiguity.get_cpi(), Catch::Matchers::WithinAbs(tCpi, 0.02)); + CHECK(ambiguity.get_doppler_middle() == 0); + CHECK(ambiguity.get_n_corr() == 3322); + CHECK(ambiguity.get_n_delay_bins() == delayMax + std::abs(delayMin) + 1); + CHECK(ambiguity.get_n_doppler_bins() == 301); + CHECK(ambiguity.get_nfft() == 6643); } /// @brief Test constructor with rounded Hamming number FFT length. @@ -107,12 +107,12 @@ TEST_CASE("Constructor_Round", "[constructor]") Ambiguity ambiguity(delayMin, delayMax, dopplerMin, dopplerMax, fs, nSamples, true); - CHECK_THAT(ambiguity.cpi_length_seconds(), Catch::Matchers::WithinAbs(tCpi, 0.02)); - CHECK(ambiguity.doppler_middle() == 0); - CHECK(ambiguity.corr_samples_per_pulse() == 3322); - CHECK(ambiguity.delay_bin_count() == delayMax + std::abs(delayMin) + 1); - CHECK(ambiguity.doppler_bin_count() == 301); - CHECK(ambiguity.fft_bin_count() == 6750); + CHECK_THAT(ambiguity.get_cpi(), Catch::Matchers::WithinAbs(tCpi, 0.02)); + CHECK(ambiguity.get_doppler_middle() == 0); + CHECK(ambiguity.get_n_corr() == 3322); + CHECK(ambiguity.get_n_delay_bins() == delayMax + std::abs(delayMin) + 1); + CHECK(ambiguity.get_n_doppler_bins() == 301); + CHECK(ambiguity.get_nfft() == 6750); } /// @brief Test simple ambiguity processing. @@ -141,9 +141,6 @@ TEST_CASE("Process_Simple", "[process]") map->set_metrics(); CHECK(map->maxPower > 0.0); CHECK(map->noisePower > 0.0); - - std::cout << "Process_Simple with" << (round_hamming ? " hamming\n" : "out hamming\n") - << ambiguity.get_latest_performance() << "\n-----------" << std::endl; } /// @brief Test processing from a file. @@ -178,15 +175,4 @@ TEST_CASE("Process_File", "[process]") map->set_metrics(); CHECK_THAT(map->maxPower, Catch::Matchers::WithinAbs(30.2816, 0.001)); CHECK_THAT(map->noisePower, Catch::Matchers::WithinAbs(76.918, 0.001)); - - std::cout << "Process_File with" << (round_hamming ? " hamming\n" : "out hamming\n") - << ambiguity.get_latest_performance() << "\n-----------" << std::endl; } - -/// @brief Test Hamming number calculation. -TEST_CASE("Next_Hamming", "[hamming]") -{ - CHECK(next_hamming(104) == 108); - CHECK(next_hamming(3322) == 3375); - CHECK(next_hamming(19043) == 19200); -} \ No newline at end of file diff --git a/test/unit/process/meta/TestHammingNumber.cpp b/test/unit/process/meta/TestHammingNumber.cpp new file mode 100644 index 0000000..4ae58e5 --- /dev/null +++ b/test/unit/process/meta/TestHammingNumber.cpp @@ -0,0 +1,18 @@ +/// @file TestHammingNumber.cpp +/// @brief Unit test for HammingNumber.cpp +/// @author 30hours +/// @author Dan G + +#include +#include +#include + +#include "process/meta/HammingNumber.h" + +/// @brief Test Hamming number calculation. +TEST_CASE("Next_Hamming", "[hamming]") +{ + CHECK(next_hamming(104) == 108); + CHECK(next_hamming(3322) == 3375); + CHECK(next_hamming(19043) == 19200); +} \ No newline at end of file