Skip to content

Commit b9cf384

Browse files
authored
Merge pull request #755 from murrayrm/timebase_bug-03Aug2022
Fix timebase bug in InterconnectedSystem (issue #754)
2 parents a73a03d + cf30479 commit b9cf384

File tree

2 files changed

+74
-2
lines changed

2 files changed

+74
-2
lines changed

control/iosys.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -871,9 +871,12 @@ def __init__(self, syslist, connections=[], inplist=[], outlist=[],
871871
if not isinstance(outlist, (list, tuple)):
872872
outlist = [outlist]
873873

874-
# Process keyword arguments
874+
# Check if dt argument was given; if not, pull from systems
875+
dt = kwargs.pop('dt', None)
876+
877+
# Process keyword arguments (except dt)
875878
defaults = {'inputs': len(inplist), 'outputs': len(outlist)}
876-
name, inputs, outputs, states, dt = _process_namedio_keywords(
879+
name, inputs, outputs, states, _ = _process_namedio_keywords(
877880
kwargs, defaults, end=True)
878881

879882
# Initialize the system list and index

control/tests/timebase_test.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import pytest
2+
import inspect
3+
import numpy as np
4+
import control as ct
5+
6+
@pytest.mark.parametrize(
7+
"dt1, dt2, dt3", [
8+
(0, 0, 0),
9+
(0, 0.1, ValueError),
10+
(0, None, 0),
11+
(0, True, ValueError),
12+
(0.1, 0, ValueError),
13+
(0.1, 0.1, 0.1),
14+
(0.1, None, 0.1),
15+
(0.1, True, 0.1),
16+
(None, 0, 0),
17+
(None, 0.1, 0.1),
18+
(None, None, None),
19+
(None, True, True),
20+
(True, 0, ValueError),
21+
(True, 0.1, 0.1),
22+
(True, None, True),
23+
(True, True, True),
24+
(0.2, None, 0.2),
25+
(0.2, 0.1, ValueError),
26+
])
27+
@pytest.mark.parametrize("op", [ct.series, ct.parallel, ct.feedback])
28+
@pytest.mark.parametrize("type", [ct.StateSpace, ct.ss, ct.tf])
29+
def test_composition(dt1, dt2, dt3, op, type):
30+
# Define the system
31+
A, B, C, D = [[1, 1], [0, 1]], [[0], [1]], [[1, 0]], 0
32+
sys1 = ct.StateSpace(A, B, C, D, dt1)
33+
sys2 = ct.StateSpace(A, B, C, D, dt2)
34+
35+
# Convert to the desired form
36+
sys1 = type(sys1)
37+
sys2 = type(sys2)
38+
39+
if inspect.isclass(dt3) and issubclass(dt3, Exception):
40+
with pytest.raises(dt3, match="incompatible timebases"):
41+
sys3 = op(sys1, sys2)
42+
else:
43+
sys3 = op(sys1, sys2)
44+
assert sys3.dt == dt3
45+
46+
47+
@pytest.mark.parametrize("dt", [None, 0, 0.1])
48+
def test_composition_override(dt):
49+
# Define the system
50+
A, B, C, D = [[1, 1], [0, 1]], [[0], [1]], [[1, 0]], 0
51+
sys1 = ct.ss(A, B, C, D, None, inputs='u1', outputs='y1')
52+
sys2 = ct.ss(A, B, C, D, None, inputs='y1', outputs='y2')
53+
54+
# Show that we can override the type
55+
sys3 = ct.interconnect([sys1, sys2], inputs='u1', outputs='y2', dt=dt)
56+
assert sys3.dt == dt
57+
58+
# Overriding the type with an inconsistent type generates an error
59+
sys1 = ct.StateSpace(A, B, C, D, 0.1, inputs='u1', outputs='y1')
60+
if dt != 0.1 and dt is not None:
61+
with pytest.raises(ValueError, match="incompatible timebases"):
62+
sys3 = ct.interconnect(
63+
[sys1, sys2], inputs='u1', outputs='y2', dt=dt)
64+
65+
sys1 = ct.StateSpace(A, B, C, D, 0, inputs='u1', outputs='y1')
66+
if dt != 0 and dt is not None:
67+
with pytest.raises(ValueError, match="incompatible timebases"):
68+
sys3 = ct.interconnect(
69+
[sys1, sys2], inputs='u1', outputs='y2', dt=dt)

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