Teknik 1 · område 3 · pass 9
Labyrintlogiken
Koden till labyrinten, i bitar. Den bygger på allt du har: motorfunktionerna,
readLine(), biblioteken. Det som är nytt är att känna igen tre
lägen och välja i ett av dem. Koden finns här – det som är ert jobb är att
få den att fungera på er robot: trösklarna, tiderna, farterna.
MORK – kalibrerat värde över detta räknas som svart (0–1000).
KORSNING_FRAM – sekunder framåt för att få hjulen mitt i korsningen.
FART och SVANGFART. Utgångsvärden: 500 · 0.25 · 35 · 30.
Vad som fungerar på er robot skriver ni i loggboken – det är mätvärden.
1. Läsa läget
Överst i filen: motorerna från pass 5 med kor, stopp,
vanster och hoger, sedan biblioteken. Sedan konstanterna och
en funktion som läser allt på en gång:
sensor = TRSensor()
lcd = ST7789()
MORK = 500
KORSNING_FRAM = 0.25
FART = 35
SVANGFART = 30
def las():
position, varden = sensor.readLine()
morka = 0
for v in varden:
if v > MORK:
morka += 1
return position, varden, morka
def folj(position):
if position < 1500:
kor(20, 45)
elif position > 2500:
kor(45, 20)
else:
kor(FART, FART)
las() svarar med tre saker: positionen, listan, och hur många
sensorer som ser svart. Det sista talet är det som skiljer lägena åt:
morka | Läge | Vad roboten gör |
|---|---|---|
| 1–2 | Linje | folj(position) |
| 3 eller fler | Korsning – tejpen går tvärs över | Kör fram, titta, välj |
| 0 | Återvändsgränd – tejpen tog slut | Vänd |
| 4–5 även efter att ha kört fram | Mål – tjock linje | Stopp |
for v in varden: går genom listan – samma for-loop som på skärmen, men
utan index: v blir varje tal i tur och ordning.
2. Svänga tills linjen hittas
En sväng ska inte vara en fast tid. Den ska vara tills mittsensorn hittar en linje igen. Två steg: vänta tills mitten lämnat linjen den stod på, sedan vänta tills den hittar nästa.
def svang_tills_linje(riktning):
if riktning == "V":
vanster(SVANGFART)
else:
hoger(SVANGFART)
while True:
p, varden, m = las()
if varden[2] < MORK:
break
while True:
p, varden, m = las()
if varden[2] > MORK:
break
stopp()
def vand():
svang_tills_linje("V")
break avbryter loopen. Första loopen: så länge mitten är svart, fortsätt
svänga. Andra loopen: så länge mitten är vit, fortsätt svänga. Sedan stanna. En
vändning i en återvändsgränd är samma sak – svänger man vänster tillräckligt länge
hittar man samma linje bakifrån.
3. Vänsterhandsregeln – nivå 1
I korsningen: kom ihåg vad som fanns till vänster och höger när korsningen upptäcktes, kör fram så att hjulen står mitt i den, titta om det finns en linje rakt fram, välj.
def korsning(varden_vid):
vanster_finns = varden_vid[0] > MORK
hoger_finns = varden_vid[4] > MORK
kor(FART, FART)
sleep(KORSNING_FRAM)
stopp()
p, varden, m = las()
if m >= 4:
return "MAL"
rakt_finns = m >= 1
if vanster_finns:
svang_tills_linje("V")
return "V"
elif rakt_finns:
return "R"
elif hoger_finns:
svang_tills_linje("H")
return "H"
else:
vand()
return "B"
def atervandsgrand_bekraftad():
kor(FART, FART)
sleep(0.1)
p, varden, m = las()
return m == 0
while True:
position, varden, morka = las()
if morka >= 3:
val = korsning(varden)
if val == "MAL":
stopp()
break
elif morka == 0 and atervandsgrand_bekraftad():
vand()
else:
folj(position)
Läs korsning() uppifrån: vänster om det går, annars rakt, annars höger,
annars vänd. Det är vänsterhandsregeln. Funktionen svarar med en bokstav –
den behövs inte än, men den behövs i nivå 2.
I en snäv kurva kan alla fem sensorer tappa linjen en tiondels sekund. Utan bekräftelsen vänder roboten i varje kurva. Kör en bit, läs igen – är det fortfarande vitt är det på riktigt.
4. Listan som minne – nivå 2
Varje val sparas. vag.append(val) lägger till sist i listan. När roboten
når målet är listan vägen den tog – med återvändsgränderna.
REGLER = {"VBV": "R", "VBR": "H", "RBV": "H", "VBH": "B", "RBR": "B", "HBV": "B"}
def forkorta(vag):
ny = []
for steg in vag:
ny.append(steg)
while len(ny) >= 3 and ny[-2] == "B":
tre = ny[-3] + ny[-2] + ny[-1]
if tre in REGLER:
ny[-3:] = [REGLER[tre]]
else:
break
return ny
def utforska():
vag = []
while True:
position, varden, morka = las()
if morka >= 3:
val = korsning(varden)
if val == "MAL":
stopp()
return vag
vag.append(val)
elif morka == 0 and atervandsgrand_bekraftad():
vand()
vag.append("B")
else:
folj(position)
forkorta() tar bort varje återvändsgränd: så fort de tre sista i listan
har ett B i mitten slås de ihop enligt reglerna. Reglerna är vinklar –
vänster är +90, höger −90, vänd 180, rakt 0. Summera tre och du vet vart man kom:
V B V → R 90 + 180 + 90 = 360 = rakt
V B R → H 90 + 180 + 0 = 270 = höger
R B V → H 0 + 180 + 90 = 270 = höger
V B H → B 90 + 180 − 90 = 180 = vänd
R B R → B 0 + 180 + 0 = 180 = vänd
H B V → B −90 + 180 + 90 = 180 = vänd
Skriv forkorta(["V","B","V","R","H"]) i terminalen. Svaret ska bli
["R","R","H"]. Stämmer det inte är det forkorta som är fel,
inte roboten.
5. Andra körningen
Samma loop, men i korsningen väljer roboten inte – den läser nästa bokstav ur listan.
def kor_vag(vag):
i = 0
while True:
position, varden, morka = las()
if morka >= 3:
kor(FART, FART)
sleep(KORSNING_FRAM)
stopp()
p, v2, m = las()
if m >= 4 or i >= len(vag):
stopp()
return
steg = vag[i]
i += 1
if steg == "V":
svang_tills_linje("V")
elif steg == "H":
svang_tills_linje("H")
else:
folj(position)
vag = utforska()
kort = forkorta(vag)
lcd.fill(lcd.SVART)
lcd.text("Kort: " + "".join(kort), 5, 10, lcd.GRON)
lcd.show()
sleep(10)
kor_vag(kort)
i räknar var i listan roboten är. "".join(kort) gör listan
till en text för skärmen. De tio sekunderna är till för att ställa tillbaka roboten på
start. Sedan kör den den korta vägen – utan att gå in i återvändsgränderna.
Nivå 1 — hitta ut
Nivå 2 — minnas vägen
Kryssen sparas i din webbläsare.
6. Felsökning
8 rader
| Symptom | Trolig orsak | Åtgärd |
|---|---|---|
| Kör rakt igenom korsningen | MORK för högt, eller dålig kalibrering | print(morka) över korsningen. Sänk MORK, eller kalibrera om med vaggning |
| Varje kurva blir en korsning | Tre sensorer svarta i snäva kurvor | Kräv dessutom varden[0] > MORK or varden[4] > MORK |
| Svänger 360 i stället för 90 | SVANGFART för hög – mitten hinner förbi linjen | 25 eller 30. Kontrollera att mitten var vit innan svängen började |
| Vänder i kurvor | Återvändsgränden bekräftas inte | atervandsgrand_bekraftad() i villkoret |
| Kör in i korsningen och tappar allt | KORSNING_FRAM för lång | 0.2. Sensorn sitter framför hjulen – det behövs bara några cm |
| Stannar aldrig vid målet | Mållinjen för tunn, eller m >= 4 nås inte efter framkörningen | Tjockare mål. Eller m >= 3 |
forkorta ger fel | Fel i REGLER eller i loopen | Testa i terminalen. Jämför med tabellen treord för treord |
| Andra körningen svänger fel | Listan läses i fel ordning, eller i ökar inte | print(steg) vid varje korsning |
Ord på den här sidan
| Ord | Betyder |
|---|---|
| vänsterhandsregeln | Håll alltid vänster. Leder ut ur varje labyrint utan öar |
| tillstånd | Vilket läge programmet är i: linje, korsning, återvändsgränd, mål |
| break | Avbryt loopen nu |
| append | Lägg till sist i en lista |
| dictionary | Ett uppslagsverk: REGLER["VBV"] ger "R" |
| algoritm | En regel som alltid ger ett svar, steg för steg. Vänsterhandsregeln är en |
Ordträning