tcp

12. ROBOTER-KOMMUNIKATION ÜBER TCP/IP

 

 

DU LERNST HIER...

 

wie zwei EV3-Roboter miteinander über das WLAN kommunizieren.

 

 

WIE FUNKTIONIERT TCP-KOMMUNIKATION?

 

Zwei EV3-Roboter können einander über das WLAN kurze Meldungen zusenden. Dabei läuft auf einem EV3 ein TCP-Server- und auf dem anderen ein TCP-Client-Programm.

 
 


Unter der Verwendung des Moduls tcpcon aus der TigerJython-Distribution, kannst du mit wenig Aufwand interessante Anwendungen programmieren. Das Server-Programm muss aber immer zuerst gestartet werden. Der Client erstellt danach unter der Verwendung der IP-Adresse des Servers und der Portnummer, welche im Serverprogramm festgelegt ist, eine Verbindung zum Server. Die Verbindung kann über das öffentliche Internet, einen lokalen WLAN-Router oder einen mobiler WLAN-Hotspot deinem Smartphone erfolgen.

Die Kommunikation erfolgt Eventgesteuert. Der Status der Verbindung wird mit der Callbackfunktion onStateChanged(state, msg) überwacht. Diese wird bei der Erzeugung von TCPServers bzw. TCPClients registriert. Beim state TCPClient.MESSAGE() bzw. TCPServer.MESSAGE() wird eine Nachricht empfangen. Mit sendMessage() wir eine Nachricht verschickt.

 

 

MUSTERBEISPIELE

 

Beispiel 1: Client-Robot wird über TCP durch Server-Robot gesteuert
Der Server-Roboter ist mit einem Lichtsensor ausgerüstet. Er bewegt sich auf der weissen Fläche so lange bis er eine schwarze Kante detektiert. Dann hält er an, bewegt sich kurz rückwärts und danach wieder vorwärts. Diese Bewegung führt er so lange aus, bis die Taste Escape gedrückt wird. Bei jeder Zustandsänderung sendet er eine Meldung an den Client-Roboter, der danach die gleichen Bewegungen ausführt, obwohl er keinen Lichtsensor und keine schwarz-weise Unterlage hat.

   
  TCPServer TCPClient

Das Serverprogramm wird zuerst gestartet und der Server wartet danach, bist der Client eine Verbindung zu seiner IP-Adresse erstellt hat. Ist die Verbindung aufgebaut, spielt der Server einen Ton ab und startet die Bewegung.


Programm für den TCP Server:

# TCPServer1.py

from grobot import *
from ev3robot import tcpcom 
#from tcpcom import TCPServer #Simulation mode

def onStateChanged(state, msg):
    global isWaiting
    if state == TCPServer.LISTENING:
        isWaiting = True
    if state == TCPServer.CONNECTED:
        print("Connected")
        playTone(440, 150)
        isWaiting = False 
    if state == TCPServer.MESSAGE:
        if msg == "go":            
            isWaiting = False
   
RobotContext.useBackground("sprites/circle.gif")
port = 5000
server = TCPServer(port, stateChanged = onStateChanged)
isWaiting = True
moveState = "stop"
while not button_escape.was_pressed():
    if isWaiting:
        continue
    v = ls3.getValue()
    if v > 500 and moveState == "stop":
        server.sendMessage("go")
        forward()        
        moveState = "go"
    if v < 500 and moveState == "go":
        server.sendMessage("stop")        
        backward(1500)        
        moveState = "stop"
    delay(100)                    
server.terminate()        
exit()
► In Zwischenablage kopieren

Programm für den TCP Client:
# TCPClient1.py

from grobot import *
from ev3robot import tcpcom 
#from tcpcom import TCPClient #simulation mode

def onStateChanged(state, msg):
    if state == TCPClient.CONNECTED:
        print("connected")
    if state == TCPClient.DISCONNECTED:
        stop()
    if state == TCPClient.MESSAGE:
        if msg == "go":
            forward()
            print("go")
        if msg == "stop":
            stop()
            backward()
            print("stop")      
            
host = "192.168.254.139" #real mode
#host = "localhost" #simulation mode
port = 5000
client = TCPClient(host, port, stateChanged = onStateChanged)
if client.connect():
    while not button_escape.was_pressed():
        pass
        Tools.delay(100)            
client.disconnect()                
exit()
► In Zwischenablage kopieren

In diesem Beispiel spielt die "Zustandsprogrammierung" eine zentrale Rolle. Der Server verschickt die Meldungen "go" bzw. "stop" nur wenn sein Zustand geändert hat, nicht alle 100 ms, gemäss der while-Schleife.

Das Beispiel kann auch im Simulationsmodus ausgeführt werden, indem die Programme für den TCPServer und TCPClient in zwei TigerJython-Fenstern ausgeführt werden. Ändern musst du in beiden Programmen nur die zweite Importzeile und im Client-Programm anstelle der IP-Adresse "localhost" verwenden. Beachte, dass du das Programm in beiden TigerJython-Fenstern mit der Taste "Esc" beenden musst damit die Kommunikation abgebrochen wird.

 

 

Beispiel 2: Train
Die Roboter stellen Züge dar, die sich auf einer runden Bahn bewegen. Ein Teil der Strecke ist nur einspurig befahrbar. Die Roboter teilen einander via TCP mit, wenn sie am Bahnhof angekommen sind und die Bahn frei ist. Das Serverprogramm wird zuerst gestartet. Nach dem Aufbau der Verbindung fährt der Client zuerst seine Runde und hält an der Barriere an, die mit einem zweiten Lichtsensor erkannt wird. Dabei sendet er die Message "go" an den Server. Dann fährt der Server eine Runde und sendet die Message "go" an den Client, sobald er angehalten hat und die Bahn frei ist.


Programm für den TCP Server:

#TcpServer2.py

from grobot import *
from ev3robot import tcpcon
import time

def onStateChanged(state, msg):
    global isWaiting, isStoped, start
    if state == TCPServer.LISTENING:
        stop()
        isWaiting = True
    if state == TCPServer.CONNECTED:
        playTone(260, 100) 
    if state == TCPServer.MESSAGE:
        if msg == "go":
            isWaiting = False
            start = time.time()
            print("run")
    
port = 5000
server = TCPServer(port, stateChanged = onStateChanged)
start = time.time()
isWaiting = True

while not button_escape.was_pressed():
    if isWaiting:
        continue
    v1 = ls1.getValue()
    v2 = ls2.getValue()
    if v2 > 500:  
        rightArc(0.2)
    else: 
        leftArc(0.2)
    if v1 > 300 and v1 < 650 and time.time() - start > 5: 
        server.sendMessage("go")
        print("ok")
        stop()
        isWaiting = True           
    delay(100)                    
server.terminate()        
exit()
► In Zwischenablage kopieren

Programm für den TCP Client:
# TcpClient2.py

from grobot import *
from ev3robot import tcpcon
import time

def onStateChanged(state, msg):
    global isWaiting, start
    if state == TCPClient.CONNECTED:
        print("connected")
    if state == TCPClient.DISCONNECTED:
        stop()
    if state == TCPClient.MESSAGE:
        if msg == "go":
            isWaiting = False 
            start = time.time() 
            print("run")     
            
forward()
host = "192.168.254.139"
port = 5000
client = TCPClient(host, port, stateChanged = onStateChanged)
isWaiting = False
if client.connect():
    start = time.time()
    while not button_escape.was_pressed():
        if isWaiting:
            continue
        v1 = ls1.getValue()
        v2 = ls2.getValue()
        if v1 > 500:  
            rightArc(0.2)
        else: 
            leftArc(0.2) 
        if v2 > 300 and v2 < 650 and time.time() - start > 5: 
            print("ok")
            stop()
            client.sendMessage("go")
            isWaiting = True   
        delay(100)            
    client.disconnect()                
exit()
► In Zwischenablage kopieren

Die Zeitmessung time.time()-start() > 5 ist notwendig, damit der Roboter nach dem die Bahn frei gegeben wurde, in Bewegung gesetzt werden kann. Sonst bleibt er in der Bedingung v2 > 300 and v2 < 600 "hängen". Anstelle des zweiten Lichtsensors könnte auch ein Touchsensor oder ein Colorsensor verwendet werden.



 

MERKE DIR...

 

Die Kommunikation zwischen zwei EV3-Robotern erfolgt unter der Verwendung der Bibliothek tcpcon aus dem Modul ev3robot. Die Kommunikation ist Eventgesteuert aufgebaut. Beim state TcpServer.MESSAGE() bzw. TcpClient.MESSAGE() wird eine Meldung empfangen. Mit dem Befehl sendMessage() können Messages in Form eines Strings vom Server zum Client und umgekehrt verschickt werden.

 

 

ZUM SELBST LÖSEN

 

 

1.
Synchron fahren: Der TcpServer fährt jeweils eine bestimmte Strecken vorwärts und ändert dann zufällig die Fahrtrichtung, indem er eine Drehung nach links mit einem zufällig gewählten Winkel zwischen 0° und 360° durchführt. Vor jeder Drehung sendet er den Drehwinkel auf den Client, der danach genau die gleiche Bewegung nachmacht.