[Hans Blom, 970304]
(Bill Powers, 97.03.??)
I would MUCH prefer to stick to a realistic example.
All right. Let's stick to this example but do away with the output
saturation. That can be done by specifying a slowly changing setpoint
as I have done in the code below, and as you suggested as well.
Consider this. While the output is saturated, this is due to a very
large error which cannot be corrected. In the past you have analyzed
this sort of situation for the case of conflict between controllers.
In fact, control is lost, one could say. The loop gain is zero while
the output is saturated. Feedback is thus lost; a disturbance cannot
be corrected. That is why I consider output saturation a different
problem that needs separate consideration.
One of my (still-valid) criticisms of the MCT model is that it is
allowed to generate extremely large output forces; ...
There is no difference, in principle. In the PCT model, however,
there is a "slowing factor" whose effect is that the same large
output will only be reached gradually. Hence large outputs are less
noticeable. But if you give the PCT controller sufficient time, it
will generate similarly large outputs. Please check!
Due to PCT's slowing factor, the effect of saturation may be benign
(in some cases!): the output will build up slowly. But remember that
it will also build _down_ slowly!
I have maintained that the one-iteration error correction claimed
for an MCT model is possible only with unrealistic levels of output.
I think we have settled that question: one-jump error correction is
not possible in a physical system.
This is far from true. In the program below, the setpoint is varied
slowly, and one-jump error correction (of a smaller error!) is fully
possible. The same is true while stabilization occurs and x is to be
kept at the same position. It is only when unrealistic reference
levels are specified that one-jump correction is impossible, and the
reason is output saturation: the controller's output section is
insufficiently powerful to achieve what it is commanded to achieve.
To quote you: I think we have settled the question: one-jump error
correction is entirely possible and quite normal in physical systems.
If you want to put the required "self-knowledge" into your MCT
model, that's OK with me.
I'd rather not do that. It would complicate matters greatly and make
our investigation of the principal differences between PCT and MCT
control far less clear. I think that the code below -- which you may
want to beautify again and give a graphical display (thanks! you make
it look so much nicer!) -- could be my final version. It is small
enough to be understandable and leaves all possibilities for any type
of modification.
However, we can restrict the required output in a different way. One
method is to change the reference signal in a more reasonable way
instead of having it jump instantly from one value to another.
I've done that in the code below. And behold, the behavior of the MCT
controller is almost perfect again. Due to its almost perfect model,
to be sure...
Note that one of the things I want to try next is looking at the
effect of errors of computation. But first we have to see both
models running correctly.
Done that. It's just a simple change, compared to my previous code,
in the specification of the reference level. If you want to, you can
release your prettied-up version of this program to the group. If
there is any interest. I think we have lost most of the audience...
We want the physical model of the theodolite to respond to torques
as realistically as possible, and not for its behavior to depend on
the sampling rate with which the control system works.
My guess is that as long as the output saturation problem does not
occur, the value of dt won't matter too much. Think of it this way:
given a certain dt, the output "power" is given in "chunks" of u*dt.
Especially when the output is maximal (saturated), this "power" may
be large. If the reference is (unanticipatedly!) reached somewhere
_during_ the interval that this maximal output "power" is applied,
there is no way to change the output _during this same interval_.
This may cause an inappropriately large output "power chunk" to be
delivered, which needs to be corrected for again afterwards. Hence
over- and undershoots and oscillatory behavior.
Greetings,
Hans
program MCT_theodolite;
uses
crt;
var
J, K, dt, r, x, xold, xpre, xsav, d, u, t: real;
fo: text;
function make_reference (t: real): real;
{this function defines the setpoint at time t}
begin
if t < 2.0 then
make_reference := 0.0 else {0 for 2 secs}
if t < 7.0 then
make_reference := (t - 2.0) / 5.0 else {increase for 5 secs}
make_reference := 1.0 {1 for last 3 secs}
end;
function true_disturb (t: real): real;
{this function defines the true disturbance}
begin
if (t < 3.0) or (t > 6.0) then
true_disturb := 0.0
else
true_disturb := 100.0
end;
function do_observation: real;
{this function generates the x that the controller will observe}
begin
do_observation := 2.0 * x - xold + u/K + true_disturb(t)/K
end;
{initialization}
begin
clrscr; {clear screen}
assign (fo, 'output.csg');
rewrite (fo); {open file for output}
J := 1.0; {or whatever value...}
dt := 0.01; {or whatever value...}
K := (J / dt) / dt; {auxiliary constant}
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}
repeat
{the control loop starts here}
r := make_reference (t+dt); {define reference}
u := K * (r - 2.0 * x + xold) - d; {compute output}
if u < -750.0 then u := -750.0 else {limit output, if desired}
if u > +750.0 then u := +750.0;
xpre := 2.0 * x - xold + u / K + d / K; {generate prediction}
xsav := x; {save present x}
x := do_observation; t := t + dt; {observe x}
xold := xsav; {xold := previous x}
d := d + K * (x - xpre); {estimate disturbance}
{output to screen and file:
time, reference, predicted x, true x, estimated disturbance, output}
writeln (t:10:3, r:10:3, xpre:10:3, x:10:3, d:10:3, u:10:3);
writeln (fo, t:10:3, r:10:3, xpre:10:3, x:10:3, d:10:3, u:10:3);
until t >= 9.0; {at this point the loop ends}
close (fo)
end.