Skip to main content

Codebeispiele

Theo III

Best Practise

Ausschalten der Motoren bei Unterbrechung des Programms

Anfangs wird man sehr viel an dem Roboterprogramm testen müssen. Dabei wird das Programm dann häufig abstürzen. Damit die Motoren nicht weiter in dem Zustand laufen, in dem sie dabei geschaltet waren, kann man mit einem try/excepts arbeiten:

try:
  # Hier läuft das Programm
except Exception as err:
    print(err) # Nötig, um Fehlermeldungen angezeigt zu bekommen.
    r.emergency_stop() # Roboter anhalten, hier ein Beispiel mit der robotlibrary.
    print("Robot stopped") # Damit es ganz deutlich ist.
except KeyboardInterrupt:
    r.emergency_stop()
    print("Keyboard interrupt")

Überschreiben von Methoden aus der Bibliothek

Möchte man die Funktion einer Methode aus der Roboterbibliothek (robotlibrary) verändern, kann man die Methode überschreiben (Fachbegriff aus der objektorientierten Programmierung). Dafür wird die Klasse Robot vererbt, wie in dem Codebeispiel angegeben. Möchte man nun z.B. die Methode set_speed() verändern, dann definiert man sie einfach neu. Ist eine Methode nicht in der abgeleiteten Klasse (in diesem Fall MyRobot definiert, dann wird die Methode der Elternklasse (Robot) genommen. Probiere es aus, in dem du das vorliegende Programm einmal mit und einmal ohne die Definition von set_speed() aufrufst.

from robotlibrary.robot import Robot
from time import sleep, sleep_ms


class MyRobot(Robot):
    def __init__(self):
        super().__init__(False,None)
        print("start")
        
    def set_speed(self,x):
        print(f"Child method set_speed. Value: {x}")
        
def main():
    try:
        robot = MyRobot()
        robot.set_speed(90)
        while True:
            sleep(1)
    except KeyboardInterrupt:
        robot.emergency_stop()
     
if __name__ == "__main__":
    # execute only if run as a script
    main()

Verändern der Funktion der Fernbedienung

Eine Ableitung funktioniert nicht, wenn man die Methode read() verändern möchte, da von der Bibliothek immer die Elternklasse aufgerufen würde. Man kann aber vor der Initialisierung der Klasse Robot eine neue Methode definieren und diese als Parameter übergeben. Hier ist ein Beispiel, wie es geht.

# Example for how to override the read() method that gets input from the remove control.
# Define your own method. 
def my_read(buffer: memoryview):
    print("my_read called.")
    
def main():
    try:
        # Use the name of your method as a parameter when initialising the robot object. 
        r = Robot(True,my_read)
        r.set_speed(100)
        while True:
            sleep(1)
    except KeyboardInterrupt:
        r.emergency_stop()
    
    
if __name__ == "__main__":
    # execute only if run as a script
    main()

Effizienter Code

Auch wenn die Rechenleistung der Picos ausreichen sollte, ergibt es Sinn, sich über Effizienz Gedanken zu machen, da schwer zu erkennen ist, ob manche Probleme durch Überlastung des Prozessors hervorgerufen werden.

while True:
    robot.drive()
    if us.get_dist() > min_distance:
        # stop or turn
        robot.stop()

In diesem Beispiel wird in der Schleife der Befehl drive() mit jedem Durchlauf aufgerufen, was nicht sonderlich effizient ist, da die Motoren weiterfahren, auch wenn das Programm gerade andere Befehle ausführt. Eine bessere Variante wäre diese:

robot.drive()
while us.get_dist() > min_distance:
    pass
robot.turn()

Hier wird nur die Entfernung zum nächsten Hindernis überprüft. Sobald der Roboter zu nahe gekommen ist, wird die Schleife beendet und der Code wird weiter ausgeführt.

Fehlertoleranter Code

Die Sensoren, die wir benutzen, liefern nicht immer zuverlässige und korrekte Ergebnisse. Daher kann man sich nicht darauf verlassen, dass eine Messung ausreicht. Ist man auf genauere Ergebnisse angewiesen, kann es sinnvoll sein, die Ergebnisse von Sensormessungen (insbesondere des Ultraschallsensors) zu filtern. Dazu kann gehören, Extremwerte, die im vorliegenden Fall unwahrscheinlich sind, zu ignorieren oder Mittelwerte von mehreren Messungen zu bilden.

Beschleunigung mit Entfernungsmessung

obstacle_detected = False
new_speed = 100
speed_now = 0
min_distance = 15
while speed_now <= new_speed and not obstacle_detected:
    #Set the speed for the motors, f. ex. motor.set_speed(speed_now)
    utime.sleep_ms(10+int(speed_now/2))
    speed_now += 1
    if us.get_dist() < min_distance: # Adjust the code to your needs. 
        obstacle_detected = True
if obstacle_detected:
    # Stop or turn or whatever
    obstacle_detected = False
else:
    # keep going
    pass