Generated: 2026-06-10 20:20 EDT (investigator skill, report-only — no
code modified) Subject: GNC/guidance/ee_guidance.py under
the adopted Mission-1 defaults (commit
64c3905). Supersedes the mode-machine picture in current_state_machine_Jun06.md
for default-config runs. Companion result: mission_1_success.md (coverage 0.9990,
p_e p99 0.165 m).
set_ee_target
returns from the orbit-path branch (:638-639) before the
reactive logic that produced them is ever reached.orbit_path.enable: false — it remains the A/B
reference arm (0.998 coverage / 0.404 p_e p99) and the Jun-06 report
stays the correct documentation for that configuration.YAMLs_by_domain/parameters.yaml (adopted
knobs).GuidanceMode
enum and CameraPose (member names from usage),
BaseGuidance/COMGuidance progress machinery
(_current_progress), the controller loop.docs/report_images/STARTUP.png is the pre-Claude
(codex-era) dispatcher diagram — ~20 nodes, crossing edges, three
startup sub-behaviors. It documents a machine that was retired on Jun 6;
nothing in it survives. It is the “before” picture.At every control step the guidance asks one question — where is
the vehicle along its orbit? — and aims the camera at the
pre-computed surface path point for that progress
(x_surf(s_achieved)), from a fixed 0.275 m standoff sphere
around the spacecraft’s center of mass. Achieved progress (not
wall-clock time) drives the schedule, so the aim never outruns the
vehicle. During the first 90 s (INITIAL), the same aim runs while the
controller settles — the existing pose filter slews the camera smoothly
from its boot posture to the path, the camera marks coverage the whole
time, and a posture term keeps the elbow away from its singular
configuration. At step 3000 the mode label flips to TARGETING and
nothing else changes — the same aim function serves both phases
(:625 vs :639, same
orbit_path_pose, different mode argument). The
mission ends when achieved progress reaches the end of the helix (~1064
s).
stateDiagram-v2
direction LR
[*] --> INITIAL : step 0 (q0 pose seeds the filter)
INITIAL --> TARGETING : step 3000 (90 s settle elapsed)
TARGETING --> [*] : orbit progress complete (~1064 s)
INITIAL : steps 1..2999
INITIAL : aim at x_surf(progress) + mark coverage
INITIAL : full-arm posture pull toward q0
TARGETING : steps 3000..end
TARGETING : same aim function, same marking
note right of TARGETING
no HOLD, no FALLBACK,
no reselect events
end note
The transition is scheduled, not decided —
step_idx >= startup.steps_effective (:284-286). Compare the
Jun-06 diagram: 4 states and 6 event-driven transitions (score margins,
forced reselects, feasibility checks). All of those decisions are gone
from the live path.
set_ee_target (:611)The function is a four-rung ladder of early returns, read top to bottom. Under mission defaults only the green rungs ever fire after step 0:
flowchart TD
A["compute q0 default pose<br/>(always, keeps the fallback fresh) :616"]
A --> B{"aiming during INITIAL<br/>and step >= 1<br/>and still settling? :620"}
B -- yes --> C["return orbit_path_pose(mode=INITIAL) :625"]
B -- no --> D{"guidance disabled or<br/>still settling (aim off)? :627"}
D -- yes --> E["return q0 default pose :635"]
D -- no --> F{"orbit path enabled? :638"}
F -- yes --> G["return orbit_path_pose(mode=TARGETING) :639"]
F -- no --> H["external: legacy reactive machine<br/>(HOLD / TARGETING / FALLBACK, Jun-06 report)"]
classDef live fill:#d4edda,stroke:#28a745,color:#0f3d1e;
classDef external fill:#fff3cd,stroke:#d39e00,color:#3d2b00;
class C,G live;
class H external;
Mission config: steps 1–2999 exit at the first rung (C); step 3000 onward exits at the third (G). The q0 default (A→E) serves exactly one live step — step 0, which seeds the pose filter at the true end-effector pose so the slew toward the path starts continuously.
flowchart LR
A["controller calls<br/>add_ee_goal :174"] --> B["set_ee_target<br/>(ladder above)"]
B --> C["consistent_finalize_pose<br/>filter + reach clamp"]
C --> D["write Desired<br/>(p_e, R_e, z_e)"]
D --> E["external: controller marks<br/>camera FOV coverage :156"]
classDef external fill:#fff3cd,stroke:#d39e00,color:#3d2b00;
class E external;
Unchanged from Jun 06 and still the design’s best property: every branch’s pose flows through the same single finalizer (low-pass + rate caps + reach clamp). What changed is the marking gate at the end: it now also marks during INITIAL — but only when the path is aiming (breve_controller.py:156; the “mark iff aiming” contract, ee_guidance.py:30,106).
| Mode | Old role (Jun 06, reactive) | New role (Mission-1 defaults) |
|---|---|---|
| INITIAL | 90 s hold at the boot arm pose; camera aimed at nothing; zero coverage | 90 s settle while aiming and marking the dense southern revs (~0.59 coverage by t=60 s) |
| HOLD | the sustained inspection state (40,928/50,000 steps): stare at one chosen surface point | unreachable (dormant code) |
| TARGETING | 1-step commit pulse when a new target won the score (69 steps) | the sustained state: continuous path-following inspection (~32,500 steps) |
| FALLBACK | safety revert when reselect found nothing (3 steps) | unreachable (dormant code) |
Why it changed: the reactive machine chose where to look by scoring candidate targets each reselect window. The orbit-path schedule answers that question offline — the path is computed once at construction by projecting the orbit onto the target surface — so the run-time machine has nothing left to decide. The scorer’s coverage instinct (0.998) was matched and exceeded (0.9990) by simply flying the whole schedule and looking the whole time, while the reselect jumps that caused the old tracking spikes (p_e p99 0.404) disappeared outright (0.165).
The Jun-06 report is not wrong — it is now
conditional. Flip orbit_path.enable: false and its
machine, numbers, and diagrams apply again verbatim; that configuration
is retained as the A/B reference arm.
F1 — Mode semantics inverted: TARGETING is now sustained, HOLD never occurs. Evidence: mission mode histogram INITIAL 3,000 / TARGETING ~32,500 / HOLD 0 / FALLBACK 0 (C4 verdict run); old histogram HOLD 40,928 / TARGETING 69 (Jun-06 report). Impact: any script, plot, or mental model keyed on “HOLD = inspection, TARGETING = rare pulse” silently inverts. The Jun-06 report’s F1 lesson now applies in mirror image. Next step: recorded here; see task T1.
F2 — The repo’s front-door diagram is stale.
GNC/CLAUDE_README.md (lines 4-22) still shows the old
4-mode/6-edge machine as “the state machine.” Evidence:
compared against ee_guidance.py:611-648
under adopted defaults. Impact: the first thing a new reader
(or supervisor) meets contradicts the running system. Next
step: task T1 (report-only rule: not edited here).
F3 — set_ee_target carries its own follow-up
note. The code comment at :610 (“repeated
terminal exits should be helpers”) plus five adoption knobs that imply
one another suggest the planned knob-consolidation (single mode enum)
would also collapse the ladder’s first two rungs into one.
Impact: low — clarity debt, not behavior. Next step:
already pinned in tasks/PIN_IT_FOR_LATER.md (knob
consolidation).
No code was modified during this investigation (report-only).