Breve – Simulation von dezentralen Systemen und künstlichem Leben

In einem früheren Artikel habe ich Robocode thematisiert. In einem spielerischen Umfeld wird hier von den Topshots eindrucksvoll gezeigt, zu welchen komplexen Funktionen autonome Agenten fähig sind.
Ein ernsthafteren Ansatz verfolgen Simulationsumgebungen für dezentrale Systeme. Eine davon ist breve. Breve ermöglicht die Simulation von Multi-Agenten Systemen über zelluläre Automaten bis hin zu künstlichem Leben. Dabei unterscheidet breve sich im Ansatz nicht groß von anderen Frameworks, wie z.B. Swarm.
Was breve hervorhebt und was ein Grund ist, warum ich breve hier trotz des Alters vorstellen möchte, ist der auf OpenGL basierende 3D Simulator, der die Agenten und die Umwelt visualisiert. Hinzu kommt eine experimentelle Physik – Engine, die Kollisionen und deren Auswirkungen simulieren kann. Damit ist breve auch zur Robotik – Simulation geeignet. Breve wurde von verschiedenen Universitäten und der US Airforce entwickelt, die letzte veröffentlichte Version datiert auf 2008 und ist für Windows, Linux und Mac Os X zum Download erhältlich.
Programmiert werden die Simulationen wahlweise in Python oder der hauseigenen objektorientierten Programmiersprache steve. Die Entwicklung von steve wurde vor geraumer Zeit eingestellt, weshalb es sich empfiehlt Python zu nutzen, gerade wenn man eigene PlugIns schreiben möchte.
Zwei Jahre sind gerade in der Informatik eine Ewigkeit und im Vergleich zu Swarm gibt es keine aktive Community zu breve. Für Interessierte werde ich hier eine kleine Reihe von Programmierbeispielen veröffentlichen, die sich an den Tutorials auf der Breve Seite orientieren.
Demnach mache ich heute den Anfang mit einem Braitenberg Vehikel.

Kleiner Exkurs:
Braitenberg Vehikel sind nach ihrem Schöpfer Valentino Braitenberg benannt. In seinem Theorem beschrieb Braitenberg die evolutionären Möglichkeiten von den einfachsten möglichen Agenten. Damit gehören die Braitenberg Vehikel zu und sind gleichzeitig die einfachsten verhaltensbasierten künstlichen Intelligenzen.

Ein Braitenberg Vehikel hat zwei Räder, die jeweils von einem Motor angetrieben werden. Die Räder sind auf einer Achse montiert. Zusätzlich besitzt ein Braitenberg Vehikel zwei Sensoren, die jeweils direkt an einen Motor gekoppelt sind. Eine kleine Grafik um das Konzept zu verdeutlichen:
Breitenberg Vehikel

Geht man nun davon aus, dass ein Reiz, z.B. Licht dafür sorgt, dass sich der verbundene Motor schneller dreht, würde dies dazu führen, dass das Vehikel sich vom Licht entfernt. Braitenberg formulierte diese Reaktion als Fluchtinstinkt. In einer komplexen Umgebung mit mehreren Lichtquellen verhalten sich Braitenberg Vehikel so, dass sie den möglichst dunklen Platz aufsuchen. Dies kann z.B. dazu führen dass verschiedene Figuren gefahren werden, wenn keine eindeutige Lösung möglich ist. Dementsprechend sorgt eine Überkreuzschaltung der Sensoren zu den Motoren dazu, dass sich das Braitenberg Vehikel der Lichtquelle annähert ohne sie jemals zu berühren. Soviel zum Exkurs, der die Vehikel nur vereinfacht darstellt. Wer sich tiefergehend mit Braitenberg Vehikeln beschäftigen möchte, sei auf die Original – Schrift verwiesen:
Braitenberg, V. Vehicles: Experiment in synthetic psychology. Cambridge, MA. MIT Press, 1984.

Kommen wir nun zum wirklich spannenden Teil, der Programmierung unseres Vehikel:

Damit breve mit Python programmiert werden kann und man auf Funktionen der breve Engine zugreifen kann, gibt es einiges zu beachten. Zuerst sollte natürlich das breve Modul importiert werden. Danach gibt es eigentlich nur zwei Dinge zu beachten. Eine Simulation besteht immer aus einem Controller und einem Agent. Der Controller initialisiert die Simulation, der Agent bewegt sich in ihr.
Das Grundgerüst für eine Simulation sieht wie folgt aus:

Anmerkung: WordPress frisst leider die Python Einrückung, ich werd mich mal um ein entsprechendes Plugin bemühen.

import breve

class myController( breve.Control ):
def __init__( self ):
breve.Control.__init__( self )
self.agent = myAgent()
print “’simulation started“‘

def iterate( self ):
breve.Control.iterate( self )

class myAgent( breve.Mobile ):
def __init__( self ):
breve.Mobile.__init__( self )
print “’created agent“‘

def iterate( self ):
breve.Control.iterate( self )

myController()


Dabei gilt zu beachten, dass jedes Python Objekt zu breve.object gehören muss, damit es für die Engine „sichtbar“ wird. Eine ausführliche Beschreibung der Python API liegt breve bei.

Auf obigem Beispiel aufbauend hier nun der Rumpf Code für ein Breitenberg Vehikel, wie er in den Demos von breve zu finden ist (BraitenbergTemplate.py).

import breve
class myBraitenbergControl( breve.BraitenbergControl ):

def __init__( self ):
breve.BraitenbergControl.__init__( self )
self.leftSensor = None
self.leftWheel = None
self.light = None
self.rightSensor = None
self.rightWheel = None
self.vehicle = None
myBraitenbergControl.init( self )
def init( self )
self.n = 0
while (self.n < 0):
self.light = breve.createInstances( breve.BraitenbergLight, 1 )
self.light.move( breve.vector( 10, 1, 0 ) )
self.vehicle = breve.createInstances( breve.BraitenbergVehicle, 1 )
self.watch( self.vehicle )

breve.myBraitenbergControl = myBraitenbergControl

# Create an instance of our controller object to initialize the simulation

myBraitenbergControl()

Als erstes braucht unser Vehikel nun Räder:

self.leftWheel = self.vehicle.addWheel( breve.vector( -0.500000, 0, 1.500000 ) )
self.rightWheel = self.vehicle.addWheel( breve.vector( -0.500000, 0, -1.500000 ) )

und Sensoren:

self.rightSensor = self.vehicle.addSensor( breve.vector( 2.000000, 0.400000, -1.500000 ) )
self.leftSensor = self.vehicle.addSensor( breve.vector( 2.000000, 0.400000, 1.500000 ) )

Nicht ganz unwichtig ist nun natürlich der Zusammenschluss von Sensoren und Rädern:

self.leftSensor.link( self.leftWheel )
self.rightSensor.link( self.rightWheel )

Die Stärke der Reaktion, die ein Reiz auslöst wird über setBias gesteuert:

self.leftSensor.setBias( 15 )
self.rightSensor.setBias( 15 )

Je nachdem welche Werte man angibt und ob beide Räder gleich funktionieren oder z.B. in verschiedene Richtungen drehen lässt, kann das Verhalten des Vehikels beeinflusst werden.

self.leftSensor.setBias( 30 )
self.rightSensor.setBias( 15 )

sorgt z.B. für ein Vehikel dass innerhalb der Lichtquellen gefangen ist und einen möglichst kleinen Kreis beschreibt.
Breve beinhaltet unter Demos zwei Varianten, einmal ein Vehikel das versucht dem Licht auszuweichen und eins dass die Nähe sucht.