Porównaj commity

...

5 Commity

Autor SHA1 Wiadomość Data
David Protzman 8cf47662f7 Ignoring all .py files in the examples folder
This is to prevent pre-compiled Python files from being uploaded by mistake
2022-10-13 01:29:01 -04:00
David Protzman 03d29eb84e Updated examples readme 2022-10-13 01:28:54 -04:00
David Protzman ce82d18caf Added deps for gnuradio-filter and gnuradio-blocks 2022-10-13 01:26:30 -04:00
David Protzman 718875173b Added example flow graph that can sync up on DroneID bursts without custom OOT modules 2022-10-13 01:25:50 -04:00
David Protzman b1b2be57c3 Added variance_vector and conj methods 2022-10-12 22:20:30 -04:00
9 zmienionych plików z 1136 dodań i 5 usunięć

Wyświetl plik

@ -1,3 +1,4 @@
cmake-build-debug
build
.idea
examples/*.py

Wyświetl plik

@ -1,3 +1,5 @@
It is considered good practice to add examples in here to demonstrate the
functionality of your OOT module. Python scripts, GRC flow graphs or other
code can go here.
The `autocorrelator.grc` graph is just a demonstration of how to detect DroneID frames without any OOT modules.
It does still require the use of the GNU Radio module as there are functions in the OOT that are needed. Just no
normal OOT blocks required.
This ended up being a lot faster than doing the coding by hand, so huzzah to the GNU Radio devs!

Wyświetl plik

@ -107,6 +107,24 @@ public:
* @return Variance of the complex vector
*/
static float variance(const std::complex<float> * samples, uint32_t sample_count);
/**
* Calculate the variance of a complex vector where the mean is not known to be zero
*
* This function is mostly the same as utils::variance_no_mean but does have to calculate the
* mean value of the input vector and subtract it from each sample, so this will take longer
* @param samples Vector of complex samples
* @return Variance of the complex vector
*/
static float variance_vector(const std::vector<std::complex<float>> & samples);
/**
* Get the conjugate of the provided vector
* @param samples Vector of complex samples
* @return Conjugate of the input sample vector
*/
static std::vector<std::complex<float>> conj_vector(const std::vector<std::complex<float>> & samples);
private:
};

Wyświetl plik

@ -22,7 +22,7 @@ if(NOT dji_droneid_sources)
endif(NOT dji_droneid_sources)
add_library(gnuradio-dji_droneid SHARED ${dji_droneid_sources})
target_link_libraries(gnuradio-dji_droneid gnuradio::gnuradio-runtime gnuradio-fft fftw3)
target_link_libraries(gnuradio-dji_droneid gnuradio::gnuradio-runtime gnuradio-fft fftw3 gnuradio-blocks gnuradio-filter)
target_include_directories(gnuradio-dji_droneid
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include>
PUBLIC $<INSTALL_INTERFACE:include>
@ -92,6 +92,7 @@ include(GrTest)
#include_directories()
# List all files that contain Boost.UTF unit tests here
list(APPEND test_dji_droneid_sources
# Only tests that do not require MATLAB will live here
)
# Anything we need to link to for the unit tests go here
list(APPEND GR_TEST_TARGET_DEPS gnuradio-dji_droneid)

Wyświetl plik

@ -145,6 +145,17 @@ struct TestFixture {
return {output_samples.begin(), output_samples.end()};
}
static std::vector<std::complex<float>> conj(const std::vector<std::complex<float>> & samples) {
matlab_engine->setVariable("samples", factory.createArray({1, samples.size()}, samples.begin(), samples.end()));
matlab_engine->eval(u"samples = single(conj(samples));");
const matlab::data::TypedArray<std::complex<float>> output_samples = matlab_engine->getVariable("samples");
matlab_engine->eval(u"clear samples");
BOOST_REQUIRE_EQUAL(output_samples.getNumberOfElements(), samples.size());
return {output_samples.begin(), output_samples.end()};
}
static std::vector<std::complex<float>> create_test_vector(const uint32_t sample_count) {
matlab_engine->setVariable("sample_count", factory.createScalar(static_cast<double>(sample_count)));
matlab_engine->eval(u"samples = single(complex(randn(1, sample_count), randn(1, sample_count)));");
@ -279,6 +290,20 @@ BOOST_AUTO_TEST_CASE(test_utils__variance) {
}
}
BOOST_AUTO_TEST_CASE(test_utils__variance_vector) {
const uint32_t iters = 100;
const uint32_t length = 10000;
for (auto iter = decltype(iters){0}; iter < iters; iter++) {
const auto samples = create_test_vector(length);
const auto expected = var(samples);
const auto calculated = utils::variance_vector(samples);
BOOST_REQUIRE_CLOSE(expected, calculated, 0.002);
}
}
BOOST_AUTO_TEST_CASE(test_utils__variance_no_mean) {
const uint32_t iters = 100;
const uint32_t length = 10000;
@ -293,6 +318,20 @@ BOOST_AUTO_TEST_CASE(test_utils__variance_no_mean) {
}
}
BOOST_AUTO_TEST_CASE(test_utils__conj_vector) {
const uint32_t iters = 100;
const uint32_t length = 10000;
for (auto iter = decltype(iters){0}; iter < iters; iter++) {
const auto samples = create_test_vector(length);
const auto expected = conj(samples);
const auto calculated = utils::conj_vector(samples);
BOOST_REQUIRE_EQUAL_COLLECTIONS(expected.begin(), expected.end(), calculated.begin(), calculated.end());
}
}
BOOST_AUTO_TEST_SUITE_END()
} /* namespace dji_droneid */

Wyświetl plik

@ -172,5 +172,25 @@ float utils::variance(const std::complex<float> * const samples, const uint32_t
return total / static_cast<float>(sample_count - 1);
}
std::vector<std::complex<float>>
utils::conj_vector(const std::vector<std::complex<float>>& samples)
{
std::vector<std::complex<float>> output(samples.size());
for (auto idx = decltype(samples.size()){0}; idx < samples.size(); idx++) {
const auto & sample = samples[idx];
output[idx] = {
sample.real(),
-sample.imag()
};
}
return output;
}
float utils::variance_vector(const std::vector<std::complex<float>>& samples)
{
return variance(&samples[0], samples.size());
}
} /* namespace dji_droneid */
} /* namespace gr */

Wyświetl plik

@ -40,3 +40,18 @@ static const char* __doc_gr_dji_droneid_utils_create_zc = R"doc()doc";
static const char* __doc_gr_dji_droneid_utils_get_cyclic_prefix_lengths = R"doc()doc";
static const char* __doc_gr_dji_droneid_utils_mean_fast = R"doc()doc";
static const char* __doc_gr_dji_droneid_utils_variance_no_mean = R"doc()doc";
static const char* __doc_gr_dji_droneid_utils_variance = R"doc()doc";
static const char* __doc_gr_dji_droneid_utils_variance_vector = R"doc()doc";
static const char* __doc_gr_dji_droneid_utils_conj_vector = R"doc()doc";

Wyświetl plik

@ -14,7 +14,7 @@
/* BINDTOOL_GEN_AUTOMATIC(0) */
/* BINDTOOL_USE_PYGCCXML(0) */
/* BINDTOOL_HEADER_FILE(utils.h) */
/* BINDTOOL_HEADER_FILE_HASH(341b0421657c63a408a05e68560d4ff8) */
/* BINDTOOL_HEADER_FILE_HASH(2b797448fb8ea6ebcdf63ff38c33eb3c) */
/***********************************************************************************/
#include <pybind11/complex.h>
@ -78,5 +78,36 @@ void bind_utils(py::module& m)
py::arg("sample_rate"),
D(utils, get_cyclic_prefix_lengths))
.def_static("mean_fast",
&utils::mean_fast,
py::arg("samples"),
py::arg("sample_count"),
D(utils, mean_fast))
.def_static("variance_no_mean",
&utils::variance_no_mean,
py::arg("samples"),
py::arg("sample_count"),
D(utils, variance_no_mean))
.def_static("variance",
&utils::variance,
py::arg("samples"),
py::arg("sample_count"),
D(utils, variance))
.def_static("variance_vector",
&utils::variance_vector,
py::arg("samples"),
D(utils, variance_vector))
.def_static(
"conj_vector", &utils::conj_vector, py::arg("samples"), D(utils, conj_vector))
;
}