Created
February 16, 2024 05:09
-
-
Save kleinerm/928c21fa0b5a866ef85c1146a8d874f3 to your computer and use it in GitHub Desktop.
Demo for Psychtoolbox forum message 5248 - Joystick motion recording principle.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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