FERS 1.0.0
The Flexible Extensible Radar Simulator
Loading...
Searching...
No Matches
main.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-only
2// Copyright (c) 2025-present FERS Contributors (see AUTHORS.md).
3
4/**
5 * @file main.cpp
6 * @brief Entry point for the FERS command-line interface (CLI).
7 *
8 * This executable acts as a wrapper around the libfers core library. It parses
9 * command-line arguments, uses the libfers C-API to load and run a simulation,
10 * and reports progress to the console.
11 */
12
13#include <filesystem>
14#include <format>
15#include <fstream>
16#include <iostream>
17#include <libfers/api.h>
18#include <string>
19
20#include "arg_parser.h"
21
22// --- Shim to restore LOG() functionality via C-API ---
23namespace logging
24{
25 inline std::string getLevelString(fers_log_level_t l)
26 {
27 switch (l)
28 {
29 case FERS_LOG_TRACE:
30 return "TRACE";
31 case FERS_LOG_DEBUG:
32 return "DEBUG";
33 case FERS_LOG_INFO:
34 return "INFO";
36 return "WARNING";
37 case FERS_LOG_ERROR:
38 return "ERROR";
39 case FERS_LOG_FATAL:
40 return "FATAL";
41 default:
42 return "UNKNOWN";
43 }
44 }
45}
46
47// Define LOG macro to format arguments and pass them to the library's logger
48#define LOG(level, ...) \
49 do \
50 { \
51 std::string _msg = std::format(__VA_ARGS__); \
52 fers_log(level, _msg.c_str()); \
53 } \
54 while (0)
55// -----------------------------------------------------
56
57int main(const int argc, char* argv[])
58{
59 // Parse command-line arguments using the local arg parser
60 const auto config_result = core::parseArguments(argc, argv);
61 if (!config_result)
62 {
63 if (config_result.error() != "Help requested." && config_result.error() != "Version requested." &&
64 config_result.error() != "No arguments provided.")
65 {
66 // Use basic stderr here because logging isn't configured yet
67 std::cerr << "[ERROR] Argument parsing error: " << config_result.error() << std::endl;
68 return 1;
69 }
70 return 0;
71 }
72
73 const auto& [script_file, log_level, num_threads, validate, log_file, generate_kml] = config_result.value();
74
75 // Configure logging via the C API
76 const char* log_file_ptr = log_file ? log_file->c_str() : nullptr;
77 if (fers_configure_logging(log_level, log_file_ptr) != 0)
78 {
79 // If we can't configure logging, we must print to stderr manually
80 char* err = fers_get_last_error_message();
81 std::cerr << "[ERROR] Failed to configure logging: " << (err ? err : "Unknown error") << std::endl;
83 return 1;
84 }
85
86 LOG(FERS_LOG_INFO, "FERS CLI started. Using libfers backend.");
87
89 "Running FERS with arguments: script_file={}, log_level={}, num_threads={}, validate={}, log_file={}",
90 script_file, logging::getLevelString(log_level), num_threads, validate, log_file.value_or("None"));
91
92 // Create a simulation context using the C-API
94 if (!context)
95 {
96 LOG(FERS_LOG_FATAL, "Failed to create FERS simulation context.");
97 return 1;
98 }
99
100 // Load the scenario from file via the C-API
101 LOG(FERS_LOG_INFO, "Loading scenario from '{}'...", script_file);
102 if (fers_load_scenario_from_xml_file(context, script_file.c_str(), validate ? 1 : 0) != 0)
103 {
104 char* err = fers_get_last_error_message();
105 LOG(FERS_LOG_FATAL, "Failed to load scenario: {}", err ? err : "Unknown error");
106 fers_free_string(err);
107 fers_context_destroy(context);
108 return 1;
109 }
110
111 if (generate_kml)
112 {
113 std::filesystem::path kml_output_path = script_file;
114 kml_output_path.replace_extension(".kml");
115 const std::string kml_output_file = kml_output_path.string();
116
117 LOG(FERS_LOG_INFO, "Generating KML file for scenario: {}", kml_output_file);
118 if (fers_generate_kml(context, kml_output_file.c_str()) == 0)
119 {
120 LOG(FERS_LOG_INFO, "KML file generated successfully: {}", kml_output_file);
121 }
122 else
123 {
124 char* err = fers_get_last_error_message();
125 LOG(FERS_LOG_FATAL, "Failed to generate KML file: {}", err ? err : "Unknown error");
126 fers_free_string(err);
127 }
128
129 fers_context_destroy(context);
130 return 0; // Exit after generating KML
131 }
132
133 // Set thread count via the C-API
134 if (fers_set_thread_count(num_threads) != 0)
135 {
136 char* err = fers_get_last_error_message();
137 LOG(FERS_LOG_ERROR, "Failed to set number of threads: {}", err ? err : "Unknown error");
138 fers_free_string(err);
139 }
140
141 // Run the simulation via the C-API
142 LOG(FERS_LOG_INFO, "Starting simulation...");
143 if (fers_run_simulation(context, nullptr, nullptr) != 0)
144 {
145 char* err = fers_get_last_error_message();
146 LOG(FERS_LOG_FATAL, "Simulation run failed: {}", err ? err : "Unknown error");
147 fers_free_string(err);
148 fers_context_destroy(context);
149 return 1;
150 }
151 LOG(FERS_LOG_INFO, "Simulation completed successfully.");
152
153 fers_context_destroy(context);
154
155 return 0;
156}
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.
Definition api.cpp:162
char * fers_get_last_error_message()
Retrieves the last error message that occurred on the current thread.
Definition api.cpp:334
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.
Definition api.cpp:390
fers_log_level_t
Log levels for the FERS library.
Definition api.h:76
@ FERS_LOG_FATAL
Definition api.h:82
@ FERS_LOG_DEBUG
Definition api.h:78
@ FERS_LOG_ERROR
Definition api.h:81
@ FERS_LOG_INFO
Definition api.h:79
@ FERS_LOG_TRACE
Definition api.h:77
@ FERS_LOG_WARNING
Definition api.h:80
void fers_context_destroy(fers_context_t *context)
Destroys a FERS simulation context and releases all associated memory.
Definition api.cpp:79
fers_context_t * fers_context_create()
Creates a new FERS simulation context.
Definition api.cpp:60
int fers_run_simulation(fers_context_t *context, fers_progress_callback_t callback, void *user_data)
Runs the simulation defined in the provided context.
Definition api.cpp:354
void fers_free_string(char *str)
Frees a string that was allocated and returned by the libfers API.
Definition api.cpp:346
int fers_configure_logging(fers_log_level_t level, const char *log_file_path)
Configures the internal logger.
Definition api.cpp:112
int fers_set_thread_count(unsigned num_threads)
Sets the number of worker threads for the simulation.
Definition api.cpp:144
Command-line argument parsing utilities for the application.
int main(const int argc, char *argv[])
Definition main.cpp:57
#define LOG(level,...)
Definition main.cpp:48
std::expected< Config, std::string > parseArguments(const int argc, char *argv[]) noexcept
Parses command-line arguments.
std::string getLevelString(const Level level) noexcept
Converts a log level enum value to its string representation.
Definition logging.h:121