steeringWheel.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. #!/usr/bin/env python
  2. '''
  3. Demonstrate usage of steering wheels
  4. In this sample you can use a wheel type device to control the camera and
  5. show some messages on screen. You can acclerate forward using the
  6. accleration pedal and slow down using the break pedal.
  7. '''
  8. from direct.showbase.ShowBase import ShowBase
  9. from panda3d.core import TextNode, InputDevice, loadPrcFileData, Vec3
  10. from direct.gui.OnscreenText import OnscreenText
  11. loadPrcFileData("", """
  12. default-fov 60
  13. notify-level-device debug
  14. """)
  15. class App(ShowBase):
  16. def __init__(self):
  17. ShowBase.__init__(self)
  18. # Print all events sent through the messenger
  19. #self.messenger.toggleVerbose()
  20. self.lblWarning = OnscreenText(
  21. text = "No devices found",
  22. fg=(1,0,0,1),
  23. scale = .25)
  24. self.lblAction = OnscreenText(
  25. text = "Action",
  26. fg=(1,1,1,1),
  27. scale = .15)
  28. self.lblAction.hide()
  29. # Is there a steering wheel connected?
  30. self.wheel = None
  31. devices = self.devices.getDevices(InputDevice.DeviceClass.steering_wheel)
  32. if devices:
  33. self.connect(devices[0])
  34. self.currentMoveSpeed = 0.0
  35. self.maxAccleration = 28.0
  36. self.deaccleration = 10.0
  37. self.deaclerationBreak = 37.0
  38. self.maxSpeed = 80.0
  39. # Accept device dis-/connection events
  40. self.accept("connect-device", self.connect)
  41. self.accept("disconnect-device", self.disconnect)
  42. self.accept("escape", exit)
  43. # Accept button events of the first connected steering wheel
  44. self.accept("steering_wheel0-face_a", self.action, extraArgs=["Action"])
  45. self.accept("steering_wheel0-face_a-up", self.actionUp)
  46. self.accept("steering_wheel0-hat_up", self.center_wheel)
  47. self.environment = loader.loadModel("environment")
  48. self.environment.reparentTo(render)
  49. # save the center position of the wheel
  50. # NOTE: here we assume, that the wheel is centered when the application get started.
  51. # In real world applications, you should notice the user and give him enough time
  52. # to center the wheel until you store the center position of the controler!
  53. self.wheelCenter = 0
  54. if self.wheel is not None:
  55. self.wheelCenter = self.wheel.findAxis(InputDevice.Axis.wheel).value
  56. # disable pandas default mouse-camera controls so we can handle the camera
  57. # movements by ourself
  58. self.disableMouse()
  59. self.reset()
  60. self.taskMgr.add(self.moveTask, "movement update task")
  61. def connect(self, device):
  62. """Event handler that is called when a device is discovered."""
  63. # We're only interested if this is a steering wheel and we don't have a
  64. # wheel yet.
  65. if device.device_class == InputDevice.DeviceClass.steering_wheel and not self.wheel:
  66. print("Found %s" % (device))
  67. self.wheel = device
  68. # Enable this device to ShowBase so that we can receive events.
  69. # We set up the events with a prefix of "steering_wheel0-".
  70. self.attachInputDevice(device, prefix="steering_wheel0")
  71. # Hide the warning that we have no devices.
  72. self.lblWarning.hide()
  73. def disconnect(self, device):
  74. """Event handler that is called when a device is removed."""
  75. if self.wheel != device:
  76. # We don't care since it's not our wheel.
  77. return
  78. # Tell ShowBase that the device is no longer needed.
  79. print("Disconnected %s" % (device))
  80. self.detachInputDevice(device)
  81. self.wheel = None
  82. # Do we have any steering wheels? Attach the first other steering wheel.
  83. devices = self.devices.getDevices(InputDevice.DeviceClass.steering_wheel)
  84. if devices:
  85. self.connect(devices[0])
  86. else:
  87. # No devices. Show the warning.
  88. self.lblWarning.show()
  89. def reset(self):
  90. """Reset the camera to the initial position."""
  91. self.camera.setPosHpr(0, -200, 2, 0, 0, 0)
  92. def action(self, button):
  93. # Just show which button has been pressed.
  94. self.lblAction.text = "Pressed %s" % button
  95. self.lblAction.show()
  96. def actionUp(self):
  97. # Hide the label showing which button is pressed.
  98. self.lblAction.hide()
  99. def center_wheel(self):
  100. """Reset the wheels center rotation to the current rotation of the wheel"""
  101. self.wheelCenter = self.wheel.findAxis(InputDevice.Axis.wheel).value
  102. def moveTask(self, task):
  103. dt = base.clock.dt
  104. movementVec = Vec3()
  105. if not self.wheel:
  106. return task.cont
  107. if self.currentMoveSpeed > 0:
  108. self.currentMoveSpeed -= dt * self.deaccleration
  109. if self.currentMoveSpeed < 0:
  110. self.currentMoveSpeed = 0
  111. # we will use the first found wheel
  112. # Acclerate
  113. accleratorPedal = self.wheel.findAxis(InputDevice.Axis.accelerator).value
  114. accleration = accleratorPedal * self.maxAccleration
  115. if self.currentMoveSpeed > accleratorPedal * self.maxSpeed:
  116. self.currentMoveSpeed -= dt * self.deaccleration
  117. self.currentMoveSpeed += dt * accleration
  118. # Break
  119. breakPedal = self.wheel.findAxis(InputDevice.Axis.brake).value
  120. deacleration = breakPedal * self.deaclerationBreak
  121. self.currentMoveSpeed -= dt * deacleration
  122. if self.currentMoveSpeed < 0:
  123. self.currentMoveSpeed = 0
  124. # Steering
  125. rotation = self.wheelCenter - self.wheel.findAxis(InputDevice.Axis.wheel).value
  126. base.camera.setH(base.camera, 100 * dt * rotation)
  127. # calculate movement
  128. base.camera.setY(base.camera, dt * self.currentMoveSpeed)
  129. return task.cont
  130. app = App()
  131. app.run()