Modified Blindtrk.pas

[From Bruce Abbott (950509.1205 EST)]

Bill Powers (950508.1250 MDT) --

I have set up a program for doing a tracking experiment under conditions
where the cursor can and can't be seen.

Bill, Blindtrk compiled and ran fine, but I thought it needed an additional
experimental condition representative of the situation in which the visual
perceptual input is only briefly and intermittantly interrupted. I've added
this condition by slightly modifying the Blindtrk code; the new version
appears below. With brief interruption, the "world model" can be fairly
crude yet still improve on the error that would accrue if the system simply
stopped controlling during the "blind" intervals. Running blind during the
whole run requires a much more accurate model, if indeed that's what is
being used.

My (brief) experience with the program agrees with yours; I find myself
attending to proprioceptive arm signals and peripheral visual input of the
mouse position as a substitute for the cursor when the cursor is absent. I
attempt to produce a pattern of mouse movement (as sensed via these signals)
that matches some internal representation I have of the way in which the
cursor moves when it is visible. It's still control, but when deprived of
cursor position input, I have to find substitutes. Because the motion of
the cursor cannot be derived from my proprioceptive and mouse-visual inputs,
the source of the references for the mouse positioning/velocity/acceleration
system must come from imagination or habit, whatever those terms mean.

When cursor input is lost only briefly, I may be able to handle the job
through preservation: simply continuing to do what I was doing when the
input was lost: moving in a given direction, at a given velocity, and
perhaps accelerating at some rate. How do I accomplish this? Am I "locking
in" the last available reference values and "computing" the changes in
reference values from these?

Here's the modified program.

Regards,

Bruce

program blindt1a;

{ A target moves in a single cycle of a slow sine-wave pattern.
The participant makes a cursor follow the target. There are three
modes of running: with a visible cursor, with an invisible cursor,
and with a cursor that occasionally disappears for short periods.
The object is to see how a person tracks the target during periods
when the cursor can't be seen, and how much improvement there can
be with practice.

}

uses dos,crt,graph,grutils,mouse;

const maxdata = 900;

type dataarraytype = array[0..maxdata-1] of integer;

var cursx,targx,visix: dataarraytype;
    targetx,targety,oldtx,oldty, count, visible: integer;
    MaxX, MaxY, Xcenter, Ycenter, color: integer;
    index,oldmx,oldmy: integer;
    Time,Scale: real;
    ch: char;

procedure InitScreen;
begin
  ClrScr;
  InitGraphics;
  MaxX := GetMaxX; MaxY := GetMaxY;
  Xcenter := (MaxX+1) div 2;
  Ycenter := (MaxY+1) div 2;
  OutTextXY(20, MaxY-50, 'Press ESC to Quit...');
end;

procedure InitSystem;
begin
targetx := 0; targety := 0;
mousex := 0; mousey := 0;
end;

procedure showtarget(init: boolean);
var t: real;
begin
if(not init) then
rectangle(xcenter + oldtx - 2,ycenter - oldty - 2,
           xcenter + oldtx + 2, ycenter - oldty + 2);

oldtx := targetx; oldty := targety;

rectangle(xcenter + oldtx - 2,ycenter - oldty - 2,
           xcenter + oldtx + 2, ycenter - oldty + 2);
end;

procedure showcursor(init: boolean);
var x,y,i,j: integer;
begin
if(not init) then
rectangle(xcenter + oldmx - 8,ycenter - oldmy - 8,
           xcenter + oldmx + 8, ycenter - oldmy + 8);
oldmx := round(scale*mousex); oldmy := round(scale*mousey);
rectangle(xcenter + oldmx - 8,ycenter - oldmy - 8,
           xcenter + oldmx + 8, ycenter - oldmy + 8);
end;

procedure calibrate; {this procedure called }
var c1,c2: real; {only if no calibration exists}
begin
clearviewport;
mousex := 0;
outtextxy(0,10,'Set Mouse to 0 on ruler, press space bar');
  while not keypressed do readmouse;
c1 := mousex;
ch := readkey;
outtextxy(0,30,'Slide Mouse to 6 inches on ruler, press space bar');
while not keypressed do readmouse;
c2 := mousex;
ch := readkey;
scale := round(1.333333*xcenter)/(c2 - c1);
clearviewport;
end;

function calmouse: boolean;
var cf: file of real;
begin
assign(cf,'mousecal');
{$i-}
reset(cf);
{$i+}
if IOresult = 0 then begin read(cf,scale); close(cf); end
else
  begin
   rewrite(cf);
   calibrate;
   write(cf,scale);
   close(cf);
  end;
end;

procedure GetCount(var Count: integer);
begin
  Count := random(80) + 20;
end;

begin
InitSystem;
{ InitMouse;} {Note: do not initialize when running inside TP 7.0}
clrscr;
gotoxy(1,15);
writeln('Press v for visible cursor, i for invisible, m for mixed');
ch := readkey;
case ch of
   'v', 'V': visible := 1;
   'm', 'M': visible := 2;
   'i', 'I': visible := 0;
   else visible := 2;
   end;
InitScreen;
calmouse; { calibrate mouse if necessary}
InitSystem;
clearviewport;
setwritemode(XorPut);
outtextxy(0,20,
'Center large square on small square, then cursor on pad, strike spacebar');
ShowTarget(true);
ShowCursor(true);
mousey := 0;
repeat
  retrace;
  readmouse;
  mousey := 0;
  ShowCursor(false);
until keypressed;
ch := readkey;
clearviewport;
if visible in [1, 2] then
  begin
   ShowTarget(true);
   ShowCursor(true);
  end;
time := 0.0;
randomize;
getCount(Count);
index := 0;
while (time < 900.0) and (not keypressed) do
  begin
   retrace;
   readmouse;
   mousey := 0;
   targetx :=round(2*xcenter div 3 * sin(2*pi* time/900.0));
   ShowTarget(false);
   cursx[index] := round(scale*mousex);
   targx[index] := targetx;
   if visible in [1, 2] then
     begin
       ShowCursor(false);
       visix[index] := 50;
     end
   else visix[index] := 0;
   time := time + 1.0;
   if visible in [2, 3] then
     begin
       dec(count);
       if count = 0 then
       begin
         GetCount(Count);
         if visible = 2 then visible := 3 else visible := 2;
         ShowCursor(true);
       end;
     end;
   inc(index);
  end;
  ch := readkey;
  clearviewport;
  setcolor(lightred);
  outtextxy(0,maxY div 2 + 20,'TARGET POSITION');
  setcolor(yellow);
  outtextxy(0,maxY div 2 + 40,'CURSOR VISIBLE');
  setcolor(white);
  outtextxy(0,maxY div 2 + 60,'CURSOR INVISIBLE');
  for index := 0 to 899 do
  begin
   if visix[index] = 0 then color := white else color := yellow;
   putpixel(2*index div 3, ycenter - cursx[index],color);
   putpixel(2*index div 3, ycenter - targx[index],lightred);
   putpixel(2*index div 3, ycenter - visix[index], yellow);
   putpixel(2*index div 3, ycenter,lightgray);
  end;
  while keypressed do ch := readkey;
  ch := readkey;
  restorecrtmode;
  closegraph;
end.