mirror of
https://github.com/azaion/gps-denied-onboard.git
synced 2026-04-23 03:06:37 +00:00
test(e2e): add VPAIRAdapter (pose-only; fixed-wing capability)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
"""Adapter for VPAIR (Aerial Visual Place Recognition) dataset sample release."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import csv
|
||||
from pathlib import Path
|
||||
from typing import Iterator
|
||||
|
||||
from gps_denied.testing.datasets.base import (
|
||||
DatasetAdapter,
|
||||
DatasetCapabilities,
|
||||
DatasetFrame,
|
||||
DatasetIMU,
|
||||
DatasetNotAvailableError,
|
||||
DatasetPose,
|
||||
PlatformClass,
|
||||
)
|
||||
|
||||
|
||||
class VPAIRAdapter(DatasetAdapter):
|
||||
"""Reads the VPAIR sample bundle (queries/ + poses.csv)."""
|
||||
|
||||
def __init__(self, root: Path) -> None:
|
||||
self._root = Path(root)
|
||||
self._queries_dir = self._root / "queries"
|
||||
self._poses_csv = self._root / "poses.csv"
|
||||
if not (self._queries_dir.is_dir() and self._poses_csv.is_file()):
|
||||
raise DatasetNotAvailableError(
|
||||
f"VPAIR sample not found at {self._root} "
|
||||
"(expected queries/ and poses.csv). "
|
||||
"Download from https://github.com/AerVisLoc/vpair sample link on Zenodo."
|
||||
)
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return f"vpair:{self._root.name}"
|
||||
|
||||
@property
|
||||
def capabilities(self) -> DatasetCapabilities:
|
||||
return DatasetCapabilities(
|
||||
has_raw_imu=False, # VPAIR ships poses, not raw IMU
|
||||
has_rtk_gt=False, # GNSS/INS 1m accuracy, not RTK
|
||||
has_loop_closures=False,
|
||||
platform_class=PlatformClass.FIXED_WING,
|
||||
)
|
||||
|
||||
def iter_frames(self) -> Iterator[DatasetFrame]:
|
||||
with self._poses_csv.open() as fh:
|
||||
reader = csv.DictReader(fh)
|
||||
for idx, row in enumerate(reader):
|
||||
yield DatasetFrame(
|
||||
frame_idx=idx,
|
||||
timestamp_ns=int(row["timestamp_ns"]),
|
||||
image_path=str(self._queries_dir / row["filename"]),
|
||||
)
|
||||
|
||||
def iter_imu(self) -> Iterator[DatasetIMU]:
|
||||
return
|
||||
yield # empty generator
|
||||
|
||||
def iter_ground_truth(self) -> Iterator[DatasetPose]:
|
||||
with self._poses_csv.open() as fh:
|
||||
reader = csv.DictReader(fh)
|
||||
for row in reader:
|
||||
yield DatasetPose(
|
||||
timestamp_ns=int(row["timestamp_ns"]),
|
||||
lat=float(row["lat"]),
|
||||
lon=float(row["lon"]),
|
||||
alt=float(row["alt"]),
|
||||
qx=float(row["qx"]),
|
||||
qy=float(row["qy"]),
|
||||
qz=float(row["qz"]),
|
||||
qw=float(row["qw"]),
|
||||
)
|
||||
Reference in New Issue
Block a user