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 vectorrand its derivatives, build the reduced (⊕) EE twistν_oplusandν_oplus_dot.GNC/guidance/ee_guidance.py(ee_guidance) — the call site that supplies the reference kinematics
(r, r_dot, r_ddot, CoMv_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 thecruise_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 intoRHS34b. - 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, CoMv_cd, a_cd, reference frames, then call the closed form —
GNC/guidance/ee_guidance.py:267(invokesreduced_desired_twistatGNC/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 thev̆_desreference the
damping is taken against,GNC/breve_controller.py:396) and its derivativeν_oplus_dot(the
acceleration FFrhs_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 = trueinparameters.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_Gmedian 0.032→0.027); the 4 EE baselines + gold were re-pinned. Cited in
analytic_feedforward fromlogs/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 trueanalytic_ffflag is necessary but not sufficient. Reading only the flag will
mis-predict which FF channel is live. (GNC/INSIGHTS.md[math])
axis_onlyzeroes roll BEFORE the⊕fold — and the linear block keeps one Coriolis termThe local roll rate (component 5) and its derivative are zeroed before the circumcentroidal fold (mirroring
the FD path’snu_des[5] = 0); folding first leaks roll into the reduced twist. And differentiating a
body-frame quantity carries−ω_ed × p_ed_dotin 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 downstreamThe 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 withlstsq, 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_feedforwardreturns0.0unlesscontroller.arm.accel_feedforward.enable
(GNC/breve_controller.py:347). The velocity twistν_oplusalways enters as thev̆_desreference; the
derivative (the inertial FFM̆·ν̇) 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 ingenerated_reports/GNC/cross_check.md.
Related
analytic_feedforward · breve_controller · ee_guidance · circumcentroidal_control · com_guidance · current_sota · terminology