Icarus
Vehicle Simulation as a Transformable Computational Graph, built on Vulcan and Janus
Loading...
Searching...
No Matches
Scheduler.hpp
Go to the documentation of this file.
1#pragma once
2
10
13
14#include <algorithm>
15#include <cstdint>
16#include <iomanip>
17#include <iostream>
18#include <sstream>
19#include <string>
20#include <vector>
21
22namespace icarus {
23
35class Scheduler {
36 public:
43 void Configure(const SchedulerConfig &config, double sim_rate_hz) {
44 config_ = config;
45 sim_rate_hz_ = sim_rate_hz;
46
47 // Sort groups by priority
48 std::sort(config_.groups.begin(), config_.groups.end(),
49 [](const SchedulerGroupConfig &a, const SchedulerGroupConfig &b) {
50 return a.priority < b.priority;
51 });
52
53 // Sort members within each group by priority
54 for (auto &group : config_.groups) {
55 std::sort(
56 group.members.begin(), group.members.end(),
57 [](const GroupMember &a, const GroupMember &b) { return a.priority < b.priority; });
58 }
59
60 // Compute frame divisors
61 config_.ComputeFrameDivisors(sim_rate_hz);
62
63 // Note: LogExecutionOrder() is called by Simulator after Configure
64 // with proper logger from config
65 }
66
74 [[nodiscard]] std::vector<std::string> GetGroupsForFrame(int frame_count,
75 int32_t current_phase = -1) const {
76 std::vector<std::string> active_groups;
77 for (const auto &group : config_.groups) {
78 // Check frame divisor
79 auto it = config_.group_frame_divisors.find(group.name);
80 if (it != config_.group_frame_divisors.end()) {
81 int divisor = it->second;
82 if (frame_count % divisor != 0) {
83 continue; // Not this frame
84 }
85 }
86
87 // Check phase gating (if phase is provided)
88 if (current_phase >= 0 && !group.IsActiveInPhase(current_phase)) {
89 continue; // Not active in this phase
90 }
91
92 active_groups.push_back(group.name);
93 }
94 return active_groups;
95 }
96
103 [[nodiscard]] std::vector<std::string> GetMembersForGroup(const std::string &group_name) const {
104 std::vector<std::string> members;
105 for (const auto &group : config_.groups) {
106 if (group.name == group_name) {
107 for (const auto &member : group.members) {
108 members.push_back(member.component);
109 }
110 break;
111 }
112 }
113 return members;
114 }
115
122 [[nodiscard]] double GetGroupDt(const std::string &group_name) const {
123 double global_dt = 1.0 / sim_rate_hz_;
124 auto it = config_.group_frame_divisors.find(group_name);
125 if (it != config_.group_frame_divisors.end()) {
126 return global_dt * it->second;
127 }
128 return global_dt;
129 }
130
137 [[nodiscard]] int GetFrameDivisor(const std::string &group_name) const {
138 auto it = config_.group_frame_divisors.find(group_name);
139 if (it != config_.group_frame_divisors.end()) {
140 return it->second;
141 }
142 return 1;
143 }
144
146 [[nodiscard]] double GetSimulationRate() const { return sim_rate_hz_; }
147
149 [[nodiscard]] const std::vector<SchedulerGroupConfig> &GetGroups() const {
150 return config_.groups;
151 }
152
154 [[nodiscard]] const SchedulerConfig &GetConfig() const { return config_; }
155
157 void LogExecutionOrder(MissionLogger *logger = nullptr) const {
158 if (logger != nullptr) {
159 // Use structured MissionLogger output
160 logger->LogSchedulerOrder(sim_rate_hz_, config_.groups, config_.group_frame_divisors);
161 } else {
162 // Fallback to stdout
163 std::ostringstream oss;
164 oss << "Scheduler execution order (sim rate: " << sim_rate_hz_ << " Hz):\n";
165
166 for (const auto &group : config_.groups) {
167 auto it = config_.group_frame_divisors.find(group.name);
168 int divisor = (it != config_.group_frame_divisors.end()) ? it->second : 1;
169 double group_dt = 1.0 / group.rate_hz;
170
171 oss << " Group '" << group.name << "' (priority " << group.priority << ", "
172 << group.rate_hz << " Hz, divisor " << divisor << ", dt=" << std::fixed
173 << std::setprecision(6) << group_dt << "s):\n";
174
175 for (const auto &member : group.members) {
176 oss << " - " << member.component << " (priority " << member.priority
177 << ")\n";
178 }
179 }
180 std::cout << oss.str();
181 }
182 }
183
185 double sim_rate_hz_ = 400.0;
186};
187
188} // namespace icarus
Flight Recorder style logging service.
Simulator and subsystem configuration structs.
Mission Logger - Flight Recorder style logging.
Definition MissionLogger.hpp:53
Group-based execution scheduler.
Definition Scheduler.hpp:35
double sim_rate_hz_
Definition Scheduler.hpp:185
int GetFrameDivisor(const std::string &group_name) const
Get frame divisor for a group.
Definition Scheduler.hpp:137
const std::vector< SchedulerGroupConfig > & GetGroups() const
Get the sorted groups (by priority).
Definition Scheduler.hpp:149
void LogExecutionOrder(MissionLogger *logger=nullptr) const
Log execution order to logger or stdout.
Definition Scheduler.hpp:157
std::vector< std::string > GetGroupsForFrame(int frame_count, int32_t current_phase=-1) const
Get groups that should execute on this frame.
Definition Scheduler.hpp:74
void Configure(const SchedulerConfig &config, double sim_rate_hz)
Configure scheduler from config.
Definition Scheduler.hpp:43
double GetGroupDt(const std::string &group_name) const
Get dt for a specific group.
Definition Scheduler.hpp:122
double GetSimulationRate() const
Get simulation rate in Hz.
Definition Scheduler.hpp:146
SchedulerConfig config_
Definition Scheduler.hpp:184
std::vector< std::string > GetMembersForGroup(const std::string &group_name) const
Get members for a group in execution order.
Definition Scheduler.hpp:103
const SchedulerConfig & GetConfig() const
Get the config.
Definition Scheduler.hpp:154
Definition AggregationTypes.hpp:13
A component member within a scheduler group.
Definition SimulatorConfig.hpp:299
Scheduler configuration with rate groups.
Definition SimulatorConfig.hpp:346
A scheduler group with its own rate and priority.
Definition SimulatorConfig.hpp:310