Interactieve simulatorGevorderd

Simulatie van dekkingspadplanning voor robotstofzuigers

Vergelijk willekeurig stuiteren, spiraal en heen-en-weer in een browserlab dat elke strategie meet tegen de afstand die een perfecte veeg zou nemen.

Categorie
Autonome robots
Tijd
20–40 min
Platform
Browser · Arduino · Raspberry Pi
Technisch schema: Simulatie van dekkingspadplanning voor robotstofzuigersBRUSHSERPENTINE COVERAGE PATH

01 / Begin hier

Inleiding

Een vloer bedekken is niet hetzelfde probleem als ergens komen. Een padplanner vindt één route naar één doel; een dekkingsplanner moet elke bereikbare tegel raken, en de eerlijke maat is de afgelegde afstand per schoongeborstelde vierkante meter. Dit lab draait willekeurig stuiteren, een uitdijende spiraal en een geplande slingerbaan over dezelfde kamer, en zet elk daarvan uit tegen het theoretische optimum.

Live lab / Coverage path planning

Coverage path planning simulator

Three ways to cover a floor — random bounce, expanding spiral, and a planned boustrophedon sweep — measured against the one number that matters: the distance a perfect robot would need.

Browser native
A top-down coverage lab. A robot sweeps a room containing four pieces of furniture using the selected strategy, shading each patch of floor as its brush passes over it. Use the controls below to run it, and the keyboard hint to move the furniture.
A plot of floor covered against distance travelled. The straight dashed line is a perfect systematic sweep; the curved dashed line is the theoretical result for random sweeping, one minus e to the minus d over optimal; the solid line is the run happening above.

Shaded floor is covered. The thin line is where the robot has driven, the circle is its brush. Below, the same run plotted as coverage against distance — the dashed straight line is a perfect sweep, the dashed curve is the theory for random sweeping. Drag furniture to rebuild the room.

  • Covered floor
  • Furniture (drag it)
  • Path driven
  • Perfect sweep
Simulation

Ready. Press Start to sweep the room, or Step to advance one move.

Covered
0%
Distance
0.00× optimal
Half the floor
—
90% covered
—
99% covered
—
Bumps
0

Keyboard: focus the room, then Space to run/pause, N to step, R to reset, M for a new room, F for full screen. Press 1–4 to pick a piece of furniture and the arrow keys to move it.

Bediening

Strategie wisselt tussen de drie. De kamer wordt opnieuw opgebouwd en de rit start onmiddellijk opnieuw, want een dekkingscijfer betekent pas iets naast de kamer waarin hij is gemeten.

Sleep een willekeurig meubelstuk met de aanwijzer, of druk op 1–4 om er een te kiezen en verplaats het met de pijltoetsen. De rit start opnieuw zodra je sleept. Zet een tafel in het midden van de vloer en zie de afstand van de geplande veeg oplopen terwijl de dekking daalt.

Nieuwe kamer strooit het meubilair opnieuw. Simulatiesnelheid ruilt gladheid tegen geduld — de willekeurige strategie heeft enkele duizenden zetten nodig, dus begin hem op snel.

Theorie

Een padplanner beantwoordt hoe kom ik daar. Een dekkingsplanner beantwoordt hoe raak ik alles aan, en die twee hebben vrijwel niets gemeen.

De enige eerlijke maatstaf is de afstand die een perfecte robot nodig zou hebben. Bij een vloer met oppervlakte A en een borstel van breedte w kost elke tegel één keer vegen zonder herhaling:

d_optimal = A / w

Alles wat het lab rapporteert is een veelvoud van dat getal. Een strategie op 1,2× besteedt 20% van haar leven aan vloer die ze al heeft gedaan; een op 8× besteedt zeven achtsten.

Willekeurig stuiteren heeft een gesloten vorm, en die is niet bemoedigend. Een robot zonder kaart bedekt nieuwe vloer naar rato van hoeveel er nog ongedekt is, dus het ongedekte oppervlak neemt exponentieel af:

covered(d) ≈ 1 − e^(−d / d_optimal)

Dat is de stippellijn in de grafiek. Lees er drie punten af: 63% van de vloer na één optimale afstand, 90% na 2,3, en 99% na 4,6. De laatste tiende van de kamer kost tweemaal zoveel als de eerste driekwart — het couponverzamelaarsprobleem, met een borstel.

Systematische dekking is lineair, dus hij eindigt op 1× plus de overhead die de rijafstand en de bochten kosten. In dit lab is die overhead ongeveer 35%.

De gemeten ritten landen dicht bij de theorie, en waar ze ernaast zitten doen ze dat in de richting die je zou verwachten: een echte willekeurige loop bezoekt naburige vloer opnieuw in plaats van te teleporteren, dus hij doet het net slechter dan de onafhankelijke steekproefcurve suggereert.

Algoritme

Willekeurig stuiteren. Rij rechtdoor. Bij een botsing kies je willekeurig een nieuwe richting en controleer je of die vrij is. Dat is het hele verhaal, en het vraagt één bit detectie en helemaal geen geheugen.

Spiraal, dan verplaatsen. Draai met een hoek omgekeerd evenredig met hoe ver je sinds het middelpunt hebt gereisd, dat tekent een uitzettende spiraal. Bij een botsing schiet je een vaste afstand rechtdoor en begin je een nieuwe spiraal. Uitstekend op open vloer — een spiraal heeft nauwelijks overlap — en hopeloos in een rommelige kamer, waar elke spiraal na een paar bochten wordt afgekapt.

Geplande kronkelende veeg. Drie stappen, en de tweede is degene die mensen overslaan:

  1. Opblazen. Vergroot elk obstakel met de straal van de robot plus een veiligheidsmarge. Wat overblijft is waar het middelpunt van de robot mag komen.
  2. Snijden. Loop de opgeblazen kaart in rijen af op één borstelbreedte van elkaar. Elke rij wordt een of meer vrije stukken.
  3. Verbinden. Bezoek de stukken in kronkelende volgorde, en route tussen opeenvolgende stukken met een kortste pad door de vrije ruimte, zodat de robot om de bank heen rijdt in plaats van erin.

Stap 3 is waar de afstandsoverhead vandaan komt, en het is waarom een rommelige kamer een planner harder straft dan een lege.

Broncode

De willekeurige strategie is de eerste die je op een echte robot wilt hebben, want hij werkt met detectie die je al hebt:

// Random-bounce coverage. Two bump switches, no map, no encoders.
const uint8_t BUMP_L = 2, BUMP_R = 3;
const uint16_t CRUISE = 170;      // PWM
unsigned long turnUntil = 0;
int turnDir = 1;

void loop() {
  bool left  = digitalRead(BUMP_L) == LOW;   // switches are active-low with pull-ups
  bool right = digitalRead(BUMP_R) == LOW;

  if (millis() < turnUntil) {                 // still executing a bounce
    drive(turnDir * CRUISE, -turnDir * CRUISE);
    return;
  }

  if (left || right) {
    // Back off first — turning while wedged against a chair leg does nothing.
    reverseFor(320);
    // A random turn between 90 and 270 degrees. The randomness is what stops the
    // robot tracing the same closed loop around the room forever.
    turnDir = right ? -1 : 1;
    turnUntil = millis() + random(420, 1250);
    return;
  }

  drive(CRUISE, CRUISE);
}

De stuiterhoek moet willekeurig zijn. Een vaste spiegeling maakt van de kamer een biljartafel, en een biljartbal op een rechthoekige tafel beschrijft een gesloten pad dat het meeste oppervlak voor altijd mist.

De geplande veeg heeft de opblazen-snijden-verbinden-pass hierboven nodig plus odometrie die goed genoeg is om een rechte rij vast te houden, en dat is een andere klasse robot. Prototipeer hem hier, waar de positie per constructie exact is, voordat je beslist of je hardware het aankan.

Aannames en hardwareverschillen

Het lab geeft de robot perfecte odometrie, een volledig bekende kaart, omslag zonder vertraging en een borstel die een zuivere cirkel bestrijkt. Een echte machine heeft daar geen van alle.

Wielslip en gyroscoopdrift buigen de rijen na ongeveer tien uit elkaar, en daarom lokaliseren commerciële robots zich opnieuw tegen muren, plafondkenmerken of een baken. Bochten kosten tijd waarvoor dit lab geen afstand rekent. En de borstel bestrijkt geen cirkel — hij bestrijkt een rechthoek achter de robot, dus achteruit rijden over vloer die je al hebt gedaan reinigt niets.

Het verschil tussen de strategieën overleeft dat allemaal. Als een planner willekeurig stuiteren hier met 3× verslaat, verslaat hij het op echte hardware misschien met 2×; de volgorde verandert niet.

Schakelschema

De detectie valt netjes uiteen in drie taken, en alleen de eerste is verplicht.

Bumper. Twee microschakelaars op een veerbelaste voorbumper, met active-low bedraad naar pinnen die interrupts kunnen verwerken en met de interne pull-ups aan. Dit is de detectie die willekeurig stuiteren mogelijk maakt en het is het laatste dat uitvalt.

Afgrond. Naar beneden gerichte reflectiesensoren op de voorhoeken, elke lusdoorgang uitgelezen. Een dekkingsrit bezoekt alles, en dat is inclusief de top van de trap — de rekensom voor hoe ver de robot voorbij de rand rijdt voordat hij kan stoppen staat hier uitgerekend.

Positie. Kwadratuurencoders op beide wielen, en een gyroscoop als je rijen evenwijdig wilt houden. Alleen de geplande strategie heeft dit nodig, en die behoefte is de hele reden dat de andere twee bestaan.

Voor de dekkingsstrategieën als bouwproject zie je de kamerdekkingsrobot; voor de reactieve laag eronder behandelt de simulatie van obstakelvermijding de stopdrempels en het aftasten.

Hardwarechecklist

Componenten

  • Een differentiaalaandrijvingsbasis waarvan je de borstelbreedte kunt meten
  • Bumperdetectie die het overleeft tegen meubels aan rijden
  • Encoders, als de robot gaat plannen in plaats van dwalen
  • Een afgrondsensor, want dekking eindigt bij de trap

Verken de graaf

Waar deze simulator wordt gebruikt

De projecten, leerroutes en tutorials die op dit lab voortbouwen.

Verder bouwen

Hulpmiddelen downloaden

Gebruik deze naslag op de pagina terwijl je het project doorwerkt. Downloadbare projectpakketten komen er pas bij nadat hun broncode en versie zijn gepubliceerd.

Veelgestelde vragen

Veelgestelde vragen

Waarom stuiteren goedkope robotstofzuigers willekeurig rond?

Omdat willekeurig stuiteren geen kaart, geen encoders en geen lokalisatie nodig heeft — de hele strategie is rechtdoor rijden, en bij een botsing een willekeurige hoeveelheid draaien. Dat past op een achtbits-microcontroller met twee bumperschakelaars. Het lab laat zien wat dat kost: de eerste helft van de vloer is even snel gedekt als met een geplande veeg, maar 90 procent kost ongeveer driemaal de ideale afstand en 99 procent zesmaal of meer. De robot komt er uiteindelijk, en daarom overleeft de strategie — hij besteedt alleen een uur aan twintig minuten werk.

Waarom is de dekking aan het einde zo traag en aan het begin zo snel?

Omdat een robot die zonder kaart veegt nieuwe vloer bedekt naar rato van hoeveel vloer er nog ongedekt is. Vroeg is vrijwel alles wat hij rijdt nieuw; laat is vrijwel alles een herhaling. Dat geeft de klassieke exponentiële nadering, dekking van ongeveer één min e tot de macht min d over optimaal, die het lab als een stippellijnreferentiecurve tekent. Het is dezelfde wiskunde als het couponverzamelaarsprobleem, en het betekent dat de laatste tiende van een kamer meer kost dan de eerste driekwart.

Als systematisch vegen zoveel beter is, waarom stopt het lab dat dan bij 90 procent?

Omdat een planner de robotbehuizing vrij van alles moet houden, dus plant hij een pad dat op afstand blijft van elke muur en elke tafelpoot — en hij bedekt nooit wat hij niet op kan rijden. In dit lab liggen 130 van de 133 tegels die de geplande veeg mist binnen twee cellen van een muur of een meubelstuk. Dat is precies waarom echte robotstofzuigers een zijborstel hebben die buiten het chassis uitsteekt en waarom ze de muren als aparte gang volgen. Willekeurig stuiteren bereikt die randen uiteindelijk, louter op geluk.

Wat heeft de geplande veeg nodig dat de willekeurige niet heeft?

Hij moet weten waar hij is. Een kronkelende route betekent pas iets als de robot een rechte lijn kan rijden, een bekende hoek kan draaien, en zijwaarts één borstelbreedte kan stappen — en dat is odometrie, en odometrie loopt weg. Het lab plant op een perfecte kaart met een perfecte robot, dus behandel zijn 1,35 keer optimaal als de vloer van wat een echte machine haalt in plaats van als een doel. Met wielslip en gyroscoopdrift zijn de rijen na ongeveer tien niet meer evenwijdig.

Hoe breed moeten de rijen zijn?

Eén borstelbreedte, minus een overlap die je bewust kiest. Zet ze precies één breedte uit elkaar en elke richtingfout laat een ongedekte strook tussen de rijen over die geen latere gang meer vindt. Overlap met 10 tot 20 procent en de stroken sluiten, ten koste van datzelfde percentage in afstand. Het lab zet de rijen op het grootste gehele aantal cellen dat de borstel bestrijkt, en daarom komt de afstand uit op 1,35 keer optimaal in plaats van 1,0 — de overhead is echt en elke dekkende robot betaalt een vorm ervan.

Geldt dit ook voor iets anders dan stofzuigers?

Het is hetzelfde probleem voor een gazonmaaierrobot, een zwembandreiniger, een vloerschrobber, een gewasverneveler en een karteringsdrone. Ze hebben allemaal een werkbreedte, een te dekken gebied en een energiebudget dat afstand tot het te minimaliseren ding maakt. De strategieën verschillen vooral in of de machine detectie kan betalen om te weten waar hij is — een karteringsdrone heeft GPS en plant altijd; een zwembandreiniger heeft niets en dwaalt altijd.

Verder lezen

Bronnen

Gezaghebbende bronnen om dieper te gaan dan het afgebakende leermodel van deze simulator.