Jython
Deutsch   English 

6. Der lernende Roboter


Das Verhalten vieler Roboter ist nicht fest einprogrammiert, sondern die Roboter verhalten sich gemäss Informationen, die sie aus einem Speicher, analog einem Gedächtnis, zurück  holen. Der Speicher kann entweder durch "Anlernen" mit einen "Teacher" oder durch "Selbstlernen" (Lernen aus eigener Erfahrung) gefüllt werden. In den folgenden Beispielen wird an einfachen Beispielen aufgezeigt, wie ein Roboter durch einen Mensch angelernt wird Dann soll er auch mit Hilfe seiner Sensoren selbst lernen, eine Aufgabe zu erfüllen.

Beispiel 1: Der Roboter lernt im "Teach-Mode"
Industrierobotern werden in einem "Teach Mode" durch einen Spezialisten (Teacher) "angelernt", beispielsweise welche Armbewegungen durchzuführen sind, um eine bestimmte Arbeit auszuführen. Der Teacher verwendet dabei meist ein Eingabesystem ähnlich einer Fernsteuerung. Dabei wird der Roboter nacheinander in die gewünschten Positionen gefahren und der jeweilige Zustand abgespeichert.

In unserem Beispiel wird der Roboter in der Lernphase mit einem zweiten micro:bit ferngesteuert, um den Weg in einem einfachen Labyrinth zu finden. Da in dieser einfachen Bahn die geraden Wegstücke gleich lang sind und senkrecht auf einander stehen, muss der Teacher den Roboter nur anweisen, ob er links oder rechts abbiegen soll. Er führt die Befehle aus und speichert die Left- bzw. Right-Commandos in der Liste memory. Die Liste ist zu Beginn leer. Beim Erhalt der Message LEFT wird mit dem Befehl memory.append(0) eine 0 , beim Erhalt der Message RIGHT mit memory.append(1) eine 1 hinzugefügt. Ist der Lernprozess abgeschlossen, wird der Roboter zurück an die Startposition versetzt und fährt mit Klick auf den Button A die Strecke selbständig.    

 

Programm Teacher (micro:bit):    
#Mr6a.py
from microbit import *
import radio

radio.on()
state = "STOP"
oldState = ""
while True:
    if button_a.was_pressed():
        state = "LEFT"
        display.show('L')
    elif button_b.was_pressed():
        state = "RIGHT"
        display.show('R')
    else:
        state = "STOP"
        display.show('S')
    if oldState != state:
        radio.send(state)
        oldState = state   
    delay(10)
► In Zwischenablage kopieren
 

 


Programm Roboter:    
# Mr6b.html (receiver)
from microbit import *
from mbrobot import *
import radio

def fd():
    forward()
    delay(moveTime)
    stop()
    
def run():
    for k in memory:
            if k == 0:
                left()
                delay(turnTime)                
            elif k == 1:         
                right()
                delay(turnTime)
            fd()

moveTime = 1000
turnTime = 500
radio.on()
setSpeed(20)
memory= []
while not button_a.was_pressed():   
    rec = radio.receive()    
    if rec == "LEFT":
        memory.append(0)
        left()
        delay(turnTime)
        fd()
    elif rec == "RIGHT":
        memory.append(1)
        right() 
        delay(turnTime)
        fd()
    else:    
        stop() 
run()            
stop()
► In Zwischenablage kopieren
 

 

Erklärungen zum Programmcode:

memory = [] : Die Liste memory ist zu Beginn leer
memory.append(0): beim Linksabbiegen wird eine 0 in die Liste hinzugefügt
memory.append(1): beim Rechtsabbiegen wird eine 1 hinzugefügt
def run(): Definiert unter Verwendung der Liste memory, wie die Bahn abzufahren ist


Beispiel 2: Der Roboter lernt mit Hilfe seiner Infrarotsensoren, ein einfaches Labyrinth durchzufahren

Mit Hilfe seiner Sensoren lernt der Roboter selbst, eine Bahn mit gleich langen Wegstücken abzufahren. Dabei verfolgt er folgende Strategie: Er beginnt beim Start und fährt vorwärts auf der weissen Bahn, bis er eine schwarze Unterlage detektiert. Danach fährt er eine kurze Strecke zurück, dreht er 90° nach links. Wenn er in den nächsten 2 Sekunden keine schwarze Unterlage "sieht", fährt er weiter bis zur nächsten Kreuzung. Sonst hat er mit Linksdrehen die falsche Richtung gewählt, eine Rechtdrehung wäre richtig. Er dreht also 180° und fährt weiter bis zur nächsten Kreuzung. In der Liste memory speichert er 0 für links und 1 für rechts. Um den Roboter am Ende des Labyrinths zu stoppen, drückt man den Button A auf dem micro:bit.

 
 


Durch Drücken des Buttons B fährt der Roboter anschliessend die Bahn selbständig ab, indem er die gespeicherten Informationen für Links-, bzw. Rechtsabbiegen verwendet. Führen Sie das Programmm zuerst im Simulationsmodus mit dem Hintergrundbild bg.gif aus. In der Simulation erscheint ein zweites Fenster mit einem micro:bit, wo die Buttons A und B verwendet werden können.
Im Realmodus muss man die Zeilen mit Robot.Context und reset() deaktivieren.


#Mr6c.py
from mbrobot import *
from microbit import*
import time

RobotContext.useBackground("sprites/bg.gif")  
RobotContext.setStartPosition(310, 460)

def run():
    for k in memory:
        print("forward")
        forward()
        delay(moveTime)
        if k == 0:
            print("left")
            left()
            delay(turnTime)            
        elif k == 1:
            print("right")
            right()
            delay(turnTime)            
    forward()
    delay(moveTime)     
   
turnTime = 540
moveTime = 3000
memory = []
startTime = time.clock()
forward()

while not button_a.was_pressed():  
    forward()
    v1 = irLeft.read_digital()
    v2 = irRight.read_digital() 
    if v1 == 0 or v2 == 0:
        dt = time.clock() - startTime 
        if dt > 2:
            backward()
            delay(300)
            memory.append(0) 
            left()
            delay(turnTime)  
        elif memory != []:
            memory.pop()
            memory.append(1) 
            left()
            delay(2 * turnTime) 
        print("Memory: " + str(memory))
        forward()
        startTime = time.clock()      
stop()

while not button_b.was_pressed():
    pass    
print("start")
reset()       
run()      
► In Zwischenablage kopieren
 
 

 

 

 

 

 

 

 

 

 

Memory: [0]
Memory: [0, 0]
Memory: [0, 1]
Memory: [0, 1, 0]
Memory: [0, 1, 1]
Memory: [0, 1, 1, 0]

 

Erklärungen zum Programmcode:

import time : Importiert das Modul time, mit dem man eine Echtzeitmessung vornehmen kann
startTime = time.clock(): Aktuelle Zeit
dt = time.clock() - startTime : Die Zeit, die seiten seit Beginn der Messung vergangen ist
memory.pop(): Da der Roboter zuerst immer links abzubiegen versucht, wird im Memory bereits eine 0 gespeichert. Falls dieser Entschein falsch war, wir der Eintrag wieder gelöscht und mit einer 1 für Rechtsfhren ersetzt
reset(): Nur im Simulationsmodus. Der Roboter wird an die Startposition versetzt. Im Realmodus muss reset() gelöscht oder deaktiviert werden

Beispiel 3: Der Roboter lernt eine Bahn mit beliebig langen Wegstücken durchfahren.

Der Roboter muss nicht nur lernen, wo er links und wo rechts abbiegen soll, sondern er muss sich auch die Zeit, die er braucht, um die geraden Wegstücke zurückzulegen, merken. Zu Beginn jedes Wegstücks startet er einen Timer und misst die Zeit, bis er bei der nächsten Kreuzung ankommt. In seiner Memory-Liste speichert er für jedes Wegstück 2 Werte: Die Fahrzeit in Millisekunden und 0 bzw. 1 für eine Drehung nach links oder rechts.

Durch Drücken des Buttons A wird der Roboter am Schluss der Lernphase gestoppt. Durch Drücken des Buttons B fährt er anschliessend die Bahn selbständig ab, indem er die gespeicherten Informationen verwendet.

 

Das Programm kann im Simulationsmodus mit dem Hintergrundbild bg2.gif augeführt werden. Im realen Modus muss man die beide Robot.Context-Zeilen und die Zeile reset() deaktivieren.

#Mr6d.py
from mbrobot import *
from microbit import*
import time

RobotContext.useBackground("sprites/bg2.gif")
RobotContext.setStartPosition(410, 450)

def run():
    for node in memory:
        moveTime = node[0]
        k = node[1]
        print("forward")
        forward()
        delay(moveTime)        
        if k == 0:
            print("left")
            left()
            delay(turnTime)            
        elif k == 1:
            print("right")
            right()
            delay(turnTime)
    forward()
turnTime = 540
moveTime = 0
backTime = 400
memory = []
startTime = time.clock()

while not button_a.was_pressed():
    forward()
    v1 = irLeft.read_digital()
    v2 = irRight.read_digital()    
    if v1 == 0 or v2 == 0:        
        dt = time.clock() - startTime 
        backward()
        delay(backTime)
        if dt > 2:
            moveTime = int(dt * 1000) - backTime   
            node = [moveTime, 0]
            memory.append(node) 
            left()
            delay(turnTime)  
        elif memory != []:        
            memory.pop()
            node = [moveTime, 1]
            memory.append(node) 
            right()
            delay(2 * turnTime) 
        print("Memory: " + str(memory))
        startTime = time.clock()   
stop()

while not button_b.was_pressed():
    pass    
print("start")
reset()   
run()    
► In Zwischenablage kopieren
 

 

 

 

Erklärungen zum Programmcode:

moveTime = int(dt * 1000) - backTime : Bestimmt die Fahrzeit für das zurückgelegte Wegstück
node = [moveTime, 0]: Fahrzeit für ein Wegstück und 0, bzw, 1 für eine Links- bzw. Rechtsdrehung

memory.append(node) : Nach jedem Wegstück werden zwei Werte gespeichert:

Memory: [[2706, 0]]
Memory: [[2706, 0], [3209, 0]]
Memory: [[2706, 0], [3209, 0], [2509, 0]]
Memory: [[2706, 0], [3209, 0], [2509, 1]]
Memory: [[2706, 0], [3209, 0], [2509, 1], [4051, 0]]
Memory: [[2706, 0], [3209, 0], [2509, 1], [4051, 1]]
Memory: [[2706, 0], [3209, 0], [2509, 1], [4051, 1], [5770, 0]]

 


Aufgaben:


1)


Erstelle eine Roboterbahn mit rechtwinklig stehenden Wegstücken. Versuche den Roboter mit einem zweiten micro:bit anzulernen, dass er deine Bahn selbständig durchfahren kann.

 

 

 


2)


Der Roboter soll mit seinen Infrarotsensoren lernen die nebenstehende Bahn durchzufahren.

Löse die Aufgabe im Simulationsmodus mit dem Hintergrundhild bg3.gif.

RobotContext.useBackground("sprites/bg3.gif")
RobotContext.setStartPosition(410, 450)