fix: batch_ is now learned in both stream and relative-time modes so hole reservation fires in stream mode.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Martino FerrariandClaude Sonnet 4.6 committed 2026-10-08 18:22:32 +02:00
1 parent 5915fc8421
commit 6830b97c02
1 file changed
+27 -20
+27 -20
View File
@@ -143,32 +143,39 @@ std::uint32_t Acquisition::build_stamps(const udps_frame_t* frame, int time_sign
stamps_.assign(n, 0.0); stamps_.assign(n, 0.0);
abs_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 // Samples per packet, needed in both modes: relative stamping must advance `slot_base_`
// below this block runs -- not the arrival-cadence override, not the degeneracy guard, not // past the reserved hole before placing this frame's own stamps, and `on_data` must size
// the glitch bridge, not the monotonic clamp's reason for existing -- because a position // the hole before calling this function -- both operations require knowing how many samples
// cannot jitter, cannot fail to advance and cannot jump. // a missing packet represents, which is only knowable from the first frame that arrives.
if (cfg_.relative_time) { if (batch_ == 0) {
if (batch_ == 0) { batch_ = n;
batch_ = n; if (cfg_.relative_time) {
std::fprintf(stderr, std::fprintf(stderr,
"[udpscope] relative time: batch=%u samples/packet, rate=%.6g S/s declared\n", "[udpscope] relative time: batch=%u samples/packet, rate=%.6g S/s declared\n",
batch_, model_.partition().base_dt > 0.0 ? 1.0 / model_.partition().base_dt batch_, model_.partition().base_dt > 0.0 ? 1.0 / model_.partition().base_dt
: 0.0); : 0.0);
std::fflush(stderr); std::fflush(stderr);
} else if (n != batch_) {
// A frame whose length disagrees with the first one is an inconsistency in the
// producer, not a loss: the counter still names one packet. Warn once and keep the
// established batch, which is only used to size holes -- the timeline itself is built
// from the lengths actually seen, so it stays exact for this frame either way.
if (!warned_batch_) {
warned_batch_ = true;
std::fprintf(stderr,
"[udpscope] warning: packet carries %u samples but the stream's first "
"carried %u; keeping %u as the packet length a lost packet is worth.\n",
n, batch_, batch_);
std::fflush(stderr);
}
} }
} else if (n != batch_) {
// A frame whose length disagrees with the first one is an inconsistency in the
// producer, not a loss: the counter still names one packet. Warn once and keep the
// established batch, which is only used to size holes -- the timeline itself is built
// from the lengths actually seen, so it stays exact for this frame either way.
if (!warned_batch_) {
warned_batch_ = true;
std::fprintf(stderr,
"[udpscope] warning: packet carries %u samples but the stream's first "
"carried %u; keeping %u as the packet length a lost packet is worth.\n",
n, batch_, batch_);
std::fflush(stderr);
}
}
// 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
// the glitch bridge, not the monotonic clamp's reason for existing -- because a position
// cannot jitter, cannot fail to advance and cannot jump.
if (cfg_.relative_time) {
double dt = model_.partition().base_dt; double dt = model_.partition().base_dt;
if (!(dt > 0.0)) dt = 1.0e-3; if (!(dt > 0.0)) dt = 1.0e-3;
// The reserved hole for the missing packets advances `slot_base_` so this frame's // The reserved hole for the missing packets advances `slot_base_` so this frame's