[From Bill Powers (970305.0501 MST)]
Hans Blom (970504...) and other programmers --
Attached is theo5mct.pas, which is a rearrangement of theo4mct.pas. The main
changes involve moving all environmental equations into "do_observation",
which is now a procedure instead of a function.
In "do_observation," it will be seen that there are _two_ environmental
equations, one used for the MCT model and the other for the PCT model. There
is a boolean variable, "ismct", which is now set by whichever model is
running, so the correct environmental model can be chosen. By inserting a
"not" before "ismct," you can verify that these environmental models work
only with the respective controllers. Therein lies a problem for the MCT model.
In the MCT model there is a "predictor" equation which is an exact
derivation from the environmental model. However, the environmental model is
not exactly, physically, correct. When the physically correct environment
model is used with the MCT model, the output of the MCT model oscillates
continuously -- although the controlled variable behaves essentially the
same as before. Control is now achieved by varying the duty cycle of a
square-wave oscillation between maximum positive and negative output at the
sampling frequency.
The physically correct environmental model is a simple application of the
laws of motion. If a constant torque u is applied to the theodolite for a
time dt, the angle x will vary as
x := x0 + v*dt + 0.5*a*dt*dt
The velocity v will increase as
v := v + a*dt.
The angular acceleration a is just (u + d)/J: torque divided by moment of
inertia. Since (u + d) is constant during the interval dt, this is the exact
way to calculate the value of x at the start of the next iteration.
This being the case, both the MCT and the PCT models should use the exact
equation of motion, and not the approximation in the original MCT model. An
adjustment has to be made to the "predictor" equation to correct for the
problems that come from using the exact environmental equations in the MCT
model. I will leave it to Hans to make the adjustment.
Appended is the new program; I will delay posting it with the runnable
version to my FTP page until Hans has the MCT model running with the correct
environmental model.
Best,
Bill P.
program theo5mct;
{
This program compares the performance of the MCT and PCT models. Both
models are controlling the position of a theodolite, under the
following conditions:
change of position: 1 radian.
time resolution: 0.01 sec (dt).
Maximum available output torque: 100 newton-meters
Moment of inertia of theodolite: 1 newton-meter^2
Rate of change of reference signal: variable from keyboard
disturbance: 100 n-m, 3 sec duration, random starting time.
The MCT model runs first, in the lower half of the screen. The slope
of the change in reference signal can be adjusted up and down (by
factors of 1.5) by pressing the + and - keys, shifted or unshifted. A
new run is done every time any key is pressed -- except 'p' or 'q'.
Pressing the 'q' key exits the program at any time. Pressing the 'p'
key switches to running the PCT model; after the first time, pressing
'p' or 'm' switches control to the PCT or MCT model, for further
adjustments of the slopes.
The beginning time of the disturbance varies randomly each time a new
run occurs. By pressing the space bar, new runs can be done with the
same value of the slope of the reference signal's rise but a different
start of the disturbance. Thus you can see what happens when there
is or is not a disturbance occurring during the change in reference
signal.
MCT program by Hans Blom; PCT program and presentation by W. T. Powers
4 March 1997
}
uses
dos, crt, graph, grutils;
var
J, K, dt, r, x, u, a, v, maxu, xold, xpre, xsav: real;
d, d1, d2, trued, t, pslope,mslope: real;
gv, gx, rv, rx: real;
xplot: integer;
maxx, maxy,ycenter: integer;
ch: char;
numstr: string;
fo: text;
ismct: boolean;
function make_reference (t: real; var slope: real): real;
{this function defines the setpoint at time t}
var ref: real;
begin
if t >= 3.0 then
begin
ref := slope*(t - 3.0);
if ref > 1.0 then ref := 1.0;
make_reference := ref;
end
else make_reference := 0.0;
end;
function true_disturb (t: real): real;
{this function defines the true disturbance}
begin
if (t < d1) or (t > d2) then
true_disturb := 0.0
else
true_disturb := 50.0;
end;
procedure do_observation;
{this function generates the x that the controller will observe}
begin
trued := true_disturb(t);
xsav := x; {save present x}
if ismct then
begin
x := 2.0 * x - xold + u/K + trued/K;
end
else
begin
x := x + v*dt + 0.5*a*dt*dt;
v := v + a*dt;
end;
xold := xsav; {xold := previous x}
end;
procedure plotit(baseline: integer);
begin
xplot := round(50.0*t)+ 160;
putpixel(xplot,baseline,white);
putpixel(xplot,baseline - round(100.0*r),yellow);
putpixel(xplot,baseline - round(100.0*x),white);
putpixel(xplot,baseline - round(trued),lightred);
putpixel(xplot,baseline - round(u),lightcyan);
end;
procedure legends;
begin
clearviewport;
setcolor(white);
outtextxy(0,0,'Pointing angle');
setcolor(yellow);
outtextxy(0,15,'Ref level');
setcolor(lightcyan);
outtextxy(0,30,'Output torque');
setcolor(lightred);
outtextxy(0,45,'Disturbance');
end;
Procedure PCTmodel;
begin
ismct := false;
setviewport(0,0,maxx,ycenter,ClipOn);
repeat {REPEAT WHOLE RUN}
t := 0.0; {start at zero time}
d := 0.0; {assume no disturbance initially}
v := 0.0;
x := 0.0;
gv := 100.0;
gx := 50.0;
j := 1.0;
d1 := 1.5 + 6.0*random;
d2 := d1 + 3.0;
maxu := 0.0;
legends;
str(pslope:5:3,numstr);
setcolor(white);
outtextxy(0,60,'Slope = ' + numstr);
outtextxy(150,100,'PCT MODEL');
repeat {the control loop starts here}
r := make_reference (t+dt,pslope); {define reference}
{COMPUTE OUTPUT}
rv := gx* (r - x); {velocity ref level = output of position control}
u := gv*(rv - v); {output force = output of velocity control}
{LIMIT OUTPUT TO +/- 100 N-M}
if u < -100.0 then u := -100.0 else {limit output, if desired}
if u > +100.0 then u := +100.0;
{ENVIRONMENTAL EQUATIONS}
do_observation;
plotit(130);
t := t + dt;
until t >= 9.0; {at this point the loop ends}
ch := readkey;
if ch in ['=','+'] then pslope := pslope*1.5;
if ch in ['_','-'] then pslope := pslope/1.5;
until ch in ['q','Q','m','M'];
end;
Procedure MCTmodel;
begin
ismct := true;
setviewport(0,ycenter+1,maxx,maxy - 20,ClipOn);
repeat {REPEAT WHOLE RUN}
t := 0.0; {start at zero time}
xold := 0.0; {start at zero position}
x := xold; {and at zero velocity}
d := 0.0; {assume no disturbance initially}
v := 0.0;
d1 := 1.5 + 6.0*random;
d2 := d1 + 3.0;
maxu := 0.0;
legends;
str(mslope:5:3,numstr);
setcolor(white);
outtextxy(0,60,'Slope = '+numstr);
outtextxy(150,100,'MCT MODEL');
repeat {the control loop starts here}
r := make_reference (t+dt,mslope); {define reference}
{COMPUTE OUTPUT}
u := K * (r - 2.0 * x + xold) - d;
{LIMIT OUTPUT TO +/- 100 N-M}
if u < -100.0 then u := -100.0 else {limit output, if desired}
if u > +100.0 then u := +100.0;
{GENERATE PREDICTED X}
xpre := 2.0 * x - xold + u / K + d / K;
{ENVIRONMENTAL EQUATIONS}
do_observation;
plotit(110);
t := t + dt;
{ESTIMATE DISTURBANCE}
d := d + K * (x - xpre);
until t >= 9.0; {at this point the loop ends}
ch := readkey;
if ch in ['=','+'] then mslope := mslope*1.5;
if ch in ['_','-'] then mslope := mslope/1.5;
until ch in ['q','Q','p','P'];
end;
{initialization}
begin
clrscr; {clear screen}
initgraphics;
maxy := getmaxy;
maxx := getmaxx;
ycenter := (maxy+1) div 2;
J := 10.0; {or whatever value...}
dt := 0.01; {or whatever value...}
K := (J / dt) / dt; {auxiliary constant}
mslope := 0.2;
pslope := 0.2;
setcolor(white);
outtextxy(0,maxy - 15,'q to quit, space to repeat, +/- to change slope');
ch := 'm';
repeat
if ch in ['m','M'] then MCTmodel;
if ch in ['p','P'] then PCTmodel;
until ch in ['q','Q'];
closegraph;
end.
···
a := (u+trued)/J;