Control System Designer: Inconsistent Controller Output Step Response

I use the control system designer with e.g simple plant and controller:
s = tf('s')
G = 1/(s+1)
C = 1/s;
controlSystemDesigner(G,C);
and the default control system architecture
After adding the step reponses
(via selection from step reponses) and
via:
I expected them to be the same responses (since du is probably 0).
The response is correct, however is wrong (unbounded) and differs from :
Is this a bug?
Best regards
Markus

 Accepted Answer

I can recreate these result and uc/r certainly looks incorrect. After exporting the systems to the base workspace I get:
>> tf(IOTransfer1)
ans =
From input "r" to output "u":
s + 1
-----------
s^2 + s + 1
Continuous-time transfer function.
Model Properties
>> tf(IOTransfer2)
ans =
From input "r" to output "uC":
s + 1
---------
s^2 + 2 s
IOTransfer2 surely is incorrect and I can't figure out how such a result was obtained.

15 Comments

The result can be obtained if one has H(s) = s
s = tf('s');
G = 1/(s+1);
C = 1/s;
H = s;
feedback(C,G*H)
ans = s + 1 --------- s^2 + 2 s Continuous-time transfer function.
Though I have no idea where H = s would come from.
Also, the transfer function from du to uc is incorrect
>> tf(IOTransfer4)
ans =
From input "du" to output "uC":
-1
---------
s^2 + 2 s
Continuous-time transfer function.
However, assuming H(s) = s does NOT obtain this result.
Dear @Paul, thanks for your further investigations! After sleeping a night and thinking about the problem I think the root cause might be an incorrect sensitivity function in Control System Designers source code:
% Calculate transfer functions to uC
% ...
Swrong = 1/(1+G*H); % should be 1/(1+L) = 1/(1+G*C*H)
r2uC = minreal(C*Swrong*F);
du2uC = minreal(-C*H*G*Swrong);
% ... other inputs to uC
This would align with your observations and could be introduced by mistake.
The incorrect sensitivity function seems to appear only when using uC as an output, I did not check much other cases though.
Could this be verified by Mathworks?
That incorrect sensitivity function explains both cases that I checked (Uc(s)/R(s), Uc(s)/Du(s) ). Good find!
The error can be verified by Mathworks if you file a bug report, and I encourage you to do so (Contact Support - MATLAB & Simulink). You can include a link to this thread in the report if you'd like and provide any other useful information. If you do file a report, would you mind posting back here a brief summary of their response?
Based only on how you've described how the tool works, I'm quite surprised that Swrong (I hope that's not what it's called in the actual code!) only is used when uC is an output. Seems like S = 1/(1 + G*C*H) would be a fundamental term that can be used to compute any closed-loop transfer function in the system. That is, from what you've described it seems like the strategy could have been to compute S once, and then multiply it by the forward path gain for any I/O pair and then use minreal. Any idea how U(s)/R(s) is (correctly) computed?
I am extremely surprised that the tool uses "transfer function algebra," insofar as the documentation explicitly states: Avoid closed-form expressions and transfer function algebra.
Hi @Paul, thanks for the tips. I created a bug report here
% >> Based only on how [you've described how the tool works,' ...
% I'm quite surprised that Swrong (I hope that's not what it's called in the actual code!)
% only is used when uC is an output.
% Seems like S = 1/(1 + G*C*H) would be a fundamental term that can be used
% to compute any closed-loop transfer function in the system.
Probably because sensitivity functions are differently orderered for MIMO systems. For SISO systems, yes I think one global sensitivity function could be used.
% >> Any idea how U(s)/R(s) is (correctly) computed?
Yes
% >> I am extremely surprised that the tool uses "transfer function algebra,"
% insofar as the documentation explicitly states: [link]
It was just an example and a guess from my side. Might be coded with non transfer function algebra, but the same error could have happened (C was forgotten in the feedback loop for S). Or could be another root cause.
Glad that you discovered this issue. You should also check other IOTransfer as well. For example, in the 1st architecture, between the error signal e and the controller output u, there is no loop. Rather, the relationship is described solely by , and yet ...
Note: This result was generated using MATLAB R2017a version.
Hi @Sam Chak, you are right it should be , but controlSystemDesigner got this one wrong too, good finding! I might check other IOTransfer's as well, but I hope Mathworks will check these and other IO Transfer's too.
Edit: After Paul's comments, I saw that my statement regarding U(s)/E(s) was wrong. Matlab indeed returns the correct result for this path, since controlSystemDesigner adds an additive input at e and calculates the response regarding that additive input, which is correct.
For the case of U(s)/E(s), I think the tool adds an external input to the error signal (e) and then computes the closed loop transfer function from that input to the U(s). I didn't read the doc to determine if that's how it should work, but that would be my expectation based on how the Control System Toolbox works with analysis points. getIOTransfer
Fortunately, @Paul pointed this out. I'd prefer if the Control System Designer allowed us to choose between an open loop and a closed loop between the specifed input and output signals by selecting a checkbox.
Closed-loop TF (Architecture #1):
s = tf('s');
G = 1/(s+1)
C = 1/s
controlSystemDesigner(G,C)
Open loop TF (Architecture #1):
s = tf('s');
G = 1/(s+1)
C = 1/s
controlSystemDesigner(G,C,0)
I see, thanks @Paul for pointing this out. I already forgot about this. U(s)/E(s) returned by controlSystemDesigner is indeed correct then.
Nevertheless the responses returned by controlSystemDesigner when using uC as an output are still wrong, even when additive inputs are added to r or du(since it does not matter in these cases).
@Sam Chak controlSystemDesigner lets you choose to break the loop at specified points when retrieving a IOTransfer (see second image in this post) if open loop is needed.
Referring to this comment ...
Did you literally step through the controlSystemDesigner (CSD) code in the debugger (or use some other means to the examine the code) and see how r2uc and du2uc are computed?
Or are you only pointing out that r2uc and du2uc can be obtained if one does not include C(s) in the loop transfer function, regardless of how the the CSD code is actually implemented?
I'm asking because I'm very curious as to how such an error could arise. It certainly wouldn't arise if the CSD were implemented as I would have thought prior to seeing your findings.
@Paul, as a user I cannot see the source code or debug the internal code.
To summarize, I was pointing out, that r2uc and du2uc are definitely wroing. My guess is that they do not include C in the sensitivity function, see comment: Wrong Sensitivity. Where this comes from in the source code? No clue but I gave a guess.
Have you received confirmation of bug, or other closure, from Mathworks tech support?
@Paul, yes Mathworks has confirmed this as a bug, which will be investaged and fixed. If an external bug report is published I am going to link it to this thread.

Sign in to comment.

More Answers (0)

Products

Release

R2025a

Tags

Asked:

on 11 Sep 2025

Commented:

on 20 Oct 2025

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!