added false target that moves in radar coordinates. The movement algorithm needs work. Also added a page in controller displaying false target truth

This commit is contained in:
bennysomers 2024-02-06 14:59:12 +11:00
parent 6cdc7e0289
commit 7007efda0e
12 changed files with 418 additions and 117 deletions

View file

@ -6,6 +6,7 @@ var stash_map = require('./stash/maxhold.js');
var stash_detection = require('./stash/detection.js');
var stash_iqdata = require('./stash/iqdata.js');
var stash_timing = require('./stash/timing.js');
var stash_falsetargets = require('./stash/falsetargets.js');
// constants
const PORT = 3000;
@ -16,6 +17,7 @@ var track = '';
var timestamp = '';
var timing = '';
var iqdata = '';
var falsetargets = '';
var data = '';
var data_map;
var data_detection;
@ -23,12 +25,13 @@ var data_tracker;
var data_timestamp;
var data_timing;
var data_iqdata;
var data_falsetargets;
var capture = false;
// api server
const app = express();
// header on all requests
app.use(function(req, res, next) {
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate');
res.header('Expires', '-1');
@ -56,6 +59,9 @@ app.get('/api/timing', (req, res) => {
app.get('/api/iqdata', (req, res) => {
res.send(iqdata);
});
app.get('/api/falsetargets', (req, res) => {
res.send(falsetargets);
});
// stash API
app.get('/stash/map', (req, res) => {
@ -70,6 +76,9 @@ app.get('/stash/iqdata', (req, res) => {
app.get('/stash/timing', (req, res) => {
res.send(stash_timing.get_data_timing());
});
app.get('/stash/falsetargets', (req, res) => {
res.send(stash_falsetargets.get_data_falsetargets());
});
// read state of capture
app.get('/capture', (req, res) => {
@ -85,100 +94,111 @@ app.listen(PORT, HOST, () => {
});
// tcp listener map
const server_map = net.createServer((socket)=>{
socket.write("Hello From Server!")
socket.on("data",(msg)=>{
data_map = data_map + msg.toString();
if (data_map.slice(-1) === "}")
{
map = data_map;
data_map = '';
}
});
socket.on("close",()=>{
console.log("Connection closed.");
})
const server_map = net.createServer((socket) => {
socket.write("Hello From Server!")
socket.on("data", (msg) => {
data_map = data_map + msg.toString();
if (data_map.slice(-1) === "}") {
map = data_map;
data_map = '';
}
});
socket.on("close", () => {
console.log("Connection closed.");
})
});
server_map.listen(3001);
// tcp listener detection
const server_detection = net.createServer((socket)=>{
const server_detection = net.createServer((socket) => {
socket.write("Hello From Server!")
socket.on("data",(msg)=>{
data_detection = data_detection + msg.toString();
if (data_detection.slice(-1) === "}")
{
detection = data_detection;
data_detection = '';
}
socket.on("data", (msg) => {
data_detection = data_detection + msg.toString();
if (data_detection.slice(-1) === "}") {
detection = data_detection;
data_detection = '';
}
});
socket.on("close",()=>{
console.log("Connection closed.");
socket.on("close", () => {
console.log("Connection closed.");
})
});
server_detection.listen(3002);
// tcp listener tracker
const server_tracker = net.createServer((socket)=>{
const server_tracker = net.createServer((socket) => {
socket.write("Hello From Server!")
socket.on("data",(msg)=>{
data_tracker = data_tracker + msg.toString();
if (data_tracker.slice(-1) === "}")
{
track = data_tracker;
data_tracker = '';
}
socket.on("data", (msg) => {
data_tracker = data_tracker + msg.toString();
if (data_tracker.slice(-1) === "}") {
track = data_tracker;
data_tracker = '';
}
});
socket.on("close",()=>{
console.log("Connection closed.");
socket.on("close", () => {
console.log("Connection closed.");
})
});
server_tracker.listen(3003);
// tcp listener timestamp
const server_timestamp = net.createServer((socket)=>{
const server_timestamp = net.createServer((socket) => {
socket.write("Hello From Server!")
socket.on("data",(msg)=>{
socket.on("data", (msg) => {
data_timestamp = data_timestamp + msg.toString();
timestamp = data_timestamp;
data_timestamp = '';
});
socket.on("close",()=>{
console.log("Connection closed.");
socket.on("close", () => {
console.log("Connection closed.");
})
});
server_timestamp.listen(4000);
// tcp listener timing
const server_timing = net.createServer((socket)=>{
const server_timing = net.createServer((socket) => {
socket.write("Hello From Server!")
socket.on("data",(msg)=>{
socket.on("data", (msg) => {
data_timing = data_timing + msg.toString();
if (data_timing.slice(-1) === "}")
{
if (data_timing.slice(-1) === "}") {
timing = data_timing;
data_timing = '';
}
});
socket.on("close",()=>{
console.log("Connection closed.");
socket.on("close", () => {
console.log("Connection closed.");
})
});
server_timing.listen(4001);
// tcp listener iqdata metadata
const server_iqdata = net.createServer((socket)=>{
const server_iqdata = net.createServer((socket) => {
socket.write("Hello From Server!")
socket.on("data",(msg)=>{
socket.on("data", (msg) => {
data_iqdata = data_iqdata + msg.toString();
if (data_iqdata.slice(-1) === "}")
{
if (data_iqdata.slice(-1) === "}") {
iqdata = data_iqdata;
data_iqdata = '';
}
});
socket.on("close",()=>{
console.log("Connection closed.");
socket.on("close", () => {
console.log("Connection closed.");
})
});
server_iqdata.listen(4002);
// tcp listener falsetargets
const server_falsetargets = net.createServer((socket) => {
socket.write("Hello From Server!")
socket.on("data", (msg) => {
data_falsetargets = data_falsetargets + msg.toString();
if (data_falsetargets.slice(-1) === "}") {
falsetargets = data_falsetargets;
data_falsetargets = '';
}
});
socket.on("close", () => {
console.log("Connection closed.");
})
});
server_falsetargets.listen(4003);

50
api/stash/falsetargets.js Normal file
View file

@ -0,0 +1,50 @@
const http = require('http');
var falsetargets = [];
frequency = [];
var ts = '';
var output = [];
const options_falsetargets = {
host: '127.0.0.1',
path: '/api/falsetargets',
port: 3000
};
function update_data() {
// check if timestamp is updated
http.get(options_falsetargets, function (res) {
res.setEncoding('utf8');
res.on('data', function (body) {
if (ts != body) {
ts = body;
http.get(options_falsetargets, function (res) {
let body_map = '';
res.setEncoding('utf8');
res.on('data', (chunk) => {
body_map += chunk;
});
res.on('end', () => {
try {
output = JSON.parse(body_map);
// false targets
falsetargets.push(output.falsetargets);
} catch (e) {
console.error(e.message);
}
});
});
}
});
});
};
setInterval(update_data, 100);
function get_data() {
return output;
};
module.exports.get_data_falsetargets = get_data;

View file

@ -2,7 +2,7 @@ capture:
fs: 2000000
fc: 204640000
device:
type: "RspDuo"
type: "IqSimulator"
replay:
state: false
loop: true
@ -14,13 +14,13 @@ process:
buffer: 1.5
overlap: 0
ambiguity:
delayMin: -10
delayMax: 400
dopplerMin: -200
dopplerMax: 200
delayMin: -10 # bins
delayMax: 400 # bins
dopplerMin: -200 # Hz
dopplerMax: 200 # Hz
clutter:
delayMin: -10
delayMax: 400
delayMin: -10 # bins
delayMax: 400 # bins
detection:
pfa: 0.00001
nGuard: 2
@ -46,6 +46,7 @@ network:
timestamp: 4000
timing: 4001
iqdata: 4002
falsetargets: 4003
truth:
asdb:
@ -58,7 +59,7 @@ truth:
port: 30001
save:
iq: true
iq: false
map: false
detection: false
timing: false

View file

@ -1,5 +1,5 @@
targets:
- id: 1
- id: 0
type: "static"
location:
range: 10000 # meters
@ -8,11 +8,21 @@ targets:
rcs: -20 # dBsm - this is a bit contrived for a static target
state: "active"
- id: 2
- id: 1
type: "static"
location:
range: 30000 # meters
velocity:
doppler: -150 # Hertz
rcs: -20 # dBsm
state: "active"
- id: 2
type: "moving_radar"
location:
range: 5000 # meters
velocity:
doppler: 100 # Hertz
dopplerRate: 0 # Hertz/second
rcs: -20 # dBsm - this is also contrived
state: "active"

View file

@ -38,6 +38,7 @@
<li class="py-1"><a class="text-reset text-decoration-none" href="/display/detection/delay-doppler">Detections in delay-Doppler over time</a></li>
<li class="py-1"><a class="text-reset text-decoration-none" href="/display/spectrum">Spectrum reference</a></li>
<li class="py-1"><a class="text-reset text-decoration-none" href="/display/timing">Timing display</a></li>
<li class="py-1"><a class="text-reset text-decoration-none" href="/display/falsetargets">False Target Data</a></li>
</ul>
</div>
<div class="col-sm-12 col-md-12">

View file

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="UTF-8">
<title>blah2</title>
<!-- load lib js -->
<script src="../../lib/bootstrap-5.2.3.min.js"></script>
<script src="../../lib/jquery-3.6.4.min.js"></script>
<!-- load lib css -->
<link rel="stylesheet" href="../../lib/bootstrap-5.2.3.min.css">
<style>
</style>
</head>
<body style="background-color:#f78c58;">
<div style="height: 100vh; width: 95vw" class="container-fluid">
<div style="height: 100vh; width: 95vw" class="row d-flex">
<div class="justify-content-center" id="data"></div>
</div>
</body>
<script>
xTitle = "False Targets";
</script>
<script src="../../js/table_falsetargets.js"></script>
</html>

View file

@ -0,0 +1,60 @@
var host = window.location.hostname;
var isLocalHost = (host === "localhost" || host === "127.0.0.1" || host === "192.168.0.112");
// setup API
var urlFalseTargets;
if (isLocalHost) {
urlFalseTargets = '//' + host + ':3000/api/falsetargets';
} else {
urlFalseTargets = '//' + host + '/api/falsetargets';
}
//callback function
var intervalId = window.setInterval(function () {
$.getJSON(urlFalseTargets, function (data) {
if (data != null) {
var table = document.getElementById("data");
// PLEASE SOMEONE FORMAT THIS NICER! //
var output = "";
data.false_targets.forEach((target) => {
output += "id: " + target.id + "<br>";
output += "<ul> <li>" + target.type + "</li>";
if (target.type === "static") {
output += "<li> delay: " + target.delay + "</li>";
output += "<li> delay_samples: " + target.delay_samples + "</li>";
output += "<li> range: " + target.range + "</li>";
output += "<li> doppler: " + target.doppler + "</li>";
output += "<li> rcs: " + target.rcs + "</li>";
} else if (target.type === "moving_radar") {
output += "<li> delay: " + target.delay + "</li>";
output += "<li> delay_samples: " + target.delay_samples + "</li>";
output += "<li> range: " + target.range + "</li>";
output += "<li> start_range: " + target.start_range + "</li>";
output += "<li> doppler: " + target.doppler + "</li>";
output += "<li> doppler_rate: " + target.doppler_rate + "</li>";
output += "<li> rcs: " + target.rcs + "</li>";
}
output += "</ul>";
});
table.innerHTML = output;
// data.false_targets.foreach((targetjson) => {
// target = JSON.parse(targetjson);
// console.log(target);
// });
// for (var i = 0; i < data.length; i++) {
// var row = table.insertRow(i + 1);
// var cell1 = row.insertCell(0);
// var cell2 = row.insertCell(1);
// var cell3 = row.insertCell(2);
// cell1.innerHTML = data[i].x;
// cell2.innerHTML = data[i].y;
// cell3.innerHTML = data[i].z;
// }
}
});
}, 100);

View file

@ -92,9 +92,7 @@ std::unique_ptr<Source> Capture::factory_source(const std::string &type, c4::yml
{
uint32_t n_min;
n_min = 2000000;
std::string false_targets_config_file_path = "config/false_targets.yml";
return std::make_unique<IqSimulator>(type, fc, fs, path, &saveIq, n_min,
false_targets_config_file_path);
return std::make_unique<IqSimulator>(type, fc, fs, path, &saveIq, n_min);
}
// Handle unknown type
std::cerr << "Error: Source type does not exist." << std::endl;

View file

@ -4,12 +4,14 @@
IqSimulator::IqSimulator(std::string _type, uint32_t _fc, uint32_t _fs,
std::string _path, bool *_saveIq,
uint32_t _n_min = 1000,
std::string _falseTargetsConfigFilePath = "config/false_targets.yml")
std::string _falseTargetsConfigFilePath,
std::string _configFilePath)
: Source(_type, _fc, _fs, _path, _saveIq)
{
n_min = _n_min;
u_int64_t total_samples = 0;
false_targets_config_file_path = _falseTargetsConfigFilePath;
config_file_path = _configFilePath;
}
void IqSimulator::start()
@ -24,7 +26,7 @@ void IqSimulator::process(IqData *buffer1, IqData *buffer2)
{
const u_int32_t samples_per_iteration = 1000;
TgtGen false_targets = TgtGen(false_targets_config_file_path, fs);
TgtGen false_targets = TgtGen(false_targets_config_file_path, config_file_path, fs, fc);
while (true)
{
uint32_t n_start = buffer1->get_length();

View file

@ -41,6 +41,9 @@ private:
/// @brief Path to the false targets configuration file.
std::string false_targets_config_file_path;
/// @brief Path to the radar configuration file.
std::string config_file_path;
public:
/// @brief Constructor.
/// @param type Type of source. = "IQSimulator"
@ -51,7 +54,9 @@ public:
/// @param n Number of samples.
/// @return The object.
IqSimulator(std::string type, uint32_t fc, uint32_t fs, std::string path,
bool *saveIq, uint32_t n_min, std::string false_targets_config_file_path);
bool *saveIq, uint32_t n_min,
std::string false_targets_config_file_path = "config/false_targets.yml",
std::string config_file_path = "config/config.yml");
/// @brief Implement capture function on IQSimulator.
/// @param buffer1 Pointer to reference buffer.

View file

@ -5,14 +5,14 @@
std::string ryml_get_file_copy(const char *filename);
// constants
const std::string TgtGen::VALID_TYPE[1] = {"static"};
const std::string TgtGen::VALID_TYPE[2] = {"static", "moving_radar"};
const std::string TgtGen::VALID_STATE[1] = {"active"};
// constructor
TgtGen::TgtGen(std::string configPath, uint32_t fs)
TgtGen::TgtGen(std::string false_tgt_config_path, std::string config_path, uint32_t fs, uint32_t fc)
{
// Read in the config file
std::string config = ryml_get_file_copy(configPath.c_str());
// Read in the false targets config file
std::string config = ryml_get_file_copy(false_tgt_config_path.c_str());
ryml::Tree tree = ryml::parse_in_arena(ryml::to_csubstr(config));
// Create a FalseTarget object for each target in the config file
@ -22,7 +22,7 @@ TgtGen::TgtGen(std::string configPath, uint32_t fs)
{
try
{
targets.push_back(FalseTarget(target_node, fs));
targets.push_back(FalseTarget(target_node, fs, fc));
}
catch (const std::exception &e)
{
@ -30,23 +30,55 @@ TgtGen::TgtGen(std::string configPath, uint32_t fs)
}
}
}
// Create the socket using details from the config file.
config = ryml_get_file_copy(config_path.c_str());
tree = ryml::parse_in_arena(ryml::to_csubstr(config));
std::string ip;
uint16_t port;
tree["network"]["ip"] >> ip;
tree["network"]["ports"]["falsetargets"] >> port;
socket = new Socket(ip, port);
sample_counter = 0;
}
std::complex<double> TgtGen::process(IqData *ref_buffer)
{
std::complex<double> response = std::complex<double>(0, 0);
// loop through each target
for (auto target : targets)
for (auto &target : targets)
{
response += target.process(ref_buffer);
}
return response;
}
// output false target truth
if (sample_counter % 100000 == 0)
{
rapidjson::Document document;
document.SetObject();
rapidjson::Document::AllocatorType &allocator = document.GetAllocator();
rapidjson::Value json_false_targets(rapidjson::kArrayType);
for (auto target : targets)
{
json_false_targets.PushBack(target.to_json(allocator), allocator);
}
std::string FalseTarget::get_type()
{
return type;
document.AddMember("false_targets", json_false_targets, allocator);
rapidjson::StringBuffer strbuf;
rapidjson::Writer<rapidjson::StringBuffer> writer(strbuf);
writer.SetMaxDecimalPlaces(2);
document.Accept(writer);
socket->sendData(strbuf.GetString());
}
sample_counter++;
return response;
}
double FalseTarget::get_range()
@ -54,14 +86,11 @@ double FalseTarget::get_range()
return range;
}
double FalseTarget::get_doppler()
void FalseTarget::set_range(double _range)
{
return doppler;
}
double FalseTarget::get_rcs()
{
return rcs;
range = _range;
delay = range / Constants::c;
delay_samples = delay * fs;
}
double FalseTarget::get_delay()
@ -69,40 +98,72 @@ double FalseTarget::get_delay()
return delay;
}
u_int32_t FalseTarget::get_id()
void FalseTarget::set_delay(double _delay)
{
return id;
delay = _delay;
range = delay * Constants::c;
delay_samples = delay * fs;
}
FalseTarget::FalseTarget(c4::yml::NodeRef target_node, uint32_t _fs)
FalseTarget::FalseTarget(c4::yml::NodeRef target_node, uint32_t _fs, uint32_t _fc)
{
target_node["id"] >> id;
target_node["type"] >> type;
fs = _fs;
fc = _fc;
sample_counter = 0;
if (type == TgtGen::VALID_TYPE[0])
{
target_node["location"]["range"] >> range;
delay = range / 3e8;
delay = range / Constants::c;
delay_samples = delay * fs;
target_node["velocity"]["doppler"] >> doppler;
target_node["rcs"] >> rcs;
}
else if (type == TgtGen::VALID_TYPE[1])
{
target_node["location"]["range"] >> range;
start_range = range;
delay = range / Constants::c;
delay_samples = delay * fs;
target_node["velocity"]["doppler"] >> doppler;
target_node["velocity"]["dopplerRate"] >> doppler_rate;
target_node["rcs"] >> rcs;
}
else
{
throw std::invalid_argument("Invalid target type");
}
}
std::complex<double> FalseTarget::process(IqData *buffer)
std::complex<double> FalseTarget::process(IqData *ref_buffer)
{
uint32_t buffer_length = buffer->get_length();
uint32_t buffer_length = ref_buffer->get_length();
std::complex<double> response = 0;
try
{
response = Conversions::db2lin(rcs) * buffer->get_sample(buffer_length - delay_samples);
response = Conversions::db2lin(rcs) * ref_buffer->get_sample(buffer_length - delay_samples);
response *= std::exp(std::polar<double>(1, 2 * M_PI * doppler * buffer_length / fs));
if (type == TgtGen::VALID_TYPE[1])
{
double range_rate = -1 * doppler * Constants::c / 2.0 / fc;
set_range(range + (range_rate / fs));
// very basic PD controller
// will need tuning for different fs
doppler_rate += 0.0000001 * (range - start_range) / start_range; // target tends towards start_range
// doppler_rate -= doppler / std::abs(doppler) / std::max(std::abs(doppler), 0.1) / 100; // target tends towards 0 Doppler
doppler_rate = std::clamp(doppler_rate, -5.0, 5.0); // clamp to a reasonable value
doppler += doppler_rate / fs; // update doppler
doppler = std::clamp(doppler,
std::max(-range, -250.0),
std::min(range, 250.0)); // clamp to range
}
sample_counter++;
}
catch (const std::exception &e)
{
@ -111,6 +172,46 @@ std::complex<double> FalseTarget::process(IqData *buffer)
return response;
}
rapidjson::Value FalseTarget::to_json(rapidjson::Document::AllocatorType &allocator)
{
rapidjson::Value target(rapidjson::kObjectType);
target.AddMember("id", id, allocator);
target.AddMember("type", rapidjson::Value(type.c_str(), allocator).Move(), allocator);
try
{
if (type == TgtGen::VALID_TYPE[0])
{
target.AddMember("range", range, allocator);
target.AddMember("delay", delay, allocator);
target.AddMember("delay_samples", delay_samples, allocator);
target.AddMember("doppler", doppler, allocator);
target.AddMember("rcs", rcs, allocator);
}
else if (type == TgtGen::VALID_TYPE[1])
{
target.AddMember("range", range, allocator);
target.AddMember("start_range", start_range, allocator);
target.AddMember("delay", delay, allocator);
target.AddMember("delay_samples", delay_samples, allocator);
target.AddMember("doppler", doppler, allocator);
target.AddMember("doppler_rate", doppler_rate, allocator);
target.AddMember("rcs", rcs, allocator);
}
else
{
throw std::invalid_argument("Invalid target type");
}
}
catch (const std::exception &e)
{
std::cerr << e.what() << '\n';
}
return target;
}
std::string ryml_get_file_copy(const char *filename)
{
std::ifstream in(filename, std::ios::in | std::ios::binary);

View file

@ -14,17 +14,27 @@
#include "data/IqData.h"
#include "utilities/Conversions.h"
#include "data/meta/Constants.h"
#include "process/utility/Socket.h"
#include <ryml/ryml.hpp>
#include <ryml/ryml_std.hpp>
#include <c4/format.hpp>
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/filewritestream.h"
#include <stdint.h>
#include <string>
#include <iostream>
#include <vector>
#include <fstream>
#include <complex>
#include <math.h>
#include <iomanip>
class FalseTarget
{
@ -32,8 +42,8 @@ private:
/// @brief fs
uint32_t fs;
/// @brief Target type.
std::string type;
/// @brief fc
uint32_t fc;
/// @brief Target delay
double delay;
@ -44,48 +54,56 @@ private:
/// @brief Target range
double range;
/// @brief Target starting range
double start_range;
/// @brief Sample counter
uint64_t sample_counter;
public:
/// @brief Target type.
std::string type;
/// @brief Target Doppler
double doppler;
/// @brief Target Doppler Rate
double doppler_rate;
/// @brief Target RCS
double rcs;
/// @brief Target ID
u_int32_t id;
public:
/// @brief Constructor for targets.
/// @return The object.
FalseTarget(c4::yml::NodeRef target_node, uint32_t _fs);
FalseTarget(c4::yml::NodeRef target_node, uint32_t _fs, uint32_t _fc);
/// @brief Generate the signal from a false target.
/// @param buffer Pointer to reference buffer.
/// @param ref_buffer Pointer to reference buffer.
/// @return Target reflection signal.
std::complex<double> process(IqData *buffer);
std::complex<double> process(IqData *ref_buffer);
/// @brief Getter for target type.
/// @return Target type.
std::string get_type();
/// @brief Getter for target range.type
/// @return Target range.
/// @brief Getter for range.
/// @return Range in meters.
double get_range();
/// @brief Getter for target Doppler.
/// @return Target Doppler.
double get_doppler();
/// @brief Setter for range.
/// @param range Range in meters.
void set_range(double range);
/// @brief Getter for target RCS.
/// @return Target RCS.
double get_rcs();
/// @brief Getter for target delay.
/// @return Target delay.
/// @brief Getter for delay.
/// @return Delay in seconds.
double get_delay();
/// @brief Getter for target id.
/// @return Target id.
u_int32_t get_id();
/// @brief Setter for delay.
/// @param delay Delay in seconds.
void set_delay(double delay);
/// @brief Outputs false target truth as JSON
/// @return JSON string.
rapidjson::Value to_json(rapidjson::Document::AllocatorType &allocator);
};
class TgtGen
@ -94,16 +112,26 @@ private:
/// @brief Vector of false targets.
std::vector<FalseTarget> targets;
/// @brief Socket to send false target data.
Socket *socket;
/// @brief Sample counter
uint64_t sample_counter;
public:
/// @brief The valid false target types.
static const std::string VALID_TYPE[1];
static const std::string VALID_TYPE[2];
/// @brief The valid false target states.
static const std::string VALID_STATE[1];
/// @brief Constructor.
/// @param false_tgt_config_path Path to false targets configuration file.
/// @param config_path Path to blah2 config file.
/// @param fs Sample rate (Hz).
/// @param fc Center frequency (Hz).
/// @return The object.
TgtGen(std::string configPath, uint32_t fs);
TgtGen(std::string false_tgt_config_path, std::string config_path, uint32_t fs, uint32_t fc);
/// @brief Generate the signal from all false targets.
/// @param ref_buffer Pointer to reference buffer.