Skip to content

Commit 2304cc6

Browse files
committed
improve robustness of hinfnorm
1 parent f18f27b commit 2304cc6

File tree

2 files changed

+67
-7
lines changed

2 files changed

+67
-7
lines changed

lib/ControlSystemsBase/src/matrix_comps.jl

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,27 @@ end
300300
LinearAlgebra.norm(sys::TransferFunction, p::Real=2; tol=1e-6) = norm(ss(sys), p, tol=tol)
301301

302302

303+
"""
304+
sysm, T, SF = schur_form(sys)
305+
306+
Bring `sys` to Schur form.
307+
308+
The Schur form is characterized by `A` being Schur with the real values of eigenvalues of `A` on the main diagonal. `T` is the similarity transform applied to the system such that
309+
```julia
310+
sysm ≈ similarity_transform(sys, T)
311+
```
312+
`SF` is the Schur-factorization of `A`.
313+
314+
See also [`modal_form`](@ref) and [`hess_form`](@ref)
315+
"""
316+
function schur_form(sys)
317+
SF = schur(sys.A)
318+
A = SF.T
319+
B = SF.Z'*sys.B
320+
C = sys.C*SF.Z
321+
ss(A,B,C,sys.D, sys.timeevol), SF.Z, SF
322+
end
323+
303324
"""
304325
Ninf, ω_peak = hinfnorm(sys; tol=1e-6)
305326
@@ -324,8 +345,8 @@ state space systems in continuous and discrete time', American Control Conferenc
324345
325346
See also [`linfnorm`](@ref).
326347
"""
327-
hinfnorm(sys::AbstractStateSpace{<:Continuous}; tol=1e-6) = _infnorm_two_steps_ct(sys, :hinf, tol)
328-
hinfnorm(sys::AbstractStateSpace{<:Discrete}; tol=1e-6) = _infnorm_two_steps_dt(sys, :hinf, tol)
348+
hinfnorm(sys::AbstractStateSpace{<:Continuous}; tol=1e-6) = _infnorm_two_steps_ct(schur_form(sys)[1], :hinf, tol)
349+
hinfnorm(sys::AbstractStateSpace{<:Discrete}; tol=1e-6) = _infnorm_two_steps_dt(schur_form(sys)[1], :hinf, tol)
329350
hinfnorm(sys::TransferFunction; tol=1e-6) = hinfnorm(ss(sys); tol=tol)
330351

331352
"""
@@ -352,10 +373,11 @@ state space systems in continuous and discrete time', American Control Conferenc
352373
See also [`hinfnorm`](@ref).
353374
"""
354375
function linfnorm(sys::AbstractStateSpace; tol=1e-6)
355-
if iscontinuous(sys)
356-
return _infnorm_two_steps_ct(sys, :linf, tol)
376+
sys2, _ = schur_form(sys)
377+
if iscontinuous(sys2)
378+
return _infnorm_two_steps_ct(sys2, :linf, tol)
357379
else
358-
return _infnorm_two_steps_dt(sys, :linf, tol)
380+
return _infnorm_two_steps_dt(sys2, :linf, tol)
359381
end
360382
end
361383
linfnorm(sys::TransferFunction; tol=1e-6) = linfnorm(ss(sys); tol=tol)
@@ -443,7 +465,8 @@ function _infnorm_two_steps_ct(sys::AbstractStateSpace, normtype::Symbol, tol=1e
443465
end
444466
end
445467
end
446-
error("In _infnorm_two_steps_dt: The computation of the H∞/L∞ norm did not converge in $maxIters iterations")
468+
@error("In _infnorm_two_steps_dt: The computation of the H∞/L∞ norm did not converge in $maxIters iterations")
469+
return T((1+tol)*lb), T(ω_peak)
447470
end
448471

449472
function _infnorm_two_steps_dt(sys::AbstractStateSpace, normtype::Symbol, tol=1e-6, maxIters=250, approxcirc=1e-8)

lib/ControlSystemsBase/test/test_matrix_comps.jl

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,5 +362,42 @@ res = observability(sys)
362362
@test all(==(3), res.ranks)
363363
@test all(<(sqrt(eps())), res.sigma_min)
364364

365-
end
365+
366+
## https://github.com/JuliaControl/ControlSystems.jl/issues/1014
367+
P_test = zpk(
368+
[-101.47795511977208 + 0.0im
369+
-48.91219110762173 + 0.0im
370+
-7.282563985219324 + 7.114985406231401im
371+
-7.282563985219324 - 7.114985406231401im
372+
-7.96322290641594 + 0.0im
373+
-1.5268748507837735 + 1.2594070637611725im
374+
-1.5268748507837735 - 1.2594070637611725im
375+
-0.7114937019357614 + 0.0im
376+
],
377+
[ -101.32273797977184 + 0.0im
378+
-49.510558929948274 + 0.0im
379+
-20.0 + 0.0im
380+
-11.82446898287247 + 0.0im
381+
-10.604444850836952 + 0.0im
382+
-5.297845964509693 + 6.146324852257861im
383+
-5.297845964509693 - 6.146324852257861im
384+
-1.4795349979133343 + 1.2376578249023653im
385+
-1.4795349979133343 - 1.2376578249023653im
386+
-0.6235091399063754 + 0.0im
387+
-0.2743617810110765 + 0.0im
388+
],
389+
704.6392766532747
390+
);
391+
392+
C_test = zpk(
393+
[-0.5 + 0.0im],
394+
[0.],
395+
0.6
396+
);
397+
398+
S_test = sensitivity(P_test, C_test);
399+
n,w = hinfnorm(S_test)
400+
@test n 1.3056118418593037 atol=1e-3
401+
@test w 5.687023116875403 atol=1e-3
402+
end
366403

0 commit comments

Comments
 (0)