FERS 0.1.0
The Flexible Extensible Radar Simulator
Loading...
Searching...
No Matches
api.cpp File Reference

Implementation of the C-style FFI for the libfers core library. More...

#include <algorithm>
#include <cmath>
#include <core/logging.h>
#include <core/parameters.h>
#include <core/sim_id.h>
#include <cstddef>
#include <cstdint>
#include <filesystem>
#include <format>
#include <functional>
#include <iterator>
#include <libfers/api.h>
#include <limits>
#include <math/path.h>
#include <math/rotation_path.h>
#include <mutex>
#include <nlohmann/json.hpp>
#include <optional>
#include <span>
#include <string>
#include <utility>
#include <vector>
#include "antenna/antenna_factory.h"
#include "core/fers_context.h"
#include "core/memory_projection.h"
#include "core/sim_threading.h"
#include "core/thread_pool.h"
#include "fers_version.h"
#include "serial/json_serializer.h"
#include "serial/kml_generator.h"
#include "serial/rotation_angle_utils.h"
#include "serial/rotation_warning_utils.h"
#include "serial/xml_parser.h"
#include "serial/xml_serializer.h"
#include "signal/radar_signal.h"
#include "simulation/channel_model.h"
+ Include dependency graph for api.cpp:

Go to the source code of this file.

Classes

struct  fers_context
 

Functions

static void handle_api_exception (const std::exception &e, const std::string &function_name)
 Centralized exception handler for the C-API boundary.
 
static void begin_warning_capture () noexcept
 
static void complete_warning_capture ()
 
static void discard_warning_capture () noexcept
 
fers_context_tfers_context_create ()
 Creates a new FERS simulation context.
 
void fers_context_destroy (fers_context_t *context)
 Destroys a FERS simulation context and releases all associated memory.
 
static logging::Level map_api_log_level (fers_log_level_t level)
 
static fers_log_level_t map_internal_log_level (logging::Level level)
 
int fers_configure_logging (fers_log_level_t level, const char *log_file_path)
 Configures the internal logger.
 
const charfers_get_version (void)
 Returns the library version string.
 
fers_log_level_t fers_get_log_level ()
 Returns the current internal logger level.
 
void fers_set_log_callback (fers_log_callback_t callback, void *user_data)
 Registers a callback for formatted log lines.
 
void fers_log (fers_log_level_t level, const char *message)
 Submits a log message to the library's unified logging system.
 
int fers_set_thread_count (unsigned num_threads)
 Sets the number of worker threads for the simulation.
 
int fers_set_output_directory (fers_context_t *context, const char *out_dir)
 Sets the output directory for simulation results.
 
int fers_use_hdf5_output (fers_context_t *context)
 Resets the context output mode to the default HDF5 output.
 
int fers_enable_vita49_udp_output (fers_context_t *context, const char *host, const std::uint16_t port)
 
int fers_set_vita49_fullscale (fers_context_t *context, const double fullscale)
 Sets the fixed ADC full-scale value used by the FERS VITA 49.2 int16 IQ profile.
 
int fers_set_vita49_epoch_unix_nanoseconds (fers_context_t *context, const std::uint64_t epoch_unix_nanoseconds)
 
int fers_set_vita49_max_udp_payload (fers_context_t *context, const std::uint16_t max_udp_payload)
 
int fers_set_vita49_queue_depth (fers_context_t *context, const std::uint32_t queue_depth)
 
int fers_set_vita49_packet_trace_enabled (fers_context_t *context, const int enabled)
 Enables or disables FERS VITA 49.2 packet trace telemetry.
 
int fers_load_scenario_from_xml_file (fers_context_t *context, const char *xml_filepath, const int validate)
 Loads a scenario into the context from a FERS XML file.
 
int fers_load_scenario_from_xml_string (fers_context_t *context, const char *xml_content, const int validate)
 Loads a scenario into the context from a FERS XML string.
 
charfers_get_scenario_as_json (fers_context_t *context)
 Serializes the current simulation scenario into a JSON string.
 
charfers_get_scenario_as_xml (fers_context_t *context)
 Serializes the current simulation scenario into a FERS XML string.
 
charfers_get_last_output_metadata_json (fers_context_t *context)
 Returns JSON metadata for the most recent simulation output files.
 
charfers_get_memory_projection_json (fers_context_t *context)
 Returns a JSON projection of simulation startup memory and HDF5 payload size.
 
int fers_update_platform_from_json (fers_context_t *context, uint64_t id, const char *json)
 Updates a single platform's paths and name from JSON without full context recreation.
 
int fers_update_parameters_from_json (fers_context_t *context, const char *json)
 Updates the global simulation parameters from JSON without full context recreation.
 
int fers_update_antenna_from_json (fers_context_t *context, const char *json)
 Updates a single antenna from JSON without full context recreation.
 
int fers_update_waveform_from_json (fers_context_t *context, const char *json)
 Updates a single waveform from JSON without full context recreation.
 
int fers_update_transmitter_from_json (fers_context_t *context, uint64_t id, const char *json)
 Updates a single transmitter from JSON without full context recreation.
 
int fers_update_receiver_from_json (fers_context_t *context, uint64_t id, const char *json)
 Updates a single receiver from JSON without full context recreation.
 
int fers_update_target_from_json (fers_context_t *context, uint64_t id, const char *json)
 Updates a single target from JSON without full context recreation.
 
int fers_update_monostatic_from_json (fers_context_t *context, const char *json)
 Updates a monostatic radar from JSON without full context recreation.
 
int fers_update_timing_from_json (fers_context_t *context, uint64_t id, const char *json)
 Updates a single timing source from JSON without full context recreation.
 
int fers_update_scenario_from_json (fers_context_t *context, const char *scenario_json)
 Updates the simulation scenario from a JSON string.
 
charfers_get_last_error_message ()
 Retrieves the last error message that occurred on the current thread.
 
charfers_get_last_warning_messages_json ()
 Returns the last deduplicated rotation-unit warning list for the calling thread as JSON.
 
void fers_free_string (char *str)
 Frees a string that was allocated and returned by the libfers API.
 
int fers_run_simulation (fers_context_t *context, fers_progress_callback_t callback, void *user_data)
 Runs the simulation defined in the provided context.
 
int fers_run_simulation_ex (fers_context_t *context, fers_progress_callback_t progress_callback, void *progress_user_data, fers_cancel_callback_t cancel_callback, void *cancel_user_data, fers_vita49_telemetry_callback_t vita49_telemetry_callback, void *vita49_telemetry_user_data)
 Runs the simulation with optional progress, cancellation, and VITA telemetry callbacks.
 
int fers_generate_kml (const fers_context_t *context, const char *output_kml_filepath)
 Generates a KML file for visualizing the scenario in the context.
 
math::Path::InterpType to_cpp_interp_type (const fers_interp_type_t type)
 
math::RotationPath::InterpType to_cpp_rot_interp_type (const fers_interp_type_t type)
 
fers_interpolated_path_tfers_get_interpolated_motion_path (const fers_motion_waypoint_t *waypoints, const size_t waypoint_count, const fers_interp_type_t interp_type, const size_t num_points)
 Calculates an interpolated motion path from a set of waypoints.
 
void fers_free_interpolated_motion_path (fers_interpolated_path_t *path)
 Frees the memory allocated for an interpolated motion path.
 
fers_interpolated_rotation_path_tfers_get_interpolated_rotation_path (const fers_rotation_waypoint_t *waypoints, const size_t waypoint_count, const fers_interp_type_t interp_type, const fers_angle_unit_t angle_unit, const size_t num_points)
 Calculates an interpolated rotation path from a set of waypoints.
 
void fers_free_interpolated_rotation_path (fers_interpolated_rotation_path_t *path)
 Frees the memory allocated for an interpolated rotation path.
 
fers_antenna_pattern_data_tfers_get_antenna_pattern (const fers_context_t *context, const uint64_t antenna_id, const size_t az_samples, const size_t el_samples, const double frequency_hz)
 Samples the gain pattern of a specified antenna and provides the data.
 
void fers_free_antenna_pattern_data (fers_antenna_pattern_data_t *data)
 Frees the memory allocated for an antenna pattern data structure.
 
fers_visual_link_list_tfers_calculate_preview_links (const fers_context_t *context, const double time)
 Calculates visual links for a specific simulation time.
 
void fers_free_preview_links (fers_visual_link_list_t *list)
 Frees the memory allocated for a preview link list.
 

Variables

thread_local std::string last_error_message
 
thread_local std::vector< std::stringlast_warning_messages
 

Detailed Description

Implementation of the C-style FFI for the libfers core library.

This file provides the C implementations for the functions declared in api.h. It acts as the bridge between the C ABI and the C++ core, handling object creation/destruction, exception catching, error reporting, and type casting.

Definition in file api.cpp.

Function Documentation

◆ begin_warning_capture()

static void begin_warning_capture ( )
staticnoexcept

Definition at line 78 of file api.cpp.

79{
82}
thread_local std::vector< std::string > last_warning_messages
Definition api.cpp:61
void clear_captured_warnings() noexcept
Clears the thread-local captured rotation warnings.

References serial::rotation_warning_utils::clear_captured_warnings(), and last_warning_messages.

Referenced by fers_load_scenario_from_xml_file(), fers_load_scenario_from_xml_string(), fers_update_parameters_from_json(), fers_update_platform_from_json(), and fers_update_scenario_from_json().

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

◆ complete_warning_capture()

static void complete_warning_capture ( )
static

Definition at line 84 of file api.cpp.

85{
87}
std::vector< std::string > take_captured_warnings()
Returns and clears the thread-local captured rotation warnings.

References last_warning_messages, and serial::rotation_warning_utils::take_captured_warnings().

Referenced by fers_load_scenario_from_xml_file(), fers_load_scenario_from_xml_string(), fers_update_parameters_from_json(), fers_update_platform_from_json(), and fers_update_scenario_from_json().

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

◆ discard_warning_capture()

static void discard_warning_capture ( )
staticnoexcept

Definition at line 89 of file api.cpp.

References serial::rotation_warning_utils::clear_captured_warnings(), and last_warning_messages.

Referenced by fers_context_create(), fers_load_scenario_from_xml_file(), fers_load_scenario_from_xml_string(), fers_update_parameters_from_json(), fers_update_platform_from_json(), and fers_update_scenario_from_json().

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

◆ fers_calculate_preview_links()

fers_visual_link_list_t * fers_calculate_preview_links ( const fers_context_t context,
double  time 
)

Calculates visual links for a specific simulation time.

Parameters
contextThe simulation context.
timeThe simulation time in seconds.
Returns
A pointer to a link list. Caller must free with fers_free_preview_links.

Definition at line 1596 of file api.cpp.

1597{
1598 last_error_message.clear();
1599 if (context == nullptr)
1600 {
1601 last_error_message = "Invalid context passed to fers_calculate_preview_links";
1603 return nullptr;
1604 }
1605
1606 try
1607 {
1608 const auto* ctx = context;
1609 // Call the core physics logic in channel_model.cpp
1610 const auto cpp_links = simulation::calculatePreviewLinks(*ctx->getWorld(), time);
1611
1612 // Convert C++ vector to C-API struct
1613 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory): Public C API returns owned preview-link lists.
1614 auto* result = new fers_visual_link_list_t();
1615 result->count = cpp_links.size();
1616
1617 if (!cpp_links.empty())
1618 {
1619 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory): Public C API frees this array with the parent list.
1620 result->links = new fers_visual_link_t[result->count];
1621 for (size_t i = 0; i < result->count; ++i)
1622 {
1623 const auto& src = cpp_links[i];
1624 auto& dst = result->links[i];
1625
1626 // Map enums
1627 switch (src.type)
1628 {
1631 break;
1634 break;
1637 break;
1640 break;
1641 }
1642
1644
1646
1647 dst.source_id = static_cast<uint64_t>(src.source_id);
1648 dst.dest_id = static_cast<uint64_t>(src.dest_id);
1649 dst.origin_id = static_cast<uint64_t>(src.origin_id);
1650 dst.rcs = src.rcs;
1651 dst.actual_power_dbm = src.actual_power_dbm;
1652 dst.display_value = src.display_value;
1653 }
1654 }
1655 else
1656 {
1657 result->links = nullptr;
1658 }
1659 return result;
1660 }
1661 catch (const std::exception& e)
1662 {
1663 handle_api_exception(e, "fers_calculate_preview_links");
1664 return nullptr;
1665 }
1666}
static void handle_api_exception(const std::exception &e, const std::string &function_name)
Centralized exception handler for the C-API boundary.
Definition api.cpp:72
thread_local std::string last_error_message
Definition api.cpp:60
@ FERS_LINK_BISTATIC_TX_TGT
Definition api.h:743
@ FERS_LINK_MONOSTATIC
Definition api.h:742
@ FERS_LINK_BISTATIC_TGT_RX
Definition api.h:744
@ FERS_LINK_DIRECT_TX_RX
Definition api.h:745
@ FERS_LINK_WEAK
Definition api.h:734
@ FERS_LINK_STRONG
Definition api.h:733
#define LOG(level,...)
Definition logging.h:19
@ ERROR
Error level for error events.
@ DirectTxRx
Interference path.
@ Monostatic
Combined Tx/Rx path.
@ BistaticTgtRx
Scattered path.
@ BistaticTxTgt
Illuminator path.
std::vector< PreviewLink > calculatePreviewLinks(const core::World &world, const RealType time)
Calculates all visual links for the current world state at a specific time.
math::Vec3 max

References simulation::BistaticTgtRx, simulation::BistaticTxTgt, simulation::calculatePreviewLinks(), simulation::DirectTxRx, logging::ERROR, FERS_LINK_BISTATIC_TGT_RX, FERS_LINK_BISTATIC_TX_TGT, FERS_LINK_DIRECT_TX_RX, FERS_LINK_MONOSTATIC, FERS_LINK_STRONG, FERS_LINK_WEAK, handle_api_exception(), last_error_message, LOG, simulation::Monostatic, simulation::Strong, and fers_visual_link_t::type.

+ Here is the call graph for this function:

◆ fers_configure_logging()

int fers_configure_logging ( fers_log_level_t  level,
const char log_file_path 
)

Configures the internal logger.

Parameters
levelThe minimum severity level to log.
log_file_pathOptional path to a log file. Pass NULL to disable file logging.
Returns
0 on success, non-zero on error.

Definition at line 354 of file api.cpp.

355{
356 last_error_message.clear();
357 try
358 {
360 if ((log_file_path != nullptr) && ((*log_file_path) != 0))
361 {
363 if (!result)
364 {
365 last_error_message = result.error();
366 return 1;
367 }
368 }
369 return 0;
370 }
371 catch (const std::exception& e)
372 {
373 handle_api_exception(e, "fers_configure_logging");
374 return 1;
375 }
376}
static logging::Level map_api_log_level(fers_log_level_t level)
Definition api.cpp:129
std::expected< void, std::string > logToFile(const std::string &filePath) noexcept
Sets the log file path to log messages to a file.
Definition logging.cpp:90
void setLevel(Level level) noexcept
Sets the logging level.
Definition logging.cpp:25
Logger logger
Externally available logger object.
Definition logging.cpp:23

References handle_api_exception(), last_error_message, logging::logger, logging::Logger::logToFile(), map_api_log_level(), and logging::Logger::setLevel().

+ Here is the call graph for this function:

◆ fers_context_create()

fers_context_t * fers_context_create ( )

Creates a new FERS simulation context.

Allocates and initializes a new, empty simulation context in memory. This context serves as the container for a scenario loaded via one of the fers_load_... or fers_update_... functions.

Note
In a C API, RAII is not available. The caller is responsible for destroying the returned context using fers_context_destroy() to prevent resource leaks.
Returns
A non-null opaque pointer (handle) to the simulation context on success. Returns NULL on failure (e.g., out of memory).

Definition at line 97 of file api.cpp.

98{
99 last_error_message.clear();
101 try
102 {
103 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory): Public C API returns an owned handle.
104 return new fers_context_t();
105 }
106 catch (const std::bad_alloc& e)
107 {
108 handle_api_exception(e, "fers_context_create");
109 return nullptr;
110 }
111 catch (const std::exception& e)
112 {
113 handle_api_exception(e, "fers_context_create");
114 return nullptr;
115 }
116}
static void discard_warning_capture() noexcept
Definition api.cpp:89
struct fers_context fers_context_t
Definition api.h:26

References discard_warning_capture(), handle_api_exception(), and last_error_message.

+ Here is the call graph for this function:

◆ fers_context_destroy()

void fers_context_destroy ( fers_context_t context)

Destroys a FERS simulation context and releases all associated memory.

This function must be called for every context created by fers_context_create() to ensure proper cleanup of the underlying C++ objects. Accessing the context handle after calling this function results in undefined behavior.

Parameters
contextA valid pointer to a fers_context_t handle. If context is NULL, the function performs no action for safety and does not set an error.

Definition at line 118 of file api.cpp.

119{
120 if (context == nullptr)
121 {
122 return;
123 }
124 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory): Frees handles allocated by `fers_context_create`.
125 delete context;
126}

◆ fers_enable_vita49_udp_output()

int fers_enable_vita49_udp_output ( fers_context_t context,
const char host,
const std::uint16_t  port 
)

Definition at line 465 of file api.cpp.

466{
467 last_error_message.clear();
468 if (context == nullptr)
469 {
470 set_api_error("Invalid arguments: context is NULL.");
471 return -1;
472 }
473 if (host == nullptr)
474 {
475 set_api_error("Invalid VITA49 endpoint: host is NULL.");
476 return -1;
477 }
478 if (*host == '\0')
479 {
480 set_api_error("Invalid VITA49 endpoint: host must be non-empty.");
481 return 1;
482 }
483 if (port == 0)
484 {
485 set_api_error("Invalid VITA49 endpoint: port must be in the range 1..65535.");
486 return 1;
487 }
488
489 auto* ctx = context;
490 try
491 {
492 core::OutputConfig config = ctx->getOutputConfig();
494 config.vita49.host = host;
495 config.vita49.port = port;
496 ctx->setOutputConfig(std::move(config));
497 return 0;
498 }
499 catch (const std::exception& e)
500 {
501 handle_api_exception(e, "fers_enable_vita49_udp_output");
502 return 1;
503 }
504}

References handle_api_exception(), core::Vita49OutputConfig::host, last_error_message, core::OutputConfig::mode, core::Vita49OutputConfig::port, core::OutputConfig::vita49, and core::Vita49Udp.

+ Here is the call graph for this function:

◆ fers_free_antenna_pattern_data()

void fers_free_antenna_pattern_data ( fers_antenna_pattern_data_t data)

Frees the memory allocated for an antenna pattern data structure.

Parameters
dataA pointer to the fers_antenna_pattern_data_t struct to free.

Definition at line 1583 of file api.cpp.

1584{
1585 if (data != nullptr)
1586 {
1587 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory): Frees arrays owned by C API pattern structs.
1588 delete[] data->gains;
1589 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory): Frees structs allocated by `fers_get_antenna_pattern`.
1590 delete data;
1591 }
1592}

References fers_antenna_pattern_data_t::gains.

◆ fers_free_interpolated_motion_path()

void fers_free_interpolated_motion_path ( fers_interpolated_path_t path)

Frees the memory allocated for an interpolated motion path.

Parameters
pathA pointer to the fers_interpolated_path_t struct to free.

Definition at line 1380 of file api.cpp.

1381{
1382 if (path != nullptr)
1383 {
1384 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory): Frees arrays owned by C API path structs.
1385 delete[] path->points;
1386 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory): Frees structs allocated by
1387 // `fers_get_interpolated_motion_path`.
1388 delete path;
1389 }
1390}
fers_interpolated_point_t * points
Heap-allocated interpolated motion points.
Definition api.h:664

References fers_interpolated_path_t::points.

◆ fers_free_interpolated_rotation_path()

void fers_free_interpolated_rotation_path ( fers_interpolated_rotation_path_t path)

Frees the memory allocated for an interpolated rotation path.

Parameters
pathA pointer to the fers_interpolated_rotation_path_t struct to free.

Definition at line 1481 of file api.cpp.

1482{
1483 if (path != nullptr)
1484 {
1485 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory): Frees arrays owned by C API path structs.
1486 delete[] path->points;
1487 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory): Frees structs allocated by
1488 // `fers_get_interpolated_rotation_path`.
1489 delete path;
1490 }
1491}
fers_interpolated_rotation_point_t * points
Heap-allocated interpolated rotation points.
Definition api.h:674

References fers_interpolated_rotation_path_t::points.

◆ fers_free_preview_links()

void fers_free_preview_links ( fers_visual_link_list_t list)

Frees the memory allocated for a preview link list.

Parameters
listThe list to free.

Definition at line 1668 of file api.cpp.

1669{
1670 if (list != nullptr)
1671 {
1672 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory): Frees arrays owned by C API preview-link lists.
1673 delete[] list->links;
1674 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory): Frees structs allocated by `fers_calculate_preview_links`.
1675 delete list;
1676 }
1677}

References fers_visual_link_list_t::links.

◆ fers_free_string()

void fers_free_string ( char str)

Frees a string that was allocated and returned by the libfers API.

This function must be used to release memory for any string returned by functions like fers_get_scenario_as_json or fers_get_last_error_message. It exists to ensure that the memory deallocation mechanism (free) matches the allocation mechanism (strdup/malloc) used within the C++ library, preventing potential crashes from mismatched allocators across language boundaries.

Parameters
strA pointer to the string to be freed. If str is NULL, no action is taken.

Definition at line 1110 of file api.cpp.

1111{
1112 if (str != nullptr)
1113 {
1114 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory): Public C API frees strings returned by this library.
1115 free(str);
1116 }
1117}

◆ fers_generate_kml()

int fers_generate_kml ( const fers_context_t context,
const char output_kml_filepath 
)

Generates a KML file for visualizing the scenario in the context.

This utility exists to provide a simple, out-of-the-box method for users to validate and visualize the geographic layout and motion paths of their scenarios in common external tools like Google Earth.

Parameters
contextA valid fers_context_t handle containing a loaded scenario.
output_kml_filepathA null-terminated UTF-8 string for the output KML file path.
Returns
0 on success, a non-zero error code on failure. Use fers_get_last_error_message() to retrieve KML generation details.

Definition at line 1242 of file api.cpp.

1243{
1244 last_error_message.clear();
1245 if ((context == nullptr) || (output_kml_filepath == nullptr))
1246 {
1247 last_error_message = "Invalid arguments: context or output_kml_filepath is NULL.";
1249 return -1;
1250 }
1251
1252 const auto* ctx = context;
1253
1254 try
1255 {
1257 if (result)
1258 {
1259 return 0; // Success
1260 }
1261
1262 last_error_message = result.error();
1264 return 2; // Generation failed
1265 }
1266 catch (const std::exception& e)
1267 {
1268 handle_api_exception(e, "fers_generate_kml");
1269 return 1; // Exception thrown
1270 }
1271}
static std::expected< void, std::string > generateKml(const core::World &world, const std::string &outputKmlPath)
Generates a KML file from a pre-built simulation world.

References logging::ERROR, serial::KmlGenerator::generateKml(), handle_api_exception(), last_error_message, and LOG.

+ Here is the call graph for this function:

◆ fers_get_antenna_pattern()

fers_antenna_pattern_data_t * fers_get_antenna_pattern ( const fers_context_t context,
uint64_t  antenna_id,
size_t  az_samples,
size_t  el_samples,
double  frequency_hz 
)

Samples the gain pattern of a specified antenna and provides the data.

This function calculates the antenna's far-field gain at a specified resolution over the full sphere of directions (azimuth and elevation). The resulting gain values are linear (not in dB) and normalized relative to the pattern's peak gain. This is a stateless utility useful for UI previews and analysis.

Parameters
contextA valid fers_context_t handle containing a loaded scenario with the antenna.
antenna_idThe unique ID of the antenna asset to sample.
az_samplesThe desired number of sample points along the azimuth axis. Must be at least 2 to span the full azimuth range.
el_samplesThe desired number of sample points along the elevation axis. Must be at least 2 to span the full elevation range.
frequency_hzThe frequency in Hz to use for gain calculation (affects aperture antennas).
Returns
A pointer to a fers_antenna_pattern_data_t struct containing the results. Returns NULL on failure (e.g., antenna not found). The caller owns the returned struct and must free it with fers_free_antenna_pattern_data.

Definition at line 1495 of file api.cpp.

1498{
1499 last_error_message.clear();
1500 if ((context == nullptr) || az_samples < 2 || el_samples < 2)
1501 {
1502 last_error_message = "Invalid arguments: context must be non-null and sample counts must be >= 2.";
1504 return nullptr;
1505 }
1506
1507 try
1508 {
1509 const auto* ctx = context;
1510 antenna::Antenna const* ant = ctx->getWorld()->findAntenna(static_cast<SimId>(antenna_id));
1511
1512 if (ant == nullptr)
1513 {
1514 last_error_message = "Antenna ID '" + std::to_string(antenna_id) + "' not found in the world.";
1516 return nullptr;
1517 }
1518
1519 // TODO: Currently only using the first-found waveform. This is incorrect but also difficult to represent
1520 // correctly in scenarios with multiple waveforms as the gain for squarehorn and parabolic antennas
1521 // depends on the wavelength. Hence a decision needs to be made about whether to return multiple patterns
1522 // per waveform or have the user specify a representative wavelength in the UI per antenna.
1523 // Calculate wavelength from the provided frequency.
1524 // Default to 1GHz (0.3m) if frequency is invalid/zero, though the UI should prevent this
1525 // for antennas that strictly require it (Horn/Parabolic).
1526 RealType wavelength = 0.3;
1527 if (frequency_hz > 0.0)
1528 {
1530 }
1531
1532 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory): Public C API returns owned antenna pattern data.
1533 auto* data = new fers_antenna_pattern_data_t();
1534 data->az_count = az_samples;
1535 data->el_count = el_samples;
1536 const size_t total_samples = az_samples * el_samples;
1537 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory): Public C API frees this array with the parent data.
1538 data->gains = new double[total_samples];
1539
1540 // The reference angle (boresight) is implicitly the local X-axis in the FERS engine.
1541 // We pass a zero rotation to get the gain relative to this boresight.
1542 const math::SVec3 ref_angle(1.0, 0.0, 0.0);
1543 double max_gain = 0.0;
1544
1545 const auto az_denominator = static_cast<RealType>(az_samples - 1);
1546 const auto el_denominator = static_cast<RealType>(el_samples - 1);
1547
1548 for (size_t i = 0; i < el_samples; ++i)
1549 {
1550 // Elevation from -PI/2 to PI/2
1551 const RealType elevation = (static_cast<RealType>(i) / el_denominator) * PI - (PI / 2.0);
1552 for (size_t j = 0; j < az_samples; ++j)
1553 {
1554 // Azimuth from -PI to PI
1555 const RealType azimuth = (static_cast<RealType>(j) / az_denominator) * 2.0 * PI - PI;
1556 const math::SVec3 sample_angle(1.0, azimuth, elevation);
1557 const RealType gain = ant->getGain(sample_angle, ref_angle, wavelength);
1558 data->gains[i * az_samples + j] = gain;
1559 max_gain = std::max(gain, max_gain);
1560 }
1561 }
1562
1563 data->max_gain = max_gain;
1564
1565 // Normalize the gains
1566 if (max_gain > 0)
1567 {
1568 for (size_t i = 0; i < total_samples; ++i)
1569 {
1570 data->gains[i] /= max_gain;
1571 }
1572 }
1573
1574 return data;
1575 }
1576 catch (const std::exception& e)
1577 {
1578 handle_api_exception(e, "fers_get_antenna_pattern");
1579 return nullptr;
1580 }
1581}
Abstract base class representing an antenna.
A class representing a vector in spherical coordinates.
double RealType
Type for real numbers.
Definition config.h:27
constexpr RealType PI
Mathematical constant π (pi).
Definition config.h:43
RealType c() noexcept
Get the speed of light.
Definition parameters.h:91
uint64_t SimId
64-bit Unique Simulation ID.
Definition sim_id.h:18
Represents a sampled 2D antenna gain pattern.
Definition api.h:550

References params::c(), logging::ERROR, antenna::Antenna::getGain(), handle_api_exception(), last_error_message, LOG, and PI.

+ Here is the call graph for this function:

◆ fers_get_interpolated_motion_path()

fers_interpolated_path_t * fers_get_interpolated_motion_path ( const fers_motion_waypoint_t waypoints,
size_t  waypoint_count,
fers_interp_type_t  interp_type,
size_t  num_points 
)

Calculates an interpolated motion path from a set of waypoints.

This function is a stateless utility that computes the path without needing a full simulation context. It is useful for UI previews.

Parameters
waypointsAn array of fers_motion_waypoint_t structs.
waypoint_countThe number of waypoints in the array.
interp_typeThe interpolation algorithm to use.
num_pointsThe desired number of points in the output interpolated path.
Returns
A pointer to a fers_interpolated_path_t struct containing the results. Returns NULL on failure. The caller owns the returned struct and must free it with fers_free_interpolated_motion_path.

Definition at line 1303 of file api.cpp.

1307{
1308 last_error_message.clear();
1309 if ((waypoints == nullptr) || waypoint_count == 0 || num_points == 0)
1310 {
1311 last_error_message = "Invalid arguments: waypoints cannot be null and counts must be > 0.";
1313 return nullptr;
1314 }
1316 {
1317 last_error_message = "Cubic interpolation requires at least 2 waypoints.";
1319 return nullptr;
1320 }
1321
1322 try
1323 {
1324 math::Path path;
1326
1327 for (size_t i = 0; i < waypoint_count; ++i)
1328 {
1329 math::Coord c;
1330 c.t = waypoints[i].time;
1331 c.pos.x = waypoints[i].x;
1332 c.pos.y = waypoints[i].y;
1333 c.pos.z = waypoints[i].z;
1334 path.addCoord(c);
1335 }
1336
1337 path.finalize();
1338
1339 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory): Public C API returns an owned path struct.
1341 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory): Public C API frees this array with the parent path.
1343 result_path->count = num_points;
1344
1345 const double start_time = waypoints[0].time;
1346 const double end_time = waypoints[waypoint_count - 1].time;
1347 const double duration = end_time - start_time;
1348
1349 // Handle static case separately
1350 if (waypoint_count < 2 || duration <= 0)
1351 {
1352 const math::Vec3 pos = path.getPosition(start_time);
1353 for (size_t i = 0; i < num_points; ++i)
1354 {
1355 result_path->points[i] = {pos.x, pos.y, pos.z, 0.0, 0.0, 0.0};
1356 }
1357 return result_path;
1358 }
1359
1360 const double time_step =
1361 duration / static_cast<double>(num_points > 1 ? num_points - 1 : static_cast<size_t>(1));
1362
1363 for (size_t i = 0; i < num_points; ++i)
1364 {
1365 const double t = start_time + static_cast<double>(i) * time_step;
1366 const math::Vec3 pos = path.getPosition(t);
1367 const math::Vec3 vel = path.getVelocity(t);
1368 result_path->points[i] = {pos.x, pos.y, pos.z, vel.x, vel.y, vel.z};
1369 }
1370
1371 return result_path;
1372 }
1373 catch (const std::exception& e)
1374 {
1375 handle_api_exception(e, "fers_get_interpolated_motion_path");
1376 return nullptr;
1377 }
1378}
math::Path::InterpType to_cpp_interp_type(const fers_interp_type_t type)
Definition api.cpp:1274
@ FERS_INTERP_CUBIC
Definition api.h:598
Represents a path with coordinates and allows for various interpolation methods.
Definition path.h:31
Vec3 getPosition(RealType t) const
Retrieves the position at a given time along the path.
Definition path.cpp:36
void setInterp(InterpType settype) noexcept
Changes the interpolation type.
Definition path.cpp:164
Vec3 getVelocity(RealType t) const
Retrieves the velocity at a given time along the path.
Definition path.cpp:60
void addCoord(const Coord &coord) noexcept
Adds a coordinate to the path.
Definition path.cpp:27
void finalize()
Finalizes the path, preparing it for interpolation.
Definition path.cpp:147
A class representing a vector in rectangular coordinates.
RealType x
The x component of the vector.
RealType z
The z component of the vector.
RealType y
The y component of the vector.
RealType c
A container for an array of interpolated motion path points.
Definition api.h:663
Represents a single interpolated point on a motion path.
Definition api.h:638
Represents a position in 3D space with an associated time.
Definition coord.h:24
RealType t
Time.
Definition coord.h:26

References math::Path::addCoord(), c, logging::ERROR, FERS_INTERP_CUBIC, math::Path::finalize(), math::Path::getPosition(), math::Path::getVelocity(), handle_api_exception(), last_error_message, LOG, math::Path::setInterp(), math::Coord::t, fers_motion_waypoint_t::time, to_cpp_interp_type(), fers_motion_waypoint_t::x, math::Vec3::x, fers_motion_waypoint_t::y, math::Vec3::y, fers_motion_waypoint_t::z, and math::Vec3::z.

+ Here is the call graph for this function:

◆ fers_get_interpolated_rotation_path()

fers_interpolated_rotation_path_t * fers_get_interpolated_rotation_path ( const fers_rotation_waypoint_t waypoints,
size_t  waypoint_count,
fers_interp_type_t  interp_type,
fers_angle_unit_t  angle_unit,
size_t  num_points 
)

Calculates an interpolated rotation path from a set of waypoints.

This function is a stateless utility for UI previews.

Parameters
waypointsAn array of fers_rotation_waypoint_t structs.
waypoint_countThe number of waypoints in the array.
interp_typeThe interpolation algorithm to use (STATIC, LINEAR, CUBIC).
angle_unitThe unit used by the waypoint angles and desired output angles.
num_pointsThe desired number of points in the output interpolated path.
Returns
A pointer to a fers_interpolated_rotation_path_t struct containing the results. Returns NULL on failure. The caller owns the returned struct and must free it with fers_free_interpolated_rotation_path.

Definition at line 1392 of file api.cpp.

1397{
1398 last_error_message.clear();
1399 last_warning_messages.clear();
1401 if ((waypoints == nullptr) || waypoint_count == 0 || num_points == 0)
1402 {
1403 last_error_message = "Invalid arguments: waypoints cannot be null and counts must be > 0.";
1405 return nullptr;
1406 }
1408 {
1409 last_error_message = "Cubic interpolation requires at least 2 waypoints.";
1411 return nullptr;
1412 }
1413
1414 try
1415 {
1416 const auto unit =
1418 math::RotationPath path;
1420
1421 for (size_t i = 0; i < waypoint_count; ++i)
1422 {
1425 std::format("rotation waypoint {}", i), "azimuth");
1428 std::format("rotation waypoint {}", i), "elevation");
1430 waypoints[i].azimuth, waypoints[i].elevation, waypoints[i].time, unit));
1431 }
1432
1433 path.finalize();
1434
1435 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory): Public C API returns an owned path struct.
1437 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory): Public C API frees this array with the parent path.
1439 result_path->count = num_points;
1440
1441 const double start_time = waypoints[0].time;
1442 const double end_time = waypoints[waypoint_count - 1].time;
1443 const double duration = end_time - start_time;
1444
1445 // Handle static case separately
1446 if (waypoint_count < 2 || duration <= 0)
1447 {
1448 const math::SVec3 rot = path.getPosition(start_time);
1449 for (size_t i = 0; i < num_points; ++i)
1450 {
1454 }
1455 return result_path;
1456 }
1457
1458 const double time_step =
1459 duration / static_cast<double>(num_points > 1 ? num_points - 1 : static_cast<size_t>(1));
1460
1461 for (size_t i = 0; i < num_points; ++i)
1462 {
1463 const double t = start_time + static_cast<double>(i) * time_step;
1464 const math::SVec3 rot = path.getPosition(t);
1465
1469 }
1470
1471 return result_path;
1472 }
1473 catch (const std::exception& e)
1474 {
1476 handle_api_exception(e, "fers_get_interpolated_rotation_path");
1477 return nullptr;
1478 }
1479}
math::RotationPath::InterpType to_cpp_rot_interp_type(const fers_interp_type_t type)
Definition api.cpp:1288
@ FERS_ANGLE_UNIT_RAD
Definition api.h:607
Manages rotational paths with different interpolation techniques.
void finalize()
Finalizes the rotation path for interpolation.
void setInterp(InterpType setinterp) noexcept
Sets the interpolation type for the path.
SVec3 getPosition(RealType t) const
Gets the rotational position at a given time.
void addCoord(const RotationCoord &coord) noexcept
Adds a rotation coordinate to the path.
@ Radians
Compass azimuth and elevation expressed in radians.
@ Degrees
Compass azimuth and elevation expressed in degrees.
RealType internal_elevation_to_external(const RealType elevation, const params::RotationAngleUnit unit) noexcept
Converts an internal elevation angle to the external unit.
math::RotationCoord external_rotation_to_internal(const RealType azimuth, const RealType elevation, const RealType time, const params::RotationAngleUnit unit) noexcept
Converts external compass azimuth/elevation into internal rotation coordinates.
RealType internal_azimuth_to_external(const RealType azimuth, const params::RotationAngleUnit unit) noexcept
Converts an internal azimuth angle to the external compass convention.
void maybe_warn_about_rotation_value(const RealType value, const params::RotationAngleUnit declared_unit, const ValueKind kind, const std::string_view source, const std::string_view owner, const std::string_view field)
Emits or captures a warning when a rotation value likely uses the wrong unit.
A container for an array of interpolated rotation path points.
Definition api.h:673
Represents a single interpolated point on a rotation path.
Definition api.h:652

References math::RotationPath::addCoord(), serial::rotation_warning_utils::Angle, math::SVec3::azimuth, serial::rotation_warning_utils::clear_captured_warnings(), params::Degrees, math::SVec3::elevation, logging::ERROR, serial::rotation_angle_utils::external_rotation_to_internal(), FERS_ANGLE_UNIT_RAD, FERS_INTERP_CUBIC, math::RotationPath::finalize(), math::RotationPath::getPosition(), handle_api_exception(), serial::rotation_angle_utils::internal_azimuth_to_external(), serial::rotation_angle_utils::internal_elevation_to_external(), last_error_message, last_warning_messages, LOG, serial::rotation_warning_utils::maybe_warn_about_rotation_value(), params::Radians, math::RotationPath::setInterp(), fers_rotation_waypoint_t::time, and to_cpp_rot_interp_type().

+ Here is the call graph for this function:

◆ fers_get_last_error_message()

char * fers_get_last_error_message ( )

Retrieves the last error message that occurred on the current thread.

Because C++ exceptions cannot safely propagate across the FFI boundary into other languages, this function provides the standard C-style error reporting mechanism. The error state is stored in a thread-local variable to ensure that concurrent API calls from different threads do not overwrite each other's error messages. The error is cleared at the start of each fallible API call.

Note
Memory Management: The returned string's ownership is transferred to the caller. It MUST be freed using fers_free_string() to prevent memory leaks.
Returns
A dynamically allocated, null-terminated C-string containing the last error message, or NULL if no error has occurred.

Definition at line 1085 of file api.cpp.

1086{
1087 if (last_error_message.empty())
1088 {
1089 return nullptr; // No error to report
1090 }
1091 // `strdup` allocates with `malloc`, which is part of the C standard ABI,
1092 // making it safe to transfer ownership across the FFI boundary. The caller
1093 // must then free this memory using `fers_free_string`.
1094 // NOLINTNEXTLINE(cppcoreguidelines-no-malloc): C ABI string ownership is freed by `fers_free_string`.
1095 return strdup(last_error_message.c_str());
1096}

References last_error_message.

◆ fers_get_last_output_metadata_json()

char * fers_get_last_output_metadata_json ( fers_context_t context)

Returns JSON metadata for the most recent simulation output files.

The returned JSON describes generated HDF5 file structure and sample ranges. The caller owns the returned string and must free it with fers_free_string. If no simulation has completed yet, the returned JSON contains an empty files array.

Parameters
contextA valid fers_context_t handle.
Returns
A heap-allocated JSON string, or NULL on error.

Definition at line 759 of file api.cpp.

760{
761 last_error_message.clear();
762 if (context == nullptr)
763 {
764 last_error_message = "Invalid context provided to fers_get_last_output_metadata_json.";
766 return nullptr;
767 }
768
769 const auto* ctx = context;
770 try
771 {
772 const std::string json_str = ctx->getLastOutputMetadataJson();
773 return strdup(json_str.c_str());
774 }
775 catch (const std::exception& e)
776 {
777 handle_api_exception(e, "fers_get_last_output_metadata_json");
778 return nullptr;
779 }
780}

References logging::ERROR, FersContext::getLastOutputMetadataJson(), handle_api_exception(), last_error_message, and LOG.

+ Here is the call graph for this function:

◆ fers_get_last_warning_messages_json()

char * fers_get_last_warning_messages_json ( )

Returns the last deduplicated rotation-unit warning list for the calling thread as JSON.

The returned value is a JSON array of strings. It is populated by successful XML/JSON load and update calls that detect suspicious rotation values. The caller owns the string and must free it with fers_free_string().

Returns
A dynamically allocated JSON array string, or NULL if no warnings are available.

Definition at line 1098 of file api.cpp.

1099{
1100 if (last_warning_messages.empty())
1101 {
1102 return nullptr;
1103 }
1104
1105 const std::string warning_json = nlohmann::json(last_warning_messages).dump();
1106 last_warning_messages.clear();
1107 return strdup(warning_json.c_str());
1108}

References last_warning_messages.

◆ fers_get_log_level()

fers_log_level_t fers_get_log_level ( )

Returns the current internal logger level.

Definition at line 380 of file api.cpp.

380{ return map_internal_log_level(logging::logger.getLevel()); }
static fers_log_level_t map_internal_log_level(logging::Level level)
Definition api.cpp:152

References logging::logger, and map_internal_log_level().

+ Here is the call graph for this function:

◆ fers_get_memory_projection_json()

char * fers_get_memory_projection_json ( fers_context_t context)

Returns a JSON projection of simulation startup memory and HDF5 payload size.

The projection includes phase-noise lookup memory, streaming I/Q buffer memory, rendered HDF5 payload size, current resident memory not attributed to streaming I/Q buffers where available, and an aggregate projected total. The caller owns the returned string and must free it with fers_free_string.

Parameters
contextA valid fers_context_t handle.
Returns
A heap-allocated JSON string, or NULL on error.

Definition at line 782 of file api.cpp.

783{
784 last_error_message.clear();
785 if (context == nullptr)
786 {
787 last_error_message = "Invalid context provided to fers_get_memory_projection_json.";
789 return nullptr;
790 }
791
792 auto* ctx = context;
793
794 try
795 {
796 const auto projection = core::projectSimulationMemory(*ctx->getWorld());
798 return strdup(json_str.c_str());
799 }
800 catch (const std::exception& e)
801 {
802 handle_api_exception(e, "fers_get_memory_projection_json");
803 return nullptr;
804 }
805}
std::string memoryProjectionToJsonString(const SimulationMemoryProjection &projection)
Serializes a simulation memory projection as JSON.
SimulationMemoryProjection projectSimulationMemory(const World &world)
Projects startup memory and rendered-output sizes for a simulation world.

References logging::ERROR, handle_api_exception(), last_error_message, LOG, core::memoryProjectionToJsonString(), and core::projectSimulationMemory().

+ Here is the call graph for this function:

◆ fers_get_scenario_as_json()

char * fers_get_scenario_as_json ( fers_context_t context)

Serializes the current simulation scenario into a JSON string.

This function is the primary method for the UI to retrieve the full state of the simulation. JSON is used as the interchange format because it is lightweight, human-readable, and natively supported by web technologies, making it trivial to parse and use in the React/TypeScript frontend.

Note
Memory Management: The returned string is allocated by this library and its ownership is transferred to the caller. It is crucial to free this string using fers_free_string() to prevent memory leaks.
Parameters
contextA valid fers_context_t handle.
Returns
A dynamically allocated, null-terminated C-string containing the JSON representation of the scenario. Returns NULL on failure.

Definition at line 702 of file api.cpp.

703{
704 last_error_message.clear();
705 if (context == nullptr)
706 {
707 last_error_message = "Invalid context provided to fers_get_scenario_as_json.";
709 return nullptr;
710 }
711
712 const auto* ctx = context;
713 try
714 {
715 const nlohmann::json j = serial::world_to_json(*ctx->getWorld());
716 const std::string json_str = j.dump(2);
717 // A heap-allocated copy of the string is returned. This is necessary
718 // to transfer ownership of the memory across the FFI boundary to a
719 // client that will free it using `fers_free_string`.
720 return strdup(json_str.c_str());
721 }
722 catch (const std::exception& e)
723 {
724 handle_api_exception(e, "fers_get_scenario_as_json");
725 return nullptr;
726 }
727}
nlohmann::json world_to_json(const core::World &world)
Serializes the entire simulation world into a nlohmann::json object.

References logging::ERROR, handle_api_exception(), last_error_message, LOG, and serial::world_to_json().

+ Here is the call graph for this function:

◆ fers_get_scenario_as_xml()

char * fers_get_scenario_as_xml ( fers_context_t context)

Serializes the current simulation scenario into a FERS XML string.

This function enables exporting the in-memory state back into the standard FERS XML file format. This is essential for interoperability with legacy tools and for allowing a user to save a scenario that was created or modified in the UI.

Note
Memory Management: The returned string is dynamically allocated and its ownership is transferred to the caller. It must be freed using fers_free_string() to prevent memory leaks.
Parameters
contextA valid fers_context_t handle.
Returns
A dynamically allocated, null-terminated C-string containing the XML representation of the scenario. Returns NULL on failure.

Definition at line 729 of file api.cpp.

730{
731 last_error_message.clear();
732 if (context == nullptr)
733 {
734 last_error_message = "Invalid context provided to fers_get_scenario_as_xml.";
736 return nullptr;
737 }
738
739 const auto* ctx = context;
740 try
741 {
742 const std::string xml_str = serial::world_to_xml_string(*ctx->getWorld());
743 if (xml_str.empty())
744 {
745 throw std::runtime_error("XML serialization resulted in an empty string.");
746 }
747 // `strdup` is used to create a heap-allocated string that can be safely
748 // passed across the FFI boundary. The client is responsible for freeing
749 // this memory with `fers_free_string`.
750 return strdup(xml_str.c_str());
751 }
752 catch (const std::exception& e)
753 {
754 handle_api_exception(e, "fers_get_scenario_as_xml");
755 return nullptr;
756 }
757}
std::string world_to_xml_string(const core::World &world)
Serializes the entire simulation world into an XML formatted string.

References logging::ERROR, handle_api_exception(), last_error_message, LOG, and serial::world_to_xml_string().

+ Here is the call graph for this function:

◆ fers_get_version()

const char * fers_get_version ( void  )

Returns the library version string.

The returned pointer remains valid for the lifetime of the process and must not be freed by the caller.

Definition at line 378 of file api.cpp.

378{ return FERS_VERSION_STRING; }

Referenced by core::showHelp().

+ Here is the caller graph for this function:

◆ fers_load_scenario_from_xml_file()

int fers_load_scenario_from_xml_file ( fers_context_t context,
const char xml_filepath,
int  validate 
)

Loads a scenario into the context from a FERS XML file.

This is the standard method for initializing a simulation context from a file on disk. It is essential for interoperability with the CLI and legacy workflows that rely on the FERS XML format.

Parameters
contextA valid fers_context_t handle.
xml_filepathA null-terminated UTF-8 string for the input XML file path.
validateA boolean (0 or 1) indicating whether to validate the XML against the embedded FERS schema. Validation is recommended to ensure scenario correctness.
Returns
0 on success, a non-zero error code on failure. Use fers_get_last_error_message() to retrieve error details.

Definition at line 606 of file api.cpp.

607{
608 last_error_message.clear();
610 if ((context == nullptr) || (xml_filepath == nullptr))
611 {
612 last_error_message = "Invalid arguments: context or xml_filepath is NULL.";
615 return -1;
616 }
617
618 auto* ctx = context;
619 try
620 {
621 // Set default output directory to the scenario file's directory
622 std::filesystem::path const p(xml_filepath);
623 auto parent = p.parent_path();
624 if (parent.empty())
625 parent = ".";
626 ctx->setOutputDir(parent.string());
627
628 serial::parseSimulation(xml_filepath, ctx->getWorld(), static_cast<bool>(validate), ctx->getMasterSeeder());
629
630 // After parsing, seed the master random number generator. This is done
631 // to ensure simulation reproducibility. If the scenario specifies a seed,
632 // it is used; otherwise, a non-deterministic seed is generated so that
633 // subsequent runs are unique by default.
634 if (params::params.random_seed)
635 {
636 LOG(logging::Level::INFO, "Using master seed from scenario file: {}", *params::params.random_seed);
637 ctx->getMasterSeeder().seed(*params::params.random_seed);
638 }
639 else
640 {
641 const auto seed = std::random_device{}();
642 LOG(logging::Level::INFO, "No master seed provided in scenario. Using random_device seed: {}", seed);
644 ctx->getMasterSeeder().seed(seed);
645 }
647 return 0; // Success
648 }
649 catch (const std::exception& e)
650 {
652 handle_api_exception(e, "fers_load_scenario_from_xml_file");
653 return 1; // Error
654 }
655}
static void begin_warning_capture() noexcept
Definition api.cpp:78
static void complete_warning_capture()
Definition api.cpp:84
@ INFO
Info level for informational messages.
Parameters params
Global simulation parameter state.
Definition parameters.h:85
void parseSimulation(const std::string &filename, core::World *world, const bool validate, std::mt19937 &masterSeeder)
Parses a simulation configuration from an XML file.
std::optional< unsigned > random_seed
Random seed for simulation.
Definition parameters.h:70

References begin_warning_capture(), complete_warning_capture(), discard_warning_capture(), logging::ERROR, handle_api_exception(), logging::INFO, last_error_message, LOG, params::params, serial::parseSimulation(), and params::Parameters::random_seed.

+ Here is the call graph for this function:

◆ fers_load_scenario_from_xml_string()

int fers_load_scenario_from_xml_string ( fers_context_t context,
const char xml_content,
int  validate 
)

Loads a scenario into the context from a FERS XML string.

This function provides a way to load a scenario from an in-memory string, avoiding file I/O. It is useful for test harnesses or for UIs that manage scenarios as text content before parsing.

Parameters
contextA valid fers_context_t handle.
xml_contentA null-terminated UTF-8 string containing the FERS scenario in XML format.
validateA boolean (0 or 1) indicating whether to validate the XML against the embedded FERS schema.
Returns
0 on success, a non-zero error code on failure. Use fers_get_last_error_message() to retrieve error details.

Definition at line 657 of file api.cpp.

658{
659 last_error_message.clear();
661 if ((context == nullptr) || (xml_content == nullptr))
662 {
663 last_error_message = "Invalid arguments: context or xml_content is NULL.";
666 return -1;
667 }
668
669 auto* ctx = context;
670 try
671 {
672 serial::parseSimulationFromString(xml_content, ctx->getWorld(), static_cast<bool>(validate),
673 ctx->getMasterSeeder());
674
675 // After parsing, seed the master random number generator. This ensures
676 // that if the scenario provides a seed, the simulation will be
677 // reproducible. If not, a random seed is used to ensure unique runs.
678 if (params::params.random_seed)
679 {
680 LOG(logging::Level::INFO, "Using master seed from scenario string: {}", *params::params.random_seed);
681 ctx->getMasterSeeder().seed(*params::params.random_seed);
682 }
683 else
684 {
685 const auto seed = std::random_device{}();
686 LOG(logging::Level::INFO, "No master seed provided in scenario. Using random_device seed: {}", seed);
688 ctx->getMasterSeeder().seed(seed);
689 }
690
692 return 0; // Success
693 }
694 catch (const std::exception& e)
695 {
697 handle_api_exception(e, "fers_load_scenario_from_xml_string");
698 return 1; // Parsing or logic error
699 }
700}
void parseSimulationFromString(const std::string &xmlContent, core::World *world, const bool validate, std::mt19937 &masterSeeder)
Parses a simulation configuration directly from an XML string in memory.

References begin_warning_capture(), complete_warning_capture(), discard_warning_capture(), logging::ERROR, handle_api_exception(), logging::INFO, last_error_message, LOG, params::params, serial::parseSimulationFromString(), and params::Parameters::random_seed.

+ Here is the call graph for this function:

◆ fers_log()

void fers_log ( fers_log_level_t  level,
const char message 
)

Submits a log message to the library's unified logging system.

This ensures CLI messages match the format (timestamps, alignment) of library messages.

Definition at line 393 of file api.cpp.

394{
395 if (message == nullptr)
396 return;
397 // We pass a default source_location because C-API calls don't provide C++ source info
398 logging::logger.log(map_api_log_level(level), message, std::source_location::current());
399}
void log(Level level, const std::string &message, const std::source_location &location=std::source_location::current()) noexcept
Logs a message with a specific log level and source location.
Definition logging.cpp:45

References logging::Logger::log(), logging::logger, and map_api_log_level().

+ Here is the call graph for this function:

◆ fers_run_simulation()

int fers_run_simulation ( fers_context_t context,
fers_progress_callback_t  callback,
void user_data 
)

Runs the simulation defined in the provided context.

This function is synchronous and will block the calling thread until the simulation is complete. This design keeps the API simple. For use in a responsive UI, it is the responsibility of the caller (e.g., the Tauri backend) to invoke this function on a separate worker thread to avoid freezing the user interface.

Parameters
contextA valid fers_context_t handle containing a loaded scenario.
callbackA function pointer to a progress callback. Can be NULL.
user_dataAn opaque pointer passed to the callback function.
Returns
0 on success, a non-zero error code on failure. Use fers_get_last_error_message() to retrieve error details.

Definition at line 1212 of file api.cpp.

1213{
1214 return run_simulation_common(
1215 SimulationRunRequest{.context = context,
1216 .progress_callback = callback,
1217 .progress_user_data = user_data,
1218 .cancel_callback = nullptr,
1219 .cancel_user_data = nullptr,
1220 .vita49_telemetry_callback = nullptr,
1221 .vita49_telemetry_user_data = nullptr,
1222 .function_name = "fers_run_simulation",
1223 .invalid_context_message = "Invalid context provided to fers_run_simulation."});
1224}

◆ fers_run_simulation_ex()

int fers_run_simulation_ex ( fers_context_t context,
fers_progress_callback_t  progress_callback,
void progress_user_data,
fers_cancel_callback_t  cancel_callback,
void cancel_user_data,
fers_vita49_telemetry_callback_t  vita49_telemetry_callback,
void vita49_telemetry_user_data 
)

Runs the simulation with optional progress, cancellation, and VITA telemetry callbacks.

Return values match fers_run_simulation, except 2 means the run was cooperatively cancelled after output finalization and metadata collection.

Parameters
contextA valid fers_context_t handle containing a loaded scenario.
progress_callbackOptional progress callback. Can be NULL.
progress_user_dataOpaque pointer passed to the progress callback.
cancel_callbackOptional cancellation callback. Can be NULL.
cancel_user_dataOpaque pointer passed to the cancellation callback.
vita49_telemetry_callbackOptional VITA live telemetry callback. Can be NULL.
vita49_telemetry_user_dataOpaque pointer passed to the VITA telemetry callback.
Returns
0 on success, 2 on cancellation, a non-zero error code on failure.

Definition at line 1226 of file api.cpp.

1229{
1230 return run_simulation_common(
1231 SimulationRunRequest{.context = context,
1232 .progress_callback = progress_callback,
1233 .progress_user_data = progress_user_data,
1234 .cancel_callback = cancel_callback,
1235 .cancel_user_data = cancel_user_data,
1236 .vita49_telemetry_callback = vita49_telemetry_callback,
1237 .vita49_telemetry_user_data = vita49_telemetry_user_data,
1238 .function_name = "fers_run_simulation_ex",
1239 .invalid_context_message = "Invalid context provided to fers_run_simulation_ex."});
1240}

◆ fers_set_log_callback()

void fers_set_log_callback ( fers_log_callback_t  callback,
void user_data 
)

Registers a callback for formatted log lines.

Pass NULL as callback to disable log callbacks.

Definition at line 382 of file api.cpp.

383{
384 {
385 std::scoped_lock const lock(log_callback_mutex);
388 }
389
391}
void setCallback(Callback callback, void *user_data) noexcept
Sets an optional callback that receives each formatted log line.
Definition logging.cpp:83

References logging::logger, and logging::Logger::setCallback().

+ Here is the call graph for this function:

◆ fers_set_output_directory()

int fers_set_output_directory ( fers_context_t context,
const char out_dir 
)

Sets the output directory for simulation results.

Parameters
contextA valid fers_context_t handle.
out_dirA null-terminated UTF-8 string for the output directory path.
Returns
0 on success, non-zero on error.

Definition at line 420 of file api.cpp.

421{
422 last_error_message.clear();
423 if ((context == nullptr) || (out_dir == nullptr))
424 {
425 set_api_error("Invalid arguments: context or out_dir is NULL.");
426 return -1;
427 }
428 auto* ctx = context;
429 try
430 {
431 ctx->setOutputDir(out_dir);
432 return 0;
433 }
434 catch (const std::exception& e)
435 {
436 handle_api_exception(e, "fers_set_output_directory");
437 return 1;
438 }
439}

References handle_api_exception(), last_error_message, and FersContext::setOutputDir().

+ Here is the call graph for this function:

◆ fers_set_thread_count()

int fers_set_thread_count ( unsigned  num_threads)

Sets the number of worker threads for the simulation.

Parameters
num_threadsThe number of threads to use.
Returns
0 on success, non-zero on error. This function clears any previous thread-local error message at entry, like the other fallible API calls.

Definition at line 401 of file api.cpp.

402{
403 last_error_message.clear();
404 try
405 {
406 if (auto res = params::setThreads(num_threads); !res)
407 {
408 last_error_message = res.error();
409 return 1;
410 }
411 return 0;
412 }
413 catch (const std::exception& e)
414 {
415 handle_api_exception(e, "fers_set_thread_count");
416 return 1;
417 }
418}
std::expected< void, std::string > setThreads(const unsigned threads) noexcept
Set the number of worker threads.
Definition parameters.h:293

References handle_api_exception(), last_error_message, and params::setThreads().

+ Here is the call graph for this function:

◆ fers_set_vita49_epoch_unix_nanoseconds()

int fers_set_vita49_epoch_unix_nanoseconds ( fers_context_t context,
const std::uint64_t  epoch_unix_nanoseconds 
)

Definition at line 527 of file api.cpp.

528{
529 last_error_message.clear();
530 if (context == nullptr)
531 {
532 set_api_error("Invalid arguments: context is NULL.");
533 return -1;
534 }
535 if (!is_valid_vita49_epoch(epoch_unix_nanoseconds))
536 {
537 set_api_error("Invalid VITA49 epoch: value must fit the VRT 32-bit UTC seconds timestamp field.");
538 return 1;
539 }
540
541 auto* ctx = context;
542 core::OutputConfig config = ctx->getOutputConfig();
543 config.vita49.epoch_unix_nanoseconds = epoch_unix_nanoseconds;
544 ctx->setOutputConfig(std::move(config));
545 return 0;
546}

References core::Vita49OutputConfig::epoch_unix_nanoseconds, last_error_message, and core::OutputConfig::vita49.

◆ fers_set_vita49_fullscale()

int fers_set_vita49_fullscale ( fers_context_t context,
double  fullscale 
)

Sets the fixed ADC full-scale value used by the FERS VITA 49.2 int16 IQ profile.

VITA mode requires a positive finite full-scale before simulation starts. HDF5 output keeps its existing full-buffer scaling behavior.

Parameters
contextA valid fers_context_t handle.
fullscalePositive finite full-scale value.
Returns
0 on success, non-zero on error.

Definition at line 506 of file api.cpp.

507{
508 last_error_message.clear();
509 if (context == nullptr)
510 {
511 set_api_error("Invalid arguments: context is NULL.");
512 return -1;
513 }
514 if (!is_valid_vita49_fullscale(fullscale))
515 {
516 set_api_error("Invalid VITA49 fullscale: value must be positive and finite.");
517 return 1;
518 }
519
520 auto* ctx = context;
521 core::OutputConfig config = ctx->getOutputConfig();
522 config.vita49.adc_fullscale = static_cast<RealType>(fullscale);
523 ctx->setOutputConfig(std::move(config));
524 return 0;
525}

References core::Vita49OutputConfig::adc_fullscale, last_error_message, and core::OutputConfig::vita49.

◆ fers_set_vita49_max_udp_payload()

int fers_set_vita49_max_udp_payload ( fers_context_t context,
const std::uint16_t  max_udp_payload 
)

Definition at line 548 of file api.cpp.

549{
550 last_error_message.clear();
551 if (context == nullptr)
552 {
553 set_api_error("Invalid arguments: context is NULL.");
554 return -1;
555 }
556 if (!is_valid_vita49_max_payload(max_udp_payload))
557 {
558 set_api_error("Invalid VITA49 max UDP payload: value must be between 64 and 65507 bytes.");
559 return 1;
560 }
561
562 auto* ctx = context;
563 core::OutputConfig config = ctx->getOutputConfig();
564 config.vita49.max_udp_payload = max_udp_payload;
565 ctx->setOutputConfig(std::move(config));
566 return 0;
567}

References last_error_message, core::Vita49OutputConfig::max_udp_payload, and core::OutputConfig::vita49.

◆ fers_set_vita49_packet_trace_enabled()

int fers_set_vita49_packet_trace_enabled ( fers_context_t context,
int  enabled 
)

Enables or disables FERS VITA 49.2 packet trace telemetry.

Stream counter telemetry is unaffected. Disabling packet trace telemetry avoids per-packet diagnostic record creation for UI runs that only need live counters.

Parameters
contextA valid fers_context_t handle.
enabledNon-zero to enable packet trace telemetry, zero to disable it.
Returns
0 on success, non-zero on error.

Definition at line 590 of file api.cpp.

591{
592 last_error_message.clear();
593 if (context == nullptr)
594 {
595 set_api_error("Invalid arguments: context is NULL.");
596 return -1;
597 }
598
599 auto* ctx = context;
600 core::OutputConfig config = ctx->getOutputConfig();
601 config.vita49.packet_trace_enabled = enabled != 0;
602 ctx->setOutputConfig(std::move(config));
603 return 0;
604}

References last_error_message, core::Vita49OutputConfig::packet_trace_enabled, and core::OutputConfig::vita49.

◆ fers_set_vita49_queue_depth()

int fers_set_vita49_queue_depth ( fers_context_t context,
const std::uint32_t  queue_depth 
)

Definition at line 569 of file api.cpp.

570{
571 last_error_message.clear();
572 if (context == nullptr)
573 {
574 set_api_error("Invalid arguments: context is NULL.");
575 return -1;
576 }
577 if (queue_depth == 0)
578 {
579 set_api_error("Invalid VITA49 queue depth: value must be greater than zero.");
580 return 1;
581 }
582
583 auto* ctx = context;
584 core::OutputConfig config = ctx->getOutputConfig();
585 config.vita49.queue_depth = queue_depth;
586 ctx->setOutputConfig(std::move(config));
587 return 0;
588}

References last_error_message, core::Vita49OutputConfig::queue_depth, and core::OutputConfig::vita49.

◆ fers_update_antenna_from_json()

int fers_update_antenna_from_json ( fers_context_t context,
const char json 
)

Updates a single antenna from JSON without full context recreation.

Parameters
contextA valid fers_context_t handle.
jsonThe JSON string for the antenna.
Returns
0 on success, non-zero on failure.

Definition at line 868 of file api.cpp.

869{
870 last_error_message.clear();
871 if ((context == nullptr) || (json == nullptr))
872 return -1;
873 auto* ctx = context;
874 try
875 {
876 auto j = nlohmann::json::parse(json);
877 auto id = j.at("id").is_string() ? std::stoull(j.at("id").get<std::string>()) : j.at("id").get<uint64_t>();
878 auto* ant = ctx->getWorld()->findAntenna(id);
879 if (ant == nullptr)
880 {
881 last_error_message = "Antenna not found";
882 return 1;
883 }
885 return 0;
886 }
887 catch (const std::exception& e)
888 {
889 handle_api_exception(e, "fers_update_antenna_from_json");
890 return 1;
891 }
892}
void update_antenna_from_json(const nlohmann::json &j, antenna::Antenna *ant, core::World &world)
Updates an antenna from JSON without full context recreation.

References handle_api_exception(), last_error_message, and serial::update_antenna_from_json().

+ Here is the call graph for this function:

◆ fers_update_monostatic_from_json()

int fers_update_monostatic_from_json ( fers_context_t context,
const char json 
)

Updates a monostatic radar from JSON without full context recreation.

Parameters
contextA valid fers_context_t handle.
jsonThe JSON string for the monostatic component.
Returns
0 on success, non-zero on failure.

Definition at line 992 of file api.cpp.

993{
994 last_error_message.clear();
995 if ((context == nullptr) || (json == nullptr))
996 return -1;
997 auto* ctx = context;
998 try
999 {
1000 auto j = nlohmann::json::parse(json);
1001 uint64_t const tx_id =
1002 j.at("tx_id").is_string() ? std::stoull(j.at("tx_id").get<std::string>()) : j.at("tx_id").get<uint64_t>();
1003 uint64_t const rx_id =
1004 j.at("rx_id").is_string() ? std::stoull(j.at("rx_id").get<std::string>()) : j.at("rx_id").get<uint64_t>();
1005 auto* tx = ctx->getWorld()->findTransmitter(tx_id);
1006 auto* rx = ctx->getWorld()->findReceiver(rx_id);
1007 if ((tx == nullptr) || (rx == nullptr))
1008 {
1009 last_error_message = "Monostatic components not found";
1010 return 1;
1011 }
1012 serial::update_monostatic_from_json(j, tx, rx, *ctx->getWorld(), ctx->getMasterSeeder());
1013 return 0;
1014 }
1015 catch (const std::exception& e)
1016 {
1017 handle_api_exception(e, "fers_update_monostatic_from_json");
1018 return 1;
1019 }
1020}
void update_monostatic_from_json(const nlohmann::json &j, radar::Transmitter *tx, radar::Receiver *rx, core::World &world, std::mt19937 &masterSeeder)
Updates a monostatic radar from JSON without full context recreation.

References handle_api_exception(), last_error_message, and serial::update_monostatic_from_json().

+ Here is the call graph for this function:

◆ fers_update_parameters_from_json()

int fers_update_parameters_from_json ( fers_context_t context,
const char json 
)

Updates the global simulation parameters from JSON without full context recreation.

Parameters
contextA valid fers_context_t handle.
jsonThe JSON string for the parameters.
Returns
0 on success, non-zero on failure.

Definition at line 843 of file api.cpp.

844{
845 last_error_message.clear();
847 if ((context == nullptr) || (json == nullptr))
848 {
850 return -1;
851 }
852 auto* ctx = context;
853 try
854 {
855 auto j = nlohmann::json::parse(json);
856 serial::update_parameters_from_json(j, ctx->getMasterSeeder());
858 return 0;
859 }
860 catch (const std::exception& e)
861 {
863 handle_api_exception(e, "fers_update_parameters_from_json");
864 return 1;
865 }
866}
void update_parameters_from_json(const nlohmann::json &j, std::mt19937 &masterSeeder)
Updates global simulation parameters from JSON.

References begin_warning_capture(), complete_warning_capture(), discard_warning_capture(), handle_api_exception(), last_error_message, and serial::update_parameters_from_json().

+ Here is the call graph for this function:

◆ fers_update_platform_from_json()

int fers_update_platform_from_json ( fers_context_t context,
uint64_t  id,
const char json 
)

Updates a single platform's paths and name from JSON without full context recreation.

Parameters
contextA valid fers_context_t handle.
idThe unique ID of the platform.
jsonThe JSON string for the platform.
Returns
0 on success, non-zero on failure.

Definition at line 807 of file api.cpp.

808{
809 last_error_message.clear();
811 if ((context == nullptr) || (json == nullptr))
812 {
814 return -1;
815 }
816 auto* ctx = context;
817 try
818 {
819 auto* p = ctx->getWorld()->findPlatform(id);
820 if (p == nullptr)
821 {
822 last_error_message = "Platform not found";
824 return 1;
825 }
826 auto j = nlohmann::json::parse(json);
828 if (j.contains("name"))
829 {
830 p->setName(j.at("name").get<std::string>());
831 }
833 return 0;
834 }
835 catch (const std::exception& e)
836 {
838 handle_api_exception(e, "fers_update_platform_from_json");
839 return 1;
840 }
841}
void update_platform_paths_from_json(const nlohmann::json &j, radar::Platform *plat)
Updates a platform's motion and rotation paths from JSON.

References begin_warning_capture(), complete_warning_capture(), discard_warning_capture(), core::World::findPlatform(), FersContext::getWorld(), handle_api_exception(), last_error_message, and serial::update_platform_paths_from_json().

+ Here is the call graph for this function:

◆ fers_update_receiver_from_json()

int fers_update_receiver_from_json ( fers_context_t context,
uint64_t  id,
const char json 
)

Updates a single receiver from JSON without full context recreation.

Parameters
contextA valid fers_context_t handle.
idThe unique ID of the receiver.
jsonThe JSON string for the receiver.
Returns
0 on success, non-zero on failure.

Definition at line 942 of file api.cpp.

943{
944 last_error_message.clear();
945 if ((context == nullptr) || (json == nullptr))
946 return -1;
947 auto* ctx = context;
948 try
949 {
950 auto* rx = ctx->getWorld()->findReceiver(id);
951 if (rx == nullptr)
952 {
953 last_error_message = "Receiver not found";
954 return 1;
955 }
956 auto j = nlohmann::json::parse(json);
957 serial::update_receiver_from_json(j, rx, *ctx->getWorld(), ctx->getMasterSeeder());
958 return 0;
959 }
960 catch (const std::exception& e)
961 {
962 handle_api_exception(e, "fers_update_receiver_from_json");
963 return 1;
964 }
965}
void update_receiver_from_json(const nlohmann::json &j, radar::Receiver *rx, core::World &world, std::mt19937 &)
Updates a receiver from JSON without full context recreation.

References core::World::findReceiver(), FersContext::getWorld(), handle_api_exception(), last_error_message, and serial::update_receiver_from_json().

+ Here is the call graph for this function:

◆ fers_update_scenario_from_json()

int fers_update_scenario_from_json ( fers_context_t context,
const char scenario_json 
)

Updates the simulation scenario from a JSON string.

This is the primary method for the UI to push its state back to the C++ core. It performs a full replacement of the existing scenario.

Parameters
contextA valid fers_context_t handle.
scenario_jsonA null-terminated UTF-8 string containing the FERS scenario in JSON format.
Returns
0 on success. 1 on generic logic error. 2 on JSON parsing/schema validation error. Use fers_get_last_error_message() to retrieve error details.

Definition at line 1046 of file api.cpp.

1047{
1048 last_error_message.clear();
1050 if ((context == nullptr) || (scenario_json == nullptr))
1051 {
1052 last_error_message = "Invalid arguments: context or scenario_json is NULL.";
1055 return -1;
1056 }
1057
1058 auto* ctx = context;
1059 try
1060 {
1061 const nlohmann::json j = nlohmann::json::parse(scenario_json);
1062 serial::json_to_world(j, *ctx->getWorld(), ctx->getMasterSeeder());
1064
1065 return 0; // Success
1066 }
1067 catch (const nlohmann::json::exception& e)
1068 {
1069 // A specific catch block for JSON errors is used to provide more
1070 // detailed feedback to the client (e.g., the UI), which can help
1071 // developers diagnose schema or data format issues more easily.
1072 last_error_message = "JSON parsing/deserialization error: " + std::string(e.what());
1073 LOG(logging::Level::ERROR, "API Error in {}: {}", "fers_update_scenario_from_json", last_error_message);
1075 return 2; // JSON error
1076 }
1077 catch (const std::exception& e)
1078 {
1080 handle_api_exception(e, "fers_update_scenario_from_json");
1081 return 1; // Generic error
1082 }
1083}
void json_to_world(const nlohmann::json &j, core::World &world, std::mt19937 &masterSeeder)
Deserializes a nlohmann::json object and reconstructs the simulation world.

References begin_warning_capture(), complete_warning_capture(), discard_warning_capture(), logging::ERROR, handle_api_exception(), serial::json_to_world(), last_error_message, and LOG.

+ Here is the call graph for this function:

◆ fers_update_target_from_json()

int fers_update_target_from_json ( fers_context_t context,
uint64_t  id,
const char json 
)

Updates a single target from JSON without full context recreation.

Parameters
contextA valid fers_context_t handle.
idThe unique ID of the target.
jsonThe JSON string for the target.
Returns
0 on success, non-zero on failure.

Definition at line 967 of file api.cpp.

968{
969 last_error_message.clear();
970 if ((context == nullptr) || (json == nullptr))
971 return -1;
972 auto* ctx = context;
973 try
974 {
975 auto* tgt = ctx->getWorld()->findTarget(id);
976 if (tgt == nullptr)
977 {
978 last_error_message = "Target not found";
979 return 1;
980 }
981 auto j = nlohmann::json::parse(json);
982 serial::update_target_from_json(j, tgt, *ctx->getWorld(), ctx->getMasterSeeder());
983 return 0;
984 }
985 catch (const std::exception& e)
986 {
987 handle_api_exception(e, "fers_update_target_from_json");
988 return 1;
989 }
990}
void update_target_from_json(const nlohmann::json &j, radar::Target *existing_tgt, core::World &world, std::mt19937 &)
Updates a target from JSON without full context recreation.

References core::World::findTarget(), FersContext::getWorld(), handle_api_exception(), last_error_message, and serial::update_target_from_json().

+ Here is the call graph for this function:

◆ fers_update_timing_from_json()

int fers_update_timing_from_json ( fers_context_t context,
uint64_t  id,
const char json 
)

Updates a single timing source from JSON without full context recreation.

Parameters
contextA valid fers_context_t handle.
idThe unique ID of the timing source.
jsonThe JSON string for the timing source.
Returns
0 on success, non-zero on failure.

Definition at line 1022 of file api.cpp.

1023{
1024 last_error_message.clear();
1025 if ((context == nullptr) || (json == nullptr))
1026 return -1;
1027 auto* ctx = context;
1028 try
1029 {
1030 if (ctx->getWorld()->findTiming(id) == nullptr)
1031 {
1032 last_error_message = "Timing not found";
1033 return 1;
1034 }
1035 auto j = nlohmann::json::parse(json);
1036 serial::update_timing_from_json(j, *ctx->getWorld(), id);
1037 return 0;
1038 }
1039 catch (const std::exception& e)
1040 {
1041 handle_api_exception(e, "fers_update_timing_from_json");
1042 return 1;
1043 }
1044}
void update_timing_from_json(const nlohmann::json &j, core::World &world, const SimId id)
Updates a timing source from JSON without full context recreation.

References handle_api_exception(), last_error_message, and serial::update_timing_from_json().

+ Here is the call graph for this function:

◆ fers_update_transmitter_from_json()

int fers_update_transmitter_from_json ( fers_context_t context,
uint64_t  id,
const char json 
)

Updates a single transmitter from JSON without full context recreation.

Parameters
contextA valid fers_context_t handle.
idThe unique ID of the transmitter.
jsonThe JSON string for the transmitter.
Returns
0 on success, non-zero on failure.

Definition at line 917 of file api.cpp.

918{
919 last_error_message.clear();
920 if ((context == nullptr) || (json == nullptr))
921 return -1;
922 auto* ctx = context;
923 try
924 {
925 auto* tx = ctx->getWorld()->findTransmitter(id);
926 if (tx == nullptr)
927 {
928 last_error_message = "Transmitter not found";
929 return 1;
930 }
931 auto j = nlohmann::json::parse(json);
932 serial::update_transmitter_from_json(j, tx, *ctx->getWorld(), ctx->getMasterSeeder());
933 return 0;
934 }
935 catch (const std::exception& e)
936 {
937 handle_api_exception(e, "fers_update_transmitter_from_json");
938 return 1;
939 }
940}
void update_transmitter_from_json(const nlohmann::json &j, radar::Transmitter *tx, core::World &world, std::mt19937 &)
Updates a transmitter from JSON without full context recreation.

References core::World::findTransmitter(), FersContext::getWorld(), handle_api_exception(), last_error_message, and serial::update_transmitter_from_json().

+ Here is the call graph for this function:

◆ fers_update_waveform_from_json()

int fers_update_waveform_from_json ( fers_context_t context,
const char json 
)

Updates a single waveform from JSON without full context recreation.

Parameters
contextA valid fers_context_t handle.
jsonThe JSON string for the waveform.
Returns
0 on success, non-zero on failure.

Definition at line 894 of file api.cpp.

895{
896 last_error_message.clear();
897 if ((context == nullptr) || (json == nullptr))
898 return -1;
899 auto* ctx = context;
900 try
901 {
902 auto j = nlohmann::json::parse(json);
904 if (wf)
905 {
906 ctx->getWorld()->replace(std::move(wf));
907 }
908 return 0;
909 }
910 catch (const std::exception& e)
911 {
912 handle_api_exception(e, "fers_update_waveform_from_json");
913 return 1;
914 }
915}
std::unique_ptr< fers_signal::RadarSignal > parse_waveform_from_json(const nlohmann::json &j)
Parses a Waveform from JSON.

References handle_api_exception(), last_error_message, and serial::parse_waveform_from_json().

+ Here is the call graph for this function:

◆ fers_use_hdf5_output()

int fers_use_hdf5_output ( fers_context_t context)

Resets the context output mode to the default HDF5 output.

Runtime-only VITA 49.2 endpoint settings are retained for later VITA runs, but the selected output mode is changed back to HDF5.

Parameters
contextA valid fers_context_t handle.
Returns
0 on success, non-zero on error.

Definition at line 441 of file api.cpp.

442{
443 last_error_message.clear();
444 if (context == nullptr)
445 {
446 set_api_error("Invalid arguments: context is NULL.");
447 return -1;
448 }
449
450 auto* ctx = context;
451 try
452 {
453 core::OutputConfig config = ctx->getOutputConfig();
455 ctx->setOutputConfig(std::move(config));
456 return 0;
457 }
458 catch (const std::exception& e)
459 {
460 handle_api_exception(e, "fers_use_hdf5_output");
461 return 1;
462 }
463}

References handle_api_exception(), core::Hdf5, last_error_message, and core::OutputConfig::mode.

+ Here is the call graph for this function:

◆ handle_api_exception()

static void handle_api_exception ( const std::exception &  e,
const std::string function_name 
)
static

Centralized exception handler for the C-API boundary.

This function catches standard C++ exceptions, records their what() message into the thread-local error storage, and logs the error. This prevents C++ exceptions from propagating across the FFI boundary, which would be undefined behavior.

Parameters
eThe exception that was caught.
function_nameThe name of the API function where the error occurred.

Definition at line 72 of file api.cpp.

73{
74 last_error_message = e.what();
75 LOG(logging::Level::ERROR, "API Error in {}: {}", function_name, last_error_message);
76}

References logging::ERROR, last_error_message, and LOG.

Referenced by fers_calculate_preview_links(), fers_configure_logging(), fers_context_create(), fers_enable_vita49_udp_output(), fers_generate_kml(), fers_get_antenna_pattern(), fers_get_interpolated_motion_path(), fers_get_interpolated_rotation_path(), fers_get_last_output_metadata_json(), fers_get_memory_projection_json(), fers_get_scenario_as_json(), fers_get_scenario_as_xml(), fers_load_scenario_from_xml_file(), fers_load_scenario_from_xml_string(), fers_set_output_directory(), fers_set_thread_count(), fers_update_antenna_from_json(), fers_update_monostatic_from_json(), fers_update_parameters_from_json(), fers_update_platform_from_json(), fers_update_receiver_from_json(), fers_update_scenario_from_json(), fers_update_target_from_json(), fers_update_timing_from_json(), fers_update_transmitter_from_json(), fers_update_waveform_from_json(), and fers_use_hdf5_output().

+ Here is the caller graph for this function:

◆ map_api_log_level()

static logging::Level map_api_log_level ( fers_log_level_t  level)
static

Definition at line 129 of file api.cpp.

130{
131 switch (level)
132 {
133 case FERS_LOG_TRACE:
135 case FERS_LOG_DEBUG:
137 case FERS_LOG_INFO:
139 case FERS_LOG_WARNING:
141 case FERS_LOG_ERROR:
143 case FERS_LOG_FATAL:
145 case FERS_LOG_OFF:
146 return logging::Level::OFF;
147 default:
149 }
150}
@ FERS_LOG_FATAL
Fatal logging for unrecoverable failures.
Definition api.h:199
@ FERS_LOG_DEBUG
Debug-level diagnostic logging.
Definition api.h:195
@ FERS_LOG_ERROR
Error logging for failed operations.
Definition api.h:198
@ FERS_LOG_OFF
Disables logging output.
Definition api.h:200
@ FERS_LOG_INFO
Informational logging.
Definition api.h:196
@ FERS_LOG_TRACE
Trace-level diagnostic logging.
Definition api.h:194
@ FERS_LOG_WARNING
Warning logging for recoverable issues.
Definition api.h:197
@ WARNING
Warning level for potentially harmful situations.
@ FATAL
Fatal level for severe error events.
@ TRACE
Trace level for detailed debugging information.
@ OFF
Special level to disable all logging.
@ DEBUG
Debug level for general debugging information.

References logging::DEBUG, logging::ERROR, logging::FATAL, FERS_LOG_DEBUG, FERS_LOG_ERROR, FERS_LOG_FATAL, FERS_LOG_INFO, FERS_LOG_OFF, FERS_LOG_TRACE, FERS_LOG_WARNING, logging::INFO, logging::OFF, logging::TRACE, and logging::WARNING.

Referenced by fers_configure_logging(), and fers_log().

+ Here is the caller graph for this function:

◆ map_internal_log_level()

static fers_log_level_t map_internal_log_level ( logging::Level  level)
static

Definition at line 152 of file api.cpp.

153{
154 switch (level)
155 {
157 return FERS_LOG_TRACE;
159 return FERS_LOG_DEBUG;
161 return FERS_LOG_INFO;
163 return FERS_LOG_WARNING;
165 return FERS_LOG_ERROR;
167 return FERS_LOG_FATAL;
169 return FERS_LOG_OFF;
170 default:
171 return FERS_LOG_INFO;
172 }
173}

References logging::DEBUG, logging::ERROR, logging::FATAL, FERS_LOG_DEBUG, FERS_LOG_ERROR, FERS_LOG_FATAL, FERS_LOG_INFO, FERS_LOG_OFF, FERS_LOG_TRACE, FERS_LOG_WARNING, logging::INFO, logging::OFF, logging::TRACE, and logging::WARNING.

Referenced by fers_get_log_level().

+ Here is the caller graph for this function:

◆ to_cpp_interp_type()

math::Path::InterpType to_cpp_interp_type ( const fers_interp_type_t  type)

Definition at line 1274 of file api.cpp.

1275{
1276 switch (type)
1277 {
1278 case FERS_INTERP_LINEAR:
1280 case FERS_INTERP_CUBIC:
1282 case FERS_INTERP_STATIC:
1283 default:
1285 }
1286}
@ FERS_INTERP_STATIC
Definition api.h:596
@ FERS_INTERP_LINEAR
Definition api.h:597
@ INTERP_STATIC
Hold the first coordinate for all query times.
@ INTERP_LINEAR
Linearly interpolate between neighboring coordinates.
@ INTERP_CUBIC
Cubically interpolate between neighboring coordinates.

References FERS_INTERP_CUBIC, FERS_INTERP_LINEAR, FERS_INTERP_STATIC, math::Path::INTERP_CUBIC, math::Path::INTERP_LINEAR, and math::Path::INTERP_STATIC.

Referenced by fers_get_interpolated_motion_path().

+ Here is the caller graph for this function:

◆ to_cpp_rot_interp_type()

math::RotationPath::InterpType to_cpp_rot_interp_type ( const fers_interp_type_t  type)

Definition at line 1288 of file api.cpp.

1289{
1290 switch (type)
1291 {
1292 case FERS_INTERP_LINEAR:
1294 case FERS_INTERP_CUBIC:
1296 case FERS_INTERP_STATIC:
1297 default:
1299 }
1300}
@ INTERP_STATIC
Hold the first rotation for all query times.
@ INTERP_LINEAR
Linearly interpolate between neighboring rotations.
@ INTERP_CUBIC
Cubically interpolate between neighboring rotations.

References FERS_INTERP_CUBIC, FERS_INTERP_LINEAR, FERS_INTERP_STATIC, math::RotationPath::INTERP_CUBIC, math::RotationPath::INTERP_LINEAR, and math::RotationPath::INTERP_STATIC.

Referenced by fers_get_interpolated_rotation_path().

+ Here is the caller graph for this function:

Variable Documentation

◆ last_error_message

◆ last_warning_messages