FERS 0.1.0
The Flexible Extensible Radar Simulator
Loading...
Searching...
No Matches
fers_signal::CwSignal Class Referencefinal

Continuous-wave signal implementation. More...

#include "radar_signal.h"

+ Inheritance diagram for fers_signal::CwSignal:
+ Collaboration diagram for fers_signal::CwSignal:

Public Member Functions

 CwSignal ()=default
 
 ~CwSignal () override=default
 
 CwSignal (const CwSignal &) noexcept=delete
 
CwSignaloperator= (const CwSignal &) noexcept=delete
 
 CwSignal (CwSignal &&) noexcept=delete
 
CwSignaloperator= (CwSignal &&) noexcept=delete
 
std::vector< ComplexTyperender (const std::vector< interp::InterpPoint > &points, unsigned &size, RealType fracWinDelay) const override
 Renders the signal data.
 
void clear () noexcept
 Clears the internal signal data.
 
void load (std::span< const ComplexType > inData, unsigned samples, RealType sampleRate)
 Loads complex radar waveform data.
 
RealType getRate () const noexcept
 Gets the sample rate of the signal.
 
unsigned getSampleCount () const noexcept
 Gets the number of native samples held by this signal.
 
virtual std::vector< ComplexTyperenderSlice (const std::vector< interp::InterpPoint > &points, RealType outputStartTime, RealType outputSampleRate, std::size_t sampleCount, RealType fracWinDelay) const
 Renders a bounded absolute-time slice on the requested output grid.
 
virtual bool isFmcwFamily () const noexcept
 Returns true when this signal belongs to the FMCW waveform family.
 
ComplexType sampleAt (RealType time_since_start) const noexcept
 Samples the finite stored complex envelope using the render interpolation filter.
 

Detailed Description

Continuous-wave signal implementation.

Definition at line 324 of file radar_signal.h.

Constructor & Destructor Documentation

◆ CwSignal() [1/3]

fers_signal::CwSignal::CwSignal ( )
default

◆ ~CwSignal()

fers_signal::CwSignal::~CwSignal ( )
overridedefault

◆ CwSignal() [2/3]

fers_signal::CwSignal::CwSignal ( const CwSignal )
deletenoexcept

◆ CwSignal() [3/3]

fers_signal::CwSignal::CwSignal ( CwSignal &&  )
deletenoexcept

Member Function Documentation

◆ clear()

void fers_signal::Signal::clear ( )
noexceptinherited

Clears the internal signal data.

Definition at line 347 of file radar_signal.cpp.

348 {
349 _size = 0;
350 _rate = 0;
351 }

Referenced by fers_signal::Signal::load().

+ Here is the caller graph for this function:

◆ getRate()

RealType fers_signal::Signal::getRate ( ) const
noexceptinherited

Gets the sample rate of the signal.

Returns
The sample rate of the signal.

Definition at line 94 of file radar_signal.h.

94{ return _rate; }

◆ getSampleCount()

unsigned fers_signal::Signal::getSampleCount ( ) const
noexceptinherited

Gets the number of native samples held by this signal.

Definition at line 97 of file radar_signal.h.

97{ return _size; }

◆ isFmcwFamily()

virtual bool fers_signal::Signal::isFmcwFamily ( ) const
virtualnoexceptinherited

Returns true when this signal belongs to the FMCW waveform family.

Reimplemented in fers_signal::FileSignal, fers_signal::FmcwChirpSignal, and fers_signal::FmcwTriangleSignal.

Definition at line 117 of file radar_signal.h.

117{ return false; }

◆ load()

void fers_signal::Signal::load ( std::span< const ComplexType inData,
unsigned  samples,
RealType  sampleRate 
)
inherited

Loads complex radar waveform data.

Parameters
inDataThe input span of complex signal data.
samplesThe number of samples in the input data.
sampleRateThe sample rate of the input data.

Definition at line 353 of file radar_signal.cpp.

354 {
355 clear();
356 const unsigned ratio = params::oversampleRatio();
357 const auto oversampled_samples = static_cast<std::size_t>(samples) * static_cast<std::size_t>(ratio);
358 if (oversampled_samples > std::numeric_limits<unsigned>::max())
359 {
360 throw std::overflow_error("Oversampled signal sample count exceeds unsigned range");
361 }
362 _data.resize(oversampled_samples);
363 _size = static_cast<unsigned>(oversampled_samples);
364 _rate = sampleRate * static_cast<RealType>(ratio);
365
366 if (ratio == 1)
367 {
368 std::ranges::copy(inData, _data.begin());
369 }
370 else
371 {
372 upsample(inData, samples, _data);
373 }
374 }
void clear() noexcept
Clears the internal signal data.
double RealType
Type for real numbers.
Definition config.h:27
void upsample(const std::span< const ComplexType > in, const unsigned size, std::span< ComplexType > out)
Upsamples a complex waveform with zero-stuffing followed by Blackman FIR filtering.
unsigned oversampleRatio() noexcept
Get the oversampling ratio.
Definition parameters.h:151
math::Vec3 max

References fers_signal::Signal::clear(), max, params::oversampleRatio(), and fers_signal::upsample().

+ Here is the call graph for this function:

◆ operator=() [1/2]

CwSignal & fers_signal::CwSignal::operator= ( const CwSignal )
deletenoexcept

◆ operator=() [2/2]

CwSignal & fers_signal::CwSignal::operator= ( CwSignal &&  )
deletenoexcept

◆ render()

std::vector< ComplexType > fers_signal::CwSignal::render ( const std::vector< interp::InterpPoint > &  points,
unsigned size,
RealType  fracWinDelay 
) const
overridevirtual

Renders the signal data.

For CW signals, this is a no-op.

Returns
An empty vector of complex signal data.

Reimplemented from fers_signal::Signal.

Definition at line 48 of file radar_signal.cpp.

50 {
51 size = 0;
52 return {};
53 }

References max.

◆ renderSlice()

std::vector< ComplexType > fers_signal::Signal::renderSlice ( const std::vector< interp::InterpPoint > &  points,
RealType  outputStartTime,
RealType  outputSampleRate,
std::size_t  sampleCount,
RealType  fracWinDelay 
) const
virtualinherited

Renders a bounded absolute-time slice on the requested output grid.

Definition at line 413 of file radar_signal.cpp.

416 {
417 auto out = std::vector<ComplexType>(sampleCount);
418 if (_size == 0 || _rate <= 0.0 || outputSampleRate <= 0.0 || points.empty())
419 {
420 return out;
421 }
422
423 const RealType timestep = 1.0 / outputSampleRate;
424 const int filt_length = static_cast<int>(params::renderFilterLength());
426
427 auto iter = points.begin();
428 auto next = points.size() > 1 ? std::next(iter) : iter;
429 const RealType idelay = std::round(_rate * iter->delay);
431
432 for (std::size_t i = 0; i < sampleCount; ++i)
433 {
434 while (sample_time > next->time && next != iter)
435 {
436 iter = next;
437 if (std::next(next) != points.end())
438 {
439 ++next;
440 }
441 else
442 {
443 break;
444 }
445 }
446
447 auto [amplitude, phase, fdelay, i_sample_unwrap] =
448 calculateWeightsAndDelays(iter, next, sample_time, idelay, fracWinDelay);
449 const RealType native_position = (sample_time - points.front().time) * _rate;
450 const auto source_index = static_cast<int>(std::floor(native_position));
453 {
454 source_fraction = 0.0;
455 }
456
458 const auto delay_unwrap = static_cast<int>(std::floor(combined_delay));
459 fdelay = combined_delay - static_cast<RealType>(delay_unwrap);
461
462 const auto& filt = interp.getFilter(fdelay);
463 const ComplexType accum =
464 performConvolution(source_index, filt.data(), filt_length, amplitude, i_sample_unwrap);
465 out[i] = std::exp(ComplexType(0.0, 1.0) * phase) * accum;
466
468 }
469
470 return out;
471 }
static InterpFilter & getInstance() noexcept
Retrieves the singleton instance of the InterpFilter class.
std::complex< RealType > ComplexType
Type for complex numbers.
Definition config.h:35
unsigned renderFilterLength() noexcept
Get the render filter length.
Definition parameters.h:139

References interp::InterpFilter::getInstance(), max, and params::renderFilterLength().

Referenced by fers_signal::Signal::render().

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

◆ sampleAt()

ComplexType fers_signal::Signal::sampleAt ( RealType  time_since_start) const
noexceptinherited

Samples the finite stored complex envelope using the render interpolation filter.

Times outside [0, duration) return zero; file-backed signals never wrap implicitly.

Definition at line 376 of file radar_signal.cpp.

377 {
378 if (_data.empty() || _rate <= 0.0 || !std::isfinite(time_since_start) || time_since_start < 0.0 ||
379 time_since_start >= static_cast<RealType>(_size) / _rate)
380 {
381 return {0.0, 0.0};
382 }
383
384 const RealType position = time_since_start * _rate;
385 const auto center = static_cast<long long>(std::floor(position));
386 const RealType fraction = position - std::floor(position);
388 const auto filter_length = static_cast<long long>(filter.size());
389 const auto sample_count = static_cast<long long>(_data.size());
390 ComplexType value{0.0, 0.0};
391 for (long long tap = 0; tap < filter_length; ++tap)
392 {
393 const long long sample_index = center + tap - filter_length / 2;
394 if (sample_index >= 0 && sample_index < sample_count)
395 {
396 value += _data[static_cast<std::size_t>(sample_index)] * filter[static_cast<std::size_t>(tap)];
397 }
398 }
399 return value;
400 }
Vec3 position
std::span< const RealType > getFilter(RealType delay) const
Retrieves a span of precomputed filter values for a given delay.

References interp::InterpFilter::getFilter(), interp::InterpFilter::getInstance(), max, and position.

+ Here is the call graph for this function:

The documentation for this class was generated from the following files: