The processor appended sweeps the GUI fed back to its own history, so its next replay
published them twice and out of order, and the B-scan came out with rotated columns.
Fed-back sweeps now stay out of that history, results are kept in timestamp order,
picking the displayed combo only redraws and only new sweeps are recorded to disk.
The sar3d processor is rewritten as a checked port of Multi_antenna_3D_clean_v1.ipynb:
NVRTC kernels, timing from the trace stamps, notebook parameter names and one cubic
SAR_VOXEL_M. It adds front, side, top and 3D views, drops gpr_cpp and the parity tools,
and the GUI speed now applies only while the socket speed is ignored.
The grid bounds are now explicit config (sar3d_x/y/z_min/max_m) instead of
being derived from the antenna span and the depth gate. The depth mask
still zeroes voxels outside [min_depth, max_depth], so the wider Z window
just shows the masked wedge. The bound fields are double: the parity tool
recomputes the notebook-derived bounds (notebook_grid_bounds) and passes
them through the live config, and a float roundtrip shifted the axes by
~1e-7 m, flipping depth-mask knife-edge voxels against the reference npz.
Parity on frames 0034-0036 unchanged (1.3e-6, axes bit-match).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Full-volume acc/cnt device buffers (~115 MB for the 9.6M-voxel grid) plus
the CUDA context did not fit next to a desktop session that had taken the
T600's 4 GB down to ~190 MB free, so every frame died with cuMemAlloc OOM
and the GUI showed no sar3d picture. The kernel now processes
[gid_begin, gid_end) ranges and the host launches it in 2M-voxel chunks
reusing one ~24 MB buffer pair. Parity vs the reference volumes is
unchanged (max diff 1.3e-6).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The old sar3d core was a port of the superseded Horns_3D notebook and
produced wrong volumes. The compute core now follows the reference
notebook exactly:
- segmented_interleaved frame timing rebuilt from per-trace capture
stamps (uniform tx_per_segment split as the no-stamps fallback), with
the coarse inter-segment dtau and the intra-sweep dtau applied as one
phase ramp before the IFFT;
- ground scene coordinates with the ground_depth_m lift (scene Y=0 is
the ground), full-region grid instead of a window around a center
depth, geo_ref compensation anchored on the ground plane, power 0.3;
- notebook finalization in C++: |acc/cnt|, depth mask, normalization
without the Y-edge planes, separable Gaussian over (Z, X), level;
- CUDA kernel computes geometry in double: float32 loses ~3e-4 of an
A-scan sample in tau and drifts ~1e-4 from the float64 reference.
Live-config keys follow: the center_depth/half_width/grid_n window knobs
are replaced by ground/voxel/y-range/margin/sigma/power/tx_per_segment.
Parity against the notebook npz exports (frames 0034-0036 of the
20260922_mine_fast_true dataset): max|diff| <= 1.6e-6 off the depth-mask
knife edge, identical argmax, level rel diff <= 7e-7. Verified via
make sar3d_parity --dump-dir + scripts/sar3d_volume_compare.py; the
executable spec lives in scripts/sar3d_reference_check.py (bit-tight
against the npz, including the animation shifted-grid arithmetic).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Verified on the bench that the modified master bitstream excites in every stage
and the RF switch routes: 16 traces per sweep, 62 dB between the two switch
positions of one master port, 9.9k measurements/s. Adds the built master image,
two run profiles, a verification script and librevna_protocol.md, and drops the
stale prototype driver copy that the firmware tree still carried.