View Single Post
  #5  
Old 02-15-2012, 02:13 PM
AySz88 AySz88 is offline
Member
 
Join Date: Aug 2011
Posts: 13
Part 2 of sunyhardware.py:
Code:
class Keyboard:
	"""
	Implements a simulated positional tracker using the keyboard.
	
	This class is especially useful for debugging, when access to the
	HiBall hardware is unavailable or undesirable. The key mapping is
	displayed in the main window. An associated cave object, with
	tracker-adjusted frustum, and link to the active viewpoint are
	created by default.
	
	Variables: head, cave, view.
	Functions: write.
	
	The variable head provides access to the Vizard tracker object, the
	variable cave provides access to the Vizard cave object with which
	the tracker is associated, and the variable view provides access to
	the view to which the tracker is linked. For additional information
	about a particular function, please see the documentation string
	for that function.
	
	Definition:
	Keyboard(makeCave=True,orthographic=False,trackCave=True,makeLink=True)
	
	Usage:
	>>> tracker = Keyboard()
	>>> position = tracker.head.getPosition()
	"""
	
	head = cave = view = None
	
	def __init__(self,makeCave=True,orthographic=False,trackCave=True,makeLink=True):
		#keyboard simulated tracker
		import viztracker
		self.head = viztracker.add()
		self.head.setPosition(-_screenWidth/2-_screenWidthOffset,_screenHeight/2+_screenHeightOffset+_eyesHeightOffset,-2) #start in the "middle" of the room
		
		#display keyboard mapping
		import vizinfo #Vizard 2D GUI commands
		self.info = vizinfo.add('Left/Right = Q/E\n'+
			'Up/Down = R/F\n'+
			'Forwards/Backwards = W/S\n\n'+
			'Roll Left/Right = G/J\n'+
			'Pitch Up/Down = Y/H\n'+
			'Yaw Left/Right = A/D')
		self.info.title('Keyboard Tracker Mapping')
		
		#add cave and link viewpoint
		if makeCave:
			if trackCave:
				self.cave = loadCave(self.head,orthographic)
			else:
				self.cave = loadCave(None,orthographic)
		if makeLink:
			self.view = linkView(self.head,makeCave)
		
	def write(self,timerID):
		"""
		Prints the simulated keyboard coordinates to standard output.
		
		Accepts the timerID as specified by viz.callback. Prints the
		current tracker position and orientation whenever a timer
		expires.
		
		Definition:
		write(timerID)
		
		Usage:
		>>> viz.callback(viz.TIMER_EVENT,write)
		>>> viz.starttimer(0,3,viz.FOREVER)
		"""
		
		print 'Keyboard [x, y, z] = [%.3f, %.3f, %.3f]'%tuple(self.head.getPosition())
		print 'Keyboard [yaw, pitch, roll] = [%.3f, %.3f, %.3f]'%tuple(self.head.getEuler())

class HiBall:
	"""
	Implements a connection to the HiBall Wide Area Tracker via VRPN.
	
	This class simplifies access to the HiBall hardware. It loads the
	required VRPN plug-in and creates the tracker object(s). An
	associated cave object, with tracker-adjusted frustum, and link
	to the active viewpoint are created by default.
	
	The HiBall sensor zero point (X=Y=Z=0) is located on floor below
	front-right LED. The default directional vectors (+X=Left,
	+Y=Backwards, +Z=Up) are remapped (+X=Right, +Y=Up, +Z=Forwards).
	The default orientational vectors are correspondingly remapped.
	
	For the headtracker, the location tracked is between the eyes of
	a generic individual.  For the stylus, the location tracked is at
	the base of the HiBall sensor. (TODO calibrate for the stylus point)
	
	Variables: head, cave, view.
	Functions: write.
	
	The variable head provides access to a viz.Linkable tracking the
	appropriate location (not necessarily a VizExtensionSensor), the
	variable cave provides access to the Vizard cave object with which
	the tracker is associated, and the variable view provides access to
	the view to which the tracker is linked. For additional information
	about a particular function, please see the documentation string
	for that function.
	
	Definition:
	HiBall(makeCave=True,orthographic=False,trackCave=True,makeLink=True,sensor=SENSOR_HEADTRACKER)
	
	Usage:
	>>> tracker = HiBall()
	>>> position = tracker.head.getPosition()
	"""
	
	SENSOR_HEADTRACKER = 0;
	SENSOR_STYLUS = 1; #handheld stylus (borrowed from UNC as of 7/2011)
	
	SENSOR_DEFAULT = SENSOR_HEADTRACKER;
	
	vrpn = viz.add('vrpn7.dle') #VRPN 7.15 plug-in
	
	head = cave = view = None
	
	def __init__(self,makeCave=True,orthographic=False,trackCave=True,makeLink=True,sensor=SENSOR_DEFAULT):
		"""VRPN head tracker"""
		
		# the 0 in 'Tracker0' is NOT the sensor number
		self.raw = self.__class__.vrpn.addTracker('Tracker0@localhost', sensor)
		self.raw.swapPos([-1,3,-2])
		self.raw.swapQuat([1,-3,2,4])
		
		# Find appropriate offset in local coordinate space
		if sensor == self.__class__.SENSOR_HEADTRACKER:
			offset = (0,-_eyesHeightOffset,-_eyesDepthOffset)
		elif sensor == self.__class__.SENSOR_STYLUS:
			offset = _stylusOffset
		else:
			offset = (0,0,0)
			print 'Unknown sensor %s; please update sunyhardware'%sensor
		
		link = viz.link(self.raw, viz.NullLinkable)
		link.preTrans(offset)
		self.head = link # Links are themselves linkables
		
		self.sensor = sensor; # just for .write()
		
		#add cave and link viewpoint
		if makeCave:
			if trackCave:
				self.cave = loadCave(self.head,orthographic)
			else:
				self.cave = loadCave(None,orthographic)
		if makeLink:
			self.view = linkView(self.head,makeCave)
		
	def write(self,timerID):
		"""
		Prints the HiBall coordinates to standard output.
		
		Accepts the timerID as specified by viz.callback. Prints the
		current tracker position and orientation whenever any timer
		expires.
		
		Definition:
		write(timerID)
		
		Usage:
		>>> viz.callback(viz.TIMER_EVENT,write)
		>>> viz.starttimer(0,3,viz.FOREVER)
		"""
		print 'HiBall%s'%self.sensor, '[x, y, z] = [%.3f, %.3f, %.3f]'%tuple(self.head.getPosition())
		print 'HiBall%s'%self.sensor, '[yaw, pitch, roll] = [%.3f, %.3f, %.3f]'%tuple(self.head.getEuler())

def isHiBallAvailable():
	"""
	Tries to connect to the HiBall server (computer name 'hiball')
	on port 3883, and returns true when successful.
	Doesn't actually do anything (similar to a ping).
	"""
	
	import socket #built-in Python socket module
	
	try:
		udpSock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #create UDP socket
		udpSock.connect(('hiball',3883)) #try to connect
		udpSock.close() #close socket test connection
		return True
	except socket.gaierror:
		return False

def getTracker(makeCave=True,orthographic=False,trackCave=True,makeLink=True,sensor=HiBall.SENSOR_DEFAULT):
	"""
	Factory function to return a HiBall or Keyboard tracker.
	
	This class is a factory function, which returns a HiBall tracker
	object when the HiBall system is present, or a simulated Keyboard
	tracker object otherwise. For additional information about the
	HiBall and Keyboard classes, please see the class documentation
	strings.
	
	The boolean flags makeCave, orthographic, trackCave, and makeLink
	specify the type of virtual reality environment to construct:
	makeCave=True uses hard-coded cave parameters (see loadCave),
	orthographic=True results in orthographic projection (object size
	will need to be reduced by a factor of 100), trackCave=True allows
	the tracker object to update the cave frustums, and makeLink=True
	links the tracker object's position to the cave's view matrix.
	
	Definition:
	getTracker(makeCave=True,orthographic=False,trackCave=True,makeLink=True,sensor=HiBall.SENSOR_DEFAULT)
	
	Usage:
	>>> tracker = getTracker(sensor=HiBall.SENSOR_HEADTRACKER)
	>>> position = tracker.head.getPosition()
	"""
	
	# return appropriate tracker object
	if isHiBallAvailable():
		return HiBall(makeCave,orthographic,trackCave,makeLink,sensor)
	else:
		return Keyboard(makeCave,orthographic,trackCave,makeLink)

def getAllSensors():
	"""
	Returns all three sensors (head and stylus trackers, and stylus button)
	after constructing them using 'reasonable' default settings.  This sets
	up the cave with perspective projection, with tracking, and links the
	headtracker to the cave's view matrix.
	
	The head tracker tracks the orientation of the head and the location of
	the point between the eyes (of a generic subject).  The stylus tracker
	provides the position of the stylus at the bottom of the sensor and its
	orientation.
	
	Note that if the hiball server is not available, it will return a
	keyboard tracker as the headtracker, and None for the stylus tracker
	and stylus button.
	
	Usage:
	>>> (headTracker, stylusTracker, button) = getAllSensors()
	>>> # EXAMPLES FOR DEBUGGING
	>>> def writeAll(timerID):
			headTracker.write(timerID)
			if stylusTracker: stylusTracker.write(timerID)
			if stylusButton: print 'Button =', stylusButton.buttonState(), '(buttons:' + str(stylusButton.buttonCount()) + ')'
	>>> viz.callback(viz.TIMER_EVENT,writeAll)
	>>> viz.starttimer(0,3,viz.FOREVER)
	
	>>> def onButtonUp(e):
			if e.object is stylusButton:
				pass #YOUR CODE HERE
	>>> viz.callback(viz.SENSOR_UP_EVENT,onButtonUp)
	
	>>> def onButtonDown(e):
			if e.object is stylusButton:
				pass #YOUR CODE HERE
	>>> viz.callback(viz.SENSOR_DOWN_EVENT,onButtonDown)
	"""
	
	if True:#isHiBallAvailable():
		headTracker = HiBall(sensor=HiBall.SENSOR_HEADTRACKER)
		stylusTracker = HiBall(makeCave=False,
								   makeLink=False,
								   sensor=HiBall.SENSOR_STYLUS)
		button = HiBall.vrpn.addButton('Button0@localhost')
	else:
		headTracker = Keyboard()
		stylusTracker = None
		button = None
		
	return (headTracker, stylusTracker, button)

if __name__=='__main__': #if module is run as a script
	#display the documentation string
	print __doc__
Reply With Quote