feat: relative mode keeps the stream's absolute clock for the export

This commit is contained in:
Martino Ferrari committed 2026-10-08 17:20:47 +02:00
1 parent d11e7d48c4
commit 57e2f6aa8b
6 files changed
+87 -9

No files matched your search

+28
View File
@@ -135,6 +135,7 @@ std::uint32_t Acquisition::build_stamps(const udps_frame_t* frame, int time_sign
n = std::max(n, udps_signal_num_elements(&frame->signals[i]));
}
stamps_.assign(n, 0.0);
abs_stamps_.assign(n, 0.0);
// Relative mode: the stamp is a pure function of position and the *declared* rate. Nothing
// below this block runs -- not the arrival-cadence override, not the degeneracy guard, not
@@ -168,6 +169,21 @@ std::uint32_t Acquisition::build_stamps(const udps_frame_t* frame, int time_sign
stamps_[k] = double(slot_base_ + k) * dt;
}
slot_base_ += n;
// The absolute clock is still read, for export only. When the stream carries no usable
// time signal there is no absolute clock to record and the relative stamp is the honest
// answer -- an export then says what the counter says, which is all anyone had.
if (time_signal >= 0 && time_signal < static_cast<int>(frame->num_signals)) {
const udps_signal_t& ts = frame->signals[time_signal];
const bool scalar_time = udps_signal_num_elements(&ts) == 1;
for (std::uint32_t k = 0; k < n; ++k) {
abs_stamps_[k] =
scalar_time
? udps_frame_value(frame, static_cast<std::uint32_t>(time_signal), k, 0)
: udps_frame_value(frame, static_cast<std::uint32_t>(time_signal), 0, k);
}
} else {
for (std::uint32_t k = 0; k < n; ++k) abs_stamps_[k] = stamps_[k];
}
return n;
}
@@ -413,6 +429,10 @@ std::uint32_t Acquisition::build_stamps(const udps_frame_t* frame, int time_sign
for (std::uint32_t k = 0; k < n; ++k) stamps_[k] *= unit_scale;
}
// Stream mode: `time()` already holds the absolute clock, so the parallel ring repeats it
// rather than carrying a second timeline. One rule for the export either way.
for (std::uint32_t k = 0; k < n; ++k) abs_stamps_[k] = stamps_[k];
return n;
}
@@ -476,6 +496,7 @@ void Acquisition::on_data(const udps_frame_t* frame) {
value_acc_n_.assign(channels.size(), 0);
math_sample_.assign(channels.size(), std::nanf(""));
time_acc_ = 0.0;
abs_time_acc_ = 0.0;
time_acc_n_ = 0;
}
@@ -595,10 +616,17 @@ void Acquisition::on_data(const udps_frame_t* frame) {
// boxcar's group delay puts the averaged value, and stamping it at the end of the
// group would shift every trace half a stored sample late.
time_acc_ += rel;
abs_time_acc_ += abs_stamps_[k] - epoch;
++time_acc_n_;
if (tick % g == g - 1) {
store.time().push(time_acc_ / static_cast<double>(time_acc_n_));
time_acc_ = 0.0;
// The absolute clock on the same slot and under the same group mean, so an export can
// pair value, relative stamp and absolute stamp by index with no interpolation.
if (plot::data::RingBuffer<f64>* abs = store.abs_time(); abs != nullptr) {
abs->push(abs_time_acc_ / static_cast<double>(time_acc_n_));
}
abs_time_acc_ = 0.0;
time_acc_n_ = 0;
}