Add doxygen comments

This commit is contained in:
30hours 2023-05-20 13:10:55 +09:30
parent d432945c0b
commit 2d325d257d
14 changed files with 2963 additions and 87 deletions

4
.gitignore vendored
View file

@ -4,3 +4,7 @@ bin/*
!bin/README.md !bin/README.md
*.a *.a
*.so *.so
.vscode/
doc/html/*
doc/latex/*
!doc/html/example.png

View file

@ -4,7 +4,7 @@ MAINTAINER 30hours <nathan@30hours.dev>
WORKDIR blah2 WORKDIR blah2
ADD lib lib ADD lib lib
RUN apt-get update RUN apt-get update
RUN apt-get install -y g++ make cmake libfftw3-dev liblapack-dev libopenblas-dev xz-utils libudev-dev libusb-1.0.0-dev sudo systemd RUN apt-get install -y g++ make cmake libfftw3-dev liblapack-dev libopenblas-dev xz-utils libudev-dev libusb-1.0.0-dev sudo systemd doxygen graphviz
RUN cd lib && tar xf armadillo-12.0.1.tar.xz && cd armadillo-12.0.1 && cmake . && make install RUN cd lib && tar xf armadillo-12.0.1.tar.xz && cd armadillo-12.0.1 && cmake . && make install
RUN cd lib/sdrplay-3.0.7 && mkdir -p /etc/udev/rules.d && yes | ./install_lib.sh RUN cd lib/sdrplay-3.0.7 && mkdir -p /etc/udev/rules.d && yes | ./install_lib.sh

2494
Doxyfile Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,2 +1,5 @@
## [0.1] - 04/May/2023 ## [0.1] - 04/May/2023
- Initial release - Initial release
## [0.2] - 20/May/2023
- Add doxygen comments

1
doc/html/example.png Symbolic link
View file

@ -0,0 +1 @@
../../example.png

View file

@ -1,20 +1,16 @@
// A real-time radar. /// @file blah2.cpp
/// @brief A real-time radar.
// Author: github.com/30hours /// @author 30hours
// Date: 31/Jan/2023
// License: MIT
#define RYML_SINGLE_HDR_DEFINE_NOW #define RYML_SINGLE_HDR_DEFINE_NOW
#include <ryml-0.5.0.hpp> #include <ryml-0.5.0.hpp>
#include <asio.hpp> #include <asio.hpp>
#include <Capture.h> #include <Capture.h>
#include <Ambiguity.h> #include <Ambiguity.h>
#include <WienerHopf.h> #include <WienerHopf.h>
#include <IqData.h> #include <IqData.h>
#include <Map.h> #include <Map.h>
#include <sys/types.h> #include <sys/types.h>
#include <getopt.h> #include <getopt.h>
#include <string> #include <string>

View file

@ -1,3 +1,8 @@
/// @file Capture.h
/// @class Capture
/// @brief A class for a generic IQ capture device.
/// @author 30hours
#ifndef CAPTURE_H #ifndef CAPTURE_H
#define CAPTURE_H #define CAPTURE_H
@ -7,20 +12,53 @@
class Capture class Capture
{ {
private: private:
/// @brief The valid capture devices.
static const std::string VALID_TYPE[2]; static const std::string VALID_TYPE[2];
bool replay;
bool loop;
std::string file;
public:
std::string type;
uint32_t fs;
uint32_t fc;
bool saveIq;
std::string path;
Capture(std::string type, uint32_t fs, uint32_t fc, std::string path);
void process(IqData *buffer1, IqData *buffer2);
void set_replay(bool loop, std::string file);
/// @brief True if file replay is enabled.
bool replay;
/// @brief True if replay file should loop when complete.
bool loop;
/// @brief Absolute path of file to replay.
std::string file;
public:
/// @brief The capture device type.
std::string type;
/// @brief Sampling frequency (Hz).
uint32_t fs;
/// @brief Center frequency (Hz).
uint32_t fc;
/// @brief True if IQ data is saved to file.
bool saveIq;
/// @brief Absolute path to IQ save location.
std::string path;
/// @brief Constructor.
/// @param type The capture device type.
/// @param fs Sampling frequency (Hz).
/// @param fc Center frequency (Hz).
/// @param path Absolute path to IQ save location.
/// @return The object.
Capture(std::string type, uint32_t fs, uint32_t fc, std::string path);
/// @brief Implement the capture process.
/// @param buffer1 Buffer for reference samples.
/// @param buffer2 Buffer for surveillance samples.
/// @return Void.
void process(IqData *buffer1, IqData *buffer2);
/// @brief Set parameters to enable file replay.
/// @param loop True if replay file should loop when complete.
/// @param file Absolute path of file to replay.
/// @return Void.
void set_replay(bool loop, std::string file);
}; };
#endif #endif

View file

@ -1,30 +1,3 @@
/******************************************************************************
*
* Filename: rspduo_iq_recorder.c
*
* Author: Michael Parker
*
* Created: 13 Feb 2022
*
* Description: IQ Recorder for SDRplay RSPduo
*
* Loosely based upon the sdrplay_api_sample_app.c and sdr_play.c examples
* provided in the SDRplay API V3 documentation
* This should be read in conjuction with that documentation
*
* For coherent operation the use of sdrplay_api_Tuner_Both is most important
* This clue was provided by Gustaw Mazurek of WUT
*
* Revision History:
*
* 13 Feb 2022 MCP Initial coding
*
*
* https://github.com/fventuri/gr-sdrplay/issues/2
* https://github.com/g4eev/RSPduoEME/blob/main/rspduointerface.cpp
*
******************************************************************************/
#include <RspDuo.h> #include <RspDuo.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>

View file

@ -1,3 +1,21 @@
/// @file RspDuo.h
/// @class RspDuo
/// @brief A class to capture data on the SDRplay RspDuo.
/// @details Loosely based upon the sdrplay_api_sample_app.c and sdr_play.c examples
/// provided in the SDRplay API V3 documentation.
/// This should be read in conjuction with that documentation
///
/// For coherent operation the use of sdrplay_api_Tuner_Both is most important
/// This clue was provided by Gustaw Mazurek of WUT
/// <https://github.com/fventuri/gr-sdrplay/issues/2>
/// <https://github.com/g4eev/RSPduoEME/blob/main/rspduointerface.cpp>
///
/// Reference for using C style callback API with a C++ wrapper:
/// <https://stackoverflow.com/questions/63768893/pointer-problem-using-functions-from-non-object-api-in-objects?rq=1>
/// @author 30hours
/// @author Michael P
/// @todo Remove max time.
#ifndef RSPDUO_H #ifndef RSPDUO_H
#define RSPDUO_H #define RSPDUO_H
@ -6,76 +24,212 @@
#include <string> #include <string>
#include <IqData.h> #include <IqData.h>
#define BUFFER_SIZE_NR 1024 /* standard size of buffers */ #define BUFFER_SIZE_NR 1024
// https://stackoverflow.com/questions/63768893/pointer-problem-using-functions-from-non-object-api-in-objects?rq=1
class RspDuo class RspDuo
{ {
private: private:
uint32_t fc; // frequency (Hz) /// @brief Center frequency (Hz)
int chunk_time_nr; // chunk time of recording (s) uint32_t fc;
int agc_bandwidth_nr; // agc bandwidth (Hz) /// @brief chunk time of recording (s)
int agc_set_point_nr; // agc set point (dBfs) int chunk_time_nr;
int gain_reduction_nr; // gain reduction (dB) /// @brief AGC bandwidth (Hz)
int lna_state_nr; // lna state int agc_bandwidth_nr;
int nDecimation; // decimation factor /// @brief AGC set point (dBfs)
bool rf_notch_fg; // MW and FM notch filters int agc_set_point_nr;
bool dab_notch_fg; // DAB notch filter /// @brief Gain reduction (dB).
bool usb_bulk_fg; // usb bulk transfer mode int gain_reduction_nr;
bool small_verbose_fg; // debugging /// @brief LNA state
bool more_verbose_fg; // debugging int lna_state_nr;
std::string path; // file path /// @brief Decimation factor (integer).
bool capture; // flag to capture int nDecimation;
static const double MAX_FREQUENCY_NR; /// @brief MW and FM notch filters.
static const uint8_t DEF_DECIMATION_NR; bool rf_notch_fg;
static const int DEF_WAIT_TIME_NR; // default wait time before recording /// @brief DAB notch filter.
static const int DEF_CHUNK_TIME_NR; // default chunk time of recording bool dab_notch_fg;
static const int MAX_RUN_TIME_NR; // max run time of recording /// @brief USB bulk transfer mode.
static const int DEF_AGC_BANDWIDTH_NR; // default agc bandwidth bool usb_bulk_fg;
static const int MIN_AGC_SET_POINT_NR; // min agc set point /// @brief Debugging.
static const int DEF_AGC_SET_POINT_NR; // default agc set point bool small_verbose_fg;
static const int MIN_GAIN_REDUCTION_NR; // min gain reduction /// @brief Debugging.
static const int DEF_GAIN_REDUCTION_NR; // default gain reduction bool more_verbose_fg;
static const int MAX_GAIN_REDUCTION_NR; // max gain reduction /// @brief File path.
static const int DEF_LNA_STATE_NR; // default lna state std::string path;
static const int MAX_LNA_STATE_NR; // max lna state /// @brief True if capture is enabled.
static const int DEF_SAMPLE_FREQUENCY_NR; // default sample frequency bool capture;
static const int DEF_SAMPLE_RATE_NR; // default sample rate
/// @brief Maximum frequency (Hz).
static const double MAX_FREQUENCY_NR;
/// @brief Default decimation.
static const uint8_t DEF_DECIMATION_NR;
/// @brief Default wait time before recording.
static const int DEF_WAIT_TIME_NR;
/// @brief Default chunk time of recording.
static const int DEF_CHUNK_TIME_NR;
/// @brief Maximum run time of recording.
static const int MAX_RUN_TIME_NR;
/// @brief Default AGC bandwidth.
static const int DEF_AGC_BANDWIDTH_NR;
/// @brief Minimum AGC set point.
static const int MIN_AGC_SET_POINT_NR;
/// @brief Default AGC set point.
static const int DEF_AGC_SET_POINT_NR;
/// @brief Minimum gain reduction.
static const int MIN_GAIN_REDUCTION_NR;
/// @brief Default gain reduction.
static const int DEF_GAIN_REDUCTION_NR;
/// @brief Maximum gain reduction.
static const int MAX_GAIN_REDUCTION_NR;
/// @brief Default LNA state.
static const int DEF_LNA_STATE_NR;
/// @brief Max LNA state.
static const int MAX_LNA_STATE_NR;
/// @brief Default sample frequency.
static const int DEF_SAMPLE_FREQUENCY_NR;
/// @brief Default sample rate.
static const int DEF_SAMPLE_RATE_NR;
/// @brief Check parameters for valid for capture device.
/// @return The object.
void validate(); void validate();
/// @brief Start API functions.
/// @return The object.
void open_api(); void open_api();
/// @brief Device selection function.
/// @return The object.
void get_device(); void get_device();
/// @brief Set device parameters.
/// @return The object.
void set_device_parameters(); void set_device_parameters();
/// @brief Wrapper for C style callback function for stream_a_callback().
/// @param xi Pointer to real part of sample.
/// @param xq Pointer to imag part of sample.
/// @param params As defined in SDRplay API.
/// @param numSamples Number of samples in block.
/// @param reset As defined in SDRplay API.
/// @param cbContext As defined in SDRplay API.
/// @return Void.
static void _stream_a_callback(short *xi, short *xq, sdrplay_api_StreamCbParamsT *params, unsigned int numSamples, unsigned int reset, void *cbContext) static void _stream_a_callback(short *xi, short *xq, sdrplay_api_StreamCbParamsT *params, unsigned int numSamples, unsigned int reset, void *cbContext)
{ {
static_cast<RspDuo *>(cbContext)->stream_a_callback(xi, xq, params, numSamples, reset, cbContext); static_cast<RspDuo *>(cbContext)->stream_a_callback(xi, xq, params, numSamples, reset, cbContext);
}; };
/// @brief Wrapper for C style callback function for stream_b_callback().
/// @param xi Pointer to real part of sample.
/// @param xq Pointer to imag part of sample.
/// @param params As defined in SDRplay API.
/// @param numSamples Number of samples in block.
/// @param reset As defined in SDRplay API.
/// @param cbContext As defined in SDRplay API.
/// @return Void.
static void _stream_b_callback(short *xi, short *xq, sdrplay_api_StreamCbParamsT *params, unsigned int numSamples, unsigned int reset, void *cbContext) static void _stream_b_callback(short *xi, short *xq, sdrplay_api_StreamCbParamsT *params, unsigned int numSamples, unsigned int reset, void *cbContext)
{ {
static_cast<RspDuo *>(cbContext)->stream_b_callback(xi, xq, params, numSamples, reset, cbContext); static_cast<RspDuo *>(cbContext)->stream_b_callback(xi, xq, params, numSamples, reset, cbContext);
}; };
/// @brief Wrapper for C style callback function for event_callback().
/// @param eventId As defined in SDRplay API.
/// @param tuner As defined in SDRplay API.
/// @param params As defined in SDRplay API.
/// @param cbContext As defined in SDRplay API.
/// @return Void.
static void _event_callback(sdrplay_api_EventT eventId, sdrplay_api_TunerSelectT tuner, sdrplay_api_EventParamsT *params, void *cbContext) static void _event_callback(sdrplay_api_EventT eventId, sdrplay_api_TunerSelectT tuner, sdrplay_api_EventParamsT *params, void *cbContext)
{ {
static_cast<RspDuo *>(cbContext)->event_callback(eventId, tuner, params, cbContext); static_cast<RspDuo *>(cbContext)->event_callback(eventId, tuner, params, cbContext);
}; };
/// @brief Tuner a callback as defined in SDRplay API.
/// @param xi Pointer to real part of sample.
/// @param xq Pointer to imag part of sample.
/// @param params As defined in SDRplay API.
/// @param numSamples Number of samples in block.
/// @param reset As defined in SDRplay API.
/// @param cbContext As defined in SDRplay API.
/// @return Void.
void stream_a_callback(short *xi, short *xq, sdrplay_api_StreamCbParamsT *params, unsigned int numSamples, unsigned int reset, void *cbContext); void stream_a_callback(short *xi, short *xq, sdrplay_api_StreamCbParamsT *params, unsigned int numSamples, unsigned int reset, void *cbContext);
/// @brief Tuner b callback as defined in SDRplay API.
/// @param xi Pointer to real part of sample.
/// @param xq Pointer to imag part of sample.
/// @param params As defined in SDRplay API.
/// @param numSamples Number of samples in block.
/// @param reset As defined in SDRplay API.
/// @param cbContext As defined in SDRplay API.
/// @return Void.
void stream_b_callback(short *xi, short *xq, sdrplay_api_StreamCbParamsT *params, unsigned int numSamples, unsigned int reset, void *cbContext); void stream_b_callback(short *xi, short *xq, sdrplay_api_StreamCbParamsT *params, unsigned int numSamples, unsigned int reset, void *cbContext);
/// @brief Event callback function as defined in SDRplay API.
/// @param eventId As defined in SDRplay API.
/// @param tuner As defined in SDRplay API.
/// @param params As defined in SDRplay API.
/// @param cbContext As defined in SDRplay API.
/// @return Void.
void event_callback(sdrplay_api_EventT eventId, sdrplay_api_TunerSelectT tuner, sdrplay_api_EventParamsT *params, void *cbContext); void event_callback(sdrplay_api_EventT eventId, sdrplay_api_TunerSelectT tuner, sdrplay_api_EventParamsT *params, void *cbContext);
/// @brief Start running capture callback function.
/// @return Void.
void initialise_device(); void initialise_device();
/// @brief Stop running capture callback function.
/// @return Void.
void uninitialise_device(); void uninitialise_device();
/// @brief Internal method to gracefully stop capture..
/// @return Void.
void finish(); void finish();
public: public:
/// @brief Constructor.
/// @param fc Center frequency (Hz).
/// @param path Path to save IQ data.
/// @return The object.
RspDuo(uint32_t fc, std::string path); RspDuo(uint32_t fc, std::string path);
/// @brief Get file name from path.
/// @return String of file name based on current time.
std::string set_file(std::string path); std::string set_file(std::string path);
/// @brief Call methods to start capture.
/// @return Void.
void start(); void start();
/// @brief Call methods to gracefully stop capture.
/// @return Void.
void stop(); void stop();
/// @brief Implement capture function on RSPduo.
/// @param buffer1 Pointer to reference buffer.
/// @param buffer2 Pointer to surveillance buffer.
/// @return Void.
void process(IqData *buffer1, IqData *buffer2); void process(IqData *buffer1, IqData *buffer2);
/// @brief Implement replay function on RSPduo.
/// @param buffer1 Pointer to reference buffer.
/// @param buffer2 Pointer to surveillance buffer.
/// @param file Path to file to replay data from.
/// @param loop True if samples should loop at EOF.
/// @return Void.
void replay(IqData *buffer1, IqData *buffer2, std::string file, bool loop); void replay(IqData *buffer1, IqData *buffer2, std::string file, bool loop);
/// @brief Open a new file to record IQ.
/// @return Void.
void open_file(); void open_file();
/// @brief Close IQ file gracefully.
/// @return Void.
void close_file(); void close_file();
/// @brief Setter for capture.
/// @param capture True if capture is enabled.
/// @return Void.
void set_capture(bool capture); void set_capture(bool capture);
/// @brief Getter for capture.
/// @return True if capture is true.
bool get_capture(); bool get_capture();
}; };

View file

@ -1,3 +1,9 @@
/// @file IqData.h
/// @class IqData
/// @brief A class to store IQ data.
/// @details Implements a FIFO queue to store IQ samples.
/// @author 30hours
#ifndef IQDATA_H #ifndef IQDATA_H
#define IQDATA_H #define IQDATA_H
@ -8,20 +14,57 @@
class IqData class IqData
{ {
private: private:
/// @brief Maximum number of samples.
uint32_t n; uint32_t n;
/// @brief True if should not push to buffer (mutex).
bool doNotPush; bool doNotPush;
/// @brief Pointer to IQ data.
std::deque<std::complex<double>> *data; std::deque<std::complex<double>> *data;
public: public:
/// @brief Constructor.
/// @param n Number of samples.
/// @return The object.
IqData(uint32_t n); IqData(uint32_t n);
/// @brief Getter for maximum number of samples.
/// @return Maximum number of samples.
uint32_t get_n(); uint32_t get_n();
/// @brief Getter for current data length.
/// @return Number of samples currently in data.
uint32_t get_length(); uint32_t get_length();
/// @brief Setter for mutex.
/// @param doNotPush True if should not push to buffer (mutex).
/// @return Void.
void set_doNotPush(bool doNotPush); void set_doNotPush(bool doNotPush);
/// @brief Getter for mutex.
/// @return True if should not push to buffer (mutex).
bool get_doNotPush(); bool get_doNotPush();
/// @brief Getter for data.
/// @return IQ data.
std::deque<std::complex<double>> get_data(); std::deque<std::complex<double>> get_data();
/// @brief Push a sample to the queue.
/// @param sample A single sample.
/// @return Void.
void push_back(std::complex<double> sample); void push_back(std::complex<double> sample);
/// @brief Pop the front of the queue.
/// @return Sample from the front of the queue.
std::complex<double> pop_front(); std::complex<double> pop_front();
/// @brief Print to stdout (debug).
/// @return Void.
void print(); void print();
/// @brief Clear samples from the queue.
/// @return Void.
void clear(); void clear();
}; };

View file

@ -8,9 +8,6 @@
#include "rapidjson/stringbuffer.h" #include "rapidjson/stringbuffer.h"
#include "rapidjson/filewritestream.h" #include "rapidjson/filewritestream.h"
// References:
// - https://stackoverflow.com/questions/39110263/append-to-an-existing-array-of-json-objects-on-file-using-rapidjson
// constructor // constructor
template <class T> template <class T>
Map<T>::Map(uint32_t _nRows, uint32_t _nCols) Map<T>::Map(uint32_t _nRows, uint32_t _nCols)

View file

@ -1,3 +1,12 @@
/// @file Map.h
/// @class Map
/// @brief A class to store an ambiguity map.
/// @details References:
/// <a href="https://stackoverflow.com/questions/39110263/append-to-an-existing-array-of-json-objects-on-file-using-rapidjson">
/// Append to an existing array using rapidjson.</a>
/// @author 30hours
/// @todo Fix memory leak in get_map_db().
#ifndef MAP_H #ifndef MAP_H
#define MAP_H #define MAP_H
@ -11,26 +20,84 @@ template <typename T>
class Map class Map
{ {
private: private:
/// @brief Number of rows.
uint32_t nRows; uint32_t nRows;
/// @brief Number of columns.
uint32_t nCols; uint32_t nCols;
public: public:
/// @brief Map data to store.
std::vector<std::vector<T>> data; std::vector<std::vector<T>> data;
/// @brief Delay units of map data (bins).
std::deque<int> delay; std::deque<int> delay;
/// @brief Doppler units of map data (Hz).
std::deque<double> doppler; std::deque<double> doppler;
/// @brief Noise power of map (dB).
double noisePower; double noisePower;
/// @brief Dynamic range of map (dB).
double maxPower; double maxPower;
/// @brief Constructor.
/// @param nRows Number of rows.
/// @param nCols Number of columns.
/// @return The object.
Map(uint32_t nRows, uint32_t nCols); Map(uint32_t nRows, uint32_t nCols);
/// @brief Update a row in the 2D map.
/// @param i Index of row to update.
/// @param row Data to update.
/// @return Void.
void set_row(uint32_t i, std::vector<T> row); void set_row(uint32_t i, std::vector<T> row);
/// @brief Update a column in the 2D map.
/// @param i Index of column to update.
/// @param col Data to update.
/// @return Void.
void set_col(uint32_t i, std::vector<T> col); void set_col(uint32_t i, std::vector<T> col);
/// @brief Create map metrics (noise power, dynamic range).
/// @return Void.
void set_metrics(); void set_metrics();
/// @brief Get the number of rows in the map.
/// @return Number of rows.
uint32_t get_nRows(); uint32_t get_nRows();
/// @brief Get the number of columns in the map.
/// @return Number of columns.
uint32_t get_nCols(); uint32_t get_nCols();
/// @brief Get a row from the 2D map.
/// @param row Index of row to get.
/// @return Vector of data.
std::vector<T> get_row(uint32_t row); std::vector<T> get_row(uint32_t row);
/// @brief Get a column from the 2D map.
/// @param col Index of column to get.
/// @return Vector of data.
std::vector<T> get_col(uint32_t col); std::vector<T> get_col(uint32_t col);
/// @brief Get a copy of the map in dB units.
/// @return Pointer to dB map.
Map<double> *get_map_db(); Map<double> *get_map_db();
/// @brief Print the map to stdout (for debugging).
/// @return Void.
void print(); void print();
/// @brief Generate JSON of the map and metadata.
/// @return JSON string.
std::string to_json(); std::string to_json();
/// @brief Append the map to a save file.
/// @param json JSON string of map and metadata.
/// @param path Path of file to save.
/// @return True is save is successful.
bool save(std::string json, std::string path); bool save(std::string json, std::string path);
}; };

View file

@ -1,3 +1,11 @@
/// @file Ambiguity.h
/// @class Ambiguity
/// @brief A class to implement a ambiguity map processing.
/// @details Implements a the batches algorithm as described in Principles of Modern Radar, Volume II, Chapter 17.
/// 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.
#ifndef AMBIGUITY_H #ifndef AMBIGUITY_H
#define AMBIGUITY_H #define AMBIGUITY_H
@ -9,30 +17,79 @@
class Ambiguity class Ambiguity
{ {
private: 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 n; uint32_t n;
/// @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, fftYi, fftZi, fftDoppler; fftw_plan fftXi, fftYi, fftZi, fftDoppler;
/// @}
/// @brief FFTW storage for ambiguity processing.
/// @{
std::complex<double> *dataXi, *dataYi, *dataZi, *dataCorr, *dataDoppler; std::complex<double> *dataXi, *dataYi, *dataZi, *dataCorr, *dataDoppler;
/// @}
/// @brief Number of samples to perform FFT per pulse.
uint32_t nfft; uint32_t nfft;
/// @brief Vector storage for ambiguity processing
/// @{
std::vector<std::complex<double>> corr, delayProfile; std::vector<std::complex<double>> corr, delayProfile;
/// @}
/// @brief Pointer to map to store result.
Map<std::complex<double>> *map; Map<std::complex<double>> *map;
public: public:
/// @brief Constructor.
/// @param delayMin Minimum delay (bins).
/// @param delayMax Maximum delay (bins).
/// @param dopplerMin Minimum Doppler (Hz).
/// @param dopplerMax Maximum Doppler (Hz).
/// @param fs Sampling frequency (Hz).
/// @param n Number of samples.
/// @return The object.
Ambiguity(int32_t delayMin, int32_t delayMax, int32_t dopplerMin, int32_t dopplerMax, uint32_t fs, uint32_t n); Ambiguity(int32_t delayMin, int32_t delayMax, int32_t dopplerMin, int32_t dopplerMax, uint32_t fs, uint32_t n);
/// @brief Destructor.
/// @return Void.
~Ambiguity(); ~Ambiguity();
/// @brief Implement the ambiguity processor.
/// @param x Reference samples.
/// @param y Surveillance samples.
/// @return Ambiguity map data of IQ samples.
Map<std::complex<double>> *process(IqData *x, IqData *y); Map<std::complex<double>> *process(IqData *x, IqData *y);
}; };

View file

@ -1,3 +1,11 @@
/// @file WienerHopf.h
/// @class WienerHopf
/// @brief A class to implement a Wiener-Hopf clutter filter.
/// @details Implements a <a href="https://en.wikipedia.org/wiki/Wiener_filter#Finite_impulse_response_Wiener_filter_for_discrete_series">Wiener-Hopf filter</a>.
/// Uses <a href="https://en.wikipedia.org/wiki/Cholesky_decomposition">Cholesky decomposition</a> to speed up matrix inversion, as the Toeplitz matrix is positive-definite and Hermitian.
/// @author 30hours
/// @todo Fix the segmentation fault from clutter filter numerical instability.
#ifndef WIENERHOPF_H #ifndef WIENERHOPF_H
#define WIENERHOPF_H #define WIENERHOPF_H
@ -9,23 +17,64 @@
class WienerHopf class WienerHopf
{ {
private: private:
/// @brief Minimum clutter filter delay (bins).
int32_t delayMin; int32_t delayMin;
/// @brief Maximum clutter filter delay (bins).
int32_t delayMax; int32_t delayMax;
/// @brief Number of bins (delayMax - delayMin + 1).
uint32_t nBins; uint32_t nBins;
/// @brief Number of samples per CPI.
uint32_t nSamples; uint32_t nSamples;
/// @brief True if clutter filter processing is successful.
bool success; bool success;
/// @brief FFTW plans for clutter filter processing.
/// @{
fftw_plan fftX, fftY, fftA, fftB, fftFiltX, fftFiltW, fftFilt; fftw_plan fftX, fftY, fftA, fftB, fftFiltX, fftFiltW, fftFilt;
/// @}
/// @brief FFTW storage for clutter filter processing.
/// @{
std::complex<double> *dataX, *dataY, *dataOutX, *dataOutY, *dataA, *dataB, *filtX, *filtW, *filt; std::complex<double> *dataX, *dataY, *dataOutX, *dataOutY, *dataA, *dataB, *filtX, *filtW, *filt;
/// @}
/// @brief Deque storage for clutter filter processing.
/// @{
std::deque<std::complex<double>> xData, yData; std::deque<std::complex<double>> xData, yData;
/// @}
/// @brief Autocorrelation toeplitz matrix.
arma::cx_mat A; arma::cx_mat A;
arma::cx_vec a, b, w;
/// @brief Autocorrelation vector.
arma::cx_vec a;
/// @brief Cross-correlation vector.
arma::cx_vec b;
/// @brief Weights vector.
arma::cx_vec w;
public: public:
/// @brief Constructor.
/// @param delayMin Minimum clutter filter delay (bins).
/// @param delayMax Maximum clutter filter delay (bins).
/// @param nSamples Number of samples per CPI.
/// @return The object.
WienerHopf(int32_t delayMin, int32_t delayMax, uint32_t nSamples); WienerHopf(int32_t delayMin, int32_t delayMax, uint32_t nSamples);
/// @brief Destructor.
/// @return Void.
~WienerHopf(); ~WienerHopf();
/// @brief Implement the clutter filter.
/// @param x Reference samples.
/// @param y Surveillance samples.
/// @return True if clutter filter successful.
bool process(IqData *x, IqData *y); bool process(IqData *x, IqData *y);
}; };