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

Commited4ff84

Browse files
authored
Merge pull request#797 from sawyerbfuller/named-signals
Preserve signal names upon conversion to discrete-time
2 parents23a7791 +16d9e6a commited4ff84

File tree

11 files changed

+319
-69
lines changed

11 files changed

+319
-69
lines changed

‎control/config.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ def reset_defaults():
9797
from .rlocusimport_rlocus_defaults
9898
defaults.update(_rlocus_defaults)
9999

100+
from .namedioimport_namedio_defaults
101+
defaults.update(_namedio_defaults)
102+
100103
from .xferfcnimport_xferfcn_defaults
101104
defaults.update(_xferfcn_defaults)
102105

@@ -285,7 +288,7 @@ def use_legacy_defaults(version):
285288
set_defaults('control',default_dt=None)
286289

287290
# changed iosys naming conventions
288-
set_defaults('iosys',state_name_delim='.',
291+
set_defaults('namedio',state_name_delim='.',
289292
duplicate_system_name_prefix='copy of ',
290293
duplicate_system_name_suffix='',
291294
linearized_system_name_prefix='',

‎control/dtime.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@
5353
__all__= ['sample_system','c2d']
5454

5555
# Sample a continuous time system
56-
defsample_system(sysc,Ts,method='zoh',alpha=None,prewarp_frequency=None):
56+
defsample_system(sysc,Ts,method='zoh',alpha=None,prewarp_frequency=None,
57+
name=None,copy_names=True,**kwargs):
5758
"""
5859
Convert a continuous time system to discrete time by sampling
5960
@@ -72,12 +73,35 @@ def sample_system(sysc, Ts, method='zoh', alpha=None, prewarp_frequency=None):
7273
prewarp_frequency : float within [0, infinity)
7374
The frequency [rad/s] at which to match with the input continuous-
7475
time system's magnitude and phase (only valid for method='bilinear')
76+
name : string, optional
77+
Set the name of the sampled system. If not specified and
78+
if `copy_names` is `False`, a generic name <sys[id]> is generated
79+
with a unique integer id. If `copy_names` is `True`, the new system
80+
name is determined by adding the prefix and suffix strings in
81+
config.defaults['namedio.sampled_system_name_prefix'] and
82+
config.defaults['namedio.sampled_system_name_suffix'], with the
83+
default being to add the suffix '$sampled'.
84+
copy_names : bool, Optional
85+
If True, copy the names of the input signals, output
86+
signals, and states to the sampled system.
7587
7688
Returns
7789
-------
7890
sysd : linsys
7991
Discrete time system, with sampling rate Ts
8092
93+
Additional Parameters
94+
---------------------
95+
inputs : int, list of str or None, optional
96+
Description of the system inputs. If not specified, the origional
97+
system inputs are used. See :class:`NamedIOSystem` for more
98+
information.
99+
outputs : int, list of str or None, optional
100+
Description of the system outputs. Same format as `inputs`.
101+
states : int, list of str, or None, optional
102+
Description of the system states. Same format as `inputs`. Only
103+
available if the system is :class:`StateSpace`.
104+
81105
Notes
82106
-----
83107
See :meth:`StateSpace.sample` or :meth:`TransferFunction.sample` for
@@ -94,7 +118,8 @@ def sample_system(sysc, Ts, method='zoh', alpha=None, prewarp_frequency=None):
94118
raiseValueError("First argument must be continuous time system")
95119

96120
returnsysc.sample(Ts,
97-
method=method,alpha=alpha,prewarp_frequency=prewarp_frequency)
121+
method=method,alpha=alpha,prewarp_frequency=prewarp_frequency,
122+
name=name,copy_names=copy_names,**kwargs)
98123

99124

100125
defc2d(sysc,Ts,method='zoh',prewarp_frequency=None):

‎control/iosys.py

Lines changed: 29 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,7 @@
4747
'interconnect','summing_junction']
4848

4949
# Define module default parameter values
50-
_iosys_defaults= {
51-
'iosys.state_name_delim':'_',
52-
'iosys.duplicate_system_name_prefix':'',
53-
'iosys.duplicate_system_name_suffix':'$copy',
54-
'iosys.linearized_system_name_prefix':'',
55-
'iosys.linearized_system_name_suffix':'$linearized'
56-
}
50+
_iosys_defaults= {}
5751

5852

5953
classInputOutputSystem(NamedIOSystem):
@@ -515,7 +509,7 @@ def feedback(self, other=1, sign=-1, params=None):
515509
returnnewsys
516510

517511
deflinearize(self,x0,u0,t=0,params=None,eps=1e-6,
518-
name=None,copy=False,**kwargs):
512+
name=None,copy_names=False,**kwargs):
519513
"""Linearize an input/output system at a given state and input.
520514
521515
Return the linearization of an input/output system at a given state
@@ -571,25 +565,26 @@ def linearize(self, x0, u0, t=0, params=None, eps=1e-6,
571565

572566
# Create the state space system
573567
linsys=LinearIOSystem(
574-
StateSpace(A,B,C,D,self.dt,remove_useless_states=False),
575-
name=name,**kwargs)
568+
StateSpace(A,B,C,D,self.dt,remove_useless_states=False))
576569

577-
# Set the names the system, inputs, outputs, and states
578-
ifcopy:
570+
# Set the system name, inputs, outputs, and states
571+
if'copy'inkwargs:
572+
copy_names=kwargs.pop('copy')
573+
warn("keyword 'copy' is deprecated. please use 'copy_names'",
574+
DeprecationWarning)
575+
576+
ifcopy_names:
577+
linsys._copy_names(self)
579578
ifnameisNone:
580579
linsys.name= \
581-
config.defaults['iosys.linearized_system_name_prefix']+ \
582-
self.name+ \
583-
config.defaults['iosys.linearized_system_name_suffix']
584-
linsys.ninputs,linsys.input_index=self.ninputs, \
585-
self.input_index.copy()
586-
linsys.noutputs,linsys.output_index= \
587-
self.noutputs,self.output_index.copy()
588-
linsys.nstates,linsys.state_index= \
589-
self.nstates,self.state_index.copy()
590-
591-
returnlinsys
580+
config.defaults['namedio.linearized_system_name_prefix']+\
581+
linsys.name+\
582+
config.defaults['namedio.linearized_system_name_suffix']
583+
else:
584+
linsys.name=name
592585

586+
# re-init to include desired signal names if names were provided
587+
returnLinearIOSystem(linsys,**kwargs)
593588

594589
classLinearIOSystem(InputOutputSystem,StateSpace):
595590
"""Input/output representation of a linear (state space) system.
@@ -966,7 +961,7 @@ def __init__(self, syslist, connections=None, inplist=None, outlist=None,
966961

967962
ifstatesisNone:
968963
states= []
969-
state_name_delim=config.defaults['iosys.state_name_delim']
964+
state_name_delim=config.defaults['namedio.state_name_delim']
970965
forsys,sysnameinsysobj_name_dct.items():
971966
states+= [sysname+state_name_delim+
972967
statenameforstatenameinsys.state_index.keys()]
@@ -2197,19 +2192,17 @@ def linearize(sys, xeq, ueq=None, t=0, params=None, **kw):
21972192
params : dict, optional
21982193
Parameter values for the systems. Passed to the evaluation functions
21992194
for the system as default values, overriding internal defaults.
2200-
copy : bool, Optional
2201-
If `copy` is True, copy the names of the input signals, output signals,
2202-
and states to the linearized system. If `name` is not specified,
2203-
the system name is set to the input system name with the string
2204-
'_linearized' appended.
22052195
name : string, optional
22062196
Set the name of the linearized system. If not specified and
2207-
if `copy` is `False`, a generic name <sys[id]> is generated
2208-
with a unique integer id. If `copy` is `True`, the new system
2197+
if `copy_names` is `False`, a generic name <sys[id]> is generated
2198+
with a unique integer id. If `copy_names` is `True`, the new system
22092199
name is determined by adding the prefix and suffix strings in
2210-
config.defaults['iosys.linearized_system_name_prefix'] and
2211-
config.defaults['iosys.linearized_system_name_suffix'], with the
2200+
config.defaults['namedio.linearized_system_name_prefix'] and
2201+
config.defaults['namedio.linearized_system_name_suffix'], with the
22122202
default being to add the suffix '$linearized'.
2203+
copy_names : bool, Optional
2204+
If True, Copy the names of the input signals, output signals, and
2205+
states to the linearized system.
22132206
22142207
Returns
22152208
-------
@@ -2221,7 +2214,7 @@ def linearize(sys, xeq, ueq=None, t=0, params=None, **kw):
22212214
---------------------
22222215
inputs : int, list of str or None, optional
22232216
Description of the system inputs. If not specified, the origional
2224-
system inputs are used. See :class:`InputOutputSystem` for more
2217+
system inputs are used. See :class:`NamedIOSystem` for more
22252218
information.
22262219
outputs : int, list of str or None, optional
22272220
Description of the system outputs. Same format as `inputs`.
@@ -2733,8 +2726,8 @@ def interconnect(syslist, connections=None, inplist=None, outlist=None,
27332726
If a system is duplicated in the list of systems to be connected,
27342727
a warning is generated and a copy of the system is created with the
27352728
name of the new system determined by adding the prefix and suffix
2736-
strings in config.defaults['iosys.linearized_system_name_prefix']
2737-
and config.defaults['iosys.linearized_system_name_suffix'], with the
2729+
strings in config.defaults['namedio.linearized_system_name_prefix']
2730+
and config.defaults['namedio.linearized_system_name_suffix'], with the
27382731
default being to add the suffix '$copy'$ to the system name.
27392732
27402733
It is possible to replace lists in most of arguments with tuples instead,

‎control/namedio.py

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,24 @@
66
# and other similar classes to allow naming of signals.
77

88
importnumpyasnp
9-
fromcopyimportcopy
9+
fromcopyimportdeepcopy
1010
fromwarningsimportwarn
1111
from .importconfig
1212

1313
__all__= ['issiso','timebase','common_timebase','timebaseEqual',
1414
'isdtime','isctime']
15-
15+
# Define module default parameter values
16+
_namedio_defaults= {
17+
'namedio.state_name_delim':'_',
18+
'namedio.duplicate_system_name_prefix':'',
19+
'namedio.duplicate_system_name_suffix':'$copy',
20+
'namedio.linearized_system_name_prefix':'',
21+
'namedio.linearized_system_name_suffix':'$linearized',
22+
'namedio.sampled_system_name_prefix':'',
23+
'namedio.sampled_system_name_suffix':'$sampled'
24+
}
25+
26+
1627
classNamedIOSystem(object):
1728
def__init__(
1829
self,name=None,inputs=None,outputs=None,states=None,**kwargs):
@@ -88,26 +99,37 @@ def __str__(self):
8899
def_find_signal(self,name,sigdict):
89100
returnsigdict.get(name,None)
90101

102+
def_copy_names(self,sys):
103+
"""copy the signal and system name of sys. Name is given as a keyword
104+
in case a specific name (e.g. append 'linearized') is desired. """
105+
self.name=sys.name
106+
self.ninputs,self.input_index= \
107+
sys.ninputs,sys.input_index.copy()
108+
self.noutputs,self.output_index= \
109+
sys.noutputs,sys.output_index.copy()
110+
self.nstates,self.state_index= \
111+
sys.nstates,sys.state_index.copy()
112+
91113
defcopy(self,name=None,use_prefix_suffix=True):
92114
"""Make a copy of an input/output system
93115
94116
A copy of the system is made, with a new name. The `name` keyword
95117
can be used to specify a specific name for the system. If no name
96118
is given and `use_prefix_suffix` is True, the name is constructed
97-
by prepending config.defaults['iosys.duplicate_system_name_prefix']
98-
and appending config.defaults['iosys.duplicate_system_name_suffix'].
119+
by prepending config.defaults['namedio.duplicate_system_name_prefix']
120+
and appending config.defaults['namedio.duplicate_system_name_suffix'].
99121
Otherwise, a generic system name of the form `sys[<id>]` is used,
100122
where `<id>` is based on an internal counter.
101123
102124
"""
103125
# Create a copy of the system
104-
newsys=copy(self)
126+
newsys=deepcopy(self)
105127

106128
# Update the system name
107129
ifnameisNoneanduse_prefix_suffix:
108130
# Get the default prefix and suffix to use
109-
dup_prefix=config.defaults['iosys.duplicate_system_name_prefix']
110-
dup_suffix=config.defaults['iosys.duplicate_system_name_suffix']
131+
dup_prefix=config.defaults['namedio.duplicate_system_name_prefix']
132+
dup_suffix=config.defaults['namedio.duplicate_system_name_suffix']
111133
newsys.name=self._name_or_default(
112134
dup_prefix+self.name+dup_suffix)
113135
else:

‎control/statesp.py

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@
6363
from .exceptionimportControlSlycot
6464
from .frdataimportFrequencyResponseData
6565
from .ltiimportLTI,_process_frequency_response
66-
from .namedioimportcommon_timebase,isdtime
67-
from .namedioimport_process_namedio_keywords
66+
from .namedioimportcommon_timebase,isdtime,_process_namedio_keywords, \
67+
_process_dt_keyword
6868
from .importconfig
6969
fromcopyimportdeepcopy
7070

@@ -359,7 +359,7 @@ def __init__(self, *args, init_namedio=True, **kwargs):
359359
raiseTypeError("unrecognized keyword(s): ",str(kwargs))
360360

361361
# Reset shapes (may not be needed once np.matrix support is removed)
362-
if0==self.nstates:
362+
ifself._isstatic():
363363
# static gain
364364
# matrix's default "empty" shape is 1x0
365365
A.shape= (0,0)
@@ -1298,7 +1298,8 @@ def __getitem__(self, indices):
12981298
returnStateSpace(self.A,self.B[:,j],self.C[i, :],
12991299
self.D[i,j],self.dt)
13001300

1301-
defsample(self,Ts,method='zoh',alpha=None,prewarp_frequency=None):
1301+
defsample(self,Ts,method='zoh',alpha=None,prewarp_frequency=None,
1302+
name=None,copy_names=True,**kwargs):
13021303
"""Convert a continuous time system to discrete time
13031304
13041305
Creates a discrete-time system from a continuous-time system by
@@ -1317,22 +1318,42 @@ def sample(self, Ts, method='zoh', alpha=None, prewarp_frequency=None):
13171318
alpha=0)
13181319
* backward_diff: Backwards differencing ("gbt" with alpha=1.0)
13191320
* zoh: zero-order hold (default)
1320-
13211321
alpha : float within [0, 1]
13221322
The generalized bilinear transformation weighting parameter, which
13231323
should only be specified with method="gbt", and is ignored
13241324
otherwise
1325-
13261325
prewarp_frequency : float within [0, infinity)
13271326
The frequency [rad/s] at which to match with the input continuous-
13281327
time system's magnitude and phase (the gain=1 crossover frequency,
13291328
for example). Should only be specified with method='bilinear' or
13301329
'gbt' with alpha=0.5 and ignored otherwise.
1330+
name : string, optional
1331+
Set the name of the sampled system. If not specified and
1332+
if `copy_names` is `False`, a generic name <sys[id]> is generated
1333+
with a unique integer id. If `copy_names` is `True`, the new system
1334+
name is determined by adding the prefix and suffix strings in
1335+
config.defaults['namedio.sampled_system_name_prefix'] and
1336+
config.defaults['namedio.sampled_system_name_suffix'], with the
1337+
default being to add the suffix '$sampled'.
1338+
copy_names : bool, Optional
1339+
If True, copy the names of the input signals, output
1340+
signals, and states to the sampled system.
13311341
13321342
Returns
13331343
-------
13341344
sysd : StateSpace
1335-
Discrete time system, with sampling rate Ts
1345+
Discrete-time system, with sampling rate Ts
1346+
1347+
Additional Parameters
1348+
---------------------
1349+
inputs : int, list of str or None, optional
1350+
Description of the system inputs. If not specified, the origional
1351+
system inputs are used. See :class:`InputOutputSystem` for more
1352+
information.
1353+
outputs : int, list of str or None, optional
1354+
Description of the system outputs. Same format as `inputs`.
1355+
states : int, list of str, or None, optional
1356+
Description of the system states. Same format as `inputs`.
13361357
13371358
Notes
13381359
-----
@@ -1347,14 +1368,26 @@ def sample(self, Ts, method='zoh', alpha=None, prewarp_frequency=None):
13471368
ifnotself.isctime():
13481369
raiseValueError("System must be continuous time system")
13491370

1350-
sys= (self.A,self.B,self.C,self.D)
13511371
if (method=='bilinear'or (method=='gbt'andalpha==0.5))and \
13521372
prewarp_frequencyisnotNone:
13531373
Twarp=2*np.tan(prewarp_frequency*Ts/2)/prewarp_frequency
13541374
else:
13551375
Twarp=Ts
1376+
sys= (self.A,self.B,self.C,self.D)
13561377
Ad,Bd,C,D,_=cont2discrete(sys,Twarp,method,alpha)
1357-
returnStateSpace(Ad,Bd,C,D,Ts)
1378+
sysd=StateSpace(Ad,Bd,C,D,Ts)
1379+
# copy over the system name, inputs, outputs, and states
1380+
ifcopy_names:
1381+
sysd._copy_names(self)
1382+
ifnameisNone:
1383+
sysd.name= \
1384+
config.defaults['namedio.sampled_system_name_prefix']+\
1385+
sysd.name+ \
1386+
config.defaults['namedio.sampled_system_name_suffix']
1387+
else:
1388+
sysd.name=name
1389+
# pass desired signal names if names were provided
1390+
returnStateSpace(sysd,**kwargs)
13581391

13591392
defdcgain(self,warn_infinite=False):
13601393
"""Return the zero-frequency gain

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp