Skip to content

LQR redesign for delay tolerance + velocity-aware catch condition (opt-in) - #4

Open
baggepinnen wants to merge 4 commits into
robust-swingupfrom
velocity-aware-switch
Open

LQR redesign for delay tolerance + velocity-aware catch condition (opt-in)#4
baggepinnen wants to merge 4 commits into
robust-swingupfrom
velocity-aware-switch

Conversation

@baggepinnen

@baggepinnen baggepinnen commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

Stacked on #3 (base branch robust-swingup; retarget to main after #3 merges).

Summary

Implements recommendation 2 of the robustness campaign (velocity-aware handover) and redesigns the LQR from the actual model linearization after the design work revealed the implemented gains were stale.

LQR redesign (robustness/08_lqr_redesign.jl)

The original LQRstabilizer gains (L₂ ≈ 394) did not correspond to any LQR design from this model's linearization with the weights documented in test/runtests.jl (fresh design at those weights: L₂ ≈ 120), and the loop had essentially no delay margin. New gains: discrete LQR with the documented output weights diag([1000, 10, 1, 1]) and control weight 300, selected by sweeping the control weight and validating candidates in simulation (classical margin numbers are misleading for this unstable plant).

Paired MC (300 identical draws, tf = 20 s, robust swingup config):

metric original gains redesigned
swingup success 93.0% 93.7%
swingup success, 1-sample actuation delay 57.0% 92.0%
swingup, 3-sample delay (nominal) fails at 1 sample catches at 5.8 s
LQR catch region (nominal / 1-sample delay) 142 / 8 of 625 179 / 191 of 625
catch capability at top (nominal / +20% mass) 2.5 / 2.5 rad/s 2.5 / 2.5 rad/s

The campaign harness pins the original gains in its "baseline" configs, so historical comparisons and the behavior-neutrality regression are unaffected (verified exact).

Velocity-aware catch condition (opt-in)

CatchCondition replaces the angle-only NearTop: optional gating of the handover on an ellipsoidal sublevel set V = eᵀSe ≤ c_engage of a Lyapunov function of the implemented LQR loop, with hysteresis release at c_release, calibrated for zero false positives against empirical catch-region grids of four perturbed plants (07_design_catch_condition.jl, recalibrated for the redesigned LQR: retains 63–68% of the catchable set, was 40–44%). With use_ellipsoid = false (default) behavior is identical to before.

Honest negative result in simulation: paired MC gives 85.7% for the gate (was 79.7% before the LQR redesign) vs 93.7% for the angle-only switch — the gate is computed from the nominal model, which is exactly what mismatch invalidates, and failed catch attempts are cheap in simulation. Loosening the thresholds made it worse (76.3%; subset-based tuning did not generalize). Benefits are qualitative and hardware-relevant: exactly one chatter-free engagement and mean arrival speed under half of the angle-only switch. Hence opt-in, trade-offs documented in robustness/README.md.

Verification

  • Behavior-neutrality regression passes exactly (pinned original controller reproduces the pre-change trajectory)
  • Out-of-the-box defaults (robust swingup + redesigned LQR) swing up and match the adaptive_ab_newlqr campaign config exactly
  • Opt-in gate swings up nominally with a single engagement at 1.06 rad/s arrival
  • Smoke tests: rec1_defaults_smoke.jl, rec2_vswitch_smoke.jl, candidate validation in 08b_lqr_candidates.jl

🤖 Generated with Claude Code

https://claude.ai/code/session_01NV21TmGAkB1uH6auMT78vj

baggepinnen and others added 3 commits July 10, 2026 11:47
Replaces NearTop with CatchCondition: optionally gates the swingup-to-LQR
handover on an ellipsoidal sublevel set V = e'Se <= c_engage of a Lyapunov
function of the implemented LQR loop, with hysteresis release at c_release.
S is designed in robustness/07_design_catch_condition.jl and calibrated for
zero false positives against the empirical catch-region grids of four
perturbed plants. With use_ellipsoid = false (the default) the component
reproduces the previous angle-only condition exactly.

The design script also revealed that the implemented LQR gains do not
correspond to a fresh LQR design from this model's linearization with the
documented weights, so the Lyapunov function is computed for the
implemented loop rather than from the design Riccati solution.

Evaluated with the paired Monte Carlo campaign (300 identical draws,
tf = 20 s): angle-only switch 93.0%, ellipsoidal gate 79.7% at the
zero-false-positive calibration and 76.3% loosened. The gate is computed
from the nominal model, which is exactly what mismatch invalidates, and in
simulation failed catch attempts are cheap, so refusing marginal attempts
costs success. Its benefits are qualitative: single chatter-free
engagement and mean arrival speed below half of the angle-only switch,
which matters on hardware where failed high-speed catch attempts stress
the system. Hence opt-in, with the trade-off documented in
robustness/README.md.

Verified: behavior-neutrality regression passes exactly; defaults
reproduce the previous behavior; the opt-in gate swings up nominally with
a single engagement.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NV21TmGAkB1uH6auMT78vj
The original LQRstabilizer gains did not correspond to any LQR design from
this model's linearization with the weights documented in test/runtests.jl
and the loop had no delay margin: one sample of actuation delay dropped the
swingup Monte Carlo success from 93.0% to 57.0%, and two samples failed
everywhere.

New gains (robustness/08_lqr_redesign.jl): discrete LQR with the documented
output weights and control weight 300, selected by sweeping the control
weight and validating each candidate in simulation (classical margin
numbers are misleading for this unstable plant). Results, paired MC at
tf = 20 s:

- swingup success 93.7% (was 93.0%)
- with 1-sample actuation delay 92.0% (was 57.0%); catches with 3 samples
- LQR catch region grows ~30% on all tested plants and 24x under delay
  (8/625 -> 191/625 grid points)
- equal catch capability at the top (2.5 rad/s, retained under +20% mass)

The ellipsoidal catch condition is recalibrated for the new loop (retains
63-68% of the catchable set, was 40-44%, zero false positives) and reaches
85.7% when opted in (was 79.7%) - still below the angle-only switch, which
remains the default. The campaign harness pins the original gains in its
"baseline" configs, so historical comparisons and the behavior-neutrality
regression are unaffected (verified exact).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NV21TmGAkB1uH6auMT78vj
@baggepinnen baggepinnen changed the title Velocity-aware ellipsoidal catch condition with hysteresis (opt-in) LQR redesign for delay tolerance + velocity-aware catch condition (opt-in) Jul 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant