Files
gps-denied-onboard/tests/e2e/test_vpair.py
T
Yuzviak 5744ff65ac feat(02-03): apply module-level pytestmark to 37 test files
- Add pytestmark = [pytest.mark.<category>] to all 23 root test files and 14 e2e test files
- Marker distribution: 22 unit, 7 integration, 1 blackbox, 1 sitl, 5 e2e + 2 e2e integration
- Add import pytest to test_models.py, test_download.py, test_synthetic_adapter.py (were missing)
- Convert test_sitl_integration.py's bare pytestmark to list form preserving skipif guard
- Union of all 5 markers = 298/298 = 100% coverage; 216 tests pass with --strict-markers
2026-05-11 18:20:05 +03:00

58 lines
2.0 KiB
Python

"""VPAIR nominal e2e — fixed-wing, downward, no raw IMU.
Tests that require full ESKF path are skipped because VPAIR ships poses only.
The VO + GPR + graph path is still exercised.
"""
from pathlib import Path
import pytest
pytestmark = [pytest.mark.e2e]
from gps_denied.testing.datasets.vpair import VPAIRAdapter
from gps_denied.testing.harness import E2EHarness
from gps_denied.testing.metrics import absolute_trajectory_error
VPAIR_SAMPLE_RMSE_CEILING_M = 20.0 # initial target, calibrate after first runs
@pytest.mark.e2e
@pytest.mark.e2e_slow
@pytest.mark.needs_dataset
@pytest.mark.asyncio
async def test_vpair_sample_pipeline_completes(vpair_sample_root: Path):
adapter = VPAIRAdapter(vpair_sample_root)
if not adapter.capabilities.has_raw_imu:
# ESKF path is skipped automatically inside the product because IMU
# callbacks are never fired; we only check completion here.
pass
harness = E2EHarness(adapter)
result = await harness.run()
assert result.num_frames_submitted > 0
@pytest.mark.e2e
@pytest.mark.e2e_slow
@pytest.mark.needs_dataset
@pytest.mark.asyncio
async def test_vpair_sample_trajectory_bounded(vpair_sample_root: Path):
adapter = VPAIRAdapter(vpair_sample_root)
harness = E2EHarness(adapter)
result = await harness.run()
if result.estimated_positions_enu.shape[0] == 0:
pytest.xfail(
"Pipeline produced no GPS estimates on VPAIR sample. "
"Expected until VO + GPR tuning for 300-400m nadir imagery is validated."
)
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]
)
if ate["rmse"] >= VPAIR_SAMPLE_RMSE_CEILING_M:
pytest.xfail(
f"ATE RMSE={ate['rmse']:.2f}m exceeds {VPAIR_SAMPLE_RMSE_CEILING_M}m ceiling. "
"VO + GPR not yet tuned for 300-400m nadir imagery."
)
assert ate["rmse"] < VPAIR_SAMPLE_RMSE_CEILING_M, f"ATE RMSE={ate['rmse']:.2f}m"