From f17c9194456b659c390c0190d14d2c38f5bc932c Mon Sep 17 00:00:00 2001 From: Richard Murray Date: Wed, 3 Aug 2022 21:34:27 -0700 Subject: [PATCH 1/3] fix timebase bug in InterconnectedSystem (issue #754) --- control/iosys.py | 7 +++++-- control/tests/timebase_test.py | 37 ++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 control/tests/timebase_test.py diff --git a/control/iosys.py b/control/iosys.py index 6008cf43d..ce717c0fb 100644 --- a/control/iosys.py +++ b/control/iosys.py @@ -871,9 +871,12 @@ def __init__(self, syslist, connections=[], inplist=[], outlist=[], if not isinstance(outlist, (list, tuple)): outlist = [outlist] - # Process keyword arguments + # Check if dt argument was given; if not, pull from systems + dt = kwargs.pop('dt', None) + + # Process keyword arguments (except dt) defaults = {'inputs': len(inplist), 'outputs': len(outlist)} - name, inputs, outputs, states, dt = _process_namedio_keywords( + name, inputs, outputs, states, _ = _process_namedio_keywords( kwargs, defaults, end=True) # Initialize the system list and index diff --git a/control/tests/timebase_test.py b/control/tests/timebase_test.py new file mode 100644 index 000000000..50d69fb88 --- /dev/null +++ b/control/tests/timebase_test.py @@ -0,0 +1,37 @@ +import pytest +import inspect +import numpy as np +import control as ct + +@pytest.mark.parametrize( + "dt1, dt2, dt3", [ + (0, 0, 0), + (0, 0.1, ValueError), + (0, None, 0), + (0.1, 0, ValueError), + (0.1, 0.1, 0.1), + (0.1, None, 0.1), + (None, 0, 0), + (None, 0.1, 0.1), + (None, None, None), + (0.2, None, 0.2), + (0.2, 0.1, ValueError), + ]) +@pytest.mark.parametrize("op", [ct.series, ct.parallel, ct.feedback]) +@pytest.mark.parametrize("type", [ct.StateSpace, ct.ss, ct.tf]) +def test_composition(dt1, dt2, dt3, op, type): + # Define the system + A, B, C, D = [[1, 1], [0, 1]], [[0], [1]], [[1, 0]], 0 + sys1 = ct.StateSpace(A, B, C, D, dt1) + sys2 = ct.StateSpace(A, B, C, D, dt2) + + # Convert to the desired form + sys1 = type(sys1) + sys2 = type(sys2) + + if inspect.isclass(dt3) and issubclass(dt3, Exception): + with pytest.raises(dt3, match="incompatible timebases"): + sys3 = op(sys1, sys2) + else: + sys3 = op(sys1, sys2) + assert sys3.dt == dt3 From 3c13f2c58eb17f37a95551a5171dc7c9ad45bd6b Mon Sep 17 00:00:00 2001 From: Richard Murray Date: Wed, 3 Aug 2022 21:54:06 -0700 Subject: [PATCH 2/3] add additional checks for overriding timebase --- control/tests/timebase_test.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/control/tests/timebase_test.py b/control/tests/timebase_test.py index 50d69fb88..f245f625f 100644 --- a/control/tests/timebase_test.py +++ b/control/tests/timebase_test.py @@ -35,3 +35,28 @@ def test_composition(dt1, dt2, dt3, op, type): else: sys3 = op(sys1, sys2) assert sys3.dt == dt3 + + +@pytest.mark.parametrize("dt", [None, 0, 0.1]) +def test_composition_override(dt): + # Define the system + A, B, C, D = [[1, 1], [0, 1]], [[0], [1]], [[1, 0]], 0 + sys1 = ct.ss(A, B, C, D, None, inputs='u1', outputs='y1') + sys2 = ct.ss(A, B, C, D, None, inputs='y1', outputs='y2') + + # Show that we can override the type + sys3 = ct.interconnect([sys1, sys2], inputs='u1', outputs='y2', dt=dt) + assert sys3.dt == dt + + # Overriding the type with an inconsistent type generates an error + sys1 = ct.StateSpace(A, B, C, D, 0.1, inputs='u1', outputs='y1') + if dt != 0.1 and dt is not None: + with pytest.raises(ValueError, match="incompatible timebases"): + sys3 = ct.interconnect( + [sys1, sys2], inputs='u1', outputs='y2', dt=dt) + + sys1 = ct.StateSpace(A, B, C, D, 0, inputs='u1', outputs='y1') + if dt != 0 and dt is not None: + with pytest.raises(ValueError, match="incompatible timebases"): + sys3 = ct.interconnect( + [sys1, sys2], inputs='u1', outputs='y2', dt=dt) From cf304794745baf4aa246df30feccdc3b0c43a490 Mon Sep 17 00:00:00 2001 From: Richard Murray Date: Wed, 3 Aug 2022 22:56:47 -0700 Subject: [PATCH 3/3] added tests for dt=True case per @sawyerbfuller suggestion --- control/tests/timebase_test.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/control/tests/timebase_test.py b/control/tests/timebase_test.py index f245f625f..a391d2fe7 100644 --- a/control/tests/timebase_test.py +++ b/control/tests/timebase_test.py @@ -8,12 +8,19 @@ (0, 0, 0), (0, 0.1, ValueError), (0, None, 0), + (0, True, ValueError), (0.1, 0, ValueError), (0.1, 0.1, 0.1), (0.1, None, 0.1), + (0.1, True, 0.1), (None, 0, 0), (None, 0.1, 0.1), (None, None, None), + (None, True, True), + (True, 0, ValueError), + (True, 0.1, 0.1), + (True, None, True), + (True, True, True), (0.2, None, 0.2), (0.2, 0.1, ValueError), ]) 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