mirror of
https://github.com/azaion/gps-denied-onboard.git
synced 2026-04-23 01:26:37 +00:00
test(e2e): wire EuRoC CI-tier test with skip-when-absent fixture
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,36 @@
|
|||||||
|
"""Shared fixtures for e2e tests — dataset discovery + skip markers."""
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
REPO_ROOT = Path(__file__).resolve().parents[2]
|
||||||
|
DATASETS_ROOT = REPO_ROOT / "datasets"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="session")
|
||||||
|
def euroc_mh01_root() -> Path:
|
||||||
|
root = DATASETS_ROOT / "euroc" / "MH_01"
|
||||||
|
if not (root / "mav0").is_dir():
|
||||||
|
pytest.skip(
|
||||||
|
f"EuRoC MH_01 not present at {root}. "
|
||||||
|
"Run `python scripts/download_dataset.py euroc_mh01` to fetch it."
|
||||||
|
)
|
||||||
|
return root
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="session")
|
||||||
|
def vpair_sample_root() -> Path:
|
||||||
|
root = DATASETS_ROOT / "vpair" / "sample"
|
||||||
|
if not root.is_dir():
|
||||||
|
pytest.skip(f"VPAIR sample not present at {root}.")
|
||||||
|
return root
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="session")
|
||||||
|
def mars_lvig_root() -> Path:
|
||||||
|
root = DATASETS_ROOT / "mars_lvig"
|
||||||
|
if not root.is_dir():
|
||||||
|
pytest.skip(f"MARS-LVIG not present at {root}.")
|
||||||
|
return root
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
"""CI-tier e2e: run the full pipeline on EuRoC MH_01.
|
||||||
|
|
||||||
|
Skipped if the dataset is not installed under datasets/euroc/MH_01/.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from gps_denied.testing.datasets.euroc import EuRoCAdapter
|
||||||
|
from gps_denied.testing.harness import E2EHarness
|
||||||
|
from gps_denied.testing.metrics import absolute_trajectory_error
|
||||||
|
|
||||||
|
|
||||||
|
# Initial target — calibrated once real numbers land.
|
||||||
|
EUROC_MH01_RMSE_CEILING_M = 5.0
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.e2e
|
||||||
|
@pytest.mark.needs_dataset
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_euroc_mh01_pipeline_completes(euroc_mh01_root: Path):
|
||||||
|
adapter = EuRoCAdapter(euroc_mh01_root)
|
||||||
|
harness = E2EHarness(adapter)
|
||||||
|
result = await harness.run()
|
||||||
|
assert result.num_frames_submitted > 100, (
|
||||||
|
"MH_01 has thousands of frames; harness should have submitted them all"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.e2e
|
||||||
|
@pytest.mark.needs_dataset
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_euroc_mh01_rmse_within_ceiling(euroc_mh01_root: Path):
|
||||||
|
adapter = EuRoCAdapter(euroc_mh01_root)
|
||||||
|
harness = E2EHarness(adapter)
|
||||||
|
result = await harness.run()
|
||||||
|
if result.estimated_positions_enu.shape[0] == 0:
|
||||||
|
pytest.xfail(
|
||||||
|
"Pipeline currently emits zero GPS estimates on EuRoC — "
|
||||||
|
"expected: VO works but satellite matching + ESKF anchoring not yet tuned. "
|
||||||
|
"Convert to regular assert once the pipeline stabilises."
|
||||||
|
)
|
||||||
|
# Align lengths by truncating to shorter (estimates may lag GT at start)
|
||||||
|
n = min(result.estimated_positions_enu.shape[0], result.ground_truth.shape[0])
|
||||||
|
ate = absolute_trajectory_error(
|
||||||
|
result.estimated_positions_enu[:n],
|
||||||
|
result.ground_truth[:n],
|
||||||
|
)
|
||||||
|
assert ate["rmse"] < EUROC_MH01_RMSE_CEILING_M, f"ATE RMSE={ate['rmse']:.2f}m"
|
||||||
Reference in New Issue
Block a user