1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
|
// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
// Copyright (C) INRIA
// This file must be used under the terms of the CeCILL.
// This source file is licensed as described in the file COPYING, which
// you should have received as part of this distribution. The terms
// are also available at
// http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
function evans(n,d,kmax)
// Seuil maxi et mini (relatifs) de discretisation en espace
// Copyright INRIA
smax=0.002;smin=smax/3;
nptmax=2000 //nbre maxi de pt de discretisation en k
//analyse de la liste d'appel
[lhs,rhs]=argn(0)
if rhs <= 0 then // demo
n=real(poly([0.1-%i 0.1+%i,-10],'s'));
d=real(poly([-1 -2 -%i %i],'s'));
evans(n,d,80);
return
end
select typeof(n)
case 'constant' then
if rhs==2 then kmax=0,end
case 'polynomial' then
if rhs==2 then kmax=0,end
//-compat next case retained for list/tlist compatibility
case 'rational' then
if rhs==2 then kmax=d,else kmax=0,end
[n,d]=n(2:3)
case 'state-space' then
if rhs==2 then kmax=d,else kmax=0,end
n=ss2tf(n);
[n,d]=n(2:3);n=clean(n);d=clean(d);
else
error(msprintf(gettext("%s: Wrong type for input argument #%d: A linear dynamical system or a polynomial expected.\n"),"evans",1));
end
if prod(size(n))<>1 then
error(msprintf(gettext("%s: Wrong value for input argument #%d: Single input, single output system expected.\n"),"evans",1));
end
if kmax<=0 then
nm=mini([degree(n),degree(d)])
fact=norm(coeff(d),2)/norm(coeff(n),2)
kmax=round(500*fact),
end
//
//calcul de la discretisation en k et racines associees
nroots=roots(n);racines=roots(d);
if nroots==[] then
nrm=maxi([norm(racines,1),norm(roots(d+kmax*n),1)])
else
nrm=maxi([norm(racines,1),norm(nroots,1),norm(roots(d+kmax*n),1)])
end
md=degree(d)
//
ord=1:md;kk=0;nr=1;k=0;pas=0.99;fin='no';
while fin=='no' then
k=k+pas
r=roots(d+k*n);r=r(ord)
dist=maxi(abs(racines(:,nr)-r))/nrm
//
point='nok'
if dist <smax then //pas correct
point='ok'
else //pas trop grand ou ordre incorrect
// on cherche l'ordre qui minimise la distance
ix=1:md
ord1=[]
for ky=1:md
yy=r(ky)
mn=10*dist*nrm
for kx=1:md
if ix(kx)>0 then
if abs(yy-racines(kx,nr)) < mn then
mn=abs(yy-racines(kx,nr))
kmn=kx
end
end
end
ix(kmn)=0
ord1=[ord1 kmn]
end
r(ord1)=r
dist=maxi(abs(racines(:,nr)-r))/nrm
if dist <smax then
point='ok',
ord(ord1)=ord
else
k=k-pas,pas=pas/2.5
end
end
if dist<smin then
//pas trop petit
pas=2*pas;
end
if point=='ok' then
racines=[racines,r];kk=[kk,k];nr=nr+1
if k>kmax then fin='kmax',end
if nr>nptmax then fin='nptmax',end
end
end
//draw the axis
x1 =[nroots;matrix(racines,md*nr,1)];
xmin=mini(real(x1));xmax=maxi(real(x1))
ymin=mini(imag(x1));ymax=maxi(imag(x1))
dx=abs(xmax-xmin)*0.05
dy=abs(ymax-ymin)*0.05
if dx<1d-10, dx=0.01,end
if dy<1d-10, dy=0.01,end
legs=[],lstyle=[];lhandle=[]
rect=[xmin-dx;ymin-dy;xmax+dx;ymax+dy];
f=gcf();
cur_im_dr= f.immediate_drawing;
f.immediate_drawing = 'off';
a=gca()
a.data_bounds=[rect(1) rect(2);rect(3) rect(4)]
if nroots<>[] then
xpoly(real(nroots),imag(nroots))
e=gce();e.line_mode='off';e.mark_mode='on';
e.mark_size_unit="point";e.mark_size=7;e.mark_style=5;
legs=[legs; _("open loop zeroes")]
lhandle=[lhandle; e];
end
if racines<>[] then
xpoly(real(racines(:,1)),imag(racines(:,1)))
e=gce();e.line_mode='off';e.mark_mode='on';
e.mark_size_unit="point";e.mark_size=7;e.mark_style=2;
legs=[legs;_("open loop poles")]
lhandle=[lhandle; e];
end
dx=maxi(abs(xmax-xmin),abs(ymax-ymin));
//plot the zeros locations
//computes and draw the asymptotic lines
m=degree(n);q=md-m
if q>0 then
la=0:q-1;
so=(sum(racines(:,1))-sum(nroots))/q
i1=real(so);i2=imag(so);
if prod(size(la))<>1 then
ang1=%pi/q*(ones(la)+2*la)
x1=dx*cos(ang1),y1=dx*sin(ang1)
else
x1=0,y1=0,
end
if md==2,
if coeff(d,md)<0 then
x1=0*ones(2),y1=0*ones(2)
end,
end;
if maxi(k)>0 then
xpoly(i1,i2);
e=gce();
legs=[legs;_("asymptotic directions")]
lhandle=[lhandle; e];
axes = gca();
axes.clip_state = "clipgrf";
for i=1:q,xsegs([i1,x1(i)+i1],[i2,y1(i)+i2]),end,
axes.clip_state = "off";
end
end;
//lieu de evans
[n1,n2]=size(racines);
plot2d(real(racines)',imag(racines)',style=2+(1:n2));
legend(lhandle,legs,1);
xtitle(_("Evans root locus"),_("Real axis"),_("Imaginary axis"));
f=gcf();
if(cur_im_dr=="on") then f.immediate_drawing = 'on';end
if fin=='nptmax' then
warning(msprintf(gettext("%s: Curve truncated to the first %d discretization points.\n"),"evans",nptmax))
end
endfunction
|