Tutorial · Principiante · 17 min de lectura

Ruido de sensores, sesgo y filtrado en robótica

Comprende y limpia las señales de sensores ruidosos: ruido, sesgo y deriva, cómo elegir filtro, el retardo que introduce y cuándo aplicar fusión.

Todos los robots actúan sobre mediciones que son ruidosas, retrasadas, sesgadas y a veces ausentes. Tratar una lectura cruda como verdad es la forma más rápida de construir un robot que se comporta de forma impredecible. Esta guía cubre el vocabulario y los intercambios que necesitas antes de fiarte de un sensor. Experimenta con cada efecto en el Robot Sensor Simulator.

Ruido, sesgo y deriva son problemas distintos

  • Ruido varía aleatoriamente de una muestra a otra. Promediar o filtrar lo reduce.
  • Sesgo es un desplazamiento fijo respecto al valor verdadero. Filtrar no lo elimina; tienes que medirlo durante la calibración y restarlo.
  • Deriva es un sesgo que cambia lentamente a lo largo del tiempo, normalmente con la temperatura. Una calibración tomada al arrancar deja de coincidir con la realidad poco a poco, y por eso las pasadas largas necesitan recalibración periódica o una referencia contra la que corregir.

Confundir estos tres lleva al arreglo equivocado—más filtrado nunca cura un sesgo.

Cuatro trazas representadas frente a veinte segundos de tiempo alrededor de un valor verdadero discontinuo horizontal. Una traza ruidosa se dispersa ampliamente por encima y por debajo del valor verdadero pero promedia sobre él. Una traza con sesgo se sitúa como un desplazamiento constante por encima del valor verdadero con poca dispersión. Una traza con deriva empieza en el valor verdadero y se aleja de él de forma constante durante toda la grabación.
Tres fallos que todos parecen «una mala lectura» y necesitan tres arreglos distintos. Promediar solo cura el primero. Descargar SVG

Elegir un filtro

Tres filtros comunes cubren la mayoría de los casos:

  • Una media móvil y un paso bajo exponencial suavizan ambos el ruido aleatorio, intercambiando reactividad por suavidad mediante su ventana o su constante de tiempo.
  • Un filtro de mediana es mejor quitando picos y caídas ocasionales, porque unas pocas muestras malas no mueven el valor central.

Elige el filtro más ligero que cumpla el requisito de lo que consuma la medición—no el que produzca la gráfica de aspecto más suave.

Filtrar siempre añade retardo

Todo filtro de suavizado retrasa la señal verdadera, y más suavizado significa más retardo. Un filtro paso bajo con constante de tiempo larga rechaza más ruido pero se queda más atrás ante los cambios rápidos. Representa siempre la estimación filtrada junto a las muestras crudas y a la verdad, para que el retardo sea visible antes de meter el filtro dentro de un lazo de control, donde el retardo puede causar inestabilidad.

class LowPass:
    def __init__(self, alpha):
        self.alpha = alpha      # smaller alpha = smoother but more lag
        self.value = None
    def update(self, sample):
        if self.value is None:
            self.value = sample
        else:
            self.value += self.alpha * (sample - self.value)
        return self.value

Lo que la fusión de sensores puede y no puede hacer

La fusión combina varios sensores en una sola estimación, y solo ayuda cuando los sensores aportan información complementaria y su incertidumbre se representa honestamente. Combinar dos mediciones sesgadas no crea verdad. Un filtro complementario, por ejemplo, se fía de un sensor a altas frecuencias y de otro a bajas frecuencias; un filtro de Kalman pondera cada fuente según su incertidumbre. Pase lo que pase, empieza por la calibración, las marcas de tiempo y los marcos de coordenadas compartidos antes de fusionar nada.

Pon marca de tiempo a todo

Las muestras rara vez llegan a un intervalo perfectamente fijo, y tanto el filtrado como la fusión asumen que sabes cuándo se midió cada valor. Las marcas de tiempo te permiten detectar jitter, alinear datos de sensores distintos y descartar lecturas obsoletas. Registra los valores crudos junto a los procesados para que fallos como el recorte y las caídas sigan siendo reproducibles.

Mide tu sensor antes de filtrarlo

Elegir un filtro antes de saber cómo es el ruido es adivinar. Diez minutos de registro lo resuelven, y el procedimiento es el mismo para cualquier sensor:

  1. Sujeta el sensor perfectamente quieto contra una entrada conocida y constante.
  2. Registra unos miles de muestras crudas con marcas de tiempo.
  3. Calcula la media y la desviación típica.
  4. Representa las muestras, y representa un histograma de ellas.

Esos cuatro números y dos gráficas te dicen cuál de los tres fallos tienes:

Qué observas Qué es El arreglo
La media coincide con la verdad, los valores se dispersan simétricamente Ruido Fíltralo
La media está desplazada respecto a la verdad, la dispersión es pequeña Sesgo Mídelo y réstralo — filtrar nunca ayudará
La media se aleja a lo largo de minutos Deriva Recalibra periódicamente, o corrige contra una referencia
Mayormente ajustados, con valores salvajes ocasionales Valores atípicos Mediana, no una media
Los valores caen en escalones discretos Cuantificación Lo esperable; acota tu resolución

El histograma es la parte que la gente se salta, y es la más informativa. El ruido gaussiano hace una campana; los valores atípicos hacen una campana con unos pocos puntos muy lejos en las colas. Esos dos necesitan filtros distintos, y ninguna cantidad de mirar fijamente una gráfica de serie temporal los distingue con la misma claridad.

Elegir un filtro, cuantificado

Filtro Mata ruido gaussiano Mata valores atípicos Retardo Coste
Media móvil, N muestras Sí — por √N No — difumina un pico sobre N muestras (N−1)/2 muestras Buffer de N muestras
Paso bajo exponencial (EMA) Sí No ≈ (1−α)/α muestras Un float
Mediana de N En parte Completamente, hasta N/2 atípicos (N−1)/2 muestras Ordenar, trivial con N pequeña
Mediana y luego EMA Sí Sí Ambos Ambos

El √N de la primera fila es el número útil: promediar 4 muestras reduce el ruido a la mitad; promediar 100 muestras lo reduce a la décima parte, al precio de 50 muestras de retardo. La reducción de ruido tiene rendimientos decrecientes muy marcados y el retardo no, y por eso las medias muy largas casi siempre son la respuesta equivocada.

Para un EMA, la constante de tiempo se relaciona con α así:

tau = dt x (1 - alpha) / alpha

Así que en un bucle de 10 ms, α = 0.1 da una constante de tiempo de 90 ms. Ajustar α a ojo es como la gente acaba con filtros mucho más lentos de lo que cree — calcúlalo una vez y sabrás lo que tienes.

El retardo no es gratis, y aquí está lo que cuesta

Todo filtro de suavizado retrasa la señal, y dentro de un lazo de control ese retardo es indistinguible de que la planta responda más despacio. Reduce directamente cuánta ganancia el lazo puede tolerar antes de oscilar.

Filtro Retardo en un bucle de 10 ms Distancia recorrida a 0,3 m/s
Mediana de 3 10 ms 3 mm
Mediana de 5 20 ms 6 mm
Media móvil de 10 45 ms 14 mm
EMA, α = 0.1 90 ms 27 mm
EMA, α = 0.02 490 ms 147 mm

Esa última fila merece que te detengas a mirarla. Un α de 0.02 produce una gráfica preciosamente suave y medio segundo de retardo — el robot está guiándose por donde estaba el obstáculo hace 15 cm. Esta es la forma más habitual de que un filtro bienintencionado empeore un robot, y es invisible salvo que representes filtrado contra crudo con la verdad al lado.

Elige el filtro más ligero que cumpla el requisito, y comprueba siempre cuánto cuesta el retardo en las unidades que le importan al robot — milímetros, o grados, no muestras.

Un filtro complementario, y cómo elegir su constante

El filtro complementario es el caballo de batalla de la robótica de hobby porque son tres líneas y resuelve el problema real: dos sensores que fallan de maneras opuestas.

// gyroRate in deg/s, accelAngle in degrees, dt in seconds.
angle = alpha * (angle + gyroRate * dt) + (1.0f - alpha) * accelAngle;

alpha fija la frecuencia de cruce — por encima te fías del giroscopio, por debajo del acelerómetro:

tau = alpha x dt / (1 - alpha)          # the filter's time constant, seconds
f_crossover = 1 / (2 x pi x tau)        # Hz
α con dt = 5 ms Constante de tiempo Cruce Comportamiento
0.90 45 ms 3.5 Hz Muy reactivo, visiblemente ruidoso por el acelerómetro
0.98 245 ms 0.65 Hz El valor por defecto habitual — buen equilibrio
0.995 1.0 s 0.16 Hz Muy suave, deriva de forma perceptible antes de corregir
0.999 5.0 s 0.03 Hz En la práctica solo giroscopio durante cualquier maniobra corta

Elígelo a partir de la física y no a ojo: la constante de tiempo debería ser larga comparada con las perturbaciones que quieres rechazar, y corta comparada con la tasa de deriva del giroscopio. Un giroscopio con un sesgo de 1 °/s alcanza 1° de error en un segundo, así que una constante de tiempo de varios segundos deja acumularse error real antes de que el acelerómetro lo corrija.

Fíjate también en que α depende de dt. Copiar un α de un proyecto con otra tasa de bucle te da un filtro distinto — una fuente común e invisible de «estas ganancias no me funcionan».

Lo que la fusión no puede hacer

La fusión no es magia, y hay tres límites que merece la pena enunciar sin rodeos:

No puede quitar un sesgo compartido. Dos acelerómetros que ambos leen 2° alto producen una estimación fusionada que lee 2° alto. La fusión explota errores independientes; un error en modo común sobrevive intacto.

No puede crear información que no está. Ninguna cantidad de filtrado le da a una IMU de seis ejes un rumbo absoluto. El guiñada no tiene referencia de gravedad, así que deriva, y solo un magnetómetro o una referencia externa lo arregla.

No puede arreglar marcas de tiempo malas. Fusionar un fix de GPS de 10 Hz con un giroscopio de 200 Hz exige saber cuándo se midió cada uno, con una fracción del intervalo más rápido. Un fix con 100 ms de antigüedad tratado como actual corromperá activamente una estimación que el giroscopio solo tenía bien.

Marcas de tiempo, en concreto

«Pon marca de tiempo a todo» es fácil de—asentir y fácil de saltarse. La versión práctica:

struct Sample {
  float value;
  unsigned long micros;    // when it was MEASURED, not when it was read
};

// Reject anything too old to be useful, rather than fusing it.
bool isFresh(const Sample &s, unsigned long maxAgeUs) {
  return (micros() - s.micros) < maxAgeUs;
}

Captura la marca de tiempo tan cerca de la medida como puedas — dentro de la interrupción, no después del procesado. Una frase de GPS analizada 80 ms después de tomar el fix y marcada con la hora del análisis tiene 80 ms de error, y nada de lo que viene después puede recuperar eso.

Resolución de problemas

Síntoma Causa probable Solución
Más filtrado, ninguna mejora Es sesgo, no ruido Mide el desplazamiento en reposo y réstralo
La estimación se aleja poco a poco Deriva Recalibración periódica, o una referencia absoluta
Un pico puntual sobrevive al filtro Estás usando una media La mediana rechaza atípicos; una media los difumina
El lazo de control oscila tras añadir un filtro El retardo redujo la ganancia estable Filtro más ligero, o reajusta
Gráfica suave, el robot reacciona tarde Constante de tiempo mucho más larga de lo previsto Calcula τ a partir de α — no ajustes α a ojo
La estimación fusionada es peor que cualquiera de los sensores Marcas de tiempo obsoletas, o un sesgo compartido Marca el tiempo en la medida; comprueba los desplazamientos de ambos sensores
El filtro funciona en el banco, no en el robot La vibración es una señal real, no ruido Monta el sensor con goma; el filtro no puede distinguirlas
El filtro complementario se comporta distinto que en un tutorial α depende de dt Calcula α para tu tasa de bucle

Pruébalo tú mismo

En el Robot Sensor Simulator puedes ajustar ruido, sesgo, deriva y caídas, y luego comparar los datos crudos con las estimaciones de paso bajo, media móvil y mediana. Es la forma más rápida de sentir el intercambio entre ruido y retardo—el mismo intercambio que decide cómo reacciona un robot en el Obstacle Avoidance Simulator.

Explora el grafo

Forma parte de estos montajes

Proyectos y rutas de aprendizaje que incluyen este tutorial.

Lecturas adicionales

Referencias