40constexpr const char *
Init =
"INIT";
42constexpr const char *
Stage =
"STAGE";
43constexpr const char *
Run =
"RUN";
55 using Clock = std::chrono::high_resolution_clock;
61 : startup_time_(
Clock::now()), log_file_(log_file_path), log_file_name_(log_file_path) {}
72 void SetVersion(
const std::string &version) { version_ = version; }
75 void SetBuildType(
const std::string &build_type) { build_type_ = build_type; }
97 return Clock::now() - startup_time_;
102 if (log_file_.is_open()) {
105 log_file_name_ = path;
107 log_file_.open(path);
116 console_.WriteLine(splash);
122 const std::string &description =
"") {
123 std::ostringstream oss;
124 oss <<
"[SIM] Simulation: " << name <<
" (v" << version <<
")";
127 if (!description.empty()) {
129 std::string first_line = description;
130 auto pos = first_line.find(
'\n');
131 if (pos != std::string::npos) {
132 first_line = first_line.substr(0, pos);
134 if (!first_line.empty()) {
145 std::ostringstream oss;
146 oss <<
"[CFG] Time: start=" << std::fixed << std::setprecision(1) << t_start
147 <<
"s, end=" << t_end <<
"s, dt=" << std::setprecision(4) << dt <<
"s";
164 std::ostringstream oss;
165 oss <<
"[PHASE] Configured with " << config.
definitions.size()
172 current_lifecycle_ = lifecycle_name;
173 lifecycle_start_time_ = Clock::now();
176 console_.WriteLine(header);
182 auto elapsed = std::chrono::duration<double>(Clock::now() - lifecycle_start_time_).count();
183 std::ostringstream oss;
184 oss <<
"[SYS] " << current_lifecycle_ <<
" phase complete (" << FormatDuration(elapsed)
191 if (log_file_name_.empty()) {
192 return "signal_dictionary.dict";
195 std::string base = log_file_name_;
196 auto dot_pos = base.rfind(
'.');
197 if (dot_pos != std::string::npos) {
198 base = base.substr(0, dot_pos);
200 return base +
"_signal_dictionary.dict";
216 run_start_wall_time_ = Clock::now();
217 std::ostringstream oss;
218 oss <<
"[SYS] Starting simulation (t=" << std::fixed << std::setprecision(3) << t_start
219 <<
" → " << std::setprecision(1) << t_end <<
" s, dt=" << std::setprecision(4) << dt
226 double progress = (t_end > 0) ? (sim_time / t_end) * 100.0 : 0.0;
228 std::chrono::duration<double>(Clock::now() - run_start_wall_time_).count();
229 double rtf = (wall_elapsed > 0) ? sim_time / wall_elapsed : 0.0;
231 std::ostringstream oss;
232 oss <<
"[RUN] Progress: " << std::fixed << std::setprecision(1) << progress <<
"% ("
233 << std::setprecision(1) << sim_time <<
"/" << t_end
234 <<
" s, RTF: " << std::setprecision(1) << rtf <<
"x)";
245 if (profiling_enabled_) {
249 std::string output = debrief.
Generate();
250 console_.Write(output);
263 const std::string &config_source =
"defaults",
bool is_last =
false) {
264 std::string prefix = is_last ?
"└─" :
"├─";
265 std::ostringstream oss;
266 oss <<
" " << prefix <<
" [CMP] " << component_name <<
" (" << type <<
")";
267 if (config_source !=
"defaults") {
268 oss <<
" [" << config_source <<
"]";
270 console_.WriteLine(oss.str());
271 WriteToFile(oss.str());
275 void LogAssetLoad(
const std::string &asset_name,
const std::string &description) {
281 std::ostringstream oss;
282 oss <<
"[MEM] States: " << continuous <<
" continuous";
284 oss <<
", " << discrete <<
" discrete";
292 void LogWiring(
const std::string &source,
const std::string &target,
bool is_warning =
false) {
293 std::string prefix = is_warning ?
"[!WIR]" :
"[WIR]";
294 std::ostringstream oss;
295 oss <<
" ├─ " << source <<
" >> " << target;
297 console_.Warning(oss.str());
311 for (std::size_t i = 0; i < component_order.size(); ++i) {
312 std::ostringstream oss;
313 oss <<
" " << (i + 1) <<
". " << component_order[i];
320 const std::unordered_map<std::string, int> &divisors) {
321 std::ostringstream header;
322 header <<
"[SCH] Scheduler (sim rate: " << sim_rate_hz <<
" Hz)";
325 for (std::size_t i = 0; i < groups.size(); ++i) {
326 const auto &group = groups[i];
327 auto it = divisors.find(group.name);
328 int divisor = (it != divisors.end()) ? it->second : 1;
329 double group_dt = 1.0 / group.rate_hz;
331 std::ostringstream oss;
332 bool is_last = (i == groups.size() - 1);
333 oss <<
" " << (is_last ?
"└─" :
"├─") <<
" [" << group.name <<
"] "
334 << group.rate_hz <<
" Hz (÷" << divisor <<
", dt=" << std::fixed
335 << std::setprecision(6) << group_dt <<
"s)";
338 for (std::size_t j = 0; j < group.members.size(); ++j) {
339 const auto &member = group.members[j];
340 std::ostringstream mem_oss;
341 bool mem_last = (j == group.members.size() - 1);
342 mem_oss <<
" " << (is_last ?
" " :
"│ ") << (mem_last ?
"└─" :
"├─")
343 <<
" " << member.component;
351 const std::vector<std::pair<std::string, double>> &targets) {
353 for (
const auto &[name, value] : targets) {
354 std::ostringstream oss;
355 oss <<
" └─ Target: " << name <<
" = " << value;
361 std::ostringstream oss;
362 oss <<
"[TRM] Iteration " << iteration <<
": residual = " << std::scientific << residual;
367 std::ostringstream oss;
368 oss <<
"[TRM] Converged in " << iterations <<
" iterations";
381 Log(
LogLevel::Info,
"[LIN] ═══════════════════════════════════════════════════════");
383 Log(
LogLevel::Info,
"[LIN] ═══════════════════════════════════════════════════════");
387 std::ostringstream oss;
388 oss <<
"[LIN] State-Space: A[" << model.
A.rows() <<
"x" << model.
A.cols() <<
"], B["
389 << model.
B.rows() <<
"x" << model.
B.cols() <<
"], C[" << model.
C.rows() <<
"x"
390 << model.
C.cols() <<
"], D[" << model.
D.rows() <<
"x" << model.
D.cols() <<
"]";
396 for (std::size_t i = 0; i < model.
state_names.size(); ++i) {
397 std::ostringstream oss;
398 oss <<
" " << model.
state_names[i] <<
" = " << std::scientific
399 << std::setprecision(4) << model.
x0(
static_cast<Eigen::Index
>(i));
405 for (Eigen::Index i = 0; i < model.
A.rows(); ++i) {
406 std::ostringstream oss;
408 for (Eigen::Index j = 0; j < model.
A.cols(); ++j) {
409 oss << std::fixed << std::setw(12) << std::setprecision(6) << model.
A(i, j);
410 if (j < model.
A.cols() - 1)
420 for (Eigen::Index i = 0; i < eigenvalues.size(); ++i) {
421 double real = eigenvalues(i).real();
422 double imag = eigenvalues(i).imag();
424 std::ostringstream oss;
425 oss <<
" λ" << (i + 1) <<
" = " << std::scientific << std::setprecision(4)
427 if (std::abs(imag) > 1e-10) {
428 oss << (imag >= 0 ?
" + " :
" - ") << std::abs(imag) <<
"i";
430 double period = 2.0 * std::numbers::pi / std::abs(imag);
431 oss << std::fixed << std::setprecision(1) <<
" (period: " << period
432 <<
" s = " << period / 60.0 <<
" min)";
439 std::ostringstream oss;
440 oss <<
"[LIN] Stability: " << (model.
IsStable() ?
"STABLE" :
"UNSTABLE")
441 <<
" (Lyapunov sense)";
445 std::ostringstream oss;
452 std::ostringstream oss;
453 oss <<
"[LIN] Observability: " << model.
ObservabilityRank() <<
" / " << model.
A.rows()
458 Log(
LogLevel::Info,
"[LIN] ═══════════════════════════════════════════════════════");
464 void LogPhaseEvent(
const std::string &from_phase,
const std::string &to_phase,
467 "[PHS] Phase transition: " + from_phase +
" -> " + to_phase);
471 void LogEvent(
const std::string &event_name,
double sim_time,
const std::string &details =
"") {
472 std::string msg =
"[EVT] " + event_name;
473 if (!details.empty()) {
474 msg +=
": " + details;
480 void LogRunWarning(
const std::string &source,
const std::string &message,
double sim_time) {
485 void LogRunError(
const std::string &source,
const std::string &message,
double sim_time) {
491 const std::map<std::string, double> &key_values = {}) {
492 if (!progress_enabled_ || !console_.
IsTerminal()) {
496 double progress = (t_max > 0) ? (sim_time / t_max) : 0.0;
497 int filled =
static_cast<int>(progress *
static_cast<double>(progress_width_));
499 std::ostringstream oss;
500 oss <<
"\r[RUN] Time: " << std::fixed << std::setprecision(2) << sim_time <<
"s | [";
502 for (
int i = 0; i < progress_width_; ++i) {
510 oss <<
"] " <<
static_cast<int>(progress * 100) <<
"%";
512 for (
const auto &[key, value] : key_values) {
513 oss <<
" | " << key <<
": " << std::fixed << std::setprecision(1) << value;
516 std::cout << oss.str() << std::flush;
521 if (progress_enabled_ && console_.IsTerminal()) {
522 std::cout <<
"\r" << std::string(120,
' ') <<
"\r" << std::flush;
530 if (!profiling_enabled_) {
533 current_timed_component_ = component_name;
534 component_start_time_ = Clock::now();
539 if (!profiling_enabled_ || current_timed_component_.empty()) {
544 std::chrono::duration<double, std::micro>(Clock::now() - component_start_time_).count();
546 auto &stats = component_stats_[current_timed_component_];
547 stats.name = current_timed_component_;
549 stats.total_time_us += elapsed;
550 stats.max_time_us = std::max(stats.max_time_us, elapsed);
551 stats.avg_time_us = stats.total_time_us /
static_cast<double>(stats.call_count);
553 current_timed_component_.clear();
558 std::vector<ComponentStats> result;
559 result.reserve(component_stats_.size());
562 double total_time = 0.0;
563 for (
const auto &[name, stats] : component_stats_) {
564 total_time += stats.total_time_us;
567 for (
auto [name, stats] : component_stats_) {
568 if (total_time > 0) {
569 stats.percent_load = (stats.total_time_us / total_time) * 100.0;
571 result.push_back(stats);
585 console_.Log(level, message);
586 if (log_file_.is_open() && level >= file_level_) {
587 log_file_ << LevelPrefix(level) <<
" " << StripAnsi(message) <<
"\n";
593 std::string formatted = FormatTime(sim_time) +
" " + message;
594 console_.Log(level, formatted);
595 if (log_file_.is_open() && level >= file_level_) {
596 log_file_ << LevelPrefix(level) <<
" " << StripAnsi(formatted) <<
"\n";
603 std::ofstream log_file_;
604 std::string log_file_name_;
610 std::string build_type_ =
"RELEASE";
612 std::string build_type_ =
"DEBUG";
622 bool progress_enabled_ =
true;
623 int progress_width_ = 40;
626 bool profiling_enabled_ =
false;
627 std::map<std::string, ComponentStats> component_stats_;
628 std::string current_timed_component_;
632 [[nodiscard]]
double GetWallClockSeconds()
const {
633 return std::chrono::duration<double>(Clock::now() - startup_time_).count();
637 [[nodiscard]]
static std::string FormatTime(
double t) {
638 std::ostringstream oss;
639 if (t >= 1000.0 || t <= -1000.0) {
640 oss <<
"[" << std::scientific << std::setprecision(2) << t <<
"]";
642 oss <<
"[" << std::fixed << std::setprecision(6) << t <<
"]";
648 [[nodiscard]]
static std::string FormatDuration(
double seconds) {
649 std::ostringstream oss;
650 if (seconds < 0.001) {
651 oss << std::fixed << std::setprecision(1) << (seconds * 1e6) <<
"μs";
652 }
else if (seconds < 1.0) {
653 oss << std::fixed << std::setprecision(2) << (seconds * 1000) <<
"ms";
655 oss << std::fixed << std::setprecision(2) << seconds <<
"s";
660 void WriteToFile(
const std::string &message) {
661 if (log_file_.is_open()) {
662 log_file_ << StripAnsi(message) <<
"\n";
667 [[nodiscard]]
static std::string LevelPrefix(
LogLevel level) {
687 [[nodiscard]]
static std::string StripAnsi(
const std::string &s) {
689 result.reserve(s.size());
690 bool in_escape =
false;
694 }
else if (in_escape && c ==
'm') {
696 }
else if (!in_escape) {
ASCII art banners and headers.
Console abstraction with ANSI color support.
Core type definitions, concepts, and configuration for Icarus.
Complete catalog of simulation interface.
ASCII Data Dictionary formatter.
Shutdown statistics and profiling report.
Simulator and subsystem configuration structs.
Core types for staging subsystem (trim, linearization, symbolic).
static std::string GetLifecycleHeader(const std::string &lifecycle_name)
Get a section header.
Definition Banner.hpp:28
static std::string GetSplashScreen(const std::string &build_type="RELEASE", const std::string &version="0.1.0")
Get the main Icarus splash screen (ASCII art logo).
Definition Banner.hpp:20
Console output with color and formatting support.
Definition Console.hpp:111
bool IsTerminal() const
Check if stdout is a terminal (supports ANSI codes).
Definition Console.hpp:116
Generate Flight Manifest (ASCII Data Dictionary).
Definition FlightManifest.hpp:38
std::string GenerateSummary(const DataDictionary &dict) const
Generate summary string (for console).
Definition FlightManifest.hpp:94
void SetVersion(const std::string &version)
Set simulation version string.
Definition FlightManifest.hpp:48
void SetOutputPath(const std::filesystem::path &path)
Set output file path (default: "signal_dictionary.dict").
Definition FlightManifest.hpp:45
void Generate(const DataDictionary &dict)
Generate manifest: write full to file, summary to console.
Definition FlightManifest.hpp:61
Mission Debrief generator.
Definition MissionDebrief.hpp:51
std::string Generate() const
Generate the full debrief string.
Definition MissionDebrief.hpp:74
void SetTiming(double sim_time, double wall_time)
Set timing information.
Definition MissionDebrief.hpp:62
void SetExitReason(const std::string &reason)
Set exit reason message.
Definition MissionDebrief.hpp:59
void SetExitStatus(ExitStatus status)
Set exit status.
Definition MissionDebrief.hpp:56
void SetProfilingData(const std::vector< ComponentStats > &stats)
Set profiling data.
Definition MissionDebrief.hpp:71
void LogRunError(const std::string &source, const std::string &message, double sim_time)
Log error during run.
Definition MissionLogger.hpp:485
LogLevel GetConsoleLevel() const
Get current console level.
Definition MissionLogger.hpp:87
void BeginComponentTiming(const std::string &component_name)
Begin timing a component.
Definition MissionLogger.hpp:529
void LogStateAllocation(std::size_t continuous, std::size_t discrete=0)
Log state vector allocation.
Definition MissionLogger.hpp:280
void LogAssetLoad(const std::string &asset_name, const std::string &description)
Log static asset loading.
Definition MissionLogger.hpp:275
void LogSimulationConfig(const std::string &name, const std::string &version, const std::string &description="")
Log simulation configuration info (from YAML).
Definition MissionLogger.hpp:121
void LogPhaseConfig(const PhaseConfig &config)
Log phase configuration.
Definition MissionLogger.hpp:160
void SetFileLevel(LogLevel level)
Set file log level (log file output).
Definition MissionLogger.hpp:69
void UpdateProgress(double sim_time, double t_max, const std::map< std::string, double > &key_values={})
Update progress display (single-line, \r overwrite).
Definition MissionLogger.hpp:490
MissionLogger()
Definition MissionLogger.hpp:58
void LogTimeConfig(double t_start, double t_end, double dt)
Log time configuration.
Definition MissionLogger.hpp:144
void LogEntityLoad(const std::string &entity_name)
Log entity loading.
Definition MissionLogger.hpp:257
void LogComponentAdd(const std::string &component_name, const std::string &type, const std::string &config_source="defaults", bool is_last=false)
Log component addition (tree format).
Definition MissionLogger.hpp:262
void LogWiring(const std::string &source, const std::string &target, bool is_warning=false)
Log signal wiring.
Definition MissionLogger.hpp:292
void BeginLifecycle(const char *lifecycle_name)
Begin a lifecycle phase.
Definition MissionLogger.hpp:171
void Log(LogLevel level, const std::string &message)
Log raw message.
Definition MissionLogger.hpp:584
void EndComponentTiming()
End timing for current component.
Definition MissionLogger.hpp:538
void LogRunWarning(const std::string &source, const std::string &message, double sim_time)
Log warning during run.
Definition MissionLogger.hpp:480
void LogTrimStart(const std::string &mode, const std::vector< std::pair< std::string, double > > &targets)
Log trim solver progress.
Definition MissionLogger.hpp:350
void LogManifest(const DataDictionary &dict)
Log the Flight Manifest (Data Dictionary).
Definition MissionLogger.hpp:204
Clock::time_point TimePoint
Definition MissionLogger.hpp:56
std::string GetDictionaryPath() const
Get the signal dictionary output path (derived from log file name).
Definition MissionLogger.hpp:190
void SetVersion(const std::string &version)
Set simulation version string.
Definition MissionLogger.hpp:72
void LogRunStart(double t_start, double t_end, double dt)
Log simulation run start (entering RUN phase).
Definition MissionLogger.hpp:215
void SetLogFile(const std::string &path)
Set log file path (closes existing if open).
Definition MissionLogger.hpp:101
MissionLogger(const std::string &log_file_path)
Definition MissionLogger.hpp:60
std::string GetLogFileName() const
Get current log file name.
Definition MissionLogger.hpp:84
void LogSchedulerOrder(double sim_rate_hz, const std::vector< SchedulerGroupConfig > &groups, const std::unordered_map< std::string, int > &divisors)
Log scheduler execution order with groups and rates (Debug level).
Definition MissionLogger.hpp:319
void LogIntegrator(IntegratorType type)
Log integrator type (enum version).
Definition MissionLogger.hpp:157
void LogTimed(LogLevel level, double sim_time, const std::string &message)
Definition MissionLogger.hpp:592
bool IsProgressEnabled() const
Check if progress is enabled.
Definition MissionLogger.hpp:90
Console & GetConsole()
Get underlying console.
Definition MissionLogger.hpp:580
void LogRunProgress(double sim_time, double t_end)
Log periodic run progress.
Definition MissionLogger.hpp:225
void LogIntegrator(const std::string &type)
Log integrator type.
Definition MissionLogger.hpp:152
void LogLinearModel(const staging::LinearModel &model)
Log linear model summary (called after linearization).
Definition MissionLogger.hpp:379
std::chrono::nanoseconds WallElapsed() const
Get total wall time elapsed since startup.
Definition MissionLogger.hpp:96
void LogPhaseEvent(const std::string &from_phase, const std::string &to_phase, double sim_time)
Log phase transition event.
Definition MissionLogger.hpp:464
void LogExecutionOrder(const std::vector< std::string > &component_order)
Log topological sort order.
Definition MissionLogger.hpp:309
void SetBuildType(const std::string &build_type)
Set build type (DEBUG/RELEASE) - auto-detected by default.
Definition MissionLogger.hpp:75
void LogConfigFile(const std::string &path)
Log configuration file path.
Definition MissionLogger.hpp:141
void LogTrimConverged(int iterations)
Definition MissionLogger.hpp:366
void LogStartup()
Log simulation startup (splash screen) - uses Icarus engine version.
Definition MissionLogger.hpp:114
void EndLifecycle(double sim_time=0.0)
End current lifecycle phase (pass current sim time for consistent timestamps).
Definition MissionLogger.hpp:181
std::chrono::high_resolution_clock Clock
Definition MissionLogger.hpp:55
bool IsProfilingEnabled() const
Check if profiling is enabled.
Definition MissionLogger.hpp:93
void LogTrimIteration(int iteration, double residual)
Definition MissionLogger.hpp:360
void ClearProgress()
Clear progress line (call after Run completes).
Definition MissionLogger.hpp:520
void LogWiringWarning(const std::string &message)
Log wiring warning (multiple writers, etc.).
Definition MissionLogger.hpp:304
std::vector< ComponentStats > GetProfilingStats() const
Get profiling statistics.
Definition MissionLogger.hpp:557
void LogEvent(const std::string &event_name, double sim_time, const std::string &details="")
Log notable event (apogee, impact, etc.).
Definition MissionLogger.hpp:471
const Console & GetConsole() const
Definition MissionLogger.hpp:581
void LogDebrief(double sim_time, double wall_time)
Log mission debrief (shutdown statistics).
Definition MissionLogger.hpp:239
void SetProfilingEnabled(bool enabled)
Enable/disable profiling.
Definition MissionLogger.hpp:81
void SetProgressEnabled(bool enabled)
Enable/disable progress display during Run.
Definition MissionLogger.hpp:78
void SetConsoleLevel(LogLevel level)
Set console log level (terminal output).
Definition MissionLogger.hpp:66
void LogTrimFailed(const std::string &reason)
Definition MissionLogger.hpp:372
Simulation phase names for logging banners.
Definition MissionLogger.hpp:39
constexpr const char * Run
Definition MissionLogger.hpp:43
constexpr const char * Provision
Definition MissionLogger.hpp:41
constexpr const char * Stage
Definition MissionLogger.hpp:42
constexpr const char * Init
Definition MissionLogger.hpp:40
constexpr const char * Shutdown
Definition MissionLogger.hpp:44
Definition AggregationTypes.hpp:13
@ EndConditionMet
End condition triggered.
Definition MissionDebrief.hpp:28
const char * to_string(SignalKind kind)
Convert SignalKind to string.
Definition Signal.hpp:86
IntegratorType
Available integrator methods.
Definition IntegratorTypes.hpp:27
constexpr const char * Version()
Version string (derived from components).
Definition CoreTypes.hpp:152
LogLevel
Log severity levels.
Definition Console.hpp:35
@ Warning
Potential issues.
Definition Console.hpp:40
@ Info
Normal operation.
Definition Console.hpp:38
@ Fatal
Unrecoverable errors.
Definition Console.hpp:42
@ Error
Recoverable errors.
Definition Console.hpp:41
@ Event
Simulation events (phase changes, etc.).
Definition Console.hpp:39
@ Debug
Debugging info.
Definition Console.hpp:37
@ Trace
Most verbose, internal debugging.
Definition Console.hpp:36
Complete catalog of simulation interface.
Definition DataDictionary.hpp:45
Configuration for phase management.
Definition PhaseManager.hpp:40
std::map< std::string, int32_t > definitions
Phase name to integer mapping (e.g., {"GROUND": 0, "BOOST": 1, ...}).
Definition PhaseManager.hpp:42
std::string initial_phase
Initial phase name.
Definition PhaseManager.hpp:45
Linear state-space model.
Definition LinearModel.hpp:31
bool IsStable() const
Check if system is stable (all eigenvalues have negative real part).
Definition LinearModel.hpp:367
std::vector< std::string > state_names
Definition LinearModel.hpp:37
Eigen::MatrixXd B
Input matrix (n_states x n_inputs).
Definition LinearModel.hpp:33
int ObservabilityRank() const
Compute observability matrix rank.
Definition LinearModel.hpp:343
Eigen::MatrixXd D
Feedthrough matrix (n_outputs x n_inputs).
Definition LinearModel.hpp:35
Eigen::MatrixXd C
Output matrix (n_outputs x n_states).
Definition LinearModel.hpp:34
Eigen::MatrixXd A
State matrix (n_states x n_states).
Definition LinearModel.hpp:32
Eigen::VectorXcd Eigenvalues() const
Get eigenvalues of A matrix.
Definition LinearModel.hpp:380
Eigen::VectorXd x0
Operating point where linearization was performed.
Definition LinearModel.hpp:42
int ControllabilityRank() const
Compute controllability matrix rank.
Definition LinearModel.hpp:314