guidance_modes — the per-step EE guidance state machine

Concept

Every control step picks one raw EE camera pose by running a small state machine over
GuidanceMode (INITIAL → HOLD/TARGETING/FALLBACK). The vocabulary (enums + records) lives in one
file and the transitions in another, so neither per-file page tells the whole story — this page does.
The recurring trap: TARGETING reads like “the tracking mode” but is a 1-step reselect event; the EE
actually tracks in HOLD.

What this spans

  • GNC/guidance/guidance_classes.py (guidance_classes) — the enums and records: GuidanceMode,
    OrbitPathMode, ScoringMode, and the CameraPose / SurfaceTarget / Selection payloads the
    machine emits and latches.
  • GNC/guidance/ee_guidance.py (ee_guidance) — the machine itself: the branch owner
    set_ee_target and the per-mode pose builders, plus the OrbitPathMode fork (POSE schedule vs ANCHOR
    scorer).
  • Thesis: the four modes are not a symmetric ring; INITIAL is a one-shot startup latch, HOLD is the
    operational steady state, and TARGETING/FALLBACK are momentary excursions. Which transitions are even
    reachable depends on OrbitPathMode — in the adopted POSE default the scorer (and hence
    TARGETING/HOLD/FALLBACK) is inert.

Constituent pages

Down-links to the per-file pages that hold each part’s contract:

  • guidance_classes — defines GuidanceMode (the IntEnum whose ordinal indexes the plot-band colour),
    OrbitPathMode (POSE vs ANCHOR routing), and the typed records that flow between modes.
  • ee_guidance — runs the machine: set_ee_target is the branch owner, the guidanceMode* methods
    build each mode’s pose, and OrbitPathMode selects the deterministic-schedule vs scorer path.

Mechanism (where it lives in code)

The state set and the ordinal→colour map are declared once:

  • GuidanceMode IntEnum members INITIAL=0, FALLBACK, HOLD, TARGETINGGNC/guidance/guidance_classes.py:46
  • GuidanceMode.colour — ordinal indexes the band hex (white / orange / light-blue / black) — GNC/guidance/guidance_classes.py:55
  • OrbitPathMode StrEnum (POSE, ANCHOR) — the routing fork — GNC/guidance/guidance_classes.py:39

The machine runs once per step in the branch owner:

  • set_ee_target — selects exactly one raw CameraPose per step across all modes — GNC/guidance/ee_guidance.py:699
  • INITIAL latch: guidanceModeINITIAL holds the CoM-relative offset p_ce and base-relative rotation
    R_be0, captured on the first call — GNC/guidance/ee_guidance.py:346
  • INITIAL exit gate: initial_phase_complete (step counter past the startup window) — GNC/guidance/ee_guidance.py:380; until then set_ee_target returns the INITIAL pose — GNC/guidance/ee_guidance.py:711
  • CHAIN-4 wrinkle: when aim_during_initial, steps 1..startup aim along the path while still tagged INITIAL — GNC/guidance/ee_guidance.py:704
  • POSE fork (adopted default): deterministic schedule, scorer never runs — GNC/guidance/ee_guidance.py:722
  • ANCHOR fork: update_due gates the reselect; not due → exit_hold (the EE actually tracks here) — GNC/guidance/ee_guidance.py:730
  • HOLD pose: re-place the EE at the preserved p_ce and re-aim at the held target — GNC/guidance/ee_guidance.py:469
  • ANCHOR vantage = a CoM-orbit point (not x_surf), fed to the finder — GNC/guidance/ee_guidance.py:740
  • TARGETING (1-step event): accept_target margin gate → exit_targeting rebuilds the accepted candidate’s pose — GNC/guidance/ee_guidance.py:562, :540
  • FALLBACK: no viable candidate → hold a copy of the last active pose with score −∞GNC/guidance/ee_guidance.py:451

Evidence

  • Mode semantics and the StrEnum/IntEnum design rationale are recorded in GNC/INSIGHTS.md ([guidance],
    [config] markers) and surfaced on guidance_classes (the band colours, the fail-loud config
    validation).
  • “POSE is the adopted default — the scorer is INERT” and “ANCHOR vantage is a CoM-orbit point, not
    x_surf” are both committed in GNC/INSIGHTS.md ([guidance]) and carried on ee_guidance.
  • The operational reading — TARGETING is a 1-step reselect event, the EE tracks in HOLD — is project
    memory (operational-regime-is-hold-velocity-lag), consistent with exit_hold being the not-due ANCHOR
    return path at GNC/guidance/ee_guidance.py:730.

Footguns

TARGETING is a momentary event, not the tracking mode

Reading the four members as a symmetric ring is wrong. HOLD is where the EE spends its operational
life; TARGETING fires for a single step when accept_target clears a reselect, then immediately
latches back to HOLD (commit_targeting_selection stores the new p_ce). Sizing dwell or tracking off
the TARGETING band undercounts the real tracking window. (project memory
operational-regime-is-hold-velocity-lag)

In the adopted POSE mode, three of the four modes never run

OrbitPathMode.POSE short-circuits set_ee_target to orbit_path_pose (GNC/guidance/ee_guidance.py:722),
so the finder, update_due, HOLD, TARGETING and FALLBACK are all inert. The mode bands you see on a
POSE run are INITIAL (startup) then the scheduled path — not scorer transitions. ANCHOR is the only
route that exercises the full machine. (GNC/INSIGHTS.md [guidance])

INITIAL latches persist until an explicit reset

default_selection.p_ce and default_R_be0 are captured on the first INITIAL call and only
reset_runtime_state clears them — a fresh run that reuses a guidance object inherits stale offsets.
The enums are IntEnum/StrEnum on purpose (fail-loud config validation); do not demote them to magic
strings. (GNC/INSIGHTS.md [footgun], [config])

Equations & references

Key equations mirrored from current_sota — the math source of truth; see there for derivations.

POSE standoff pose (deterministic, adopted default) — §5.4, eq (5.7):

ANCHOR weighted-product score (inert in POSE; novelty ) — §7, eq (7.2):

References:

  • POSE-mode standoff construction (the pose the schedule emits): current_sota > 5.4.
  • CoM orbit reference + startup ramp (the INITIAL window’s clock): current_sota > 5.1.
  • The pointing/coverage metric vocabulary the records carry (§7): current_sota > 7. The pointing
    metric (versine 1 − cos θ) is computed in the measurement layer, not in the modes.

guidance_classes · ee_guidance · target_finding_coverage · orbit_com_path · ee_feedforward · target_finder · terminology