[From Bill Powers (980319.0632 MST)]
Here is the program (below) for doing a compensatory tracking run at three
levels of difficulty. I'm attaching the source files for Units that are
used, as well as the main program, Track.pas
The program constructs three disturbance tables with slowing factors of 3,
10, and 30 to produce fast, medium, and slow changes in the disturbance. My
results for these disturbances are
fast medium slow
disturbance vs qo: -0.076 -0.892 -0.981
disturbance vs qi: 0.578 0.181 0.053
qi vs qo: 0.754 0.282 0.142
I should have done each of these trials many times, but my hand cramps up
so I did just one each. Somebody younger can do the multiple trials.
For the fastest disturbance I was barely able to control at all. The
slowest disturbance case was pretty easy. The filtering on the disturbance
was a three-stage filter with a relatively sharp frequency cutoff.
As predicted, the slower the fluctations in the disturbing variable, the
higher is the disturbance-qo correlation, and the lower are the other two
correlations.
I have also attached the runnable file, track.exe, for those with PCs but
no compilation facilities. The program first computes the three disturbance
tables, scales them, and shows them on the screen, pausing after each one.
A keystroke will end the pause. There are three runs of the tracking task,
one for each disturbance table. A keystroke starts each run, and at the end
of the run the three correlations are displayed. Move the mouse sideways to
keep the white marker aligned with the stationary red one.
The Borland graphics file, EGAVGA.BGI is also attached; it should be in the
directory where the executable program file is.
Best,
Bill P.
unit GrUtils;
{ Graphics Utilities Unit }
interface
uses
Graph, bgidriv;
var
GraphDriver, GraphMode, Error: integer;
hsize, hcenter, vsize, vcenter: integer;
procedure InitGraphics;
procedure Retrace;
implementation
const BGIDIR = '\tp\bgi';
procedure retrace;
begin
case Graphdriver of
Ega,Vga,Ega64,EgaMono: begin
while (port[$3da] and 8) = 8 do ;
while (port[$3da] and 8) = 0 do ;
end;
HercMono: begin
while (port[$3ba] and $80) = 0 do ;
while (port[$3ba] and $80) = $80 do ;
end;
ELSE begin
while (port[$3da] and 8) = 0 do ;
while (port[$3da] and 8) = 8 do ;
end;
end;
end;
procedure Abort(Msg : string);
begin
Writeln(Msg, ': ', GraphErrorMsg(GraphResult));
Halt(1);
end;
procedure InitGraphics; {ADAPTS TO HARDWARE}
begin
{ Register all the drivers }
if RegisterBGIdriver(@CGADriverProc) < 0 then
Abort('CGA');
if RegisterBGIdriver(@EGAVGADriverProc) < 0 then
Abort('EGA/VGA');
GraphDriver := Detect; { autodetect the hardware }
InitGraph(GraphDriver, GraphMode, ''); { activate graphics }
if GraphResult <> grOk then { any errors? }
begin
Writeln('Graphics init error: ', GraphErrorMsg(GraphDriver));
Halt(1);
end;
GraphMode := getmaxmode;
setgraphmode(GraphMode);
vsize := getmaxy; hsize := getmaxx;
vcenter := (vsize + 1) div 2;
hcenter := (hsize + 1) div 2;
end;
begin
end.
unit mouse;
interface
uses dos,crt;
var mousex,mousey: integer;
function initmouse: boolean;
procedure readmouse;
function readbutton: integer;
implementation
var MouseR : registers;
dx,dy: real;
{ ---------------------- Mouse Functions -----------------------------------}
function initmouse: boolean;
begin { false if mouse not found }
mousex := 0; mousey := 0;
dx := 0; dy := 0;
MouseR.ax := 0;
intr ($33, mouser);
if Mouser.ax <> $ffff then
begin
writeln('MOUSE NOT INSTALLED');
delay(1000);
end;
Initmouse := (MouseR.ax = $ffff);
end;
procedure readmouse;
begin
mouser.ax := 11;
intr ($33, mouser);
dx := dx + 0.7*(integer(MouseR.cx) - dx);
dy := dy + 0.7*(integer(MouseR.dx) - dy);
mousex := mousex + round(dx);
mousey := mousey - round(dy);
end;
function readbutton: integer; { returns 1,2,or 4}
begin
MouseR.ax := 3;
intr ($33, MouseR);
readbutton := MouseR.bx and 3;
end;
end. { of unit }
{$N+}
unit stats;
interface
var sx,sy,sx2,sy2,sxy,xbar,ybar,sigx,sigy,corr,regression,intercept: real;
procedure correl(ty: char; x,y: pointer ; datasize: integer);
implementation
type dataarraytype = array[0..2047] of integer;
rdataarraytype = array[0..2047] of real;
dataptrtype = ^dataarraytype;
rdataptrtype = ^rdataarraytype;
procedure correl;
var n,u,v,w,z: real;
i: integer;
dxptr,dyptr: dataptrtype;
rdxptr,rdyptr: rdataptrtype;
begin
if ty = 'i' then
begin
dxptr := x; dyptr := y;
end
else
begin
rdxptr := x; rdyptr := y;
end;
sx := 0.0; sy := 0.0;
n := datasize;
for i := 0 to datasize - 1 do
begin
if ty = 'i' then
begin
u := dxptr^[i]; v := dyptr^[i];
end
else
begin
u := rdxptr^[i]; v := rdyptr^[i];
end;
sx := sx + u; sy := sy + v;
end;
xbar := sx/n; ybar := sy/n;
sx2 := 0.0; sy2 := 0.0; sxy := 0.0;
for i := 0 to datasize - 1 do
begin
if ty = 'i' then
begin
u := dxptr^[i]; v := dyptr^[i];
end
else
begin
u := rdxptr^[i]; v := rdyptr^[i];
end;
sx2 := sx2 + (u - xbar)*(u - xbar);
sy2 := sy2 + (v - ybar)*(v - ybar);
sxy := sxy + (u - xbar)*(v - ybar);
end;
sigx :=sqrt(sx2/n);
sigy :=sqrt(sy2/n);
if (abs(sigx*sigy) > 0.0001) then
z := sxy/(n * sigx * sigy)
else z := 0.0;
corr := z;
if abs(sigx) > 0.001 then regression := z * sigy/sigx
else regression := 9999.99;
intercept := ybar - regression*xbar;
end;
end.program track;
uses dos,crt,graph,grutils,mouse,stats;
var dist: array[0..2] of array[0..1799] of integer;
qi,qo: array[1..1800] of integer;
slow: real;
d: integer;
ch: char;
procedure makedist;
var i,j: integer;
maxd: real;
d: array[0..2] of real;
ch: char;
begin
for j := 0 to 2 do
begin
d[0] := 0.0;
d[1] := 0.0;
d[2] := 0.0;
case j of
0: slow := 3.0;
1: slow := 10.0;
2: slow := 30.0;
end;
for i := 0 to 1799 do
begin
d[0] := d[0] + (20000.0*(random - 0.5) - d[0])/slow;
d[1] := d[1] + (d[0] - d[1])/slow;
d[2] := d[2] + (d[1] - d[2])/slow;
dist[j,i] := round(d[2]);
end;
maxd := 0.0;
for i := 0 to 1799 do
if abs(dist[j,i]) > maxd then maxd := abs(dist[j,i]);
for i := 0 to 1799 do
begin
dist[j,i] := round(dist[j,i]/maxd*300.0);
putpixel(i div 6,vcenter - dist[j,i] div 2,white);
end;
ch := readkey;
clearviewport;
end;
end;
procedure showqi(i: integer);
const oldx: integer = 0;
begin
if i <> -200 then
line(hcenter + oldx,vcenter,hcenter + oldx,vcenter - 10)
else
begin
clearviewport;
setcolor(lightred);
line(hcenter,vcenter + 11,hcenter,vcenter + 21);
setcolor(white);
end;
oldx := qi[abs(i)];
line(hcenter + oldx,vcenter,hcenter + oldx,vcenter - 10);
end;
procedure showcorr(j: integer);
var numstr: string;
begin
correl('i',@dist[j,0],@qo,1800);
str(corr:6:3,numstr);
outtextxy(0,0,'Correlation d vs qo = ' + numstr);
correl('i',@dist[j,0],@qi,1800);
str(corr:6:3,numstr);
outtextxy(0,15,'Correlation d vs qi = ' + numstr);
correl('i',@qi,@qo,1800);
str(corr:6:3,numstr);
outtextxy(0,30,'Correlation qi vs qo = ' + numstr);
end;
procedure doexp;
var i,j,k: integer;
begin
for j := 0 to 2 do
begin
clearviewport;
mousex := 0;
for k := -200 to 1799 do
begin
i := abs(k);
readmouse;
qi[i] := dist[j,i] + mousex;
qo[i] := mousex;
showqi(k);
delay(33);
end;
showcorr(j);
ch := readkey;
end;
end;
begin
initgraphics;
setwritemode(XORput);
makedist;
doexp;
end.
Track.exe (58 Bytes)
Egavga.bgi (59 Bytes)