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 theCameraPose/SurfaceTarget/Selectionpayloads the
machine emits and latches.GNC/guidance/ee_guidance.py(ee_guidance) — the machine itself: the branch owner
set_ee_targetand the per-mode pose builders, plus theOrbitPathModefork (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 onOrbitPathMode— 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_targetis the branch owner, theguidanceMode*methods
build each mode’s pose, andOrbitPathModeselects the deterministic-schedule vs scorer path.
Mechanism (where it lives in code)
The state set and the ordinal→colour map are declared once:
GuidanceModeIntEnum membersINITIAL=0, FALLBACK, HOLD, TARGETING—GNC/guidance/guidance_classes.py:46GuidanceMode.colour— ordinal indexes the band hex (white / orange / light-blue / black) —GNC/guidance/guidance_classes.py:55OrbitPathModeStrEnum (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 rawCameraPoseper step across all modes —GNC/guidance/ee_guidance.py:699- INITIAL latch:
guidanceModeINITIALholds the CoM-relative offsetp_ceand 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 thenset_ee_targetreturns the INITIAL pose —GNC/guidance/ee_guidance.py:711 - CHAIN-4 wrinkle: when
aim_during_initial, steps1..startupaim 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_duegates 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_ceand 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_targetmargin gate →exit_targetingrebuilds 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 inGNC/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 withexit_holdbeing the not-due ANCHOR
return path atGNC/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 whenaccept_targetclears a reselect, then immediately
latches back to HOLD (commit_targeting_selectionstores the newp_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.POSEshort-circuitsset_ee_targettoorbit_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_ceanddefault_R_be0are captured on the first INITIAL call and only
reset_runtime_stateclears them — a fresh run that reuses a guidance object inherits stale offsets.
The enums areIntEnum/StrEnumon 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 (versine1 − cos θ) is computed in the measurement layer, not in the modes.
Related
guidance_classes · ee_guidance · target_finding_coverage · orbit_com_path · ee_feedforward · target_finder · terminology