Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit45f3555

Browse files
committed
renamed function to highlight that it is based on root locus, set initial gain to 1, new noplot argument for faster testing
1 parentbf4b479 commit45f3555

File tree

3 files changed

+45
-31
lines changed

3 files changed

+45
-31
lines changed

‎control/rlocus.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ def root_locus(sys, kvect=None, xlim=None, ylim=None,
188188
zeta=-1*s.real/abs(s)
189189
fig.suptitle(
190190
"Clicked at: %10.4g%+10.4gj gain: %10.4g damp: %10.4g"%
191-
(s.real,s.imag,1,zeta),
191+
(s.real,s.imag,kvect[0],zeta),
192192
fontsize=12ifint(mpl.__version__[0])==1else10)
193193
fig.canvas.mpl_connect(
194194
'button_release_event',

‎control/sisotool.py

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
__all__= ['sisotool','pid_designer']
1+
__all__= ['sisotool','rootlocus_pid_designer']
22

33
fromcontrol.exceptionimportControlMIMONotImplemented
44
from .freqplotimportbode_plot
@@ -180,19 +180,21 @@ def _SisotoolUpdate(sys, fig, K, bode_plot_params, tvect=None):
180180
fig.subplots_adjust(top=0.9,wspace=0.3,hspace=0.35)
181181
fig.canvas.draw()
182182

183-
# contributed by Sawyer Fuller, minster@uw.edu 2021.11.02
184-
defpid_designer(plant,gain='P',sign=+1,input_signal='r',
183+
# contributed by Sawyer Fuller, minster@uw.edu 2021.11.02, based on
184+
# an implementation in Matlab by Martin Berg.
185+
defrootlocus_pid_designer(plant,gain='P',sign=+1,input_signal='r',
185186
Kp0=0,Ki0=0,Kd0=0,tau=0.01,
186-
C_ff=0,derivative_in_feedback_path=False):
187-
"""Manual PID controller design using sisotool
187+
C_ff=0,derivative_in_feedback_path=False,
188+
noplot=False):
189+
"""Manual PID controller design based on root locus using Sisotool
188190
189191
Uses `Sisotool` to investigate the effect of adding or subtracting an
190192
amount `deltaK` to the proportional, integral, or derivative (PID) gains of
191193
a controller. One of the PID gains, `Kp`, `Ki`, or `Kd`, respectively, can
192194
be modified at a time. `Sisotool` plots the step response, frequency
193195
response, and root locus.
194196
195-
When first run, `deltaK` is set to1; click on a branch of the root locus
197+
When first run, `deltaK` is set to0; click on a branch of the root locus
196198
plot to try a different value. Each click updates plots and prints
197199
the corresponding `deltaK`. To tune all three PID gains, repeatedly call
198200
`pid_designer`, and select a different `gain` each time (`'P'`, `'I'`,
@@ -240,13 +242,13 @@ def pid_designer(plant, gain='P', sign=+1, input_signal='r',
240242
plant : :class:`LTI` (:class:`TransferFunction` or :class:`StateSpace` system)
241243
The dynamical system to be controlled
242244
gain : string (optional)
243-
Which gain to vary by deltaK. Must be one of 'P','I', or 'D'
245+
Which gain to vary by`deltaK`. Must be one of`'P'`, `'I'`, or`'D'`
244246
(proportional, integral, or derative)
245247
sign : int (optional)
246248
The sign of deltaK gain perturbation
247249
input : string (optional)
248-
The input used for the step response; must be 'r' (reference) or
249-
'd' (disturbance) (see figure above)
250+
The input used for the step response; must be`'r'` (reference) or
251+
`'d'` (disturbance) (see figure above)
250252
Kp0, Ki0, Kd0 : float (optional)
251253
Initial values for proportional, integral, and derivative gains,
252254
respectively
@@ -257,16 +259,24 @@ def pid_designer(plant, gain='P', sign=+1, input_signal='r',
257259
C_ff : float or :class:`LTI` system (optional)
258260
Feedforward controller. If :class:`LTI`, must have timebase that is
259261
compatible with plant.
262+
derivative_in_feedback_path : bool (optional)
263+
Whether to place the derivative term in feedback transfer function
264+
`C_b` instead of the forward transfer function `C_f`.
265+
noplot : bool (optional)
266+
267+
Returns
268+
----------
269+
closedloop : class:`StateSpace` system
270+
The closed-loop system using initial gains.
260271
"""
261272

262273
plant=_convert_to_statespace(plant)
263274
ifplant.ninputs==1:
264275
plant=ss2io(plant,inputs='u',outputs='y')
265276
elifplant.ninputs==2:
266-
plant=ss2io(plant,inputs=('u','d'),outputs='y')
277+
plant=ss2io(plant,inputs=['u','d'],outputs='y')
267278
else:
268279
raiseValueError("plant must have one or two inputs")
269-
#plant = ss2io(plant, inputs='u', outputs='y')
270280
C_ff=ss2io(_convert_to_statespace(C_ff),inputs='r',outputs='uff')
271281
dt=common_timebase(plant,C_ff)
272282

@@ -277,29 +287,30 @@ def pid_designer(plant, gain='P', sign=+1, input_signal='r',
277287
else:
278288
u_summer=summing_junction(['ufb','uff','d'],'u')
279289

280-
prop=tf(1,1)
281290
ifisctime(plant):
282-
integ=tf(1,[1,0])
291+
prop=tf(1,1)
292+
integ=tf(1, [1,0])
283293
deriv=tf([1,0], [tau,1])
284-
else:
285-
integ=tf([dt/2,dt/2],[1,-1],dt)
286-
deriv=tf([1,-1],[dt,0],dt)
294+
else:# discrete-time
295+
prop=tf(1,1,dt)
296+
integ=tf([dt/2,dt/2], [1,-1],dt)
297+
deriv=tf([1,-1], [dt,0],dt)
287298

288-
# add signal names
299+
# add signal names by turning into iosystems
289300
prop=tf2io(prop,inputs='e',outputs='prop_e')
290301
integ=tf2io(integ,inputs='e',outputs='int_e')
291302
ifderivative_in_feedback_path:
292-
deriv=tf2io(-deriv,inputs='y',outputs='deriv_')
303+
deriv=tf2io(-deriv,inputs='y',outputs='deriv')
293304
else:
294-
deriv=tf2io(deriv,inputs='e',outputs='deriv_')
305+
deriv=tf2io(deriv,inputs='e',outputs='deriv')
295306

296307
# create gain blocks
297308
Kpgain=tf2io(tf(Kp0,1),inputs='prop_e',outputs='ufb')
298309
Kigain=tf2io(tf(Ki0,1),inputs='int_e',outputs='ufb')
299-
Kdgain=tf2io(tf(Kd0,1),inputs='deriv_',outputs='ufb')
310+
Kdgain=tf2io(tf(Kd0,1),inputs='deriv',outputs='ufb')
300311

301-
# for the gain that is varied,create a specialgain block withan
302-
# 'input' and an 'output'signal to create the loop transfer function
312+
# for the gain that is varied,replacegain block witha special block
313+
#that has an'input' and an 'output'that creates loop transfer function
303314
ifgainin ('P','p'):
304315
Kpgain=ss2io(ss([],[],[],[[0,1], [-sign,Kp0]]),
305316
inputs=['input','prop_e'],outputs=['output','ufb'])
@@ -308,13 +319,15 @@ def pid_designer(plant, gain='P', sign=+1, input_signal='r',
308319
inputs=['input','int_e'],outputs=['output','ufb'])
309320
elifgainin ('D','d'):
310321
Kdgain=ss2io(ss([],[],[],[[0,1], [-sign,Kd0]]),
311-
inputs=['input','deriv_'],outputs=['output','ufb'])
322+
inputs=['input','deriv'],outputs=['output','ufb'])
312323
else:
313324
raiseValueError(gain+' gain not recognized.')
314325

315326
# the second input and output are used by sisotool to plot step response
316327
loop=interconnect((plant,Kpgain,Kigain,Kdgain,prop,integ,deriv,
317328
C_ff,e_summer,u_summer),
318-
inplist=['input',input_signal],outlist=['output','y'])
319-
sisotool(loop)
320-
returnloop[1,1]
329+
inplist=['input',input_signal],
330+
outlist=['output','y'])
331+
if~noplot:
332+
sisotool(loop,kvect=(0.,))
333+
return_convert_to_statespace(loop[1,1])

‎control/tests/sisotool_test.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
fromnumpy.testingimportassert_array_almost_equal
77
importpytest
88

9-
fromcontrol.sisotoolimportsisotool,pid_designer
9+
fromcontrol.sisotoolimportsisotool,rootlocus_pid_designer
1010
fromcontrol.rlocusimport_RLClickDispatcher
1111
fromcontrol.xferfcnimportTransferFunction
1212
fromcontrol.statespimportStateSpace
@@ -151,13 +151,14 @@ def plant(self, request):
151151
'syscont221':StateSpace([[-.3,0],[1,0]],[[-1,],[.1,]], [0,-.3],0)}
152152
returnplants[request.param]
153153

154+
# check
154155
# cont or discrete, vary P I or D
155156
# @pytest.mark.parametrize('plant', (syscont, sysdisc1))
156157
@pytest.mark.parametrize('plant', ('syscont','sysdisc1'),indirect=True)
157158
@pytest.mark.parametrize('gain', ('P','I','D'))
158-
@pytest.mark.parametrize("kwargs", [{'Kp0':0.01},])
159+
@pytest.mark.parametrize("kwargs", [{'Kp0':0.1,'noplot':True},])
159160
deftest_pid_designer_1(self,plant,gain,kwargs):
160-
pid_designer(plant,gain,**kwargs)
161+
rootlocus_pid_designer(plant,gain,**kwargs)
161162

162163
# input from reference or disturbance
163164
@pytest.mark.parametrize('plant', ('syscont','syscont221'),indirect=True)
@@ -166,5 +167,5 @@ def test_pid_designer_1(self, plant, gain, kwargs):
166167
{'input_signal':'r','Kp0':0.01,'derivative_in_feedback_path':True},
167168
{'input_signal':'d','Kp0':0.01,'derivative_in_feedback_path':True},])
168169
deftest_pid_designer_2(self,plant,kwargs):
169-
pid_designer(plant,**kwargs)
170+
rootlocus_pid_designer(plant,**kwargs)
170171

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp