com_guidance — COMGuidance + COMController
Purpose
Per-step desired CoM state
(p_c, v_c, a_c)from the discrete helix orbit: a lookahead velocity
field with monotonic progress tracking, a startup speed ramp, and low-pass reference smoothing.
The root of the guidance tower — base attitude and EE pose are layered on top.
Since Jun25 (e14ee16) the file also hostsCOMController— the CoM force law, extracted from the
control loop and composed by com_controller asself.com. Two classes, one file: the CoM reference
(guidance) and the law that regulates against it (control), co-located. See the COMController section below.
Role in the system
- Root of the deep guidance chain: base_guidance
extendsCOMGuidance, and ee_guidanceextendsbase_guidance. - Reference is consumed by the control tower → breve_controller (and com_controller) regulate the CoM force loop against
p_c/v_c/a_c. - Orbit geometry comes from
OrbitGenerator(utils/orbit.py); progress projection fromclosest_point_on_segment_polyline(utils/curvature.py). - The cached
a_c0seeds the analytic feedforward warm-start in analytic_feedforward.
Inputs / Outputs
- In: current CoM position
p_c, timet, the previous desired (des_prev) for smoothing; config (guidance.com.tracking,controller.com.startup,constraints.com). - Out:
Desired(p_c, v_c, a_c)— the tracked point, lookahead velocity, and centripetal acceleration demand — plus the guidance log fields (p_cd,v_cd,kappa_cd,z_bd, progress).
Key methods
desired_at_window— the velocity-field core: monotonic progress → lookahead tangent →(p,v,a)—GNC/com_guidance.py:171build_com_desired_for_step— live per-step entry (ramped speed + optional smoothing) —:90smooth_desired_com_reference— low-passv_c, rebuilda_c = (v_smooth−v_prev)/dt—:44startup_speed_scale—exp_scalelaunch ramp, gated oncontroller.com.startup.enable—:39desired_com_start— t=0 seed that cachesa_c(0)for the feedforward warm-start —:111orbit_duration— curvature-limited arc-time oracle (v ≤ √(a_ff_max/κ)) —:134
Footguns
Progress is strictly monotonic — never regress
progress_phase = max(progress_prev, progress_geom): once a segment is passed, guidance refuses to
walk backward. This re-centers the cheap local search window (search_windowradius) each step;
the full-orbit polyline scan runs only once per run. (GNC/INSIGHTS.md[guidance])
a_tcd = v_mag² · κis centripetal feedforward, NOT a position-error termThe acceleration demand pre-loads the CoM force against orbit curvature — it is the §5.3 term, not
a tracking correction. Don’t confuse it with the lateral/along-track error blends. (GNC/INSIGHTS.md[frame])
Startup ramp must be owned in one place
Both the live path (
build_com_desired_for_step) and the t=0 seed (desired_com_start) call
startup_speed_scale, so the initial state and the ramp agree. With the launch ramp on,a_c(0) ≈ 0
(the FF is effectively ramped twice); with it off,a_c(0)is the full curvature demand. (GNC/INSIGHTS.md[guidance])
Orbit-synced termination replaced the orbit-end brake (
8d24ad9)The mission now ends when the CoM has traversed the orbit (
orbit_complete; the loop breaks in
ControlLoop.run_control_loop) instead of running a fixedduration— removing the ~397 s overrun whose
abrupt stop produced the orbit-end CoM spike. The formerbrake_decelband-aid (a constant-deceleration
speed cap near the end) thus became redundant and was deleted;desired_at_windowkeeps only the one-step
reach capv_cmd ≤ d_end/dt. See com_breve_decoupling + Jun25 CLAIMS.
Pseudocode (one guidance step)
v_d = desired_speed * startup_speed_scale(t) # exp launch ramp (eq 5.1)
prog = max(prev_progress, project(p_c → local window)) # monotonic; local search only
ref = orbit.sample_analytic(prog + v_d·t_look/ds) # lookahead point: tangent t̂, curvature κ
e = p_track − p_c ; e_along, e_lateral split on t̂
d = t̂ + k_track·e_lateral # cross-track blend into direction
v_cmd = clamp(v_d − k_progress·e_along, dist_to_end/dt) # along-track speed; no terminal overshoot
v_c = v_cmd · d̂ ; a_c = ‖v_c‖²·κ # centripetal FF (eq 5.3)
if smooth: low-pass v_c, rebuild a_c = (v_smooth−v_prev)/dt # saturate vs v_max, v_dot_max
Equations & references
Key equations mirrored from current_sota — the math source of truth; see there for derivations.
Startup speed ramp — §5.1, eq (5.1):
Centripetal acceleration feedforward — §5.2, eq (5.3):
Analytic helix curvature (radial part projected out) — §5.2, eq (5.5):
Orbit-end brake (constant-deceleration speed cap) — kinematic, project-adopted Jun25:
References:
- CoM orbit reference + startup ramp (§5.1, eq 5.1): current_sota > 5.
- Centripetal acceleration feedforward
a_cd = ‖v_cd‖²κ(§5.2–5.3, eq 5.3): current_sota > 5.
COMController — the composed CoM force law
Second class in this file
COMControlleris the CoM force law: feedforward + PD feedback + integral (anti-wound), saturated to
F_max. Composed by com_controller (ControlLoop) asself.com— has-a, not is-a — holding the
loop’srobot/motion_cache/uncertainty/trajby reference so it reads the same per-step state the
loop mutates. Extracted Jun25 (e14ee16, byte-identical: base + ee_coverage0.000e+00).
compute_f_c_terms— packageff + fb + i, saturateF_max, add force noise —GNC/com_guidance.py:328feedforward_accel— warm-start from cacheda_c(0), exp-ramp to the live demand —:318f_c_fb— PD feedback−K_c x̃_c − D_c ẋ̃_c—:312x_c_tilde/x_c_tilde_dot— CoM position / velocity error (belief side; the manipulator RHS readsx_c_tilde_dot) —:295/:303clamp_com_integral/_update_com_integral_state— anti-windup (OFF by default) —:287/:348
CoM force law (PD on the centroid) — §4.2, eq (4.4):
The decoupled CoM Newton equation m v̇_c = f_c and the closed-loop error dynamics are detailed in
com_controller > Equations & references and §3.
Related
base_guidance · ee_guidance · analytic_feedforward · breve_controller · com_controller · terminology · com_vs_base · orbit_com_path