Icarus
Vehicle Simulation as a Transformable Computational Graph, built on Vulcan and Janus
Loading...
Searching...
No Matches
DataDictionary.hpp
Go to the documentation of this file.
1#pragma once
2
10
11#include <cerrno>
12#include <cstddef>
13#include <cstring>
14#include <fstream>
15#include <icarus/core/Error.hpp>
17#include <nlohmann/json.hpp>
18#include <string>
19#include <vector>
20#include <yaml-cpp/yaml.h>
21
22namespace icarus {
23
24namespace detail {
26template <typename WriteFunc>
27inline void WriteToFile(const std::string &path, WriteFunc write_content) {
28 std::ofstream file(path);
29 if (!file.is_open()) {
30 throw IOError("open", path, "Failed to open file for writing");
31 }
32 write_content(file);
33 if (file.fail()) {
34 throw IOError("write", path, "Failed to write to file");
35 }
36}
37} // namespace detail
38
50 std::string name;
51 std::string type;
52
53 std::vector<SignalDescriptor> outputs;
54 std::vector<SignalDescriptor> inputs;
55 std::vector<SignalDescriptor> parameters;
56 std::vector<SignalDescriptor> config;
57 };
58
60 std::vector<ComponentEntry> components;
61
62 // Summary statistics
63 std::size_t total_outputs = 0;
64 std::size_t total_inputs = 0;
65 std::size_t total_parameters = 0;
66 std::size_t total_config = 0;
67 std::size_t integrable_states = 0;
68 std::size_t unwired_inputs = 0;
69
70 static void AppendSignalsToYAML(YAML::Emitter &out, const std::string &key,
71 const std::vector<SignalDescriptor> &signals) {
72 if (signals.empty()) {
73 return;
74 }
75
76 out << YAML::Key << key << YAML::Value << YAML::BeginSeq;
77 for (const auto &sig : signals) {
78 out << YAML::BeginMap;
79 out << YAML::Key << "name" << YAML::Value << sig.name;
80 out << YAML::Key << "unit" << YAML::Value << sig.unit;
81 out << YAML::Key << "description" << YAML::Value << sig.description;
82 if (!sig.wired_to.empty()) {
83 out << YAML::Key << "wired_to" << YAML::Value << sig.wired_to;
84 }
85 if (sig.is_integrable) {
86 out << YAML::Key << "is_integrable" << YAML::Value << true;
87 }
88 out << YAML::EndMap;
89 }
90 out << YAML::EndSeq;
91 }
92
93 void AppendComponentsToYAML(YAML::Emitter &out) const {
94 out << YAML::Key << "components" << YAML::Value << YAML::BeginSeq;
95 for (const auto &comp : components) {
96 out << YAML::BeginMap;
97 out << YAML::Key << "name" << YAML::Value << comp.name;
98 out << YAML::Key << "type" << YAML::Value << comp.type;
99
100 AppendSignalsToYAML(out, "outputs", comp.outputs);
101 AppendSignalsToYAML(out, "inputs", comp.inputs);
102 AppendSignalsToYAML(out, "parameters", comp.parameters);
103 AppendSignalsToYAML(out, "config", comp.config);
104
105 out << YAML::EndMap;
106 }
107 out << YAML::EndSeq;
108 }
109
110 [[nodiscard]] nlohmann::json ToJSONValue() const {
111 nlohmann::json j;
112
113 j["summary"]["total_outputs"] = total_outputs;
114 j["summary"]["total_inputs"] = total_inputs;
115 j["summary"]["total_parameters"] = total_parameters;
116 j["summary"]["total_config"] = total_config;
117 j["summary"]["integrable_states"] = integrable_states;
118 j["summary"]["unwired_inputs"] = unwired_inputs;
119
120 auto to_json_signals = [](const std::vector<SignalDescriptor> &signals) {
121 nlohmann::json arr = nlohmann::json::array();
122 for (const auto &sig : signals) {
123 nlohmann::json jsig;
124 jsig["name"] = sig.name;
125 jsig["unit"] = sig.unit;
126 jsig["description"] = sig.description;
127 if (!sig.wired_to.empty()) {
128 jsig["wired_to"] = sig.wired_to;
129 }
130 if (sig.is_integrable) {
131 jsig["is_integrable"] = true;
132 }
133 arr.push_back(jsig);
134 }
135 return arr;
136 };
137
138 j["components"] = nlohmann::json::array();
139 for (const auto &comp : components) {
140 nlohmann::json jcomp;
141 jcomp["name"] = comp.name;
142 jcomp["type"] = comp.type;
143 jcomp["outputs"] = to_json_signals(comp.outputs);
144 jcomp["inputs"] = to_json_signals(comp.inputs);
145 jcomp["parameters"] = to_json_signals(comp.parameters);
146 jcomp["config"] = to_json_signals(comp.config);
147 j["components"].push_back(jcomp);
148 }
149
150 return j;
151 }
152
157 total_outputs = 0;
158 total_inputs = 0;
160 total_config = 0;
162 unwired_inputs = 0;
163
164 for (const auto &comp : components) {
165 total_outputs += comp.outputs.size();
166 total_inputs += comp.inputs.size();
167 total_parameters += comp.parameters.size();
168 total_config += comp.config.size();
169
170 for (const auto &output : comp.outputs) {
171 if (output.is_integrable) {
173 }
174 }
175
176 for (const auto &input : comp.inputs) {
177 if (input.wired_to.empty()) {
179 }
180 }
181 }
182 }
183
188 void ToYAML(const std::string &path) const {
189 YAML::Emitter out;
190 out << YAML::BeginMap;
191
192 // Summary section
193 out << YAML::Key << "summary" << YAML::Value << YAML::BeginMap;
194 out << YAML::Key << "total_outputs" << YAML::Value << total_outputs;
195 out << YAML::Key << "total_inputs" << YAML::Value << total_inputs;
196 out << YAML::Key << "total_parameters" << YAML::Value << total_parameters;
197 out << YAML::Key << "total_config" << YAML::Value << total_config;
198 out << YAML::Key << "integrable_states" << YAML::Value << integrable_states;
199 out << YAML::Key << "unwired_inputs" << YAML::Value << unwired_inputs;
200 out << YAML::EndMap;
201
203 out << YAML::EndMap;
204
205 detail::WriteToFile(path, [&](std::ofstream &file) { file << out.c_str(); });
206 }
207
212 void ToJSON(const std::string &path) const {
213 auto j = ToJSONValue();
214
215 detail::WriteToFile(path, [&](std::ofstream &file) { file << j.dump(2); });
216 }
217};
218
219} // namespace icarus
Consolidated error handling for Icarus.
Signal types and descriptors for the Icarus Signal Backplane.
File and I/O operation errors.
Definition Error.hpp:356
Definition DataDictionary.hpp:24
void WriteToFile(const std::string &path, WriteFunc write_content)
Helper to write content to a file with error handling.
Definition DataDictionary.hpp:27
Definition AggregationTypes.hpp:13
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
static void AppendSignalsToYAML(YAML::Emitter &out, const std::string &key, const std::vector< SignalDescriptor > &signals)
Definition DataDictionary.hpp:70
void ComputeStats()
Compute summary statistics from components.
Definition DataDictionary.hpp:156
std::size_t total_parameters
Definition DataDictionary.hpp:65
void ToJSON(const std::string &path) const
Export to JSON file.
Definition DataDictionary.hpp:212
std::size_t total_inputs
Definition DataDictionary.hpp:64
std::vector< ComponentEntry > components
All registered components.
Definition DataDictionary.hpp:60
std::size_t total_outputs
Definition DataDictionary.hpp:63
void ToYAML(const std::string &path) const
Export to YAML file.
Definition DataDictionary.hpp:188
nlohmann::json ToJSONValue() const
Definition DataDictionary.hpp:110
std::size_t integrable_states
Definition DataDictionary.hpp:67
void AppendComponentsToYAML(YAML::Emitter &out) const
Definition DataDictionary.hpp:93
std::size_t total_config
Definition DataDictionary.hpp:66
std::size_t unwired_inputs
Definition DataDictionary.hpp:68