mirror of
https://github.com/azaion/gps-denied-onboard.git
synced 2026-04-23 01:46:38 +00:00
feat(testing): add max_frames parameter to E2EHarness
Caps the iteration length (and the matching GT slice) when set, so CI tiers can stay fast on multi-thousand-frame sequences like EuRoC MH_01 (3682 frames ≈ 3+ hours at 3-5s/frame). Also useful for eyeballing a new adapter's first N frames before committing to a full run. Three new harness tests cover truncation, explicit None, and over-large limits. No change to existing adapters or downstream tests. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -45,11 +45,24 @@ class HarnessResult:
|
|||||||
|
|
||||||
|
|
||||||
class E2EHarness:
|
class E2EHarness:
|
||||||
"""Drives FlightProcessor from a DatasetAdapter; collects results."""
|
"""Drives FlightProcessor from a DatasetAdapter; collects results.
|
||||||
|
|
||||||
def __init__(self, adapter: DatasetAdapter, flight_id: str = "e2e-flight") -> None:
|
`max_frames` caps the iteration (and the matching GT slice). Useful for:
|
||||||
|
- CI tiers where a full multi-thousand-frame sequence is too slow.
|
||||||
|
- Debugging a new adapter — eyeball the first N frames before committing
|
||||||
|
to a multi-hour run.
|
||||||
|
`None` (default) means "consume the full dataset".
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
adapter: DatasetAdapter,
|
||||||
|
flight_id: str = "e2e-flight",
|
||||||
|
max_frames: Optional[int] = None,
|
||||||
|
) -> None:
|
||||||
self._adapter = adapter
|
self._adapter = adapter
|
||||||
self._flight_id = flight_id
|
self._flight_id = flight_id
|
||||||
|
self._max_frames = max_frames
|
||||||
self._estimates: list[tuple[int, Optional[tuple[float, float, float]]]] = []
|
self._estimates: list[tuple[int, Optional[tuple[float, float, float]]]] = []
|
||||||
|
|
||||||
async def run(self) -> HarnessResult:
|
async def run(self) -> HarnessResult:
|
||||||
@@ -57,6 +70,10 @@ class E2EHarness:
|
|||||||
frames = list(self._adapter.iter_frames())
|
frames = list(self._adapter.iter_frames())
|
||||||
gt_poses = list(self._adapter.iter_ground_truth())
|
gt_poses = list(self._adapter.iter_ground_truth())
|
||||||
|
|
||||||
|
if self._max_frames is not None:
|
||||||
|
frames = frames[: self._max_frames]
|
||||||
|
gt_poses = gt_poses[: self._max_frames]
|
||||||
|
|
||||||
for frame in frames:
|
for frame in frames:
|
||||||
image = self._load_or_synth_image(frame.image_path)
|
image = self._load_or_synth_image(frame.image_path)
|
||||||
result = await processor.process_frame(
|
result = await processor.process_frame(
|
||||||
|
|||||||
@@ -35,3 +35,32 @@ async def test_harness_captures_ground_truth_as_enu():
|
|||||||
east_disp = result.ground_truth[-1, 0] - result.ground_truth[0, 0]
|
east_disp = result.ground_truth[-1, 0] - result.ground_truth[0, 0]
|
||||||
# Allow 5% tolerance for the lat/lon → ENU conversion approximation
|
# Allow 5% tolerance for the lat/lon → ENU conversion approximation
|
||||||
assert abs(east_disp - 4.0) < 0.5
|
assert abs(east_disp - 4.0) < 0.5
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_harness_max_frames_truncates_iteration():
|
||||||
|
# Adapter says 10 frames; harness with max_frames=3 should stop at 3.
|
||||||
|
adapter = SyntheticAdapter(num_frames=10, fps=5.0)
|
||||||
|
harness = E2EHarness(adapter, max_frames=3)
|
||||||
|
result = await harness.run()
|
||||||
|
assert result.num_frames_submitted == 3
|
||||||
|
# GT aligned to the same truncation so downstream metrics match lengths
|
||||||
|
assert result.ground_truth.shape[0] == 3
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_harness_max_frames_none_runs_full():
|
||||||
|
# Explicit None = no limit (same as omitting the parameter).
|
||||||
|
adapter = SyntheticAdapter(num_frames=4, fps=5.0)
|
||||||
|
harness = E2EHarness(adapter, max_frames=None)
|
||||||
|
result = await harness.run()
|
||||||
|
assert result.num_frames_submitted == 4
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_harness_max_frames_larger_than_dataset_is_harmless():
|
||||||
|
# Limit above dataset size should not over-extend.
|
||||||
|
adapter = SyntheticAdapter(num_frames=4, fps=5.0)
|
||||||
|
harness = E2EHarness(adapter, max_frames=100)
|
||||||
|
result = await harness.run()
|
||||||
|
assert result.num_frames_submitted == 4
|
||||||
|
|||||||
Reference in New Issue
Block a user