Skip to content

gds-analysis: detectability analysis for observer design #210

@rororowyourboat

Description

@rororowyourboat

Summary

Add detectability analysis to gds_analysis.linear as the weaker observability property needed for observer design.

Detectability asks whether every unobservable mode is at least stable. This is the mathematically correct precondition for steady-state observer synthesis and aligns with the existing kalman() API contract.

Motivation

The current control stack already provides:

  • observability_matrix() / is_observable() in gds_domains.symbolic
  • is_stable() in gds_analysis.linear
  • kalman() in gds_analysis.linear

But there is no first-class API for the intermediate property controls engineers actually use when full observability is too strong. Detectability completes the classical pair:

  • controllability → stabilizability
  • observability → detectability

Proposed API

In gds_analysis.linear

def unobservable_modes(
    A: list[list[float]],
    C: list[list[float]],
    *,
    tol: float = 1e-9,
) -> list[complex]:
    """Return eigenvalues corresponding to unobservable modes via PBH."""


def is_detectable(
    A: list[list[float]],
    C: list[list[float]],
    *,
    continuous: bool = True,
    tol: float = 1e-9,
) -> bool:
    """Check detectability of (A, C).

    Continuous-time: every mode with Re(lambda) >= 0 must be observable.
    Discrete-time: every mode with |lambda| >= 1 must be observable.
    """

Implementation notes

Use the PBH observability test mode-by-mode:

  • mode λ is observable iff rank([[λI - A], [C]]) = n
  • a system is detectable iff every unobservable mode lies strictly in the stable region

This belongs in gds_analysis.linear rather than gds_domains.symbolic because:

  • it is a numerical matrix-level property
  • it matches the existing home of is_stable(), lqr(), and kalman()
  • it should accept plain list[list[float]] matrices, independent of any DSL object

Follow-on

  • Update kalman() docs and validation language to reference detectability explicitly.
  • Export through gds_analysis.__init__ lazy imports.

Testing

Add known-answer tests for:

  1. fully observable stable system → detectable
  2. unobservable but stable mode → detectable
  3. unobservable unstable mode → not detectable
  4. discrete-time analog with an unobservable pole inside/outside the unit circle

Labels

enhancement, control-theory

Metadata

Metadata

Assignees

No one assigned

    Labels

    control-theoryClassical control theory capabilitiesenhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions