Difference between revisions of "Optitrak + Projector touch table/surface"

From REALab Wiki
Jump to navigation Jump to search
Line 11: Line 11:


This function should be called before opening a main window with psychtoolbox.
This function should be called before opening a main window with psychtoolbox.




  function [touch_plane_info, client] = opti_setup_touch_plane_srt
  function [touch_plane_info, client] = opti_setup_touch_plane_srt
%This gives an error (freezes) if the NET assembly is already loaded.  In
%that case you need to quit Matlab and start over
   
   
  if ~IsAssemblyAdded('NatNetML')   
  if ~IsAssemblyAdded('NatNetML')   
      Opti = NET.addAssembly('C:\Users\Jim Enns\Documents\MATLAB\NatNetSDK2.2\NatNetSDK\lib\NatNetML.dll');
Opti = NET.addAssembly('C:\Users\Jim Enns\Documents\MATLAB\NatNetSDK2.2\NatNetSDK\lib\NatNetML.dll');
end
client = NatNetML.NatNetClientML(1);
%client.Initialize('142.103.0.167','142.103.0.167');
client.Initialize('142.103.251.175','142.103.251.175');
data = client.GetLastFrameOfData;
reply = 'N';
while ~strcmpi(reply,'Y')
answer = {};
while isempty(answer)       
prompt={'Pixel Coords: '};
name='Lower Left Corner';
numlines=[1,35]; %this width allows for title to be seen
defaultanswer={'[0 768]'};
answer=inputdlg(prompt,name,numlines,defaultanswer);
%convert from string to number data for output variables
if ~isempty(answer)
OriginPixelCoords = str2num(answer{1});
end
end
pDataDest = [data.OtherMarkers(1).x data.OtherMarkers(1).z data.OtherMarkers(1).y];
Question = {'LOWER LEFT pre coordinate transform:'...
''...
'Marker 1: ' num2str(pDataDest(1:3))...
''...
'Accept?'...
''};
ButtonName = questdlg(Question, 'Data Check', 'Yes', 'No', 'Quit', 'Yes');
switch ButtonName
case 'Yes'
orig_pos = pDataDest;
reply = 'Y';
case 'No'
reply = 'N';
case 'Quit'
%quit opto too?
%need to pass quit flag so this actually works?
transform_info = [];
clear all; close all; Screen('CloseAll');
disp('*** Exiting Program ***');
return
end
end
%take a point on +ve x axis
reply='N';
while ~strcmpi(reply,'Y')
answer = {};
while isempty(answer)       
prompt={'Pixel Coords: '};
name='Lower Right Corner';
numlines=[1,35]; %this width allows for title to be seen
defaultanswer={'[1024 768]'};
answer=inputdlg(prompt,name,numlines,defaultanswer);
%convert from string to number data for output variables
if ~isempty(answer)
XAxisPixelCoords = str2num(answer{1});
end
end
pDataDest = [data.OtherMarkers(1).x data.OtherMarkers(1).z data.OtherMarkers(1).y];
Question = {'LOWER RIGHT pre coordinate transform:'...
''...
'Marker 1: ' num2str(pDataDest(1:3))...
''...
'Accept?'...
''};
ButtonName = questdlg(Question, 'Data Check', 'Yes', 'No', 'Quit', 'Yes');
switch ButtonName
case 'Yes'
x_axis = pDataDest;
reply = 'Y';
case 'No'
reply = 'N';
case 'Quit'
%quit opto too?
%need to pass quit flag so this actually works?
clear all; close all; Screen('CloseAll');
disp('*** Exiting Program ***');
return
end
  end
  end
% point on the xy plane
reply='N';
while ~strcmpi(reply,'Y')
answer = {};
while isempty(answer)       
prompt={'Pixel Coords: '};
name='Upper Left Corner';
numlines=[1,35]; %this width allows for title to be seen
defaultanswer={'[0 0]'};
answer=inputdlg(prompt,name,numlines,defaultanswer);
%convert from string to number data for output variables
if ~isempty(answer)
YAxisPixelCoords = str2num(answer{1});
end
end
pDataDest = [data.OtherMarkers(1).x data.OtherMarkers(1).z data.OtherMarkers(1).y];
Question = {'UPPER LEFT pre coordinate transform:'...
''...
'Marker 1: ' num2str(pDataDest(1:3))...
''...
'Accept?'...
''};
ButtonName = questdlg(Question, 'Data Check', 'Yes', 'No', 'Quit', 'Yes');
switch ButtonName
case 'Yes'
y_axis = pDataDest;
reply = 'Y';
case 'No'
reply = 'N';
case 'Quit'
%quit opto too?
%need to pass quit flag so this actually works?
clear all; close all; Screen('CloseAll');
disp('*** Exiting Program ***');
return
end
end
% finish the screen rect (event though this is redundant for establishing
% the plane)
reply='N';
while ~strcmpi(reply,'Y')
answer = {};
while isempty(answer)       
prompt={'Pixel Coords: '};
name='Upper Right Corner';
numlines=[1,35]; %this width allows for title to be seen
defaultanswer={'[1024 0]'};
answer=inputdlg(prompt,name,numlines,defaultanswer);
%convert from string to number data for output variables
if ~isempty(answer)
OppCornerPixelCoords = str2num(answer{1});
end
end
pDataDest = [data.OtherMarkers(1).x data.OtherMarkers(1).z data.OtherMarkers(1).y];
Question = {'UPPER RIGHT pre coordinate transform:'...
''...
'Marker 1: ' num2str(pDataDest(1:3))...
''...
'Accept?'...
''};
ButtonName = questdlg(Question, 'Data Check', 'Yes', 'No', 'Quit', 'Yes');
switch ButtonName
case 'Yes'
opp_corner = pDataDest;
reply = 'Y';
case 'No'
reply = 'N';
case 'Quit'
%quit opto too?
%need to pass quit flag so this actually works?
clear all; close all; Screen('CloseAll');
disp('*** Exiting Program ***');
return
end
end
%Create the Coordinate Systesm
[T_opto_plane,T_plane_opto]=MakeCoordSystem(orig_pos,x_axis,y_axis);
%Display the new transformed coordinate system
disp('Points in Local Coordinate System are:')
[new_orig]=transform4(T_opto_plane, orig_pos)
[new_x_axis]=transform4(T_opto_plane, x_axis)
[new_y_axis]=transform4(T_opto_plane, y_axis)
[new_opp_corner]=transform4(T_opto_plane, opp_corner)
touch_plane_info.T_opto_plane = double(T_opto_plane);
touch_plane_info.T_plane_opto = double(T_plane_opto);
touch_plane_info.opto_rect = double([new_orig; new_x_axis; new_y_axis; new_opp_corner]);
touch_plane_info.pixel_rect = double([OriginPixelCoords; XAxisPixelCoords; YAxisPixelCoords; OppCornerPixelCoords]);
touch_plane_info.old_opto_rect = double([orig_pos; x_axis; y_axis; opp_corner]);
%calculate the pixel to opto conversion
mm1 = double((new_x_axis(1) - new_orig(1))/(XAxisPixelCoords(1) - OriginPixelCoords(1)) * 1000);
mm2 = double((new_opp_corner(1) - new_y_axis(1))/(OppCornerPixelCoords(1) - YAxisPixelCoords(1)) * 1000);
mm3 = double(-(new_orig(2) - new_y_axis(2))/(OriginPixelCoords(2) - YAxisPixelCoords(2)) * 1000);
mm4 = double(-(new_x_axis(2) - new_opp_corner(2))/(XAxisPixelCoords(2) - OppCornerPixelCoords(2)) * 1000);
touch_plane_info.mmPerPixel = mean ([mm1 mm2 mm3 mm4]);

Revision as of 18:50, 19 April 2012


Matlab scripts

Setting the optitrak plane in matlab

In place of the matlab code for reading in optitrak data, the following matlab function can be used to:

  1. read in data sent from the optitrak system, and furthermore
  2. set the table top plane, as understood by the Optitrak, into variables for reference in matlab, and
  3. transform the native coordinate system of the optitrak (x z y) into another, possibly more familiar coordinate system (x y z).

This function should be called before opening a main window with psychtoolbox.


function [touch_plane_info, client] = opti_setup_touch_plane_srt

%This gives an error (freezes) if the NET assembly is already loaded.  In
%that case you need to quit Matlab and start over

if ~IsAssemblyAdded('NatNetML')  
	Opti = NET.addAssembly('C:\Users\Jim Enns\Documents\MATLAB\NatNetSDK2.2\NatNetSDK\lib\NatNetML.dll');
end

client = NatNetML.NatNetClientML(1);
%client.Initialize('142.103.0.167','142.103.0.167');
client.Initialize('142.103.251.175','142.103.251.175');
data = client.GetLastFrameOfData;
	

reply = 'N';
while ~strcmpi(reply,'Y')
	
	answer = {};
	while isempty(answer)        
		prompt={'Pixel Coords: '};
		name='Lower Left Corner';
		numlines=[1,35]; %this width allows for title to be seen
		defaultanswer={'[0 768]'};
		answer=inputdlg(prompt,name,numlines,defaultanswer);

		%convert from string to number data for output variables
		if ~isempty(answer)
			OriginPixelCoords = str2num(answer{1});
		end
	end

	pDataDest = [data.OtherMarkers(1).x data.OtherMarkers(1).z data.OtherMarkers(1).y];
	
	Question = {'LOWER LEFT pre coordinate transform:'...
		...
		'Marker 1: ' num2str(pDataDest(1:3))...
		...
		'Accept?'...
		};
	ButtonName = questdlg(Question, 'Data Check', 'Yes', 'No', 'Quit', 'Yes');

	switch ButtonName
		case 'Yes'
			orig_pos = pDataDest;
			reply = 'Y';
		case 'No'
			reply = 'N';
		case 'Quit'
			%quit opto too?
			%need to pass quit flag so this actually works?
			transform_info = [];
			clear all; close all; Screen('CloseAll'); 
			disp('*** Exiting Program ***');
			return
	end

end

%take a point on +ve x axis
reply='N';
while ~strcmpi(reply,'Y')

	answer = {};
	while isempty(answer)        
		prompt={'Pixel Coords: '};
		name='Lower Right Corner';
		numlines=[1,35]; %this width allows for title to be seen
		defaultanswer={'[1024 768]'};
		answer=inputdlg(prompt,name,numlines,defaultanswer);

		%convert from string to number data for output variables
		if ~isempty(answer)
			XAxisPixelCoords = str2num(answer{1});
		end
	end


	 pDataDest = [data.OtherMarkers(1).x data.OtherMarkers(1).z data.OtherMarkers(1).y];
	
	Question = {'LOWER RIGHT pre coordinate transform:'...
		...
		'Marker 1: ' num2str(pDataDest(1:3))...
		...
		'Accept?'...
		};
	ButtonName = questdlg(Question, 'Data Check', 'Yes', 'No', 'Quit', 'Yes');

	switch ButtonName
		case 'Yes'
			x_axis = pDataDest;
			reply = 'Y';
		case 'No'
			reply = 'N';
		case 'Quit'
			%quit opto too?
			%need to pass quit flag so this actually works?
			clear all; close all; Screen('CloseAll'); 
			disp('*** Exiting Program ***');
			return
	end
end

% point on the xy plane
reply='N';
while ~strcmpi(reply,'Y')

	answer = {};
	while isempty(answer)        
		prompt={'Pixel Coords: '};
		name='Upper Left Corner';
		numlines=[1,35]; %this width allows for title to be seen
		defaultanswer={'[0 0]'};
		answer=inputdlg(prompt,name,numlines,defaultanswer);

		%convert from string to number data for output variables
		if ~isempty(answer)
			YAxisPixelCoords = str2num(answer{1});
		end
	end

	 pDataDest = [data.OtherMarkers(1).x data.OtherMarkers(1).z data.OtherMarkers(1).y];
	
	Question = {'UPPER LEFT pre coordinate transform:'...
		...
		'Marker 1: ' num2str(pDataDest(1:3))...
		...
		'Accept?'...
		};
	ButtonName = questdlg(Question, 'Data Check', 'Yes', 'No', 'Quit', 'Yes');

	switch ButtonName
		case 'Yes'
			y_axis = pDataDest;
			reply = 'Y';
		case 'No'
			reply = 'N';
		case 'Quit'
			%quit opto too?
			%need to pass quit flag so this actually works?
			clear all; close all; Screen('CloseAll'); 
			disp('*** Exiting Program ***');
			return
	end
end

% finish the screen rect (event though this is redundant for establishing
% the plane)
reply='N';
while ~strcmpi(reply,'Y')

	answer = {};
	while isempty(answer)        
		prompt={'Pixel Coords: '};
		name='Upper Right Corner';
		numlines=[1,35]; %this width allows for title to be seen
		defaultanswer={'[1024 0]'};
		answer=inputdlg(prompt,name,numlines,defaultanswer);

		%convert from string to number data for output variables
		if ~isempty(answer)
			OppCornerPixelCoords = str2num(answer{1});
		end
	end

	 pDataDest = [data.OtherMarkers(1).x data.OtherMarkers(1).z data.OtherMarkers(1).y];
	
	Question = {'UPPER RIGHT pre coordinate transform:'...
		...
		'Marker 1: ' num2str(pDataDest(1:3))...
		...
		'Accept?'...
		};
	ButtonName = questdlg(Question, 'Data Check', 'Yes', 'No', 'Quit', 'Yes');

	switch ButtonName
		case 'Yes'
			opp_corner = pDataDest;
			reply = 'Y';
		case 'No'
			reply = 'N';
		case 'Quit'
			%quit opto too?
			%need to pass quit flag so this actually works?
			clear all; close all; Screen('CloseAll'); 
			disp('*** Exiting Program ***');
			return
	end
end

%Create the Coordinate Systesm
[T_opto_plane,T_plane_opto]=MakeCoordSystem(orig_pos,x_axis,y_axis);

%Display the new transformed coordinate system
disp('Points in Local Coordinate System are:')
[new_orig]=transform4(T_opto_plane, orig_pos)
[new_x_axis]=transform4(T_opto_plane, x_axis)
[new_y_axis]=transform4(T_opto_plane, y_axis)
[new_opp_corner]=transform4(T_opto_plane, opp_corner)

touch_plane_info.T_opto_plane = double(T_opto_plane);
touch_plane_info.T_plane_opto = double(T_plane_opto); 
touch_plane_info.opto_rect = double([new_orig; new_x_axis; new_y_axis; new_opp_corner]);
touch_plane_info.pixel_rect = double([OriginPixelCoords; XAxisPixelCoords; YAxisPixelCoords; OppCornerPixelCoords]);
touch_plane_info.old_opto_rect = double([orig_pos; x_axis; y_axis; opp_corner]);

%calculate the pixel to opto conversion
mm1 = double((new_x_axis(1) - new_orig(1))/(XAxisPixelCoords(1) - OriginPixelCoords(1)) * 1000);
mm2 = double((new_opp_corner(1) - new_y_axis(1))/(OppCornerPixelCoords(1) - YAxisPixelCoords(1)) * 1000);
mm3 = double(-(new_orig(2) - new_y_axis(2))/(OriginPixelCoords(2) - YAxisPixelCoords(2)) * 1000);
mm4 = double(-(new_x_axis(2) - new_opp_corner(2))/(XAxisPixelCoords(2) - OppCornerPixelCoords(2)) * 1000);
touch_plane_info.mmPerPixel = mean ([mm1 mm2 mm3 mm4]);