ee_feedforward — EE analytic feedforward into control

Concept

The end-effector feedforward: a desired EE twist ν_e (and its derivative) built in closed form from
the trajectory reference alone
, then folded into the controller’s reduced RHS so the stiffness loop holds
only the standing pose error instead of chasing the velocity/inertial demand. It spans guidance (where the
twist is computed) and control (where it enters the RHS), so the per-file pages document the parts and this
page documents the whole demand → fold path. Math source: current_sota > 5 §5.5–5.6.

What this spans

  • GNC/guidance/analytic_feedforward.py (analytic_feedforward) — the pure-kinematics closed form: from the
    CoM→surface vector r and its derivatives, build the reduced () EE twist ν_oplus and ν_oplus_dot.
  • GNC/guidance/ee_guidance.py (ee_guidance) — the call site that supplies the reference kinematics
    (r, r_dot, r_ddot, CoM v_cd, a_cd, reference frames) and returns (ν_local, ν_oplus, ν_oplus_dot).
  • GNC/breve_controller.py (breve_controller) — the consumer: gates analytic vs finite-difference FF,
    stores the twist, and folds the acceleration FF into the working control RHS.
  • Thesis: the EE feedforward is a demand-cancelling term sourced only from the reference — it carries
    the cruise velocity/inertial demand so the impedance loop is left to hold the residual standing error
    (the cruise-lag floor), not to track motion. “Lever E.”

Constituent pages

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

  • analytic_feedforward — the stateless closed-form module: reduced_desired_twist (twist + derivative),
    the unit-vector projector derivatives, the world→local rotation, the fold, and the cruise_lag_floor
    prediction. Every function is a function of the reference alone.
  • breve_controller — the live workhorse that gates the analytic path on, stores nu_e.oplus.{des,dot},
    and adds the acceleration FF into RHS34b.
  • ee_guidance — the guidance leaf that wires the reference kinematics into the closed form (the bridge
    between the two pages above).

Mechanism (where it lives in code)

The end-to-end demand → fold path, each step cited to live code:

  • closed form: reduced () EE twist + derivative from the reference — GNC/guidance/analytic_feedforward.py:110
  • call site: assemble r, r_dot, r_ddot, CoM v_cd, a_cd, reference frames, then call the closed form —
    GNC/guidance/ee_guidance.py:267 (invokes reduced_desired_twist at GNC/guidance/ee_guidance.py:293)
  • gate per step: analytic FF when _analytic_ff_on, else the finite-difference path — GNC/breve_controller.py:67
  • the gate predicate (key absence keeps FD unchanged) — GNC/breve_controller.py:564
  • store the reduced twist + derivative as the FF the RHS will add — GNC/breve_controller.py:105
  • acceleration FF term M̆ · [0 ; ν_oplus_dot], zero when disabled — GNC/breve_controller.py:345
  • folded into the working RHS (the FF is the final additive term) — GNC/breve_controller.py:377 (added at :411)

Two FF channels, one source

The closed form returns both a velocity twist ν_oplus (enters the RHS as the v̆_des reference the
damping is taken against, GNC/breve_controller.py:396) and its derivative ν_oplus_dot (the
acceleration FF rhs_feedforward, GNC/breve_controller.py:345). The FD path lacks a consistent
derivative; that is why the analytic derivative is the headline upgrade.

Evidence

  • Adopted default since 2026-06-21 (controller.arm.desired_twist.analytic_ff = true in parameters.yaml):
    the closed form replaced the FD path mission-wide (pe_median −28 %, pe_p99 −11 %, coverage up) at a bounded
    conditioning cost (s_min_G median 0.032→0.027); the 4 EE baselines + gold were re-pinned. Cited in
    analytic_feedforward from logs/logs_Jun21_26/CLAIMS.md.
  • The noise-robust “lever E” (analytic FF) variant is the one carried alongside gold in the Jun-21
    check-in overlay — it is the feedforward variant promoted to the default.
  • The why of the closed form, the frame-convention Coriolis term, and the POSE-only restriction:
    GNC/INSIGHTS.md ([math], [frame], [derate]).
  • Equation ↔ code cross-check for the desired-twist FF and its conversion:
    generated_reports/GNC/cross_check.md.

Footguns

FF is PURE reference, POSE-mode only — the controller silently falls back to FD elsewhere

The closed form assumes v_des = const, s_ddot = 0, ω_bd_dot ≈ 0, and a single aim point. In ANCHOR
the scorer picks a different target, so the closed form would not match the selected aim and ee_guidance
falls back to finite difference. The gate _analytic_ff_on (GNC/breve_controller.py:564) is config- and
mode-conditioned: a true analytic_ff flag is necessary but not sufficient. Reading only the flag will
mis-predict which FF channel is live. (GNC/INSIGHTS.md [math])

axis_only zeroes roll BEFORE the fold — and the linear block keeps one Coriolis term

The local roll rate (component 5) and its derivative are zeroed before the circumcentroidal fold (mirroring
the FD path’s nu_des[5] = 0); folding first leaks roll into the reduced twist. And differentiating a
body-frame quantity carries −ω_ed × p_ed_dot in the linear block (the angular block is clean). Dropping
either is a sign/convention footgun invisible from the controller side. (GNC/INSIGHTS.md [math] [frame])

The cruise-lag floor uses lstsq — derated steps must be filtered downstream

The companion cruise_lag_floor (GNC/guidance/analytic_feedforward.py:144, run by the controller as
x_ss_floor, GNC/breve_controller.py:352) solves the static balance with lstsq, so a near-singular
J_xᵀ K̆ returns the minimum-norm pose error rather than diverging. Such derated steps are meaningless
in the cruise comparison and must be filtered out. (GNC/INSIGHTS.md [footgun] [derate])

The acceleration FF only fires when its own flag is on

rhs_feedforward returns 0.0 unless controller.arm.accel_feedforward.enable
(GNC/breve_controller.py:347). The velocity twist ν_oplus always enters as the v̆_des reference; the
derivative (the inertial FF M̆·ν̇) is a separate switch. Do not assume “analytic FF on” implies the
acceleration term is active.

Equations & references

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

World-frame desired twist (one feeds all 6 DOF) — §5.5, eq (5.14):

Acceleration feedforward into the RHS ( frame) — §5.6, eq (5.18):

References:

  • Analytic desired twist (translational + rotational FF), §5.5: current_sota > 5 · GNC/guidance/analytic_feedforward.py:110.
  • Conversion to the circumcentroidal () frame, §5.6: current_sota > 5 · GNC/breve_controller.py:105.
  • The cruise-lag (steady-state) error floor the FF leaves behind, §4.5: current_sota > 4 ·
    GNC/guidance/analytic_feedforward.py:144 · eq↔code in generated_reports/GNC/cross_check.md.

analytic_feedforward · breve_controller · ee_guidance · circumcentroidal_control · com_guidance · current_sota · terminology