Beispiel Lichtfolger
Aufgabenstellung:
Ein
mobiler Roboter mit differenziellem Antrieb soll so programmiert
werden, dass er sich in Richtung einer Lichtquelle bewegt, ohne
mit Hindernissen zu kollidieren. Die Lichtquelle wird mit Hilfe
von zwei lichtempfindlichen Widerständen erkannt. Zwei
Infrarot-Abstandssensoren blicken nach vorne links und vorne
rechts. Die Abstandswerte sollen den Roboter frühzeitig um ein
Hindernis leiten.
Lösungsansatz:
Der mobile
Roboter wird mit vier Regeln ausgerüstet: Die Regel
driveForward lässt ihn stur
geradeaus fahren. Mit der Regel
turn orientiert sich der Roboter in
Richtung der Lichtquelle. Dazu werden linker und rechter
Lichtsensor in
diffLight
durch Sensorfusion zu einem virtuellen Sensor zusammengefasst.
Aus diesem Differenzsignal kann die Richtung zur Lichtquelle
ermittelt werden. Dass der Roboter nicht mit einem Hindernis
kollidiert, ist die Aufgabe der zwei zusätzlichen Regeln
leftObstacle und
rigthtObstacle. Diese
überwachen unabhängig die Werte der Abstandssensoren um die
Geschwindigkeit auf dem gegenüberliegenden Antrieb zu
verringern. Sie sorgen nicht zuverlässig für eine
Kollisionsvermeidung, sondern helfen ledig den Roboter um das
Hindernis herum zu leiten. Koordiniert werden die vier Regeln in
dem für jeden Antrieb die Sollwerte der Regeln aufsummiert
werden. Dieser Lösungsansatz weist Parallelen zum Braitenberg
Vehikel Nummer 3c auf. Es gibt weder den expliziten Zustand
ausweichen noch
sucheLicht, sondern alle
Vorgaben werden kontinuierlich mit einer Vektoraddition
überlagert.
Ausgestattet ist der Roboter mit zwei Paaren von Sensoren. Das
erste Paar sind die zwei lichtempfindliche Widerstände, welche
im Programm mit LdrLeft
und LdrRight bezeichnet
werden, sind vorne seitlich am Chassis angebracht. Bei heller
Beleuchtung liefern diese Sensoren einen kleineren Wert. Aus der
Differenz der Beleuchtungsstärke wird die Richtungskorrektur
abgeleitet. Dies geschieht durch die Sensorfunktion diffLight (Zeile 30) mit Hilfe von
Sensor-Fusion. Das zweite Paar ''Augen'' sind die
Infrarotabstandssensoren. Mit ihnen werden Hindernisse erkannt.
Sie liefern einen höheren Wert, wenn das Hindernis nahe ist.
Angetrieben wird der Roboter von zwei Motoren. In den Regeln
und im Koordinator werden diese nicht direkt angesprochen. Die
Sollwerte werden stattdessen über die self.SpeedLeft und self.SpeedRight Variablen der Regeln
und Koordinatoren verwaltet. Das verhaltensbasierte Programm
verfügt über die vier Regeln driveForward (ab Zeile 46),
turn (ab Zeile 51),
leftObstacle (ab Zeile
63) und rightObstacle (ab
Zeile 71). Koordiniert werden diese Regel von total (ab Zeile 80). Dieser
Koordinator summiert lediglich die Vorgaben der einzelnen
Regeln.
Die Regel turn
arbeitet mit der persistenten Variable angularSpeed. Diese sorgt dafür,
dass die Richtungskorrektur mehr Einfluss bekommt, wenn es über
mehrere Zyklen zu einer Abweichung kommt. Die zwei
Hilfsfunktionen increment
und decrement werden
benötigt um die persistente Variable auf einen sinnvollen
Wertebereich zu begrenzen.
Vehikel Beispielprogramm
1 # Lichtfolger
2 #
3 # Lichtsuche mit Hinderniserkennung.
4 #
5 # Der Roboter besitzt einen differenziellen Antrieb.
6 #
7 # <SpeedLeft>
8 # /-----\\--- LdrLeft <
9 # | |-- IrLeft <
10 # | |-- IrRight <
11 # \\-----/--- LdrRright <
12 # <SpeedRight>
13
14
15 system:
16 # folgende Beschreibung der Aktoren und Sensoren verwenden.
17 configuration ctBot.simpleCtBot
18
19 # Kurskorrektur
20 const maxAngularSpeed = 30
21 const deltaAngularSpeed = 3
22 const hysteresis = 3
23 # Vorwaerts fahren
24 const forwardSpeed = 50
25 # leicht bremsen, wegen Hindernis
26 const breakSpeed = -25
27
28 # Sensor Fusion,
29 # aus zwei realen Lichtsensoren einen virtuellen Richtungssensor berechnen.
30 sensor diffLight :
31 return LdrLeft - LdrRight
32
33 # Inkrementieren mit Obergrenze
34 def increment(var value):
35 if value < +maxAngularSpeed:
36 value = value + deltaAngularSpeed
37 return value
38
39 # Dekrementieren mit Untergrenze
40 def decrement(var value):
41 if value > -maxAngularSpeed:
42 value = value - deltaAngularSpeed
43 return value
44
45 # 1. Regel : vorwaerts fahren
46 rule driveForward:
47 self.SpeedLeft = +forwardSpeed
48 self.SpeedRight = +forwardSpeed
49
50 # 2. Regel : In Richtung des Lichts drehen.
51 rule turn:
52 persistent var angularSpeed = 0
53 if diffLight < -hysteresis:
54 angularSpeed = decrement(angularSpeed)
55 if diffLight > +hysteresis:
56 angularSpeed = increment(angularSpeed)
57 if (diffLight > -hysteresis) and (diffLight < +hysteresis):
58 angularSpeed = 0
59 self.SpeedLeft = +angularSpeed
60 self.SpeedRight = -angularSpeed
61
62 # 3. Regel : links aufpassen
63 rule leftObstacle:
64 if IrLeft > 300:
65 self.SpeedLeft = 0
66 self.SpeedRight = breakSpeed
67 if IrLeft > 450:
68 self.SpeedRight = 2 * breakSpeed
69
70 # 4. Regel : rechts aufpassen
71 rule rigthtObstacle:
72 if IrRight > 300:
73 self.SpeedLeft = breakSpeed
74 self.SpeedRight = 0
75 if IrRight > 450:
76 self.SpeedLeft = 2 * breakSpeed
77
78 # Koordinator fuer das Verhalten Lichtfolger.
79 # Bildet die Summe aller Sollwerte .
80 arbiter total(array rules):
81 self.SpeedLeft = 0
82 self.SpeedRight = 0
83 for r in rules:
84 self.SpeedLeft = self.SpeedLeft + r.SpeedLeft
85 self.SpeedRight = self.SpeedRight + r.SpeedRight
86
87 # Ende