2009-10-28 16 views
23

Come filtro il rumore dei dati dell'accelerometro in Android? Vorrei creare un filtro passa-alto per i miei dati di esempio in modo da eliminare i componenti a bassa frequenza e concentrarmi sui componenti ad alta frequenza. Ho letto che il filtro Kalman potrebbe essere il miglior candidato per questo, ma come faccio ad integrare o utilizzare questo metodo nella mia applicazione che sarà scritto principalmente in Android Java? o può essere fatto in primo luogo? o tramite Android NDK? È per caso che ciò può essere fatto in tempo reale?Filtro rumore accelerometro

Qualsiasi idea sarà molto apprezzata. Grazie!

risposta

24

I campioni di SDK di Apple attuino effettivamente il filtraggio in modo ancora più semplice che utilizzando rampa:

 
//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

Non sono sicuro di seguire ciò che sta accadendo qui ... se l'accelerazione.x è costante (in teoria ciò può accadere), che result.x = 0; accel [0] assomiglia all'output filtrato; non sono sicuro di quale risultato sia. – Pandrei

1

Mi sembra di ricordare questo viene fatto nel codice di esempio di Apple per l'iPhone. Vediamo ...

Cercare AccelerometerFilter.h/.m su Google (o afferrare campione AccelerometerGraph di Apple) e questo link: http://en.wikipedia.org/wiki/High-pass_filter (che è quello che il codice di Apple si basa su).

C'è qualche pseudo-codice nel Wiki, anche. Ma la matematica è abbastanza semplice da tradurre in codice.

0

IMO, progettare un filtro Kalman come primo tentativo è complicare eccessivamente quello che probabilmente è un problema abbastanza semplice. Vorrei iniziare con un semplice filtro FIR, e provare solo qualcosa di più complesso quando/se lo hai testato e trovato con ragionevole certezza che non può fornire quello che vuoi. La mia ipotesi, tuttavia, è che sarà in grado di fare tutto il necessario e farlo molto più facilmente ed efficacemente.

+0

Io attualmente sto esplorare diversi meccanismi di filtraggio. Quali sono i vantaggi del filtro FIR rispetto alla risposta sopra accettata? – Nazerke

+0

@Nazerke: Sembra che la risposta accettata * sia * un (molto semplice) filtro FIR. Più poli nel filtro ti daranno più controllo sulla velocità con cui il filtro si spegne, e soprattutto la possibilità di avere un roll-off più veloce (se lo vuoi). –

+0

@JerryCoffin La risposta accettata è una semplice IIR ed è anche un KF molto semplice. –

12

Ecco il codice per Android, adattato dall'esempio filtro passa alto mela adattativo. Basta collegare questo e implementare 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

Cosa dovrebbero fare norm() e clamp()? –

+0

Direi che "norm" risponde al calcolo della norma del vettore dato (sqrt ([0]^2 + [1]^2'[2]^2)) e clamp è una funzione limitante con un limite superiore e inferiore (in questo caso, il primo argomento è limitato tra 0.0f e 1.0f). Inoltre, grazie mille per l'esempio adattativo, penso di averne una qualche forma. – ravemir

+0

norma? non è lì in Android SDK –

Problemi correlati