Update GPR and SAR3D processing

This commit is contained in:
Ayzen
2026-10-08 16:24:01 +03:00
parent 390015ec39
commit 3575ca68f5
67 changed files with 1187 additions and 2581 deletions
@@ -21,8 +21,6 @@ class ProcessingLiveConfig:
bscan_gain: float = 1.0
bscan_start_freq_mhz: float = 100.0
bscan_stop_freq_mhz: float = 8800.0
legacy_gpr_mode: str = "point"
relative_permittivity: float | None = None
tx_geometry: list[dict] | None = None
rx_geometry: list[dict] | None = None
gpr_input_positions: list[int] | None = None
@@ -30,7 +28,6 @@ class ProcessingLiveConfig:
gpr_min_depth_m: float = 2.0
gpr_max_depth_m: float = 14.0
gpr_range_comp_power: float = 0.1
gpr_comp_power: float = 0.2
gpr_object_min_frac: float = 0.7
gpr_score_mode: str = "combined"
# Backprojection intra-sweep speed-correction mode: "int_minus" (full
@@ -41,28 +38,14 @@ class ProcessingLiveConfig:
gpr_object_approach_min_frames: int = 3
gpr_speed_m_s: float = 0.0
gpr_look_angle_deg: float = 0.0
# Motion-model knobs for the legacy GPR pipeline. `direction_sign` flips
# which way later events appear deeper (+1) vs shallower (-1) along Z.
# `apply_freq_phase_correction` enables intra-sweep frequency-domain phase
# compensation that fires *before* the IFFT — needed when the radar moves
# appreciably during one sweep.
gpr_direction_sign: float = 1.0
gpr_apply_freq_phase_correction: bool = True
# Anchor for the motion model's per-event `dt_ref`: 'frame_center' (default)
# or 'first_tx_event'. Mirrors Python `MOTION_CONFIG.reference_mode`.
gpr_reference_mode: str = "frame_center"
gpr_snr_thresh: float = 4.5
gpr_snr_comp_max: float = 25.0
gpr_start_freq_mhz: float = 3000.0
gpr_stop_freq_mhz: float = 6000.0
gpr_background_subtract_enabled: bool = True
gpr_background_mean_count: int = 10
gpr_remove_sidelobe_objects_enabled: bool = True
gpr_imaging_plane_y_m: float = 0.0
# Locator filter parameter consumed by the C++ TCP locator server. Coherent BP
# objects are already finalized in the processor (no score threshold); only legacy
# GPR still thresholds, on a pair count.
legacy_gpr_min_visible_pair_count: float = 0.0
gpr_bp_ground_depth_m: float = 1.25
pair_depth_equalize: bool = True
# Visible X/Z window (metres). The locator and the desktop plot both clip
# detected objects to this window, so the socket broadcasts only what is shown.
gpr_visible_x_min_m: float = -2.0
@@ -70,7 +53,7 @@ class ProcessingLiveConfig:
gpr_visible_z_min_m: float = 0.0
gpr_visible_z_max_m: float = 14.0
# 3D SAR (sar3d processor) parameters, named after the reference notebook
# Multi_antenna_3D_clean_v1.ipynb (SAR_FRAME_RADIUS, BP_GROUND_DEPTH_M, ...).
# Multi_antenna_demonstrate_depthnorm.ipynb (SAR_FRAME_RADIUS, BP_GROUND_DEPTH_M, ...).
# The band, depth gate, antenna selection, speed and look angle are the
# shared gpr_* fields.
sar3d_frame_radius: int = 0
@@ -79,6 +62,10 @@ class ProcessingLiveConfig:
sar3d_comp_range_power: float = 0.3
sar3d_use_compensation: bool = True
sar3d_normalize_each_frame: bool = True
sar3d_x_size_m: float = 0.0
sar3d_y_min_m: float = -0.5
sar3d_y_max_m: float = 2.0
sar3d_z_size_m: float = 0.0
# When true, the C++ data_processor ignores socket-supplied vlc updates
# and keeps using `gpr_speed_m_s` from this file.
ignore_socket_speed: bool = False
@@ -100,7 +87,7 @@ class ProcessingLiveConfig:
def to_dict(self) -> dict[str, object]:
"""Convert live config to JSON-serializable dictionary."""
optional_geometry = {"relative_permittivity", "tx_geometry", "rx_geometry"}
optional_geometry = {"tx_geometry", "rx_geometry"}
return {
name: value for name, value in asdict(self).items()
if name not in optional_geometry or value is not None