Regeln und Koordination

Prozessabbild


Das Prozessabbild enthält die aktuellen Werte der Sensoren und die Sollwerte für die Aktoren. In einem starren zeitlichen Ablauf werden die Sensorwerte einmalig zu Beginn des Zyklus in das Prozessabbild eingetragen. Das verhaltensbasierte Programm arbeiten mit einer Momentaufnahme der Umwelt. Während eines Durchlaufs durch die Regeln ändern sich zwar die realen Umweltbedingungen, aber im Prozessabbild bleiben die gemessenen Werte innerhalb eines Zyklus konstant. Zum Abschluss des Zyklus werden die Sollwerte in das Prozessabbild geschrieben und von dort auf die Aktoren übertragen

Regeln

Regeln bilden die Grundbausteine für das Verhalten des Roboters. Durch sie werden die Messwerte der Sensoren auf die Aktoren abgebildet. Intern bestehen sie aus arithmetischen Ausdrücken, bedingten Anweisungen und Funktionsaufrufen. Die Regeln lesen die Sensorwerte, führen ihre logischen Entscheidungen und Berechnungen durch und leiten die Sollwerte an die Aktoren weiter. Zur Laufzeit können Regeln nicht geändert werden.

Mehrere Regeln dürfen auf den selben Aktor einwirken. Dabei liefern die Regeln höchstwahrscheinlich widersprüchliche Sollwerte. Eine Regel könnte zum Beispiel in Richtung einer Lichtquelle steuern, während eine Andere die Motoren stoppen will. In einem verhaltensbasierten System ist dies kein fehlerhafter Zustand, sondern der Normalfall. Die Widersprüche werden von den, im nächsten Abschnitt beschriebenen, Koordinatoren ausgeglichen.

Beispiel: Zwei Regeln melden ihre Wünsche für die Motoren an:

# 1. Regel: Anteil für geradeaus fahren
rule driveForward:
    self.SpeedLeft  = 120
    self.SpeedRight = 120

# 2. Regel: Anteil für die Kurve
rule driveCurve:
    if curve > 0:
        self.SpeedLeft  =  0
        self.SpeedRight = -40

 

Koordination

Für die Koordination der unterschiedlichen Vorgaben der Regeln gibt es mehrer Ansätze. Sie unterscheiden sich dadurch wie viel Koordinatoren mitarbeiten und ob diese eher kooperativ oder elitär entscheiden.

Anzahl der Koordinatoren

  • Ein zentraler Koordinator pro Aktor
  • Mehrere dezentrale Koordinatoren. Diese sind jeweils für eine Untermengen der Regeln zuständig.

Strategien für Koordination

  • Kooperative Strategien: Summation oder Mittelwertbildung der beteiligten Regeln, geeignet für kontinuierliche Funktionen
  • Prioritäten: Eine der Regeln setzen sich mit Hilfe ihrer hohen Prioritäten durch. Bezeichnet wird diese Strategie als "winner takes all". Die Regel mit der höchsten Priorität setzt sich alleinig durch.
  • Gewichte: Die Ergebnisse der Regeln werden situationsbedingt gewichtet. Zum Beispiel könnte verbleibende Ladungskapazität des Akkus für die Gewichtung der Regeln eine Rolle spielen.

Welche Koordinationsstrategie gewählt wird, hängt von der Aufgabenstellung ab. Es kann keine ideale Strategie für alle verhaltensbasierte Aufgabenstellungen angeboten werden. Der Koordinator wird deshalb vom Anwender in der Vehikel-Programmiersprache selbst formuliert.

Beispiel: Mittelwertbildung der beteiligten Regeln:

arbiter average(array rules):
    var count = 0
    var left = 0
    var right = 0
    for r in rules:
        left = left + r.SpeedLeft
        right = right + r.SpeedRight
        count = count + 1
    assert count > 0
    self.SpeedLeft  = left / count
    self.SpeedRight = right / count

 

Dezentrale Koordination

Zusätzlich ist es möglich, Koordinatoren, die nur eine Untermenge der Regeln ausgleichen, zu definieren. Die Regeln können gruppiert werden. Pro Regelgruppe wird dann ein Koordinator formuliert. Dieser lokale Koordinator kann nur zwischen den Regeln seiner Gruppe ausgleichen. Sein Ergebnis konkurriert mit den anderen Regelgruppen auf der nächst äußeren Stufe und wird vom dortigen Koordinator ausgeglichen. Das Gesamtsystem besteht dann aus mehreren Regeln, die gruppiert sind und lokal pro Gruppe koordiniert werden. Die einzelnen Koordinatoren müssen nur jeweils eine Strategie implementieren. Regeln und Koordinatoren bleiben dadurch übersichtlich.

Im folgenden Programmbeispiel sind die Regeln inner21 und inner22 zur Gruppe outer2 zusammengefasst. Konflikte zwischen inner21 und inner22 werden vom Koordinator vectorAddition ausgeglichen. Er soll in diesem Beispiel eine kooperative Strategie verfolgen, indem er die Sollwerte der konkurrierenden Regeln mittelt. Die äußeren Regeln sind für ihn nicht sichtbar. Der Koordinator vectorAddition liefert den Wunsch für outer2 nach außen. Dort tritt er in Konkurrenz zu Regel outer1, welche in diesem Beispiel für den Nothalt des Systems zuständig ist. Der Koordinator winnerTakesAll trifft dann, ganz unkooperativ, eine 1 aus n Entscheidung zwischen Normalbetrieb und Nothalt.

rule outer1:
        ....

rule outer2:
    rule inner21:
        ....
    rule inner22:
        ....
    arbiter vectorAddition(array rules):
        ....

arbiter winnerTakesAll(array rules):
        ....

 

Zeit

In dieser Implementierung wird von einer endlichen Bearbeitungszeit für die Regeln und Koordinatoren ausgegangen. Pro Zyklus werden alle aktiven Regeln ausgeführt. Somit liefert jede dieser Regeln ihren Beitrag an die Koordinatoren ab. Dies zieht jedoch die Einschränkung nach sich, dass innerhalb einer Regel oder eines Koordinators keine Konstrukte, die zu einer beliebig langen Rechenzeit führen, erlaubt sind.

Von außen betrachtet laufen die Regeln zeitlich parallel ab und wirken ohne Zeitverzögerung. In einem realen Einprozessorsystem werden die Regeln natürlich sequenziell abgearbeitet. Im Unterschied zum biologischen Vorbild ist es nur möglich, eine Quasiparallelisierung zu erreichen. Die Reihenfolge ist zwar reproduzierbar, aber für den Anwender nicht offensichtlich. Beim Entwurf von Regeln sollte der Programmierer deshalb keine Annahme bezüglich der Reihenfolge ihrer Bearbeitung einzelner Regeln voraussetzen.

 

Verzögerungsglieder

Das ablaufen der Zeit kann mit Verzögerungsgliedern modelliert werden. Der Wert eines Verzögerungsglied wird, nach dem es gestartet wurde, pro Zyklus um eins erniedrigt bis es Null erreicht. Im folgenden Beispiel soll der Roboter über ein Schalter verfügen, um Kollisionen mit der Wand zu erkennen. Wird dieser gedrückt fährt der Roboter blind zurück.

system:
    configuration .....
    delay backward = 20

# Vorwärts bis ''FrontBumper'' eine Kollision meldet
rule drive:
    if FrontBumper:
        backward.trigger()
    else:
        self.SpeedLeft  = 50
        self.SpeedRight = 50

# Blind rückwärts fahren mit Kurve.
rule back:
    if backward > 0:
        self.SpeedLeft  = -10
        self.SpeedRight = -30

# Addition der Sollwerte aus den beiden Regeln
arbiter vectorField(array rules):
    self.SpeedLeft = 0
    self.SpeedRight = 0
    for r in rules:
        self.SpeedLeft = self.SpeedLeft + r.SpeedLeft
        self.SpeedRight = self.SpeedRight + r.SpeedRight
 

 

SourceForge.net Logo  
     
 
Creative Commons License
Text and images are licensed under a Creative Commons License.
 
CC-GNU GPL
This software is licensed under the CC-GNU GPL.


 
     
 
Kandid, a genetic art project InnerWorld, a terrain generator for Blender Vehikel, embodied intelligence for mobile robots