mirror of
https://github.com/azaion/gps-denied-onboard.git
synced 2026-06-22 21:31:13 +00:00
[AZ-231] Add anchor verification gates
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
from anchor_verification import AnchorFrame, GeometryGatedAnchorVerifier, MatchEvidence
|
||||
from shared.contracts import VprCandidate
|
||||
|
||||
|
||||
def _candidate(freshness_status: str = "fresh") -> VprCandidate:
|
||||
return VprCandidate(
|
||||
chunk_id="chunk-1",
|
||||
tile_id="tile-1",
|
||||
score=0.91,
|
||||
footprint={"min_lat": 49.0, "max_lat": 49.2, "min_lon": 36.0, "max_lon": 36.2},
|
||||
freshness_status=freshness_status,
|
||||
)
|
||||
|
||||
|
||||
def _evidence(**overrides: object) -> MatchEvidence:
|
||||
payload: dict[str, object] = {
|
||||
"candidate": _candidate(),
|
||||
"matcher_profile": "aliked_lightglue",
|
||||
"inliers": 48,
|
||||
"mean_reprojection_error_px": 1.4,
|
||||
"homography": {"h00": 1.0, "h11": 1.0, "h22": 1.0},
|
||||
"runtime_ms": 72.5,
|
||||
"provenance_trusted": True,
|
||||
}
|
||||
payload.update(overrides)
|
||||
return MatchEvidence.model_validate(payload)
|
||||
|
||||
|
||||
def test_candidate_verification_emits_acceptance_evidence() -> None:
|
||||
# Arrange
|
||||
verifier = GeometryGatedAnchorVerifier()
|
||||
frame = AnchorFrame(frame_id="frame-1", image_ref="replay/frame-1.jpg")
|
||||
|
||||
# Act
|
||||
result = verifier.verify(frame, _evidence())
|
||||
|
||||
# Assert
|
||||
assert result.decision.accepted is True
|
||||
assert result.decision.inliers == 48
|
||||
assert result.decision.mean_reprojection_error_px == 1.4
|
||||
assert result.reason == "accepted_geometry"
|
||||
assert result.homography == {"h00": 1.0, "h11": 1.0, "h22": 1.0}
|
||||
|
||||
|
||||
def test_unsafe_candidate_is_rejected_with_reason() -> None:
|
||||
# Arrange
|
||||
verifier = GeometryGatedAnchorVerifier()
|
||||
frame = AnchorFrame(frame_id="frame-1", image_ref="replay/frame-1.jpg")
|
||||
evidence = _evidence(
|
||||
candidate=_candidate(freshness_status="stale"),
|
||||
inliers=6,
|
||||
mean_reprojection_error_px=8.0,
|
||||
)
|
||||
|
||||
# Act
|
||||
result = verifier.verify(frame, evidence)
|
||||
|
||||
# Assert
|
||||
assert result.decision.accepted is False
|
||||
assert result.decision.estimated_pose is None
|
||||
assert result.decision.rejection_reason == "stale_or_untrusted_provenance"
|
||||
assert result.reason == "stale_or_untrusted_provenance"
|
||||
|
||||
|
||||
def test_matcher_benchmark_reports_profile_runtime_and_quality_metrics() -> None:
|
||||
# Arrange
|
||||
verifier = GeometryGatedAnchorVerifier()
|
||||
frame = AnchorFrame(frame_id="frame-1", image_ref="replay/frame-1.jpg")
|
||||
|
||||
# Act
|
||||
report = verifier.benchmark(
|
||||
frame,
|
||||
(
|
||||
_evidence(matcher_profile="aliked_lightglue", runtime_ms=72.5),
|
||||
_evidence(matcher_profile="sift_orb", inliers=12, runtime_ms=18.0),
|
||||
),
|
||||
)
|
||||
|
||||
# Assert
|
||||
assert [result.matcher_profile for result in report.results] == [
|
||||
"aliked_lightglue",
|
||||
"sift_orb",
|
||||
]
|
||||
assert report.results[0].accepted is True
|
||||
assert report.results[0].runtime_ms == 72.5
|
||||
assert report.results[1].accepted is False
|
||||
assert report.results[1].reason == "low_inliers"
|
||||
Reference in New Issue
Block a user