Repository navigation
fix(autotune): closed-loop simulation and stability margins - #56
Merged
Merged
Conversation
The identified coefficients are in powers of z^-1 but ctrl.TransferFunction interprets them in powers of z, so models with more poles than zeros were simulated with n - m extra samples of delay. This skewed the parameter search fit, the replay and the closed-loop PID simulation.
The ARX model delay belongs to the plant, but the closed-loop simulation applied it to the reference only, and the disturbance simulation ignored it entirely. The step and disturbance responses were therefore only time-shifted and did not show the loss of damping the delay causes, making the tuning look better than it is.
The "open loop" was obtained by removing the error summing junction, but the D term (and the P term with PI no-zero) acts on the feedback signal and stayed in the loop. The margins were then those of a partially closed loop covering only part of the controller, and could be very optimistic, even reporting comfortable margins for an unstable design. Build the loop gain directly as sign * Kp * (1 + I + D) * G * z^-(d+1): where P and D are applied only changes the reference path, not the loop.
The signals were reshaped into column vectors before being passed to the fit, so every sample assignment in the filters converted a 1-element array to a scalar. NumPy deprecates this (and will make it an error), and it emitted two warnings per sample.
The grid went up to 1000 rad/s regardless of the sample time, above the Nyquist frequency for any dt > 3.1 ms, where the discrete-time response has no meaning and python-control warns.
python-control's default method switches from the polynomial to the frequency-response method when it expects numerical trouble, which is the case for most identified loops, and warns every time. Use the frequency-response method directly on a dense grid up to Nyquist: the margins match the polynomial method where that one is accurate.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes to the closed-loop simulation and the stability margins, which could be very optimistic and report comfortable margins for an unstable design, plus warning/crash fixes.
Simulation and margins
ctrl.TransferFunctionreads them in powers of z, so models with more poles than zeros had n − m extra samples of delay.sign · Kp(1 + I + D) · G · z^-(d+1). The "open loop" was built by removing the error junction, but D (and P with PI no-zero) act on the feedback and stayed in the loop. The margins then covered only part of the controller.Example on a synthetic plant, K = (0.8, 0.3, 0.02):
With K = (1.5, 0.5, 0.08) the old code reported PM 113°. The closed loop actually has a pole at |z| = 1.19, and the new margins are negative.
For all combinations of delay, PI no-zero and negated output, the closed-loop poles contain the roots of 1 + L.
Warnings
Testing
logs/: no warnings, and the identification fit is unchanged.