File: p_margin.sci

package info (click to toggle)
scilab 5.2.2-9
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 334,832 kB
  • ctags: 52,586
  • sloc: xml: 526,945; ansic: 223,590; fortran: 163,080; java: 56,934; cpp: 33,840; tcl: 27,936; sh: 20,397; makefile: 9,908; ml: 9,451; perl: 1,323; cs: 614; lisp: 30
file content (52 lines) | stat: -rw-r--r-- 2,090 bytes parent folder | download
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
// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
// Copyright (C) INRIA -  Author: Serge Steer
// 
// 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 [phm,fr]=p_margin(h)
  //compute the phase margin of a SISO transfer function
  select typeof(h)
  case 'rational' then 
  case 'state-space' then 
    h=ss2tf(h)
  else 
    error(97,1)
  end
  if or(size(h)<>[1 1]) then 
   error(msprintf(_("%s: Wrong size for input argument #%d: Single input, single output system expected.\n"),"p_margin",1))
  end
  eps=1.e-7// threshold used for testing if complex numbers are real or pure imaginary
  
  if h.dt=='c' then  //continuous time case
    w=poly(0,'w');
    niw=horner(h.num,%i*w);diw=horner(h.den,%i*w);
    // |n(iw)/d(iw)|=1 <-- (n(iw)*n(-iw))/(d(iw)*d(-iw))=1 <--  (n(iw)*n(-iw)) - (d(iw)*d(-iw))=0
    w=roots(real(niw*conj(niw)-diw*conj(diw)))
    //select positive real roots
    ws=w(find((abs(imag(w))<eps)&(real(w)>0))) //frequency points with unitary modulus
    if ws==[] then phm=[],fr=[],return,end
    f=horner(h,%i*ws);
  else  //discrete time case
    if h.dt=='d' then dt=1,else dt=h.dt,end
    // |h(e^(i*w*dt))|=1 <-- h(e^(i*w*dt))*h(e^(-i*w*dt))
    z=poly(0,varn(h.den));
    sm=simp_mode();simp_mode(%f);hh=h*horner(h,1/z)-1;simp_mode(sm)
    //find the numerator roots
    z=roots(hh.num);
    z(abs(abs(z)-1)>eps)=[];// retain only roots with modulus equal to 1
    w=log(z)/(%i*dt);
    ws=real(w(abs(imag(w))<eps&real(w)>0)); //frequency points with unitary modulus
    if ws==[] then phm=%inf,fr=[],return,end
    f=horner(h,exp(%i*ws*dt));
  end
  phm=atan(imag(f),real(f))// phase of the frequency response in [-%pi %pi]
  phm=pmodulo(phm,2*%pi)-%pi
  phm=phm*180/%pi; //transform in degree
  [phm,k]=min(phm);ws=ws(k) //select the minimum
  //disp([phm,ws])
  fr=real(ws)/(2*%pi) 
endfunction