Skip to content

Instantly share code, notes, and snippets.

@kleinerm
Created February 16, 2024 05:09
Show Gist options
  • Save kleinerm/928c21fa0b5a866ef85c1146a8d874f3 to your computer and use it in GitHub Desktop.
Save kleinerm/928c21fa0b5a866ef85c1146a8d874f3 to your computer and use it in GitHub Desktop.
Demo for Psychtoolbox forum message 5248 - Joystick motion recording principle.
function MouseMotionRecordingDemoPimped
% MouseMotionRecordingDemoPimped - Record mouse motion via KbQueues.
%
% This demo shows very basic recording of mouse/touchpad motion
% movement data under Linux.
%
% Press a key on the keyboard to end the demo.
%
% It requests recording of raw motion, ie. of the device itself,
% in device and operating system specific distance units, not
% neccessarily in screen pixels. No pointe acceleration / ballistics
% should be applied to the motion. It prints cursor position, vs.
% integrated raw position, vs. reported raw movement deltas for
% comparison. Also mouse wheel motion on some OS + device combos.
%
% Note that you may have to calibrate / map reported positions yourself
% for any given mouse device, e.g., a 400 DPI mouse may report in different
% units than a 1000 DPI mouse etc.
%
% This functionality is not supported on Apple macOS.
%
% History:
% 25-Jul-2019 mk Written.
% 06-Oct-2020 mk Add timestamping/dT calculation and printing.
if ~IsLinux
fprintf('Sorry, this demo does not work on non-Linux.\n');
return;
end
% Wait for all keyboard buttons released:
KbReleaseWait;
% Get first mouse device: Replace GetMouseIndices with GetGamepadIndices for
% Joysticks...
d = GetMouseIndices;
d = d(1);
% Create a keyboard queue for it, requesting return of first 3 valuators,
% ie. x and y axis, and maybe some scroll-wheel axis. Request return of
% raw motion event data (flag 4), so no pointer gain/acceleration/ballistics
% is applied by the OS and returned valuators are in device specific units
% of relative motion / movement, not absolute desktop pixel coordinates:
KbQueueCreate(d, [], 3, [], 4);
% Start movement data collection, place mouse cursor in top-left (0,0) pos:
SetMouse(0,0);
[x,y] = GetMouse;
motion = [];
win = Screen('Openwindow', 0, 0);
% Start of trial. Discard all motion data from keyboard queue:
KbEventFlush(d);
% Start motion recording:
KbQueueStart(d);
% Main trial animation loop. Repeat until keypress:
while ~KbCheck
% Get latest motion samples, store in 'motion', also return most recent
% values [x,y]:
[motion, x, y] = fetchData(d, motion, x, y);
% Visualize latest recorded sample:
Screen('DrawDots', win, [x ; y], 8, [255 255 0]);
% Show:
Screen('Flip', win);
end
% Done. Stop data collection for this trial.
KbQueueStop(d);
% Fetch all remaining motion data from the queue:
[motion, x, y] = fetchData(d, motion, x, y);
% motion contains the full movement trajectory including timestamps...
fprintf('Record from this trial follows:\n');
disp(motion);
% Do next iteration in trial loop...
% End - Cleanup:
KbQueueRelease(d);
sca;
fprintf('\nDone, bye!\n\n');
end
function [motion, x, y] = fetchData(d, motion, x, y)
persistent oldTime;
% Fetch all queued samples:
while KbEventAvail(d)
evt = KbEventGet(d);
% Motion event? We don't care about other events:
if evt.Type == 1
% Accumulate absolute position x,y from provided dx,dy movements:
x = x + evt.Valuators(1);
y = y + evt.Valuators(2);
% This stuff just for illustration:
if ~isempty(oldTime)
dT = evt.Time - oldTime;
else
dT = 0;
end
oldTime = evt.Time;
% On Linux/X11 in raw mode, no dedicated cursor position is reported, so
% skip that. Also, wheel position would be valuator 4, scrap that.
fprintf('dT=%f msecs xi=%f yi=%f vx=%f vy=%f\n', dT * 1000, x, y, ...
evt.Valuators(1), evt.Valuators(2));
% End of stuff to show...
motion = [motion ; [x, y, evt.Time]];
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment