mirror of
https://github.com/azaion/gps-denied-onboard.git
synced 2026-06-22 16:41:13 +00:00
[AZ-623] [AZ-625] Phase E: c282_ransac + c5 helpers; split handle work
Wire 4 stateless / cached helpers into airborne_bootstrap.build_pre_constructed: c282_ransac_filter, c5_imu_preintegrator (cached on calibration path), c5_se3_utils (helpers.se3_utils module as namespace handle), c5_wgs_converter. The original AZ-623 5th deliverable (c5_isam2_graph_handle) hit an unresolvable construction-order conflict between c4_pose (consumes the handle) and c5_state (creates it inside build_state_estimator's tuple return) under the umbrella's "MUST NOT touch any per-component factory signature" constraint. Per AZ-623 spec's escalation gate, scope was split: AZ-625 captures the handle ordering work; AZ-624 dependency edge updated to require both. Tests: tests/unit/runtime_root/test_az623_pre_constructed_phase_e.py adds 7 tests covering AC-623.1..3 (4 new keys + correct types, IMU preintegrator caching, operator-actionable error messages for empty / unreadable / malformed calibration paths). Autouse stubs added to test_az619/620/621/622 so prior phase tests remain isolated from new builders. Quality gates: ruff format clean, ruff lint clean, 24/24 phase tests pass, 247/247 runtime_root + c5_state regression suite passes. Code review verdict PASS_WITH_WARNINGS (3 Low findings; full report in _docs/03_implementation/reviews/batch_94_review.md). Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
# AZ-623 — Phase E: build_pre_constructed seeds c282_ransac_filter + 3 c5 helpers
|
||||
|
||||
**Task**: AZ-623_pre_constructed_phase_e_ransac_c5_helpers
|
||||
**Name**: AZ-618 Phase E: build_pre_constructed seeds c282_ransac_filter + c5 helpers
|
||||
**Description**: Fifth subtask of AZ-618. Extends `airborne_bootstrap.build_pre_constructed(config)` to populate the small / stateless helper entries.
|
||||
**Complexity**: 3 points
|
||||
**Dependencies**: AZ-619, AZ-282 (RansacFilter), AZ-276 (ImuPreintegrator), AZ-277 (SE3Utils), AZ-279 (WgsConverter). All in `done/`.
|
||||
**Component**: runtime_root (cross-cutting)
|
||||
**Tracker**: AZ-623
|
||||
**Epic**: AZ-602 (parent: AZ-618 umbrella)
|
||||
|
||||
## Scope split note (2026-05-19)
|
||||
|
||||
The original AZ-623 included `c5_isam2_graph_handle`. Path 1 of the spec's two-path investigation requires a Protocol seam change to `ISam2GraphHandleImpl` (handle is tightly coupled to `GtsamIsam2StateEstimator` via constructor injection); the AZ-618 umbrella forbids per-component factory signature changes. Per the spec's own escalation gate, the user was asked and chose to split: this ticket lands the 4 stateless helpers; AZ-625 (`AZ-618 follow-up: c5_isam2_graph_handle ordering`) lands the handle wiring with a documented in-bootstrap (estimator, handle) build + look-aside short-circuit pattern. AZ-624 (main wiring + AC verification) now blocks on BOTH AZ-623 and AZ-625.
|
||||
|
||||
## Outcome
|
||||
|
||||
- `build_pre_constructed(config)` adds keys `c282_ransac_filter`, `c5_imu_preintegrator`, `c5_se3_utils`, `c5_wgs_converter` on top of AZ-619..AZ-622. (`c5_isam2_graph_handle` moved to AZ-625.)
|
||||
- New unit tests under `tests/unit/runtime_root/test_az623_pre_constructed_phase_e.py`.
|
||||
|
||||
## Scope
|
||||
|
||||
### Included
|
||||
|
||||
- Internal builders for the 4 keys above. `c282_ransac_filter` and `c5_wgs_converter` return fresh stateless instances (`RansacFilter()`, `WgsConverter()`); `c5_se3_utils` returns the `gps_denied_onboard.helpers.se3_utils` module (consumers access functions as attributes; tests stub via `MagicMock` with the same attribute-access shape); `c5_imu_preintegrator` builds via `make_imu_preintegrator(camera_calibration)` with the calibration loaded from `config.runtime.camera_calibration_path` and the result cached per path.
|
||||
- The calibration loader function in `airborne_bootstrap.py` mirrors the JSON shape `runtime_root._replay_branch._load_camera_calibration` already uses — same on-disk format, no new file format introduced.
|
||||
- Unit tests covering AC-623.1 + AC-623.2.
|
||||
|
||||
### Excluded
|
||||
|
||||
- main() wiring (AZ-624).
|
||||
- GPU-touching builders (AZ-621 / AZ-622).
|
||||
- `c5_isam2_graph_handle` seeding (AZ-625, see Scope split note).
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
**AC-623.1**: `build_pre_constructed(config)` adds the 4 keys above on top of AZ-619..AZ-622.
|
||||
|
||||
**AC-623.2**: invoking `build_pre_constructed(config)` twice within the same process produces a dict where `c5_imu_preintegrator` is the same object both times (cached by `config.runtime.camera_calibration_path`). The 3 stateless helpers may be either fresh or cached — caching is irrelevant for them.
|
||||
|
||||
**AC-623.3**: when `config.runtime.camera_calibration_path` is empty or unreadable, `_build_c5_imu_preintegrator` raises `AirborneBootstrapError` naming the missing input and the consuming component slug `c5_state` (operator-actionable error mirroring AC-3 / AC-622.2).
|
||||
|
||||
**AC-623.4**: `pytest tests/unit/runtime_root/test_az623_pre_constructed_phase_e.py` covers AC-623.1 + AC-623.2 + AC-623.3.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- `c5_se3_utils` returns the `helpers.se3_utils` MODULE (Python modules support attribute access for their public names; consumers store it as `self._se3_utils: Any` and call `self._se3_utils.exp_map(...)`). The `MagicMock()` fixture used by existing C5 estimator tests has the same shape.
|
||||
- `c5_wgs_converter` returns `WgsConverter()` (instance of a static-only class) — same pattern `runtime_root._replay_branch.run` already uses (`wgs_converter = WgsConverter()`).
|
||||
- `c282_ransac_filter` returns `RansacFilter()` (instance of a static-only class) — consumers (`c3_matcher`, `c3_5_adhop`, `c4_pose`) use it for attribute-dispatch only.
|
||||
- `c5_imu_preintegrator` is the only stateful helper; its bias accumulator survives across `build_pre_constructed` invocations, hence the per-path cache.
|
||||
|
||||
## Constraints
|
||||
|
||||
- MUST NOT modify per-component factory signatures.
|
||||
- MUST be additive on top of AZ-619..AZ-622.
|
||||
|
||||
## Evidence
|
||||
|
||||
- Umbrella spec: `_docs/02_tasks/todo/AZ-618_airborne_bootstrap_pre_constructed.md`
|
||||
- Helper modules: `src/gps_denied_onboard/helpers/{ransac_filter,imu_preintegrator,se3_utils,wgs_converter}.py`
|
||||
- `c5_state` factory: `src/gps_denied_onboard/runtime_root/state_factory.py`
|
||||
- ISam2GraphHandle (deferred to AZ-625): `src/gps_denied_onboard/components/c5_state/_isam2_handle.py`
|
||||
- Calibration loader pattern: `runtime_root/_replay_branch.py::_load_camera_calibration`
|
||||
Reference in New Issue
Block a user