DirectDeviceManager.py 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. """ Class used to create and control vrpn devices """
  2. from PandaObject import *
  3. from DirectGeometry import CLAMP
  4. ANALOG_MIN = -0.95
  5. ANALOG_MAX = 0.95
  6. ANALOG_RANGE = ANALOG_MAX - ANALOG_MIN
  7. ANALOG_DEADBAND = 0.075
  8. class DirectDeviceManager(VrpnClient, PandaObject):
  9. def __init__(self, server = None):
  10. # Determine which server to use
  11. if server != None:
  12. # One give as constructor argument
  13. self.server = server
  14. else:
  15. # Check config file, if that fails, use default
  16. self.server = base.config.GetString('vrpn-server', 'spacedyne')
  17. # Create a vrpn client
  18. VrpnClient.__init__(self, self.server)
  19. def createButtons(self, device):
  20. return DirectButtons(self, device)
  21. def createAnalogs(self, device):
  22. return DirectAnalogs(self, device)
  23. def createDials(self, device):
  24. return DirectDials(self, device)
  25. def createTimecodeReader(self, device):
  26. return DirectTimecodeReader(self, device)
  27. class DirectButtons(ButtonNode, PandaObject):
  28. buttonCount = 0
  29. def __init__(self, vrpnClient, device):
  30. # Keep track of number of buttons created
  31. DirectButtons.buttonCount += 1
  32. # Create a unique name for this button object
  33. self.name = 'DirectButtons-' + `DirectButtons.buttonCount`
  34. # Create a new button node for the given device
  35. ButtonNode.__init__(self, vrpnClient, device)
  36. # Attach node to data graph
  37. self.nodePath = base.dataRoot.attachNewNode(self)
  38. def __getitem__(self, index):
  39. if (index < 0) or (index > self.getNumButtons()):
  40. raise IndexError
  41. return self.getButtonState(index)
  42. def __len__(self):
  43. return self.getNumButtons()
  44. def enable(self):
  45. self.nodePath.reparentTo(base.dataRoot)
  46. def disable(self):
  47. self.nodePath.reparentTo(base.dataUnused)
  48. def getName(self):
  49. return self.name
  50. def getNodePath(self):
  51. return self.nodePath
  52. def __repr__(self):
  53. str = self.name + ': '
  54. for val in self:
  55. str = str + '%d' % val + ' '
  56. return str
  57. class DirectAnalogs(AnalogNode, PandaObject):
  58. analogCount = 0
  59. def __init__(self, vrpnClient, device):
  60. # Keep track of number of analogs created
  61. DirectAnalogs.analogCount += 1
  62. # Create a unique name for this analog object
  63. self.name = 'DirectAnalogs-' + `DirectAnalogs.analogCount`
  64. # Create a new analog node for the given device
  65. AnalogNode.__init__(self, vrpnClient, device)
  66. # Attach node to data graph
  67. self.nodePath = base.dataRoot.attachNewNode(self)
  68. def __getitem__(self, index):
  69. if (index < 0) or (index > self.getNumControls()):
  70. raise IndexError
  71. return self.getControlState(index)
  72. def __len__(self):
  73. return self.getNumControls()
  74. def enable(self):
  75. self.nodePath.reparentTo(base.dataRoot)
  76. def disable(self):
  77. self.nodePath.reparentTo(base.dataUnused)
  78. def normalize(self, val, minVal = -1, maxVal = -1):
  79. # First record sign
  80. if val < 0:
  81. sign = -1
  82. else:
  83. sign = 1
  84. # Zero out values in deadband
  85. val = sign * max(abs(val) - ANALOG_DEADBAND, 0.0)
  86. # Now clamp value between minVal and maxVal
  87. val = CLAMP(val, ANALOG_MIN, ANALOG_MAX)
  88. return (((maxVal - minVal) * ((val - ANALOG_MIN) / ANALOG_RANGE))
  89. + minVal)
  90. def normalizeChannel(self, chan, minVal = -1, maxVal = 1):
  91. try:
  92. if (chan == 2) or (chan == 6):
  93. # These channels have reduced range
  94. return self.normalize(self[chan] * 3.0, minVal, maxVal)
  95. else:
  96. return self.normalize(self[chan], minVal, maxVal)
  97. except IndexError:
  98. return 0.0
  99. def getName(self):
  100. return self.name
  101. def getNodePath(self):
  102. return self.nodePath
  103. def __repr__(self):
  104. str = self.name + ': '
  105. for val in self:
  106. str = str + '%.3f' % val + ' '
  107. return str
  108. class DirectDials(DialNode, PandaObject):
  109. dialCount = 0
  110. def __init__(self, vrpnClient, device):
  111. # Keep track of number of dials created
  112. DirectDials.dialCount += 1
  113. # Create a unique name for this dial object
  114. self.name = 'DirectDials-' + `DirectDials.dialCount`
  115. # Create a new dial node for the given device
  116. DialNode.__init__(self, vrpnClient, device)
  117. # Attach node to data graph
  118. self.nodePath = base.dataRoot.attachNewNode(self)
  119. def __getitem__(self, index):
  120. if (index < 0) or (index > self.getNumDials()):
  121. raise IndexError
  122. return self.readDial(index)
  123. def __len__(self):
  124. return self.getNumDials()
  125. def enable(self):
  126. self.nodePath.reparentTo(base.dataRoot)
  127. def disable(self):
  128. self.nodePath.reparentTo(base.dataUnused)
  129. def getName(self):
  130. return self.name
  131. def getNodePath(self):
  132. return self.nodePath
  133. def __repr__(self):
  134. str = self.name + ': '
  135. for val in self:
  136. str = str + '%.3f' % val + ' '
  137. return str
  138. class DirectTimecodeReader(AnalogNode, PandaObject):
  139. timecodeReaderCount = 0
  140. def __init__(self, vrpnClient, device):
  141. # Keep track of number of timecodeReader created
  142. DirectTimecodeReader.timecodeReaderCount += 1
  143. # Create a unique name for this dial object
  144. self.name = ('DirectTimecodeReader-' +
  145. `DirectTimecodeReader.timecodeReaderCount`)
  146. # Initialize components of timecode
  147. self.frames = 0
  148. self.seconds = 0
  149. self.minutes = 0
  150. self.hours = 0
  151. # Create a new dial node for the given device
  152. AnalogNode.__init__(self, vrpnClient, device)
  153. # Attach node to data graph
  154. self.nodePath = base.dataRoot.attachNewNode(self)
  155. def enable(self):
  156. self.nodePath.reparentTo(base.dataRoot)
  157. def disable(self):
  158. self.nodePath.reparentTo(base.dataUnused)
  159. def getName(self):
  160. return self.name
  161. def getNodePath(self):
  162. return self.nodePath
  163. def getTime(self):
  164. # Assume only one card, use channel 0
  165. timeBits = int(self.getControlState(0))
  166. self.frames = ((timeBits & 0xF) +
  167. (((timeBits & 0xF0) >> 4) * 10))
  168. self.seconds = (((timeBits & 0x0F00) >> 8) +
  169. (((timeBits & 0xF000) >> 12) * 10))
  170. self.minutes = (((timeBits & 0x0F0000) >> 16) +
  171. (((timeBits & 0xF00000) >> 20) * 10))
  172. self.hours = (((timeBits & 0xF0000000) >> 24) +
  173. (((timeBits & 0xF0000000) >> 28) * 10))
  174. self.totalSeconds = ((self.hours * 3600) +
  175. (self.minutes * 60) +
  176. self.seconds +
  177. (self.frames / 30.0))
  178. return (self.hours, self.minutes, self.seconds, self.frames,
  179. self.totalSeconds)
  180. def __repr__(self):
  181. str = ('%s: %d:%d:%d:%d' % ((self.name,) + self.getTime()[:-1]))
  182. return str