Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix issue with multiplying MIMO LTI system by scalar #1078

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions control/frdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,14 +261,20 @@ def __init__(self, *args, **kwargs):

# create interpolation functions
if smooth:
# Set the order of the fit
if self.omega.size < 2:
raise ValueError("can't smooth with only 1 frequency")
degree = 3 if self.omega.size > 3 else self.omega.size - 1

self.ifunc = empty((self.fresp.shape[0], self.fresp.shape[1]),
dtype=tuple)
for i in range(self.fresp.shape[0]):
for j in range(self.fresp.shape[1]):
self.ifunc[i, j], u = splprep(
u=self.omega, x=[real(self.fresp[i, j, :]),
imag(self.fresp[i, j, :])],
w=1.0/(absolute(self.fresp[i, j, :]) + 0.001), s=0.0)
w=1.0/(absolute(self.fresp[i, j, :]) + 0.001),
s=0.0, k=degree)
else:
self.ifunc = None

Expand Down Expand Up @@ -392,7 +398,12 @@ def __add__(self, other):

# Convert the second argument to a frequency response function.
# or re-base the frd to the current omega (if needed)
other = _convert_to_frd(other, omega=self.omega)
if isinstance(other, (int, float, complex, np.number)):
other = _convert_to_frd(
other, omega=self.omega,
inputs=self.ninputs, outputs=self.noutputs)
else:
other = _convert_to_frd(other, omega=self.omega)

# Check that the input-output sizes are consistent.
if self.ninputs != other.ninputs:
Expand Down
18 changes: 18 additions & 0 deletions control/tests/lti_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,3 +350,21 @@ def test_subsys_indexing(fcn, outdx, inpdx, key):
np.testing.assert_almost_equal(
subsys_fcn.frequency_response(omega).response,
subsys_chk.frequency_response(omega).response)


@slycotonly
@pytest.mark.parametrize("op", [
'__mul__', '__rmul__', '__add__', '__radd__', '__sub__', '__rsub__'])
@pytest.mark.parametrize("fcn", [ct.ss, ct.tf, ct.frd])
def test_scalar_algebra(op, fcn):
sys_ss = ct.rss(4, 2, 2)
match fcn:
case ct.ss:
sys = sys_ss
case ct.tf:
sys = ct.tf(sys_ss)
case ct.frd:
sys = ct.frd(sys_ss, [0.1, 1, 10])

scaled = getattr(sys, op)(2)
np.testing.assert_almost_equal(getattr(sys(1j), op)(2), scaled(1j))
17 changes: 8 additions & 9 deletions control/xferfcn.py
Original file line number Diff line number Diff line change
Expand Up @@ -634,11 +634,11 @@ def __mul__(self, other):
from .statesp import StateSpace

# Convert the second argument to a transfer function.
if isinstance(other, StateSpace):
if isinstance(other, (StateSpace, np.ndarray)):
other = _convert_to_transfer_function(other)
elif isinstance(other, (int, float, complex, np.number, np.ndarray)):
other = _convert_to_transfer_function(other, inputs=self.ninputs,
outputs=self.noutputs)
elif isinstance(other, (int, float, complex, np.number)):
# Multiply by a scaled identity matrix (transfer function)
other = _convert_to_transfer_function(np.eye(self.ninputs) * other)
if not isinstance(other, TransferFunction):
return NotImplemented

Expand Down Expand Up @@ -681,8 +681,8 @@ def __rmul__(self, other):

# Convert the second argument to a transfer function.
if isinstance(other, (int, float, complex, np.number)):
other = _convert_to_transfer_function(other, inputs=self.ninputs,
outputs=self.ninputs)
# Multiply by a scaled identity matrix (transfer function)
other = _convert_to_transfer_function(np.eye(self.noutputs) * other)
else:
other = _convert_to_transfer_function(other)

Expand Down Expand Up @@ -723,9 +723,8 @@ def __truediv__(self, other):
"""Divide two LTI objects."""

if isinstance(other, (int, float, complex, np.number)):
other = _convert_to_transfer_function(
other, inputs=self.ninputs,
outputs=self.ninputs)
# Multiply by a scaled identity matrix (transfer function)
other = _convert_to_transfer_function(np.eye(self.ninputs) * other)
else:
other = _convert_to_transfer_function(other)

Expand Down
Loading