21#include <vulcan/io/CSVExport.hpp>
22#include <vulcan/io/Frame.hpp>
23#include <vulcan/io/HDF5Reader.hpp>
24#include <vulcan/io/HDF5Writer.hpp>
25#include <vulcan/io/TelemetrySchema.hpp>
30struct HDF5RecorderConfig;
64 : registry_(registry), config_(config) {}
70 void Open(
const std::string &path)
override {
75 writer_ = std::make_unique<vulcan::io::HDF5Writer>(config_.path, schema_);
76 frame_ = std::make_unique<vulcan::io::Frame>(schema_);
88 throw std::runtime_error(
"Recorder not open");
93 if (config_.decimation > 1 && (frame_counter_ % config_.decimation) != 1) {
97 frame_->set_time(time);
99 writer_->write_frame(*frame_);
113 if (config_.export_csv) {
122 [[nodiscard]]
size_t FrameCount()
const {
return writer_ ? writer_->frame_count() : 0; }
136 [[nodiscard]]
const vulcan::io::TelemetrySchema &
Schema()
const {
return schema_; }
142 return recorded_signals_;
148 vulcan::io::TelemetrySchema schema_;
149 std::unique_ptr<vulcan::io::HDF5Writer> writer_;
150 std::unique_ptr<vulcan::io::Frame> frame_;
151 std::vector<std::string> recorded_signals_;
152 size_t frame_counter_ = 0;
158 schema_ = vulcan::io::TelemetrySchema();
159 recorded_signals_.clear();
162 std::vector<std::regex> include_re, exclude_re;
163 if (config_.
mode ==
"signals" && !config_.
include.empty()) {
164 for (
const auto &pat : config_.
include) {
165 include_re.emplace_back(pat);
168 for (
const auto &pat : config_.exclude) {
169 exclude_re.emplace_back(pat);
173 for (
const auto &desc : registry_.GetDescriptors()) {
175 if (!config_.include_derivatives && desc.name.find(
"_dot") != std::string::npos) {
180 bool should_include =
false;
182 if (config_.mode ==
"all") {
185 should_include = config_.include_inputs;
187 should_include =
true;
189 }
else if (config_.mode ==
"outputs") {
193 }
else if (config_.mode ==
"signals") {
195 if (include_re.empty()) {
196 should_include =
true;
198 for (
const auto &re : include_re) {
199 if (std::regex_search(desc.name, re)) {
200 should_include =
true;
207 if (!should_include) {
212 bool excluded =
false;
213 for (
const auto &re : exclude_re) {
214 if (std::regex_search(desc.name, re)) {
225 case SignalType::Double:
226 schema_.add_double(desc.name, desc.lifecycle, desc.unit);
228 case SignalType::Int32:
229 schema_.add_int32(desc.name, desc.lifecycle, desc.semantic);
231 case SignalType::Int64:
232 schema_.add_int64(desc.name, desc.lifecycle);
236 recorded_signals_.push_back(desc.name);
243 void CaptureSignals() {
244 for (
const auto &name : recorded_signals_) {
245 const auto *desc = registry_.get_descriptor(name);
246 if (!desc || !desc->data_ptr) {
250 switch (desc->type) {
251 case SignalType::Double:
252 frame_->set(name, *
static_cast<const double *
>(desc->data_ptr));
254 case SignalType::Int32:
255 frame_->set(name, *
static_cast<const int32_t *
>(desc->data_ptr));
257 case SignalType::Int64:
258 frame_->set(name, *
static_cast<const int64_t *
>(desc->data_ptr));
272 std::string csv_path = config_.path;
273 auto dot_pos = csv_path.rfind(
'.');
274 if (dot_pos != std::string::npos) {
275 csv_path = csv_path.substr(0, dot_pos) +
".csv";
281 vulcan::io::CSVExportOptions options;
282 options.signals = recorded_signals_;
283 vulcan::io::export_to_csv(config_.path, csv_path, options);
Signal Registry (Backplane) for Icarus.
Simulator and subsystem configuration structs.
void Flush()
Flush buffered data to disk.
Definition HDF5Recorder.hpp:127
HDF5Recorder(const SignalRegistry< double > ®istry, const RecordingConfig &config)
Construct recorder from RecordingConfig.
Definition HDF5Recorder.hpp:63
void Record(double time) override
Record current signal values as a frame.
Definition HDF5Recorder.hpp:86
void Close() override
Close recording file.
Definition HDF5Recorder.hpp:107
size_t FrameCount() const
Get number of frames written.
Definition HDF5Recorder.hpp:122
const vulcan::io::TelemetrySchema & Schema() const
Get the generated schema.
Definition HDF5Recorder.hpp:136
const std::vector< std::string > & RecordedSignals() const
Get list of recorded signal names.
Definition HDF5Recorder.hpp:141
void Open(const std::string &path) override
Open recording file and initialize writer.
Definition HDF5Recorder.hpp:70
Simulation data recorder interface.
Definition Recorder.hpp:12
Central registry for all simulation signals.
Definition Registry.hpp:37
Definition AggregationTypes.hpp:13
@ Output
Dynamic output signal (Scalar, Vec3, etc.).
Definition Signal.hpp:77
@ Input
Input port (wired to an output).
Definition Signal.hpp:78
@ Parameter
Scalar-typed parameter (optimizable).
Definition Signal.hpp:79
HDF5 recording configuration.
Definition SimulatorConfig.hpp:503
std::vector< std::string > include
Include patterns (regex) - used when mode = "signals".
Definition SimulatorConfig.hpp:514
std::string mode
Recording mode: "off", "all", "outputs", "signals".
Definition SimulatorConfig.hpp:511