Jython HomeDruckenJava-Online

Lernfähige Roboter

Es ist leicht, lernfähige Roboter zu programmieren, da der Roboter beliebig viele Informationen speichern kann. In unseren Beispielen lernt der Roboter eine Hindernisbahn selbstständig durchzufahren.

Beispiel 1: In der Lernphase wird der Roboter mit Hilfe der Cursortasten LEFT und RIGHT durch den Benutzer gesteuert, wobei in dieser einfachen Bahn die geraden Wegstücke gleich lang sind und senkrecht auf einander stehen. Der Roboter muss sich nur einprägen, ob er links oder rechts abbiegen soll.

Der Roboter führt die Befehle aus und speichert die Left- bzw. Right-Commandos in der Liste memory. Wenn er links abbiegen muss, speichert er 0, beim rechtsabbiegen 1. Die Datenstruktur Liste eignet sich optimal für die Speicherung solchen Daten. Mit der Funktion memory.append(x) kann ein Element x hinzugefügt werden.

Mir drücken der ENTER-Taste kann der Roboter anschliessend die Bahn selbständig durchfahren, in dem er die gespeicherten Informationen verwendet. In der Schleife for i in memory werden die Werte aus der Liste memory der Reihe nach geholt und der Roboter weiss dadurch, ob er links oder rechts abbigen soll.

 


#Ro12a.py

from simrobot import *
#from ev3robot import *
#from nxtrobot import *

RobotContext.useBackground("sprites/bg.gif")
RobotContext.setStartPosition(310, 470)
RobotContext.showStatusBar(30)

def run():
    gear.forward(tMove)
    for i in memory:
        if i == 0:
            gear.left(tTurn)
            gear.forward(tMove)
        elif i == 1:
            gear.right(tTurn)
            gear.forward(tMove)  

robot = LegoRobot()
gear = Gear()
robot.addPart(gear)
tMove = 3200
tTurn = 545
gear.forward(tMove)
memory = []

while not robot.isEscapeHit():
    if robot.isLeftHit():        
        gear.left(tTurn)
        memory.append(0)
        robot.drawString("Memory: " + str(memory), 0, 1)
        gear.forward(tMove) 
    elif robot.isRightHit():         
        gear.right(tTurn)
        memory.append(1)
        robot.drawString("Memory: " + str(memory), 0, 1)
        gear.forward(tMove)
    elif robot.isEnterHit():
        robot.reset()    
        run()      
robot.exit()
Programmcode markieren (Ctrl+C kopieren)

Erklärungen zum Programmcode:

memory = [] : Memory ist zu Beginn eine leere Liste
memory.append(0): beim Llinksabbiegen wird eine 0 in die Liste hinzugefügt
memory.append(1): beim Rechtsabbiegen wird eine 1 hinzugefügt
def run(): Funktion run() definiert unter Verwendung der Liste Memory, wie die Bahn durchzufahren ist

 

Beispiel 2: In der Lernphase wird die infrarot Fernsteuerung verwendet (nur autonomer Modus)

Der Roboter kennt 4 Zustände: FORWARD, LEFT, RIGHT und RUN. Zu Beginn des Programms wird er in den Zustand FORWARD versetzt. Die drei weiteren Zustände werden mit der Fernsteuerung durch Klicken der Tasten obern links (LEFT), oben rechts (RIGHT) und unten links (RUN) aufgerugen.

 


# Ro12b.py

from ev3robot import *

def onActionPerformed(port, command):
    global state
    if command == 1:
        state = "LEFT"
    elif command == 3:
        state = "RIGHT"
    elif command == 2:
        state = "RUN"

moveTime = 5000
turnTime = 580
memory = []       
robot = LegoRobot()
gear = Gear()
gear.setSpeed(50)
robot.addPart(gear)
irs = IRRemoteSensor(SensorPort.S1, actionPerformed = onActionPerformed)
robot.addPart(irs)
state = "FORWARD"
robot.drawString("Learning...", 0, 3)

while not robot.isEscapeHit():
    if state == "FORWARD":
        gear.forward(moveTime)
    elif state == "LEFT":
        memory.append(0)
        gear.left(turnTime)
        gear.forward(moveTime)
    elif state == "RIGHT":
        memory.append(1)
        gear.right(turnTime)
        gear.forward(moveTime)
    elif state == "RUN":
        robot.drawString("Executing...", 0, 3)
        robot.reset()
        gear.forward(moveTime)
        for k in memory:
            if k == 0:
                gear.left(turnTime)
            else:         
                gear.right(turnTime)
            gear.forward(moveTime)
        gear.stop() 
        robot.drawString("All done", 0, 3)
robot.exit()
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

Erklärungen zum Programmcode:

global state: die Variable state muss global sein, da sie in einer Funktion verwendet wird.

 

Beispiel 3: Mit Hilfe eines Touchsensors und Timers kann Roboter selbst lernen, die Bahn durchzufahren. Dabei verfolgt er folgende Strategie: Er fährt vorwärts, bis es mit dem Touchsensor die Wand berührt. Danach fährt er eine kurze Strecke zurück und dreht 90° nach links und startet den Timer. Wenn er inner einer kurzen Zeit wirde eine Wand berührt, hat er die falsche Richtung gewählt. Er dreht um 180° un fährt in die andere Richtung. Da in dieser Bahn die Wegabschnitte gleich lange sind, braucht er in seinem Memory nur 0 bzw. 1 für links oder rechts zu speichern

Mir drücken der ENTER-Taste kann der Roboter anschliessend die Bahn selbständig durchfahren, in dem er die gespeicherten Informationen verwendet..

 


# Ro12c.py

from simrobot import *
#from ev3robot import *
#from nxtrobot import *
import time

RobotContext.useObstacle("sprites/bg.gif", 250, 250)  
RobotContext.setStartPosition(310, 480)
RobotContext.showStatusBar(30)

def pressCallback(port):
    global startTime
    global backTime
    global t
    dt = time.clock() - startTime 
    gear.backward(backTime)
    if dt > 2:
        memory.append(0) 
        gear.left(turnTime)  
    else:
        memory.pop()
        memory.append(1) 
        gear.right(2 * turnTime) 
    robot.drawString("Memory: " + str(memory), 0, 1)
    gear.forward()
    startTime = time.clock()      

def run():
    for k in memory:
        robot.drawString("Moving forward",0, 1)
        gear.forward(moveTime)
        if k == 0:
            robot.drawString("Turning left",0, 1)
            gear.left(turnTime)            
        elif k == 1:
            robot.drawString("Turning right",0, 1)
            gear.right(turnTime)            
    gear.forward(moveTime) 
    robot.drawString("All done", 0, 1)          
    isExecuting = False
    
moveTime = 3200
turnTime = 545
backTime = 600
memory = []      
robot = LegoRobot()
gear = Gear()
robot.addPart(gear)
ts = TouchSensor(SensorPort.S3, pressed = pressCallback)      
robot.addPart(ts)
startTime = time.clock()
gear.forward()

while not robot.isEscapeHit():
    if robot.isDownHit():  
        gear.stop()
    elif robot.isEnterHit():
        robot.reset()    
        run()      
robot.exit()
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

Erklärungen zum Programmcode:

dt = time.clock() - startTime : die Zeit zwischen zwei aufeinander folgenden Wandberührungen
if dt > 2 : falls die Zeit zwischen den Berührungen zu kurz ist, war die Drehung nach links falsch. es folgt drehung um 180°, was der Drehung um 90° hach rechts entspricht
memory.pop(): das letzte Element im Memory wird gelöscht

 

Beispiel 4: Touchsensoren und Timer verwenden um einen beliebige Bahn durchzufahren
Der Roboter fährt so lange, bis er mit dem Tousensor das Ende eines Wegstücks registiert. Danach fährt er eine kurze Strecke zurück und fährt die Links- bzw. Rechtsrichtung nach folgender Strategie: zuerst dreht er nach links. Wenn er länger als 2 Sekunden fahren kann, war der Entscheid richtg. Wenn er inner einer kurzen Zeit wieder an einer Wand ankommt, war der Entscheid falsch. Er dreht um 180° und fährt dadurch in die umgekehrte Richtung (rechts). Der Roboter speichert die Links- bzw. Rechtsentscheide im Memory. Die gerade Wegstücke sind in diesem Beispiel immer noch gleich lang.

Danach kann der Roboter mit drücken der ENTER-Taste die Bahn selbständig abfahren.

 

# Ro12d.py

from simrobot import *
#from ev3robot import *
#from nxtrobot import *
import time

RobotContext.useObstacle("sprites/bg2.gif", 250, 250)  
RobotContext.setStartPosition(410, 480)
RobotContext.showStatusBar(30)

def pressCallback(port):
    global startTime
    global backTime
    global turnTime
    global moveTime
    dt = time.clock() - startTime # time since last hit in s
    gear.backward(backTime)
    if dt > 2: 
        moveTime = int(dt * 1000) - backTime  # save long-track time
        node = [moveTime, 0] 
        memory.append(node) # save long-track time 
        gear.left(turnTime) # turning left   
    else:
        memory.pop() # discard node
        node = [moveTime, 1] 
        memory.append(node) 
        gear.right(1090) # turning right
    robot.drawString("Memory: " + str(memory), 0, 1)
    gear.forward()
    startTime = time.clock()      

def run():
    for node in memory:
        moveTime = node[0]
        k = node[1]
        robot.drawString("Moving forward",0, 1)
        gear.forward(moveTime)
        if k == 0:
            robot.drawString("Turning left",0, 1)
            gear.left(turnTime)            
        elif k == 1:
            robot.drawString("Turning right",0, 1)
            gear.right(turnTime)            
    gear.forward() 
    robot.drawString("All done, press DOWN to stop", 0, 1)          
    isExecuting = False
    
turnTime = 545
backTime = 600
     
robot = LegoRobot()
gear = Gear()
robot.addPart(gear)
ts = TouchSensor(SensorPort.S3, pressed = pressCallback)      
robot.addPart(ts)
startTime = time.clock()
moveTime = 0
memory = [] 
gear.forward()

while not robot.isEscapeHit():
    if robot.isDownHit():  
        gear.stop()
    elif robot.isEnterHit():
        robot.reset()    
        run()      
robot.exit()
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

Erklärungen zum Programmcode:

node = [moveTime, 0] : die Liste node besteht aus zwei Werten: 1) Zeit, die der Roboter für einen Weg benötigt 2) 0 für links drehen
memory.append(node) : in die List memory wird jeweils eine Liste mit zwei Werten hinzugefügt

 


Aufgaben: Serie 12

1)

Lerne den Roboter die nebenstehende Bahn durchzufahren, in dem du die Tasten LEFT, RIGHT, UP für vorwärts fahen und DOWN für stopen verwendest.

Der Roboter speichert die Entscheiden links bzw. rechts und die Zeit, die er für die geraden Wege benötigt im Memory.

Für die Simulation kannst du das Hintergrundbild bg3.gif verwenden:

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

 

 

 

2)

Der Roboter soll mit Hilfe eines Colorsensors und eines Timers lernen die nebenstehende Bahn durchzufahren. Anschliessend soll er die Bahn selbständig (ohne die Wände zu berühren durchfahren.

Für die Simulation kannst du das Hintergrundbild colorparcours.png verwenden..

RobottContext.useBackground("sprites/colorparcours.png")
RobotContext.setStartPosition(35, 245)
RobotContext.setStartDirection(0)