Accès au capteur de mouvement DualShock 4 sous Windows (idéalement Unity)

10

J'essaie d'utiliser l' IMU d' un DualShock 4 comme contrôleur de mouvement dans Unity, sous Windows 7.

Jusqu'à présent, j'ai essayé:

  • DS4Windows (1.5.11): lit les données du capteur de mouvement, mais ne les expose pas à Unity en tant qu'axes, sauf si je les mappe sur les joysticks gauche et droit. Ce n'est pas suffisant car je perds l'usage des sticks, je ne peux adapter que 4 des 6 canaux de données, et les valeurs qui transitent sont écrêtées dans une plage étroite.
  • Motioninjoy (0.7.1001): ne semble pas détecter le DS4 en tant que contrôleur (les derniers documents se réfèrent uniquement à DS3 et antérieurs)
  • GlovePIE (0.43): après avoir suivi les instructions d'utilisation du DualShock 3 avec LibUSB-Win32 (un plan long), les propriétés SixAxis sont toutes vides.

Dans le passé, j'ai utilisé des programmes externes comme GlovePIE pour capturer les données du capteur de mouvement à distance Wii et les transmettre à Unity via les messages OSC , donc je serais ouvert à une approche comme celle-ci si je ne peux pas demander à Unity de lire les capteurs du contrôleur directement via son système d'entrée .

Quelqu'un a eu de la chance avec ça?

DMGregory
la source

Réponses:

8

J'ai trouvé une approche viable. J'ai saisi la source DS4Tool et copié les bits dont j'avais besoin dans mon projet Unity afin de pouvoir lire directement les rapports de l'appareil.

(Il s'agit de la classe NativeMethods pour l'interface avec Kernel32.dll, l'énumération des périphériques de HidDevices et la lecture du rapport de la classe HidDevice . J'ai coupé le reste pour que les choses soient aussi simples que possible - je viens de recevoir une interrogation de thread pour les nouveaux données aussi vite que possible.)

Ce guide m'a dit où trouver les données du capteur de mouvement dans le rapport de 64 octets. Un petit test empirique et il semble que cela obtient les données en gs et radians / sec:

accel = new Vector3(
            System.BitConverter.ToInt16(_inputBuffer, 19),
            System.BitConverter.ToInt16(_inputBuffer, 21),
            System.BitConverter.ToInt16(_inputBuffer, 23)
            )/8192f;

gyro = new Vector3(
            System.BitConverter.ToInt16(_inputBuffer, 13),
            System.BitConverter.ToInt16(_inputBuffer, 15),
            System.BitConverter.ToInt16(_inputBuffer, 17)
            )/1024f;

C'est un système de coordonnées pour droitier avec x + droite, y + haut et z + pointant vers le joueur.

La récupération des données de cette manière n'interfère pas avec InputManager d'Unity, qui récupérera toujours les boutons et les bâtons comme prévu, sans avoir besoin de télécharger des pilotes non standard ou d'exécuter des logiciels supplémentaires en arrière-plan.


Mise à jour: sans fil (Bluetooth)

J'ai trouvé deux problèmes pour étendre cela pour fonctionner sans fil (et deux solutions):

  1. Les DualShock 4 n'aiment pas rester associés à Windows (avant Windows 8). Cette procédure stupide semble contourner cela sur Windows 7.

  2. Aucune donnée de capteur de mouvement lors de la connexion via Bluetooth . J'ai découvert que vous devez écrire un rapport de sortie sur l'appareil (voir HidDevice pour la méthode et DS4Device pour les nombres magiques) afin de l'inciter à envoyer des données de mouvement. Une fois cela fait, les rapports d'entrée que vous récupérez seront décalés de 2 octets.

DMGregory
la source
Est-il possible pour vous de clarifier cette réponse par ce post ?
Je voyage en ce moment, mais je m'en occuperai quand j'aurai un temps d'arrêt avec le wifi. Merci @JoshPetrie!
DMGregory
En creusant dans cela, je n'ai plus le code source du projet de détection de mouvement sur lequel je travaillais, et revenir à DS4Tool m'a rappelé pourquoi je n'avais arraché que les bits dont j'avais besoin! Cela devient super verbeux et peut aller au-delà d'une longueur raisonnable pour une réponse StackExchange. J'essaierai de simplifier autant que possible mais cela prendra du temps.
DMGregory
1
@DMGregory - Cette fiche technique est, je pense, pour l'IMU que DualShock 4 utilise: mouser.com/ds/2/783/BST-BMI055-DS000-08-786482.pdf - et il est écrit Short.MaxValue correspond à 2000 degrés par seconde. D'après mon calcul, vous obtenez environ 1833 degrés par seconde, ce qui est proche (et raisonnable pour le résultat des tests), mais peut-être que l'ajustement de votre calcul en conséquence vous donnera un peu plus de précision?
Jibb Smart
(Je fais des trucs gyroscopiques moi-même en ce moment, et j'allais essayer de comprendre les conversions d'unités standard en me testant, puis un ami a trouvé ce lien pour moi)
Jibb Smart
1

J'ai moi-même créé une solution à cela. Il s'appelle JoyShockLibrary et lit à partir de DualShock 4, Switch Pro Controller et Joy-Cons. Il est open source, licence MIT et fonctionne bien, bien que le support Bluetooth pour le DS4 n'ait été ajouté que récemment et continue de s'améliorer.

Il est utilisé dans JoyShockMapper , qui est un outil de mappage d'entrée, et JoyShockOverlay, qui n'est pas encore public, mais vous pouvez le voir en action ici (Gfycat) et ici (YouTube).

JoyShockLibrary complète bien XInput - en plus de ses rapports IMU, il ressemble beaucoup à XInput - vous pouvez donc couvrir facilement tous les contrôleurs de console de génération actuels, avec l'avantage du gyroscope et de l'accéléromètre de ceux qui le prennent en charge.

C'est assez facile à utiliser avec Unity, bien que je devrais mettre en place un fichier .cs pour le rendre plus facile pour les autres.

Jibb Smart
la source
0

Ceux-ci semblent tous être des outils qui enveloppent DirectInput dans XInput. Unity prend en charge DirectInput et vous devriez donc envisager de le faire fonctionner sans outils tiers. La clé est de savoir si l'IMU est mappé à quelque chose dans DirectInput et s'il est déjà dans un état utilisable. Sinon, vous devrez peut-être écrire votre propre gestionnaire DirectInput pour gérer les données brutes.

Vous pouvez remercier la xbox pour tous ces problèmes de contrôleur.

user54892
la source
Malheureusement, l'IMU ne semble être mappé à aucun des 20 "axes du joystick" de Unity, ni à Input.gyro etc. J'ai fini par creuser dans les données brutes; a ajouté une réponse avec les détails de la solution.
DMGregory