FERS 1.0.0
The Flexible Extensible Radar Simulator
Loading...
Searching...
No Matches
radar_signal.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-only
2//
3// Copyright (c) 2006-2008 Marc Brooker and Michael Inggs
4// Copyright (c) 2008-present FERS Contributors (see AUTHORS.md).
5//
6// See the GNU GPLv2 LICENSE file in the FERS project root for more information.
7
8/**
9 * @file radar_signal.cpp
10 * @brief Classes for handling radar waveforms and signals.
11 */
12
13#include "radar_signal.h"
14
15#include <algorithm>
16#include <cmath>
17#include <complex>
18#include <iterator>
19#include <stdexcept>
20#include <utility>
21
22#include "core/parameters.h"
23#include "dsp_filters.h"
26
27namespace fers_signal
28{
29 std::vector<ComplexType> CwSignal::render(const std::vector<interp::InterpPoint>& points, unsigned& size,
30 const RealType /*fracWinDelay*/) const
31 {
32 size = 0;
33 return {};
34 }
35
36 RadarSignal::RadarSignal(std::string name, const RealType power, const RealType carrierfreq, const RealType length,
37 std::unique_ptr<Signal> signal) :
38 _name(std::move(name)), _power(power), _carrierfreq(carrierfreq), _length(length), _signal(std::move(signal))
39 {
40 if (!_signal)
41 {
42 throw std::runtime_error("Signal is empty");
43 }
44 }
45
46 std::vector<ComplexType> RadarSignal::render(const std::vector<interp::InterpPoint>& points, unsigned& size,
47 const RealType fracWinDelay) const
48 {
49 auto data = _signal->render(points, size, fracWinDelay);
50 const RealType scale = std::sqrt(_power);
51
52 std::ranges::for_each(data, [scale](auto& value) { value *= scale; });
53
54 return data;
55 }
56
57 void Signal::clear() noexcept
58 {
59 _size = 0;
60 _rate = 0;
61 }
62
63 void Signal::load(std::span<const ComplexType> inData, const unsigned samples, const RealType sampleRate)
64 {
65 clear();
66 const unsigned ratio = params::oversampleRatio();
67 _data.resize(samples * ratio);
68 _size = samples * ratio;
69 _rate = sampleRate * ratio;
70
71 if (ratio == 1)
72 {
73 std::ranges::copy(inData, _data.begin());
74 }
75 else
76 {
77 upsample(inData, samples, _data);
78 }
79 }
80
81 std::vector<ComplexType> Signal::render(const std::vector<interp::InterpPoint>& points, unsigned& size,
82 const double fracWinDelay) const
83 {
84 auto out = std::vector<ComplexType>(_size);
85 size = _size;
86
87 const RealType timestep = 1.0 / _rate;
88 const int filt_length = static_cast<int>(params::renderFilterLength());
90
91 auto iter = points.begin();
92 auto next = points.size() > 1 ? std::next(iter) : iter;
93 const RealType idelay = std::round(_rate * iter->delay);
94 RealType sample_time = iter->time;
95
96 for (int i = 0; i < static_cast<int>(_size); ++i)
97 {
98 if (sample_time > next->time && next != iter)
99 {
100 iter = next;
101 if (std::next(next) != points.end())
102 {
103 ++next;
104 }
105 }
106
107 auto [amplitude, phase, fdelay, i_sample_unwrap] =
108 calculateWeightsAndDelays(iter, next, sample_time, idelay, fracWinDelay);
109 const auto& filt = interp.getFilter(fdelay);
110 ComplexType accum = performConvolution(i, filt.data(), filt_length, amplitude, i_sample_unwrap);
111 out[i] = std::exp(ComplexType(0.0, 1.0) * phase) * accum;
112
113 sample_time += timestep;
114 }
115
116 return out;
117 }
118
119 constexpr std::tuple<RealType, RealType, RealType, int>
120 Signal::calculateWeightsAndDelays(const std::vector<interp::InterpPoint>::const_iterator iter,
121 const std::vector<interp::InterpPoint>::const_iterator next,
122 const RealType sampleTime, const RealType idelay,
123 const RealType fracWinDelay) const noexcept
124 {
125 const RealType bw = iter < next ? (sampleTime - iter->time) / (next->time - iter->time) : 0.0;
126
127 const RealType amplitude = std::lerp(std::sqrt(iter->power), std::sqrt(next->power), bw);
128 const RealType phase = std::lerp(iter->phase, next->phase, bw);
129 RealType fdelay = -(std::lerp(iter->delay, next->delay, bw) * _rate - idelay + fracWinDelay);
130
131 const int i_sample_unwrap = static_cast<int>(std::floor(fdelay));
132 fdelay -= i_sample_unwrap;
133
134 return {amplitude, phase, fdelay, i_sample_unwrap};
135 }
136
137 ComplexType Signal::performConvolution(const int i, const RealType* filt, const int filtLength,
138 const RealType amplitude, const int iSampleUnwrap) const noexcept
139 {
140 const int start = std::max(-filtLength / 2, -i);
141 const int end = std::min(filtLength / 2, static_cast<int>(_size) - i);
142
143 ComplexType accum(0.0, 0.0);
144
145 for (int j = start; j < end; ++j)
146 {
147 if (const unsigned sample_idx = i + j + iSampleUnwrap;
148 sample_idx < _size && j + filtLength / 2 < filtLength)
149 {
150 accum += amplitude * _data[sample_idx] * filt[j + filtLength / 2];
151 }
152 }
153
154 return accum;
155 }
156}
std::vector< ComplexType > render(const std::vector< interp::InterpPoint > &points, unsigned &size, RealType fracWinDelay) const override
Renders the signal data.
RadarSignal(std::string name, RealType power, RealType carrierfreq, RealType length, std::unique_ptr< Signal > signal)
Constructs a RadarSignal object.
std::vector< ComplexType > render(const std::vector< interp::InterpPoint > &points, unsigned &size, RealType fracWinDelay) const
Renders the radar signal.
void clear() noexcept
Clears the internal signal data.
void load(std::span< const ComplexType > inData, unsigned samples, RealType sampleRate)
Loads complex radar waveform data.
virtual std::vector< ComplexType > render(const std::vector< interp::InterpPoint > &points, unsigned &size, double fracWinDelay) const
Renders the signal data based on interpolation points.
static InterpFilter & getInstance() noexcept
Retrieves the singleton instance of the InterpFilter class.
double RealType
Type for real numbers.
Definition config.h:27
std::complex< RealType > ComplexType
Type for complex numbers.
Definition config.h:35
Header file for Digital Signal Processing (DSP) filters and upsampling/downsampling functionality.
Interpolation filter implementation using Kaiser windowing.
Defines a structure to store interpolation point data for signal processing.
void upsample(const std::span< const ComplexType > in, const unsigned size, std::span< ComplexType > out)
Upsamples a signal by a given ratio.
unsigned oversampleRatio() noexcept
Get the oversampling ratio.
Definition parameters.h:139
unsigned renderFilterLength() noexcept
Get the render filter length.
Definition parameters.h:127
Defines the Parameters struct and provides methods for managing simulation parameters.
Classes for handling radar waveforms and signals.