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

FMCW symmetric triangular modulation signal implementation. More...

#include "radar_signal.h"

+ Inheritance diagram for fers_signal::FmcwTriangleSignal:
+ Collaboration diagram for fers_signal::FmcwTriangleSignal:

Public Member Functions

 FmcwTriangleSignal (RealType chirp_bandwidth, RealType chirp_duration, RealType start_frequency_offset=0.0, std::optional< std::size_t > triangle_count=std::nullopt)
 Constructs an FMCW triangular modulation signal.
 
 ~FmcwTriangleSignal () override=default
 
 FmcwTriangleSignal (const FmcwTriangleSignal &) noexcept=delete
 
FmcwTriangleSignaloperator= (const FmcwTriangleSignal &) noexcept=delete
 
 FmcwTriangleSignal (FmcwTriangleSignal &&) noexcept=delete
 
FmcwTriangleSignaloperator= (FmcwTriangleSignal &&) noexcept=delete
 
RealType getChirpBandwidth () const noexcept
 Gets the chirp bandwidth in hertz.
 
RealType getChirpDuration () const noexcept
 Gets the per-leg chirp duration in seconds.
 
RealType getStartFrequencyOffset () const noexcept
 Gets the start frequency offset relative to carrier in hertz.
 
const std::optional< std::size_t > & getTriangleCount () const noexcept
 Gets the optional finite triangle count.
 
RealType getChirpRate () const noexcept
 Gets the chirp rate magnitude in hertz per second.
 
RealType getTrianglePeriod () const noexcept
 Gets the full up/down triangle period in seconds.
 
RealType getDeltaPhiUp () const noexcept
 Gets the full, unreduced phase accumulated by one leg.
 
bool isTriangle () const noexcept
 Returns true for triangular FMCW waveforms.
 
RealType basebandPhaseForTriangleTime (RealType triangle_time) const noexcept
 Computes baseband phase at a time since the triangle train start.
 
std::optional< RealTypeinstantaneousBasebandPhase (RealType time_since_segment_start) const noexcept
 Computes instantaneous baseband phase at a time since segment start.
 
std::vector< ComplexTyperender (const std::vector< interp::InterpPoint > &points, unsigned &size, RealType fracWinDelay) const override
 Renders an FMCW waveform from interpolation points.
 
bool isFmcwFamily () const noexcept override
 Returns true when this signal belongs to the FMCW waveform family.
 
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.
 

Detailed Description

FMCW symmetric triangular modulation signal implementation.

Definition at line 391 of file radar_signal.h.

Constructor & Destructor Documentation

◆ FmcwTriangleSignal() [1/3]

fers_signal::FmcwTriangleSignal::FmcwTriangleSignal ( RealType  chirp_bandwidth,
RealType  chirp_duration,
RealType  start_frequency_offset = 0.0,
std::optional< std::size_t >  triangle_count = std::nullopt 
)

Constructs an FMCW triangular modulation signal.

Definition at line 113 of file radar_signal.cpp.

115 :
116 _chirp_bandwidth(chirp_bandwidth), _chirp_duration(chirp_duration),
117 _start_frequency_offset(start_frequency_offset), _triangle_count(triangle_count),
118 _chirp_rate(chirp_bandwidth / chirp_duration), _triangle_period(2.0 * chirp_duration),
119 _delta_phi_up(2.0 * PI * start_frequency_offset * chirp_duration +
120 PI * _chirp_rate * chirp_duration * chirp_duration)
121 {
122 }
constexpr RealType PI
Mathematical constant π (pi).
Definition config.h:43

◆ ~FmcwTriangleSignal()

fers_signal::FmcwTriangleSignal::~FmcwTriangleSignal ( )
overridedefault

◆ FmcwTriangleSignal() [2/3]

fers_signal::FmcwTriangleSignal::FmcwTriangleSignal ( const FmcwTriangleSignal )
deletenoexcept

◆ FmcwTriangleSignal() [3/3]

fers_signal::FmcwTriangleSignal::FmcwTriangleSignal ( FmcwTriangleSignal &&  )
deletenoexcept

Member Function Documentation

◆ basebandPhaseForTriangleTime()

RealType fers_signal::FmcwTriangleSignal::basebandPhaseForTriangleTime ( RealType  triangle_time) const
noexcept

Computes baseband phase at a time since the triangle train start.

Definition at line 124 of file radar_signal.cpp.

125 {
126 if (triangle_time <= 0.0)
127 {
128 return 0.0;
129 }
130
131 const auto triangle_index = static_cast<std::size_t>(std::floor(triangle_time / _triangle_period));
132 const RealType local_triangle_time = triangle_time - static_cast<RealType>(triangle_index) * _triangle_period;
133 const bool down_leg = local_triangle_time >= _chirp_duration;
134 const RealType u = down_leg ? local_triangle_time - _chirp_duration : local_triangle_time;
135 const RealType phi_base =
136 static_cast<RealType>(triangle_index) * 2.0 * _delta_phi_up + (down_leg ? _delta_phi_up : 0.0);
137 if (!down_leg)
138 {
139 return phi_base + 2.0 * PI * _start_frequency_offset * u + PI * _chirp_rate * u * u;
140 }
141 return phi_base + 2.0 * PI * (_start_frequency_offset + _chirp_bandwidth) * u - PI * _chirp_rate * u * u;
142 }
double RealType
Type for real numbers.
Definition config.h:27
math::Vec3 max

References max, and PI.

◆ clear()

void fers_signal::Signal::clear ( )
noexceptinherited

Clears the internal signal data.

Definition at line 232 of file radar_signal.cpp.

233 {
234 _size = 0;
235 _rate = 0;
236 }

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

+ Here is the caller graph for this function:

◆ getChirpBandwidth()

RealType fers_signal::FmcwTriangleSignal::getChirpBandwidth ( ) const
noexcept

Gets the chirp bandwidth in hertz.

Definition at line 409 of file radar_signal.h.

409{ return _chirp_bandwidth; }

◆ getChirpDuration()

RealType fers_signal::FmcwTriangleSignal::getChirpDuration ( ) const
noexcept

Gets the per-leg chirp duration in seconds.

Definition at line 412 of file radar_signal.h.

412{ return _chirp_duration; }

◆ getChirpRate()

RealType fers_signal::FmcwTriangleSignal::getChirpRate ( ) const
noexcept

Gets the chirp rate magnitude in hertz per second.

Definition at line 421 of file radar_signal.h.

421{ return _chirp_rate; }

◆ getDeltaPhiUp()

RealType fers_signal::FmcwTriangleSignal::getDeltaPhiUp ( ) const
noexcept

Gets the full, unreduced phase accumulated by one leg.

Definition at line 427 of file radar_signal.h.

427{ return _delta_phi_up; }

◆ 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 86 of file radar_signal.h.

86{ return _rate; }

◆ getSampleCount()

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

Gets the number of native samples held by this signal.

Definition at line 89 of file radar_signal.h.

89{ return _size; }

◆ getStartFrequencyOffset()

RealType fers_signal::FmcwTriangleSignal::getStartFrequencyOffset ( ) const
noexcept

Gets the start frequency offset relative to carrier in hertz.

Definition at line 415 of file radar_signal.h.

415{ return _start_frequency_offset; }

◆ getTriangleCount()

const std::optional< std::size_t > & fers_signal::FmcwTriangleSignal::getTriangleCount ( ) const
noexcept

Gets the optional finite triangle count.

Definition at line 418 of file radar_signal.h.

418{ return _triangle_count; }

◆ getTrianglePeriod()

RealType fers_signal::FmcwTriangleSignal::getTrianglePeriod ( ) const
noexcept

Gets the full up/down triangle period in seconds.

Definition at line 424 of file radar_signal.h.

424{ return _triangle_period; }

◆ instantaneousBasebandPhase()

std::optional< RealType > fers_signal::FmcwTriangleSignal::instantaneousBasebandPhase ( RealType  time_since_segment_start) const
noexcept

Computes instantaneous baseband phase at a time since segment start.

Definition at line 145 of file radar_signal.cpp.

146 {
147 if (time_since_segment_start < 0.0)
148 {
149 return std::nullopt;
150 }
151
152 const auto triangle_index = static_cast<std::size_t>(std::floor(time_since_segment_start / _triangle_period));
153 if (_triangle_count.has_value() && triangle_index >= *_triangle_count)
154 {
155 return std::nullopt;
156 }
157
159 time_since_segment_start - static_cast<RealType>(triangle_index) * _triangle_period;
161 {
162 return std::nullopt;
163 }
165 }
RealType basebandPhaseForTriangleTime(RealType triangle_time) const noexcept
Computes baseband phase at a time since the triangle train start.

References max.

◆ isFmcwFamily()

bool fers_signal::FmcwTriangleSignal::isFmcwFamily ( ) const
overridevirtualnoexcept

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

Reimplemented from fers_signal::Signal.

Definition at line 443 of file radar_signal.h.

443{ return true; }

◆ isTriangle()

bool fers_signal::FmcwTriangleSignal::isTriangle ( ) const
noexcept

Returns true for triangular FMCW waveforms.

Definition at line 430 of file radar_signal.h.

430{ return true; }

◆ 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 238 of file radar_signal.cpp.

239 {
240 clear();
241 const unsigned ratio = params::oversampleRatio();
242 const auto oversampled_samples = static_cast<std::size_t>(samples) * static_cast<std::size_t>(ratio);
243 if (oversampled_samples > std::numeric_limits<unsigned>::max())
244 {
245 throw std::overflow_error("Oversampled signal sample count exceeds unsigned range");
246 }
247 _data.resize(oversampled_samples);
248 _size = static_cast<unsigned>(oversampled_samples);
249 _rate = sampleRate * static_cast<RealType>(ratio);
250
251 if (ratio == 1)
252 {
253 std::ranges::copy(inData, _data.begin());
254 }
255 else
256 {
257 upsample(inData, samples, _data);
258 }
259 }
void clear() noexcept
Clears the internal signal data.
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

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

+ Here is the call graph for this function:

◆ operator=() [1/2]

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

◆ operator=() [2/2]

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

◆ render()

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

Renders an FMCW waveform from interpolation points.

Reimplemented from fers_signal::Signal.

Definition at line 167 of file radar_signal.cpp.

169 {
170 size = 0;
171 return {};
172 }

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 272 of file radar_signal.cpp.

275 {
276 auto out = std::vector<ComplexType>(sampleCount);
277 if (_size == 0 || _rate <= 0.0 || outputSampleRate <= 0.0 || points.empty())
278 {
279 return out;
280 }
281
282 const RealType timestep = 1.0 / outputSampleRate;
283 const int filt_length = static_cast<int>(params::renderFilterLength());
285
286 auto iter = points.begin();
287 auto next = points.size() > 1 ? std::next(iter) : iter;
288 const RealType idelay = std::round(_rate * iter->delay);
290
291 for (std::size_t i = 0; i < sampleCount; ++i)
292 {
293 while (sample_time > next->time && next != iter)
294 {
295 iter = next;
296 if (std::next(next) != points.end())
297 {
298 ++next;
299 }
300 else
301 {
302 break;
303 }
304 }
305
306 auto [amplitude, phase, fdelay, i_sample_unwrap] =
307 calculateWeightsAndDelays(iter, next, sample_time, idelay, fracWinDelay);
308 const RealType native_position = (sample_time - points.front().time) * _rate;
309 const auto source_index = static_cast<int>(std::floor(native_position));
312 {
313 source_fraction = 0.0;
314 }
315
317 const auto delay_unwrap = static_cast<int>(std::floor(combined_delay));
318 fdelay = combined_delay - static_cast<RealType>(delay_unwrap);
320
321 const auto& filt = interp.getFilter(fdelay);
322 const ComplexType accum =
323 performConvolution(source_index, filt.data(), filt_length, amplitude, i_sample_unwrap);
324 out[i] = std::exp(ComplexType(0.0, 1.0) * phase) * accum;
325
327 }
328
329 return out;
330 }
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:

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