Skip to content

Commit dc7d71b

Browse files
authored
Merge pull request #1142 from murrayrm/xferfcn_typecheck-23Mar2025
Add type error checks, unit tests, documentation for real-valued systems
2 parents 394e1c2 + 6b4501e commit dc7d71b

File tree

5 files changed

+16
-6
lines changed

5 files changed

+16
-6
lines changed

control/tests/statesp_test.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ def test_constructor(self, sys322ABCD, dt, argfun):
136136
((np.ones((3, 3)), np.ones((3, 2)),
137137
np.ones((2, 3)), np.ones((2, 3))), ValueError,
138138
r"Incompatible dimensions of D matrix; expected \(2, 2\)"),
139+
(([1j], 2, 3, 0), TypeError, "real number, not 'complex'"),
139140
])
140141
def test_constructor_invalid(self, args, exc, errmsg):
141142
"""Test invalid input to StateSpace() constructor"""

control/tests/xferfcn_test.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ def test_constructor_bad_input_type(self):
4949
[[4, 5], [6, 7]]],
5050
[[[6, 7], [4, 5]],
5151
[[2, 3]]])
52+
53+
with pytest.raises(TypeError, match="unsupported data type"):
54+
ct.tf([1j], [1, 2, 3])
55+
5256
# good input
5357
TransferFunction([[[0, 1], [2, 3]],
5458
[[4, 5], [6, 7]]],

control/xferfcn.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1954,6 +1954,7 @@ def _clean_part(data, name="<unknown>"):
19541954
19551955
"""
19561956
valid_types = (int, float, complex, np.number)
1957+
unsupported_types = (complex, np.complexfloating)
19571958
valid_collection = (list, tuple, ndarray)
19581959

19591960
if isinstance(data, np.ndarray) and data.ndim == 2 and \
@@ -1998,8 +1999,11 @@ def _clean_part(data, name="<unknown>"):
19981999
for i in range(out.shape[0]):
19992000
for j in range(out.shape[1]):
20002001
for k in range(len(out[i, j])):
2001-
if isinstance(out[i, j][k], (int, np.int32, np.int64)):
2002+
if isinstance(out[i, j][k], (int, np.integer)):
20022003
out[i, j][k] = float(out[i, j][k])
2004+
elif isinstance(out[i, j][k], unsupported_types):
2005+
raise TypeError(
2006+
f"unsupported data type: {type(out[i, j][k])}")
20032007
return out
20042008

20052009

doc/linear.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ of linear time-invariant (LTI) systems:
3939
y &= C x + D u
4040
4141
where :math:`u` is the input, :math:`y` is the output, and :math:`x`
42-
is the state.
42+
is the state. All vectors and matrices must be real-valued.
4343

4444
To create a state space system, use the :func:`ss` function:
4545

@@ -94,7 +94,8 @@ transfer functions
9494
{b_0 s^n + b_1 s^{n-1} + \cdots + b_n},
9595
9696
where :math:`n` is greater than or equal to :math:`m` for a proper
97-
transfer function. Improper transfer functions are also allowed.
97+
transfer function. Improper transfer functions are also allowed. All
98+
coefficients must be real-valued.
9899

99100
To create a transfer function, use the :func:`tf` function::
100101

examples/cruise.ipynb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -420,8 +420,8 @@
420420
"name": "stdout",
421421
"output_type": "stream",
422422
"text": [
423-
"system: a = (0.010124405669387215-0j) , b = (1.3203061238159202+0j)\n",
424-
"pzcancel: kp = 0.5 , ki = (0.005062202834693608+0j) , 1/(kp b) = (1.5148002148317266+0j)\n",
423+
"system: a = 0.010124405669387215 , b = 1.3203061238159202\n",
424+
"pzcancel: kp = 0.5 , ki = 0.005062202834693608 , 1/(kp b) = 1.5148002148317266\n",
425425
"sfb_int: K = 0.5 , ki = 0.1\n"
426426
]
427427
},
@@ -442,7 +442,7 @@
442442
"\n",
443443
"# Construction a controller that cancels the pole\n",
444444
"kp = 0.5\n",
445-
"a = -P.poles()[0]\n",
445+
"a = -P.poles()[0].real\n",
446446
"b = np.real(P(0)) * a\n",
447447
"ki = a * kp\n",
448448
"control_pz = ct.TransferFunction(\n",

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy