Acesso ao sensor de movimento DualShock 4 no Windows (idealmente Unity)

10

Estou tentando usar o IMU de um DualShock 4 como um controlador de movimento no Unity, no Windows 7.

Até agora eu tentei:

  • DS4Windows (1.5.11): lê dados do sensor de movimento, mas não os expõe ao Unity como eixos, a menos que eu os mapeie para os manípulos esquerdo e direito. Isso não é suficiente, já que eu perco o uso das varas, posso caber apenas 4 dos 6 canais de dados, e os valores recebidos são cortados em um intervalo estreito.
  • Motioninjoy (0.7.1001): não parece detectar o DS4 como um controlador (os documentos mais recentes referem-se apenas ao DS3 e anteriores)
  • GlovePIE (0,43): depois de seguir as instruções de uso do DualShock 3 com LibUSB-Win32 (possibilidade remota), as propriedades do SixAxis ficam em branco.

No passado, eu usei programas externos como o GlovePIE para capturar dados do sensor de movimento remoto do Wii e passá-lo para o Unity por meio de mensagens OSC , então eu estaria aberto a uma abordagem como essa se não conseguir que o Unity leia os sensores do controlador diretamente através de seu sistema de entrada .

Alguém teve sorte com isso?

DMGregory
fonte

Respostas:

8

Eu encontrei uma abordagem viável. Peguei a fonte do DS4Tool e copiei os bits necessários no meu projeto do Unity para poder ler os relatórios diretamente do dispositivo.

(Essa é a classe NativeMethods para fazer interface com o Kernel32.dll, a enumeração de dispositivos do HidDevices e ler o relatório da classe HidDevice . Recortei o restante para manter as coisas o mais simples possível - eu acabei de pesquisar um novo tópico dados o mais rápido possível.)

Este guia me disse onde encontrar os dados do sensor de movimento no relatório de 64 bytes. Um pouco de teste empírico e parece que isso coloca os dados em gs e radianos / s:

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;

É um sistema de coordenadas destro com x + direita, y + para cima e z + apontando em direção ao jogador.

A busca por dados dessa maneira não interfere no InputManager da Unity, que ainda apanha os botões e paus como esperado, sem a necessidade de baixar drivers não padrão ou executar software extra em segundo plano.


Atualização: Sem fio (Bluetooth)

Encontrei dois problemas para estender isso para funcionar sem fio (e duas soluções):

  1. O DualShock 4s não gosta de ficar emparelhado com o Windows (antes do Windows 8). Esse procedimento bobo parece solucionar esse problema no Windows 7.

  2. Não há dados do sensor de movimento quando conectado via Bluetooth . Descobri que você precisa escrever um relatório de saída no dispositivo (consulte HidDevice para o método e DS4Device para os números mágicos) para convencê-lo a enviar dados de movimento. Feito isso, os relatórios de entrada que você recebe serão deslocados em 2 bytes.

DMGregory
fonte
É possível que você esclareça esta resposta por este post ?
Estou viajando agora, mas assumirei isso quando tiver algum tempo de inatividade com wifi. Obrigado @JoshPetrie!
DMGregory
Analisando isso, não tenho mais o código-fonte do projeto de detecção de movimento em que estava trabalhando e, voltando ao DS4Tool, lembrei-me por que arranquei apenas os bits necessários! Isso fica super detalhado e pode ir além de um comprimento razoável para uma resposta do StackExchange. Vou tentar simplificar o máximo que puder, mas levará algum tempo.
DMGregory
1
@DMGregory - Acho que esta ficha técnica é para o IMU que o DualShock 4 usa: mouser.com/ds/2/783/BST-BMI055-DS000-08-786482.pdf - e diz Short.MaxValue corresponde a 2000 graus por segundo. Pelo meu cálculo, você está obtendo cerca de 1833 graus por segundo, o que é próximo (e razoável para o resultado do teste), mas talvez o ajuste do seu cálculo adequadamente lhe dê um pouco mais de precisão?
Jibb Inteligente
(Eu estou fazendo coisas giroscópio me agora, e estava indo para tentar descobrir as conversões de unidades padrão, testando-me, em seguida, um amigo encontrou que apontam para mim)
Jibb Inteligente
1

Eu mesmo criei uma solução para isso. Chama-se JoyShockLibrary e lê DualShock 4, Switch Pro Controller e Joy-Cons. É de código aberto, licença MIT e funciona bem, embora o suporte ao Bluetooth para o DS4 tenha sido adicionado apenas recentemente e ainda esteja melhorando.

É usado no JoyShockMapper , que é uma ferramenta de mapeamento de entrada, e no JoyShockOverlay, que ainda não é público, mas você pode vê-lo em ação aqui (Gfycat) e aqui (YouTube).

O JoyShockLibrary complementa muito bem o XInput - além de seus relatórios IMU, é muito semelhante ao XInput - para que você possa cobrir todos os controladores atuais de console gen facilmente, com o benefício da entrada de giroscópio e acelerômetro daqueles que o suportam.

É muito fácil de usar com o Unity, embora eu deva colocar um arquivo .cs para facilitar para outros.

Jibb Smart
fonte
0

Todas parecem ferramentas que envolvem o DirectInput no XInput. O Unity tem suporte para DirectInput e, portanto, você deve procurar fazê-lo funcionar sem ferramentas de terceiros. A chave é se o IMU está mapeado para qualquer coisa no DirectInput e se já está em um estado utilizável. Caso contrário, talvez seja necessário gravar seu próprio manipulador DirectInput para lidar com os dados brutos.

Você pode agradecer ao xbox por todos esses problemas de controle.

user54892
fonte
Infelizmente, o IMU não parece estar mapeado para nenhum dos 20 "eixos do joystick" que o Unity lê, nem para o Input.gyro etc. Acabei pesquisando os dados brutos; adicionou uma resposta com detalhes da solução.
DMGregory