target_finding_coverage — where the camera looks, and how area coverage accrues

Concept

Two intertwined-but-separable jobs that no single file owns: target finding (the EE camera
deciding where to look) and coverage (accumulating which surface triangles the camera has
actually swept). They share one ground-truth (EETargetFinder’s per-triangle counts), so they read
like one mechanism — but in the adopted POSE default they are decoupled: the look-axis is
scheduled, and coverage accrues from the achieved trajectory, not from any selection decision.

What this spans

  • GNC/guidance/target_finder.py (target_finder) — owns the mesh, the ANCHOR-mode scorer, and the
    FOV coverage marker / area-coverage summary (the source of inspection.area_coverage_frac).
  • GNC/guidance/ee_guidance.py (ee_guidance) — runs target selection (the GuidanceMode branch)
    and the deterministic POSE aim path; the top of the guidance tower.
  • GNC/breve_controller.py (breve_controller) — marks FOV coverage every EE_COVERAGE_MARK_STRIDEth
    step from the actual camera pose, not the desired one.
  • Thesis: coverage is trajectory-driven, not selection-driven. In POSE mode the scorer is inert,
    yet area_coverage_frac → 1.0 over the full helix — so the lever for coverage is the orbit path, never
    the scoring weights or the reselect cadence.

Constituent pages

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

  • target_finder — mesh sampling, candidate scoring (ANCHOR-only), and the FOV raycast marker + area summary.
  • ee_guidance — the per-step pose decision: INITIAL → POSE / HOLD / TARGETING / FALLBACK.
  • breve_controller — the strided marking call from the achieved camera pose.

Mechanism (where it lives in code)

The end-to-end path — select a pose, then mark what the achieved pose actually saw:

Selection (one raw EE pose per step)

  • Step counter set, then branch into the pose decision — GNC/guidance/ee_guidance.py:216
  • Branch owner across all GuidanceModes — GNC/guidance/ee_guidance.py:699
  • POSE default: deterministic schedule, scorer never runs — GNC/guidance/ee_guidance.py:722
  • ANCHOR scorer entry (candidate poses around the anchor → best Selection) — GNC/guidance/target_finder.py:546
  • candidate hemisphere poses ranked by visible-target count — GNC/guidance/target_finder.py:126
  • position-only visibility gate (depth + incidence + line-of-sight) — GNC/guidance/target_finder.py:159
  • per-(target, pose) score across all terms — GNC/guidance/target_finder.py:360

Marking (accumulate coverage from the ACHIEVED pose)

  • stride constant — GNC/breve_controller.py:32
  • strided + mode-gated marking guard — GNC/breve_controller.py:132
  • mark from the actual camera pose (motion_cache.p_e, motion.R_te) — GNC/breve_controller.py:145
  • the raycast that increments per-triangle counts — GNC/breve_controller.py:146
  • pinhole-frustum raycast marker (the live coverage marker) — GNC/guidance/target_finder.py:201
  • area-weighted coverage summary (the reported metric) — GNC/guidance/target_finder.py:266

Reporting

  • area_coverage_frac logged into the inspection Package — analysis/logger.py:313
  • gate direction registered as higher-is-betteranalysis/pre_run_loader.py:423

Evidence

  • Mission headline: coverage 0.9990 at the adopted operating point (path + sync + aim + clip + INITIAL
    posture) — generated_reports/GNC/Jun10_26/mission_1_success.md (the >= 0.99 mission gate is met).
  • Coverage = orbit-traversal clock, not selection: full pole-to-pole helix → 1.0, short runs only sweep
    the southern cap (~0.47); the appendage-offset correlate was a red herring (detours cancel) —
    GNC/INSIGHTS.md [guidance] / [coverage].
  • Scorer is inert in POSE yet coverage still accrues — GNC/INSIGHTS.md [guidance] (lifted into
    target_finder > Footguns).

Footguns

Coverage is trajectory-driven — do NOT tune scoring to move it

In POSE (the adopted default) the pose is scheduled by orbit_path_pose and the
EETargetFinder scorer never runs (GNC/guidance/ee_guidance.py:722), yet area_coverage_frac
still climbs because compute_triangle_camera_visibility marks the FOV in every mode
(GNC/breve_controller.py:146). The lever for coverage is the orbit trajectory (full helix,
traversal completion), not the scoring.weights keys or the reselect cadence. (GNC/INSIGHTS.md [guidance])

Marking reads the ACHIEVED pose, not the desired one

The controller marks from motion_cache.p_e / motion.R_te (GNC/breve_controller.py:145), so a
tracking lag or derate shows up as missed triangles — coverage measures what the camera physically
swept, decoupled from what guidance asked for. It is strided (EE_COVERAGE_MARK_STRIDE = 5,
GNC/breve_controller.py:32) and gated to skip pure-INITIAL steps unless mark_during_initial
(CHAIN_4 aim-during-INITIAL); a guidance-only rollout that bypasses the controller marks nothing.

Two FOV definitions: don't invent a third

Both novelty scoring and area coverage read the same per-triangle counts (triangle_stats /
seen_triangles), so they share one ground truth. The pointing-error metric is the catalog versine
1 − cos θ and lives in the measurement layer, not here — never recompute coverage or pointing in an
ad-hoc script. (GNC/INSIGHTS.md; MEASUREMENT contract)

Equations & references

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

Area coverage (surface-area fraction seen ≥ once) — §7, eq (7.1):

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

References:

  • Per-triangle coverage marking + the area-coverage measure (eq 7.1): current_sota > 7 — implemented at
    GNC/guidance/target_finder.py:201 onward; analysis/logger.py:313 logs the reported fraction.
  • POSE-mode standoff pose (the scheduled aim point coverage rides on): current_sota > 5 (§5.4) —
    realized by orbit_path_pose (GNC/guidance/ee_guidance.py:684).
  • ANCHOR scoring law (inert in POSE): current_sota > 7 (weighted-product) · eq↔code in
    generated_reports/GNC/cross_check.md.

guidance_modes · orbit_com_path · target_finder · ee_guidance · breve_controller · terminology