web-dev-qa-db-fra.com

Comment puis-je obtenir la direction du mouvement avec l'aide d'un accéléromètre?

Je développe une application Android et j'aimerais savoir s'il est possible de détecter la direction du mouvement avec un axe fixe. Par exemple, je veux poser mon téléphone sur la table et détecter la direction quand je le déplace (à gauche, à droite, en haut et en bas). La distance n'est pas nécessaire, je veux juste connaître la direction exacte.

15
Marcos Passos

Oui.

À l'aide de SensorEventListener.onSensorChanged(SensorEvent event), vous pouvez déterminer les valeurs fournies le long des axes X et Y. Vous devrez enregistrer ces valeurs, puis les comparer aux nouvelles valeurs que vous recevrez lors d'appels ultérieurs à la méthode onSensorChanged pour obtenir une valeur delta. Si la valeur delta sur un axe est positive, l'appareil se déplace dans un sens, si sa valeur négative est dans l'autre sens.

Vous devrez probablement ajuster à la fois la vitesse à laquelle vous recevez les événements de l'accéléromètre et le seuil auquel vous considérez une valeur delta pour indiquer un changement de direction.

Voici un exemple de code rapide de ce dont je parle:

public class AccelerometerExample extends Activity implements SensorEventListener {
    TextView textView;
    StringBuilder builder = new StringBuilder();

    float [] history = new float[2];
    String [] direction = {"NONE","NONE"};

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        textView = new TextView(this);
        setContentView(textView);

        SensorManager manager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        Sensor accelerometer = manager.getSensorList(Sensor.TYPE_ACCELEROMETER).get(0);
        manager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_GAME);
    }

    @Override
    public void onSensorChanged(SensorEvent event) {

        float xChange = history[0] - event.values[0];
        float yChange = history[1] - event.values[1];

        history[0] = event.values[0];
        history[1] = event.values[1];

        if (xChange > 2){
          direction[0] = "LEFT";
        }
        else if (xChange < -2){
          direction[0] = "RIGHT";
        }

        if (yChange > 2){
          direction[1] = "DOWN";
        }
        else if (yChange < -2){
          direction[1] = "UP";
        }

        builder.setLength(0);
        builder.append("x: ");
        builder.append(direction[0]);
        builder.append(" y: ");
        builder.append(direction[1]);

        textView.setText(builder.toString());
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // nothing to do here
    }
}

Ce code ne vous indiquera que la direction générale des axes X et Y dans lesquels le téléphone a été déplacé. Pour permettre une détermination plus précise de la direction (par exemple, pour tenter de reproduire le mouvement d’une souris d’ordinateur), vous constaterez peut-être qu’une L'accéléromètre du téléphone n'est pas adapté.

Pour tenter cela, je voudrais d’abord régler le délai du capteur sur SensorManager.SENSOR_DELAY_FAST et créer une liste de plusieurs événements d’historique afin de pouvoir détecter un mouvement dans le temps et ne pas être influencé par de légers mouvements dans la direction opposée qui se produisent souvent lors de la prise de mesures par l’accéléromètre. bon niveau. Vous devrez également mesurer le temps écoulé pour vous aider à calculer la mesure exacte du mouvement, comme suggéré dans vos commentaires.

23
Louth

D'après ce que j'ai lu, avec les capteurs, on ne peut détecter que les accélérations et l'orientation du téléphone. Ainsi, vous pouvez facilement détecter le début du mouvement (et dans quelle direction) ainsi que l’arrêt du mouvement, car la vitesse change, ce qui entraîne une accélération (lorsque l’accélération est arrêtée dans le sens opposé à la vitesse).

Si le téléphone se déplace à une vitesse constante, les accéléromètres donneront des valeurs nulles (accélération linéaire qui soustrait la gravité). Donc, pour savoir si le téléphone est en mouvement, vous devez calculer la vitesse à chaque instant, par

V(t)=V(t0)+a*dt

dans lequel:

  • V(t0) est la vitesse connue à l’instant précédent,
  • V(t) est la vitesse à l'instant courant,
  • a est l'accélération (considérons l'accélération de l'instant précédent ou l'accélération moyenne entre l'instant précédent et l'instant actuel).

Le problème est qu’en raison de l’incertitude des valeurs du capteur, vous pouvez éventuellement additionner de petites erreurs à chaque instant, ce qui entraînera des valeurs de vitesse erronées. Vous devrez probablement ajuster un filtre passe-bas aux valeurs.

0
renatogsousa