mirror of
https://github.com/azaion/gps-denied-onboard.git
synced 2026-06-22 06:01:12 +00:00
[AZ-343] C2.5 InlierCountReRanker + shared FeatureExtractor helper
Implements the production-default ReRankStrategy: K=10 → N=3 by single-pair LightGlue inlier count, with strict drop-and-continue (INV-8) on per-candidate TileFetch / backbone / zero-inlier failures and RerankAllCandidatesFailedError on zero survivors. Composition root injects the shared LightGlueRuntime + Clock + the new FeatureExtractor helper (an L1 placeholder OpenCvOrbExtractor that unblocks AZ-343 and future C3 strategies — task scope expansion). Architectural notes: - Cross-component imports stay banned; tile_store types as `object` and the C6 TileCacheError family is duck-typed by class module prefix (same workaround AZ-348 adopted for c7_inference; proper fix is to relocate TileCacheError to _types/ in a follow-up). - Clock injection follows the replay contract (AZ-398 Invariant 2); reranked_at is sourced from clock.monotonic_ns(). - AZ-342 factory grew `feature_extractor` + `clock` + `fdr_client` parameters; existing AZ-342 conformance tests updated. Tests: 19 new AC-1..AC-12 + mixed-failure scenarios in test_inlier_count_reranker.py; existing AZ-342 suite (26) still green. Full repo sweep 1093 passed / 2 skipped (cmake/actionlint not on PATH). Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -70,11 +70,46 @@ class _FakeLightGlueRuntime:
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class _FakeFeatureExtractor:
|
||||
def descriptor_dim(self):
|
||||
return 256
|
||||
|
||||
def extract(self, image_bgr):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class _FakeClock:
|
||||
def __init__(self) -> None:
|
||||
self._t = 1_000_000_000
|
||||
|
||||
def monotonic_ns(self):
|
||||
self._t += 1
|
||||
return self._t
|
||||
|
||||
def time_ns(self):
|
||||
return self._t
|
||||
|
||||
def sleep_until_ns(self, target_ns):
|
||||
return None
|
||||
|
||||
|
||||
class _FullReRankStrategy:
|
||||
def __init__(self, config, *, tile_store, lightglue_runtime) -> None:
|
||||
def __init__(
|
||||
self,
|
||||
config,
|
||||
*,
|
||||
tile_store,
|
||||
lightglue_runtime,
|
||||
feature_extractor=None,
|
||||
clock=None,
|
||||
fdr_client=None,
|
||||
) -> None:
|
||||
self._config = config
|
||||
self._tile_store = tile_store
|
||||
self._lightglue_runtime = lightglue_runtime
|
||||
self._feature_extractor = feature_extractor
|
||||
self._clock = clock
|
||||
self._fdr_client = fdr_client
|
||||
self._label = config.components["c2_5_rerank"].strategy
|
||||
|
||||
def rerank(self, frame, vpr_result, n, calibration):
|
||||
@@ -127,6 +162,7 @@ def test_ac1_rerank_strategy_conformance_full() -> None:
|
||||
_config_with_strategy(),
|
||||
tile_store=_FakeTileStore(),
|
||||
lightglue_runtime=_FakeLightGlueRuntime(),
|
||||
clock=_FakeClock(),
|
||||
)
|
||||
assert isinstance(instance, ReRankStrategy)
|
||||
|
||||
@@ -201,6 +237,8 @@ def test_ac3_factory_rejects_missing_build_flag(
|
||||
config,
|
||||
tile_store=_FakeTileStore(),
|
||||
lightglue_runtime=_FakeLightGlueRuntime(),
|
||||
feature_extractor=_FakeFeatureExtractor(),
|
||||
clock=_FakeClock(),
|
||||
)
|
||||
assert "BUILD_RERANK_INLIER_COUNT is OFF" in str(exc_info.value)
|
||||
assert any(
|
||||
@@ -219,6 +257,8 @@ def test_ac3_factory_does_not_load_module_when_flag_off(
|
||||
config,
|
||||
tile_store=_FakeTileStore(),
|
||||
lightglue_runtime=_FakeLightGlueRuntime(),
|
||||
feature_extractor=_FakeFeatureExtractor(),
|
||||
clock=_FakeClock(),
|
||||
)
|
||||
assert module_name not in sys.modules
|
||||
|
||||
@@ -256,6 +296,8 @@ def test_ac5_factory_emits_info_log_on_success(
|
||||
config,
|
||||
tile_store=_FakeTileStore(),
|
||||
lightglue_runtime=_FakeLightGlueRuntime(),
|
||||
feature_extractor=_FakeFeatureExtractor(),
|
||||
clock=_FakeClock(),
|
||||
)
|
||||
assert isinstance(instance, ReRankStrategy)
|
||||
records = [
|
||||
@@ -281,6 +323,8 @@ def test_ac6_strategy_resolution(monkeypatch, strategy_module_cleanup) -> None:
|
||||
config,
|
||||
tile_store=_FakeTileStore(),
|
||||
lightglue_runtime=_FakeLightGlueRuntime(),
|
||||
feature_extractor=_FakeFeatureExtractor(),
|
||||
clock=_FakeClock(),
|
||||
)
|
||||
assert isinstance(instance, fake_cls)
|
||||
assert isinstance(instance, ReRankStrategy)
|
||||
@@ -373,12 +417,18 @@ def test_nfr_perf_factory_under_50ms_p99(
|
||||
config = _config_with_strategy(strategy)
|
||||
tile_store = _FakeTileStore()
|
||||
lightglue_runtime = _FakeLightGlueRuntime()
|
||||
feature_extractor = _FakeFeatureExtractor()
|
||||
clock = _FakeClock()
|
||||
|
||||
durations_ms: list[float] = []
|
||||
for _ in range(100):
|
||||
t0 = time.perf_counter()
|
||||
build_rerank_strategy(
|
||||
config, tile_store=tile_store, lightglue_runtime=lightglue_runtime
|
||||
config,
|
||||
tile_store=tile_store,
|
||||
lightglue_runtime=lightglue_runtime,
|
||||
feature_extractor=feature_extractor,
|
||||
clock=clock,
|
||||
)
|
||||
durations_ms.append((time.perf_counter() - t0) * 1000.0)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user