2009-10-28 4 views
23

Wie filtere ich das Rauschen der Beschleunigungsmesserdaten in Android? Ich würde gerne einen Hochpassfilter für meine Beispieldaten erstellen, damit ich niederfrequente Komponenten eliminieren und mich auf die hochfrequenten Komponenten konzentrieren kann. Ich habe gelesen, dass der Kalman-Filter der beste Kandidat hierfür sein könnte, aber wie kann ich diese Methode in meine Anwendung, die hauptsächlich in Android Java geschrieben ist, integrieren oder verwenden? oder kann es überhaupt gemacht werden? oder über Android NDK? Gibt es einen Zufall, dass dies in Echtzeit möglich ist?Filtern von Beschleunigungsmesserdaten Rauschen

Jede Idee wird sehr geschätzt. Vielen Dank!

Antwort

24

Die Proben aus Apples SDK tatsächlich die Filterung in einer noch einfacheren Art und Weise implementieren, die unter Verwendung Ramping ist:

 
//ramp-speed - play with this value until satisfied 
const float kFilteringFactor = 0.1f; 

//last result storage - keep definition outside of this function, eg. in wrapping object 
float accel[3]; 

//acceleration.x,.y,.z is the input from the sensor 

//result.x,.y,.z is the filtered result 

//high-pass filter to eliminate gravity 
accel[0] = acceleration.x * kFilteringFactor + accel[0] * (1.0f - kFilteringFactor); 
accel[1] = acceleration.y * kFilteringFactor + accel[1] * (1.0f - kFilteringFactor); 
accel[2] = acceleration.z * kFilteringFactor + accel[2] * (1.0f - kFilteringFactor); 
result.x = acceleration.x - accel[0]; 
result.y = acceleration.y - accel[1]; 
result.z = acceleration.z - accel[2]; 
+1

Ich bin mir nicht sicher, ob ich folge, was hier passiert ... wenn acceleration.x konstant ist (theoretisch kann das passieren), dann result.x = 0; accel [0] sieht aus wie die gefilterte Ausgabe; nicht sicher, was result.x ist. – Pandrei

1

Ich erinnere mich, dass dies in Apples Beispielcode für das iPhone getan wird. Mal sehen ...

Suchen Sie nach AccelerometerFilter.h/.m auf Google (oder greifen Apple AccelerometerGraph Probe) und auf diesen Link: http://en.wikipedia.org/wiki/High-pass_filter (das ist, was Code von Apple basiert auf).

Auch im Wiki gibt es Pseudo-Code. Aber die Mathematik ist ziemlich einfach in Code zu übersetzen.

0

IMO, das Entwerfen eines Kalman-Filters als Ihr erster Versuch ist es, das wahrscheinlich ein ziemlich einfaches Problem zu komplizieren. Ich würde mit einem einfachen FIR-Filter beginnen und nur etwas Komplexeres versuchen, wenn Sie das getestet haben und mit einiger Sicherheit feststellen, dass es nicht das liefern kann, was Sie wollen. Ich schätze jedoch, dass es in der Lage sein wird, alles zu tun, was Sie brauchen, und dies viel einfacher und effizienter.

+0

Ich bin zur Zeit Erforschung verschiedener Filtermechanismen. Was sind die Vorteile von FIR-Filter im Vergleich mit der oben angenommenen Antwort? – Nazerke

+0

@Nazerke: Es sieht aus wie die angenommene Antwort * ist * ein (wirklich einfacher) FIR-Filter. Mehr Pole im Filter geben Ihnen mehr Kontrolle über die Geschwindigkeit, mit der der Filter abrollt, und vor allem die Fähigkeit, schneller abzurollen (wenn Sie es wünschen). –

+0

@JerryCoffin Die akzeptierte Antwort ist eine einfache IIR und ist auch eine sehr einfache KF. –

12

Hier ist der Code für Android, von dem adaptiven Beispiel Hochpassfilter Apfel angepasst. Plug diese einfach an und implementieren onFilteredAccelerometerChanged()

private static final boolean ADAPTIVE_ACCEL_FILTER = true; 
float lastAccel[] = new float[3]; 
float accelFilter[] = new float[3]; 

public void onAccelerometerChanged(float accelX, float accelY, float accelZ) { 
    // high pass filter 
    float updateFreq = 30; // match this to your update speed 
    float cutOffFreq = 0.9f; 
    float RC = 1.0f/cutOffFreq; 
    float dt = 1.0f/updateFreq; 
    float filterConstant = RC/(dt + RC); 
    float alpha = filterConstant; 
    float kAccelerometerMinStep = 0.033f; 
    float kAccelerometerNoiseAttenuation = 3.0f; 

    if(ADAPTIVE_ACCEL_FILTER) 
    { 
     float d = clamp(Math.abs(norm(accelFilter[0], accelFilter[1], accelFilter[2]) - norm(accelX, accelY, accelZ))/kAccelerometerMinStep - 1.0f, 0.0f, 1.0f); 
     alpha = d * filterConstant/kAccelerometerNoiseAttenuation + (1.0f - d) * filterConstant; 
    } 

    accelFilter[0] = (float) (alpha * (accelFilter[0] + accelX - lastAccel[0])); 
    accelFilter[1] = (float) (alpha * (accelFilter[1] + accelY - lastAccel[1])); 
    accelFilter[2] = (float) (alpha * (accelFilter[2] + accelZ - lastAccel[2])); 

    lastAccel[0] = accelX; 
    lastAccel[1] = accelY; 
    lastAccel[2] = accelZ; 
    onFilteredAccelerometerChanged(accelFilter[0], accelFilter[1], accelFilter[2]); 
} 
+4

Was sollte norm() und clamp() tun? –

+0

Ich würde sagen "Norm" bezieht sich auf die Berechnung der Norm des gegebenen Vektors (sqrt ([0]^2 + [1]^2 '[2]^2)) und Klemme ist eine begrenzende Funktion mit einer oberen und unteren Grenze (In diesem Fall ist der erste Arg zwischen 0,0f und 1,0f begrenzt). Auch, vielen Dank für das adaptive Beispiel, ich denke, ich gehe eine Form davon. – ravemir

+0

Norm? es ist nicht da in android sdk –