Skip to content

Commit 23c4b09

Browse files
committed
fixes/cleanups suggested by @murrayrm
1 parent 64d0dde commit 23c4b09

File tree

3 files changed

+28
-24
lines changed

3 files changed

+28
-24
lines changed

control/iosys.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ def _rhs(self, t, x, u, params={}):
370370
NotImplemented("Evaluation not implemented for system of type ",
371371
type(self))
372372

373-
def dynamics(self, t, x, u, params={}):
373+
def dynamics(self, t, x, u):
374374
"""Compute the dynamics of a differential or difference equation.
375375
376376
Given time `t`, input `u` and state `x`, returns the value of the
@@ -401,7 +401,7 @@ def dynamics(self, t, x, u, params={}):
401401
-------
402402
dx/dt or x[t+dt] : ndarray
403403
"""
404-
return self._rhs(t, x, u, params)
404+
return self._rhs(t, x, u)
405405

406406
def _out(self, t, x, u, params={}):
407407
"""Evaluate the output of a system at a given state, input, and time
@@ -415,7 +415,7 @@ def _out(self, t, x, u, params={}):
415415
# If no output function was defined in subclass, return state
416416
return x
417417

418-
def output(self, t, x, u, params={}):
418+
def output(self, t, x, u):
419419
"""Compute the output of the system
420420
421421
Given time `t`, input `u` and state `x`, returns the output of the
@@ -438,7 +438,7 @@ def output(self, t, x, u, params={}):
438438
-------
439439
y : ndarray
440440
"""
441-
return self._out(t, x, u, params)
441+
return self._out(t, x, u)
442442

443443
def set_inputs(self, inputs, prefix='u'):
444444
"""Set the number/names of the system inputs.
@@ -768,6 +768,7 @@ def _out(self, t, x, u):
768768
+ np.dot(self.D, np.reshape(u, (-1, 1)))
769769
return np.array(y).reshape((-1,))
770770

771+
771772
class NonlinearIOSystem(InputOutputSystem):
772773
"""Nonlinear I/O system.
773774

control/statesp.py

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,7 +1227,7 @@ def dcgain(self, warn_infinite=False):
12271227
return self(0, warn_infinite=warn_infinite) if self.isctime() \
12281228
else self(1, warn_infinite=warn_infinite)
12291229

1230-
def dynamics(self, *args):
1230+
def dynamics(self, t, x, u=0):
12311231
"""Compute the dynamics of the system
12321232
12331233
Given input `u` and state `x`, returns the dynamics of the state-space
@@ -1242,11 +1242,10 @@ def dynamics(self, *args):
12421242
12431243
The inputs `x` and `u` must be of the correct length for the system.
12441244
1245-
The calling signature is ``out = sys.dynamics(t, x[, u])``
12461245
The first argument `t` is ignored because :class:`StateSpace` systems
12471246
are time-invariant. It is included so that the dynamics can be passed
1248-
to most numerical integrators, such as scipy's `integrate.solve_ivp` and
1249-
for consistency with :class:`IOSystem` systems.
1247+
to most numerical integrators, such as :func:`scipy.integrate.solve_ivp`
1248+
and for consistency with :class:`IOSystem` systems.
12501249
12511250
Parameters
12521251
----------
@@ -1261,23 +1260,19 @@ def dynamics(self, *args):
12611260
-------
12621261
dx/dt or x[t+dt] : ndarray
12631262
"""
1264-
if len(args) not in (2, 3):
1265-
raise ValueError("received" + len(args) + "args, expected 2 or 3")
1266-
1267-
x = np.reshape(args[1], (-1, 1)) # force to a column in case matrix
1263+
x = np.reshape(x, (-1, 1)) # force to a column in case matrix
12681264
if np.size(x) != self.nstates:
12691265
raise ValueError("len(x) must be equal to number of states")
1270-
1271-
if len(args) == 2: # received t and x, ignore t
1266+
if u is 0:
12721267
return self.A.dot(x).reshape((-1,)) # return as row vector
12731268
else: # received t, x, and u, ignore t
1274-
u = np.reshape(args[2], (-1, 1)) # force to a column in case matrix
1269+
u = np.reshape(u, (-1, 1)) # force to a column in case matrix
12751270
if np.size(u) != self.ninputs:
12761271
raise ValueError("len(u) must be equal to number of inputs")
12771272
return self.A.dot(x).reshape((-1,)) \
12781273
+ self.B.dot(u).reshape((-1,)) # return as row vector
12791274

1280-
def output(self, *args):
1275+
def output(self, t, x, u=0):
12811276
"""Compute the output of the system
12821277
12831278
Given input `u` and state `x`, returns the output `y` of the
@@ -1287,7 +1282,6 @@ def output(self, *args):
12871282
12881283
where A and B are the state-space matrices of the system.
12891284
1290-
The calling signature is ``y = sys.output(t, x[, u])``
12911285
The first argument `t` is ignored because :class:`StateSpace` systems
12921286
are time-invariant. It is included so that the dynamics can be passed
12931287
to most numerical integrators, such as scipy's `integrate.solve_ivp` and
@@ -1308,17 +1302,14 @@ def output(self, *args):
13081302
-------
13091303
y : ndarray
13101304
"""
1311-
if len(args) not in (2, 3):
1312-
raise ValueError("received"+len(args)+"args, expected 2 or 3")
1313-
1314-
x = np.reshape(args[1], (-1, 1)) # force to a column in case matrix
1305+
x = np.reshape(x, (-1, 1)) # force to a column in case matrix
13151306
if np.size(x) != self.nstates:
13161307
raise ValueError("len(x) must be equal to number of states")
13171308

1318-
if len(args) == 2: # received t and x, ignore t
1309+
if u is 0:
13191310
return self.C.dot(x).reshape((-1,)) # return as row vector
13201311
else: # received t, x, and u, ignore t
1321-
u = np.reshape(args[2], (-1, 1)) # force to a column in case matrix
1312+
u = np.reshape(u, (-1, 1)) # force to a column in case matrix
13221313
if np.size(u) != self.ninputs:
13231314
raise ValueError("len(u) must be equal to number of inputs")
13241315
return self.C.dot(x).reshape((-1,)) \

control/tests/statesp_test.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,12 @@ def test_dynamics_and_output_siso(self, x, u, sys121):
773773
assert_array_almost_equal(
774774
sys121.output(0, x, u),
775775
sys121.C.dot(x).reshape((-1,)) + sys121.D.dot(u).reshape((-1,)))
776+
assert_array_almost_equal(
777+
sys121.dynamics(0, x),
778+
sys121.A.dot(x).reshape((-1,)))
779+
assert_array_almost_equal(
780+
sys121.output(0, x),
781+
sys121.C.dot(x).reshape((-1,)))
776782

777783
# too few and too many states and inputs
778784
@pytest.mark.parametrize('x', [0, 1, [], [1, 2, 3], np.atleast_1d(2)])
@@ -799,6 +805,12 @@ def test_dynamics_and_output_mimo(self, x, u, sys222):
799805
assert_array_almost_equal(
800806
sys222.output(0, x, u),
801807
sys222.C.dot(x).reshape((-1,)) + sys222.D.dot(u).reshape((-1,)))
808+
assert_array_almost_equal(
809+
sys222.dynamics(0, x),
810+
sys222.A.dot(x).reshape((-1,)))
811+
assert_array_almost_equal(
812+
sys222.output(0, x),
813+
sys222.C.dot(x).reshape((-1,)))
802814

803815
# too few and too many states and inputs
804816
@pytest.mark.parametrize('x', [0, 1, [1, 1, 1]])
@@ -807,7 +819,7 @@ def test_error_x_dynamics_mimo(self, x, sys222):
807819
sys222.dynamics(0, x)
808820
with pytest.raises(ValueError):
809821
sys222.output(0, x)
810-
@pytest.mark.parametrize('u', [0, 1, [1, 1, 1]])
822+
@pytest.mark.parametrize('u', [1, [1, 1, 1]])
811823
def test_error_u_dynamics_mimo(self, u, sys222):
812824
with pytest.raises(ValueError):
813825
sys222.dynamics(0, (1, 1), u)

0 commit comments

Comments
 (0)