plotter3d — interactive 3-D trajectory plots + report-figure generators
Purpose
Two unrelated jobs in one file.
Plotter3Ddraws interactive 3-D base-CoM / EE trajectories
with pointing-axis quivers (a debugging viewer). The module-levelfig_*functions are
standalone report-figure generators that rebuild their geometry live fromparameters.yaml
and write the week-2 paper figures.
Role in the system
- A standalone visualization helper in utils — not on the control/guidance hot path.
Plotter3Dconsumes a log object exposingp_actual/p_desired/z_actual/z_desired
(and optionalp_e*/z_e*for EE) — the interactive eyeball view, no pipeline provenance.- The
fig_*generators pull live geometry from orbit (OrbitGenerator) and mesh (Mesh)
via_setup, and the coverage figure reuses geometry’ssafe_normalizeand the mesh ray-cast
scene — so nothing is hard-coded. - Run directly:
python utils/plotter3d.pywrites the three figures intodocs/week2/report_v2/figures/.
Not the sanctioned figure path
Pipeline figures render through
analysis/plotter.py(the matplotlib-only home, hook-enforced).
This file imports matplotlib directly because it lives inutils/, notGNC//validation/, and
these are one-off paper schematics built outside the run→log→analyze pipeline — they carry no
scoreboard provenance. See orchestrator /.claude/rules/MEASUREMENT.mdfor the catalog path.
Inputs / Outputs
Plotter3Din: a log/record withp_actual,p_desired, optionalz_*andp_e*/z_e*
arrays (shape(N,3)); out: an interactive matplotlib window (plt.show()), no file.fig_*in: an output path + figure-only knobs (helixn_rev, frame/point counts); out:
PNG/GIF on disk, plus a dict of the live-computed annotation values (rho,r_cam, coverage).
Key methods / functions
Plotter3D.plot_combined— base-CoM + every available EE trajectory together, each with quivers —utils/plotter3d.py:164Plotter3D.plot_base_com— actual vs desired base-CoM with base-pointing quivers —utils/plotter3d.py:83Plotter3D.plot_quiver— the strided pointing-axis quiver primitive (shared by the plots) —utils/plotter3d.py:65fig_standoff— POSE-mode standoff/pointing schematic (sec 5.3) —utils/plotter3d.py:340fig_coverage— cumulative inspection-coverage GIF+PNG (sec 4.4) —utils/plotter3d.py:405fig_progress— progress-coloured helix + along-/cross-track error panel (sec 1) —utils/plotter3d.py:526_setup— load config + orbit + mesh once;n_revoverride is figures-only —utils/plotter3d.py:327
Footguns
The standoff schematic is deliberately not to scale
r_camis only ~5% ofrho; a to-scale view collapses the standoff construction.fig_standoff
drawsr_camexaggerated but annotates the live-computedrho/r_camso the caption stays
numerically correct. Read the numbers, not the proportions. (utils/INSIGHTS.md[plotting])
Coverage fraction is a real estimator, not a cartoon
fig_coveragesamples the mesh area-uniformly (Mesh.sample), soseen/totalis an unbiased
estimate of inspected-area fraction, and the predicate is the codebase’s own FOV-cone + depth-band
- unoccluded-LoS test (not a bespoke approximation). The colorbar is pinned to
[0, vmax]so every
frame shares one axis. (utils/INSIGHTS.md[plotting])
Pseudocode (report-figure entrypoint)
__main__: switch backend -> Agg, mkdir figures/
fig_standoff(...) # schematic geometry, exaggerated r_cam, live rho annotation
fig_coverage(...) # marking pass over the helix -> per-frame cumulative counts -> GIF + final PNG
fig_progress(...) # helix coloured by orbit progress + 2D along-/cross-track error panel
# each fig_* calls _setup() -> live (cfg, orbit, mesh); notation tracks final.tex secs 1, 4.4, 5.3
Related
orbit · mesh · geometry · plotter · orchestrator · terminology