Skip to content

Commit 4792163

Browse files
committed
Removed epsilon perturbation value in solve_passivity_LMI. Change unit test to reflect scaling values from empirical testing.
1 parent 9d65bf8 commit 4792163

2 files changed

Lines changed: 28 additions & 23 deletions

File tree

control/passivity.py

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
except ImportError:
1515
cvx = None
1616

17-
eps = np.nextafter(0, 1)
1817

1918
__all__ = ["get_output_fb_index", "get_input_ff_index", "ispassive",
2019
"solve_passivity_LMI"]
@@ -28,8 +27,8 @@ def solve_passivity_LMI(sys, rho=None, nu=None):
2827
passive. Inputs of None for `rho` or `nu` indicate that the function should
2928
solve for that index (they are mutually exclusive, they can't both be
3029
None, otherwise you're trying to solve a nonconvex bilinear matrix
31-
inequality.) The last element of `solution` is either the output or input
32-
passivity index, for `rho` = None and `nu` = None respectively.
30+
inequality.) The last element of the output `solution` is either the output or input
31+
passivity index, for `rho` = None and `nu` = None respectively.
3332
3433
The sources for the algorithm are:
3534
@@ -74,11 +73,8 @@ def solve_passivity_LMI(sys, rho=None, nu=None):
7473
D = sys.D
7574

7675
# account for strictly proper systems
77-
[n, m] = D.shape
78-
D = D + eps * np.eye(n, m)
79-
76+
[_, m] = D.shape
8077
[n, _] = A.shape
81-
A = A - eps*np.eye(n)
8278

8379
def make_LMI_matrix(P, rho, nu, one):
8480
q = sys.noutputs
@@ -113,7 +109,7 @@ def make_P_basis_matrices(n, rho, nu):
113109
P[i, j] = 1
114110
P[j, i] = 1
115111
matrix_list.append(make_LMI_matrix(P, 0, 0, 0).flatten())
116-
zeros = eps*np.eye(n)
112+
zeros = 0.0*np.eye(n)
117113
if rho is None:
118114
matrix_list.append(make_LMI_matrix(zeros, 1, 0, 0).flatten())
119115
elif nu is None:
@@ -149,9 +145,9 @@ def P_pos_def_constraint(n):
149145
if rho is not None and nu is not None:
150146
sys_constants = -make_LMI_matrix(np.zeros_like(A), rho, nu, 1.0)
151147
elif rho is not None:
152-
sys_constants = -make_LMI_matrix(np.zeros_like(A), rho, eps, 1.0)
148+
sys_constants = -make_LMI_matrix(np.zeros_like(A), rho, 0.0, 1.0)
153149
elif nu is not None:
154-
sys_constants = -make_LMI_matrix(np.zeros_like(A), eps, nu, 1.0)
150+
sys_constants = -make_LMI_matrix(np.zeros_like(A), 0.0, nu, 1.0)
155151

156152
sys_coefficents = np.vstack(sys_matrix_list).T
157153

@@ -174,8 +170,18 @@ def P_pos_def_constraint(n):
174170

175171
# crunch feasibility solution
176172
cvx.solvers.options['show_progress'] = False
177-
sol = cvx.solvers.sdp(c, Gs=Gs, hs=hs)
178-
return sol["x"]
173+
try:
174+
sol = cvx.solvers.sdp(c, Gs=Gs, hs=hs)
175+
return sol["x"]
176+
177+
except ZeroDivisionError as e:
178+
print(e)
179+
print(
180+
"""The system is probably ill conditioned.
181+
Consider perturbing the system matrices a small amount."""
182+
)
183+
raise(ZeroDivisionError)
184+
179185

180186

181187
def get_output_fb_index(sys):
@@ -194,7 +200,7 @@ def get_output_fb_index(sys):
194200
float
195201
The OFP index
196202
"""
197-
sol = solve_passivity_LMI(sys, nu=eps)
203+
sol = solve_passivity_LMI(sys, nu=0.0)
198204
if sol is None:
199205
raise RuntimeError("LMI passivity problem is infeasible")
200206
else:
@@ -218,7 +224,7 @@ def get_input_ff_index(sys):
218224
float
219225
The IFP index
220226
"""
221-
sol = solve_passivity_LMI(sys, rho=eps)
227+
sol = solve_passivity_LMI(sys, rho=0.0)
222228
if sol is None:
223229
raise RuntimeError("LMI passivity problem is infeasible")
224230
else:

control/tests/passivity_test.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -99,16 +99,15 @@ def test_system_dimension():
9999

100100

101101
@pytest.mark.parametrize(
102-
"systemmatrices, expected",
103-
[((A, B, C, D*0.0), True),
102+
"system_matrices, expected",
103+
[((A, B, C, D*1e-8), True),
104104
((A_d, B, C, D), True),
105-
pytest.param((A*1e12, B, C, D*0), True,
106-
marks=pytest.mark.xfail(reason="gh-761")),
107-
((A, B*0, C*0, D), True),
108-
((A*0, B, C, D), True),
109-
((A*0, B*0, C*0, D*0), True)])
110-
def test_ispassive_edge_cases(systemmatrices, expected):
111-
sys = ss(*systemmatrices)
105+
pytest.param((A*1e8, B, C, D*1e-8), True),
106+
((A, B*1e-8, C*1e-8, D), True),
107+
((A*1e-8, B, C, D), True),
108+
((A*1e-8, B*1e-8, C*1e-8, D*1e-8), True)])
109+
def test_ispassive_edge_cases(system_matrices, expected):
110+
sys = ss(*system_matrices)
112111
assert passivity.ispassive(sys) == expected
113112

114113

0 commit comments

Comments
 (0)