Source code for direct.directdevices.DirectDeviceManager

"""Class used to create and control VRPN devices."""

from direct.showbase.DirectObject import DirectObject
from panda3d.core import *
from panda3d.vrpn import *

ANALOG_MIN = -0.95
ANALOG_MAX = 0.95
ANALOG_DEADBAND = 0.125
ANALOG_CENTER = 0.0


[docs]class DirectDeviceManager(VrpnClient, DirectObject):
[docs] def __init__(self, server = None): # Determine which server to use if server is not None: # One given as constructor argument self.server = server else: # Check config file, if that fails, use default self.server = ConfigVariableString('vrpn-server', 'spacedyne').getValue() # Create a vrpn client VrpnClient.__init__(self, self.server)
[docs] def createButtons(self, device): return DirectButtons(self, device)
[docs] def createAnalogs(self, device): return DirectAnalogs(self, device)
[docs] def createTracker(self, device): return DirectTracker(self, device)
[docs] def createDials(self, device): return DirectDials(self, device)
[docs] def createTimecodeReader(self, device): return DirectTimecodeReader(self, device)
[docs]class DirectButtons(ButtonNode, DirectObject): buttonCount = 0
[docs] def __init__(self, vrpnClient, device): # Keep track of number of buttons created DirectButtons.buttonCount += 1 # Create a new button node for the given device ButtonNode.__init__(self, vrpnClient, device) # Create a unique name for this button object self.name = 'DirectButtons-' + repr(DirectButtons.buttonCount) # Attach node to data graph try: self._base = base except: self._base = simbase self.nodePath = self._base.dataRoot.attachNewNode(self)
def __getitem__(self, index): if (index < 0) or (index >= self.getNumButtons()): raise IndexError return self.getButtonState(index) def __len__(self): return self.getNumButtons()
[docs] def enable(self): self.nodePath.reparentTo(self._base.dataRoot)
[docs] def disable(self): self.nodePath.reparentTo(self._base.dataUnused)
[docs] def getName(self): return self.name
[docs] def getNodePath(self): return self.nodePath
def __repr__(self): string = self.name + ': ' for val in self: string = string + '%d' % val + ' ' return string
[docs]class DirectAnalogs(AnalogNode, DirectObject): analogCount = 0 _analogDeadband = ConfigVariableDouble('vrpn-analog-deadband', ANALOG_DEADBAND) _analogMin = ConfigVariableDouble('vrpn-analog-min', ANALOG_MIN) _analogMax = ConfigVariableDouble('vrpn-analog-max', ANALOG_MAX) _analogCenter = ConfigVariableDouble('vrpn-analog-center', ANALOG_CENTER)
[docs] def __init__(self, vrpnClient, device): # Keep track of number of analogs created DirectAnalogs.analogCount += 1 # Create a new analog node for the given device AnalogNode.__init__(self, vrpnClient, device) # Create a unique name for this analog object self.name = 'DirectAnalogs-' + repr(DirectAnalogs.analogCount) # Attach node to data graph try: self._base = base except: self._base = simbase self.nodePath = self._base.dataRoot.attachNewNode(self) # See if any of the general analog parameters are dconfig'd self.analogDeadband = self._analogDeadband.getValue() self.analogMin = self._analogMin.getValue() self.analogMax = self._analogMax.getValue() self.analogCenter = self._analogCenter.getValue() self.analogRange = self.analogMax - self.analogMin
def __getitem__(self, index): if (index < 0) or (index >= self.getNumControls()): raise IndexError return self.getControlState(index) def __len__(self): return self.getNumControls()
[docs] def enable(self): self.nodePath.reparentTo(self._base.dataRoot)
[docs] def disable(self): self.nodePath.reparentTo(self._base.dataUnused)
[docs] def normalizeWithoutCentering(self, val, minVal = -1, maxVal = 1): # # This is the old code that doesn't incorporate the centering fix # # First record sign if val < 0: sign = -1 else: sign = 1 # Zero out values in deadband val = sign * max(abs(val) - self.analogDeadband, 0.0) # Clamp value between analog range min and max and scale about center val = min(max(val, self.analogMin), self.analogMax) # Normalize values to given minVal and maxVal range return (((maxVal - minVal) * ((val - self.analogMin) / float(self.analogRange))) + minVal)
[docs] def normalize(self, rawValue, minVal = -1, maxVal = 1, sf = 1.0): aMax = self.analogMax aMin = self.analogMin center = self.analogCenter deadband = self.analogDeadband # Zero out values in deadband if abs(rawValue - center) <= deadband: return 0.0 # Clamp value between aMin and aMax and scale around center if rawValue >= center: # Convert positive values to range 0 to 1 val = min(rawValue * sf, aMax) percentVal = ((val - (center + deadband))/ float(aMax - (center + deadband))) else: # Convert negative values to range -1 to 0 val = max(rawValue * sf, aMin) percentVal = -((val - (center - deadband))/ float(aMin - (center - deadband))) # Normalize values to given minVal and maxVal range return ((maxVal - minVal) * ((percentVal + 1)/2.0)) + minVal
[docs] def normalizeChannel(self, chan, minVal = -1, maxVal = 1, sf = 1.0): try: return self.normalize(self[chan], minVal, maxVal, sfx) except IndexError: return 0.0
[docs] def getName(self): return self.name
[docs] def getNodePath(self): return self.nodePath
def __repr__(self): string = self.name + ': ' for val in self: string = string + '%.3f' % val + ' ' return string
[docs]class DirectTracker(TrackerNode, DirectObject): trackerCount = 0
[docs] def __init__(self, vrpnClient, device): # Keep track of number of trackers created DirectTracker.trackerCount += 1 # Create a new tracker node for the given device TrackerNode.__init__(self, vrpnClient, device) # Create a unique name for this tracker object self.name = 'DirectTracker-' + repr(DirectTracker.trackerCount) # Attach node to data graph try: self._base = base except: self._base = simbase self.nodePath = self._base.dataRoot.attachNewNode(self)
[docs] def enable(self): self.nodePath.reparentTo(self._base.dataRoot)
[docs] def disable(self): self.nodePath.reparentTo(self._base.dataUnused)
[docs] def getName(self): return self.name
[docs] def getNodePath(self): return self.nodePath
def __repr__(self): return self.name
[docs]class DirectDials(DialNode, DirectObject): dialCount = 0
[docs] def __init__(self, vrpnClient, device): # Keep track of number of dials created DirectDials.dialCount += 1 # Create a new dial node for the given device DialNode.__init__(self, vrpnClient, device) # Create a unique name for this dial object self.name = 'DirectDials-' + repr(DirectDials.dialCount) # Attach node to data graph try: self._base = base except: self._base = simbase self.nodePath = self._base.dataRoot.attachNewNode(self)
def __getitem__(self, index): """ if (index < 0) or (index >= self.getNumDials()): raise IndexError """ return self.readDial(index) def __len__(self): return self.getNumDials()
[docs] def enable(self): self.nodePath.reparentTo(self._base.dataRoot)
[docs] def disable(self): self.nodePath.reparentTo(self._base.dataUnused)
[docs] def getName(self): return self.name
[docs] def getNodePath(self): return self.nodePath
def __repr__(self): string = self.name + ': ' for i in range(self.getNumDials()): string = string + '%.3f' % self[i] + ' ' return string
[docs]class DirectTimecodeReader(AnalogNode, DirectObject): timecodeReaderCount = 0
[docs] def __init__(self, vrpnClient, device): # Keep track of number of timecodeReader created DirectTimecodeReader.timecodeReaderCount += 1 # Create a new dial node for the given device AnalogNode.__init__(self, vrpnClient, device) # Create a unique name for this dial object self.name = ('DirectTimecodeReader-' + repr(DirectTimecodeReader.timecodeReaderCount)) # Initialize components of timecode self.frames = 0 self.seconds = 0 self.minutes = 0 self.hours = 0 # Attach node to data graph try: self._base = base except: self._base = simbase self.nodePath = self._base.dataRoot.attachNewNode(self)
[docs] def enable(self): self.nodePath.reparentTo(self._base.dataRoot)
[docs] def disable(self): self.nodePath.reparentTo(self._base.dataUnused)
[docs] def getName(self): return self.name
[docs] def getNodePath(self): return self.nodePath
[docs] def getTime(self): # Assume only one card, use channel 0 timeBits = int(self.getControlState(0)) self.frames = ((timeBits & 0xF) + (((timeBits & 0xF0) >> 4) * 10)) self.seconds = (((timeBits & 0x0F00) >> 8) + (((timeBits & 0xF000) >> 12) * 10)) self.minutes = (((timeBits & 0x0F0000) >> 16) + (((timeBits & 0xF00000) >> 20) * 10)) self.hours = (((timeBits & 0xF000000) >> 24) + (((timeBits & 0xF0000000) >> 28) * 10)) self.totalSeconds = ((self.hours * 3600) + (self.minutes * 60) + self.seconds + (self.frames / 30.0)) return (self.hours, self.minutes, self.seconds, self.frames, self.totalSeconds)
def __repr__(self): string = ('%s: %d:%d:%d:%d' % ((self.name,) + self.getTime()[:-1])) return string