DualShock4 Motion Sensors Demo

Made a simple demo of usage DualShock4 gamepad’s motion sensors. It uses the real DualShock4 gamepad’s rotation (from internal gyro) to rotate the 3D model.

The model downloaded from Dualshock 4 - Download Free 3D model by Saba.Lanchava [66a48c6] - Sketchfab

import sys

from direct.showbase.ShowBase import ShowBase

from panda3d.core import load_prc_file_data, InputDeviceManager, PandaNode

import simplepbr


class DS4Demo(ShowBase):
    def __init__(self):
        load_prc_file_data('', '''
            win-size 1280 720
        ''')

        super().__init__()
        self.disable_mouse()
        self.pipeline = simplepbr.init()

        idm = InputDeviceManager.get_global_ptr()

        self._devices = set()
        for device in idm.get_devices():
            self._connect_device(device)

        self.accept('connect-device', self._connect_device)
        self.accept('disconnect-device', self._disconnect_device)
        self.accept('escape', sys.exit)

        self._container = self.render.attach_new_node(PandaNode('Container'))
        self._model = self.loader.load_model('scene.gltf')
        self._model.reparent_to(self._container)
        # self._model.set_p(90)
        self._x = [0] * 10
        self._y = [0] * 10

        self.cam.set_y(-100)

        self.task_mgr.add(self._update, '_update')

    def _connect_device(self, device):
        if device not in self._devices:
            self.attach_input_device(device)
            self._devices.add(device)

            print('{manufacturer} {name} [{class}] [{vid:04x}:{pid:04x}]'.format(**{
                'name': device.name,
                'class': device.device_class.name,
                'manufacturer': device.manufacturer,
                'vid': device.vendor_id,
                'pid': device.product_id,
            }))

    def _disconnect_device(self, device):
        if device in self._devices:
            self._devices.remove(device)

    def _update(self, task):
        x = 0
        y = 0

        for device in self._devices:
            if device.name == 'Wireless Controller Motion Sensors':
                for axis in device.axes:
                    # X axis: 0.25 (rotated left/CCW) to -0.25 (rotated right/CW)
                    if axis.axis.name == 'x':
                        x = axis.value * -4  # convert to range: -1 to 1

                    # elif axis.axis.name == 'y':  # Y axis: 0.25 (flat on table) to -0.25 (upside down)
                    elif axis.axis.name == 'throttle':  # Y axis: 0.25 (lightbar up) to -0.25 (lightbar down)
                        y = axis.value * -4  # convert to range: -1 to 1

        # fixes wobble, but adds a delay
        self._x.append(x)
        self._x = self._x[1:]
        self._y.append(y)
        self._y = self._y[1:]
        x_ave = sum(self._x) / len(self._x)
        y_ave = sum(self._y) / len(self._y)
        # print(x_ave, y_ave)

        self._container.set_r(x_ave * 90)
        self._container.set_p(y_ave * 90)

        return task.again


if __name__ == '__main__':
    demo = DS4Demo()
    demo.run()

8 Likes