[comp.sys.handhelds] Root Locus Routines

paul+@andrew.cmu.edu (Paul J. Dujmich) (07/20/90)

I wrote the following 2 small routines this term for my control systems
class. The programs calculate the exit point of complex roots from
the real axis, and the entry point for complex roots to the real axis,
for Root Locus plots. "Exit" finds the point on the real axis where gain (K)
is maximum. At this point a pair of complex roots leave the real axis.
"Entry" finds the point on a real axis line segment where gain (K) is minimum.
It is at this point that a complex root pair enter the real axis line segment.

Paul
pauld@fs1.ece.cmu.edu
Dept. of Electrical and Computer Engineering
Carnegie-Mellon University
Pittsburgh, PA.
-------------------------------------------------------------------------------
%%HP: T(3)A(R)F(.);
@ PROGRAM NAME:    EXIT
@ DATE:            7-19-90
@ PURPOSE:         Calculate the breakaway point for complex roots from real
@                  axis, for Root Locus analysis.
@ ARGUMENTS:       Level 4: 'Algebraic expression in terms of "S"'(Capital S)
@                  Level 3: Left limit of real axis line segment
@                  Level 2: Right limit of real axis line segment
@                  Level 1: Desired accuracy (ex: .0001)

\<<
\-> fs ll rl a    @load in function (as algebraic object in terms of "S"),
  \<<             @ left limit, right limit, accuracy
      0
      'tstk'
      STO         @clear the Point and K variables
      0
      'pt'
      STO

@************************ Main DO loop **************************************
      DO
         ll
         rl
         -
         2
         /
         'hs'   @calculate half the real line segment length
         STO

         hs
         rl
         +
         'tp'
         STO    @tp = center between left and right line limits
         hs
         2
         /
         tp
         +
         'tp1'
         STO     @find left half test point ,half way between left limit and tp

         tp1
         'S'
         STO
         'fs' EVAL
         ABS
         MINV
         'tp1k'
         STO        @find K at left half test point

         hs
         2
         /
         rl
         +
         'tp2'
         STO      @find the right half test point, between tp and right limit

         tp2
         'S'
         STO
         'fs'  EVAL
         ABS
         MINV
         'tp2k'
         STO        @find K at right half test point



         IF 'tp1k > tp2k' @left half of line segment has bigger K value
             THEN  tp
                   'rl'
                   STO      @ tp is new right limit
                   tstk
                   'oldk'   @save old K value from last pass
                   STO
                   tp1k     @left test point has larger K value
                   'tstk'
                   STO      @save the K value
                   pt
                   'opt'    @save old point value from last pass
                   STO
                   tp1      @left test point produces largest K value
                   'pt'     @save the left half point value
                   STO

             ELSE  tp       @right half of line segment has larger K value
                   'll'
                   STO      @tp is now new left limit
                   tstk
                   'oldk'   @save old K value from last pass
                   STO
                   tp2k
                   'tstk'
                   STO      @right half line segment has larger K value
                   pt
                   'opt'    @save point value from last pass
                   STO
                   tp2      @save right half point value
                   'pt'
                   STO
         END




      tstk         @calculate difference in K between last pass and this pass
      oldk
      -
      'dif'        @save it
      STO


      UNTIL  dif 0 <  dif a \<= OR     @run DO loop until the difference
      END                              @between this pass K value and the K
                                       @value from the last pass is negative
                                       @(K value started to decrease) or
                                       @run DO loop until the difference
                                       @between 2 successive passes produced
                                       @K values that differed by less than
                                       @the required accuracy value.

@************************ end main DO loop ***********************************
IF 'dif < 0 '                       @K value started to decrease
    THEN opt                        @we want the Point and K value from the
         'loc'                      @last pass
         STO
         oldk
         'val'
         STO
    ELSE pt                         @we want the Point and K value from this
         'loc'                      @pass (required accuracy has been met)
         STO
         tstk
         'val'
         STO
END



@Print the results on LCD screen
CLLCD
"Breakaway Point = "
1 DISP
loc \->STR
2 DISP
"K at Breakaway Point"
4 DISP
val \->STR
5 DISP
7 FREEZE


@Nuke all the variables
{val loc dif opt pt oldk tp2k tp2 tp1k tp1 tp hs tstk S}
PURGE
CLEAR                              @clean off stack
fs                                 @leave the function on the stack in level 1
\>>                                @in case user wants to do another line
\>>                                @segment

-------------------------------------------------------------------------------
%%HP: T(3)A(R)F(.);
@ PROGRAM NAME:    ENTRY
@ DATE:            7-19-90
@ PURPOSE:         Calculate the entry point for complex roots to real
@                  axis, for Root Locus analysis.
@ ARGUMENTS:       Level 4: 'Algebraic expression in terms of "S"'(Capital S)
@                  Level 3: Left limit of real axis line segment
@                  Level 2: Right limit of real axis line segment
@                  Level 1: Desired accuracy (ex: .0001)

\<<
\-> fs ll rl a    @load in function (as algebraic object in terms of "S"),
  \<<             @ left limit, right limit, accuracy
      1E400
      'tstk'
      STO         @clear the Point and K variables
      0
      'pt'
      STO

@************************ Main DO loop **************************************
      DO
         ll
         rl
         -
         2
         /
         'hs'   @calculate half the real line segment length
         STO

         hs
         rl
         +
         'tp'
         STO    @tp = center between left and right line limits


         hs
         2
         /
         tp
         +
         'tp1'
         STO     @find left half test point ,half way between left limit and tp

         tp1
         'S'
         STO
         'fs' EVAL
         ABS
         MINV
         'tp1k'
         STO        @find K at left half test point

         hs
         2
         /
         rl
         +
         'tp2'
         STO      @find the right half test point, between tp and right limit

         tp2
         'S'
         STO
         'fs'  EVAL
         ABS
         MINV
         'tp2k'
         STO        @find K at right half test point



         IF 'tp1k < tp2k'   @left half of line segment has smaller K value
             THEN  tp
                   'rl'
                   STO      @ tp is new right limit
                   tstk
                   'oldk'   @save old K value from last pass
                   STO
                   tp1k     @left test point has smaller K value
                   'tstk'
                   STO      @save the K value
                   pt
                   'opt'    @save old point value from last pass
                   STO
                   tp1      @left test point produces smallest K value
                   'pt'     @save the left half point value
                   STO
               @tp2k < tp1k
             ELSE  tp       @right half of line segment has smallest K value
                   'll'
                   STO      @tp is now new left limit
                   tstk
                   'oldk'   @save old K value from last pass
                   STO
                   tp2k
                   'tstk'
                   STO      @right half line segment has smallest K value
                   pt
                   'opt'    @save point value from last pass
                   STO
                   tp2      @save right half point value
                   'pt'
                   STO
         END




      oldk         @calculate difference in K between last pass and this pass
      tstk         @(we expect tstk to normally be smaller than oldk)
      -
      'dif'        @save it
      STO


      UNTIL  dif 0 <  dif a \<= OR     @run DO loop until the difference
      END                              @between this pass K value and the K
                                       @value from the last pass is negative
                                       @(K value started to increase) or
                                       @run DO loop until the difference
                                       @between 2 successive passes produced
                                       @K values that differed by less than
                                       @the required accuracy value.

@************************ end main DO loop ***********************************
IF 'dif < 0 '                       @K value started to increase
    THEN opt                        @we want the Point and K value from the
         'loc'                      @last pass
         STO
         oldk
         'val'
         STO
    ELSE pt                         @we want the Point and K value from this
         'loc'                      @pass (required accuracy has been met)
         STO
         tstk
         'val'
         STO
END



@Print the results on LCD screen
CLLCD
"Entry Point = "
1 DISP
loc \->STR
2 DISP
"K at Entry Point"
4 DISP
val \->STR
5 DISP
7 FREEZE


@Nuke all the variables
{val loc dif opt pt oldk tp2k tp2 tp1k tp1 tp hs tstk S}
PURGE
CLEAR                              @clean off stack
fs                                 @leave the function on the stack in level 1
\>>                                @in case user wants to do another line
\>>                                @segment