Thursday, November 21, 2013

Deadzones em controles analógicos e remoção de ruído


Encontrei um ótimo post sobre o assunto, que vai direto ao ponto e compara as abordagens existentes.
http://www.third-helix.com/2013/04/doing-thumbstick-dead-zones-right/



Deadzones

Para quem ainda não conhecem, permita-me uma simples introdução.
Deadzone é a área que deve ser ignorada por conta do ruído que existe naturalmente nos controles e sensores analógicos.  

abordagem simplista 

float deadzone = 0.25f;
Vector2 stickInput = new Vector2(Input.GetAxis(“Horizontal”), Input.GetAxis(“Vertical”));
if(Mathf.Abs(stickInput.x) < deadzone)
    stickInput.x = 0.0f;
if(Mathf.Abs(stickInput.y) < deadzone)
    stickInput.y = 0.0f;

O controle/sensor fica como se estive frouxo / falhando.
Essa é a solução natural que a maioria dá quando vê o problema pela primeira vez.

abordagem radial

float deadzone = 0.25f;
Vector2 stickInput = new Vector2(Input.GetAxis(“Horizontal”), Input.GetAxis(“Vertical”));
if(stickInput.magnitude < deadzone)
    stickInput = Vector2.zero;

Essa solução já é visivelmente melhor que a primeira,
no caso de um joystick com manche analógico (com os 2 do xbox360) somente
a área circular central  vai ser ignorada como ruído.
Só que ainda existe um problema, o ruído não existe apenas na posição central do controle/sensor.

abordagem radial escalar normalizada

float deadzone = 0.25f;
Vector2 stickInput = new Vector2(Input.GetAxis(“Horizontal”), Input.GetAxis(“Vertical”));
if(stickInput.magnitude < deadzone)
    stickInput = Vector2.zero;
else
    stickInput = stickInput.normalized * ((stickInput.magnitude - deadzone) / (1 - deadzone));

Essa solução resolve o problema que restava, da solução anterior.
O ruído é filtrado de maneira proporcional ao afastamento do centro.


Tudo isso se aplica tanto a controles (manches do xbox360), bem como, sensores (praticamente todos do drone).