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

Commitcf77f99

Browse files
authored
Merge pull request#1117 from murrayrm/update_isstatic-01Feb2025
Update use/computation of sys._isstatic()
2 parentsf73e893 +ce77e6b commitcf77f99

File tree

7 files changed

+64
-47
lines changed

7 files changed

+64
-47
lines changed

‎control/descfcn.py‎

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ def describing_function(
152152
#
153153
# The describing function of a nonlinear function F() can be computed by
154154
# evaluating the nonlinearity over a sinusoid. The Fourier series for a
155-
#staticnonlinear function evaluated on a sinusoid can be written as
155+
# nonlinear function evaluated on a sinusoid can be written as
156156
#
157157
# F(A\sin\omega t) = \sum_{k=1}^\infty M_k(A) \sin(k\omega t + \phi_k(A))
158158
#
@@ -226,10 +226,10 @@ class DescribingFunctionResponse:
226226
"""Results of describing function analysis.
227227
228228
Describing functions allow analysis of a linear I/O systems with a
229-
staticnonlinear feedback function. The DescribingFunctionResponse
230-
classis used by the `describing_function_response`
231-
function to returnthe results of a describing function analysis. The
232-
responseobject can be used to obtain information about the describing
229+
nonlinear feedback function. The DescribingFunctionResponse class
230+
is used by the `describing_function_response` function to return
231+
the results of a describing function analysis. The response
232+
object can be used to obtain information about the describing
233233
function analysis or generate a Nyquist plot showing the frequency
234234
response of the linear systems and the describing function for the
235235
nonlinear element.
@@ -283,16 +283,16 @@ def describing_function_response(
283283
"""Compute the describing function response of a system.
284284
285285
This function uses describing function analysis to analyze a closed
286-
loop system consisting of a linear system with astaticnonlinear
287-
function inthe feedback path.
286+
loop system consisting of a linear system with a nonlinear function in
287+
the feedback path.
288288
289289
Parameters
290290
----------
291291
H : LTI system
292292
Linear time-invariant (LTI) system (state space, transfer function,
293293
or FRD).
294-
F :staticnonlinear function
295-
A static nonlinearity, either a scalar function or a single-input,
294+
F : nonlinear function
295+
Feedback nonlinearity, either a scalar function or a single-input,
296296
single-output, static input/output system.
297297
A : list
298298
List of amplitudes to be used for the describing function plot.
@@ -405,8 +405,7 @@ def describing_function_plot(
405405
Nyquist plot with describing function for a nonlinear system.
406406
407407
This function generates a Nyquist plot for a closed loop system
408-
consisting of a linear system with a static nonlinear function in the
409-
feedback path.
408+
consisting of a linear system with a nonlinearity in the feedback path.
410409
411410
The function may be called in one of two forms:
412411
@@ -426,9 +425,9 @@ def describing_function_plot(
426425
H : LTI system
427426
Linear time-invariant (LTI) system (state space, transfer function,
428427
or FRD).
429-
F :staticnonlinear function
430-
A static nonlinearity, either a scalar function or a single-input,
431-
single-output, static input/output system.
428+
F : nonlinear function
429+
Nonlinearity in the feedback path, either a scalar function or a
430+
single-input, single-output, static input/output system.
432431
A : list
433432
List of amplitudes to be used for the describing function plot.
434433
omega : list, optional

‎control/iosys.py‎

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -757,10 +757,6 @@ def issiso(self):
757757
"""Check to see if a system is single input, single output."""
758758
returnself.ninputs==1andself.noutputs==1
759759

760-
def_isstatic(self):
761-
"""Check to see if a system is a static system (no states)"""
762-
returnself.nstates==0
763-
764760

765761
# Test to see if a system is SISO
766762
defissiso(sys,strict=False):

‎control/nlsys.py‎

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ def __call__(sys, u, params=None, squeeze=None):
181181
182182
"""
183183
# Make sure the call makes sense
184-
ifnotsys._isstatic():
184+
ifsys.nstates!=0:
185185
raiseTypeError(
186186
"function evaluation is only supported for static "
187187
"input/output systems")
@@ -199,7 +199,7 @@ def __call__(sys, u, params=None, squeeze=None):
199199
def__mul__(self,other):
200200
"""Multiply two input/output systems (series interconnection)"""
201201
# Convert 'other' to an I/O system if needed
202-
other=_convert_static_iosystem(other)
202+
other=_convert_to_iosystem(other)
203203
ifnotisinstance(other,InputOutputSystem):
204204
returnNotImplemented
205205

@@ -231,7 +231,7 @@ def __mul__(self, other):
231231
def__rmul__(self,other):
232232
"""Pre-multiply an input/output systems by a scalar/matrix"""
233233
# Convert other to an I/O system if needed
234-
other=_convert_static_iosystem(other)
234+
other=_convert_to_iosystem(other)
235235
ifnotisinstance(other,InputOutputSystem):
236236
returnNotImplemented
237237

@@ -263,7 +263,7 @@ def __rmul__(self, other):
263263
def__add__(self,other):
264264
"""Add two input/output systems (parallel interconnection)"""
265265
# Convert other to an I/O system if needed
266-
other=_convert_static_iosystem(other)
266+
other=_convert_to_iosystem(other)
267267
ifnotisinstance(other,InputOutputSystem):
268268
returnNotImplemented
269269

@@ -284,7 +284,7 @@ def __add__(self, other):
284284
def__radd__(self,other):
285285
"""Parallel addition of input/output system to a compatible object."""
286286
# Convert other to an I/O system if needed
287-
other=_convert_static_iosystem(other)
287+
other=_convert_to_iosystem(other)
288288
ifnotisinstance(other,InputOutputSystem):
289289
returnNotImplemented
290290

@@ -305,7 +305,7 @@ def __radd__(self, other):
305305
def__sub__(self,other):
306306
"""Subtract two input/output systems (parallel interconnection)"""
307307
# Convert other to an I/O system if needed
308-
other=_convert_static_iosystem(other)
308+
other=_convert_to_iosystem(other)
309309
ifnotisinstance(other,InputOutputSystem):
310310
returnNotImplemented
311311

@@ -329,7 +329,7 @@ def __sub__(self, other):
329329
def__rsub__(self,other):
330330
"""Parallel subtraction of I/O system to a compatible object."""
331331
# Convert other to an I/O system if needed
332-
other=_convert_static_iosystem(other)
332+
other=_convert_to_iosystem(other)
333333
ifnotisinstance(other,InputOutputSystem):
334334
returnNotImplemented
335335
returnother-self
@@ -355,6 +355,10 @@ def __truediv__(self, other):
355355
else:
356356
returnNotImplemented
357357

358+
# Determine if a system is static (memoryless)
359+
def_isstatic(self):
360+
returnself.nstates==0
361+
358362
def_update_params(self,params):
359363
# Update the current parameter values
360364
self._current_params=self.params.copy()
@@ -484,7 +488,7 @@ def feedback(self, other=1, sign=-1, params=None):
484488
485489
"""
486490
# Convert sys2 to an I/O system if needed
487-
other=_convert_static_iosystem(other)
491+
other=_convert_to_iosystem(other)
488492

489493
# Make sure systems can be interconnected
490494
ifself.noutputs!=other.ninputsorother.noutputs!=self.ninputs:
@@ -932,6 +936,7 @@ def _out(self, t, x, u):
932936
# Make the full set of subsystem outputs to system output
933937
returnself.output_map @ylist
934938

939+
# Find steady state (static) inputs and outputs
935940
def_compute_static_io(self,t,x,u):
936941
# Figure out the total number of inputs and outputs
937942
(ninputs,noutputs)=self.connect_map.shape
@@ -1711,8 +1716,8 @@ def ufun(t):
17111716
dt= (t-T[idx-1])/ (T[idx]-T[idx-1])
17121717
returnU[...,idx-1]* (1.-dt)+U[...,idx]*dt
17131718

1714-
# Check to make sure this is not a static function
1715-
ifnstates==0:# No states => map input to output
1719+
# Check to make suresee ifthis is a static function
1720+
ifsys.nstates==0:
17161721
# Make sure the user gave a time vector for evaluation (or 'T')
17171722
ift_evalisNone:
17181723
# User overrode t_eval with None, but didn't give us the times...
@@ -2924,8 +2929,8 @@ def _process_vector_argument(arg, name, size):
29242929
returnval,nelem
29252930

29262931

2927-
# Utility function to create an I/O system froma static gain
2928-
def_convert_static_iosystem(sys):
2932+
# Utility function to create an I/O system(fromnumber or array)
2933+
def_convert_to_iosystem(sys):
29292934
# If we were given an I/O system, do nothing
29302935
ifisinstance(sys,InputOutputSystem):
29312936
returnsys

‎control/statesp.py‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,9 @@ def __init__(self, *args, **kwargs):
229229
self.C=C
230230
self.D=D
231231

232+
# Determine if the system is static (memoryless)
233+
static= (A.size==0)
234+
232235
#
233236
# Process keyword arguments
234237
#
@@ -242,7 +245,7 @@ def __init__(self, *args, **kwargs):
242245
{'inputs':B.shape[1],'outputs':C.shape[0],
243246
'states':A.shape[0]}
244247
name,inputs,outputs,states,dt=_process_iosys_keywords(
245-
kwargs,defaults,static=(A.size==0))
248+
kwargs,defaults,static=static)
246249

247250
# Create updfcn and outfcn
248251
updfcn=lambdat,x,u,params: \
@@ -257,7 +260,7 @@ def __init__(self, *args, **kwargs):
257260
states=states,dt=dt,**kwargs)
258261

259262
# Reset shapes if the system is static
260-
ifself._isstatic():
263+
ifstatic:
261264
A.shape= (0,0)
262265
B.shape= (0,self.ninputs)
263266
C.shape= (self.noutputs,0)

‎control/xferfcn.py‎

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -219,15 +219,22 @@ def __init__(self, *args, **kwargs):
219219
raiseValueError("display_format must be 'poly' or 'zpk',"
220220
" got '%s'"%self.display_format)
221221

222-
# Determine if the transfer function is static (needed for dt)
222+
#
223+
# Determine if the transfer function is static (memoryless)
224+
#
225+
# True if and only if all of the numerator and denominator
226+
# polynomials of the (MIMO) transfer function are zeroth order.
227+
#
223228
static=True
224229
forarrin [num,den]:
230+
# Iterate using refs_OK since num and den are ndarrays of ndarrays
225231
forpoly_innp.nditer(arr,flags=['refs_ok']):
226232
ifpoly_.item().size>1:
227233
static=False
228234
break
229235
ifnotstatic:
230236
break
237+
self._static=static# retain for later usage
231238

232239
defaults=args[0]iflen(args)==1else \
233240
{'inputs':num.shape[1],'outputs':num.shape[0]}
@@ -1283,16 +1290,9 @@ def dcgain(self, warn_infinite=False):
12831290
"""
12841291
returnself._dcgain(warn_infinite)
12851292

1293+
# Determine if a system is static (memoryless)
12861294
def_isstatic(self):
1287-
"""returns True if and only if all of the numerator and denominator
1288-
polynomials of the (possibly MIMO) transfer function are zeroth order,
1289-
that is, if the system has no dynamics. """
1290-
forlist_of_polysinself.num,self.den:
1291-
forrowinlist_of_polys:
1292-
forpoly_inrow:
1293-
iflen(poly_)>1:
1294-
returnFalse
1295-
returnTrue
1295+
returnself._static# Check done at initialization
12961296

12971297
# Attributes for differentiation and delay
12981298
#

‎doc/descfcn.rst‎

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,21 @@ Describing Functions
66
====================
77

88
For nonlinear systems consisting of a feedback connection between a
9-
linear system and astaticnonlinearity, it is possible to obtain a
9+
linear system and a nonlinearity, it is possible to obtain a
1010
generalization of Nyquist's stability criterion based on the idea of
1111
describing functions. The basic concept involves approximating the
12-
response of astaticnonlinearity to an input:math:`u = A e^{j\omega
13-
t}` asan output:math:`y = N(A) (A e^{j\omega t})`, where:math:`N(A)
14-
\in\mathbb{C}` represents the (amplitude-dependent) gain and phase
12+
response of a nonlinearity to an input:math:`u = A e^{j\omega t}` as
13+
an output:math:`y = N(A) (A e^{j\omega t})`, where:math:`N(A)\in
14+
\mathbb{C}` represents the (amplitude-dependent) gain and phase
1515
associated with the nonlinearity.
1616

17+
In the most common case, the nonlinearity will be a static,
18+
time-invariant nonlinear function:math:`y = h(u)`. However,
19+
describing functions can be defined for nonlinear input/output systems
20+
that have some internal memory, such as hysteresis or backlash. For
21+
simplicity, we take the nonlinearity to be static (memoryless) in the
22+
description below, unless otherwise specified.
23+
1724
Stability analysis of a linear system:math:`H(s)` with a feedback
1825
nonlinearity:math:`F(x)` is done by looking for amplitudes:math:`A`
1926
and frequencies:math:`\omega` such that

‎doc/nlsys.rst‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ Discrete time systems are also supported and have dynamics of the form
2323
x[t+1] &= f(t, x[t], u[t],\theta), \\
2424
y[t] &= h(t, x[t], u[t],\theta).
2525
26+
A nonlinear input/output model is said to be "static" if the output
27+
:math:`y(t)` at any given time:math:`t` depends only on the input
28+
:math:`u(t)` at that same time:math:`t` and not on past or future
29+
values of:math:`u`.
30+
2631

2732
.. _sec-nonlinear-models:
2833

@@ -47,7 +52,9 @@ dynamics of the system can be in continuous or discrete time (use the
4752
The output function `outfcn` is used to specify the outputs of the
4853
system and has the same calling signature as `updfcn`. If it is not
4954
specified, then the output of the system is set equal to the system
50-
state. Otherwise, it should return an array of shape (p,).
55+
state. Otherwise, it should return an array of shape (p,). If a
56+
input/output system is static, the state `x` should still be passed to
57+
the output function, but the state is ignored.
5158

5259
Note that the number of states, inputs, and outputs should generally
5360
be explicitly specified, although some operations can infer the

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp