fix(v7): align live host-DSP units with replay path
Use WaveformConfig for live range/velocity conversion in RadarDataWorker and add headless AST-based regression checks in test_v7.py. Before: RadarDataWorker._run_host_dsp used RadarSettings.velocity_resolution (default 1.0 in models.py:113), while ReplayWorker used WaveformConfig (~5.343 m/s/bin). Live GUI under-reported velocity by factor ~5.34x. Fix: local WaveformConfig() in _run_host_dsp, mirroring ReplayWorker pattern. Doppler center derived from frame shape, matching processing.py:520. Test: TestLiveReplayPhysicalUnitsParity in test_v7.py uses ast.parse on workers.py (no v7.workers import, headless-CI-safe despite PyQt6 dep) and asserts AST Call/Attribute/BinOp nodes for both RadarDataWorker and ReplayWorker paths.
This commit is contained in:
@@ -23,7 +23,7 @@ import numpy as np
|
||||
|
||||
from PyQt6.QtCore import QThread, QObject, QTimer, pyqtSignal
|
||||
|
||||
from .models import RadarTarget, GPSData, RadarSettings
|
||||
from .models import RadarTarget, GPSData, RadarSettings, WaveformConfig
|
||||
from .hardware import (
|
||||
RadarAcquisition,
|
||||
RadarFrame,
|
||||
@@ -169,8 +169,8 @@ class RadarDataWorker(QThread):
|
||||
The FPGA already does: FFT, MTI, CFAR, DC notch.
|
||||
Host-side DSP adds: clustering, tracking, geo-coordinate mapping.
|
||||
|
||||
Bin-to-physical conversion uses RadarSettings.range_resolution
|
||||
and velocity_resolution (should be calibrated to actual waveform).
|
||||
Bin-to-physical conversion uses WaveformConfig defaults to keep
|
||||
live and replay units aligned (same source of truth as ReplayWorker).
|
||||
"""
|
||||
targets: list[RadarTarget] = []
|
||||
|
||||
@@ -180,8 +180,11 @@ class RadarDataWorker(QThread):
|
||||
|
||||
# Extract detections from FPGA CFAR flags
|
||||
det_indices = np.argwhere(frame.detections > 0)
|
||||
r_res = self._settings.range_resolution
|
||||
v_res = self._settings.velocity_resolution
|
||||
wf = WaveformConfig()
|
||||
r_res = wf.range_resolution_m
|
||||
v_res = wf.velocity_resolution_mps
|
||||
n_doppler = frame.detections.shape[1] if frame.detections.ndim == 2 else 32
|
||||
doppler_center = n_doppler // 2
|
||||
|
||||
for idx in det_indices:
|
||||
rbin, dbin = idx
|
||||
@@ -190,8 +193,9 @@ class RadarDataWorker(QThread):
|
||||
|
||||
# Convert bin indices to physical units
|
||||
range_m = float(rbin) * r_res
|
||||
# Doppler: centre bin (16) = 0 m/s; positive bins = approaching
|
||||
velocity_ms = float(dbin - 16) * v_res
|
||||
# Doppler: centre bin = 0 m/s; positive bins = approaching.
|
||||
# Derived from frame shape — mirrors processing.py:520.
|
||||
velocity_ms = float(dbin - doppler_center) * v_res
|
||||
|
||||
# Apply pitch correction if GPS data available
|
||||
raw_elev = 0.0 # FPGA doesn't send elevation per-detection
|
||||
|
||||
Reference in New Issue
Block a user