Skip to content

diskmargin: auto-compute MIMO frequency-grid bounds by default#151

Merged
baggepinnen merged 1 commit into
masterfrom
fix/diskmargin-auto-freq-bounds
Jun 24, 2026
Merged

diskmargin: auto-compute MIMO frequency-grid bounds by default#151
baggepinnen merged 1 commit into
masterfrom
fix/diskmargin-auto-freq-bounds

Conversation

@baggepinnen

Copy link
Copy Markdown
Member

Motivation

The MIMO diskmargin searched a fixed log-spaced frequency grid l=1e-3 … u=1e3 rad/s (500 points). When the worst-case disk margin lies near or beyond a bound, the reported worst-case frequency lands exactly on the grid edge (e.g. u=1000.0 rad/s) — a grid artifact rather than a true interior minimum. This corrupts derived quantities, in particular the delay margin (phase_margin / ω_crit), where dividing by an artificially-fixed crossover frequency gives a misleading value.

Change

  • Default l and u to nothing in diskmargin(L; l, u) and sim_diskmargin(L, σ, l, u).
  • When a bound is nothing, derive it from the poles/zeros of L via ControlSystemsBase._bounds_and_features(L, Val{:nyquist}()) — the same heuristic ControlSystems uses to pick frequency ranges for Bode/Nyquist plots, padded around the extreme dynamics with high-frequency headroom and clamped to Nyquist for discrete systems.
  • Explicit l/u still override (backward compatible).
  • Particle/uncertain systems are already covered by the existing _bounds_and_features specialization in uncertainty_interface.jl.

Only the scalar-l/u path is affected; all AbstractVector-grid callers (e.g. diskmargin(P,C,σ,w)) are unchanged.

Tests

test/test_diskmargin.jl passes locally. The discrete default-grid regression test's reference grid was made dense and Nyquist-relative so the comparison is robust to the now system-derived bounds.

🤖 Generated with Claude Code

The MIMO diskmargin searched a fixed grid l=1e-3..u=1e3 rad/s. When the
worst-case margin lay near a bound, the reported worst-case frequency pinned
to the grid edge (e.g. exactly 1000.0 rad/s), corrupting derived quantities
such as the delay margin (phase_margin/ω_crit).

Default l and u to `nothing`; when unset, derive them from the poles/zeros of
L via ControlSystemsBase._bounds_and_features(L, Val{:nyquist}()), the same
heuristic used for Bode/Nyquist plots. Explicit l/u still override.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.85%. Comparing base (ce8094d) to head (dffd616).

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #151      +/-   ##
==========================================
+ Coverage   91.84%   91.85%   +0.01%     
==========================================
  Files          20       20              
  Lines        3067     3071       +4     
==========================================
+ Hits         2817     2821       +4     
  Misses        250      250              
Flag Coverage Δ
unittests 91.85% <100.00%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@baggepinnen baggepinnen merged commit ee07234 into master Jun 24, 2026
2 checks passed
@baggepinnen baggepinnen deleted the fix/diskmargin-auto-freq-bounds branch June 24, 2026 08:27
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.

2 participants