orbit — spherical helix coverage orbit

Purpose

Generate a pole-to-pole spherical helix that the CoM follows to sweep the target for full coverage,
and expose its geometry two ways: an analytic (smooth, closed-form) sampler and a polyline
(uniform-arclength, index-addressable) path with per-sample tangents and curvature.

Role in the system

  • Instantiated by com_guidance (self.orbit = OrbitGenerator(cfg)), the only owner.
  • com_guidance calls sample_analytic for the moving reference point and reads .curvature over a window.
  • base_guidance reads .tangents / .curvature windows to build the base-attitude reference frame.
  • mesh’s SurfacePath projects this CoM orbit (.path, .arclength_samples) inward onto the satellite surface for the EE aim path.
  • Geometry is also imported live by plotter3d for the standoff / coverage report figures.

Inputs / Outputs

  • In: config (guidance.com.orbit: radius, path.psi_deg, path.n_rev) + simulation.time (duration, dt → N) + EPS.
  • Out: self.path (N×3 uniform-arclength polyline), self.tangents, self.curvature (N×3 vectors),
    self.u_samples (progress→helix-parameter table), self.helix cache; sample_analytic(progress) → Package(p, v, kappa).

Key methods

  • generate_coverage_orbit — build (once, cached) the resampled path + the analytic-sampler u-table — utils/orbit.py:27
  • sample_analytic — closed-form position / unit-tangent / curvature vector at a continuous progress index — utils/orbit.py:46
  • generate_spherical_helix — sample the analytic helix on the time grid; cache its helix coefficients — utils/orbit.py:75
  • resample_path_uniform_arclength — re-interpolate the raw path to N points uniform in arclength — utils/orbit.py:97
  • spherical_helix_curvature — analytic curvature magnitude at axial coordinate sutils/orbit.py:119
  • compute_curvature — polyline tangents + Frenet curvature vectors (run at construction) — utils/orbit.py:150

Footguns

Two curvature paths, two reasons

sample_analytic evaluates curvature in closed form to dodge the polyline finite-difference ripple
at segment crossings that would contaminate the reference signal; the cached self.curvature field is the
polyline Frenet form for windowed lookups. Don’t cross-wire them. (utils/INSIGHTS.md orbit [math])

Open path — never wrap terminal onto initial

Tangents and dt/ds use one-sided differences at the endpoints and centered differences in the interior;
the helix is an open pole-to-pole curve, so wrapping the last sample back onto the first would inject a
spurious jump. (utils/INSIGHTS.md orbit [math])

Pseudocode

# construction (compute_curvature → generate_coverage_orbit)
raw      = generate_spherical_helix()          # analytic samples on the time grid; cache self.helix
path     = resample_uniform_arclength(raw)     # N points, uniform ds
u_samples = interp(uniform_s → helix u∈[0,1])  # progress-index → helix parameter table
tangents, curvature = open-path FD + Frenet(spherical_helix_curvature)

# runtime (per guidance step)
sample_analytic(progress):
    u   = interp(progress → u_samples)         # uniform index → helix parameter
    θ,φ = θ_rate·u, φ0 + φ_rate·u              # both linear in u → constant-coeff derivatives
    p,dp,ddp = closed-form helix + du-derivatives
    κ_vec    = (ddp − (dp·ddp / |dp|²) dp) / |dp|²   # component of p'' ⟂ tangent, per ds²
    return Package(p, v=normalize(dp), kappa=κ_vec)

Equations & references

  • CoM orbit reference (§5.1) + analytic spherical-helix tangent & curvature (§5.2): current_sota > 5.

com_guidance · base_guidance · mesh · geometry · plotter3d · terminology · orbit_com_path