Frage

Im Erstellen einer Anwendung, wo ich brauche einen Image je nach Ausrichtung des Geräts zu positionieren. Ich verwende die Werte aus einem Magnetfeld und Beschleunigungs-Sensoren, um das Gerät mit Orientierung

zu berechnen
SensorManager.getRotationMatrix(rotationMatrix, null, accelerometerValues, magneticFieldValues)
SensorManager.getOrientation(rotationMatrix, values);
double degrees = Math.toDegrees(values[0]);

Mein Problem ist, dass die Positionierung des Image auf Veränderungen in der Orientierung sehr empfindlich ist. Making the Imageview springen ständig den Bildschirm um. (Weil die Grade ändern)

Ich habe gelesen, dass dies sein kann, weil mein Gerät in der Nähe Dinge, die die Magnetfeldmesswerte beeinflussen können. Aber dies ist nicht der einzige Grund, warum es scheint.

Ich habe versucht, einige Anwendungen herunterzuladen und festgestellt, dass die „ 3D-Kompass “und " Compass " extrem stabil bleibt in seinen Lesungen (wenn das Rauschfilter auf Einstellung), würde ich das gleiche Verhalten in meiner Anwendung möge.

Ich habe gelesen, dass ich das „Rauschen“ meiner Lesungen können zwicken durch Hinzufügen eines „ Tiefpassfilter “, aber ich habe keine Ahnung, wie dies zu implementieren (wegen meiner fehlenden Math).

Im Hoffnung, jemand kann mir helfen, eine konstante Anzeige auf dem Gerät zu schaffen, wo eine wenig Bewegung auf das Gerät die aktuelle Orientierung beeinflussen würde nicht. Gerade jetzt ich habe eine kleine

if (Math.abs(lastReadingDegrees - newReadingDegrees) > 1) { updatePosition() }

Um Filter abit des Lärms. Aber es ist nicht sehr gut funktioniert:)

War es hilfreich?

Lösung

Obwohl benutzte ich havn't den Kompass auf Android, die grundlegende Verarbeitung gezeigt unten (in JavaScript) wird wahrscheinlich für Sie arbeiten.

Es basiert auf dem Tiefpassfilter auf dem Beschleunigungssensor, der durch die Windows Phone Team mit Änderungen einen Kompass (alle 360 ??das zyklische Verhalten anzupassen".

)

Ich nehme an der Kompassmessung in Grad, ein Schwimmer zwischen 0-360, und die Ausgabe sollte ähnlich sein.

Sie mögen 2 Dinge im Filter erreichen:

  1. Wenn die Änderung klein ist, gitter zu verhindern, drehen Sie allmählich zu dieser Richtung.
  2. Wenn die Änderung groß ist, Verzögerung zu vermeiden, schalten Sie zu dieser Richtung sofort (und es kann aufgehoben werden, wenn Sie den Kompass wollen in eine glatte Art und Weise nur bewegen).

, dass wir zwei Konstanten haben:

  1. Die Lockerung Schwimmer, die definiert, wie die Bewegung glatt sein wird (1 keine Glättung ist und 0 ist nie zu aktualisieren, meine Standard-0,5). Wir werden es SmoothFactorCompass nennen.
  2. Die Schwelle, bei denen der Abstand groß genug ist, sofort zu drehen (0 ist immer springen, 360 nie springt, mein Standard ist 30). Wir werden es SmoothThresholdCompass nennen.

Wir haben eine Variable für die Anrufe gespeichert, einen Schwimmer genannt oldCompass und es ist das Ergebnis des Algorithmus.

So wird die Variable defenition ist:

var SmoothFactorCompass = 0.5;
var SmoothThresholdCompass = 30.0;
var oldCompass = 0.0;

und die Funktion recieves NewCompass und gibt oldCompass als das Ergebnis.

if (Math.abs(newCompass - oldCompass) < 180) {
    if (Math.abs(newCompass - oldCompass) > SmoothThresholdCompass) {
        oldCompass = newCompass;
    }
    else {
        oldCompass = oldCompass + SmoothFactorCompass * (newCompass - oldCompass);
    }
}
else {
    if (360.0 - Math.abs(newCompass - oldCompass) > SmoothThresholdCompass) {
        oldCompass = newCompass;
    }
    else {
        if (oldCompass > newCompass) {
            oldCompass = (oldCompass + SmoothFactorCompass * ((360 + newCompass - oldCompass) % 360) + 360) % 360;
        } 
        else {
            oldCompass = (oldCompass - SmoothFactorCompass * ((360 - newCompass + oldCompass) % 360) + 360) % 360;
        }
    }
}

Ich sehe, dass die Frage vor 5 Monaten geöffnet wurde und wahrscheinlich nicht mehr relevant, aber ich bin sicher, dass andere Programmierer es nützlich finden könnten.

Oded Elyada.

Andere Tipps

Dieses Tiefpaßfilter arbeitet für Winkel in Radiant. Verwenden Sie die hinzufügen Funktion für jeden Kompass lesen, dann rufen Sie Durchschnitt bekommen den Durchschnitt.

public class AngleLowpassFilter {

    private final int LENGTH = 10;

    private float sumSin, sumCos;

    private ArrayDeque<Float> queue = new ArrayDeque<Float>();

    public void add(float radians){

        sumSin += (float) Math.sin(radians);

        sumCos += (float) Math.cos(radians);

        queue.add(radians);

        if(queue.size() > LENGTH){

            float old = queue.poll();

            sumSin -= Math.sin(old);

            sumCos -= Math.cos(old);
        }
    }

    public float average(){

        int size = queue.size();

        return (float) Math.atan2(sumSin / size, sumCos / size);
    }
}

Mit Math.toDegrees() oder Math.toRadians() konvertieren.

Beachten Sie, dass zum Beispiel der Durchschnitt von 350 und 10 nicht 180. Meine Lösung:

int difference = 0;
for(int i= 1;i <numberOfAngles;i++){
    difference += ( (angles[i]- angles[0] + 180 + 360 ) % 360 ) - 180;
}
averageAngle = (360 + angles[0] + ( difference / numberOfAngles ) ) % 360;

Ein Tiefpassfilter (LPF) -Blöcke schnell ändernden Signalen und
erlaubt nur langsame Veränderungen in den Signalen. Das bedeutet, jede kleine
plötzliche Änderungen ignoriert.

Der Standard-Weg, dies in Software zu implementieren ist ein gleitenden Mittelwert
nehmen die letzten N Proben und berichtet, dass Wert. Beginnen Sie mit N so klein wie 3 und
halte zunehmenden N bis Sie ausreichend geglättet Antwort in Ihrer Anwendung finden.

Do beachten Sie, dass je höher man machen N, langsamer die Reaktion des Systems.

Sehen Sie meine Antwort auf diese Frage im Zusammenhang: Glättung Daten von einem Sensor

Ein Software-Tiefpassfilter ist im Grunde eine modifizierte Version davon. Tatsächlich habe ich in dieser Antwort auch auf diesen Link auf eine andere Frage im Zusammenhang zur Verfügung gestellt: Tiefpassfilter-Software

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top