sar3d: fixed default scene window X [-2,2], Y [-0.5,2], Z [0,8] m
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>
This commit is contained in:
@@ -93,9 +93,12 @@ _WEB_LIVE_SCHEMA = [
|
||||
("sar3d_pitch_override_enabled", "3D SAR", ("sar3d",), _attr("_sar3d_pitch_override_enabled")),
|
||||
("sar3d_pitch_deg", "3D SAR", ("sar3d",), _attr("_sar3d_pitch_deg")),
|
||||
("sar3d_ground_depth_m", "3D SAR", ("sar3d",), _attr("_sar3d_ground_depth_m")),
|
||||
("sar3d_x_margin_m", "3D SAR", ("sar3d",), _attr("_sar3d_x_margin_m")),
|
||||
("sar3d_x_min_m", "3D SAR", ("sar3d",), _attr("_sar3d_x_min_m")),
|
||||
("sar3d_x_max_m", "3D SAR", ("sar3d",), _attr("_sar3d_x_max_m")),
|
||||
("sar3d_y_min_m", "3D SAR", ("sar3d",), _attr("_sar3d_y_min_m")),
|
||||
("sar3d_y_max_m", "3D SAR", ("sar3d",), _attr("_sar3d_y_max_m")),
|
||||
("sar3d_z_min_m", "3D SAR", ("sar3d",), _attr("_sar3d_z_min_m")),
|
||||
("sar3d_z_max_m", "3D SAR", ("sar3d",), _attr("_sar3d_z_max_m")),
|
||||
("sar3d_voxel_x_m", "3D SAR", ("sar3d",), _attr("_sar3d_voxel_x_m")),
|
||||
("sar3d_voxel_y_m", "3D SAR", ("sar3d",), _attr("_sar3d_voxel_y_m")),
|
||||
("sar3d_voxel_z_m", "3D SAR", ("sar3d",), _attr("_sar3d_voxel_z_m")),
|
||||
|
||||
@@ -353,9 +353,12 @@ class AppWindowConfigProfileIOMixin:
|
||||
self._sar3d_pitch_override_enabled,
|
||||
self._sar3d_pitch_deg,
|
||||
self._sar3d_ground_depth_m,
|
||||
self._sar3d_x_margin_m,
|
||||
self._sar3d_x_min_m,
|
||||
self._sar3d_x_max_m,
|
||||
self._sar3d_y_min_m,
|
||||
self._sar3d_y_max_m,
|
||||
self._sar3d_z_min_m,
|
||||
self._sar3d_z_max_m,
|
||||
self._sar3d_voxel_x_m,
|
||||
self._sar3d_voxel_y_m,
|
||||
self._sar3d_voxel_z_m,
|
||||
@@ -570,9 +573,12 @@ class AppWindowConfigProfileIOMixin:
|
||||
self._sar3d_pitch_override_enabled.setChecked(bool(sar3d_state.pitch_override_enabled))
|
||||
self._sar3d_pitch_deg.setValue(float(sar3d_state.pitch_deg))
|
||||
self._sar3d_ground_depth_m.setValue(float(sar3d_state.ground_depth_m))
|
||||
self._sar3d_x_margin_m.setValue(float(sar3d_state.x_margin_m))
|
||||
self._sar3d_x_min_m.setValue(float(sar3d_state.x_min_m))
|
||||
self._sar3d_x_max_m.setValue(float(sar3d_state.x_max_m))
|
||||
self._sar3d_y_min_m.setValue(float(sar3d_state.y_min_m))
|
||||
self._sar3d_y_max_m.setValue(float(sar3d_state.y_max_m))
|
||||
self._sar3d_z_min_m.setValue(float(sar3d_state.z_min_m))
|
||||
self._sar3d_z_max_m.setValue(float(sar3d_state.z_max_m))
|
||||
self._sar3d_voxel_x_m.setValue(float(sar3d_state.voxel_x_m))
|
||||
self._sar3d_voxel_y_m.setValue(float(sar3d_state.voxel_y_m))
|
||||
self._sar3d_voxel_z_m.setValue(float(sar3d_state.voxel_z_m))
|
||||
|
||||
@@ -441,9 +441,12 @@ class AppWindowConfigStateBuildersMixin:
|
||||
pitch_override_enabled=bool(self._sar3d_pitch_override_enabled.isChecked()),
|
||||
pitch_deg=float(self._sar3d_pitch_deg.value()),
|
||||
ground_depth_m=float(self._sar3d_ground_depth_m.value()),
|
||||
x_margin_m=float(self._sar3d_x_margin_m.value()),
|
||||
x_min_m=float(self._sar3d_x_min_m.value()),
|
||||
x_max_m=float(self._sar3d_x_max_m.value()),
|
||||
y_min_m=float(self._sar3d_y_min_m.value()),
|
||||
y_max_m=float(self._sar3d_y_max_m.value()),
|
||||
z_min_m=float(self._sar3d_z_min_m.value()),
|
||||
z_max_m=float(self._sar3d_z_max_m.value()),
|
||||
voxel_x_m=float(self._sar3d_voxel_x_m.value()),
|
||||
voxel_y_m=float(self._sar3d_voxel_y_m.value()),
|
||||
voxel_z_m=float(self._sar3d_voxel_z_m.value()),
|
||||
|
||||
@@ -685,12 +685,29 @@ def build_processing_group(owner) -> QGroupBox:
|
||||
"Height of the lower antenna row above the ground (m); scene Y=0 is the ground."
|
||||
)
|
||||
|
||||
owner._sar3d_x_margin_m = QDoubleSpinBox()
|
||||
owner._sar3d_x_margin_m.setDecimals(2)
|
||||
owner._sar3d_x_margin_m.setRange(0.0, 20.0)
|
||||
owner._sar3d_x_margin_m.setSingleStep(0.1)
|
||||
owner._sar3d_x_margin_m.setValue(float(sar3d_defaults.x_margin_m))
|
||||
owner._sar3d_x_margin_m.setToolTip("Grid X margin beyond the antenna span (m).")
|
||||
owner._sar3d_x_min_m = QDoubleSpinBox()
|
||||
owner._sar3d_x_min_m.setDecimals(2)
|
||||
owner._sar3d_x_min_m.setRange(-50.0, 50.0)
|
||||
owner._sar3d_x_min_m.setSingleStep(0.1)
|
||||
owner._sar3d_x_min_m.setValue(float(sar3d_defaults.x_min_m))
|
||||
|
||||
owner._sar3d_x_max_m = QDoubleSpinBox()
|
||||
owner._sar3d_x_max_m.setDecimals(2)
|
||||
owner._sar3d_x_max_m.setRange(-50.0, 50.0)
|
||||
owner._sar3d_x_max_m.setSingleStep(0.1)
|
||||
owner._sar3d_x_max_m.setValue(float(sar3d_defaults.x_max_m))
|
||||
|
||||
owner._sar3d_z_min_m = QDoubleSpinBox()
|
||||
owner._sar3d_z_min_m.setDecimals(2)
|
||||
owner._sar3d_z_min_m.setRange(-50.0, 50.0)
|
||||
owner._sar3d_z_min_m.setSingleStep(0.1)
|
||||
owner._sar3d_z_min_m.setValue(float(sar3d_defaults.z_min_m))
|
||||
|
||||
owner._sar3d_z_max_m = QDoubleSpinBox()
|
||||
owner._sar3d_z_max_m.setDecimals(2)
|
||||
owner._sar3d_z_max_m.setRange(-50.0, 50.0)
|
||||
owner._sar3d_z_max_m.setSingleStep(0.1)
|
||||
owner._sar3d_z_max_m.setValue(float(sar3d_defaults.z_max_m))
|
||||
|
||||
owner._sar3d_y_min_m = QDoubleSpinBox()
|
||||
owner._sar3d_y_min_m.setDecimals(2)
|
||||
@@ -789,9 +806,12 @@ def build_processing_group(owner) -> QGroupBox:
|
||||
owner._sar3d_pitch_override_enabled,
|
||||
("Pitch deg", owner._sar3d_pitch_deg),
|
||||
("Ground depth m", owner._sar3d_ground_depth_m),
|
||||
("X margin m", owner._sar3d_x_margin_m),
|
||||
("X min m", owner._sar3d_x_min_m),
|
||||
("X max m", owner._sar3d_x_max_m),
|
||||
("Y min m", owner._sar3d_y_min_m),
|
||||
("Y max m", owner._sar3d_y_max_m),
|
||||
("Z min m", owner._sar3d_z_min_m),
|
||||
("Z max m", owner._sar3d_z_max_m),
|
||||
("Voxel X m", owner._sar3d_voxel_x_m),
|
||||
("Voxel Y m", owner._sar3d_voxel_y_m),
|
||||
("Voxel Z m", owner._sar3d_voxel_z_m),
|
||||
@@ -895,7 +915,10 @@ def build_processing_group(owner) -> QGroupBox:
|
||||
owner._sar3d_pitch_override_enabled.toggled.connect(owner._on_processing_live_settings_changed)
|
||||
owner._sar3d_pitch_deg.valueChanged.connect(owner._on_processing_live_settings_changed)
|
||||
owner._sar3d_ground_depth_m.valueChanged.connect(owner._on_processing_live_settings_changed)
|
||||
owner._sar3d_x_margin_m.valueChanged.connect(owner._on_processing_live_settings_changed)
|
||||
owner._sar3d_x_min_m.valueChanged.connect(owner._on_processing_live_settings_changed)
|
||||
owner._sar3d_x_max_m.valueChanged.connect(owner._on_processing_live_settings_changed)
|
||||
owner._sar3d_z_min_m.valueChanged.connect(owner._on_processing_live_settings_changed)
|
||||
owner._sar3d_z_max_m.valueChanged.connect(owner._on_processing_live_settings_changed)
|
||||
owner._sar3d_y_min_m.valueChanged.connect(owner._on_processing_live_settings_changed)
|
||||
owner._sar3d_y_max_m.valueChanged.connect(owner._on_processing_live_settings_changed)
|
||||
owner._sar3d_voxel_x_m.valueChanged.connect(owner._on_processing_live_settings_changed)
|
||||
|
||||
@@ -551,10 +551,16 @@ def gui_profile_from_dict(payload: dict[str, Any]) -> GuiProfileModel:
|
||||
gui.processing.sar3d.ground_depth_m,
|
||||
"gui.processing.sar3d",
|
||||
),
|
||||
x_margin_m=_optional_float(
|
||||
x_min_m=_optional_float(
|
||||
sar3d_object,
|
||||
"x_margin_m",
|
||||
gui.processing.sar3d.x_margin_m,
|
||||
"x_min_m",
|
||||
gui.processing.sar3d.x_min_m,
|
||||
"gui.processing.sar3d",
|
||||
),
|
||||
x_max_m=_optional_float(
|
||||
sar3d_object,
|
||||
"x_max_m",
|
||||
gui.processing.sar3d.x_max_m,
|
||||
"gui.processing.sar3d",
|
||||
),
|
||||
y_min_m=_optional_float(
|
||||
@@ -569,6 +575,18 @@ def gui_profile_from_dict(payload: dict[str, Any]) -> GuiProfileModel:
|
||||
gui.processing.sar3d.y_max_m,
|
||||
"gui.processing.sar3d",
|
||||
),
|
||||
z_min_m=_optional_float(
|
||||
sar3d_object,
|
||||
"z_min_m",
|
||||
gui.processing.sar3d.z_min_m,
|
||||
"gui.processing.sar3d",
|
||||
),
|
||||
z_max_m=_optional_float(
|
||||
sar3d_object,
|
||||
"z_max_m",
|
||||
gui.processing.sar3d.z_max_m,
|
||||
"gui.processing.sar3d",
|
||||
),
|
||||
voxel_x_m=_optional_float(
|
||||
sar3d_object,
|
||||
"voxel_x_m",
|
||||
@@ -675,8 +693,12 @@ def gui_profile_from_dict(payload: dict[str, Any]) -> GuiProfileModel:
|
||||
raise ValueError("gui.processing.sar3d.edge_frame_weight must be within [0, 1]")
|
||||
if min(gui.processing.sar3d.voxel_x_m, gui.processing.sar3d.voxel_y_m, gui.processing.sar3d.voxel_z_m) <= 0.0:
|
||||
raise ValueError("gui.processing.sar3d.voxel_x/y/z_m must each be > 0")
|
||||
if gui.processing.sar3d.x_max_m <= gui.processing.sar3d.x_min_m:
|
||||
raise ValueError("gui.processing.sar3d.x_max_m must be > x_min_m")
|
||||
if gui.processing.sar3d.y_max_m <= gui.processing.sar3d.y_min_m:
|
||||
raise ValueError("gui.processing.sar3d.y_max_m must be > y_min_m")
|
||||
if gui.processing.sar3d.z_max_m <= gui.processing.sar3d.z_min_m:
|
||||
raise ValueError("gui.processing.sar3d.z_max_m must be > z_min_m")
|
||||
if gui.processing.sar3d.ground_depth_m < 0.0:
|
||||
raise ValueError("gui.processing.sar3d.ground_depth_m must be >= 0")
|
||||
if gui.processing.sar3d.tx_per_segment < 1:
|
||||
@@ -849,9 +871,12 @@ def gui_profile_to_dict(model: GuiProfileModel) -> dict[str, Any]:
|
||||
"pitch_override_enabled": gui.processing.sar3d.pitch_override_enabled,
|
||||
"pitch_deg": gui.processing.sar3d.pitch_deg,
|
||||
"ground_depth_m": gui.processing.sar3d.ground_depth_m,
|
||||
"x_margin_m": gui.processing.sar3d.x_margin_m,
|
||||
"x_min_m": gui.processing.sar3d.x_min_m,
|
||||
"x_max_m": gui.processing.sar3d.x_max_m,
|
||||
"y_min_m": gui.processing.sar3d.y_min_m,
|
||||
"y_max_m": gui.processing.sar3d.y_max_m,
|
||||
"z_min_m": gui.processing.sar3d.z_min_m,
|
||||
"z_max_m": gui.processing.sar3d.z_max_m,
|
||||
"voxel_x_m": gui.processing.sar3d.voxel_x_m,
|
||||
"voxel_y_m": gui.processing.sar3d.voxel_y_m,
|
||||
"voxel_z_m": gui.processing.sar3d.voxel_z_m,
|
||||
|
||||
@@ -148,9 +148,12 @@ class GuiSar3dStateModel:
|
||||
pitch_override_enabled: bool = False
|
||||
pitch_deg: float = 17.5
|
||||
ground_depth_m: float = 1.25
|
||||
x_margin_m: float = 2.0
|
||||
x_min_m: float = -2.0
|
||||
x_max_m: float = 2.0
|
||||
y_min_m: float = -0.5
|
||||
y_max_m: float = 2.0
|
||||
z_min_m: float = 0.0
|
||||
z_max_m: float = 8.0
|
||||
voxel_x_m: float = 0.025
|
||||
voxel_y_m: float = 0.02
|
||||
voxel_z_m: float = 0.02
|
||||
|
||||
@@ -82,11 +82,15 @@ class ProcessingLiveConfig:
|
||||
sar3d_pitch_deg: float = 17.5
|
||||
# Height of the lower antenna row above the ground (scene Y=0 = ground).
|
||||
sar3d_ground_depth_m: float = 1.25
|
||||
# Full-region grid: X spans the antennas +- margin, Y is height above the
|
||||
# ground, Z covers the radar depth gate over the Y range.
|
||||
sar3d_x_margin_m: float = 2.0
|
||||
# Scene grid bounds (metres): X across, Y height above the ground, Z along
|
||||
# the ground away from the radar. Voxels outside the radar depth gate are
|
||||
# zeroed by the mask regardless of the Z window.
|
||||
sar3d_x_min_m: float = -2.0
|
||||
sar3d_x_max_m: float = 2.0
|
||||
sar3d_y_min_m: float = -0.5
|
||||
sar3d_y_max_m: float = 2.0
|
||||
sar3d_z_min_m: float = 0.0
|
||||
sar3d_z_max_m: float = 8.0
|
||||
sar3d_voxel_x_m: float = 0.025
|
||||
sar3d_voxel_y_m: float = 0.02
|
||||
sar3d_voxel_z_m: float = 0.02
|
||||
@@ -171,9 +175,12 @@ class ProcessingLiveConfig:
|
||||
"sar3d_pitch_override_enabled": bool(self.sar3d_pitch_override_enabled),
|
||||
"sar3d_pitch_deg": float(self.sar3d_pitch_deg),
|
||||
"sar3d_ground_depth_m": float(self.sar3d_ground_depth_m),
|
||||
"sar3d_x_margin_m": float(self.sar3d_x_margin_m),
|
||||
"sar3d_x_min_m": float(self.sar3d_x_min_m),
|
||||
"sar3d_x_max_m": float(self.sar3d_x_max_m),
|
||||
"sar3d_y_min_m": float(self.sar3d_y_min_m),
|
||||
"sar3d_y_max_m": float(self.sar3d_y_max_m),
|
||||
"sar3d_z_min_m": float(self.sar3d_z_min_m),
|
||||
"sar3d_z_max_m": float(self.sar3d_z_max_m),
|
||||
"sar3d_voxel_x_m": float(self.sar3d_voxel_x_m),
|
||||
"sar3d_voxel_y_m": float(self.sar3d_voxel_y_m),
|
||||
"sar3d_voxel_z_m": float(self.sar3d_voxel_z_m),
|
||||
|
||||
@@ -89,9 +89,12 @@ def _sar3d_live_config(profile_path: Path) -> ProcessingLiveConfig:
|
||||
)
|
||||
live.sar3d_pitch_deg = float(sar3d.get("pitch_deg", live.sar3d_pitch_deg))
|
||||
live.sar3d_ground_depth_m = float(sar3d.get("ground_depth_m", live.sar3d_ground_depth_m))
|
||||
live.sar3d_x_margin_m = float(sar3d.get("x_margin_m", live.sar3d_x_margin_m))
|
||||
live.sar3d_x_min_m = float(sar3d.get("x_min_m", live.sar3d_x_min_m))
|
||||
live.sar3d_x_max_m = float(sar3d.get("x_max_m", live.sar3d_x_max_m))
|
||||
live.sar3d_y_min_m = float(sar3d.get("y_min_m", live.sar3d_y_min_m))
|
||||
live.sar3d_y_max_m = float(sar3d.get("y_max_m", live.sar3d_y_max_m))
|
||||
live.sar3d_z_min_m = float(sar3d.get("z_min_m", live.sar3d_z_min_m))
|
||||
live.sar3d_z_max_m = float(sar3d.get("z_max_m", live.sar3d_z_max_m))
|
||||
live.sar3d_voxel_x_m = float(sar3d.get("voxel_x_m", live.sar3d_voxel_x_m))
|
||||
live.sar3d_voxel_y_m = float(sar3d.get("voxel_y_m", live.sar3d_voxel_y_m))
|
||||
live.sar3d_voxel_z_m = float(sar3d.get("voxel_z_m", live.sar3d_voxel_z_m))
|
||||
|
||||
Reference in New Issue
Block a user