← Område 3 Guide · Labyrintlogiken Felsökning

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.

Fyra tal ni ställer in själva

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:

morkaLägeVad roboten gör
1–2Linjefolj(position)
3 eller flerKorsning – tejpen går tvärs överKör fram, titta, välj
0Återvändsgränd – tejpen tog slutVänd
4–5 även efter att ha kört framMål – tjock linjeStopp

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.

Varför bekräfta återvändsgränden?

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
Testa utan robot

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

SymptomTrolig orsakÅtgärd
Kör rakt igenom korsningenMORK för högt, eller dålig kalibreringprint(morka) över korsningen. Sänk MORK, eller kalibrera om med vaggning
Varje kurva blir en korsningTre sensorer svarta i snäva kurvorKräv dessutom varden[0] > MORK or varden[4] > MORK
Svänger 360 i stället för 90SVANGFART för hög – mitten hinner förbi linjen25 eller 30. Kontrollera att mitten var vit innan svängen började
Vänder i kurvorÅtervändsgränden bekräftas inteatervandsgrand_bekraftad() i villkoret
Kör in i korsningen och tappar alltKORSNING_FRAM för lång0.2. Sensorn sitter framför hjulen – det behövs bara några cm
Stannar aldrig vid måletMållinjen för tunn, eller m >= 4 nås inte efter framkörningenTjockare mål. Eller m >= 3
forkorta ger felFel i REGLER eller i loopenTesta i terminalen. Jämför med tabellen treord för treord
Andra körningen svänger felListan läses i fel ordning, eller i ökar inteprint(steg) vid varje korsning

Ord på den här sidan

OrdBetyder
vänsterhandsregelnHåll alltid vänster. Leder ut ur varje labyrint utan öar
tillståndVilket läge programmet är i: linje, korsning, återvändsgränd, mål
breakAvbryt loopen nu
appendLägg till sist i en lista
dictionaryEtt uppslagsverk: REGLER["VBV"] ger "R"
algoritmEn regel som alltid ger ett svar, steg för steg. Vänsterhandsregeln är en

Ordträning