38#include <unordered_map>
39#include <unordered_set>
43#include <janus/core/Function.hpp>
44#include <janus/core/JanusTypes.hpp>
47#include <vulcan/time/Epoch.hpp>
85 [[nodiscard]]
static std::unique_ptr<Simulator>
FromConfig(
const std::string &config_path);
126 void Step(
double dt);
134 [[nodiscard]]
const std::string &
Name()
const {
return config_.name; }
137 [[nodiscard]]
double Dt()
const {
return config_.dt; }
140 [[nodiscard]]
double EndTime()
const {
return config_.t_end; }
143 [[nodiscard]]
double Time()
const {
return epoch_ - epoch_start_; }
146 [[nodiscard]]
const vulcan::time::NumericEpoch &
Epoch()
const {
return epoch_; }
149 [[nodiscard]]
double JD_UTC()
const {
return epoch_.jd_utc(); }
152 [[nodiscard]]
double JD_TAI()
const {
return epoch_.jd_tai(); }
155 [[nodiscard]]
double JD_TT()
const {
return epoch_.jd_tt(); }
158 [[nodiscard]]
double JD_GPS()
const {
return epoch_.jd_gps(); }
161 [[nodiscard]]
int GPSWeek()
const {
return epoch_.gps_week(); }
167 [[nodiscard]] std::string
ISO8601()
const {
return epoch_.to_iso_string(); }
173 [[nodiscard]] int32_t
GetFlightPhase()
const {
return phase_manager_.CurrentPhase(); }
177 return phase_manager_.CurrentPhaseName();
190 [[nodiscard]]
double Peek(
const std::string &name)
const {
return registry_.GetByName(name); }
211 void Poke(
const std::string &name,
double value) { registry_.SetByName(name, value); }
258 [[nodiscard]] Eigen::VectorXd
GetState()
const;
261 void SetState(
const Eigen::VectorXd &X);
279 [[nodiscard]] std::optional<janus::Function>
GetJacobian()
const;
285 [[nodiscard]]
const std::optional<staging::TrimResult> &
GetTrimResult()
const {
293 [[nodiscard]]
const std::optional<staging::LinearModel> &
GetLinearModel()
const {
294 return linear_model_;
316 void AddRoutes(
const std::vector<signal::SignalRoute> &routes);
319 [[nodiscard]] std::size_t
NumComponents()
const {
return components_.size(); }
337 void AllocateAndBindState();
340 void ApplyInitialConditions();
343 void ValidateWiring();
346 void InvokeInputSources();
349 void InvokeOutputObservers();
352 void InitializeEpoch();
361 std::vector<std::unique_ptr<Component<double>>> components_;
378 vulcan::time::NumericEpoch epoch_;
379 vulcan::time::NumericEpoch epoch_start_;
381 int frame_count_ = 0;
384 std::optional<janus::Function> dynamics_graph_;
385 std::optional<janus::Function> jacobian_;
388 std::unique_ptr<HDF5Recorder> recorder_;
391 std::optional<staging::TrimResult> trim_result_;
392 std::optional<staging::LinearModel> linear_model_;
395 std::unordered_map<std::string, InputSourceCallback> input_sources_;
396 std::unordered_map<std::string, OutputObserverCallback> output_observers_;
399 std::unordered_map<Component<double> *, std::vector<std::string>> outputs_;
400 std::unordered_map<Component<double> *, std::vector<std::string>> inputs_;
412 struct FrameContext {
413 std::unordered_set<std::string> active_components;
414 std::unordered_set<std::string> all_scheduled_components;
417 [[nodiscard]]
bool ShouldRun(
const std::string &name)
const {
419 if (!all_scheduled_components.contains(name)) {
423 return active_components.contains(name);
428 [[nodiscard]] FrameContext BuildFrameContext()
const;
431 void ExecComponent(Component<double> &comp,
void (Component<double>::*method)(
double,
double),
432 double t,
double dt);
452 size_t frames = recorder_->FrameCount();
454 logger_.Log(
LogLevel::Info,
"[REC] Recording complete: " + std::to_string(frames) +
455 " frames written to " + config_.recording.path);
462 auto wall_time = std::chrono::duration<double>(logger_.WallElapsed()).count();
463 logger_.LogDebrief(
Time(), wall_time);
474 sim->logger_.LogConfigFile(config_path);
480 auto sim = std::make_unique<Simulator>();
481 sim->Configure(config);
484 sim->logger_.LogStartup();
490 sim->logger_.LogTimeConfig(config.
t_start, config.
t_end, config.
dt);
494 sim->logger_.LogPhaseConfig(config.
phases);
501 std::size_t comp_count = config.
components.size();
502 for (std::size_t i = 0; i < comp_count; ++i) {
504 auto component = factory.Create(comp_cfg);
507 bool is_last = (i == comp_count - 1);
508 sim->logger_.LogComponentAdd(comp_cfg.name, comp_cfg.type,
"YAML", is_last);
510 sim->AddComponent(std::move(component));
514 sim->AddRoutes(config.
routes);
520 sim->logger_.LogStateAllocation(sim->state_manager_.TotalSize());
523 auto dict = sim->GetDataDictionary();
524 sim->logger_.LogManifest(dict);
526 sim->logger_.EndLifecycle();
531inline void Simulator::InitializeEpoch() {
536 static const std::regex iso8601_regex(
537 R
"(^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(\.\d+)?(Z|([+-])(\d{2}):?(\d{2}))?$)");
544 if (!std::regex_match(config_.
epoch.
reference, match, iso8601_regex)) {
546 " (expected ISO 8601: YYYY-MM-DDTHH:MM:SS[.sss][Z|±HH:MM])");
550 int year = std::stoi(match[1].str());
551 int month = std::stoi(match[2].str());
552 int day = std::stoi(match[3].str());
553 int hour = std::stoi(match[4].str());
554 int min = std::stoi(match[5].str());
555 double sec = std::stod(match[6].str());
558 if (match[7].matched) {
559 sec += std::stod(match[7].str());
563 if (match[8].matched && match[8].str() !=
"Z") {
565 int tz_sign = (match[9].str() ==
"-") ? -1 : 1;
566 int tz_hours = std::stoi(match[10].str());
567 int tz_minutes = std::stoi(match[11].str());
568 int offset_minutes = tz_sign * (tz_hours * 60 + tz_minutes);
572 int total_minutes = hour * 60 + min - offset_minutes;
575 while (total_minutes < 0) {
576 total_minutes += 24 * 60;
579 while (total_minutes >= 24 * 60) {
580 total_minutes -= 24 * 60;
584 hour = total_minutes / 60;
585 min = total_minutes % 60;
588 auto days_in_month = [](
int y,
int m) ->
int {
589 static constexpr int days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
591 bool leap = (y % 4 == 0 && y % 100 != 0) || (y % 400 == 0);
592 return leap ? 29 : 28;
603 day += days_in_month(year, month);
605 while (day > days_in_month(year, month)) {
606 day -= days_in_month(year, month);
616 epoch_start_ = vulcan::time::NumericEpoch::from_utc(year, month, day, hour, min, sec);
617 }
else if (config_.epoch.system ==
"TAI" && config_.epoch.jd > 0.0) {
618 epoch_start_ = vulcan::time::NumericEpoch::from_jd_tai(config_.epoch.jd);
619 }
else if (config_.epoch.system ==
"GPS" && config_.epoch.gps_configured) {
620 epoch_start_ = vulcan::time::NumericEpoch::from_gps_week(config_.epoch.gps_week,
621 config_.epoch.gps_seconds);
624 epoch_start_ = vulcan::time::NumericEpoch();
628 epoch_ = epoch_start_;
635 if (!config_.logging.file_path.empty() && config_.logging.file_enabled) {
636 logger_.SetLogFile(config_.logging.file_path);
638 logger_.SetConsoleLevel(config_.logging.console_level);
639 logger_.SetFileLevel(config_.logging.file_level);
640 logger_.SetProgressEnabled(config_.logging.progress_enabled);
641 logger_.SetProfilingEnabled(config_.logging.profiling_enabled);
642 logger_.SetVersion(config_.version);
645 integration_manager_.Configure(config_.integrator.type);
649 auto timing_errors = config_.scheduler.ValidateGlobalTiming(sim_rate);
650 if (!timing_errors.empty()) {
651 throw ConfigError(
"Scheduler timing validation failed: " + timing_errors[0]);
653 scheduler_.Configure(config_.scheduler, sim_rate);
656 if (!config_.phases.definitions.empty()) {
657 phase_manager_.Configure(config_.phases);
665 components_.push_back(std::move(component));
670 auto component = factory.Create(config);
671 components_.push_back(std::move(component));
675 for (
const auto &route : routes) {
676 router_.AddRoute(route);
680inline void Simulator::Provision() {
686 for (
auto &comp : components_) {
687 backplane_.
set_context(comp->Entity(), comp->Name());
691 comp->Provision(backplane_);
692 }
catch (
const Error &e) {
693 backplane_.clear_context();
697 comp->MarkProvisioned();
699 outputs_[comp.get()] = backplane_.registered_outputs();
700 backplane_.clear_context();
707 AllocateAndBindState();
712inline void Simulator::ApplyRouting() { router_.ApplyRoutes(backplane_); }
714inline void Simulator::AllocateAndBindState() {
716 state_manager_.DiscoverStates(registry_);
719inline void Simulator::ApplyInitialConditions() {
724inline void Simulator::ValidateWiring() {
725 auto unwired = registry_.get_unwired_inputs();
726 if (!unwired.empty()) {
728 for (
const auto &name : unwired) {
732 if (msg.size() >= 2) {
733 msg.resize(msg.size() - 2);
736 if (config_.staging.validate_wiring) {
737 throw WiringError(
"Unwired inputs: " + msg);
740 logger_.Log(
LogLevel::Warning,
"[WIRE] Unwired inputs (defaulting to 0): " + msg);
761 logger_.Log(
LogLevel::Debug,
"[TOPO] Computing execution order from signal dependencies");
765 config_, config_.scheduler.topology.cycle_detection);
767 if (result.has_cycles) {
769 for (
const auto &cycle : result.cycles) {
778 scheduler_.Configure(config_.scheduler, config_.scheduler.MaxRate());
783 for (
size_t i = 0; i < result.execution_order.size(); ++i) {
784 s += result.execution_order[i];
785 if (i < result.execution_order.size() - 1)
793 for (
const auto &route : router_.GetRoutes()) {
794 std::string from = route.output_path;
795 std::string to = route.input_path;
796 logger_.LogWiring(from, to);
800 scheduler_.LogExecutionOrder(&logger_);
803 backplane_.set_epoch(&epoch_);
806 for (
auto &comp : components_) {
807 backplane_.set_context(comp->Entity(), comp->Name());
808 backplane_.clear_tracking();
811 backplane_.bind_epoch_to(*comp);
814 comp->Stage(backplane_);
815 }
catch (
const Error &e) {
816 backplane_.clear_context();
822 inputs_[comp.get()] = backplane_.resolved_inputs();
823 backplane_.clear_context();
832 if (config_.staging.trim.enabled) {
836 auto result = solver->Solve(*
this, config_.staging.trim);
838 if (config_.staging.trim.tolerance > 0 && !result.converged) {
840 throw StageError(
"Trim optimization failed: " + result.message);
843 trim_result_ = std::move(result);
849 if (config_.staging.linearization.enabled) {
850 std::ostringstream oss;
851 oss <<
"[LIN] Computing linear model (" << config_.staging.linearization.states.size()
852 <<
" states, " << config_.staging.linearization.inputs.size() <<
" inputs, "
853 << config_.staging.linearization.outputs.size() <<
" outputs)";
857 auto model = linearizer->Compute(*
this, config_.staging.linearization);
860 logger_.LogLinearModel(model);
863 const auto &lin = config_.staging.linearization;
864 if (!lin.output_dir.empty()) {
865 if (lin.export_matlab) {
866 model.ExportMatlab(lin.output_dir +
"/linear_model.m");
868 "[LIN] Exported MATLAB to " + lin.output_dir +
"/linear_model.m");
870 if (lin.export_numpy) {
871 model.ExportNumPy(lin.output_dir +
"/linear_model.py");
873 "[LIN] Exported NumPy to " + lin.output_dir +
"/linear_model.py");
875 if (lin.export_json) {
876 model.ExportJSON(lin.output_dir +
"/linear_model.json");
878 "[LIN] Exported JSON to " + lin.output_dir +
"/linear_model.json");
882 linear_model_ = std::move(model);
888 if (config_.staging.symbolics.enabled) {
900 dynamics_graph_ = sym_dynamics.
dynamics;
901 if (config_.staging.symbolics.generate_jacobian) {
902 jacobian_ = sym_dynamics.jacobian_x;
907 }
catch (
const Error &e) {
909 "[SYM] Symbolic generation failed: " + std::string(e.what()));
911 }
catch (
const std::exception &e) {
913 "[SYM] Symbolic generation failed: " + std::string(e.what()));
918 logger_.EndLifecycle();
921 if (config_.recording.IsActive()) {
922 recorder_ = std::make_unique<HDF5Recorder>(registry_, config_.recording);
925 std::to_string(recorder_->RecordedSignals().size()) +
926 " signals to " + config_.recording.path);
932 if (!config_.staging.trim.IsWarmstart()) {
933 epoch_ = epoch_start_;
938 config_.staging = config;
951 logger_.LogRunStart(
Time(), config_.t_end, config_.dt);
955 InvokeInputSources();
958 auto ctx = BuildFrameContext();
964 if (state_manager_.TotalSize() == 0) {
965 for (
auto &comp : components_) {
966 if (ctx.ShouldRun(comp->FullName())) {
970 for (
auto &comp : components_) {
971 if (ctx.ShouldRun(comp->FullName())) {
975 for (
auto &comp : components_) {
976 if (ctx.ShouldRun(comp->FullName())) {
982 auto deriv_func = [
this, &ctx, dt](
double t,
983 const JanusVector<double> &x) -> JanusVector<double> {
984 state_manager_.SetState(x);
985 state_manager_.ZeroDerivatives();
987 for (
auto &comp : components_) {
988 if (ctx.ShouldRun(comp->FullName())) {
995 return state_manager_.GetDerivatives(ctx.active_components);
1000 JanusVector<double> X = state_manager_.GetState();
1001 JanusVector<double> X_new = integration_manager_.Step(deriv_func, X, t, dt);
1002 state_manager_.SetState(X_new);
1003 }
catch (
const Error &e) {
1012 epoch_ = epoch_start_ + frame_count_ * dt;
1015 phase_manager_.EvaluateTransitions(registry_);
1016 if (phase_manager_.PhaseChangedThisStep()) {
1018 "[PHASE] Transition: " +
1019 phase_manager_.GetConfig().GetPhaseName(phase_manager_.PreviousPhase()) +
1020 " → " + phase_manager_.CurrentPhaseName() +
1021 " at t=" + std::to_string(
Time()) +
"s");
1025 if (logger_.IsProgressEnabled() && (frame_count_ % 100 == 0)) {
1026 logger_.LogRunProgress(
Time(), config_.t_end);
1030 InvokeOutputObservers();
1034 recorder_->Record(
Time());
1045 epoch_ = epoch_start_;
1049 if (state_manager_.TotalSize() > 0) {
1050 JanusVector<double> zero =
1051 JanusVector<double>::Zero(
static_cast<Eigen::Index
>(state_manager_.TotalSize()));
1052 state_manager_.SetState(zero);
1056 for (
auto &comp : components_) {
1057 backplane_.set_context(comp->Entity(), comp->Name());
1058 backplane_.clear_tracking();
1060 comp->Stage(backplane_);
1061 }
catch (
const Error &e) {
1062 backplane_.clear_context();
1063 LogError(e, 0.0, comp->FullName());
1066 inputs_[comp.get()] = backplane_.resolved_inputs();
1067 backplane_.clear_context();
1074 epoch_ = epoch_start_ + met;
1076 frame_count_ =
static_cast<int>(met / config_.dt);
1081 input_sources_[signal_name] = std::move(callback);
1086 output_observers_[signal_name] = std::move(callback);
1090 input_sources_.erase(signal_name);
1094 output_observers_.erase(signal_name);
1102 state_manager_.ZeroDerivatives();
1104 double dt = config_.dt;
1105 auto ctx = BuildFrameContext();
1107 for (
auto &comp : components_) {
1108 if (ctx.ShouldRun(comp->FullName())) {
1112 for (
auto &comp : components_) {
1113 if (ctx.ShouldRun(comp->FullName())) {
1117 for (
auto &comp : components_) {
1118 if (ctx.ShouldRun(comp->FullName())) {
1123 return state_manager_.GetDerivatives(ctx.active_components);
1135 logger_.LogRunStart(
Time(), config_.t_end, config_.dt);
1139 InvokeInputSources();
1142 auto ctx = BuildFrameContext();
1148 auto deriv_func = [
this, &ctx,
1149 dt_request](
double t,
const JanusVector<double> &x) -> JanusVector<double> {
1150 state_manager_.SetState(x);
1151 state_manager_.ZeroDerivatives();
1153 for (
auto &comp : components_) {
1154 if (ctx.ShouldRun(comp->FullName())) {
1161 return state_manager_.GetDerivatives(ctx.active_components);
1164 JanusVector<double> X = state_manager_.GetState();
1167 result = integration_manager_.AdaptiveStep(deriv_func, X, t, dt_request);
1168 }
catch (
const Error &e) {
1174 state_manager_.SetState(result.
state);
1179 InvokeOutputObservers();
1186 return dynamics_graph_;
1194 for (
const auto &comp : components_) {
1196 entry.
name = comp->FullName();
1197 entry.
type = comp->TypeName();
1198 entry.
outputs = registry_.get_outputs_for_component(comp->FullName());
1199 entry.
inputs = registry_.get_inputs_for_component(comp->FullName());
1200 entry.
parameters = registry_.get_params_for_component(comp->FullName());
1201 entry.
config = registry_.get_config_for_component(comp->FullName());
1214 for (
const auto &route : router_.GetRoutes()) {
1222 for (
const auto &comp : components_) {
1223 auto it = inputs_.find(comp.get());
1224 if (it != inputs_.end()) {
1225 for (
const auto &resolved_signal : it->second) {
1234inline void Simulator::InvokeInputSources() {
1235 for (
const auto &[name, callback] : input_sources_) {
1236 double value = callback(name);
1241inline void Simulator::InvokeOutputObservers() {
1242 for (
const auto &[name, callback] : output_observers_) {
1243 double value = registry_.GetByName(name);
1244 callback(name, value);
1248inline Simulator::FrameContext Simulator::BuildFrameContext()
const {
1252 int32_t current_phase = phase_manager_.CurrentPhase();
1253 auto active_groups = scheduler_.GetGroupsForFrame(frame_count_, current_phase);
1256 for (
const auto &group_name : active_groups) {
1257 for (
const auto &comp_name : scheduler_.GetMembersForGroup(group_name)) {
1258 ctx.active_components.insert(comp_name);
1263 for (
const auto &group : scheduler_.GetGroups()) {
1264 for (
const auto &member : group.members) {
1265 ctx.all_scheduled_components.insert(member.component);
1276 logger_.BeginComponentTiming(comp.Name());
1277 (comp.*method)(t, dt);
1278 logger_.EndComponentTiming();
1279 }
catch (
const Error &e) {
1280 logger_.EndComponentTiming();
Component-facing facade for signal registration and resolution.
Configuration container for components with typed accessors.
Factory for creating components from configuration.
Base class for all simulation components.
Core type definitions, concepts, and configuration for Icarus.
Complete catalog of simulation interface.
Integration between Error types and LogService.
HDF5 recorder wrapping Vulcan's telemetry system.
Manages integrator lifecycle and stepping.
Full topology graph for block diagram visualization.
Linearization of dynamics around operating point.
Flight Recorder style logging service.
Flight phase transition management.
Signal Registry (Backplane) for Icarus.
Group-based execution scheduler for components.
Centralized signal routing configuration.
Loads complete simulation configuration from YAML.
Simulator and subsystem configuration structs.
Core types for staging subsystem (trim, linearization, symbolic).
Manages state integration via unified signal model.
Symbolic graph generation during Stage().
Dependency graph analysis and topological sorting for component scheduling.
Trim/initialization solvers for state setup during Stage().
Component-facing facade for signal registration and resolution.
Definition Backplane.hpp:32
void set_context(const std::string &entity, const std::string &component)
Set current component context.
Definition Backplane.hpp:45
void clear_tracking()
Clear tracking for next component.
Definition Backplane.hpp:480
static ComponentFactory & Instance()
Get singleton instance.
Definition ComponentFactory.hpp:109
Base class for all simulation components.
Definition Component.hpp:47
virtual void PostStep(Scalar, Scalar)
Called after all component Steps (for post-processing).
Definition Component.hpp:97
virtual void Step(Scalar t, Scalar dt)=0
Step phase - called every time step (hot path!).
virtual void PreStep(Scalar, Scalar)
Called before any component Steps (for pre-processing).
Definition Component.hpp:92
Configuration/parsing errors with optional file context.
Definition Error.hpp:185
Base class for all Icarus exceptions.
Definition Error.hpp:52
Manages integrator lifecycle and stepping.
Definition IntegrationManager.hpp:40
Lifecycle ordering/state errors.
Definition Error.hpp:236
Mission Logger - Flight Recorder style logging.
Definition MissionLogger.hpp:53
Manages flight phase transitions.
Definition PhaseManager.hpp:100
Group-based execution scheduler.
Definition Scheduler.hpp:35
Central registry for all simulation signals.
Definition Registry.hpp:37
void SetByName(const std::string &name, const Scalar &value)
Set signal value by name (slow path, for initialization).
Definition Registry.hpp:445
Simulator & operator=(Simulator &&)=delete
Lifecycle GetLifecycle() const
Get current simulation lifecycle state.
Definition Simulator.hpp:170
const std::optional< staging::LinearModel > & GetLinearModel() const
Get linear model Available after Stage() if linearization.enabled = true.
Definition Simulator.hpp:293
void ClearOutputObserver(const std::string &signal_name)
Remove an output observer.
Definition Simulator.hpp:1093
double Peek(const std::string &name) const
Read a signal value by name.
Definition Simulator.hpp:190
void AddComponent(std::unique_ptr< Component< double > > component)
Add a component to the simulation.
Definition Simulator.hpp:664
std::string ISO8601() const
Get current time as ISO 8601 string.
Definition Simulator.hpp:167
const std::string & Name() const
Get simulation name (from config).
Definition Simulator.hpp:134
bool IsInitialized() const
Check if simulation is initialized (Staged or later).
Definition Simulator.hpp:181
Eigen::VectorXd GetState() const
Get current state vector.
Definition Simulator.hpp:1097
void Configure(const SimulatorConfig &config)
Configure simulator with full config struct.
Definition Simulator.hpp:631
const SimulatorConfig & GetConfig() const
Get simulator configuration.
Definition Simulator.hpp:300
void ClearInputSource(const std::string &signal_name)
Remove an input source.
Definition Simulator.hpp:1089
~Simulator()
Destructor.
Definition Simulator.hpp:449
double Dt() const
Get configured timestep.
Definition Simulator.hpp:137
void Poke(const std::string &name, double value)
Write a signal value by name.
Definition Simulator.hpp:211
double EndTime() const
Get configured end time.
Definition Simulator.hpp:140
const std::optional< staging::TrimResult > & GetTrimResult() const
Get trim result Available after Stage() if trim.enabled = true.
Definition Simulator.hpp:285
double GPSSecondsOfWeek() const
Get GPS seconds of week.
Definition Simulator.hpp:164
void AddRoutes(const std::vector< signal::SignalRoute > &routes)
Add signal routes.
Definition Simulator.hpp:674
Simulator(Simulator &&)=delete
Eigen::VectorXd ComputeDerivatives(double t)
Compute derivatives for current state at time t.
Definition Simulator.hpp:1101
int GPSWeek() const
Get GPS week number.
Definition Simulator.hpp:161
AdaptiveStepResult< double > AdaptiveStep(double dt_request)
Execute adaptive step (requires RK45 integrator).
Definition Simulator.hpp:1126
void SetState(const Eigen::VectorXd &X)
Set state vector.
Definition Simulator.hpp:1099
IntrospectionGraph GetIntrospectionGraph() const
Get introspection graph (data dictionary + topology edges).
Definition Simulator.hpp:1209
double JD_TAI() const
Get Julian Date in TAI scale.
Definition Simulator.hpp:152
void SetOutputObserver(const std::string &signal_name, OutputObserverCallback callback)
Register an output observer for a signal.
Definition Simulator.hpp:1084
std::optional< janus::Function > GetJacobian() const
Get symbolic Jacobian Available after Stage() if symbolics.generate_jacobian = true.
Definition Simulator.hpp:1189
MissionLogger & GetLogger()
Get the mission logger.
Definition Simulator.hpp:216
double JD_GPS() const
Get Julian Date in GPS scale.
Definition Simulator.hpp:158
std::function< double(const std::string &)> InputSourceCallback
Input source callback: (signal_name) -> value.
Definition Simulator.hpp:236
Simulator & operator=(const Simulator &)=delete
void Reset()
Reset simulation to initial state Re-applies ICs, resets time to 0.
Definition Simulator.hpp:1040
std::size_t NumComponents() const
Get number of components.
Definition Simulator.hpp:319
std::function< void(const std::string &, double)> OutputObserverCallback
Output observer callback: (signal_name, value) -> void.
Definition Simulator.hpp:239
void SetTime(double met)
Set simulation time (MET).
Definition Simulator.hpp:1073
void Stage()
Stage the simulation.
Definition Simulator.hpp:744
std::optional< janus::Function > GetDynamicsGraph() const
Get symbolic dynamics graph Available after Stage() if symbolics.enabled = true.
Definition Simulator.hpp:1185
double Time() const
Get current simulation time (MET - derived from epoch).
Definition Simulator.hpp:143
static std::unique_ptr< Simulator > FromConfig(const std::string &config_path)
Create simulator from configuration file.
Definition Simulator.hpp:469
double JD_UTC() const
Get Julian Date in UTC scale.
Definition Simulator.hpp:149
double JD_TT() const
Get Julian Date in TT scale.
Definition Simulator.hpp:155
void Step()
Definition Simulator.hpp:1038
Simulator(const Simulator &)=delete
const MissionLogger & GetLogger() const
Definition Simulator.hpp:217
void SetInputSource(const std::string &signal_name, InputSourceCallback callback)
Register an external input source for a signal.
Definition Simulator.hpp:1079
const SignalRegistry< double > & Registry() const
Get signal registry (for recording, introspection).
Definition Simulator.hpp:199
const vulcan::time::NumericEpoch & Epoch() const
Get current epoch (single source of truth for time).
Definition Simulator.hpp:146
Backplane< double > & GetBackplane()
Get backplane for signal introspection (expert).
Definition Simulator.hpp:322
const Backplane< double > & GetBackplane() const
Definition Simulator.hpp:323
std::string GetFlightPhaseName() const
Get current flight phase name (from PhaseManager).
Definition Simulator.hpp:176
int32_t GetFlightPhase() const
Get current flight phase value (from PhaseManager).
Definition Simulator.hpp:173
DataDictionary GetDataDictionary() const
Get data dictionary for the simulation.
Definition Simulator.hpp:1191
Simulator()
Default constructor for programmatic setup.
Definition Simulator.hpp:467
Manages state integration via signal discovery.
Definition StateManager.hpp:55
static TopologyResult ComputeExecutionOrder(const SimulatorConfig &config, TopologyConfig::CycleHandling cycle_handling=TopologyConfig::CycleHandling::Error)
Compute execution order from configuration.
Definition TopologyAnalyzer.hpp:368
static void ApplyTopologyOrder(SchedulerConfig &config, const TopologyResult &result)
Merge topology order into existing scheduler config.
Definition TopologyAnalyzer.hpp:445
static SimulatorConfig Load(const std::string &path)
Load complete simulation config from file.
Definition SimulationLoader.hpp:60
Centralized signal routing configuration.
Definition SignalRouter.hpp:103
Abstract linearizer interface.
Definition Linearizer.hpp:46
Lightweight symbolic simulator for graph extraction.
Definition SymbolicSimulatorCore.hpp:48
std::size_t GetStateSize() const
Get total state size.
Definition SymbolicSimulatorCore.hpp:149
Symbolic graph generator.
Definition SymbolicStager.hpp:50
SymbolicDynamics GenerateDynamics(const SymbolicStagerConfig &config={})
Generate symbolic dynamics representation.
Definition SymbolicStager.hpp:69
Abstract trim solver interface.
Definition TrimSolver.hpp:52
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 * Shutdown
Definition MissionLogger.hpp:44
Definition Simulator.hpp:53
std::unique_ptr< Linearizer > CreateLinearizer(bool symbolic_enabled)
Create appropriate linearizer based on configuration.
Definition Linearizer.hpp:114
std::unique_ptr< TrimSolver > CreateTrimSolver(const TrimConfig &config, bool symbolic_enabled)
Create appropriate trim solver based on configuration.
Definition TrimSolver.hpp:184
Definition AggregationTypes.hpp:13
@ Step
Definition Error.hpp:231
@ Reset
Definition Error.hpp:231
@ Stage
Definition Error.hpp:231
@ Provision
Definition Error.hpp:231
@ Automatic
Topological sort from signal dependencies (Future TODO).
Definition SimulatorConfig.hpp:292
Lifecycle
Simulation lifecycle phases.
Definition CoreTypes.hpp:98
@ Provisioned
After Provision, before Stage.
Definition CoreTypes.hpp:100
@ Staged
After Stage, ready to run.
Definition CoreTypes.hpp:101
@ Running
During Step loop.
Definition CoreTypes.hpp:102
@ Error
Error state.
Definition CoreTypes.hpp:105
@ Uninitialized
Before Provision.
Definition CoreTypes.hpp:99
@ Resolve
Implicit dependency via Backplane::resolve() (source binding).
Definition IntrospectionGraph.hpp:31
@ Route
Explicit SignalRouter connection (input_path <- output_path).
Definition IntrospectionGraph.hpp:30
void LogError(const Error &error, double time=0.0, const std::string &component="")
Log an error to the global LogService.
Definition ErrorLogging.hpp:36
@ Warning
Potential issues.
Definition Console.hpp:40
@ Info
Normal operation.
Definition Console.hpp:38
@ Debug
Debugging info.
Definition Console.hpp:37
Result from adaptive step integrators.
Definition Integrator.hpp:26
JanusVector< Scalar > state
New state at t + dt_actual.
Definition Integrator.hpp:27
bool accepted
Whether step was accepted.
Definition Integrator.hpp:30
Scalar dt_actual
Actual step taken (may differ from requested).
Definition Integrator.hpp:28
Configuration container for components.
Definition ComponentConfig.hpp:37
Entry for a single component.
Definition DataDictionary.hpp:49
std::string name
Full component name (e.g., "X15.MainEngine").
Definition DataDictionary.hpp:50
std::vector< SignalDescriptor > outputs
Output signals.
Definition DataDictionary.hpp:53
std::vector< SignalDescriptor > config
Discrete config (not optimizable).
Definition DataDictionary.hpp:56
std::vector< SignalDescriptor > parameters
Scalar parameters (optimizable).
Definition DataDictionary.hpp:55
std::vector< SignalDescriptor > inputs
Input ports.
Definition DataDictionary.hpp:54
std::string type
Component type (e.g., "JetEngine").
Definition DataDictionary.hpp:51
Complete catalog of simulation interface.
Definition DataDictionary.hpp:45
void ComputeStats()
Compute summary statistics from components.
Definition DataDictionary.hpp:156
std::vector< ComponentEntry > components
All registered components.
Definition DataDictionary.hpp:60
std::string reference
Definition SimulatorConfig.hpp:65
std::string system
Time system: "MET" (default), "UTC", "TAI", "GPS".
Definition SimulatorConfig.hpp:61
IntegratorType type
Method to use.
Definition IntegratorTypes.hpp:84
Complete introspection graph: nodes (components) + typed edges.
Definition IntrospectionGraph.hpp:69
DataDictionary dictionary
The existing data dictionary (component nodes with signal lists).
Definition IntrospectionGraph.hpp:71
std::vector< IntrospectionEdge > edges
All topology edges (routes + resolves).
Definition IntrospectionGraph.hpp:74
double MaxRate() const
Get maximum rate across all groups.
Definition SimulatorConfig.hpp:367
Complete simulation configuration.
Definition SimulatorConfig.hpp:673
double t_end
Definition SimulatorConfig.hpp:686
std::string version
Definition SimulatorConfig.hpp:678
EpochConfig epoch
Definition SimulatorConfig.hpp:691
std::string name
Definition SimulatorConfig.hpp:677
SchedulerConfig scheduler
Definition SimulatorConfig.hpp:706
double t_start
Definition SimulatorConfig.hpp:685
std::vector< signal::SignalRoute > routes
Definition SimulatorConfig.hpp:701
double dt
Note: may be auto-derived from scheduler.
Definition SimulatorConfig.hpp:687
PhaseConfig phases
Definition SimulatorConfig.hpp:716
std::string description
Definition SimulatorConfig.hpp:679
std::vector< ComponentConfig > components
Definition SimulatorConfig.hpp:696
IntegratorConfig< double > integrator
Definition SimulatorConfig.hpp:721
Staging configuration.
Definition SimulatorConfig.hpp:261
std::optional< janus::Function > dynamics
f(t, x) -> xdot
Definition StagingTypes.hpp:55
Configuration for symbolic graph generation.
Definition SymbolicStager.hpp:30
bool generate_dynamics
Generate dynamics function f(t, x) -> xdot.
Definition SymbolicStager.hpp:31
bool include_time
Include time as explicit input.
Definition SymbolicStager.hpp:36
bool generate_jacobian
Generate state Jacobian df/dx.
Definition SymbolicStager.hpp:32