com_vs_base — COM vs base: two distinct points the GNC stack regulates

Concept

The whole-system center of mass (p_c) and the actuated free-flyer base body are different
points
: kinematically distinct, dynamically coupled through Γ. Each has its own guidance layer and
its own control loop. This page exists because conflating them mis-attributes effects — e.g. blaming
“the base” for a CoM-loop behaviour, or reading base-attitude wobble as a CoM-position error. No single
file owns the distinction, so this documents the whole while the per-file pages document the parts.

What this spans

  • utils/robot.py (robot) — computes both points in one FK pass and the Γ map that couples them.
  • GNC/com_controller.py (com_controller) — the CoM force loop (regulates p_c/v_c), control-chain root.
  • GNC/base_controller.py (base_controller) — base-attitude-only diagnostic controller (regulates z_b/omega_b).
  • GNC/com_guidance.py (com_guidance) — the CoM orbit reference (p_c, v_c, a_c), guidance-tower root.
  • GNC/base_guidance.py (base_guidance) — the desired base attitude (R_b, z_b, omega_b) layered on top.
  • Thesis: p_c (CoM position) and the base body are not interchangeable; every metric measures one
    of them — p_c/v_c are CoM, z_b/omega_b are base — and the only thing linking them is Γ.

Constituent pages

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

  • robot — computes p_c and assembles Γ (the single coupling map); owns the dynamics, not the controllers.
  • com_controller — the CoM force loop (f_c → Γᵀ → (f_b, τ_b, τ)); root of the control chain.
  • base_controller — base-attitude-only mode (every EE/arm slot zeroed); diagnostic, not the live controller.
  • com_guidance — desired CoM state along the helix orbit; root of the guidance tower.
  • base_guidance — desired base attitude (inward z_b, roll-continuous frame) added on top of the CoM reference.

Mechanism (where it lives in code)

The two points are born in the same FK pass, then regulated by separate loops the Γ map ties together:

  • CoM p_c — whole-system center of mass, inertial frame; shifts as the arm moves (Pinocchio data.com[0]) — utils/robot.py:137
  • Base pose — the actuated 6-DOF body: p_tb/R_tb and the local omega_b from the same pass — utils/robot.py:135 / utils/robot.py:143
  • The couplingΓ stacks [v_c; omega_b; ν_e⊕]; its top block maps [v_b; omega_b; q̇] → v_c, so base + arm velocities both feed the CoM — utils/robot.py:294
  • Γ assembly + s_min_G — the full 12×(6+n) stack and its smallest singular value (the one conditioning witness) — utils/robot.py:297 / utils/robot.py:298
  • CoM reference — desired (p_c, v_c, a_c) along the orbit — GNC/com_guidance.py:170
  • CoM controlf_c package mapped through Γᵀ into generalized forces — GNC/com_controller.py:201
  • Base-attitude reference — desired R_b/z_b/omega_b layered on the CoM desired — GNC/base_guidance.py:114
  • Base-attitude controlτ_b⊕ PD on the base attitude error (EE/arm slots zeroed in the diagnostic mode) — GNC/base_controller.py:66

Evidence

Purely structural: the separation is enforced by where each quantity is computed and logged, not by a
single run. p_c and the base pose come from one FK pass (utils/robot.py:137 vs :135); v_c is the
Γ top block (utils/robot.py:294); the base-only controller proves the two loops are independent by
zeroing every EE/arm slot yet still flying the base (GNC/base_controller.py:66, byte-identical baseline
per base_controller). The wider history of not conflating them is recorded in GNC/INSIGHTS.md
([frame], [control]) and the operational-regime note (the tracked error is a CoM-velocity lag, not the
base-attitude oscillation — see com_controller “CoM integral is OFF by default”).

Footguns

Name the quantity — p_c/v_c are CoM, z_b/omega_b are base

A reader seeing only one file routinely mis-attributes a CoM effect to “the base” (or vice versa). State
explicitly which point each metric measures: p_c = CoM position, v_c = CoM velocity,
z_b = base attitude (a pointing axis), omega_b = base angular rate. The CoM shifts as the arm
moves
(utils/robot.py:137), so a “position drift” can be pure arm motion with the base perfectly still.

Tikhonov / derate damping acts on Γ (the CoM-coupling map), not on "the base"

The conditioning ramp and the Tikhonov Γ regularization key off s_min_G (utils/robot.py:298) — the
singular value of the coordinated map that couples base+arm into v_c. Calling that “base damping” is
the exact conflation this page guards against; base angular damping is a separate term riding τ_b⊕
(see base_controller “Base damping rides τ_b⊕”). Sibling/dependency of tikhonov_regularization.

The base controller flies the base only — don't read its logs as CoM results

base_controller zeroes every EE/arm slot (GNC/base_controller.py:66); it regulates base attitude
against base_guidance with no EE layer. Its diagnostics speak to z_b/omega_b, never to EE
pose or CoM tracking quality. (GNC/INSIGHTS.md [control])

Equations & references

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

Block-diagonal split (the CoM decouples from the attitude+EE block) — §3, eqs (3.1–3.2):

Decoupled CoM Newton equation§3, eq (3.3):

References:

  • Coordinated map Γ + circumcentroidal velocities (the v_c/ω_b/ν_e⊕ split, eqs 2.1–2.3): current_sota > 2 · utils/robot.py:294.
  • Reduced EoM in coordinates (/Ĉ, the dynamic coupling): current_sota > 3 · utils/robot.py:297.
  • eq↔code cross-check: generated_reports/GNC/cross_check.md.

tikhonov_regularization · circumcentroidal_control · coupled_dynamics · robot · com_controller · base_controller · com_guidance · base_guidance · terminology