Tutorial · Beginner · 17 min lezen

Sensorruis, bias en filtering in de robotica

Maak ruisvolle robotsensoren begrijpelijk: ruis, bias en drift, hoe je een filter kiest, welke vertraging filtering geeft en wanneer fusie helpt.

Elke robot werkt op metingen die ruis bevatten, vertraagd zijn, een bias hebben en soms ontbreken. Een ruwe meting als waarheid behandelen is de snelste manier om een robot te bouwen die zich onvoorspelbaar gedraagt. Deze gids behandelt de woordenschat en de afwegingen die je nodig hebt voordat je een sensor vertrouwt. Experimenteer met elk effect in de Robot Sensor Simulator.

Ruis, bias en drift zijn verschillende problemen

  • Ruis varieert willekeurig van monster tot monster. Gemiddelen of filteren vermindert het.
  • Bias is een vaste afwijking van de werkelijke waarde. Filtering verwijdert hem niet; je moet hem bij kalibratie meten en aftrekken.
  • Drift is een bias die langzaam in de tijd verandert, meestal met de temperatuur. Een kalibratie die je bij het opstarten neemt houdt gaandeweg op de werkelijkheid te sluiten, en daarom hebben lange runs periodieke herkalibratie of een referentie nodig om tegen te corrigeren.

Deze door elkaar halen leidt tot de verkeerde oplossing — meer filtering geneest nooit een bias.

Vier sporen getekend tegen twintig seconden tijd rond een gestreepte horizontale werkelijke waarde. Een ruisvol spoor zwert ruim boven en onder de werkelijke waarde maar middelt erop. Een bias-spoor staat als vaste afwijking boven de werkelijke waarde met weinig spreiding. Een drift-spoor begint op de werkelijke waarde en klimt de hele registratie lang gestaag van die waarde weg.
Drie fouten die allemaal op 'een slechte meting' lijken en drie verschillende oplossingen nodig hebben. Gemiddelen helpt alleen bij de eerste. SVG downloaden

Een filter kiezen

Drie gangbare filters dekken de meeste gevallen:

  • Een voortschrijdend gemiddelde en een exponentieel laagdoorlaatfilter dempen beide willekeurige ruis en ruilen responsiviteit in voor gladheid via hun venster of tijdconstante.
  • Een mediaanfilter verwijdert incidentele pieken en uitvallers beter, omdat een paar slechte monsters de middelste waarde niet verplaatsen.

Kies het lichtste filter dat aan de eis van de verbruiker voldoet — niet het filter dat de gladste grafiek oplevert.

Filtering voegt altijd vertraging toe

Elk gladstellend filter loopt achter op het werkelijke signaal, en meer gladstelling betekent meer vertraging. Een laagdoorlaatfilter met een lange tijdconstante onderdrukt meer ruis, maar valt verder terug bij snelle veranderingen. Teken de gefilterde schatting altijd naast zowel de ruwe monsters als de werkelijke waarde, zodat de vertraging zichtbaar is voordat je het filter in een regellus zet, waar vertraging instabiliteit kan veroorzaken.

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

Wat sensorfusie wel en niet kan

Fusie combineert meerdere sensoren tot één schatting, en het helpt alleen wanneer de sensoren complementaire informatie leveren en hun onzekerheid eerlijk wordt weergegeven. Twee bevoordeelde metingen combineren levert geen waarheid op. Een complementair filter vertrouwt bijvoorbeeld op de ene sensor bij hoge frequenties en op de andere bij lage frequenties; een Kalmanfilter weegt elke bron naar haar onzekerheid. Ga in beide gevallen eerst aan de gang met kalibratie, tijdstempels en gedeelde coördinatenframes voordat je iets fuseert.

Zet op alles een tijdstempel

Monsters komen zelden op een volmaakt vast interval binnen, en zowel filtering als fusie veronderstellen dat je weet wanneer elke waarde is gemeten. Tijdstempels laten je jitter detecteren, gegevens van verschillende sensoren uitlijnen en verouderde metingen verwerpen. Log ruwe waarden naast de verwerkte, zodat fouten als clipping en uitvallers reproduceerbaar blijven.

Meet je sensor voordat je hem filtert

Een filter kiezen voordat je weet hoe de ruis eruitziet is gokken. Tien minuten loggen beslist het, en de procedure is voor elke sensor dezelfde:

  1. Houd de sensor volstrekt stil tegen een bekende, onveranderende invoer.
  2. Log een paar duizend ruwe monsters met tijdstempels.
  3. Bereken het gemiddelde en de standaardafwijking.
  4. Teken de monsters en daarnaast een histogram ervan.

Die vier getallen en twee grafieken vertellen je welke van de drie fouten je hebt:

Wat je ziet Wat het is De oplossing
Gemiddelde klopt met de werkelijkheid, waarden zwerten symmetrisch Ruis Filter het
Gemiddelde wijkt af van de werkelijkheid, spreiding is klein Bias Meet het en trek het af — filtering helpt nooit
Gemiddelde loopt in minuten weg Drift Herkalibreer periodiek, of corrigeer tegen een referentie
Meestal strak, met af en toe wilde waarden Uitwissers Mediaan, geen gemiddelde
Waarden vallen op discrete stappen Kwantisatie Verwacht; het begrinst je resolutie

Het histogram is het deel dat mensen overslaan, en het is het meest veelzeggende. Gaussische ruis maakt een bel; uitwissers maken een bel met een paar punten ver in de staarten. Die twee hebben verschillende filters nodig, en geen hoeveelheid staren naar een tijdreeksgrafiek onderscheidt ze zo duidelijk.

Een filter kiezen, gekwantificeerd

Filter Doodt gaussische ruis Doodt uitwissers Vertraging Kosten
Voortschrijdend gemiddelde, N monsters Ja — met √N Nee — smeert één piek over N monsters (N−1)/2 monsters Buffer van N monsters
Exponentieel laagdoorlaatfilter (EMA) Ja Nee ≈ (1−α)/α monsters Eén float
Mediaan van N Deels Volledig, tot N/2 uitwissers (N−1)/2 monsters Sorteren, triviaal bij kleine N
Mediaan en daarna EMA Ja Ja Beide Beide

De √N in de eerste rij is het nuttige getal: gemiddelen over 4 monsters halveert de ruis; gemiddelen over 100 monsters vermindert hem met een factor tien, ten koste van 50 monsters vertraging. Ruisreductie heeft sterk aflopende meeropbrengst en vertraging niet, en daarom zijn zeer lange gemiddelingen vrijwel altijd het verkeerde antwoord.

Voor een EMA relateert de tijdconstante zich aan α via:

tau = dt x (1 - alpha) / alpha

Dus bij een lus van 10 ms geeft α = 0.1 een tijdconstante van 90 ms. α op gevoel instellen is de manier waarop mensen eindigen met filters die veel trager zijn dan ze doorhebben — reken het één keer uit en je weet wat je hebt.

De vertraging is niet gratis, en dit is wat hij kost

Elk gladstellend filter vertraagt het signaal, en binnen een regellus is die vertraging ononderscheidbaar van een proces dat langzamer reageert. Ze vermindert rechtstreeks hoeveel versterking de lus verdraagt voordat hij gaat oscilleren.

Filter Vertraging bij een lus van 10 ms Afgelegde afstand bij 0.3 m/s
Mediaan van 3 10 ms 3 mm
Mediaan van 5 20 ms 6 mm
Voortschrijdend gemiddelde van 10 45 ms 14 mm
EMA, α = 0.1 90 ms 27 mm
EMA, α = 0.02 490 ms 147 mm

Die laatste rij is het waard om even bij stil te staan. Een α van 0.02 levert een prachtig gladde grafiek en een halve seconde vertraging — de robot stuurt op de plek waar het obstakel 15 cm geleden stond. Dit is de meest voorkomende manier waarop een welbedoeld filter een robot erger maakt, en het is onzichtbaar tenzij je gefilterd tegenover ruw tekent met de werkelijke waarde erbij.

Kies het lichtste filter dat aan de eis voldoet, en controleer altijd wat de vertraging kost in de eenheden waar de robot om geeft — millimeter, of graden, geen monsters.

Een complementair filter, en hoe je de constante kiest

Het complementaire filter is het werkpaardje van hobbyrobotica omdat het drie regels is en het echte probleem oplost: twee sensoren die op omgekeerde manieren falen.

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

alpha bepaalt de grensfrequentie — daarboven vertrouw je de gyroscope, daaronder de accelerometer:

tau = alpha x dt / (1 - alpha)          # the filter's time constant, seconds
f_crossover = 1 / (2 x pi x tau)        # Hz
α bij dt = 5 ms Tijdconstante Grensfrequentie Gedrag
0.90 45 ms 3.5 Hz Zeer responsief, duidelijk ruis van de accelerometer
0.98 245 ms 0.65 Hz De gangbare standaard — een goede balans
0.995 1.0 s 0.16 Hz Zeer glad, drijft merkbaar vóór de correctie
0.999 5.0 s 0.03 Hz Vrijwel alleen gyroscope tijdens elk kort manoeuvre

Kies hem uit de natuurkunde in plaats van uit het gevoel: de tijdconstante moet lang zijn ten opzichte van de storingen die je wilt onderdrukken, en kort ten opzichte van de driftsnelheid van de gyroscope. Een gyroscope met een bias van 1 °/s bereikt 1° fout in een seconde, dus een tijdconstante van meerdere seconden laat echte fout zich opstapelen voordat de accelerometer hem terugtrekt.

Merk ook op dat α van dt afhangt. Een α overnemen uit een project met een andere lusfrequentie geeft je een ander filter — en dat is een veelvoorkomende, onzichtbare bron van “deze versterkingen werken bij mij niet”.

Wat fusie niet kan

Fusie is geen tovertrant, en drie grenzen zijn het waard om plat te zeggen:

Het kan een gedeelde bias niet verwijderen. Twee accelerometers die allebei 2° hoog lezen leveren een gefuseerde schatting die 2° hoog leest. Fusie benut onafhankelijke fouten; een common-modefout blijft onaangeroerd.

Het kan informatie die er niet is niet creëren. Geen hoeveel filtering geeft een zesassige IMU een absolute gierhoek. Gieren heeft geen zwaartekrachtreferentie, dus het drijft, en alleen een magnetometer of een externe referentie verhelpt dat.

Het kan slechte tijdstempels niet repareren. Een GPS-fix van 10 Hz fuseren met een gyroscope van 200 Hz vereist dat je weet wanneer elk gemeten is, tot op een fractie van het snellere interval. Een fix die 100 ms oud is en als actueel wordt behandeld, bederft actief een schatting die de gyroscope alleen wel goed had.

Tijdstempels, concreet

“Alles van een tijdstempel voorzien” is makkelijk om mee in te stemmen en makkelijk over te slaan. De praktische versie:

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;
}

Leg de tijdstempel vast zo dicht mogelijk bij de meting — in de interrupt, niet na het parsen. Een GPS-zin die 80 ms na de fix is binnengekomen en bij het parsen van een tijdstempel is voorzien, is 80 ms fout, en niets verderop kan dat herstellen.

Storingzoeklijst

Symptoom Waarschijnlijke oorzaak Oplossing
Meer filtering, geen verbetering Het is bias, geen ruis Meet de afwijking in rust en trek hem af
Schatting loopt langzaam weg Drift Periodieke herkalibratie, of een absolute referentie
Af en toe een piek overleeft het filter Je gebruikt een gemiddelde Mediaan verwerpt uitwissers; een gemiddelde smeert ze uit
Regellus oscilleert na het toevoegen van een filter Vertraging heeft de stabiele versterking verlaagd Lichter filter, of opnieuw afstellen
Gladde grafiek, robot reageert laat Tijdconstante veel langer dan bedoeld Bereken τ uit α — stel α niet op gevoel in
Gefuseerde schatting slechter dan één van de sensoren Verouderde tijdstempels, of een gedeelde bias Zet de tijdstempel bij de meting; controleer de afwijkingen van beide sensoren
Filter werkt op de werkbank, niet op de robot Trilling is een echt signaal, geen ruis Zachtmonteer de sensor; het filter kan ze niet onderscheiden
Complementair filter gedraagt zich anders dan in een tutorial α hangt af van dt Bereken α voor jouw lusfrequentie

Probeer het zelf

In de Robot Sensor Simulator kun je ruis, bias, drift en uitvallers instellen en daarna ruwe gegevens vergelijken met laagdoorlaat-, voortschrijdend-gemiddelde- en mediaanschattingen. Het is de snelste manier om de afweging tussen ruis en vertraging te voelen — dezelfde afweging die bepaalt hoe een robot reageert in de Obstacle Avoidance Simulator.

Verken de graaf

Onderdeel van deze bouwprojecten

Projecten en leerroutes waarin deze tutorial voorkomt.

Verder lezen

Bronnen