10
10
11
11
import re
12
12
import warnings
13
+ import pytest
13
14
14
15
import numpy as np
15
- import pytest
16
+ from math import sqrt
16
17
17
18
import control as ct
18
19
from control import iosys as ios
@@ -238,7 +239,7 @@ def test_linearize_named_signals(self, kincar):
238
239
assert lin_nocopy .find_state ('x' ) is None
239
240
240
241
# if signal names are provided, they should override those of kincar
241
- linearized_newnames = kincar .linearize ([0 , 0 , 0 ], [0 , 0 ],
242
+ linearized_newnames = kincar .linearize ([0 , 0 , 0 ], [0 , 0 ],
242
243
name = 'linearized' ,
243
244
copy_names = True , inputs = ['v2' , 'phi2' ], outputs = ['x2' ,'y2' ])
244
245
assert linearized_newnames .name == 'linearized'
@@ -766,8 +767,8 @@ def nlsys_output(t, x, u, params):
766
767
np .testing .assert_allclose (ios_t , lin_t ,atol = 0.002 ,rtol = 0. )
767
768
np .testing .assert_allclose (ios_y , lin_y ,atol = 0.002 ,rtol = 0. )
768
769
769
- def test_find_eqpts (self , tsys ):
770
- """Test find_eqpt function"""
770
+ def test_find_eqpts_dfan (self , tsys ):
771
+ """Test find_eqpt function on dfan example """
771
772
# Simple equilibrium point with no inputs
772
773
nlsys = ios .NonlinearIOSystem (predprey )
773
774
xeq , ueq , result = ios .find_eqpt (
@@ -836,7 +837,7 @@ def test_find_eqpts(self, tsys):
836
837
np .testing .assert_array_almost_equal (
837
838
nlsys_full ._rhs (0 , xeq , ueq )[- 4 :], np .zeros ((4 ,)), decimal = 5 )
838
839
839
- # The same test as previous , but now all constraints are in the state vector
840
+ # Same test as before , but now all constraints are in the state vector
840
841
nlsys_full = ios .NonlinearIOSystem (pvtol_full , None )
841
842
xeq , ueq , result = ios .find_eqpt (
842
843
nlsys_full , [0 , 0 , 0.1 , 0.1 , 0 , 0 ], [0.01 , 4 * 9.8 ],
@@ -1482,7 +1483,7 @@ def test_linear_interconnection():
1482
1483
tf_siso = ct .tf (1 , [0.1 , 1 ])
1483
1484
ss_siso = ct .ss (1 , 2 , 1 , 1 )
1484
1485
nl_siso = ios .NonlinearIOSystem (
1485
- lambda t , x , u , params : x * x ,
1486
+ lambda t , x , u , params : x * x ,
1486
1487
lambda t , x , u , params : u * x , states = 1 , inputs = 1 , outputs = 1 )
1487
1488
1488
1489
# Create a "regular" InterconnectedSystem
@@ -1530,7 +1531,7 @@ def test_linear_interconnection():
1530
1531
np .testing .assert_array_almost_equal (io_connect .C , ss_connect .C )
1531
1532
np .testing .assert_array_almost_equal (io_connect .D , ss_connect .D )
1532
1533
1533
- # make sure interconnections of linear systems are linear and
1534
+ # make sure interconnections of linear systems are linear and
1534
1535
# if a nonlinear system is included then system is nonlinear
1535
1536
assert isinstance (ss_siso * ss_siso , ios .LinearIOSystem )
1536
1537
assert isinstance (tf_siso * ss_siso , ios .LinearIOSystem )
@@ -1541,7 +1542,7 @@ def test_linear_interconnection():
1541
1542
assert ~ isinstance (tf_siso * nl_siso , ios .LinearIOSystem )
1542
1543
assert ~ isinstance (nl_siso * tf_siso , ios .LinearIOSystem )
1543
1544
assert ~ isinstance (nl_siso * nl_siso , ios .LinearIOSystem )
1544
-
1545
+
1545
1546
1546
1547
def predprey (t , x , u , params = {}):
1547
1548
"""Predator prey dynamics"""
@@ -1898,3 +1899,73 @@ def test_rss():
1898
1899
with pytest .warns (UserWarning , match = "may be interpreted as continuous" ):
1899
1900
sys = ct .drss (2 , 1 , 1 , dt = None )
1900
1901
assert np .all (np .abs (sys .poles ()) < 1 )
1902
+
1903
+
1904
+ def eqpt_rhs (t , x , u , params ):
1905
+ return np .array ([x [0 ]/ 2 + u [0 ], x [0 ] - x [1 ]** 2 + u [1 ], x [1 ] - x [2 ]])
1906
+
1907
+ def eqpt_out (t , x , u , params ):
1908
+ return np .array ([x [0 ], x [1 ] + u [1 ]])
1909
+
1910
+ @pytest .mark .parametrize (
1911
+ "x0, ix, u0, iu, y0, iy, dx0, idx, dt, x_expect, u_expect" , [
1912
+ # Equilibrium points with input given
1913
+ (0 , None , 0 , None , None , None , None , None , 0 , [0 , 0 , 0 ], [0 , 0 ]),
1914
+ (0 , None , 0 , None , None , None , None , None , None , [0 , 0 , 0 ], [0 , 0 ]),
1915
+ ([0.9 , 0.9 , 0.9 ], None , [- 1 , 0 ], None , None , None , None , None , 0 ,
1916
+ [2 , sqrt (2 ), sqrt (2 )], [- 1 , 0 ]),
1917
+ ([0.9 , - 0.9 , 0.9 ], None , [- 1 , 0 ], None , None , None , None , None , 0 ,
1918
+ [2 , - sqrt (2 ), - sqrt (2 )], [- 1 , 0 ]), # same input, different eqpt
1919
+ (0 , None , 0 , None , None , None , None , None , 1 , [0 , 0 , 0 ], [0 , 0 ]), #DT
1920
+ (0 , None , [- 1 , 0 ], None , None , None , None , None , 1 , None , None ), #DT
1921
+ ([0 , - 0.1 , 0 ], None , [0 , - 0.25 ], None , None , None , None , None , 1 , #DT
1922
+ [0 , - 0.5 , - 0.25 ], [0 , - 0.25 ]),
1923
+
1924
+ # Equilibrium points with output given
1925
+ ([0.9 , 0.9 , 0.9 ], None , [- 0.9 , 0 ], None , [2 , sqrt (2 )], None , None ,
1926
+ None , 0 , [2 , sqrt (2 ), sqrt (2 )], [- 1 , 0 ]),
1927
+ (0 , None , [0 , - 0.25 ], None , [0 , - 0.75 ], None , None , None , 1 , #DT
1928
+ [0 , - 0.5 , - 0.25 ], [0 , - 0.25 ]),
1929
+
1930
+ # Equilibrium points with mixture of inputs and outputs given
1931
+ ([0.9 , 0.9 , 0.9 ], None , [- 1 , 0 ], [0 ], [2 , sqrt (2 )], [1 ], None ,
1932
+ None , 0 , [2 , sqrt (2 ), sqrt (2 )], [- 1 , 0 ]),
1933
+ (0 , None , [0 , - 0.22 ], [0 ], [0 , - 0.75 ], [1 ], None , None , 1 , #DT
1934
+ [0 , - 0.5 , - 0.25 ], [0 , - 0.25 ]),
1935
+ ])
1936
+
1937
+ def test_find_eqpt (x0 , ix , u0 , iu , y0 , iy , dx0 , idx , dt , x_expect , u_expect ):
1938
+ sys = ct .NonlinearIOSystem (
1939
+ eqpt_rhs , eqpt_out , dt = dt , states = 3 , inputs = 2 , outputs = 2 )
1940
+
1941
+ xeq , ueq = ct .find_eqpt (
1942
+ sys , x0 , u0 , y0 , ix = ix , iu = iu , iy = iy , dx0 = dx0 , idx = idx )
1943
+
1944
+ # If no equilibrium points, skip remaining tests
1945
+ if x_expect is None :
1946
+ assert xeq is None
1947
+ assert ueq is None
1948
+ return
1949
+
1950
+ # Make sure we are at an appropriate equilibrium point
1951
+ if dt is None or dt == 0 :
1952
+ # Continuous time system
1953
+ np .testing .assert_allclose (eqpt_rhs (0 , xeq , ueq , {}), 0 , atol = 1e-6 )
1954
+ if y0 is not None :
1955
+ y0 = np .array (y0 )
1956
+ iy = np .s_ [:] if iy is None else np .array (iy )
1957
+ np .testing .assert_allclose (
1958
+ eqpt_out (0 , xeq , ueq , {})[iy ], y0 [iy ], atol = 1e-6 )
1959
+
1960
+ else :
1961
+ # Discrete time system
1962
+ np .testing .assert_allclose (eqpt_rhs (0 , xeq , ueq , {}), xeq , atol = 1e-6 )
1963
+ if y0 is not None :
1964
+ y0 = np .array (y0 )
1965
+ iy = np .s_ [:] if iy is None else np .array (iy )
1966
+ np .testing .assert_allclose (
1967
+ eqpt_out (0 , xeq , ueq , {})[iy ], y0 [iy ], atol = 1e-6 )
1968
+
1969
+ # Check that we got the expected result as well
1970
+ np .testing .assert_allclose (np .array (xeq ), x_expect , atol = 1e-6 )
1971
+ np .testing .assert_allclose (np .array (ueq ), u_expect , atol = 1e-6 )
0 commit comments