FERS 1.0.0
The Flexible Extensible Radar Simulator
Loading...
Searching...
No Matches
fers_signal Namespace Reference

Classes

class  CwSignal
 
class  DecadeUpsampler
 Implements a specialized upsampler with a fixed upsampling factor of 10. More...
 
class  DspFilter
 Abstract base class for digital filters. More...
 
class  FirFilter
 Implements a Finite Impulse Response (FIR) filter. More...
 
class  IirFilter
 Implements an Infinite Impulse Response (IIR) filter. More...
 
class  RadarSignal
 Class representing a radar signal with associated properties. More...
 
class  Signal
 Class for handling radar waveform signal data. More...
 

Functions

void to_json (nlohmann::json &j, const RadarSignal &rs)
 
void from_json (const nlohmann::json &j, std::unique_ptr< RadarSignal > &rs)
 
void upsample (std::span< const ComplexType > in, unsigned size, std::span< ComplexType > out)
 Upsamples a signal by a given ratio.
 
std::vector< ComplexTypedownsample (std::span< const ComplexType > in)
 Downsamples a signal by a given ratio.
 

Function Documentation

◆ downsample()

std::vector< ComplexType > fers_signal::downsample ( std::span< const ComplexType in)

Downsamples a signal by a given ratio.

Parameters
inInput span of complex samples.
Exceptions
std::invalid_argumentif the input or output spans are empty or the ratio is zero.

Definition at line 93 of file dsp_filters.cpp.

94 {
95 if (in.empty())
96 {
97 throw std::invalid_argument("Input span is empty in Downsample");
98 }
99
100 const unsigned ratio = params::oversampleRatio();
101 // TODO: Replace with a more efficient multirate downsampling implementation.
102 unsigned filt_length = 0;
103 const auto coeffs = blackmanFir(1 / static_cast<RealType>(ratio), filt_length);
104
105 std::vector tmp(in.size() + filt_length, ComplexType{0, 0});
106
107 std::ranges::copy(in, tmp.begin());
108
109 const FirFilter filt(coeffs);
110 filt.filter(tmp);
111
112 const auto downsampled_size = in.size() / ratio;
113 std::vector<ComplexType> out(downsampled_size);
114 for (unsigned i = 0; i < downsampled_size; ++i)
115 {
116 out[i] = tmp[i * ratio + filt_length / 2] / static_cast<RealType>(ratio);
117 }
118
119 return out;
120 }
double RealType
Type for real numbers.
Definition config.h:27
std::complex< RealType > ComplexType
Type for complex numbers.
Definition config.h:35
unsigned oversampleRatio() noexcept
Get the oversampling ratio.
Definition parameters.h:139

References fers_signal::FirFilter::filter(), and params::oversampleRatio().

Referenced by processing::finalizeCwReceiver(), and processing::runPulsedFinalizer().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ from_json()

void fers_signal::from_json ( const nlohmann::json &  j,
std::unique_ptr< RadarSignal > &  rs 
)

Definition at line 249 of file json_serializer.cpp.

250 {
251 const auto name = j.at("name").get<std::string>();
252 const auto power = j.at("power").get<RealType>();
253 const auto carrier = j.at("carrier_frequency").get<RealType>();
254
255 if (j.contains("cw"))
256 {
257 auto cw_signal = std::make_unique<CwSignal>();
258 rs = std::make_unique<RadarSignal>(name, power, carrier, params::endTime() - params::startTime(),
259 std::move(cw_signal));
260 }
261 else if (j.contains("pulsed_from_file"))
262 {
263 const auto& pulsed_file = j.at("pulsed_from_file");
264 const auto filename = pulsed_file.value("filename", "");
265 if (filename.empty())
266 {
267 LOG(logging::Level::WARNING, "Skipping load of file-based waveform '{}': filename is empty.", name);
268 return; // rs remains nullptr
269 }
270 rs = serial::loadWaveformFromFile(name, filename, power, carrier);
271 }
272 else
273 {
274 throw std::runtime_error("Unsupported waveform type in from_json for '" + name + "'");
275 }
276 }
#define LOG(level,...)
Definition logging.h:19
@ WARNING
Warning level for potentially harmful situations.
RealType endTime() noexcept
Get the end time for the simulation.
Definition parameters.h:97
RealType startTime() noexcept
Get the start time for the simulation.
Definition parameters.h:91
std::unique_ptr< RadarSignal > loadWaveformFromFile(const std::string &name, const std::string &filename, const RealType power, const RealType carrierFreq)
Loads a radar waveform from a file and returns a RadarSignal object.

References params::endTime(), serial::loadWaveformFromFile(), LOG, params::startTime(), and logging::WARNING.

+ Here is the call graph for this function:

◆ to_json()

void fers_signal::to_json ( nlohmann::json &  j,
const RadarSignal rs 
)

Definition at line 228 of file json_serializer.cpp.

229 {
230 j = nlohmann::json{{"name", rs.getName()}, {"power", rs.getPower()}, {"carrier_frequency", rs.getCarrier()}};
231 if (dynamic_cast<const CwSignal*>(rs.getSignal()))
232 {
233 j["cw"] = nlohmann::json::object();
234 }
235 else
236 {
237 if (const auto& filename = rs.getFilename(); filename.has_value())
238 {
239 j["pulsed_from_file"] = {{"filename", *filename}};
240 }
241 else
242 {
243 throw std::logic_error("Attempted to serialize a file-based waveform named '" + rs.getName() +
244 "' without a source filename.");
245 }
246 }
247 }
const std::optional< std::string > & getFilename() const noexcept
Gets the filename associated with this signal.
const std::string & getName() const noexcept
Gets the name of the radar signal.
RealType getCarrier() const noexcept
Gets the carrier frequency of the radar signal.
const Signal * getSignal() const noexcept
Gets the underlying signal object.
RealType getPower() const noexcept
Gets the power of the radar signal.

References fers_signal::RadarSignal::getCarrier(), fers_signal::RadarSignal::getFilename(), fers_signal::RadarSignal::getName(), fers_signal::RadarSignal::getPower(), and fers_signal::RadarSignal::getSignal().

+ Here is the call graph for this function:

◆ upsample()

void fers_signal::upsample ( std::span< const ComplexType in,
unsigned  size,
std::span< ComplexType out 
)

Upsamples a signal by a given ratio.

Parameters
inInput span of complex samples.
sizeSize of the input signal.
outOutput span for upsampled complex samples.
Exceptions
std::invalid_argumentif the input or output spans are empty or the ratio is zero.

Definition at line 70 of file dsp_filters.cpp.

71 {
72 const unsigned ratio = params::oversampleRatio();
73 // TODO: this would be better as a multirate upsampler
74 // This implementation is functional but suboptimal.
75 // Users requiring higher accuracy should oversample outside FERS until this is addressed.
76 unsigned filt_length;
77 const auto coeffs = blackmanFir(1 / static_cast<RealType>(ratio), filt_length);
78
79 std::vector tmp(size * ratio + filt_length, ComplexType{0.0, 0.0});
80
81 for (unsigned i = 0; i < size; ++i)
82 {
83 tmp[i * ratio] = in[i];
84 }
85
86 const FirFilter filt(coeffs);
87 filt.filter(tmp);
88
89 const auto delay = filt_length / 2 - 1;
90 std::ranges::copy_n(tmp.begin() + delay, size * ratio, out.begin());
91 }

References fers_signal::FirFilter::filter(), and params::oversampleRatio().

Referenced by fers_signal::Signal::load(), and fers_signal::DecadeUpsampler::~DecadeUpsampler().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: