"""C5 ``StateEstimator`` error hierarchy — AZ-381. Every C5-emitted exception inherits :class:`StateEstimatorError` (AC-10) so callers can write a single ``except`` against the whole component surface. Composition-root failures use :class:`StateEstimatorConfigError`; runtime failures split into ``Degraded`` (recoverable; emit a degraded estimate + log) vs ``Fatal`` (unrecoverable; trigger the AC-5.2 IMU-only fallback path in C8). """ from __future__ import annotations __all__ = [ "EstimatorAlreadyStartedError", "EstimatorDegradedError", "EstimatorFatalError", "StateEstimatorConfigError", "StateEstimatorError", ] class StateEstimatorError(Exception): """Base class for every C5-emitted exception (AC-10).""" class EstimatorDegradedError(StateEstimatorError): """Recoverable runtime degradation. Examples: out-of-order ``add_*`` call (Invariant 2), failed factor add against the graph (R05 mitigation surfaces via this), poor convergence detected post-update. The estimator continues to produce outputs but the next ``current_estimate()`` may carry a degraded ``EstimatorHealth.isam2_state``. """ class EstimatorFatalError(StateEstimatorError): """Unrecoverable numerical failure. Raised when iSAM2 / Marginals / the smoother enter a state from which the run cannot continue: non-SPD posterior covariance after update, NaN propagation, GTSAM exception bubbling. Triggers the AC-5.2 path in C8 (IMU-only fallback) and the source-label state machine transitions to ``DEAD_RECKONED``. """ class StateEstimatorConfigError(StateEstimatorError): """Composition-time configuration error. Raised by :func:`build_state_estimator` when the requested strategy is not registered (per ADR-002 build flag gating), when the config schema fails validation, or when the runtime root cannot wire the iSAM2 graph handle into C4. AZ-490: also raised by :meth:`StateEstimator.set_takeoff_origin` when the supplied ``LatLonAlt`` is outside WGS-84 bounds, when either sigma is non-positive / non-finite, or when the entrypoint is called twice with conflicting arguments before the first measurement. """ class EstimatorAlreadyStartedError(StateEstimatorConfigError): """``set_takeoff_origin`` called after the estimator left the INIT state. AZ-490 / Contract Invariant 11a: the operator-origin entrypoint is valid only before the first ``add_*`` call. Once any factor has been added (i.e. the smoother is past INIT), seeding a new prior would silently corrupt the running estimate. ``IS-A`` of :class:`StateEstimatorConfigError` so existing ``except StateEstimatorConfigError`` callers also catch this. """