2009-10-28 16 views
23

¿Cómo se filtra el ruido de los datos del acelerómetro en Android? Me gustaría crear un filtro de paso alto para mis datos de muestra para poder eliminar componentes de baja frecuencia y enfocarme en los componentes de alta frecuencia. He leído que el filtro de Kalman podría ser el mejor candidato para esto, pero ¿cómo puedo integrar o usar este método en mi aplicación, que en su mayoría está escrito en Android Java? o se puede hacer en primer lugar? o a través de Android NDK? ¿Hay alguna posibilidad de que esto se pueda hacer en tiempo real?Filtro de datos del acelerómetro ruido

Cualquier idea será muy apreciada. ¡Gracias!

Respuesta

24

Las muestras de SDK de Apple en realidad implementar el filtrado de una manera aún más simple que es mediante el uso de 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

No estoy seguro de seguir lo que está sucediendo aquí ... si acceleration.x es constante (en teoría esto puede suceder), que result.x = 0; accel [0] se parece a la salida filtrada; no estoy seguro de qué result.x es – Pandrei

1

Parece que recuerdo esto hecho en el código de muestra de Apple para el iPhone. Vamos a ver ...

Busque AccelerometerFilter.h/.m en Google (o tomar muestras AccelerometerGraph de Apple) y este enlace: http://en.wikipedia.org/wiki/High-pass_filter (eso es lo que el código de Apple se basa en).

También hay un pseudocódigo en la Wiki. Pero la matemática es bastante simple de traducir al código.

0

IMO, el diseño de un filtro de Kalman como primer intento es una complicación excesiva de lo que probablemente sea un problema bastante simple. Comenzaría con un filtro FIR simple, y solo intentaré algo más complejo cuando/si lo haya probado y haya encontrado con razonable certeza que no puede proporcionar lo que desea. Mi suposición, sin embargo, es que podrá hacer todo lo que necesite y hacerlo de manera mucho más fácil y eficiente.

+0

estoy actualmente explorando diferentes mecanismos de filtrado. ¿Cuáles son las ventajas del filtro FIR en comparación con la respuesta aceptada anteriormente? – Nazerke

+0

@Nazerke: Parece que la respuesta aceptada * es * un filtro FIR (realmente simple). Más polos en el filtro le darán más control sobre la velocidad a la que se filtra el filtro, y especialmente la capacidad de tener un rodaje más rápido (si lo desea). –

+0

@JerryCoffin La respuesta aceptada es un IIR simple, y también es un KF muy simple. –

12

Aquí está el código para Android, adaptado del ejemplo filtro de paso alto de adaptación de manzana. Sólo tiene que enchufar esto en e implementar 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

¿Qué deberían hacer la norma() y la abrazadera()? –

+0

Diría que 'norma' se refiere al cálculo de la norma del vector dado (sqrt ([0]^2 + [1]^2'[2]^2)) y la pinza es una función limitante con un límite superior e inferior (en este caso, la primera arg está limitada entre 0.0f y 1.0f). Además, muchas gracias por el ejemplo de adaptación, creo que voy a ir de alguna forma. – ravemir

+0

norma? no está en android sdk –

Cuestiones relacionadas