Implemented full e2e testing

This commit is contained in:
Martino Ferrari
2026-07-02 10:10:57 +02:00
parent f8c79131c9
commit f2042d624b
35 changed files with 2419 additions and 78 deletions
+32 -2
View File
@@ -166,6 +166,28 @@ def sine_shape(t, v, freq):
return corr, nrmse, amp
def best_sine_shape(t, v, freq_nominal, band=0.05, n=41):
"""Refine ``freq_nominal`` within +/-``band`` (fractional) before fitting.
The gross-sanity gate assumes the nominal configured frequency, but
MARTe2's LinuxTimer RT loop runs at a small, systematic offset from true
wall-clock time (a few percent at most), which accumulates into visible
phase drift over a multi-second capture even though every sample value is
bit-correct. A coarse search for the actual best-fit frequency near the
nominal value absorbs that clock-rate skew while still rejecting a
genuinely wrong-frequency or corrupted signal, which collapses correlation
regardless of the search window. Returns (corr, nrmse, amp, freq_used).
"""
candidates = np.linspace(freq_nominal * (1.0 - band),
freq_nominal * (1.0 + band), n)
best = None
for f in candidates:
corr, nrmse, amp = sine_shape(t, v, f)
if best is None or corr > best[0]:
best = (corr, nrmse, amp, float(f))
return best
def compare_signal(gt, t_recv, v_recv, tap_v=None):
tol, step = _tol(gt)
truth_v = gt["v"].astype(np.float64)
@@ -193,7 +215,15 @@ def compare_signal(gt, t_recv, v_recv, tap_v=None):
shape_ok = True
if gt["formula"] == "sine" and v_recv.size >= 8 and gt["freq"]:
corr, nrmse, amp = sine_shape(t_recv, v_recv, gt["freq"])
# Refine the fit frequency within +/-5% of nominal before scoring:
# MARTe2's LinuxTimer RT loop runs at a small, systematic offset from
# true wall-clock time (a few percent), which accumulates into
# visible phase drift over a multi-second capture even though every
# sample value is bit-correct (see best_sine_shape docstring). This
# keeps the gate a *gross frequency-sanity* check — a wrong-frequency
# or corrupted signal still collapses corr regardless of the search
# window — while absorbing legitimate clock-rate skew.
corr, nrmse, amp, freq_fit = best_sine_shape(t_recv, v_recv, gt["freq"])
# Shape is a *gross frequency-sanity gate* plus a *tracked quality
# metric*, not a tight correctness gate. Signal values are bit-faithful
# (the fidelity oracle proves that); the gap from a perfect fit is
@@ -208,7 +238,7 @@ def compare_signal(gt, t_recv, v_recv, tap_v=None):
nrmse_tol = 0.30 + (step / (gt["range_max"] - gt["range_min"])
if gt["quant"] != "none" else 0.0)
shape_ok = corr >= 0.5 and nrmse <= nrmse_tol
m.update(corr=corr, nrmse=nrmse, amp_fit=amp,
m.update(corr=corr, nrmse=nrmse, amp_fit=amp, freq_fit=freq_fit,
nrmse_tol=nrmse_tol, shape_ok=bool(shape_ok),
shape_gate="gross")