studio para orientacion giroscopio developer aplicaciones acelerometro android accelerometer

orientacion - aplicaciones de acelerometro para android



Filtrado del ruido de los datos del acelerĂ³metro. (5)

¿Cómo puedo filtrar 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 los componentes de baja frecuencia y centrarme 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 integro o uso 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? ¿Existe alguna posibilidad de que esto se pueda hacer en tiempo real?

Cualquier idea será muy apreciada. ¡Gracias!


Aquí está el código para Android, adaptado del ejemplo del filtro de paso alto adaptable de Apple. Simplemente enchufa esto e implementa 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]); }


En mi opinión, diseñar un filtro de Kalman como su primer intento es complicar en exceso lo que probablemente sea un problema bastante simple. Comenzaría con un filtro FIR simple, y solo probaría algo más complejo cuando / si lo probó y encontró con una certeza razonable que no puede proporcionar lo que desea. Sin embargo, creo que podrá hacer todo lo que necesite y hacerlo de manera mucho más fácil y eficiente.


Las muestras del SDK de Apple implementan realmente el filtrado de una manera aún más simple que es mediante el uso de rampas:

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


Me parece recordar que esto se hizo en el código de muestra de Apple para el iPhone. Veamos...

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

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