| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321 |
- """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
- class DirectDeviceManager(VrpnClient, DirectObject):
- 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)
- def createButtons(self, device):
- return DirectButtons(self, device)
- def createAnalogs(self, device):
- return DirectAnalogs(self, device)
- def createTracker(self, device):
- return DirectTracker(self, device)
- def createDials(self, device):
- return DirectDials(self, device)
- def createTimecodeReader(self, device):
- return DirectTimecodeReader(self, device)
- class DirectButtons(ButtonNode, DirectObject):
- buttonCount = 0
- 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()
- def enable(self):
- self.nodePath.reparentTo(self._base.dataRoot)
- def disable(self):
- self.nodePath.reparentTo(self._base.dataUnused)
- def getName(self):
- return self.name
- def getNodePath(self):
- return self.nodePath
- def __repr__(self):
- string = self.name + ': '
- for val in self:
- string = string + '%d' % val + ' '
- return string
- 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)
- 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()
- def enable(self):
- self.nodePath.reparentTo(self._base.dataRoot)
- def disable(self):
- self.nodePath.reparentTo(self._base.dataUnused)
- 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)
- 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
- 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
- def getName(self):
- return self.name
- def getNodePath(self):
- return self.nodePath
- def __repr__(self):
- string = self.name + ': '
- for val in self:
- string = string + '%.3f' % val + ' '
- return string
- class DirectTracker(TrackerNode, DirectObject):
- trackerCount = 0
- 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)
- def enable(self):
- self.nodePath.reparentTo(self._base.dataRoot)
- def disable(self):
- self.nodePath.reparentTo(self._base.dataUnused)
- def getName(self):
- return self.name
- def getNodePath(self):
- return self.nodePath
- def __repr__(self):
- return self.name
- class DirectDials(DialNode, DirectObject):
- dialCount = 0
- 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()
- def enable(self):
- self.nodePath.reparentTo(self._base.dataRoot)
- def disable(self):
- self.nodePath.reparentTo(self._base.dataUnused)
- def getName(self):
- return self.name
- 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
- class DirectTimecodeReader(AnalogNode, DirectObject):
- timecodeReaderCount = 0
- 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)
- def enable(self):
- self.nodePath.reparentTo(self._base.dataRoot)
- def disable(self):
- self.nodePath.reparentTo(self._base.dataUnused)
- def getName(self):
- return self.name
- def getNodePath(self):
- return self.nodePath
- 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
|