You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Elegant way to generate a transfer function matrix #325
You could try using parallel, series and feedback to construct the system. Alternatively, take a look at the append and connect commands? All of those should produce a system that doesn't involve creating extra states (unless you list one of the systems multiple times, which I guess is what is causing the problem above?).
# Create a 3 input, 3 output system consisting of component systems
sysvec = append(ss(W1), ss(W2), Gss)
# Add interconnections between the components (NB: indexing starts at 1)
# Input of G (3) is output of W1 (1), input of W2 (2) is G (3)
# Keep all inputs and outputs
P_ = connect(sysvec, [[3, 1], [2, 3]], [1, 2, 3], [1, 2, 3])
Note that this generates a minimal representation in the state space because we never create a copy of the plant (G) or weighting filters. So P_ has 4 states, 3 inputs, 3 outputs.
One annoying (and I think confusing) aspect of this construction is that the control.connect function uses indexing starting at 1 (to be compatible with MATLAB but also to allow negative feedback), while Python indexing normally starts at 0. This is documented in the connect function, but I still think it is confusing.
I may have misunderstood the transfer function matrix you were trying to create (I sketched it out on a napkin that I have since tossed -:). The main point is that you can use append to stack the system dynamics and then use connect to interconnect them.
I put this example into MATLAB (same exact commands) and got the output
P =
A =
x1
x1 -1
B =
u1 u2
x1 2 1
C =
x1
y1 0
y2 0
y3 1
D =
u1 u2
y1 2 0
y2 0 0
y3 0 0
When I run those commands in Python 3.5 using the current master (which should be the same as v0.8.2), I get output
A = [[-1.]]
B = [[2. 1.]]
C = [[0.]
[0.]
[1.]]
D = [[2. 0.]
[0. 0.]
[0. 0.]]
This matches the output of MATLAB, but is different than what you showed as your output. What version of python-control are you running?
There is still the issue that this is not the right system description for the block diagram. I think that part of the problem is that your interconnection matrix is not right. You have [[1, 2]] for the interconnection, which sets input 1 (G) to output 2 (W1). From the block diagram, what you want is [[2, 1]], so that the input of W1 (= input #2) is the output from G (output #1).
Running the command with the updated interconnection matrix gives
P = connect(sysvec, [[2, 1]], [2, 1], [2, 3, 1])
gives
A = [[-1.]]
B = [[0. 1.]]
C = [[2.]
[0.]
[1.]]
D = [[2. 0.]
[0. 0.]
[0. 0.]]
This is almost what you expect, except that the D matrix is not correct.
The problem is because of a limitations in the connect command (in MATLAB and Python):
The outputs for the connect command can only correspond to outputs from one of the subsystems. The output that you want for y in your diagram is the output of G plus the input z. But you can't actually do that with connect (in MATLAB or Python). So one problem is that the input u should be going to output v2 through a gain of 3. (That entry is missing in both the MATLAB and Python versions, for reasons that don't make senses.)
There is a similar constrain on the inputs. It is not possible to take an input from one system and map it to the input of another. So the only input to W2 is its natural input and we removed this from the transfer function.
Thanks @bnavigator. It would be useful to think about whether there is a nice way to do these sorts of manipulations. The construct that @iljastas gave at the start is really the best way since it creates copies of the system/weighting filters that are then "minimized" away, but it is also tedious to put in the extra elements that you used to get things to work.
I'd lover to hear suggestions about what a cleaner implementation would look like.
Maybe it would be useful to have a function combine() or something similar to mimic the Matrix combination of systems like in MATLAB. Here is a hack how that could look like. Of course it still needs all the type checks etc. to have it included into the StateSpace class:
importnumpyasnpfromcontrolimportStateSpace,tf,minrealfromcontrol.statespimport_convertToStateSpacedefcombine(systems):
""" systems: 2D array of systems to combine """rrows=[]
forsrowinsystems:
s1=srow[0]
ifnotisinstance(s1,StateSpace):
s1=_convertToStateSpace(s1)
fors2insrow[1:]:
ifnotisinstance(s2, StateSpace):
s2=_convertToStateSpace(s2)
ifs1.dt!=s2.dt:
raiseValueError("Systems must have the same time step")
n=s1.states+s2.statesm=s1.inputs+s2.inputsp=s1.outputsifs2.outputs!=p:
raiseValueError('inconsistent systems')
A=np.zeros((n, n))
B=np.zeros((n, m))
C=np.zeros((p, n))
D=np.zeros((p, m))
A[:s1.states, :s1.states] =s1.AA[s1.states:, s1.states:] =s2.AB[:s1.states, :s1.inputs] =s1.BB[s1.states:, s1.inputs:] =s2.BC[:, :s1.states] =s1.CC[:, s1.states:] =s2.CD[:, :s1.inputs] =s1.DD[:, s1.inputs:] =s2.Ds1=StateSpace(A,B,C,D,s1.dt)
rrows.append(s1)
r1=rrows[0]
forr2inrrows[1:]:
ifr1.dt!=r2.dt:
raiseValueError("Systems must have the same time step")
n=r1.states+r2.statesm=r1.inputsifr2.inputs!=m:
raiseValueError('inconsistent systems')
p=r1.outputs+r2.outputsA=np.zeros((n, n))
B=np.zeros((n, m))
C=np.zeros((p, n))
D=np.zeros((p, m))
A[:r1.states, :r1.states] =r1.AA[r1.states:, r1.states:] =r2.AB[:r1.states, :] =r1.BB[r1.states:, :] =r2.BC[:r1.outputs, :r1.states] =r1.CC[r1.outputs:, r1.states:] =r2.CD[:r1.outputs, :] =r1.DD[r1.outputs:, :] =r2.Dr1=StateSpace(A,B,C,D,r1.dt)
returnr1Gss=StateSpace([[-1.0, -10.0], [1, 0]], [[10.0], [0]], [0, 1], [0])
G=tf(Gss)
W1=tf([100], [0.1, 1])
W2=tf([100], [0.1, 1])
W2G=W2*GP11=np.block([[0,0],[W2G,W2]])
P12=np.block([[W1],[W2G]])
P21=np.block([[G,1]])
P22=np.block([[G]])
P_=np.block([[P11,P12],[P21,P22]])
Pc=combine(P_)
Pctf=minreal(tf(Pc))
output:
8 states have been removed from the model
Input 1 to output 1:
0
-
1
Input 1 to output 2:
1e+04
-------------------------
s^3 + 11 s^2 + 20 s + 100
Input 1 to output 3:
10
------------
s^2 + s + 10
Input 2 to output 1:
0
-
1
Input 2 to output 2:
1000
------
s + 10
Input 2 to output 3:
1
-
1
Input 3 to output 1:
1000
------
s + 10
Input 3 to output 2:
1.756e-12 s + 1e+04
-------------------------
s^3 + 11 s^2 + 20 s + 100
Input 3 to output 3:
10
------------
s^2 + s + 10
I was not able to get the plant in a more complex example by the append, connect procedure.
Because I have a MIMO-System (G) with a disturance z2 after G: z2, G element of R^2 and W1 has to 2 inputs and two outputs
But thanks to @bnavigator: the combine-method is great. Thanks a lot! Maybe my example will help others.
BTW have you looked at control.robust.augw()? It does something similar using the connect() function and intermediate "distribution" and "summer" systems Ieand Iu.
In matlab, use lmi method to avoid the rank conditions but still always penalize your control output even the slightest to avoid the ill-conditioned solutions.
This issue has been idle for ~6 months and I don't think there is anything actionable in the comments except some ideas for future functionality. Closing for now, but someone should create a new issue if there is something specific that we would like to request as an enhancement.
Activity
murrayrm commentedon Jul 11, 2019
You could try using
parallel,seriesandfeedbackto construct the system. Alternatively, take a look at theappendandconnectcommands? All of those should produce a system that doesn't involve creating extra states (unless you list one of the systems multiple times, which I guess is what is causing the problem above?).murrayrm commentedon Jul 13, 2019
The following should work:
Note that this generates a minimal representation in the state space because we never create a copy of the plant (G) or weighting filters. So
P_has 4 states, 3 inputs, 3 outputs.One annoying (and I think confusing) aspect of this construction is that the
control.connectfunction uses indexing starting at 1 (to be compatible with MATLAB but also to allow negative feedback), while Python indexing normally starts at 0. This is documented in theconnectfunction, but I still think it is confusing.iljastas commentedon Jul 15, 2019
Thanks for your help @murrayrm !
But I don't get it. Input of G is the controller output or better say the disturbed controller output.
murrayrm commentedon Jul 15, 2019
I may have misunderstood the transfer function matrix you were trying to create (I sketched it out on a napkin that I have since tossed -:). The main point is that you can use
appendto stack the system dynamics and then useconnectto interconnect them.iljastas commentedon Jul 16, 2019
I'm unfortunately not able to produce a minimal example (Kai Müller, Entwurf robubster Regelungen Teubner Springer 1996, Chapter 12.3.1, p. 172).
from control import *
W1 = tf([2], [1])
W2 = tf([3], [1])
G = tf([1], [1, 1])
sysvec = append(ss(G), ss(W1), ss(W2))
P = connect(sysvec, [[1, 2] ], [2, 1], [2, 3, 1])
print(P)
The right answer is: A=[-1], B = [0 1], C=[2 0 1]^T, D=[2 0; 0 3; 1 0]
But I'm not able to produce it.
So there is a connection between G and W1. And I have to inputs: u and z, And I have three outputs: v1, v2 and y.
murrayrm commentedon Jul 16, 2019
I put this example into MATLAB (same exact commands) and got the output
When I run those commands in Python 3.5 using the current master (which should be the same as v0.8.2), I get output
This matches the output of MATLAB, but is different than what you showed as your output. What version of
python-controlare you running?There is still the issue that this is not the right system description for the block diagram. I think that part of the problem is that your interconnection matrix is not right. You have
[[1, 2]]for the interconnection, which sets input 1 (G) to output 2 (W1). From the block diagram, what you want is[[2, 1]], so that the input of W1 (= input #2) is the output from G (output #1).Running the command with the updated interconnection matrix gives
gives
This is almost what you expect, except that the
Dmatrix is not correct.The problem is because of a limitations in the
connectcommand (in MATLAB and Python):The outputs for the
connectcommand can only correspond to outputs from one of the subsystems. The output that you want for y in your diagram is the output of G plus the input z. But you can't actually do that withconnect(in MATLAB or Python). So one problem is that the input u should be going to output v2 through a gain of 3. (That entry is missing in both the MATLAB and Python versions, for reasons that don't make senses.)There is a similar constrain on the inputs. It is not possible to take an input from one system and map it to the input of another. So the only input to W2 is its natural input and we removed this from the transfer function.
bnavigator commentedon Jul 16, 2019
Try this:
which gives your "right answer"
I am pretty sure your D does not reflect your desired output of
(v1,v2,y)but it is(v1,v2,z+y)and your inputs are ordered(z,u)murrayrm commentedon Jul 16, 2019
Thanks @bnavigator. It would be useful to think about whether there is a nice way to do these sorts of manipulations. The construct that @iljastas gave at the start is really the best way since it creates copies of the system/weighting filters that are then "minimized" away, but it is also tedious to put in the extra elements that you used to get things to work.
I'd lover to hear suggestions about what a cleaner implementation would look like.
iljastas commentedon Jul 16, 2019
Thanks @murrayrm and @bnavigator I will try it later or tomorrow and post also a more complex example with and hinfsyn-controller!
bnavigator commentedon Jul 16, 2019
Maybe it would be useful to have a function
combine()or something similar to mimic the Matrix combination of systems like in MATLAB. Here is a hack how that could look like. Of course it still needs all the type checks etc. to have it included into the StateSpace class:output:
MATLAB:
A
combine()for TransferFunction would be even simpler, but that is just what has been done manually in the ininital question:iljastas commentedon Jul 17, 2019
I was not able to get the plant in a more complex example by the append, connect procedure.
Because I have a MIMO-System (G) with a disturance z2 after G: z2, G element of R^2 and W1 has to 2 inputs and two outputs
But thanks to @bnavigator: the combine-method is great. Thanks a lot! Maybe my example will help others.
bnavigator commentedon Jul 18, 2019
Please format your posts to include code within code tags. Mark the multiline code and click on the '<>' button. It will enclose the code in
```tagsresults in
with the python tag you even get some highlighting:
See also https://guides.github.com/features/mastering-markdown/
bnavigator commentedon Jul 18, 2019
Much better now :)
BTW have you looked at
control.robust.augw()? It does something similar using theconnect()function and intermediate "distribution" and "summer" systemsIeandIu.iljastas commentedon Jul 19, 2019
Of course I tried this with "control" and in MATLAB but I got the errror:
for:
And further on my control system has only to control disturbances, so that this formulation is more suited to my problem
ilayn commentedon Jul 19, 2019
In matlab, use
lmimethod to avoid the rank conditions but still always penalize your control output even the slightest to avoid the ill-conditioned solutions.iljastas commentedon Jul 20, 2019
@ilyan do you have an example or a literature source for solving this as a lmi formulation?
ilayn commentedon Jul 20, 2019
@iljastas Just have a look at the hinfsyn options. You can change the method. If nothing has changed in the last years, the default should be riccati based but you can change it to
lmi. See this page https://nl.mathworks.com/help/robust/ref/hinfsynoptions.htmlmurrayrm commentedon Dec 29, 2019
This issue has been idle for ~6 months and I don't think there is anything actionable in the comments except some ideas for future functionality. Closing for now, but someone should create a new issue if there is something specific that we would like to request as an enhancement.