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/
arbeiten:exceptsexcept
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. Ein Beispiel für die Glättung der Entfernungswerte aus dem Ultraschallsensor:
us = Ultra(16)
dist_values = deque([0,0,0,0,0],5)
while True:
d = us.get_dist()
dist_values.append(d)
d = sum(dist_values)/len(dist_values)
print(f"Entfernung: {d} cm")
Eine andere Methode muss für das Auslesen des Infrarotsensors gefunden werden. Hier könnte man z.B. eine kurze Wartezeit einbauen und dann abfragen, ob der Sensor immer noch denselben Wert liefert wie bei Auslösung der Reaktion.
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