Acceso al sensor de movimiento DualShock 4 en Windows (idealmente Unity)

10

Estoy tratando de usar una IMU de DualShock 4 como controlador de movimiento en Unity, bajo Windows 7.

Hasta ahora he intentado:

  • DS4Windows (1.5.11): lee los datos del sensor de movimiento, pero no los expone a Unity como ejes a menos que los asigne a los sticks izquierdo y derecho. Esto no es suficiente ya que pierdo el uso de los sticks, solo puedo ajustar 4 de los 6 canales de datos, y los valores que vienen se recortan en un rango estrecho.
  • MotioninJoy (0.7.1001): no aparece para detectar la DS4 como un controlador (últimos documentos se refieren únicamente a DS3 y antes)
  • GlovePIE (0.43): después de seguir las instrucciones para usar el DualShock 3 con LibUSB-Win32 (una posibilidad remota), las propiedades de SixAxis están en blanco.

En el pasado, he usado programas externos como GlovePIE para capturar datos del sensor de movimiento remoto de Wii y pasarlos a Unity a través de mensajes OSC , por lo que estaría abierto a un enfoque como este si no puedo hacer que Unity lea los sensores del controlador directamente a través de su sistema de entrada .

Alguien tuvo suerte con esto?

DMGregory
fuente

Respuestas:

8

He encontrado un enfoque viable. Tomé la fuente DS4Tool y copié los bits que necesitaba en mi proyecto de Unity para poder leer los informes directamente desde el dispositivo.

(Esa es la clase NativeMethods para interactuar con Kernel32.dll, la enumeración de dispositivos de HidDevices y leer el informe de la clase HidDevice . Corté el resto para mantener las cosas lo más simples posible. Acabo de recibir un sondeo de hilos para nuevos datos lo más rápido posible).

Esta guía me dijo dónde encontrar los datos del sensor de movimiento dentro del informe de 64 bytes. Un poco de prueba empírica y parece que esto obtiene los datos en gs y radianes / seg:

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;

Es un sistema de coordenadas diestro con x + derecha, y + arriba y z + apuntando hacia el jugador.

Obtener los datos de esta manera no interfiere con el InputManager de Unity, que aún recogerá los botones y palos como se esperaba, sin necesidad de descargar controladores no estándar o ejecutar software adicional en segundo plano.


Actualización: inalámbrico (Bluetooth)

Encontré dos problemas para extender esto para que funcione de forma inalámbrica (y dos soluciones):

  1. A DualShock 4s no le gusta estar emparejado con Windows (antes de Windows 8). Este procedimiento tonto parece funcionar alrededor de eso en Windows 7.

  2. No hay datos del sensor de movimiento cuando se conecta a través de Bluetooth . Descubrí que necesita escribir un Informe de salida en el dispositivo (consulte HidDevice para el método y DS4Device para los números mágicos) para convencerlo de que envíe datos de movimiento. Una vez hecho esto, los informes de entrada que recuperes se cambiarán en 2 bytes.

DMGregory
fuente
¿Es posible aclarar esta respuesta en esta publicación ?
Estoy viajando ahora, pero lo tomaré cuando tenga algún tiempo de inactividad con wifi. Gracias @JoshPetrie!
DMGregory
Al profundizar en esto, ya no tengo el código fuente para el proyecto de detección de movimiento en el que estaba trabajando, y volver a DS4Tool me recordó por qué arranqué solo los bits que necesito. Esto se vuelve súper detallado y puede ir más allá de una longitud razonable para una respuesta de StackExchange. Intentaré simplificar todo lo que pueda, pero tomará algún tiempo.
DMGregory
1
@DMGregory: esta hoja de datos es, creo, para la IMU que utiliza DualShock 4: mouser.com/ds/2/783/BST-BMI055-DS000-08-786482.pdf , y dice Short.MaxValue corresponde a 2000 grados por segundo. Según mis cálculos, está obteniendo aproximadamente 1833 grados por segundo, lo que está cerca (y es razonable para el resultado de las pruebas), pero ¿quizás ajustar su cálculo en consecuencia le dará un poco más de precisión?
Jibb Smart
(Estoy haciendo cosas de giroscopio ahora mismo, e iba a tratar de averiguar las conversiones de unidades estándar probándome a mí mismo, y luego un amigo encontró ese enlace para mí)
Jibb Smart
1

Yo mismo he creado una solución para esto. Se llama JoyShockLibrary y lee desde DualShock 4, Switch Pro Controller y Joy-Cons. Es de código abierto, licencia MIT y funciona bien, aunque el soporte Bluetooth para el DS4 solo se agregó recientemente y todavía está mejorando.

Se usa en JoyShockMapper , que es una herramienta de mapeo de entrada, y JoyShockOverlay, que aún no es público, pero puede verlo en acción aquí (Gfycat) y aquí (YouTube).

JoyShockLibrary complementa muy bien XInput, además de sus informes de IMU, se ve muy similar a XInput, por lo que puede cubrir fácilmente todos los controladores de consola genéricos actuales, con el beneficio de la entrada de giroscopio y acelerómetro de aquellos que lo admiten.

Es bastante fácil de usar con Unity, aunque debería poner un archivo .cs para que sea más fácil para los demás.

Jibb Smart
fuente
0

Parece que todas son herramientas que envuelven DirectInput a XInput. Unity tiene soporte para DirectInput y, por lo tanto, debería buscar que funcione sin herramientas de terceros. La clave es si la IMU está asignada a algo en DirectInput y si ya está en un estado utilizable. De lo contrario, es posible que deba escribir su propio controlador DirectInput para manejar los datos sin procesar.

Puedes agradecer a xbox por todos estos problemas con el controlador.

usuario54892
fuente
Desafortunadamente, la IMU no parece estar asignada a ninguno de los 20 "ejes de joystick" que lee Unity, ni a Input.gyro, etc. Terminé buscando en los datos sin procesar; Se agregó una respuesta con detalles de la solución.
DMGregory