SlideShare a Scribd company logo
1 of 134
Download to read offline
Christian Mocek



      Erweiterung des
  CASE-Werkzeugs DAVE
 um einen Code-Generator
   für LEGO Mindstorms
                   Diplomarbeit



                      7. Mai 2006




Gutachter:                            Universität Dortmund
                                      Lehrstuhl für Software-Technologie
Prof. Dr. Ernst-Erich Doberkat
                                      Baroper Straße 301
Dipl.-Inform. Jörg Pleumann
                                      44227 Dortmund
II
Vorwort
Dass mir die Leidenschaft meiner Kindheit am Ende des Studiums begegnet, hätte ich
mir niemals träumen lassen. Schon als kleines Kind war ich von LEGO, insbesondere
LEGO Technik, begeistert und freue mich auch heute immer wieder, wenn ich mit
meinem Neffen die kleinen bunten Steine zusammensetzen kann. Auf der Suche nach
einem Thema für meine Diplomarbeit stieß ich dann auf eins, welches mich vom ersten
Augenblick an interessierte: Die Steuerung von LEGO Mindstorms-Robotern mit Hil-
fe von Zustandsdiagrammen. Nach einigen Vorgesprächen mit meinem Betreuer sowie
Gutachter Jörg Pleumann und langen Überlegungen - mit zugegeben einigem Zwei-
fel, ob sich dieses Unterfangen überhaupt realisieren lässt - entschied ich mich dafür,
diese Herausforderung anzunehmen. Denn wer hat schon die Möglichkeit, in seiner Di-
plomarbeit mit LEGO spielen zu dürfen? Natürlich von einem rein wissenschaftlichen
Standpunkt betrachtet, versteht sich. So begann eine Zeit unzähliger Stunden Arbeit,
einigen frustrierenden Momenten und vielen Gesprächen über das Thema mit meinem
Betreuer. Doch letztlich haben sich all die Mühen gelohnt, als die ersten Roboter ih-
re Aufgaben mit Hilfe von Zustandsdiagrammen lösten und die letzten Zeilen dieser
Arbeit getippt waren.
   An dieser Stelle bedanke ich mich für die Hilfe all jener Personen, die mich in der
langen Zeit in irgendeiner Weise unterstützt haben diese Arbeit zu erstellen. Zunächst
bedanke ich mich bei meinen Eltern, die immer an mich geglaubt haben und denen
diese Arbeit gewidmet ist. Ganz besonderer Dank gilt zudem Jörg Pleumann, welcher
mir jederzeit verständnisvoll geholfen und meine häufigen Fragen geduldig beantwortet
hat. Insbesondere möchte ich auch Peter Segschneider und seiner Frau Christel sowie
Nina Schilf für ihre Freundschaft und moralischen Unterstützung in der langen Zeit
danken. Ein weiterer Dank gilt meinen Korrekturlesern, die sich eisern auf der Suche
nach Fehlern durch diesen Text gelesen haben.


Herten, im Mai 2006                                                   Christian Mocek
IV
Inhaltsverzeichnis

1 Thema der Arbeit                                                                                                            1
  1.1 Motivation der Arbeit . . . . . . . . . . . . . . . . . . . . . . . . . . . .                                           1
  1.2 Zielsetzung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .                                         3
  1.3 Geplantes Vorgehen . . . . . . . . . . . . . . . . . . . . . . . . . . . . .                                            4

2 Grundbegriffe                                                                                                                 5
  2.1 Zustandsdiagramme . . . . . . . . . . . . . . . . . . . . .                             .   .   .   .   .   .   .   .    5
      2.1.1 Elemente und Semantik von Zustandsdiagrammen                                      .   .   .   .   .   .   .   .    5
      2.1.2 Implementierungsansätze . . . . . . . . . . . . . .                               .   .   .   .   .   .   .   .   11
  2.2 LEGO Mindstorms Roboter . . . . . . . . . . . . . . . . .                               .   .   .   .   .   .   .   .   14
      2.2.1 Aufbau der Hardware . . . . . . . . . . . . . . . .                               .   .   .   .   .   .   .   .   14
      2.2.2 Programmierung der LEGO-Roboter . . . . . . . .                                   .   .   .   .   .   .   .   .   15

3 Lösungsansatz                                                                                                               17
  3.1 Zielplattform . . . . . . . . . . . . . . . . . . . .               .   .   .   .   .   .   .   .   .   .   .   .   .   17
  3.2 Ansatzpunkte zur Integration in DAVE . . . . .                      .   .   .   .   .   .   .   .   .   .   .   .   .   18
      3.2.1 Die Simulationsmaschine . . . . . . . . . .                   .   .   .   .   .   .   .   .   .   .   .   .   .   18
      3.2.2 Wahl der zu verwendenden Datenstruktur                        .   .   .   .   .   .   .   .   .   .   .   .   .   19
  3.3 Implementierung . . . . . . . . . . . . . . . . . .                 .   .   .   .   .   .   .   .   .   .   .   .   .   19
  3.4 Gesamtaufbau . . . . . . . . . . . . . . . . . . . .                .   .   .   .   .   .   .   .   .   .   .   .   .   19

4 Das Statechart-Framework                                                                                                    21
  4.1 Konzeptioneller Aufbau . . . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   21
      4.1.1 Zeitgesteuerte Transitionen . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   22
      4.1.2 Segmentierte Transitionen . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   23
      4.1.3 Hierarchie und Nebenläufigkeit         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   25
  4.2 Implementierung . . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   29
      4.2.1 Speicherplatzoptimierungen . .        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   31
      4.2.2 Berechnung des LCA . . . . . .        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   32
      4.2.3 Verwendung des Frameworks .           .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   33
  4.3 Unittests . . . . . . . . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   35

5 Integration der RCX-Elemente in Zustandsdiagramme                                                                           41
  5.1 Startsymbol . . . . . . . . . . . . . . . . . . . . . .                 .   .   .   .   .   .   .   .   .   .   .   .   41
  5.2 Grundregeln . . . . . . . . . . . . . . . . . . . . . .                 .   .   .   .   .   .   .   .   .   .   .   .   42
  5.3 Initialisieren der Sensoren . . . . . . . . . . . . . .                 .   .   .   .   .   .   .   .   .   .   .   .   43
  5.4 Verarbeiten eines Ereignisses . . . . . . . . . . . .                   .   .   .   .   .   .   .   .   .   .   .   .   44
  5.5 Aktionen und Bedingungen . . . . . . . . . . . . .                      .   .   .   .   .   .   .   .   .   .   .   .   44
Inhaltsverzeichnis
 VI


           5.5.1   Ausgänge .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   44
           5.5.2   Sensoren . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   45
           5.5.3   Variablen .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   46
           5.5.4   LC-Display     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   47

6 Steuerung des RCX mit Hilfe des Frameworks                                                                                                              49
  6.1 Ausgänge . . . . . . . . . . . . . . . . . . .                                      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   49
      6.1.1 Aktionen . . . . . . . . . . . . . . .                                        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   50
      6.1.2 Bedingungen . . . . . . . . . . . . .                                         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   50
  6.2 Sensoren . . . . . . . . . . . . . . . . . . . .                                    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   51
      6.2.1 Notwendige Optimierungen . . . . .                                            .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   51
      6.2.2 Ereignisse . . . . . . . . . . . . . . .                                      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   53
      6.2.3 Aktionen und Bedingungen . . . . .                                            .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   53
  6.3 Variablen und einfache Arithmetik . . . . .                                         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   54

7 Codegenerierung                                                                                                                                         57
  7.1 Das XML-Format von DAVE . . . . . . . . . . .                                                   .   .   .   .   .   .   .   .   .   .   .   .   .   57
  7.2 Verarbeitung der XML-Datei . . . . . . . . . . .                                                .   .   .   .   .   .   .   .   .   .   .   .   .   59
      7.2.1 Implementierung in Java . . . . . . . . . .                                               .   .   .   .   .   .   .   .   .   .   .   .   .   59
      7.2.2 Freemarker . . . . . . . . . . . . . . . . .                                              .   .   .   .   .   .   .   .   .   .   .   .   .   59
      7.2.3 Transformationen mittels XSL und XPath                                                    .   .   .   .   .   .   .   .   .   .   .   .   .   60
  7.3 Die Codegenerierung im Detail . . . . . . . . . .                                               .   .   .   .   .   .   .   .   .   .   .   .   .   62
      7.3.1 Umsetzung mittels XSLT . . . . . . . . .                                                  .   .   .   .   .   .   .   .   .   .   .   .   .   62
      7.3.2 Interpretieren der EBNF-Regeln . . . . .                                                  .   .   .   .   .   .   .   .   .   .   .   .   .   65
      7.3.3 Aktivieren und Deaktivieren der Sensoren                                                  .   .   .   .   .   .   .   .   .   .   .   .   .   66
      7.3.4 Aufbau des Zustandsdiagramms . . . . . .                                                  .   .   .   .   .   .   .   .   .   .   .   .   .   68
      7.3.5 Aktionen und Bedingungen . . . . . . . .                                                  .   .   .   .   .   .   .   .   .   .   .   .   .   73

8 Anbindung an DAVE mittels Ant                                                                                                                           75

9 Anwendungsbeispiele                                                                                                                                     79
  9.1 Aufgaben für die LEGO-Testunterlage                                     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   79
      9.1.1 Aufgabe 1 . . . . . . . . . . . .                                 .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   79
      9.1.2 Aufgabe 2 . . . . . . . . . . . .                                 .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   81
      9.1.3 Aufgabe 3 . . . . . . . . . . . .                                 .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   82
  9.2 Eine Sortieranlage für LEGO-Steine .                                    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   83
      9.2.1 Aufgabe 4 . . . . . . . . . . . .                                 .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   83
      9.2.2 Aufgabe 5 . . . . . . . . . . . .                                 .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   86
      9.2.3 Aufgabe 6 . . . . . . . . . . . .                                 .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   87

10 Fazit                                                                                                                                                  89

11 Ausblick                                                                                                                                               91
Inhaltsverzeichnis                                  VII


A Testfälle                                                                                                                93
  A.1 Einfache Elemente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .                                        93
  A.2 Hierarchische Zustände . . . . . . . . . . . . . . . . . . . . . . . . . . . .                                       94
  A.3 Nebenläufige Zustände . . . . . . . . . . . . . . . . . . . . . . . . . . . .                                         96

B Baupläne                                                                                                                101
  B.1 Ein mobiler Roboter für die Testunterlage       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   101
      B.1.1 Linker Motorblock . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   101
      B.1.2 Rechter Motorblock . . . . . . . .        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   104
      B.1.3 Zusammenbau der Komponenten .             .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   106
  B.2 Eine Sortiermaschine für LEGO-Steine . .        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   110
      B.2.1 Klappe . . . . . . . . . . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   110
      B.2.2 Förderband . . . . . . . . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   111
      B.2.3 Unterbau . . . . . . . . . . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   113
      B.2.4 Zusammenbau der Komponenten .             .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   119
      B.2.5 Kiste . . . . . . . . . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   122
Inhaltsverzeichnis
VIII
Abbildungsverzeichnis

 1.1    Das CASE-Werkzeug DAVE . . . . . . . . . . . . . . . . . . . . . . . . .             2
 1.2    Verwendung von Zustandsdiagrammen in eingebetteten Systemen . . . .                  3

 2.1    Umsetzung eines endlichen Automaten in prozeduralen Quelltext . . .              . 12
 2.2    Umsetzung des Beispielautomaten mit Hilfe des State-Patterns . . . .             . 13
 2.3    Beispiel der Abbildung von Hierarchie und Nebenläufigkeit in die Klas-
        senhierarchie objektorientierter Sprachen auf Basis des State-Patterns           . 13
 2.4    Klassendiagramm des FSM-Frameworks von Bosch und van Gurp . . .                  . 14
 2.5    Der RCX-Baustein . . . . . . . . . . . . . . . . . . . . . . . . . . . . .       . 15

 3.1    Aufbau des Gesamtkonzepts . . . . . . . . . . . . . . . . . . . . . . . . . 20

 4.1    Konzeptioneller Aufbau des Frameworks ohne Berücksichtigung hierar-
        chischer und nebenläufiger Zustände . . . . . . . . . . . . . . . . . . .         . 22
 4.2    Erweiterung der Klassen State und Transition für zeitgesteuerte Tran-
        sitionen, sowie Einführung der Klasse PseudoState . . . . . . . . . . .          .   23
        Verarbeitung segmentierter Transitionen für den Fall x = 0 . . . . . .
 4.3                                                                                     .   24
 4.4    Ereignisverarbeitung auf dem Oder-Zustand . . . . . . . . . . . . . . .          .   25
 4.5    Transitionsverhalten bei hierarchischen Zuständen . . . . . . . . . . .          .   26
 4.6    Erweiterung des Frameworks um Hierarchie . . . . . . . . . . . . . . .           .   27
 4.7    Ablauf der execute-Methode einer Transition . . . . . . . . . . . . . .          .   28
 4.8    Erweiterung des Frameworks um Nebenläufigkeit . . . . . . . . . . . .             .   29
 4.9    Klassendiagramm der Implementierung des Frameworks . . . . . . . .               .   30
 4.10   Beispieldiagramm für die Umsetzung in den Quelltext . . . . . . . . .            .   35
 4.11   Klassendiagramm zur Implementierung der Testfälle . . . . . . . . . .            .   37
 4.12   Beschreibung des Pfads, welcher beim Durchlauf durch das Diagramm
        zurückgelegt wird . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .    . 38
 4.13   Beispieldiagramm für einen Testfall . . . . . . . . . . . . . . . . . . . .      . 39
 4.14   Ablauf eines Testfalls . . . . . . . . . . . . . . . . . . . . . . . . . . . .   . 40

 5.1    Beispieldiagramm zur Verwendung der spezifizierten Syntax . . . . . . . 47

 6.1    Framework-Erweiterung zur Steuerung der Ausgänge des RCX . . . . . 50
 6.2    Framework-Erweiterung zur Steuerung der Sensoren des RCX . . . . . . 52
 6.3    Framework-Erweiterung zum Rechnen mit dem RCX . . . . . . . . . . . 55

 8.1    DAVE nach der Integration und Ausführung des Ant-Skripts . . . . . . 78

 9.1    LEGO-Testunterlage für den Lichtsensor . . . . . . . . . . . . . . . . . . 79
Abbildungsverzeichnis
X


    9.2    Modell des Roboters für die Testunterlage . . . . . . . . . . .     .   .   .   .   .   .   80
    9.3    Ablauf einer einfachen Rundfahrt auf der Testunterlage . . .        .   .   .   .   .   .   80
    9.4    Modifizierte Testunterlage . . . . . . . . . . . . . . . . . . . .   .   .   .   .   .   .   81
    9.5    Ablauf einer Rundfahrt auf der modifizierten Testunterlage .         .   .   .   .   .   .   81
    9.6    Zählen der grünen Blöcke auf der Testunterlage . . . . . . . .      .   .   .   .   .   .   82
    9.7    Zustandsdiagramm für Aufgabe 3 . . . . . . . . . . . . . . . .      .   .   .   .   .   .   83
    9.8    LEGO-Modell der Sortieranlage für LEGO-Steine. . . . . . .          .   .   .   .   .   .   84
    9.9    Konzept einer einfachen Sortieranlage für LEGO-Steine . . .         .   .   .   .   .   .   84
    9.10   Aufbau des Rotationssensors . . . . . . . . . . . . . . . . . .     .   .   .   .   .   .   85
    9.11   Sortieren verschiedener LEGO-Steine anhand ihrer Farbe . .          .   .   .   .   .   .   86
    9.12   Erweiterung des bisherigen Sortierers . . . . . . . . . . . . . .   .   .   .   .   .   .   87
    9.13   Sequenzielles Füllen der Kisten mit Hilfe der Sortiermaschine       .   .   .   .   .   .   88
Kapitel 1


Thema der Arbeit
Da die Anforderungen an heutige Softwaresysteme immer weiter ansteigen, wird auch
deren Entwicklung immer komplexer und kostspieliger. Um den Überblick über Struk-
turen und Abläufe in dem System behalten zu können, ist deren Dokumentation schon
in der Planungsphase enorm wichtig. Denn zum einen erleichtert dies anderen Ent-
wicklern sich einzuarbeiten und zum anderen können durch solch eine Dokumentation
frühzeitig Designfehler oder -mängel entdeckt werden. Die Abstraktionsebene reicht
von der allgemeinen Beschreibung von Anwendungsfällen bis hin zur konkreten Im-
plementierung und Beschreibung von Objektverhalten. Ein hierbei immer wichtiger
gewordenes Hilfsmittel ist die von der Object Management Group eingeführte Unified
Modelling Language (OMG, 2003). Aus diesem Grund ist es daher unerlässlich, die
Studenten im Rahmen von Übungen und Projektarbeiten an die Modellierung von
Software mittels UML heranzuführen.
   Da jedoch die normalen Modellierungstools für die Lehre aufgrund ihrer Komplexi-
tät und des hohen Preises ungeeignet sind, wurden im Rahmen des MuSoft-Projektes
(Doberkat und Engels, 2002) mehrere Werkzeuge entwickelt, welche im Funktions-
umfang explizit auf die Lehre ausgelegt sind. Eines dieser Programme ist der an der
Dortmunder Universität entstandene Dortmunder Automatenvisualisierer und -editor
(Pleumann, 2003). DAVE (siehe Abbildung 1.1) beschränkt sich auf die Modellierung
und Simulation von Zustandsdiagrammen1 - einer Verallgemeinerung von endlichen
Automaten, die unter anderem um Hierarchie und Nebenläufigkeit erweitert wurden.


1.1 Motivation der Arbeit
Das Ziel von DAVE ist das anschauliche Vermitteln der Syntax und Semantik von
Zustandsdiagrammen. Hierbei ist eine wesentliche Komponente die Simulation: Die
Studenten sind in der Lage, ihre Modelle auszuführen und somit deren Laufzeitver-
halten zu beobachten. Um einen besseren Bezug zwischen der abstrakten graphischen
Notation und dem Objekt, dessen Verhalten beschrieben wird, herzustellen, unter-
stützt DAVE die Simulation zusätzlich durch multimediale Animationen (zum Bei-
spiel eine Waschmaschine). Aufgrund dieses Bezugs von etwas Abstraktem zu et-
1 Essei angemerkt, dass sich DAVE auf die in der UML-Spezifikation beschriebene Syntax und
  Semantik bezieht (OMG, 2003). Diese unterscheidet sich etwas von der von Harel beschriebenen
  (Harel, 1987). Die wesentlichen Konzepte sind jedoch gleich.
1. Thema der Arbeit
  2




                      Abbildung 1.1.: Das CASE-Werkzeug DAVE



was Anschaulichem kann den Studenten der Nutzen und die Semantik von UML-
Zustandsdiagrammen besser vermittelt werden. Eine genaue Beschreibung des Werk-
zeugs findet sich in (Pleumann, 2004). Umfangreiche Untersuchungen haben gezeigt,
dass DAVE, und damit auch dessen didaktisches Konzept, von den Studenten mehr-
heitlich positiv aufgenommen wurde (Kamphans u. a., 2004).
   In der Realität werden Zustandsdiagramme oft im Bereich eingebetteter Systeme zur
Spezifikation und Verifikation des Systemverhaltens verwendet (siehe Abbildung 1.2),
da sich Fehler nachträglich nicht oder nur zu hohen Kosten korrigieren lassen. Anima-
tionen können also dazu genutzt werden, die real existierenden eingebetteten Systeme
nachzuahmen, zu testen und im Rahmen der Lehre den Studierenden Aufgaben zu
stellen, die an lebensnahe Anforderungen angelehnt sind.
   Letztlich ist diese Art der Visualisierung aber auch nur ein Versuch, die Kluft zwi-
schen der abstrakten Notation von Zustandsdiagrammen und der Realität zu überwin-
den, um das Lernen zu erleichtern. Daher stellt sich die Frage, ob es nicht möglich ist,
den Studenten ein reales eingebettetes System zur Verfügung zu stellen, an dem sie die
praktische Anwendung von Zustandsdiagrammen trainieren können. Ein kostengünsti-
ger Ansatz ist die Verwendung des Mindstorms Robotics Invention System 2.0 (LEGO,
2005), welches von der Firma LEGO im Rahmen ihrer Produktreihe LEGO Technik
eingeführt wurde. Dieses System verfügt über einen programmierbaren Baustein und
kann dazu genutzt werden einfache Roboter zu bauen. Die Programmierung erfolgt
über eine proprietäre graphische Sprache, welche für Kinder ausgelegt ist. Alterna-
1.2. Zielsetzung       3




  (a)   Zwei Sensoren tasten den Boden ab und (b) Das zugehörige Zustandsdiagramm des
        melden dem Roboter, wenn die Fahrbahn     Roboters. Die beiden Motoren reagieren
                     erfasst wird                auf die Farbe des Untergrunds, welche die
                                                             Sensoren melden

         Abbildung 1.2.: Beispiel für die Verwendung von Zustandsdiagrammen in
         eingebetteten Systemen: Die Aufgabe besteht darin, dass ein Roboter einem
                                  vorgegebenen Weg folgt



tiven, welche eine klassische Programmierung zulassen, finden sich im Open-Source-
Bereich und haben als Zielgruppe Programmierer, die eine vollständige Kontrolle über
den Baustein erhalten wollen.
   Neben der praktischen Anwendung bietet das System einen für die Lehre sehr wich-
tigen Zusatzfaktor, nämlich die Steigerung der Lernmotivation. Die LEGO-Roboter
fügen eine spielerische Komponente zu den Lernaufgaben hinzu. Durch jene und die
Möglichkeit, dass die Studenten selbst etwas kreieren können, kann die intrinsische
Motivation gesteigert werden. Bei den Lernenden erhöht sich durch Neugier, Spaß und
Interesse die Motivation, die Übungen zu erledigen (Heidelberg, 2000). Ein weiterer
Vorteil ist die Förderung der Gruppenarbeit: Es können Aufgaben gestellt werden, die
vom Umfang her komplex sind und in Gruppen gelöst werden müssen. Ein Beispiel
hierfür ist die Realisierung eines Hochregallagers in einer Fallstudie an der Universi-
tät Paderborn. Die dort gemachten Erfahrungen zeigen, dass der Einsatz der LEGO-
Roboter von den Studenten mehrheitlich positiv aufgenommen wurde (Magenheim
und Scheel, 2004).


1.2 Zielsetzung
Da die LEGO-Roboter didaktisch erfolgreich eingesetzt wurden, sie ein einfaches ein-
gebettetes System sind und die Verbindung zu Zustandsdiagrammen naheliegend ist,
bietet es sich an Mindstorms in der Lehre einzusetzen und in ein didaktisches Werkzeug
zu integrieren. Aufgrund der Tatsache, dass die Syntax und Semantik von Zustandsdia-
grammen und nicht die Programmierung von LEGO-Robotern im Vordergrund stehen
soll, muss nach einer Lösung gesucht werden, die es ermöglicht die Programmierung
1. Thema der Arbeit
  4


vollkommen transparent zu gestalten. Die vorliegende Diplomarbeit behandelt die Inte-
gration der LEGO-Roboter in das didaktische Werkzeug DAVE unter Berücksichtigung
eben genannter Prämisse. Die Studenten sollen in der Lage sein, ihre Zustandsdiagram-
me in DAVE zu modellieren und über diese das Verhalten der Roboter zu spezifizieren.
   Um eine höchstmögliche Akzeptanz seitens der Studenten zu erreichen, ist es eben-
falls erforderlich, dass die Syntax zur Steuerung der Roboter-Elemente sehr einfach zu
erlernen ist und sich problemlos in die Notation von Zustandsdiagrammen integrieren
lässt. Der zusätzliche Lernaufwand muss also möglichst minimal sein.
   Bei näherer Betrachtung lässt sich erkennen, dass aus den in DAVE gegebenen Infor-
mationen über das modellierte Zustandsdiagramm ein Quellcode generiert und kom-
piliert werden muss, welcher als ausführbares Programm in den Roboter eingeladen
werden kann. Um dieses Ziel zu erreichen, müssen im Rahmen der Diplomarbeit die
folgenden Fragen geklärt werden:
  • Welche Elemente von Zustandsdiagrammen sollen unterstützt werden?

  • In welcher Relation stehen die gewählten Elemente von Zustandsdiagrammen zu
    den elektro-mechanischen Bauteilen der LEGO-Roboter und wie lässt sich diese
    Relation im Diagramm darstellen?
  • Wie können Zustandsdiagramme und deren Semantik in Quellcode abgebildet
    werden?
  • Welche Daten stellt DAVE zur Verfügung und wie können diese verarbeitet wer-
    den, um daraus den benötigten Quellcode zu generieren?


1.3 Geplantes Vorgehen
Die Arbeit gliedert sich in drei Teile. Im ersten Teil werden die notwendigen Grundbe-
griffe zum Thema Zustandsdiagramme und dem LEGO Mindstorms Invention System
aufgearbeitet, damit eine Integration von LEGO in DAVE geplant und umgesetzt wer-
den kann. Anschließend werden im zweiten Teil die Konzepte und deren Umsetzung
erläutert. Kapitel 3 beschreibt das gewählte Gesamtkonzept der Kopplung beider Wel-
ten. Auf dem gewählten Ansatz aufbauend werden in den darauf folgenden Kapiteln
4 bis 8 die einzelnen Teile des Konzepts und deren Umsetzung behandelt. In Kapitel
9 des dritten Teils werden exemplarisch einige praktische Aufgaben für den Übungs-
betrieb vorgestellt. Zum Abschluss der Arbeit werden rückblickend die Ergebnisse
zusammengefasst und ein Ausblick auf mögliche Erweiterungen gegeben.
Kapitel 2


Grundbegriffe
Wie im vorherigen Abschnitt bemerkt wurde, ist es notwendig einige Grundbegriffe
aufzuarbeiten, ohne die die notwendigen Designentscheidungen zur Realisierung der
Aufgabe nicht getroffen werden können. Dieses Kapitel ist in zwei Teile aufgeteilt, wel-
che die wichtigen Themengebiete behandeln. In Abschnitt 2.1 wird näher auf die für
die Arbeit relevanten Elemente von Zustandsdiagrammen eingegangen und es werden
verschiedene Ansätze zu deren Implementierung vorgestellt. Abschnitt 2.2 widmet sich
dem LEGO Mindstorms Robotics Invention System und geht zunächst auf die techni-
schen Details der Hardware ein, bevor verschiedene Möglichkeiten der Programmierung
vorgestellt werden.


2.1 Zustandsdiagramme
Zustandsdiagramme wurden erstmals 1987 von David Harel erwähnt und basieren auf
einer Verallgemeinerung der Konzepte von endlichen Automaten (Harel, 1987). Sie
können als gerichtete Graphen angesehen werden, die das Verhalten eines Objekts be-
schreiben und komplementär zu Sequenz- und Kollaborationsdiagrammen sind, welche
die Interaktion verschiedener Objekte darstellen. Die beiden wesentlichen Erweiterun-
gen seitens Harel waren die Einführung von Hierarchie und Nebenläufigkeit, auf die
im weiteren Verlauf noch eingegangen wird. Von der OMG wurden die vorgestellten
Konzepte aufgegriffen und für die Verwendung in der UML leicht modifiziert.
   Im Folgenden werden die Elemente und deren Semantik behandelt, wie sie in der
Version 1.5, einer Untermenge der aktuellen Version 2.0, der UML-Spezifikation (OMG,
2003) aufgeführt sind und für die eine Unterstützung in DAVE und LEGO Mindstorms
vorgesehen ist. Eine genauere Beschreibung findet sich in (Hitz und Kappel, 2003).

2.1.1 Elemente und Semantik von Zustandsdiagrammen
Zustände und Aktionen
Aufgrund der Graphenstruktur besitzen die Diagramme Knoten und (gerichtete) Kan-
ten. Die Knoten repräsentieren die Zustände, die das Objekt einnehmen kann, während
die Kanten Zustandswechsel, die so genannten Transitionen, darstellen. Zustände wer-
den im Diagramm durch Rechtecke mit gerundeten Ecken dargestellt und können mit
2. Grundbegriffe
  6


einem, den Zustand beschreibenden, Namen und Aktionen versehen werden. Hierbei
werden im Rahmen der Diplomarbeit zwei Typen von Zustandsaktionen unterschie-
den: Die entry-Aktion wird ausgeführt, sobald der Zustand aktiviert, d. h. erreicht
wird. Analog hierzu existiert die exit-Aktion, welche beim Verlassen des Zustands
ausgeführt wird. Zusätzlich existiert noch die do-Aktion, die nach der entry-Aktion
ausgeführt wird, während der Zustand aktiv ist. Für diese ist keine Unterstützung
vorgesehen. Sie wird an dieser Stelle nur der Vollständigkeit halber aufgeführt. Die
Aktionen haben keine spezielle Form und können im Prinzip beliebiger Natur sein.
Sprich es ist möglich, Pseudocode ebenso zu verwenden wie konkrete Methodenaufru-
fe in einer Programmiersprache oder Ausgaben von „Ereignissen“.
                       Neben den normalen Zuständen beschreibt die UML noch eine
                    weitere Art von Zustandstypen, die so genannten Pseudozustände.
                    Sie dienen einzig der Modellierung und sind keine echten Zustände
                    des Objekts. Daher kann ihnen keine Aktion zugeordnet werden
                    bzw. das Objekt in ihnen verweilen.
                       Damit bekannt ist, welcher Zustand bei Beginn der Bearbeitung
                    aktiviert werden muss, wird dem Diagramm ein Pseudozustand,
                    der so genannte Startzustand zugewiesen. Für diesen gilt, dass von
                    ihm nur Transitionen abgehen dürfen. Analog zum Startzustand
existiert der Endzustand. Dieser ist ein normaler Zustand, der jedoch keine Aktionen
beinhalten kann. Für diesen gilt, dass keine Transition den Zustand verlassen darf.

Zustandsübergänge
Ereignisse Der Wechsel zwischen zwei Zuständen wird in der Regel über ein Er-
eignis angestoßen. Dies ist laut OMG (2003) „das Ergebnis einer beliebigen Aktion
innerhalb des Systems oder in der das System umfassenden Umgebung“. Obwohl die
Form eines Ereignisses nicht explizit festgelegt ist, unterscheidet die UML zwischen
vier verschiedenen Ereignistypen, von denen hier nur die beiden für die Arbeit rele-
vanten erwähnt werden sollen: Das SignalEvent umfasst den zuletzt genannten Fall,
dass das Ereignis durch eine Aktion außerhalb des Systems generiert wurde, während
das TimeEvent auf einer Aktion innerhalb des Systems beruht. Ereignisse werden nur
vom jeweils aktuell aktiven Zustand verarbeitet.
   Gehen von einem Zustand nur mit Ereignissen markierte Transitionen ab, so ver-
weilt das Objekt so lange in dem Zustand, bis ein Ereignis auftritt, welches einen
Zustandsübergang auslöst. Ereignisse, welche im aktuellen Zustand keiner Transition
zugeordnet sind, gehen verloren. Für Übergänge ohne Ereignismarkierung gilt die Be-
endigung aller Aktionen des Zustands als Trigger. Tritt ein Ereignis auf, wird die
derzeit aktive Aktion sofort unterbrochen und der Zustand verlassen.
Bedingungen und Aktionen Neben einem
Ereignis kann einer Transition eine Bedingung und
eine Aktion zugeordnet werden. Erstere wird mit-
tels der Schreibweise [y] und letztere durch /z an
der Transition kenntlich gemacht. Bedingungen sorgen dafür, dass das Schalten nur
dann möglich ist, wenn diese erfüllt ist. So lässt sich beispielsweise verschiedenen Tran-
2.1. Zustandsdiagramme         7


sitionen eines Zustands dasselbe Ereignis zuordnen. Abhängig von den Bedingungen
können aber unterschiedliche Aktionen ausgeführt oder verschiedene Zielzustände er-
reicht werden.
   Prinzipiell ist es bei Zustandsübergängen allerdings möglich, ein nichtdeterminis-
tisches Zustandsdiagramm zu modellieren, in welchem mehrere Transitionen gleichzei-
tig schalten können. In diesem Fall wird seitens der UML-Spezifikation keine genaue
Semantik vorgegeben. Somit bleibt es frei zu entscheiden, welche der Transitionen
schalten kann. Für die Markierung von Zustandsübergängen ergibt sich als Schreib-
weise also Ereignis[Bedingung]/Aktion.
                             Zeitgesteuerte Transitionen Durch das Schlüsselwort
                             after (x) wird das TimeEvent gekennzeichnet. Dieses defi-
                             niert einen bestimmten Typ Zustandsübergang, die zeitge-
                             steuerte Transition. Nach Ablauf der konstanten Zeitspan-
ne x wird ein Ereignis getriggert, sodass die Transition bei erfüllter Bedingung schalten
kann. Als zeitlicher Bezug wird bei diesem Ereignistyp der Zeitpunkt des Eintritts in
den aktuellen Zustand angenommen.
Segmentierte Transitionen Ein weiterer Aspekt von Zu-
standsdiagrammen sind die so genannten segmentierten Tran-
sitionen. Mit ihnen ist es möglich, mehrere Zustandsübergänge
miteinander zu verketten, um beispielsweise zu erreichen, dass
in jeder Teiltransition eine Aktion ausgeführt wird. Ebenfalls
bieten sie die Möglichkeit, Verzweigungen zu modellieren. Die
Verknüpfung segmentierter Transitionen wird im Diagramm
durch einen Pseudozustand in Form eines schwarzen Kreises
dargestellt, der Verbindungsstelle.
   Eine segmentierte Transition ist immer atomar, d. h. sie schaltet entweder ganz
oder gar nicht. Vor dem Zustandsübergang muss von der segmentierten Transition
geprüft werden, ob es einen Weg zum nächsten Zustand gibt. Doch es gibt noch eine
weitere Besonderheit, die berücksichtigt werden muss: Nur dem ersten Segment der
Transition darf ein Ereignis zugewiesen werden, während alle Segmente Bedingungen
und Aktionen halten können.

Hierarchische Zustände
In komplexen Systemen ist es häufig notwendig, Sachverhalte zunächst zu abstrahieren
und deren tatsächliche Arbeitsweise in einem nachfolgenden Schritt genauer zu mo-
dellieren. Zustandsdiagramme bieten die Bildung von Zustandshierarchien an. Diese
Oder-Verfeinerung ermöglicht es, einen komplexen Zustand in Unterzustände zu zer-
legen, die den Sachverhalt genau beschreiben. Sobald das Objekt diesen Oder-Zustand
erreicht, befindet es sich automatisch immer in genau einem Unterzustand der Verfei-
nerung. Durch diese Schachtelung treten neue Besonderheiten auf, die im Folgenden
behandelt werden.
Start- und Endzustände Innerhalb einer Oder-Verfeinerung muss bekannt sein,
welcher Unterzustand bei Erreichen aktiviert wird bzw. wann der Zustand beendet
2. Grundbegriffe
  8


ist. Diese Information wird, genau wie beim Diagramm selbst, mittels eines Start-
und Endzustands dargestellt. Das Vorhandensein dieser Zustände ist allerdings nicht
immer notwendig. Warum dies so ist, wird im nächsten Abschnitt deutlich.
Betreten und Verlassen des Zustands Es lassen sich zwei Arten unterscheiden,
wie ein komplexer Zustand aktiviert werden kann:

  1. Eine ankommende Transition endet direkt am Oder-Zustand. In einem solchen
     Fall ist es notwendig, dass in der Verfeinerung ein Startzustand spezifiziert ist.

  2. Eine ankommende Transition endet an einem beliebigen Subzustand der Verfei-
     nerung. In diesem Fall wird die Grenze des Oder-Zustands überschritten. Daher
     ist kein Startzustand notwendig, da dieser implizit durch den Zielzustand der
     Transition gegeben ist.

Das Verlassen des Zustands findet im Wesentlichen analog statt:

  1. Der Zustand kann über eine Transition verlassen werden, die von der Oder-
     Verfeinerung abgeht. Handelt es sich um einen Übergang ohne Ereignismarkie-
     rung, die so genannte Beendigungstransition, kann diese nur schalten, falls die
     Bearbeitung in der Verfeinerung abgeschlossen ist. In diesem Fall ist das Vor-
     handensein eines Endzustands notwendig.

  2. Der Zustand kann über eine Transition verlassen werden, die von einem Un-
     terzustand abgeht und als Ziel einen Zustand außerhalb der Oder-Verfeinerung
     besitzt.

Zustandsübergänge Transitionen in Hierarchien füh-
ren bei näherer Betrachtung zu zwei Fragen, für die ei-
ne Semantik bestimmt werden muss. Zunächst muss ge-
klärt werden, was für ereignismarkierte Transitionen gilt,
die vom Oberzustand wegführen. Denn laut Semantik be-
findet sich das Objekt zu jedem Zeitpunkt, während der
Oder-Zustand aktiv ist, in genau einem der Unterzustän-
de. Damit diese „top-level“-Ereignisse trotzdem verarbei-
tet werden können, werden die von der Oder-Verfeinerung
abgehenden Transitionen an alle Unterzustände „vererbt“.
Anders ausgedrückt bedeutet dies, dass jeder Unterzustand
alle ereignismarkierten Zustandsübergänge der Oberzustände kennt, die sich auf dem
Pfad vom Zustand zur Wurzel des Baums befinden, der durch die Hierarchie aufge-
spannt wird.
   Hieraus leitet sich die nächste Frage ab: Was passiert, wenn in einem Unterzustand
eine geerbte Transition „überschrieben“ wird, das heißt auf dasselbe Ereignis reagiert
wie die vom Oberzustand geerbte Transition? In diesem Fall existieren ggf. mehrere
mögliche Übergänge, die in einem Schritt schalten können. Es wird eine Vorrangsre-
gel benötigt, die festlegt, welche der Transitionen schalten kann. Hierzu werden den
Zustandsübergängen Prioritäten zugeordnet, was zu folgender Regel führt:
2.1. Zustandsdiagramme         9


Definition: Vorrangsregel
Sei t1 eine vom Zustand s1 wegführende Transition und s1 ein transitiv erreichbarer
Unterzustand von s2 . t2 ist ein von s2 wegführender Zustandsübergang mit dersel-
ben Ereignismarkierung wie t1 . Dann hat die verschachtelte Transition t1 eine höhere
Priorität als t2 (OMG, 2003).

   Es werden immer die Übergänge schalten, die in der Hierarchie weiter unten ange-
siedelt sind und das Verhalten des komplexen Zustands spezifizieren. Anhand dieser
Regel lässt sich die Idee der Verfeinerung von Zuständen erkennen.
History-Zustände In vielen Systemen ist es zum
Teil notwendig zu wissen, in welcher Konfiguration sich
der komplexe Zustand beim letzten Verlassen befun-
den hat. Mit dieser Information kann die Bearbeitung
an derselben Stelle fortgeführt werden, an der sie zu-
letzt unterbrochen wurde. Diese „Ablaufhistorie“ wird
in hierarchischen Zuständen über Pseudozustände mo-
delliert. Diese History-Zustände werden im Diagramm
durch H bzw. H ∗ gekennzeichnet und lassen sich in zwei
Kategorien unterteilen:

  1. Die flache Historie (H) eines Oder-Zustands speichert den zuletzt aktiven Sub-
     zustand.

  2. Die tiefe Historie (H ∗ ) eines Oder-Zustands speichert alle Zustände für die gilt,
     dass sie aktiv sind und sich auf dem Pfad vom hierarchischen Zustand zu einem
     Blatt des Hierarchiebaums befinden.

   Im Gegensatz zu klassischen Statecharts muss für die History-Zustände der UML-
Zustandsdiagramme eine Starttransition angegeben werden. Diese geht vom History-
Zustand aus und führt zu dem Zustand, der aktiviert werden soll, falls noch keine
Historie vorliegt. Dies ist genau dann der Fall, wenn der Oder-Zustand das erste Mal
betreten wird. Andernfalls wird der Zustand aus der Historie bzw. die Zustände der
tiefen Historie aktiviert.

Nebenläufige Zustände
Eine weitere Neuerung gegenüber endlichen Automaten ist die Modellierung von Ne-
benläufigkeit. Hierbei handelt es sich um einen Zustand, welcher mindestens zwei gleich-
zeitig aktive Subzustände besitzt. Diese bilden die einzelnen Regionen des Zustands.
Daher wird dieser Typ auch als Und-Zustand bezeichnet. Die Regionen werden über ei-
ne gestrichelte Linie im Diagramm voneinander getrennt. Nebenläufigkeit zieht jedoch
konzeptionelle Konsequenzen nach sich, auf die im Folgenden eingegangen wird.
Regionen In einer Und-Verfeinerung werden die einzelnen Regionen durch hierar-
chische Zustände beschrieben, sodass die dort beschriebene Semantik hier ebenfalls
anzuwenden ist. Grundsätzlich sind alle Regionen der Verfeinerung aktiv, sobald der
2. Grundbegriffe
 10


Und-Zustand betreten wird. Sie können als eine Art Prozesse angesehen werden, die
parallel innerhalb der Verfeinerung laufen.
                                  Es können also nicht einzelne Bereiche „ausgeschal-
                               tet“ werden. Ankommende Ereignisse werden immer von
                               allen Regionen verarbeitet, was dazu führen kann, dass
                               mehrere Regionen das Ereignis verarbeiten und somit
                               potenziell verschiedene Transitionen gleichzeitig schal-
                               ten können. Zusätzlich werden wie bei hierarchischen
                               Zuständen die wegführenden ereignismarkierten Transi-
tionen der Verfeinerung an jede Region - also an alle Unterzustände - vererbt und
Übergänge mit höherer Priorität beim Schalten bevorzugt.
Betreten und Verlassen des Und-Zustands Wird
der Zustand aktiviert, muss dafür gesorgt werden, dass alle
Regionen ebenfalls aktiviert werden. Analog müssen alle
Bereiche deaktiviert werden, sobald der Zustand verlassen
wird. Wie bei der Oder-Verfeinerung lassen sich je zwei
Fälle unterscheiden:
  1. Endet die ankommende Transition am Und-Zustand, muss für alle Regionen ein
     Startzustand angegeben werden.
  2. Endet die ankommende Transition an einem Unterzustand genau einer Region,
     wird die Oder-Verfeinerung implizit betreten und alle anderen Regionen müssen
     an dem jeweiligen Startzustand aktiviert werden. Es müssen n − 1 Startzustände
     vorhanden sein.
Das Verlassen des Zustands findet im Wesentlichen analog statt:
  1. Erreichen alle Regionen ihre Endzustände, kann der Und-Zustand über die Be-
     endigungstransition verlassen werden. Die Regionen werden an den jeweiligen
     Endzuständen synchronisiert.
  2. Schaltet eine Transition von einem Unterzustand einer beliebigen Region und
     hat ein Ziel außerhalb der Und-Verfeinerung, werden alle Regionen unabhän-
     gig von ihrem derzeit aktuellen Zustand verlassen und der nebenläufige Zustand
     deaktiviert. Eben diese Semantik gilt auch für vom Superzustand geerbte ereig-
     nismarkierte Transitionen.
Komplexe Transitionen Bei genauerer Betrachtung wurden bisher zwei Fälle be-
handelt, wie Regionen aktiviert werden können. Zum einen explizit und zum anderen
implizit. Im ersten Fall beginnen alle Bereiche an ihren Startzuständen, im letzte-
ren n − 1 Regionen an ihrem Startzustand und eine an einem beliebigen Subzustand,
nämlich dem Ziel der Transition. Es fehlt noch der Fall, dass m Regionen an einem
beliebigen Unterzustand beginnen, wobei 1 < m < n ist. Sicherlich können die Startzu-
stände so angelegt werden, dass sie das gewünschte Verhalten widerspiegeln, doch was
ist, wenn dies nicht gewünscht ist? Die Startzustände können beispielsweise die Stan-
dardkonfiguration modellieren, während in einem Spezialfall die Oder-Verfeinerung in
einer anderen Konfiguration beginnen soll.
2.1. Zustandsdiagramme        11


   Um dieses Verhalten abbilden zu können, existieren die
komplexen Transitionen. Sie zeichnen sich dadurch aus, dass
der Kontrollfluss aufgeteilt wird, also aus einer ankommen-
den Transition mehrere generiert werden. Somit kann pro
Region maximal eine neue Transition entstehen, deren Ziel
ein Zustand in der Region ist. Ein analoger Fall lässt sich
natürlich auch für das Verlassen der Oder-Verfeinerung beschreiben. Somit bieten kom-
plexe Transitionen zwei Funktionsarten:

  1. Das Aufteilen einer in mehrere Transitionen, um direkt Unterzustände der einzel-
     nen Regionen anspringen zu können. Bereiche, die von der komplexen Transition
     nicht berücksichtigt werden, also keine Zustandsübergänge in diese führen, wer-
     den automatisch an ihren Startzuständen aktiviert.

  2. Das Synchronisieren einzelner Regionen, um den Zustand zu verlassen, sobald
     bestimmte Unterzustände erreicht werden. Bereiche, die von der komplexen Tran-
     sition nicht berücksichtigt werden, also keine Übergänge aus diesen Regionen
     führen, werden unabhängig von ihrem aktuellen Zustand automatisch beendet.

In der Modellierung werden hierfür zwei Pseudozustände berücksichtigt, die beide
durch einen schwarzen Synchronisationsbalken gekennzeichnet werden. Dieser Balken
entspricht dem Fork-Zustand genau dann, wenn er eine 1 : n-Abbildung repräsentiert,
d. h. aus einer ankommenden Transition mehrere abgehende werden. Als Join-Zustand
wird er dann bezeichnet, wenn er eine n : 1-Abbildung repräsentiert, also mehrere ein-
gehende Transitionen synchronisiert und zu einer abgehenden zusammenfasst.

2.1.2 Implementierungsansätze
Nachdem die für die Arbeit relevanten Elemente von Zustandsdiagrammen und deren
Semantik erörtert wurden, sollen im Folgenden verschiedene Möglichkeiten behandelt
werden, diese in Quellcode abzubilden. Die vorgestellten Konzepte basieren auf den
klassischen Methoden der Implementierung endlicher Automaten.

Prozedurale Implementierung
Mittels prozeduraler Programmiersprachen lassen sich endliche Automaten einfach und
effizient über geschachtelte switch-case-Anweisungen implementieren. Hierzu wird der
aktuelle Zustand in einer globalen Variable gehalten, während Aktionen als Prozedur
implementiert werden. Ein einfacher endlicher Automat ließe sich wie in Abbildung
2.1 darstellen.
   Um ein Ereignis verarbeiten zu können, wird zunächst der aktuelle Zustand gewählt
und für diesen geprüft, ob er das Ereignis verarbeiten kann. Durch die Kapselung der
Aktionen in einzelne Prozeduren ist es möglich diese wiederzuverwenden. Des Weiteren
lässt sich insgesamt ein Programm erzeugen, welches wenig Speicher benötigt und in
der Regel schnell ist. Jedoch hat diese Implementierung auch essenzielle Nachteile:

  • Der Quelltext wird schnell unübersichtlich, schlecht wartbar und fehleranfällig.
2. Grundbegriffe
 12


                                  i n t s t a t e = ’A ’ ; . . .
                                  void fsm ( e v e n t )
                                  {
                                      switch ( s t a t e )
                                        case A: switch ( e v e n t )
                                                case x :
                                                  a cti on X ( ) ; s t a t e = ’B ’ ;
                                                break ;
                                                case y :
                             =⇒                   a cti on Y ( ) ; s t a t e = ’A ’ ;
                                                break ;
                                        break ;
                                        case B : switch ( e v e n t )
                                                case y :
                                                  a c t i o n Z ( ) ; s t a t e = ’A ’ ;
                                                break ;
                                        break ;
                                  }


      Abbildung 2.1.: Umsetzung eines endlichen Automaten in prozeduralen Quelltext


  • Oder- bzw. Und-Verfeinerungen lassen sich nicht abbilden und müssen zunächst
    aus dem Diagramm entfernt werden, ohne die Semantik einzuschränken (Harel,
    1987). Dieses „Plätten“ ist allerdings problematisch, da die resultierende Anzahl
    der Zustände enorm groß werden kann.

Objektorientierte Ansätze
Das State-Pattern Eine Alternative bietet der objektorientierte Ansatz. Für end-
liche Automaten hat sich das von Erich Gamma vorgestellte State-Entwurfsmuster
etabliert (Gamma u. a., 1995). Das zentrale Konzept ist die Kapselung der Zustände
in einzelne Objekte, welche von einer abstrakten Basisklasse alle Methoden erben und
bei Bedarf überschreiben. Methoden repräsentieren die Aktionen einer Transition. Zu-
dem gibt es den Kontext, welcher den Zugriff zum endlichen Automaten anbietet und
eine Referenz auf den derzeit aktuellen Zustand hält. Die Aufgabe des Kontext besteht
darin, ankommende Ereignisse (die Methodenaufrufe) an den aktuellen Zustand weiter
zu delegieren. Der oben dargestellte Beispielautomat kann mit Hilfe des State-Patterns
wie in Abbildung 2.2 implementiert werden.
   Auch hier lässt sich erkennen, dass die essenziellen Elemente nicht unterstützt wer-
den. Es muss eine Lösung gefunden werden, die es erlaubt das Entwurfsmuster sowie
Hierarchie und Nebenläufigkeit zu verwenden. In (Ali und Tanaka, 1999) wird eben
dieses Problem behandelt und eine Lösung vorgestellt. Die Idee ist das Verwenden der
Vererbungshierarchie zur Darstellung der Oder-Verfeinerung. Das heißt, eine von A
erbende Klasse B ist Unterzustand von A. Hier ist zu erkennen, dass die Semantik der
Vererbung von Transitionen erfüllt ist, da sich dies eins zu eins auf die Klassenhier-
2.1. Zustandsdiagramme         13




     Abbildung 2.2.: Umsetzung des Beispielautomaten mit Hilfe des State-Patterns


archie abbilden lässt. Offen bleibt, wie sich nebenläufige Zustände realisieren lassen.
Die Lösung ist naheliegend: In Zustandsdiagrammen besteht eine Und-Verfeinerung
aus mindestens zwei hierarchischen Zuständen. Also hält der Und-Zustand eine Refe-
renz auf eine Oder-Verfeinerung. Genau dies wird in dem Ansatz von Ali und Tanaka
verwendet. Der Und-Zustand ist eine Klasse, welche Referenzen auf die Regionen hält
und die einzelnen Ereignisse an die Regionen delegiert (siehe Abbildung 2.3).




                                  =⇒




    Abbildung 2.3.: Beispiel der Abbildung von Hierarchie und Nebenläufigkeit in die
       Klassenhierarchie objektorientierter Sprachen auf Basis des State-Patterns


Der Ansatz von Gurp und Bosch Beim State-Pattern ist das zentrale Konzept
der Zustand. Dies führt dazu, dass Elemente wie Aktionen und Transitionen nicht als
eigenes Objekt repräsentiert werden, sondern implizit in der Zustandsklasse „versteckt“
sind. Ein alternativer Ansatz wurde von Jilles van Gurp und Jan Bosch vorgestellt (van
Gurp und Bosch, 1999). Dieser verlagert das Konzept auf die explizite Modellierung
der Elemente endlicher Automaten als eigene Objekte. Hier wird nicht der Zustand,
sondern die Transition als zentrales Element betrachtet. Diese kennt den Zielzustand
und die auszuführende Aktion, während der Zustand seine abgehenden Transitionen
kennt und diese mit einem Ereignis verknüpft.
   Der Kontext dient als Schnittstelle des Zustandsdiagramms zur Anwendung und
leitet die Ereignisse an den jeweils aktuellen Zustand weiter. Dieser prüft in seiner Liste
2. Grundbegriffe
 14




      Abbildung 2.4.: Klassendiagramm des FSM-Frameworks von Bosch und van Gurp


aus (Ereignis, T ransition)-Tupeln, ob das Ereignis verarbeitet werden kann und führt
den Übergang ggf. aus. Aktionen werden mittels des Command-Patterns (Gamma u. a.,
1995) ausgeführt, sodass verschiedenartige Aktionen implementiert, aber diese auch
wiederverwendet werden können.
  Da ein Ziel in dem Ansatz die Wiederverwendbarkeit des Zustandsdiagramms ist,
werden ablaufspezifische Daten nur im Kontext verwaltet. Dies bedeutet, dass sich
verschiedene Kontexte dasselbe Diagramm teilen können. Aus diesem Grund wird in
der Implementierung der Kontext als Referenz mit übergeben (siehe Abbildung 2.4).
  Jedoch fehlt auch in diesem Ansatz die Unterstützung der wesentlichen Elemente
von Zustandsdiagrammen und beschränkt sich auf die Abbildung endlicher Automa-
ten. Die Laufzeitsemantik, Hierarchie und Nebenläufigkeit muss explizit implementiert
werden, während sie beim Ansatz von Ali und Tanaka implizit auf Elemente der Pro-
grammiersprache abgebildet werden.


2.2 LEGO Mindstorms Roboter
Das LEGO Mindstorms Robotics Invention System wurde erstmals im Jahr 1998 vorge-
stellt und basiert auf einer Zusammenarbeit der Firma LEGO mit dem Massachusetts
Institute of Technology (MIT). Es erweitert die Produktlinie LEGO Technik um einen
frei programmierbaren Baustein und ermöglicht so das Erstellen elektro-mechanischer
Komponenten wie zum Beispiel Roboter. Aufgrund der Freiheiten, die LEGO mit sei-
nem System bietet, ist es möglich eine Vielfalt verschiedenster Roboter zu bauen. Daher
soll in diesem Abschnitt zunächst auf die Hardware näher eingegangen werden, bevor
anschließend die verfügbaren Möglichkeiten der Programmierung beleuchtet werden.

2.2.1 Aufbau der Hardware
Bei dem von LEGO verwendeten RCX-Baustein handelt es sich um einen Mikrocon-
troller der Firma Hitachi mit 16MHz. Der Controller besitzt zur Interaktion mit der
Umwelt drei Eingänge für Sensoren und drei Ausgänge. Derzeit existieren Druck-,
Rotations-, Licht- und Temperatursensoren sowie Motoren und Lampen, welche an
2.2. LEGO Mindstorms Roboter          15




                          Abbildung 2.5.: Der RCX-Baustein


die Ausgänge angeschlossen werden können. Es stehen dem Anwender 32KB RAM
und 16KB ROM zur Verfügung. Im ROM werden low-level-Funktionen und Basistrei-
ber zur Steuerung der Ausgänge, Sensoren und der Infrarot-Schnittstelle bereitgestellt.
Über letztere wird der RCX mit einer Firmware versorgt, die das Betriebssystem dar-
stellt und die Programmierung ermöglicht. Die 32KB Arbeitsspeicher stehen nicht aus-
schließlich für eigene Programme zur Verfügung, sondern halten neben dem Programm
auch dessen Laufzeitobjekte und die Firmware. Somit steht je nach verwendeter Firm-
ware unterschiedlich viel Speicher für eigene Programme und Daten zur Verfügung.



2.2.2 Programmierung der LEGO-Roboter
Die Firma LEGO bietet ein eigenes Betriebssystem an, welches jedoch nicht mittels
einer Hochsprache programmiert werden kann. Stattdessen wird eine graphische Mo-
dellierungssprache angeboten, die über eine proprietäre Windows-Software verwendet
werden kann. Diese erstellt aus dem Modell schließlich das Programm für den RCX-
Baustein. Im Wesentlichen wird also dasselbe Vorgehen verwendet, welches im Rah-
men dieser Diplomarbeit behandelt werden soll: Aus einer graphischen Modellierung
ein ausführbares Programm zu erstellen.
   Da die Modellierungssprache von LEGO für Kinder ausgelegt ist, lassen sich kom-
plexe Abläufe nur umständlich bis gar nicht beschreiben. Ziel verschiedener Entwickler
war es eine Möglichkeit zu schaffen, mit der die Roboter klassisch programmiert werden
können. Aus diesem Grund wurden alternative „Betriebssysteme“ entwickelt, wobei die
drei bekanntesten jeweils kurz beleuchtet werden.

Not Quite C
Basierend auf der original LEGO-Firmware implementiert NQC (Baum und Hansen,
2004) eine eigene prozedurale Programmiersprache, die an C angelehnt ist. Objektori-
entierte Konzepte lassen sich hier also nicht umsetzen.
2. Grundbegriffe
 16


BrickOS
Das ursprünglich von Markus L. Noga entwickelte Betriebssystem BrickOS (Noga,
2002) ersetzt das Original der Firma LEGO. Als Compiler wird der GCC verwendet,
sodass der Quellcode nativ für den Hitachi-Prozessor kompiliert und gelinkt wird. Pro-
gramme können in der Hochsprache C++ entwickelt werden und bietet demnach auch
die Möglichkeiten dieser Sprache, inklusive Bibliotheken wie der Standard Template
Library und der manuellen Speicherverwaltung.

LeJOS
Das auf TinyOS aufbauende LEGO Java Operating System (Solorzano, 2000) imple-
mentiert eine virtuelle Maschine für Java und ersetzt wie BrickOS die Firmware von
LEGO. Programme lassen sich in Java, und somit objektorientiert, implementieren.
LeJOS greift auf eine abgespeckte Java API zurück, die die essenziellen Klassen der
Sun API nachbildet. Im Gegensatz zum Original bietet diese virtuelle Maschine keine
Garbage Collection an, die das Aufräumen von Objekten übernimmt. Einmal angelegte
Objekte bleiben die komplette Laufzeit des Programms im Speicher bestehen.
  Diese drei Möglichkeiten der Programmierung des RCX gehören zu den bekanntes-
ten und am meisten eingesetzten. Im nächsten Kapitel werden zunächst die Vor- und
Nachteile der einzelnen Lösungen diskutiert. Auf diesem Ergebnis aufbauend, werden
die vorgestellten Ansätze zur Implementierung von Zustandsdiagrammen verglichen
und begutachtet, um daraus ein Konzept und eine Vorgehensweise für diese Diplom-
arbeit abzuleiten.
Kapitel 3


Lösungsansatz
Das Konzept zur Durchführung der Integration von LEGO Mindstorms in DAVE ba-
siert auf mehreren Voraussetzungen und Anforderungen. Zunächst soll die Frage disku-
tiert werden, auf welcher technischen Basis die Programmierung des RCX durchgeführt
werden soll.


3.1 Zielplattform
Es wurden die drei Laufzeitumgebungen NQC, BrickOS und LeJOS kurz vorgestellt.
Natürlich hängt die Auswahl auch mit dem gewünschten Programmierkonzept und
dem verfügbaren Speicherplatz des RCX zusammen. Ausgehend von den vorgestellten
Implementierungsansätzen lässt sich zusammenfassen, dass der prozedurale Ansatz den
Vorteil hat, dass die resultierenden Programme in der Regel klein sind. Das objektori-
entierte Programmierparadigma erleichtert hingegen die Implementierung, da auf das
Plätten von Zustandsdiagrammen verzichtet werden kann und somit ein komplexer
Schritt entfällt. Daher werden im Rahmen dieser Arbeit nur objektorientierte Ansätze
verfolgt, was zur Konsequenz hat, dass NQC nicht näher betrachtet wird.
   BrickOS bietet die Vorteile, dass mittels C++ der Speicher des RCX frei verwaltet
werden kann und nativer Maschinencode für den im RCX verbauten Hitachi-Prozessor
generiert wird. Diese beiden Punkte haben zur Folge, dass sehr kleine Programme ent-
stehen, sodass der verfügbare Speicher effizient ausgenutzt werden kann. Allerdings
bedingt C++ durch seine Konzepte und dem freien Speicherzugriff potenziell eine re-
lativ hohe Fehleranfälligkeit. Es müssen sprachbedingte Probleme beachtet werden,
wie zum Beispiel zyklische Abhängigkeiten bei der Einbindung der Header-Dateien.
Diese Argumente erschweren zwar die Implementierung, bilden aber noch kein Aus-
schlusskriterium. Das wichtigste Argument gegen BrickOS ist, dass der Einsatz in der
Lehre geplant ist und somit gewährleistet sein muss, dass die Studenten ohne zusätz-
lichen Aufwand die Funktionalität aus DAVE heraus auch zu Hause nutzen können.
Dies ist bei BrickOS in dieser geforderten Form allerdings nicht ohne weiteres möglich,
da diese Plattform auf freien Unix-Werkzeugen basiert, welche unter Windows nur mit
erheblichem Aufwand verwendet werden können. Selbst die Installation von BrickOS
unter Unix-Systemen ist nicht trivial.
   LeJOS hingegen wird in Form von jar-Dateien ausgeliefert, welche keine weitere
Installation erforderlich machen. Daher können die benötigten Elemente von LeJOS
3. Lösungsansatz
 18


direkt in DAVE mitgeliefert werden, ohne dass die Studenten zusätzliche Installations-
routinen ausführen müssen. Zudem wird mit Java eine moderne Programmiersprache
angeboten, welche nicht nur betriebssystemunabhängig ist, sondern sich auch gut in
DAVE einbinden lässt, weil dieses in selbiger Sprache implementiert ist. Da es sich
bei LeJOS nur um eine abgespeckte Variante einer Java-Laufzeitumgebung handelt,
müssen allerdings Einschränkungen hingenommen werden:

  • Einmal angelegte Objekte können nicht mehr freigegeben werden und belegen
    den allokierten Speicher bis zur Programmbeendigung.

  • Die Firmware verbraucht einen hohen Anteil an Speicher des RCX, sodass für
    eigene Programme und Daten nur ca. 9 Kilobyte zur Verfügung stehen.

  Durch die fehlende Garbage Collection, die große Firmware und die Tatsache, dass
Java-Programme im Allgemeinen relativ groß sind, besteht die Gefahr, dass nur klei-
nere Zustandsdiagramme umgesetzt werden können. Da dies für die Lehre keine we-
sentliche Einschränkung ist, erscheint LeJOS als erste Wahl und soll als Basis für die
weiteren konzeptionellen Entscheidungen dienen.


3.2 Ansatzpunkte zur Integration in DAVE
Ein weiterer wichtiger Aspekt ist die Analyse der Konzepte von DAVE, um mögliche
Ansatzpunkte zu finden, an denen die Integration angesetzt werden kann. Da ein we-
sentliches Alleinstellungsmerkmal dieser Software die Simulation der Diagramme ist,
existiert in DAVE eine Simulationsmaschine für Zustandsdiagramme. Sie basiert auf
dem um Hierarchie und Nebenläufigkeit erweiterten Ansatz von Bosch. Die Persistenz-
schicht zum Speichern wird durch das LIMO-Framework realisiert. Dieses schreibt die
Datenstruktur zur Beschreibung eines Zustandsdiagramms in einem einfachem XML-
Format auf die Festplatte.
  Es ergeben sich zwei Fragestellungen: Kann die vorhandene Simulationsmaschine
verwendet werden und welche Form der Datenstruktur soll als Basis der Integration
dienen? Die nächsten beiden Abschnitten behandeln diese Fragen.


3.2.1 Die Simulationsmaschine
Zunächst stellt sich die Frage wie sich die in DAVE vorhandene Laufzeitumgebung
für Zustandsdiagramme verwenden lässt. Dies lässt sich leicht beantworten, denn die
vorhandene Implementierung ist zu umfangreich, um sie im RCX verwenden zu können.
Modifikationen an der existierenden Laufzeitumgebung könnten zwar durchgeführt
werden, können aber zu unerwünschten Seiteneffekten innerhalb DAVEs führen, sodass
zusätzliche Tests des gesamten Programms notwendig sind. Diese Aspekte implizieren
die Planung und Realisierung einer eigenen, speicherminimalen Simulationsmaschine,
die völlig unabhängig von DAVE ist.
3.3. Implementierung      19


3.2.2 Wahl der zu verwendenden Datenstruktur
Der zweite Aspekt ist die zu verwendende Datenstruktur. Als Basis können entweder
die Klassen verwendet werden, welche DAVE zur Beschreibung des Diagramms zur
Verfügung stellt, oder aber die rein textuelle Repräsentation in Form der XML-Datei.
Beim ersten Ansatz muss die Simulationsmaschine entwickelt werden, während beim
letzteren zusätzlich eine geeignete Datenstruktur geplant und programmiert werden
muss. Trotzdem ist die Verwendung der XML-Datei sinnvoller. Denn für die existie-
renden DAVE-Klassen ist nicht klar, ob sich diese in einer speicherplatzoptimierten
Simulationsmaschine ohne Modifikation verwenden lassen. Änderungen der Quellen
führen jedoch zu schon oben genanntem Problem. Somit ist letztlich eine sehr lose
Kopplung an DAVE der zu wählende Weg. Einzig die Codegenerierung ist an spezi-
fische Teile, nämlich das XML-Format, gekoppelt, während der Rest eine Wiederver-
wendbarkeit außerhalb von DAVE gewährleistet. Diese Datei wird als Eingabe für ein
Ant-Skript (Davidson, 1999) dienen, welches die notwendigen Schritte zur Fertigstel-
lung des RCX-Programms automatisiert (siehe Kapitel 8).


3.3 Implementierung
Da eine sehr lose Kopplung an DAVE gewählt wird, soll dieser Ansatz auch auf die
LEGO-spezifischen Teile ausgedehnt werden. Diese Entscheidung basiert ebenfalls auf
der Idee, einzelne Komponenten wiederverwenden zu können.
  Wie lässt sich die Implementierung realisieren? Hierzu werden im ersten Schritt die
von LeJOS generierten Programme näher betrachtet. Dabei fällt auf, dass die Ver-
wendung von Klassen speichertechnisch teuer ist. Pro Klasse entsteht je nach deren
Umfang ein Speicherverbrauch von rund 500 bis 1024 Bytes. Jede Instanz kostet hin-
gegen im Durchschnitt nur wenige Bytes. Das Ziel ist daher die Anzahl an Klassen
möglichst minimal zu halten und stattdessen viele Objekte zu erzeugen.
  Der Implementierungsansatz von Ali und Tanaka fällt dadurch auf, dass er eine große
Anzahl an Klassen generiert, nämlich mindestens so viele wie Zustände existieren.
Zudem erfordert dieser Ansatz, dass die Codegenerierung den Quelltext jedes einzelnen
Zustands in Form einer Klasse erzeugt. Denn innerhalb dieser existiert spezifischer
Quelltext für die Transitionen und Aktionen des Zustandsdiagramms. Dies führt zu
einer enormen Steigerung der Komplexität bei der Codegenerierung. Wünschenswert
wäre hingegen ein Framework, welches eine einfache Programmierschnittstelle bietet,
die bei der automatischen Erzeugung des Quelltexts aus der XML-Datei verwendet
werden kann.


3.4 Gesamtaufbau
Die Hauptprobleme liegen in der Entwicklung eines Frameworks zur Repräsentation
und Ausführung von Zustandsdiagrammen, welches mit den begrenzten Ressourcen des
RCX verwendbar ist und der Überlegung, wie aus der XML-Datei Quellcode generiert
3. Lösungsansatz
 20




  Abbildung 3.1.: Aufbau des Konzepts. Die Nummern in den Kreisen geben die Kapitel
  an, in denen der jeweilige Teil behandelt wird, während die mit Ant gekennzeichneten
        Pfeile die Schritte angeben, die über das Ant-Skript automatisiert werden.


werden kann. In Abbildung 3.1 ist der geplante Aufbau zu sehen. Nach dem Spei-
chern des Diagramms in DAVE wird die XML-Datei in Quelltext transformiert. Die-
ser variable Teil verwendet die Programmierschnittstellen des statischen Teils, nämlich
des Frameworks. Aus dem generierten Quelltext kann schließlich mittels vorhandener
Werkzeuge das Programm kompiliert, gelinkt und in den RCX hochgeladen werden.
Diese Schritte werden mittels Ant automatisiert.
   Das Framework selbst soll auf dem Ansatz von Bosch und van Gurp basieren, jedoch
um die benötigten Elemente für Zustandsdiagramme erweitert. Durch die Verwendung
dieses Ansatzes kann die Anzahl der Klassen auf ein Minimum reduziert werden, indem
die einzelnen Elemente von Zustandsdiagrammen explizit durch eine Klasse repräsen-
tiert werden. Somit steigt nur die Anzahl der Instanzen. Zusätzlich kann das Frame-
work in zwei Teile getrennt werden. Zum einen die eigentliche Laufzeitumgebung für
Zustandsdiagramme und zum anderen die LEGO-spezifischen Teile. So lässt sich errei-
chen, dass das Framework auch unabhängig von LEGO wiederverwendet werden kann,
etwa in anderen eingebetteten Umgebungen.
   Weitere Vorteile dieser Vorgehensweise sind erkennbar: Die Codegenerierung verein-
facht sich erheblich, da sie sich auf die Erzeugung genau einer einzigen Klasse beschrän-
ken kann. Und der statische Teil des Systems kann automatisiert getestet werden, was
bei komplexem, dynamisch generierten Quelltext nur mit Aufwand möglich ist.
   Es lassen sich insgesamt vier Teilaufgaben entdecken, die in den folgenden Kapiteln
bearbeitet werden. Die erste Aufgabe besteht in der Planung der Laufzeitumgebung
für Zustandsdiagramme (Kapitel 4). Die zweite Aufgabe lässt sich in zwei Bereiche
splitten. Zunächst muss überlegt werden, wie die RCX-spezifischen Elemente in die
Notation von Zustandsdiagrammen eingebettet werden können (Kapitel 5), bevor de-
ren technische Umsetzung, also die LEGO-Erweiterung des Frameworks, beschrieben
werden kann (Kapitel 6). Die dritte Aufgabe ist die Planung und Umsetzung der Code-
generierung (Kapitel 7), gefolgt von der letzten Aufgabe, der Integration der einzelnen
Teile in Form eines Automatisierungs-Skripts (Kapitel 8).
Kapitel 4


Das Statechart-Framework

4.1 Konzeptioneller Aufbau
Die genannten Anforderungen an das zu entwickelnde Framework für Zustandsdia-
gramme erfordern zunächst konzeptionelle Vorüberlegungen. Als Basis dient das von
Bosch und van Gurp vorgestellte Framework für endliche Automaten, dessen Imple-
mentierung in Abbildung 2.4 zu sehen ist. Wie beim State-Pattern wird auch bei diesem
ein Kontext eingesetzt, welcher den aktuellen Zustand kennt und Ereignisse an diesen
delegiert. Allerdings wird dem Kontext ein weiterer Zweck zugeteilt: Bosch und van
Gurp adressieren das Problem der mehrfachen Nutzung des Automaten und kapseln
ablaufspezifische Daten, wie z. B. Variablenwerte, in dem Kontext. Dies bedeutet, dass
ein Zustand nur ein Teil der Infrastruktur des Automaten ist und somit verschiedene
Kontexte gleichzeitig auf denselben Automaten zugreifen können. Daher wird in den
Methoden dispatch und execute jeweils eine Referenz des aktuellen Kontexts überge-
ben, sodass Aktionen und Zustände die Möglichkeit haben, Daten in diesem zu setzen
und abzufragen. Der für dieses Framework gewählte Ansatz sieht hingegen nicht die
mehrfache Nutzung desselben Diagramms mit unterschiedlichen Kontexten vor.
   Im Gegensatz zu endlichen Automaten können Zustandsdiagramme Hierarchien be-
inhalten, sodass es möglich ist, dass mehrere Zustände gleichzeitig aktiv sind. Die
Menge der aktuell aktiven Zustände wird im Folgenden als Konfiguration bezeichnet.
Das Zustandsdiagramm befindet sich zu jedem Zeitpunkt in einer eindeutigen Konfigu-
ration. Da nicht die Infrastruktur des Diagramms mehrfach genutzt werden soll, ist es
nicht notwendig die Information über die Konfiguration im Kontext zu speichern, son-
dern kann in die Zustände des Diagramms verlagert werden. Das heißt, jeder Zustand
weiß zu jedem Zeitpunkt, ob er aktiviert ist.
   Wozu dient also der Kontext? Werden zunächst Hierarchien und nebenläufige Zu-
stände außer acht gelassen, fällt diesem dieselbe Aufgabe wie beim State-Pattern zu,
nämlich ein eingehendes Ereignis an den aktuell aktiven Zustand weiterzuleiten. Da
ein Zustand ebenfalls ein Ereignis verarbeitet, lässt sich der Kontext als ein Spezial-
fall eines Zustands ansehen, in dem nur die Ereignisverarbeitung überschrieben wird
und die Zusatzinformation des aktuell aktiven Unterzustands bekannt ist. Der Kontext
kann als zusammengesetzter Zustand betrachtet werden. Diese Sichtweise wird später
bei der Implementierung der hierarchischen und nebenläufigen Zustände helfen.
4. Das Statechart-Framework
 22




      Abbildung 4.1.: Konzeptioneller Aufbau des Frameworks ohne Berücksichtigung
                       hierarchischer und nebenläufiger Zustände



   Ereignisse können in Zustandsdiagrammen beliebiger Natur sein. Dieser Umstand
und die Tatsache, dass als Zielsetzung die Erweiterbarkeit des Frameworks zugrunde
liegt, stellt entsprechende Anforderungen an die Konzeption. Bei Bosch werden Er-
eignisse durch eine Zeichenkette repräsentiert, was jedoch unflexibel ist. Stattdessen
eignet sich das Command-Entwurfsmuster: In einer Schnittstelle wird eine Methode
deklariert, welche in einer implementierenden Klasse ausprogrammiert wird und vom
Framework verwendet werden kann. Dieses Verfahren wird von Bosch für die Aus-
führung von Aktionen verwendet. Da sich dieses Muster für Aktionen eignet, sollen
hiermit ebenfalls Bedingungen und Ereignisse realisiert werden.
   Beim Aktivieren bzw. Deaktivieren werden mehrere Schritte durchgeführt (Setzen
der Status-Variablen, ggf. Ausführen der Entry- bzw. Exit-Aktion), weshalb diese in
einer jeweiligen Methode gekapselt werden. In Abbildung 4.1 ist eine Implementie-
rung des bisherigen Konzepts in Form eines Klassendiagramms dargestellt. Bis hierher
ähnelt der Aufbau dem von Bosch bis auf wenige Details. Allerdings sind einige für
Zustandsdiagramme spezifische Elemente noch nicht berücksichtigt worden.


4.1.1 Zeitgesteuerte Transitionen
Bei zeitgesteuerten Transitionen ist die Zeit relevant, die seit dem Betreten des aktuell
aktiven Zustands vergangen ist. Als Besonderheit sei angemerkt, dass im Falle von
Hierarchien der Oberzustand einen längeren Zeitraum aktiv sein kann als seine Unter-
zustände. Daher muss jeder Zustand die Zeit kennen, die seit seiner letzten Aktivierung
vergangen ist und die Klasse muss um diese Information erweitert werden.
  Um möglichst flexibel zu sein, soll das Hochzählen der Zeit von außen über einen
Zeitgeber gesteuert werden können. Hier gibt es prinzipiell zwei Lösungsansätze. Beim
ersten Ansatz wird eine konkrete Ausprägung der Event-Schnittstelle implementiert,
während der zweite Ansatz eine zusätzliche Methode timeout(ms) vorsieht. Da das Ziel
4.1. Konzeptioneller Aufbau        23




    Abbildung 4.2.: Erweiterung der Klassen State und Transition für zeitgesteuerte
               Transitionen, sowie Einführung der Klasse PseudoState


ist, die Anzahl der Klassen möglichst gering zu halten, wird der zweite Ansatz verfolgt.
Hieraus resultiert, dass eine Transition die zu wartende Zeit nicht als Instanz der Event-
Klasse speichert, sondern als reinen Integer-Wert. Beim Schalten der Transition wird
zunächst geprüft, ob die zu wartende Zeit abgelaufen ist. Neben der Verwaltung der
Zeit ist es in beiden Fällen notwendig, beim Betreten des Zustands in der Methode
activate() die Zeit zurückzusetzen. Abbildung 4.2 zeigt die Änderungen an den Klassen.



4.1.2 Segmentierte Transitionen
Eine weitere Besonderheit in Zustandsdiagrammen ist die Verbindungsstelle als Pseu-
dozustand für segmentierte Transitionen. Pseudozustände haben zwei Gemeinsamkei-
ten, nämlich dass diesen keine Entry- bzw. Exit-Aktion zugewiesen und nicht in ihnen
verweilt werden kann. Der erste Punkt trifft ebenso auf den Endzustand zu, obwohl es
sich hier streng genommen um keinen Pseudozustand handelt. Trotzdem wird nur eine
neue Klasse PseudoState ergänzt, welche auch den Endzustand repräsentiert (siehe
Abbildung 4.2).
   Die zur Verbindungsstelle hinführende Transition darf nur dann schalten, wenn es
einen Weg zu einem normalen Zustand gibt. Diese Prämisse muss durch das erste
Segment sichergestellt werden, sodass dieses vor der tatsächlichen Ausführung solch
einen Weg suchen muss. Hierzu bedient sich das Framework einer Tiefensuche. Eine
auszuführende Transition überprüft grundsätzlich mit ihrer Methode allowed() die ggf.
vorhandene Bedingung und schließlich, ob es sich bei dem Zielzustand um einen ech-
ten Pseudozustand, also nicht dem Endzustand, handelt. Falls ja, wird die Tiefensuche
gestartet, indem auf dem Pseudozustand die Methode lookup() aufgerufen wird, die
ihrerseits für alle ausgehenden Transitionen die Methode allowed() aufruft. Erst, wenn
ein Weg zu einem normalen Zustand gefunden wurde, wird der Quellzustand de- und
der Zielzustand aktiviert. Da es sich bei der Verbindungsstelle um einen Pseudozu-
4. Das Statechart-Framework
24




                                        x=0
                                        −→




     Abbildung 4.3.: Verarbeitung segmentierter Transitionen für den Fall x = 0
4.1. Konzeptioneller Aufbau      25




              Abbildung 4.4.: Ereignisverarbeitung auf dem Oder-Zustand


stand handelt, wird dieser automatisch bei Aktivierung sofort wieder verlassen, indem
mittels dispatch(null) die Ereignisverarbeitung neu angestoßen wird. In Abbildung 4.3
ist dieser Ablauf dargestellt.

4.1.3 Hierarchie und Nebenläufigkeit
Im Gegensatz zu Bosch und van Gurp muss das zu entwickelnde Framework noch
um die beiden essenziellen Elemente der Hierarchiebildung und der Verwendung von
Nebenläufigkeit erweitert werden.

Hierarchische Zustände
Die von Oder-Verfeinerungen aufgebaute Struktur ist die eines Baums. Ziel ist es somit
innerhalb des Frameworks solch eine Baumstruktur aufzubauen. Hier ist die oben
vorgestellte Sichtweise des Kontexts als Spezialfall eines Zustands hilfreich.
  Bisher stellt der Kontext auf oberster Hierarchieebene das Zustandsdiagramm dar
und kennt den aktuell aktiven Zustand auf der darunterliegenden Ebene. Dieses Kon-
zept lässt sich auf die Oder-Verfeinerung anwenden: Diese ist ein Spezialfall eines
Zustands, welcher jeweils genau einen aktiven Unterzustand hat. Also genau das, was
der Kontext auf oberster Hierarchieebene abbildet.
  Da die Klasse Context eine Generalisierung der Klasse State ist, kann vom Kontext
einfach eine neue Klasse abgeleitet werden, die das Spezialverhalten eines hierarchi-
schen Zustands repräsentiert. Der Kontext wird zu einer abstrakten Basisklasse für
hierarchische Zustände. Beim Aktivieren eines Zustands meldet er dies seinem Vater-
knoten. Zur Abbildung der Baumstruktur muss die Zustandsklasse erweitert werden.
Jedem Zustand muss sein Vaterknoten bekannt sein. Der einzige „Zustand“ ohne Va-
terknoten ist das Diagramm selbst, welches künftig durch die Klasse Statechart re-
präsentiert wird. Das Diagramm ist also ein zusammengesetzter Zustand und bildet
immer den Wurzelknoten der Baumstruktur.
Ereignisverarbeitung Im Gegensatz zu normalen Zuständen ist die Verarbeitung
eines eingehenden Ereignisses komplexer, da die in Abschnitt 2.1.1 beschriebene Vor-
rangsregel berücksichtigt werden muss. Hierzu muss die entsprechende Methode in der
abgeleiteten Klasse überschrieben werden, um das Ereignis zunächst an den aktiven
Unterzustand zu propagieren.
  Die Vererbung von Transitionen wird implizit durchgeführt. D. h. beim Aufbau des
Diagramms müssen vererbte Transitionen nicht explizit für die Unterzustände ange-
4. Das Statechart-Framework
 26




                                                  =⇒




           Abbildung 4.5.: Transitionsverhalten bei hierarchischen Zuständen


legt werden. Falls der Unterzustand das Ereignis nicht verarbeiten kann, wird geprüft,
ob die Oder-Verfeinerung eine Transition besitzt, die auf das Ereignis reagieren kann.
Jedoch muss eine Besonderheit berücksichtigt werden, um die Semantik korrekt ab-
zubilden: Ist der Endzustand der Oder-Verfeinerung noch nicht erreicht worden, müs-
sen alle Beendigungstransitionen von der Verarbeitung ausgeschlossen werden. Konnte
hingegen der Unterzustand das Ereignis verarbeiten, ist dessen Behandlung auf dem
Oder-Zustand abgeschlossen. Abbildung 4.4 zeigt den Ablauf solch einer Verarbeitung.
Transitionen Wie bei Bosch kennen die Übergänge bisher nur den Zielzustand,
um diesen zu aktivieren. Bei der Verwendung von Hierarchien reicht diese einfache
Sichtweise nicht mehr aus, da es jetzt möglich ist, dass beim Schalten einer Transition
mehrere Zustände (de-)aktiviert werden müssen. Im Beispiel aus Abbildung 4.5 werden
beim Ausführen der Transition zum Zustand r automatisch auch die Zustände p und
q aktiviert. Analoges gilt für den Übergang von r nach y. Hierbei werden q und p
automatisch de- und x aktiviert.
  Eine Transition muss also den Pfad vom Quell- zum Zielzustand im durch die Hier-
archie aufgespannten Baum berücksichtigen. Hierzu wird der kleinste gemeinsame Vor-
fahre (LCA = Least common ancestor) berechnet (OMG, 2003). Alle Zustände von
der Quelle zum LCA werden deaktiviert, analog werden alle Zustände auf dem Pfad
vom LCA zum Ziel aktiviert. In obigem Beispiel ist der gemeinsame Vorfahre bei allen
drei Transitionen das Zustandsdiagramm selbst, also der Wurzelknoten.
  Für die Implementierung bedeutet dies, dass bei der Erzeugung einer Transition
der Quell- und Zielzustand übergeben werden muss und anhand der Hierarchie zwei
Zustandsmengen berechnet werden.
History-Zustände Die beiden History-Zustandsarten können sehr einfach imple-
mentiert werden. Hierzu wird eine Tiefensuche auf dem Oder-Zustand ausgeführt,
welche alle derzeit aktiven Knoten in einer Liste speichert. Die Suchtiefe beschränkt
sich bei einem normalen History-Zustand auf Eins. Diese Sicherung wird beim De-
aktivieren der Oder-Verfeinerung durchgeführt. Beim Betreten des History-Zustands
werden entsprechend der gespeicherten Liste die Zustände wieder aktiviert bzw. die-
ser beim erstmaligen Betreten automatisch über seine ausgehende Transition verlassen.
Die Implementierung beschränkt sich daher auf die Erweiterung der Klasse für Pseudo-
zustände um eine Tiefensuche und die Möglichkeit der Speicherung einer Zustandsliste.
Abbildung 4.6 zeigt die entsprechenden Erweiterungen des Frameworks.
4.1. Konzeptioneller Aufbau       27




              Abbildung 4.6.: Erweiterung des Frameworks um Hierarchie


Nebenläufige Zustände
Nebenläufigkeit als der zweite zentrale Aspekt von Zustandsdiagrammen wird durch
das Hinzufügen einer neuen Klasse ConcurrentState erreicht. Diese ist wie die Oder-
Verfeinerung ein Kontext. Der essenzielle Unterschied ist, dass nicht genau ein Unterzu-
stand aktiv ist, sondern alle Unterzustände gleichzeitig. Regionen wiederum sind Oder-
Verfeinerungen, denen als Vaterknoten der nebenläufige Zustand zugewiesen wird.

Ereignisverarbeitung Die Verarbeitung eines eingehenden Ereignisses funktioniert
im Wesentlichen genauso wie bei hierarchischen Zuständen (siehe Abbildung 4.4). Der
Hauptunterschied ist der, dass das Ereignis nicht an einen Unterzustand, sondern an
alle Regionen delegiert und kein Startzustand gesetzt wird.
   Hierbei muss beachtet werden, dass ein Oder-Unterzustand das Ereignis nur dann
verarbeiten kann, wenn die Und-Verfeinerung aktiv ist: Wird beispielsweise der ne-
benläufige Zustand aus einer Region heraus über eine Transition verlassen, dürfen die
restlichen Bereiche das Signal nicht weiter verarbeiten. Sobald ein Unterzustand das
Ereignis behandeln konnte, gelten dieselben Abläufe wie bei hierarchischen Zuständen.
   Das Framework selbst unterstützt in dieser Form keine echte Nebenläufigkeit, son-
dern bearbeitet wie Ali und Tanaka die einzelnen Regionen sequenziell. Die Neben-
läufigkeit entsteht dadurch, dass alle Regionen im gleichen Schritt der Simulation auf
das Ereignis reagieren können.

Transitionen Diese haben bisher die Eigenschaft, dass ihnen eine Liste an Zustän-
den bekannt ist, die beim Schalten aktiviert bzw. deaktiviert werden müssen. Bei der
4. Das Statechart-Framework
 28




              Abbildung 4.7.: Ablauf der execute-Methode einer Transition


Und-Verfeinerung entsteht ein Problem: Wird direkt ein Unterzustand einer Region
angesprungen, stehen in der Liste der zu aktivierenden Zustände die Und-Verfeinerung
an Position n, die Region an n + 1 und der Unterzustand an n + 2. Da beim Betreten
des Und-Zustands automatisch alle Regionen aktiviert werden müssen, entsteht ein
Konflikt, denn die Aktivierung erfolgt immer an den Startzuständen der Bereiche.
  Es muss also eine Möglichkeit geschaffen werden, die es erlaubt einzelne Regio-
nen bei der Aktivierung des Und-Zustands zu ignorieren. Hierzu wird in der Klasse
ConcurrentState eine Liste von Regionen gepflegt, die nicht automatisch aktiviert wer-
den sollen. Diese Liste wird dynamisch zur Laufzeit von der Transition gefüllt, indem
geprüft wird, ob der Zielzustand des Übergangs in einer Region liegt oder die Und-
Verfeinerung selbst ist. Bei der Deaktivierung des Zustands wird diese Liste geleert.
Abbildung 4.7 zeigt den Ablauf beim Schalten einer Transition.
Gabelung einer Transition Die Implementierung des Fork-Zustands ist mit der
Erweiterung der Und-Verfeinerung um eine Menge der nicht automatisch zu aktivie-
renden Regionen einfach zu erreichen. Es wird dasselbe Prinzip angewendet wie bei
Transitionen: Zunächst wird ein Weg zu einem normalen Zustand gesucht. Ist dieser
gefunden worden, wird bei Erreichen des Fork-Zustands die Liste der Transitionen
durchlaufen und die jeweiligen Regionen ermittelt, die ignoriert werden müssen. Erst
danach werden die ausgehenden Transitionen nacheinander ausgeführt. Es reicht, die-
ses Vorgehen in der Klasse PseudoState in der Methode activate() zu programmieren.
Vereinigung mehrerer Transitionen Das Gegenstück zur Gabelung ist die Syn-
chronisation der einzelnen Regionen am Join-Zustand. Die Beendigungstransition wird
automatisch ausgeführt, wenn alle Regionen ihren jeweiligen Endzustand erreicht ha-
ben. Diese Prämisse ist beim Join-Zustand nicht erfüllt. Stattdessen bilden all diejeni-
gen Zustände einen gültigen „Endzustand“ der Und-Verfeinerung, die eine Transition
zum Join-Zustand besitzen. Im Folgenden wird diese Zustandsmenge als Endkonfigu-
ration bezeichnet.
  Es gibt prinzipiell zwei Stellen, an denen solch eine Endkonfiguration gespeichert
4.2. Implementierung      29




           Abbildung 4.8.: Erweiterung des Frameworks um Nebenläufigkeit



werden kann. Entweder im Und- oder im Join-Zustand. Da diese Menge mit letzterem
Typ assoziiert wird, soll diese dort gehalten werden. Die Klasse PseudoState bietet
hierfür zudem schon die benötigte Infrastruktur an. Der Anwender des Frameworks ist
dafür verantwortlich, dass dem Join-Zustand diese Endkonfiguration bekannt gemacht
wird. Die Methode lookup() führt neben der obligatorischen Tiefensuche im Falle des
Typs Join zusätzlich die Prüfung aus, ob die angegebenen Zustände aktiv sind.
  Diese einfache Implementierung birgt jedoch den Nachteil, dass nicht alle Aktionen
ausgeführt bzw. Bedingungen geprüft werden, die an den zum Join-Zustand hinfüh-
renden Transitionen stehen. Das Klassendiagramm aus Abbildung 4.8 zeigt die Ände-
rungen an dem Framework, die zur Realisierung der Nebenläufigkeit notwendig sind.


4.2 Implementierung
Im Folgenden wird die Implementierung des Frameworks beschrieben und auf Opti-
mierungen aufmerksam gemacht, die durch die Beschränkungen des RCX notwendig
wurden. Die Programmquellen sind in dem Paket statechart.base untergebracht. In
Abbildung 4.9 ist die Implementierung des Frameworks zu sehen. Diese unterscheidet
sich vom prinzipiellen Aufbau her nicht von dem vorgestellten Konzept. Aufgrund der
Anforderungen an das Framework wurden jedoch einige Änderungen erforderlich.
4. Das Statechart-Framework
30




     Abbildung 4.9.: Klassendiagramm der Implementierung des Frameworks
4.2. Implementierung       31


4.2.1 Speicherplatzoptimierungen
Insgesamt besteht das vorgestellte Framework aus einer möglichst minimalen Anzahl
an Klassen. Allerdings ist dies nur der erste Schritt um Speicherplatz zu sparen. Die
nächsten Abschnitte beschreiben die weiteren wesentlichen Optimierungen.

Verwaltung von Listen
Zunächst fällt auf, dass die zu verwaltenden Listen in einer Klasse über den vom JDK
zur Verfügung gestellten Vektor einen enormen Speicherplatzverbrauch verursachen.
Selbiges gilt für die Reimplementierung der Vektor-Klasse in LeJOS. Die Gründe hier-
für liegen an zwei Stellen:

  1. Es werden sehr viele Komfortmethoden angeboten, die die Handhabung der Klas-
     se vereinfachen sollen. Hierzu zählen z. B. unterschiedliche Parameterlisten.

  2. Die Methoden enthalten im Allgemeinen einen Programmcode, der prüft, ob die
     angegebenen Parameter im Definitionsbereich liegen.

   Da die Verwaltung der Listen ausschließlich im Framework stattfindet und der An-
wender keinen direkten Zugriff auf diese erhält, können die beiden aufgeführten Punkte
als Ansatz zur Platzersparnis verwendet werden. Hierzu werden unnötige Methoden
nicht implementiert und Sicherheitsüberprüfungen ausgeklammert. Dies führt dazu,
dass eine eigene Klasse Vector verwendet wird, die minimale Funktionalität besitzt
und somit platzsparend ist. Zusätzlich wird durch die ausschließliche Sichtbarkeit der
Klasse in dem Paket statechart.base sichergestellt, dass diese nur innerhalb des Pakets
Verwendung findet. Als Basis dient die gleichnamige Klasse aus dem LeJOS-Paket.

Verwendung statischer Methoden
An einigen Stellen werden Berechnungsmethoden verwendet, die in allen Instanzen
einer Klasse verwendet werden und nicht auf Klassenvariablen zugreifen. Hier ist ein
einfacher Trick die Verwendung von statischen Methoden.

Zeitereignis
Da wie in der Konzeption beschrieben kein Timeout-Ereignis als Klasse realisiert ist,
die Verarbeitung der Ereignisse aber über die dispatch-Methode stattfindet, wird als
Übergabeparameter null als Zeitereignis vereinbart. Die timeout-Methoden erhöhen
bei Aufruf nur die aktuelle Zeit im Zustand. Anschließend wird seitens der Klasse
Statechart auf dem derzeitigen Zustand die Ereignisverarbeitung angestoßen (siehe
Listing 4.1).

Objekterzeugung innerhalb des Frameworks
Ein essenzieller Punkt ist das Vermeiden von Objekt-Instanziierungen mittels new
innerhalb des Frameworks bei der Ereignisverarbeitung. Dies führt zu potenziell un-
überschaubar vielen Objekten und somit im Rahmen des RCX schnell zu einem Spei-
cherüberlauf. Objekte werden im Framework daher nur während der Konstruktion des
4. Das Statechart-Framework
 32


     Listing 4.1: Implementierung des Zeitereignis in den Klassen Statechart und State
// S t a t e c h a r t −K l a s s e
public void t i m e o u t ( i n t time )
{
  c u r r e n t S t a t e . t i m e o u t ( time ) ;
  c u r r e n t S t a t e . d i s p a t c h ( null ) ;
}

// S t a t e −K l a s s e
protected void t i m e o u t ( i n t time )
{
  currentTime += time ;
}




Zustandsdiagramms instanziiert. Sobald alle Zustände, Transitionen, Aktionen, Er-
eignisse und Bedingungen angelegt wurden, findet nur noch die Ereignisverarbeitung
mittels der timeout- und dispatch-Methoden statt. Neue Objekte werden zu diesem
Zeitpunkt seitens des Frameworks nicht mehr instanziiert.

4.2.2 Berechnung des LCA
Eines der bisher noch nicht berücksichtigten Elemente ist die Berechnung des kleins-
ten gemeinsamen Vorfahrens zweier Knoten. Diese findet in der statischen Methode
calculateStateSet der Klasse Transition statt. Auffällig ist der Rückgabewert. Hier-
bei handelt es sich um ein zweidimensionales Feld, welches die zu (de-)aktivierenden
Zustände beinhaltet. Dieses Array wird für jede Transition einmal in der benötigten
Größe erzeugt, sodass hier eine optimale Speicherausnutzung stattfindet. Die Berech-
nung selbst folgt einem einfachen Algorithmus:

   1. Speichere den Pfad vom Startzustand zum Wurzelknoten der Hierarchie.

   2. Speichere den Pfad vom Endzustand zum Wurzelknoten der Hierarchie.

   3. Wähle die Länge min des kürzeren Pfads.

   4. Setze i = 0.

   5. Solange i < min ist, vergleiche von der Wurzel ausgehend die Elemente der
      beiden Pfade an Position i.

          a) Falls die Elemente gleich sind, setzte i = i + 1.
          b) Falls die Elemente ungleich sind, stoppe den Vergleich. i − 1 ist der LCA.

  Für die Umsetzung fällt auf, dass in den Schritten eins und zwei temporäre Variablen
benötigt werden, die den Pfad sichern. Da dieser beliebig lang werden kann, muss in
4.2. Implementierung        33


der Implementierung ein dynamisches Feld verwendet werden. Die Klasse Vector bietet
sich hier an, bringt aber auch ein Problem mit sich: In jedem Aufruf des Algorithmus
werden zwei Objekte mittels new angelegt. Insgesamt werden bei n Transitionen 2n
temporäre Vektoren angelegt und somit unnötiger Speicherplatz verschwendet. Statt-
dessen werden außerhalb der statischen Methode zwei ebenfalls statische Hilfsvektoren
angelegt, sodass diese wiederverwendet werden können und 2n − 2 Objekte wegfallen.
Nach der Berechnung des LCA müssen die zu (de-)aktivierenden Zustände nur noch in
das hierzu angelegte Feld kopiert werden. Listing 4.2 zeigt den zugehörigen Quelltext.



4.2.3 Verwendung des Frameworks
Ein weiteres Ziel ist die einfache Verwendung des Frameworks. Aus diesem Grund
werden öffentlich sichtbare Hilfsfunktionen in den Klassen zur Verfügung gestellt, die
die Handhabung erleichtern und bei der Konstruktion syntaktisch korrekter Zustands-
diagramme helfen sollen. Hierzu zählen zum Beispiel die Methoden getStart() und
respektive getEnd() auf dem Kontext. Hierdurch wird nicht nur sichergestellt, dass
der Zugriff auf diese beiden Zustände einfach ist, sondern auch dass ein Kontext nur
einen Start- bzw. Endzustand1 besitzen kann. Ähnliche Komfortmethoden bieten die
hierarchischen Zustände zur Ermittlung des History-Zustands und die Pseudozustän-
de, um für die Vereinigung von Transitionen die Endkonfiguration angeben zu können.
Nebenläufige Zustände bieten die Möglichkeit, mittels addRegion() eine neue Region
zu ergänzen. Für die so ermittelten Zustände wird der Kontext automatisch gesetzt,
sodass der Anwender diesen nicht explizit setzen muss.
  Eine Besonderheit bieten Zustandsübergänge. Die Verknüpfung von einem Zustand
mit einer Transition findet automatisch beim Anlegen selbiger statt. Das heißt, es wird
dem Startzustand automatisch mitgeteilt, dass dieser eine neue abgehende Transition
erhält. So können Zustandsübergänge mit nur einer Programmzeile angelegt werden.
  Insgesamt bietet das Framework aufgrund dieser wenigen Hilfsfunktionen und mit
der Erweiterbarkeit durch die Interfaces Action, Guard und Event eine sehr einfa-
che Programmier-Schnittstelle für den Anwender. Die Verwendung funktioniert immer
nach dem selben Muster:
  1. Anlegen der Zustände (einfache, hierarchische, nebenläufige, Regionen und Pseu-
     dozustände).
  2. Aufbau der Hierarchie mittels der Methode setContext().
  3. Falls Join-Zustände verwendet werden, die Endkonfigurationen angeben.
  4. Erzeugen der Transitionen.
  Anschließend ist das Zustandsdiagramm einsatzbereit und kann in der Hauptpro-
grammschleife verwendet werden, welche Timeout-Signale und Ereignisse an das Dia-
gramm sendet. Ein Beispiel einer möglichen Programmschleife ist in Kapitel 7.3 zu
1 DieModellierung lässt mehrere Endzustände zu. Diese können jedoch immer zu einem zusammen-
  gefasst werden, sodass dies keine Einschränkung darstellt.
4. Das Statechart-Framework
    34



            Listing 4.2: Quelltext aus der Klasse Transition zur Berechnung des LCA
private s t a t i c V e c tor s t a = new Vector ( 2 0 ) ;
private s t a t i c V e c tor s t d = new Vector ( 2 0 ) ;

private s t a t i c S t a t e [ ] [ ] c a l c u l a t e S t a t e S e t ( S t a t e s t a r t , S t a t e end )
{
  // Pfad vom S t a r t zum Wurzelknoten e r m i t t e l n
  std . c l e a r ( ) ;
  State s = s t a r t ;
  while ( s != nu ll )
  {
    s t d . add ( 0 , s ) ;
    i f ( s . c o n t e x t instanceof H i e r a r c h i c a l S t a t e
            | | s . c o n t e x t instanceof C o n c u r r e n t S t a t e )
    {
        s = ( State ) s . context ;
    }
    e l s e s = nu ll ;
  }
  ...     // Q u e l l t e x t f ü r s t a a n a l o g

     // b e r e c h n e n d e s LCA
     i n t min = s t a . s i z e ( ) < s t d . s i z e ( ) ? s t a . s i z e ( ) : s t d . s i z e ( ) ;
     i n t l c a = min − 1 ; // G i l t f a l l s s t a r t=end . min i s t mind . 1
     i f ( s t a r t != end )
     {
         f o r ( l c a = 0 ; l c a < min ; l c a ++)
             i f ( s t a . g e t ( l c a ) != s t d . g e t ( l c a ) )
                break ;
     }

     // a n l e g e n d e s A u s g a b e a r r a y s
     S t a t e [ ] [ ] s t a t e s = new S t a t e [ 2 ] [ ] ;
     s t a t e s [ 0 ] = new S t a t e [ s t d . s i z e ( ) − l c a ] ;
     s t a t e s [ 1 ] = new S t a t e [ s t a . s i z e ( ) − l c a ] ;

     // k o p i e r e n d e r zu ( de −) a k t i v i e r e n d e n Zustände
     f o r ( i n t i = s t a t e s [ 0 ] . l e n g t h − 1 , j = l c a ; i >= 0 ; i −−, j ++)
         s t a t e s [ 0 ] [ i ] = ( State ) std . get ( j ) ;

     f o r ( i n t i = 0 , j = l c a ; i < s t a t e s [ 1 ] . l e n g t h ; i ++, j ++)
         s t a t e s [ 1 ] [ i ] = ( State ) sta . get ( j ) ;

     return s t a t e s ;
}
4.3. Unittests   35




           Abbildung 4.10.: Beispieldiagramm für die Umsetzung in den Quelltext


finden. Das Beispiel aus Listing 4.3 soll den Aufbau des Quelltextes verdeutlichen.
Hierzu wird das in Abbildung 4.10 dargestellte Zustandsdiagramm mit dem Frame-
work umgesetzt2 .
  Durch diesen einfachen und vor allem strukturell immer gleich aufgebauten Quell-
text, ist eine weitere Anforderung erfüllt: Die Vereinfachung der Codegenerierung da-
hingehend, dass nur eine Klasse generiert werden muss, in der das Framework verwen-
det wird. Eine genaue Beschreibung findet sich in Kapitel 7.


4.3 Unittests
Im Rahmen der Entwicklung ist das Testen der Software ein stetiger Begleiter. Da-
her soll dieser Schritt vollkommen automatisiert durchgeführt werden. Hierzu bietet
sich die Verwendung von JUnit (Clark u. a., 2006) als Testumgebung an. Allerdings
soll an dieser Stelle nur ein Verfahren erläutert werden, mit dem sich die Seman-
tik von Zustandsdiagrammen testen lässt und wie dieser Testaufbau mittels JUnit
umgesetzt werden kann. Die eigentlichen Testfälle sind im Anhang A zu finden. Da
der RCX-Baustein keine Möglichkeit zum automatisierten Testen anbietet, werden die
Prüfungen auf die Laufzeitumgebung für Zustandsdiagramme beschränkt.
   Das Testen von Zustandsdiagrammen basiert in diesem Ansatz auf einer einfachen
Erkenntnis: Der Durchlauf durch das Diagramm lässt sich komplett als eindeutiger
Pfad beschreiben. Hierbei wird jeweils registriert und aufgezeichnet, wann ein Zustand
aktiviert, deaktiviert oder eine Aktion ausgeführt wird. Das Testen besteht letztlich
darin, den durchlaufenen Pfad mit dem Soll-Pfad zu vergleichen. In letzterem wird vor-
gegeben, in welcher Reihenfolge die Zustände (de-)aktiviert und Aktionen ausgeführt
werden müssen.
   Hierbei scheinen die nebenläufigen Zustände Probleme zu bereiten, denn theoretisch
kann die Reihenfolge, in der die Regionen ein eingehendes Ereignis verarbeiten, immer
unterschiedlich sein, je nachdem welcher Prozess als nächstes die CPU-Zeit zugewiesen
bekommt. Dies würde ein wesentlich komplexeres Vorgehen erfordern, um die beiden
Pfade zu vergleichen, da für jede nebenläufige Region der Pfad aufgeteilt werden müss-
te. Um dies zu vermeiden, wird im Folgenden ohne Beschränkung der Allgemeinheit
2 Die   verwendeten Aktionen und Signale sind mit Pseudocode angegeben.
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis
Mocek Thesis

More Related Content

What's hot

lernOS Sketchnoting Leitfaden Version 1.0
lernOS Sketchnoting Leitfaden Version 1.0lernOS Sketchnoting Leitfaden Version 1.0
lernOS Sketchnoting Leitfaden Version 1.0Cogneon Akademie
 
Leseprobe: Deutsches Redmine Buch zur Anwendung und Administration
Leseprobe: Deutsches Redmine Buch zur Anwendung und AdministrationLeseprobe: Deutsches Redmine Buch zur Anwendung und Administration
Leseprobe: Deutsches Redmine Buch zur Anwendung und AdministrationClaudia Meindl
 
Homepage erstellen Benutzerhandbuch
Homepage erstellen BenutzerhandbuchHomepage erstellen Benutzerhandbuch
Homepage erstellen BenutzerhandbuchHomepageErstellen
 
SPSS: Praxis-Leitfaden
SPSS: Praxis-LeitfadenSPSS: Praxis-Leitfaden
SPSS: Praxis-LeitfadenRené Reineke
 
HTML5 und CSS3 Übersicht
HTML5 und CSS3 ÜbersichtHTML5 und CSS3 Übersicht
HTML5 und CSS3 ÜbersichtSven Brencher
 
lernOS für Dich Leitfaden (Version 1.6)
lernOS für Dich Leitfaden (Version 1.6)lernOS für Dich Leitfaden (Version 1.6)
lernOS für Dich Leitfaden (Version 1.6)Cogneon Akademie
 
Sappres Netweaver Identity Management
Sappres Netweaver Identity ManagementSappres Netweaver Identity Management
Sappres Netweaver Identity Managementgueste2a899
 
Tippsammlung 2010
Tippsammlung 2010Tippsammlung 2010
Tippsammlung 2010Cantabrian
 
lernOS Sketchnoting Leitfaden Version 0.4
lernOS Sketchnoting Leitfaden Version 0.4lernOS Sketchnoting Leitfaden Version 0.4
lernOS Sketchnoting Leitfaden Version 0.4Cogneon Akademie
 
Final Opentrans 2.0 Rfq
Final Opentrans 2.0   RfqFinal Opentrans 2.0   Rfq
Final Opentrans 2.0 Rfqguest6f1fb4
 
Sappress Sap Controlling2
Sappress Sap Controlling2Sappress Sap Controlling2
Sappress Sap Controlling2caradha
 
Informationsvisualisierung Im Semantic Web1
Informationsvisualisierung Im Semantic Web1Informationsvisualisierung Im Semantic Web1
Informationsvisualisierung Im Semantic Web1brisvegas1
 
Handbuch CONSIDEO Modeler V 5.0
Handbuch CONSIDEO Modeler V 5.0Handbuch CONSIDEO Modeler V 5.0
Handbuch CONSIDEO Modeler V 5.0Detlef Kahrs
 
The book I wrote: You can order it:http://www.amazon.de/Teile-Lagermanagement...
The book I wrote: You can order it:http://www.amazon.de/Teile-Lagermanagement...The book I wrote: You can order it:http://www.amazon.de/Teile-Lagermanagement...
The book I wrote: You can order it:http://www.amazon.de/Teile-Lagermanagement...Bernhard Seilz
 
Elektronischer Geschäftsverkehr in Mittelstand und Handwerk 2010 - Ergebniss...
Elektronischer Geschäftsverkehr in Mittelstand und Handwerk 2010 -  Ergebniss...Elektronischer Geschäftsverkehr in Mittelstand und Handwerk 2010 -  Ergebniss...
Elektronischer Geschäftsverkehr in Mittelstand und Handwerk 2010 - Ergebniss...eBusinessLotse-Suedwestfalen-Hagen
 
Machbarkeitsanalyse und prototypische Entwicklung eines eMagazines für das A...
Machbarkeitsanalyse und prototypische Entwicklung eines eMagazines für das A...Machbarkeitsanalyse und prototypische Entwicklung eines eMagazines für das A...
Machbarkeitsanalyse und prototypische Entwicklung eines eMagazines für das A...Jonathan Keller
 

What's hot (19)

Projektmanagement kompakt
Projektmanagement kompaktProjektmanagement kompakt
Projektmanagement kompakt
 
Handbuch
HandbuchHandbuch
Handbuch
 
lernOS Sketchnoting Leitfaden Version 1.0
lernOS Sketchnoting Leitfaden Version 1.0lernOS Sketchnoting Leitfaden Version 1.0
lernOS Sketchnoting Leitfaden Version 1.0
 
Leseprobe: Deutsches Redmine Buch zur Anwendung und Administration
Leseprobe: Deutsches Redmine Buch zur Anwendung und AdministrationLeseprobe: Deutsches Redmine Buch zur Anwendung und Administration
Leseprobe: Deutsches Redmine Buch zur Anwendung und Administration
 
Homepage erstellen Benutzerhandbuch
Homepage erstellen BenutzerhandbuchHomepage erstellen Benutzerhandbuch
Homepage erstellen Benutzerhandbuch
 
SPSS: Praxis-Leitfaden
SPSS: Praxis-LeitfadenSPSS: Praxis-Leitfaden
SPSS: Praxis-Leitfaden
 
HTML5 und CSS3 Übersicht
HTML5 und CSS3 ÜbersichtHTML5 und CSS3 Übersicht
HTML5 und CSS3 Übersicht
 
lernOS für Dich Leitfaden (Version 1.6)
lernOS für Dich Leitfaden (Version 1.6)lernOS für Dich Leitfaden (Version 1.6)
lernOS für Dich Leitfaden (Version 1.6)
 
Sappres Netweaver Identity Management
Sappres Netweaver Identity ManagementSappres Netweaver Identity Management
Sappres Netweaver Identity Management
 
Tippsammlung 2010
Tippsammlung 2010Tippsammlung 2010
Tippsammlung 2010
 
[DE] Dr. Ulrich Kampffmeyer - Artikel auf Wikipedia | 2015
[DE] Dr. Ulrich Kampffmeyer - Artikel auf Wikipedia | 2015[DE] Dr. Ulrich Kampffmeyer - Artikel auf Wikipedia | 2015
[DE] Dr. Ulrich Kampffmeyer - Artikel auf Wikipedia | 2015
 
lernOS Sketchnoting Leitfaden Version 0.4
lernOS Sketchnoting Leitfaden Version 0.4lernOS Sketchnoting Leitfaden Version 0.4
lernOS Sketchnoting Leitfaden Version 0.4
 
Final Opentrans 2.0 Rfq
Final Opentrans 2.0   RfqFinal Opentrans 2.0   Rfq
Final Opentrans 2.0 Rfq
 
Sappress Sap Controlling2
Sappress Sap Controlling2Sappress Sap Controlling2
Sappress Sap Controlling2
 
Informationsvisualisierung Im Semantic Web1
Informationsvisualisierung Im Semantic Web1Informationsvisualisierung Im Semantic Web1
Informationsvisualisierung Im Semantic Web1
 
Handbuch CONSIDEO Modeler V 5.0
Handbuch CONSIDEO Modeler V 5.0Handbuch CONSIDEO Modeler V 5.0
Handbuch CONSIDEO Modeler V 5.0
 
The book I wrote: You can order it:http://www.amazon.de/Teile-Lagermanagement...
The book I wrote: You can order it:http://www.amazon.de/Teile-Lagermanagement...The book I wrote: You can order it:http://www.amazon.de/Teile-Lagermanagement...
The book I wrote: You can order it:http://www.amazon.de/Teile-Lagermanagement...
 
Elektronischer Geschäftsverkehr in Mittelstand und Handwerk 2010 - Ergebniss...
Elektronischer Geschäftsverkehr in Mittelstand und Handwerk 2010 -  Ergebniss...Elektronischer Geschäftsverkehr in Mittelstand und Handwerk 2010 -  Ergebniss...
Elektronischer Geschäftsverkehr in Mittelstand und Handwerk 2010 - Ergebniss...
 
Machbarkeitsanalyse und prototypische Entwicklung eines eMagazines für das A...
Machbarkeitsanalyse und prototypische Entwicklung eines eMagazines für das A...Machbarkeitsanalyse und prototypische Entwicklung eines eMagazines für das A...
Machbarkeitsanalyse und prototypische Entwicklung eines eMagazines für das A...
 

Viewers also liked

Schülerzeitung BuGaLu März 2013
Schülerzeitung BuGaLu März 2013Schülerzeitung BuGaLu März 2013
Schülerzeitung BuGaLu März 2013rschmid
 
Forschungsergebnisse dauerhaft zugänglich machen - Strategien und Erfahrunge...
Forschungsergebnisse dauerhaft zugänglich machen - Strategien und Erfahrunge...Forschungsergebnisse dauerhaft zugänglich machen - Strategien und Erfahrunge...
Forschungsergebnisse dauerhaft zugänglich machen - Strategien und Erfahrunge...Heinz Pampel
 
Catalogue d'Antoine Nabajoth
Catalogue d'Antoine NabajothCatalogue d'Antoine Nabajoth
Catalogue d'Antoine NabajothFondationClement
 
Introduction au développement windows 8 modern ui avec html5 et javascript
Introduction au développement windows 8 modern ui avec html5 et javascriptIntroduction au développement windows 8 modern ui avec html5 et javascript
Introduction au développement windows 8 modern ui avec html5 et javascriptdavrous
 
Sites web de bibliothèques et terminaux mobiles
Sites web de bibliothèques et terminaux mobiles Sites web de bibliothèques et terminaux mobiles
Sites web de bibliothèques et terminaux mobiles Pierre Naegelen
 
GENERATIONDESIGN Messereview Ambiente 2013
GENERATIONDESIGN Messereview Ambiente 2013GENERATIONDESIGN Messereview Ambiente 2013
GENERATIONDESIGN Messereview Ambiente 2013GENERATIONDESIGN GmbH
 
S2 verbosoperativosparalosproyectosdeinnovación
S2 verbosoperativosparalosproyectosdeinnovaciónS2 verbosoperativosparalosproyectosdeinnovación
S2 verbosoperativosparalosproyectosdeinnovaciónUSET
 
LE DICTIONNAIRE DES CHAMPS SÉMANTI-QUES DANS LA TRADITION DE LA LANGUE ESPAG...
LE DICTIONNAIRE DES CHAMPS SÉMANTI-QUES DANS LA TRADITION DE LA  LANGUE ESPAG...LE DICTIONNAIRE DES CHAMPS SÉMANTI-QUES DANS LA TRADITION DE LA  LANGUE ESPAG...
LE DICTIONNAIRE DES CHAMPS SÉMANTI-QUES DANS LA TRADITION DE LA LANGUE ESPAG...EL ESPAÑOL Y OTRAS LENGUAS
 
ARDESI : Les Midi-Pyrénéens et la Société de l’Information 24-11-11
ARDESI : Les Midi-Pyrénéens et la Société de l’Information 24-11-11ARDESI : Les Midi-Pyrénéens et la Société de l’Information 24-11-11
ARDESI : Les Midi-Pyrénéens et la Société de l’Information 24-11-11CRIJ Occitanie - site Toulouse
 
Gimp 2 (+ Fotomontajes 1 Y 2)
Gimp 2 (+ Fotomontajes 1 Y 2)Gimp 2 (+ Fotomontajes 1 Y 2)
Gimp 2 (+ Fotomontajes 1 Y 2)javiraulhector
 
Produktpolitik für stromsparende Produkte
Produktpolitik für stromsparende ProdukteProduktpolitik für stromsparende Produkte
Produktpolitik für stromsparende ProdukteOeko-Institut
 
La Matinale : Introduction à Windows 8
La Matinale : Introduction à Windows 8La Matinale : Introduction à Windows 8
La Matinale : Introduction à Windows 8X-PRIME GROUPE
 

Viewers also liked (20)

Schülerzeitung BuGaLu März 2013
Schülerzeitung BuGaLu März 2013Schülerzeitung BuGaLu März 2013
Schülerzeitung BuGaLu März 2013
 
Tribus De L OMO
Tribus De L OMOTribus De L OMO
Tribus De L OMO
 
What's Hot - Juin 2015
What's Hot - Juin 2015What's Hot - Juin 2015
What's Hot - Juin 2015
 
Forschungsergebnisse dauerhaft zugänglich machen - Strategien und Erfahrunge...
Forschungsergebnisse dauerhaft zugänglich machen - Strategien und Erfahrunge...Forschungsergebnisse dauerhaft zugänglich machen - Strategien und Erfahrunge...
Forschungsergebnisse dauerhaft zugänglich machen - Strategien und Erfahrunge...
 
Catalogue d'Antoine Nabajoth
Catalogue d'Antoine NabajothCatalogue d'Antoine Nabajoth
Catalogue d'Antoine Nabajoth
 
Introduction au développement windows 8 modern ui avec html5 et javascript
Introduction au développement windows 8 modern ui avec html5 et javascriptIntroduction au développement windows 8 modern ui avec html5 et javascript
Introduction au développement windows 8 modern ui avec html5 et javascript
 
Demo Day : ClevLab
Demo Day : ClevLabDemo Day : ClevLab
Demo Day : ClevLab
 
Sites web de bibliothèques et terminaux mobiles
Sites web de bibliothèques et terminaux mobiles Sites web de bibliothèques et terminaux mobiles
Sites web de bibliothèques et terminaux mobiles
 
Adobe connectskype1.0
Adobe connectskype1.0Adobe connectskype1.0
Adobe connectskype1.0
 
Bussunda
BussundaBussunda
Bussunda
 
GENERATIONDESIGN Messereview Ambiente 2013
GENERATIONDESIGN Messereview Ambiente 2013GENERATIONDESIGN Messereview Ambiente 2013
GENERATIONDESIGN Messereview Ambiente 2013
 
S2 verbosoperativosparalosproyectosdeinnovación
S2 verbosoperativosparalosproyectosdeinnovaciónS2 verbosoperativosparalosproyectosdeinnovación
S2 verbosoperativosparalosproyectosdeinnovación
 
LE DICTIONNAIRE DES CHAMPS SÉMANTI-QUES DANS LA TRADITION DE LA LANGUE ESPAG...
LE DICTIONNAIRE DES CHAMPS SÉMANTI-QUES DANS LA TRADITION DE LA  LANGUE ESPAG...LE DICTIONNAIRE DES CHAMPS SÉMANTI-QUES DANS LA TRADITION DE LA  LANGUE ESPAG...
LE DICTIONNAIRE DES CHAMPS SÉMANTI-QUES DANS LA TRADITION DE LA LANGUE ESPAG...
 
Presentación Raúl Sánchez
Presentación Raúl SánchezPresentación Raúl Sánchez
Presentación Raúl Sánchez
 
ARDESI : Les Midi-Pyrénéens et la Société de l’Information 24-11-11
ARDESI : Les Midi-Pyrénéens et la Société de l’Information 24-11-11ARDESI : Les Midi-Pyrénéens et la Société de l’Information 24-11-11
ARDESI : Les Midi-Pyrénéens et la Société de l’Information 24-11-11
 
Gimp 2 (+ Fotomontajes 1 Y 2)
Gimp 2 (+ Fotomontajes 1 Y 2)Gimp 2 (+ Fotomontajes 1 Y 2)
Gimp 2 (+ Fotomontajes 1 Y 2)
 
Produktpolitik für stromsparende Produkte
Produktpolitik für stromsparende ProdukteProduktpolitik für stromsparende Produkte
Produktpolitik für stromsparende Produkte
 
Ablaufdiagramm
AblaufdiagrammAblaufdiagramm
Ablaufdiagramm
 
La Matinale : Introduction à Windows 8
La Matinale : Introduction à Windows 8La Matinale : Introduction à Windows 8
La Matinale : Introduction à Windows 8
 
Creación de un blog
Creación de un blogCreación de un blog
Creación de un blog
 

Similar to Mocek Thesis

Team Oldenburger Robo-Fußball – Abschlussbericht der Projektgruppe 2010
Team Oldenburger Robo-Fußball – Abschlussbericht  der Projektgruppe  2010Team Oldenburger Robo-Fußball – Abschlussbericht  der Projektgruppe  2010
Team Oldenburger Robo-Fußball – Abschlussbericht der Projektgruppe 2010Johannes Diemke
 
Vergleich des Scala Web-Frameworks Lift mit dem Java EE Programmiermodell
Vergleich des Scala Web-Frameworks Lift mit dem Java EE ProgrammiermodellVergleich des Scala Web-Frameworks Lift mit dem Java EE Programmiermodell
Vergleich des Scala Web-Frameworks Lift mit dem Java EE Programmiermodelladesso AG
 
Algorithmen und Applikationen zur interaktiven Visualisierung und Analyse ch...
Algorithmen und Applikationen zur interaktiven  Visualisierung und Analyse ch...Algorithmen und Applikationen zur interaktiven  Visualisierung und Analyse ch...
Algorithmen und Applikationen zur interaktiven Visualisierung und Analyse ch...Frank Oellien
 
Handbuch de
Handbuch deHandbuch de
Handbuch degordem
 
Large Scale Multilayer Perceptron
Large Scale Multilayer PerceptronLarge Scale Multilayer Perceptron
Large Scale Multilayer PerceptronSascha Jonas
 
Bachelorarbeit paul gerber.pdf
Bachelorarbeit paul gerber.pdfBachelorarbeit paul gerber.pdf
Bachelorarbeit paul gerber.pdfwissem hammouda
 
Visualisierung von Algorithmen und Datenstrukturen
Visualisierung von Algorithmen und DatenstrukturenVisualisierung von Algorithmen und Datenstrukturen
Visualisierung von Algorithmen und DatenstrukturenRoland Bruggmann
 
Master thesis pascal_mueller01
Master thesis pascal_mueller01Master thesis pascal_mueller01
Master thesis pascal_mueller01guest39ce4e
 

Similar to Mocek Thesis (20)

Da Hanno Rabe
Da Hanno RabeDa Hanno Rabe
Da Hanno Rabe
 
Dsvdoc
DsvdocDsvdoc
Dsvdoc
 
Dsvdoc
DsvdocDsvdoc
Dsvdoc
 
Dsvdoc
DsvdocDsvdoc
Dsvdoc
 
Dsvdoc
DsvdocDsvdoc
Dsvdoc
 
Dsvdoc
DsvdocDsvdoc
Dsvdoc
 
Dsvdoc
DsvdocDsvdoc
Dsvdoc
 
Dsvdoc
DsvdocDsvdoc
Dsvdoc
 
Dsvdoc
DsvdocDsvdoc
Dsvdoc
 
Team Oldenburger Robo-Fußball – Abschlussbericht der Projektgruppe 2010
Team Oldenburger Robo-Fußball – Abschlussbericht  der Projektgruppe  2010Team Oldenburger Robo-Fußball – Abschlussbericht  der Projektgruppe  2010
Team Oldenburger Robo-Fußball – Abschlussbericht der Projektgruppe 2010
 
Vergleich des Scala Web-Frameworks Lift mit dem Java EE Programmiermodell
Vergleich des Scala Web-Frameworks Lift mit dem Java EE ProgrammiermodellVergleich des Scala Web-Frameworks Lift mit dem Java EE Programmiermodell
Vergleich des Scala Web-Frameworks Lift mit dem Java EE Programmiermodell
 
Algorithmen und Applikationen zur interaktiven Visualisierung und Analyse ch...
Algorithmen und Applikationen zur interaktiven  Visualisierung und Analyse ch...Algorithmen und Applikationen zur interaktiven  Visualisierung und Analyse ch...
Algorithmen und Applikationen zur interaktiven Visualisierung und Analyse ch...
 
Diplomarbeit
DiplomarbeitDiplomarbeit
Diplomarbeit
 
Handbuch de
Handbuch deHandbuch de
Handbuch de
 
Large Scale Multilayer Perceptron
Large Scale Multilayer PerceptronLarge Scale Multilayer Perceptron
Large Scale Multilayer Perceptron
 
Bachelorarbeit paul gerber.pdf
Bachelorarbeit paul gerber.pdfBachelorarbeit paul gerber.pdf
Bachelorarbeit paul gerber.pdf
 
Visualisierung von Algorithmen und Datenstrukturen
Visualisierung von Algorithmen und DatenstrukturenVisualisierung von Algorithmen und Datenstrukturen
Visualisierung von Algorithmen und Datenstrukturen
 
Projektkommunikation: Leseprobe
Projektkommunikation: LeseprobeProjektkommunikation: Leseprobe
Projektkommunikation: Leseprobe
 
J3dboolop
J3dboolopJ3dboolop
J3dboolop
 
Master thesis pascal_mueller01
Master thesis pascal_mueller01Master thesis pascal_mueller01
Master thesis pascal_mueller01
 

Mocek Thesis

  • 1. Christian Mocek Erweiterung des CASE-Werkzeugs DAVE um einen Code-Generator für LEGO Mindstorms Diplomarbeit 7. Mai 2006 Gutachter: Universität Dortmund Lehrstuhl für Software-Technologie Prof. Dr. Ernst-Erich Doberkat Baroper Straße 301 Dipl.-Inform. Jörg Pleumann 44227 Dortmund
  • 2. II
  • 3. Vorwort Dass mir die Leidenschaft meiner Kindheit am Ende des Studiums begegnet, hätte ich mir niemals träumen lassen. Schon als kleines Kind war ich von LEGO, insbesondere LEGO Technik, begeistert und freue mich auch heute immer wieder, wenn ich mit meinem Neffen die kleinen bunten Steine zusammensetzen kann. Auf der Suche nach einem Thema für meine Diplomarbeit stieß ich dann auf eins, welches mich vom ersten Augenblick an interessierte: Die Steuerung von LEGO Mindstorms-Robotern mit Hil- fe von Zustandsdiagrammen. Nach einigen Vorgesprächen mit meinem Betreuer sowie Gutachter Jörg Pleumann und langen Überlegungen - mit zugegeben einigem Zwei- fel, ob sich dieses Unterfangen überhaupt realisieren lässt - entschied ich mich dafür, diese Herausforderung anzunehmen. Denn wer hat schon die Möglichkeit, in seiner Di- plomarbeit mit LEGO spielen zu dürfen? Natürlich von einem rein wissenschaftlichen Standpunkt betrachtet, versteht sich. So begann eine Zeit unzähliger Stunden Arbeit, einigen frustrierenden Momenten und vielen Gesprächen über das Thema mit meinem Betreuer. Doch letztlich haben sich all die Mühen gelohnt, als die ersten Roboter ih- re Aufgaben mit Hilfe von Zustandsdiagrammen lösten und die letzten Zeilen dieser Arbeit getippt waren. An dieser Stelle bedanke ich mich für die Hilfe all jener Personen, die mich in der langen Zeit in irgendeiner Weise unterstützt haben diese Arbeit zu erstellen. Zunächst bedanke ich mich bei meinen Eltern, die immer an mich geglaubt haben und denen diese Arbeit gewidmet ist. Ganz besonderer Dank gilt zudem Jörg Pleumann, welcher mir jederzeit verständnisvoll geholfen und meine häufigen Fragen geduldig beantwortet hat. Insbesondere möchte ich auch Peter Segschneider und seiner Frau Christel sowie Nina Schilf für ihre Freundschaft und moralischen Unterstützung in der langen Zeit danken. Ein weiterer Dank gilt meinen Korrekturlesern, die sich eisern auf der Suche nach Fehlern durch diesen Text gelesen haben. Herten, im Mai 2006 Christian Mocek
  • 4. IV
  • 5. Inhaltsverzeichnis 1 Thema der Arbeit 1 1.1 Motivation der Arbeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.2 Zielsetzung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1.3 Geplantes Vorgehen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 2 Grundbegriffe 5 2.1 Zustandsdiagramme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2.1.1 Elemente und Semantik von Zustandsdiagrammen . . . . . . . . 5 2.1.2 Implementierungsansätze . . . . . . . . . . . . . . . . . . . . . . 11 2.2 LEGO Mindstorms Roboter . . . . . . . . . . . . . . . . . . . . . . . . . 14 2.2.1 Aufbau der Hardware . . . . . . . . . . . . . . . . . . . . . . . . 14 2.2.2 Programmierung der LEGO-Roboter . . . . . . . . . . . . . . . . 15 3 Lösungsansatz 17 3.1 Zielplattform . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 3.2 Ansatzpunkte zur Integration in DAVE . . . . . . . . . . . . . . . . . . 18 3.2.1 Die Simulationsmaschine . . . . . . . . . . . . . . . . . . . . . . . 18 3.2.2 Wahl der zu verwendenden Datenstruktur . . . . . . . . . . . . . 19 3.3 Implementierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 3.4 Gesamtaufbau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 4 Das Statechart-Framework 21 4.1 Konzeptioneller Aufbau . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 4.1.1 Zeitgesteuerte Transitionen . . . . . . . . . . . . . . . . . . . . . 22 4.1.2 Segmentierte Transitionen . . . . . . . . . . . . . . . . . . . . . . 23 4.1.3 Hierarchie und Nebenläufigkeit . . . . . . . . . . . . . . . . . . . 25 4.2 Implementierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 4.2.1 Speicherplatzoptimierungen . . . . . . . . . . . . . . . . . . . . . 31 4.2.2 Berechnung des LCA . . . . . . . . . . . . . . . . . . . . . . . . . 32 4.2.3 Verwendung des Frameworks . . . . . . . . . . . . . . . . . . . . 33 4.3 Unittests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 5 Integration der RCX-Elemente in Zustandsdiagramme 41 5.1 Startsymbol . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 5.2 Grundregeln . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 5.3 Initialisieren der Sensoren . . . . . . . . . . . . . . . . . . . . . . . . . . 43 5.4 Verarbeiten eines Ereignisses . . . . . . . . . . . . . . . . . . . . . . . . 44 5.5 Aktionen und Bedingungen . . . . . . . . . . . . . . . . . . . . . . . . . 44
  • 6. Inhaltsverzeichnis VI 5.5.1 Ausgänge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 5.5.2 Sensoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 5.5.3 Variablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 5.5.4 LC-Display . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 6 Steuerung des RCX mit Hilfe des Frameworks 49 6.1 Ausgänge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 6.1.1 Aktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 6.1.2 Bedingungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 6.2 Sensoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 6.2.1 Notwendige Optimierungen . . . . . . . . . . . . . . . . . . . . . 51 6.2.2 Ereignisse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 6.2.3 Aktionen und Bedingungen . . . . . . . . . . . . . . . . . . . . . 53 6.3 Variablen und einfache Arithmetik . . . . . . . . . . . . . . . . . . . . . 54 7 Codegenerierung 57 7.1 Das XML-Format von DAVE . . . . . . . . . . . . . . . . . . . . . . . . 57 7.2 Verarbeitung der XML-Datei . . . . . . . . . . . . . . . . . . . . . . . . 59 7.2.1 Implementierung in Java . . . . . . . . . . . . . . . . . . . . . . . 59 7.2.2 Freemarker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 7.2.3 Transformationen mittels XSL und XPath . . . . . . . . . . . . . 60 7.3 Die Codegenerierung im Detail . . . . . . . . . . . . . . . . . . . . . . . 62 7.3.1 Umsetzung mittels XSLT . . . . . . . . . . . . . . . . . . . . . . 62 7.3.2 Interpretieren der EBNF-Regeln . . . . . . . . . . . . . . . . . . 65 7.3.3 Aktivieren und Deaktivieren der Sensoren . . . . . . . . . . . . . 66 7.3.4 Aufbau des Zustandsdiagramms . . . . . . . . . . . . . . . . . . . 68 7.3.5 Aktionen und Bedingungen . . . . . . . . . . . . . . . . . . . . . 73 8 Anbindung an DAVE mittels Ant 75 9 Anwendungsbeispiele 79 9.1 Aufgaben für die LEGO-Testunterlage . . . . . . . . . . . . . . . . . . . 79 9.1.1 Aufgabe 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 9.1.2 Aufgabe 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 9.1.3 Aufgabe 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 9.2 Eine Sortieranlage für LEGO-Steine . . . . . . . . . . . . . . . . . . . . 83 9.2.1 Aufgabe 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 9.2.2 Aufgabe 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 9.2.3 Aufgabe 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 10 Fazit 89 11 Ausblick 91
  • 7. Inhaltsverzeichnis VII A Testfälle 93 A.1 Einfache Elemente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 A.2 Hierarchische Zustände . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 A.3 Nebenläufige Zustände . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 B Baupläne 101 B.1 Ein mobiler Roboter für die Testunterlage . . . . . . . . . . . . . . . . . 101 B.1.1 Linker Motorblock . . . . . . . . . . . . . . . . . . . . . . . . . . 101 B.1.2 Rechter Motorblock . . . . . . . . . . . . . . . . . . . . . . . . . 104 B.1.3 Zusammenbau der Komponenten . . . . . . . . . . . . . . . . . . 106 B.2 Eine Sortiermaschine für LEGO-Steine . . . . . . . . . . . . . . . . . . . 110 B.2.1 Klappe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 B.2.2 Förderband . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 B.2.3 Unterbau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 B.2.4 Zusammenbau der Komponenten . . . . . . . . . . . . . . . . . . 119 B.2.5 Kiste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
  • 9. Abbildungsverzeichnis 1.1 Das CASE-Werkzeug DAVE . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.2 Verwendung von Zustandsdiagrammen in eingebetteten Systemen . . . . 3 2.1 Umsetzung eines endlichen Automaten in prozeduralen Quelltext . . . . 12 2.2 Umsetzung des Beispielautomaten mit Hilfe des State-Patterns . . . . . 13 2.3 Beispiel der Abbildung von Hierarchie und Nebenläufigkeit in die Klas- senhierarchie objektorientierter Sprachen auf Basis des State-Patterns . 13 2.4 Klassendiagramm des FSM-Frameworks von Bosch und van Gurp . . . . 14 2.5 Der RCX-Baustein . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 3.1 Aufbau des Gesamtkonzepts . . . . . . . . . . . . . . . . . . . . . . . . . 20 4.1 Konzeptioneller Aufbau des Frameworks ohne Berücksichtigung hierar- chischer und nebenläufiger Zustände . . . . . . . . . . . . . . . . . . . . 22 4.2 Erweiterung der Klassen State und Transition für zeitgesteuerte Tran- sitionen, sowie Einführung der Klasse PseudoState . . . . . . . . . . . . 23 Verarbeitung segmentierter Transitionen für den Fall x = 0 . . . . . . 4.3 . 24 4.4 Ereignisverarbeitung auf dem Oder-Zustand . . . . . . . . . . . . . . . . 25 4.5 Transitionsverhalten bei hierarchischen Zuständen . . . . . . . . . . . . 26 4.6 Erweiterung des Frameworks um Hierarchie . . . . . . . . . . . . . . . . 27 4.7 Ablauf der execute-Methode einer Transition . . . . . . . . . . . . . . . 28 4.8 Erweiterung des Frameworks um Nebenläufigkeit . . . . . . . . . . . . . 29 4.9 Klassendiagramm der Implementierung des Frameworks . . . . . . . . . 30 4.10 Beispieldiagramm für die Umsetzung in den Quelltext . . . . . . . . . . 35 4.11 Klassendiagramm zur Implementierung der Testfälle . . . . . . . . . . . 37 4.12 Beschreibung des Pfads, welcher beim Durchlauf durch das Diagramm zurückgelegt wird . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 4.13 Beispieldiagramm für einen Testfall . . . . . . . . . . . . . . . . . . . . . 39 4.14 Ablauf eines Testfalls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 5.1 Beispieldiagramm zur Verwendung der spezifizierten Syntax . . . . . . . 47 6.1 Framework-Erweiterung zur Steuerung der Ausgänge des RCX . . . . . 50 6.2 Framework-Erweiterung zur Steuerung der Sensoren des RCX . . . . . . 52 6.3 Framework-Erweiterung zum Rechnen mit dem RCX . . . . . . . . . . . 55 8.1 DAVE nach der Integration und Ausführung des Ant-Skripts . . . . . . 78 9.1 LEGO-Testunterlage für den Lichtsensor . . . . . . . . . . . . . . . . . . 79
  • 10. Abbildungsverzeichnis X 9.2 Modell des Roboters für die Testunterlage . . . . . . . . . . . . . . . . . 80 9.3 Ablauf einer einfachen Rundfahrt auf der Testunterlage . . . . . . . . . 80 9.4 Modifizierte Testunterlage . . . . . . . . . . . . . . . . . . . . . . . . . . 81 9.5 Ablauf einer Rundfahrt auf der modifizierten Testunterlage . . . . . . . 81 9.6 Zählen der grünen Blöcke auf der Testunterlage . . . . . . . . . . . . . . 82 9.7 Zustandsdiagramm für Aufgabe 3 . . . . . . . . . . . . . . . . . . . . . . 83 9.8 LEGO-Modell der Sortieranlage für LEGO-Steine. . . . . . . . . . . . . 84 9.9 Konzept einer einfachen Sortieranlage für LEGO-Steine . . . . . . . . . 84 9.10 Aufbau des Rotationssensors . . . . . . . . . . . . . . . . . . . . . . . . 85 9.11 Sortieren verschiedener LEGO-Steine anhand ihrer Farbe . . . . . . . . 86 9.12 Erweiterung des bisherigen Sortierers . . . . . . . . . . . . . . . . . . . . 87 9.13 Sequenzielles Füllen der Kisten mit Hilfe der Sortiermaschine . . . . . . 88
  • 11. Kapitel 1 Thema der Arbeit Da die Anforderungen an heutige Softwaresysteme immer weiter ansteigen, wird auch deren Entwicklung immer komplexer und kostspieliger. Um den Überblick über Struk- turen und Abläufe in dem System behalten zu können, ist deren Dokumentation schon in der Planungsphase enorm wichtig. Denn zum einen erleichtert dies anderen Ent- wicklern sich einzuarbeiten und zum anderen können durch solch eine Dokumentation frühzeitig Designfehler oder -mängel entdeckt werden. Die Abstraktionsebene reicht von der allgemeinen Beschreibung von Anwendungsfällen bis hin zur konkreten Im- plementierung und Beschreibung von Objektverhalten. Ein hierbei immer wichtiger gewordenes Hilfsmittel ist die von der Object Management Group eingeführte Unified Modelling Language (OMG, 2003). Aus diesem Grund ist es daher unerlässlich, die Studenten im Rahmen von Übungen und Projektarbeiten an die Modellierung von Software mittels UML heranzuführen. Da jedoch die normalen Modellierungstools für die Lehre aufgrund ihrer Komplexi- tät und des hohen Preises ungeeignet sind, wurden im Rahmen des MuSoft-Projektes (Doberkat und Engels, 2002) mehrere Werkzeuge entwickelt, welche im Funktions- umfang explizit auf die Lehre ausgelegt sind. Eines dieser Programme ist der an der Dortmunder Universität entstandene Dortmunder Automatenvisualisierer und -editor (Pleumann, 2003). DAVE (siehe Abbildung 1.1) beschränkt sich auf die Modellierung und Simulation von Zustandsdiagrammen1 - einer Verallgemeinerung von endlichen Automaten, die unter anderem um Hierarchie und Nebenläufigkeit erweitert wurden. 1.1 Motivation der Arbeit Das Ziel von DAVE ist das anschauliche Vermitteln der Syntax und Semantik von Zustandsdiagrammen. Hierbei ist eine wesentliche Komponente die Simulation: Die Studenten sind in der Lage, ihre Modelle auszuführen und somit deren Laufzeitver- halten zu beobachten. Um einen besseren Bezug zwischen der abstrakten graphischen Notation und dem Objekt, dessen Verhalten beschrieben wird, herzustellen, unter- stützt DAVE die Simulation zusätzlich durch multimediale Animationen (zum Bei- spiel eine Waschmaschine). Aufgrund dieses Bezugs von etwas Abstraktem zu et- 1 Essei angemerkt, dass sich DAVE auf die in der UML-Spezifikation beschriebene Syntax und Semantik bezieht (OMG, 2003). Diese unterscheidet sich etwas von der von Harel beschriebenen (Harel, 1987). Die wesentlichen Konzepte sind jedoch gleich.
  • 12. 1. Thema der Arbeit 2 Abbildung 1.1.: Das CASE-Werkzeug DAVE was Anschaulichem kann den Studenten der Nutzen und die Semantik von UML- Zustandsdiagrammen besser vermittelt werden. Eine genaue Beschreibung des Werk- zeugs findet sich in (Pleumann, 2004). Umfangreiche Untersuchungen haben gezeigt, dass DAVE, und damit auch dessen didaktisches Konzept, von den Studenten mehr- heitlich positiv aufgenommen wurde (Kamphans u. a., 2004). In der Realität werden Zustandsdiagramme oft im Bereich eingebetteter Systeme zur Spezifikation und Verifikation des Systemverhaltens verwendet (siehe Abbildung 1.2), da sich Fehler nachträglich nicht oder nur zu hohen Kosten korrigieren lassen. Anima- tionen können also dazu genutzt werden, die real existierenden eingebetteten Systeme nachzuahmen, zu testen und im Rahmen der Lehre den Studierenden Aufgaben zu stellen, die an lebensnahe Anforderungen angelehnt sind. Letztlich ist diese Art der Visualisierung aber auch nur ein Versuch, die Kluft zwi- schen der abstrakten Notation von Zustandsdiagrammen und der Realität zu überwin- den, um das Lernen zu erleichtern. Daher stellt sich die Frage, ob es nicht möglich ist, den Studenten ein reales eingebettetes System zur Verfügung zu stellen, an dem sie die praktische Anwendung von Zustandsdiagrammen trainieren können. Ein kostengünsti- ger Ansatz ist die Verwendung des Mindstorms Robotics Invention System 2.0 (LEGO, 2005), welches von der Firma LEGO im Rahmen ihrer Produktreihe LEGO Technik eingeführt wurde. Dieses System verfügt über einen programmierbaren Baustein und kann dazu genutzt werden einfache Roboter zu bauen. Die Programmierung erfolgt über eine proprietäre graphische Sprache, welche für Kinder ausgelegt ist. Alterna-
  • 13. 1.2. Zielsetzung 3 (a) Zwei Sensoren tasten den Boden ab und (b) Das zugehörige Zustandsdiagramm des melden dem Roboter, wenn die Fahrbahn Roboters. Die beiden Motoren reagieren erfasst wird auf die Farbe des Untergrunds, welche die Sensoren melden Abbildung 1.2.: Beispiel für die Verwendung von Zustandsdiagrammen in eingebetteten Systemen: Die Aufgabe besteht darin, dass ein Roboter einem vorgegebenen Weg folgt tiven, welche eine klassische Programmierung zulassen, finden sich im Open-Source- Bereich und haben als Zielgruppe Programmierer, die eine vollständige Kontrolle über den Baustein erhalten wollen. Neben der praktischen Anwendung bietet das System einen für die Lehre sehr wich- tigen Zusatzfaktor, nämlich die Steigerung der Lernmotivation. Die LEGO-Roboter fügen eine spielerische Komponente zu den Lernaufgaben hinzu. Durch jene und die Möglichkeit, dass die Studenten selbst etwas kreieren können, kann die intrinsische Motivation gesteigert werden. Bei den Lernenden erhöht sich durch Neugier, Spaß und Interesse die Motivation, die Übungen zu erledigen (Heidelberg, 2000). Ein weiterer Vorteil ist die Förderung der Gruppenarbeit: Es können Aufgaben gestellt werden, die vom Umfang her komplex sind und in Gruppen gelöst werden müssen. Ein Beispiel hierfür ist die Realisierung eines Hochregallagers in einer Fallstudie an der Universi- tät Paderborn. Die dort gemachten Erfahrungen zeigen, dass der Einsatz der LEGO- Roboter von den Studenten mehrheitlich positiv aufgenommen wurde (Magenheim und Scheel, 2004). 1.2 Zielsetzung Da die LEGO-Roboter didaktisch erfolgreich eingesetzt wurden, sie ein einfaches ein- gebettetes System sind und die Verbindung zu Zustandsdiagrammen naheliegend ist, bietet es sich an Mindstorms in der Lehre einzusetzen und in ein didaktisches Werkzeug zu integrieren. Aufgrund der Tatsache, dass die Syntax und Semantik von Zustandsdia- grammen und nicht die Programmierung von LEGO-Robotern im Vordergrund stehen soll, muss nach einer Lösung gesucht werden, die es ermöglicht die Programmierung
  • 14. 1. Thema der Arbeit 4 vollkommen transparent zu gestalten. Die vorliegende Diplomarbeit behandelt die Inte- gration der LEGO-Roboter in das didaktische Werkzeug DAVE unter Berücksichtigung eben genannter Prämisse. Die Studenten sollen in der Lage sein, ihre Zustandsdiagram- me in DAVE zu modellieren und über diese das Verhalten der Roboter zu spezifizieren. Um eine höchstmögliche Akzeptanz seitens der Studenten zu erreichen, ist es eben- falls erforderlich, dass die Syntax zur Steuerung der Roboter-Elemente sehr einfach zu erlernen ist und sich problemlos in die Notation von Zustandsdiagrammen integrieren lässt. Der zusätzliche Lernaufwand muss also möglichst minimal sein. Bei näherer Betrachtung lässt sich erkennen, dass aus den in DAVE gegebenen Infor- mationen über das modellierte Zustandsdiagramm ein Quellcode generiert und kom- piliert werden muss, welcher als ausführbares Programm in den Roboter eingeladen werden kann. Um dieses Ziel zu erreichen, müssen im Rahmen der Diplomarbeit die folgenden Fragen geklärt werden: • Welche Elemente von Zustandsdiagrammen sollen unterstützt werden? • In welcher Relation stehen die gewählten Elemente von Zustandsdiagrammen zu den elektro-mechanischen Bauteilen der LEGO-Roboter und wie lässt sich diese Relation im Diagramm darstellen? • Wie können Zustandsdiagramme und deren Semantik in Quellcode abgebildet werden? • Welche Daten stellt DAVE zur Verfügung und wie können diese verarbeitet wer- den, um daraus den benötigten Quellcode zu generieren? 1.3 Geplantes Vorgehen Die Arbeit gliedert sich in drei Teile. Im ersten Teil werden die notwendigen Grundbe- griffe zum Thema Zustandsdiagramme und dem LEGO Mindstorms Invention System aufgearbeitet, damit eine Integration von LEGO in DAVE geplant und umgesetzt wer- den kann. Anschließend werden im zweiten Teil die Konzepte und deren Umsetzung erläutert. Kapitel 3 beschreibt das gewählte Gesamtkonzept der Kopplung beider Wel- ten. Auf dem gewählten Ansatz aufbauend werden in den darauf folgenden Kapiteln 4 bis 8 die einzelnen Teile des Konzepts und deren Umsetzung behandelt. In Kapitel 9 des dritten Teils werden exemplarisch einige praktische Aufgaben für den Übungs- betrieb vorgestellt. Zum Abschluss der Arbeit werden rückblickend die Ergebnisse zusammengefasst und ein Ausblick auf mögliche Erweiterungen gegeben.
  • 15. Kapitel 2 Grundbegriffe Wie im vorherigen Abschnitt bemerkt wurde, ist es notwendig einige Grundbegriffe aufzuarbeiten, ohne die die notwendigen Designentscheidungen zur Realisierung der Aufgabe nicht getroffen werden können. Dieses Kapitel ist in zwei Teile aufgeteilt, wel- che die wichtigen Themengebiete behandeln. In Abschnitt 2.1 wird näher auf die für die Arbeit relevanten Elemente von Zustandsdiagrammen eingegangen und es werden verschiedene Ansätze zu deren Implementierung vorgestellt. Abschnitt 2.2 widmet sich dem LEGO Mindstorms Robotics Invention System und geht zunächst auf die techni- schen Details der Hardware ein, bevor verschiedene Möglichkeiten der Programmierung vorgestellt werden. 2.1 Zustandsdiagramme Zustandsdiagramme wurden erstmals 1987 von David Harel erwähnt und basieren auf einer Verallgemeinerung der Konzepte von endlichen Automaten (Harel, 1987). Sie können als gerichtete Graphen angesehen werden, die das Verhalten eines Objekts be- schreiben und komplementär zu Sequenz- und Kollaborationsdiagrammen sind, welche die Interaktion verschiedener Objekte darstellen. Die beiden wesentlichen Erweiterun- gen seitens Harel waren die Einführung von Hierarchie und Nebenläufigkeit, auf die im weiteren Verlauf noch eingegangen wird. Von der OMG wurden die vorgestellten Konzepte aufgegriffen und für die Verwendung in der UML leicht modifiziert. Im Folgenden werden die Elemente und deren Semantik behandelt, wie sie in der Version 1.5, einer Untermenge der aktuellen Version 2.0, der UML-Spezifikation (OMG, 2003) aufgeführt sind und für die eine Unterstützung in DAVE und LEGO Mindstorms vorgesehen ist. Eine genauere Beschreibung findet sich in (Hitz und Kappel, 2003). 2.1.1 Elemente und Semantik von Zustandsdiagrammen Zustände und Aktionen Aufgrund der Graphenstruktur besitzen die Diagramme Knoten und (gerichtete) Kan- ten. Die Knoten repräsentieren die Zustände, die das Objekt einnehmen kann, während die Kanten Zustandswechsel, die so genannten Transitionen, darstellen. Zustände wer- den im Diagramm durch Rechtecke mit gerundeten Ecken dargestellt und können mit
  • 16. 2. Grundbegriffe 6 einem, den Zustand beschreibenden, Namen und Aktionen versehen werden. Hierbei werden im Rahmen der Diplomarbeit zwei Typen von Zustandsaktionen unterschie- den: Die entry-Aktion wird ausgeführt, sobald der Zustand aktiviert, d. h. erreicht wird. Analog hierzu existiert die exit-Aktion, welche beim Verlassen des Zustands ausgeführt wird. Zusätzlich existiert noch die do-Aktion, die nach der entry-Aktion ausgeführt wird, während der Zustand aktiv ist. Für diese ist keine Unterstützung vorgesehen. Sie wird an dieser Stelle nur der Vollständigkeit halber aufgeführt. Die Aktionen haben keine spezielle Form und können im Prinzip beliebiger Natur sein. Sprich es ist möglich, Pseudocode ebenso zu verwenden wie konkrete Methodenaufru- fe in einer Programmiersprache oder Ausgaben von „Ereignissen“. Neben den normalen Zuständen beschreibt die UML noch eine weitere Art von Zustandstypen, die so genannten Pseudozustände. Sie dienen einzig der Modellierung und sind keine echten Zustände des Objekts. Daher kann ihnen keine Aktion zugeordnet werden bzw. das Objekt in ihnen verweilen. Damit bekannt ist, welcher Zustand bei Beginn der Bearbeitung aktiviert werden muss, wird dem Diagramm ein Pseudozustand, der so genannte Startzustand zugewiesen. Für diesen gilt, dass von ihm nur Transitionen abgehen dürfen. Analog zum Startzustand existiert der Endzustand. Dieser ist ein normaler Zustand, der jedoch keine Aktionen beinhalten kann. Für diesen gilt, dass keine Transition den Zustand verlassen darf. Zustandsübergänge Ereignisse Der Wechsel zwischen zwei Zuständen wird in der Regel über ein Er- eignis angestoßen. Dies ist laut OMG (2003) „das Ergebnis einer beliebigen Aktion innerhalb des Systems oder in der das System umfassenden Umgebung“. Obwohl die Form eines Ereignisses nicht explizit festgelegt ist, unterscheidet die UML zwischen vier verschiedenen Ereignistypen, von denen hier nur die beiden für die Arbeit rele- vanten erwähnt werden sollen: Das SignalEvent umfasst den zuletzt genannten Fall, dass das Ereignis durch eine Aktion außerhalb des Systems generiert wurde, während das TimeEvent auf einer Aktion innerhalb des Systems beruht. Ereignisse werden nur vom jeweils aktuell aktiven Zustand verarbeitet. Gehen von einem Zustand nur mit Ereignissen markierte Transitionen ab, so ver- weilt das Objekt so lange in dem Zustand, bis ein Ereignis auftritt, welches einen Zustandsübergang auslöst. Ereignisse, welche im aktuellen Zustand keiner Transition zugeordnet sind, gehen verloren. Für Übergänge ohne Ereignismarkierung gilt die Be- endigung aller Aktionen des Zustands als Trigger. Tritt ein Ereignis auf, wird die derzeit aktive Aktion sofort unterbrochen und der Zustand verlassen. Bedingungen und Aktionen Neben einem Ereignis kann einer Transition eine Bedingung und eine Aktion zugeordnet werden. Erstere wird mit- tels der Schreibweise [y] und letztere durch /z an der Transition kenntlich gemacht. Bedingungen sorgen dafür, dass das Schalten nur dann möglich ist, wenn diese erfüllt ist. So lässt sich beispielsweise verschiedenen Tran-
  • 17. 2.1. Zustandsdiagramme 7 sitionen eines Zustands dasselbe Ereignis zuordnen. Abhängig von den Bedingungen können aber unterschiedliche Aktionen ausgeführt oder verschiedene Zielzustände er- reicht werden. Prinzipiell ist es bei Zustandsübergängen allerdings möglich, ein nichtdeterminis- tisches Zustandsdiagramm zu modellieren, in welchem mehrere Transitionen gleichzei- tig schalten können. In diesem Fall wird seitens der UML-Spezifikation keine genaue Semantik vorgegeben. Somit bleibt es frei zu entscheiden, welche der Transitionen schalten kann. Für die Markierung von Zustandsübergängen ergibt sich als Schreib- weise also Ereignis[Bedingung]/Aktion. Zeitgesteuerte Transitionen Durch das Schlüsselwort after (x) wird das TimeEvent gekennzeichnet. Dieses defi- niert einen bestimmten Typ Zustandsübergang, die zeitge- steuerte Transition. Nach Ablauf der konstanten Zeitspan- ne x wird ein Ereignis getriggert, sodass die Transition bei erfüllter Bedingung schalten kann. Als zeitlicher Bezug wird bei diesem Ereignistyp der Zeitpunkt des Eintritts in den aktuellen Zustand angenommen. Segmentierte Transitionen Ein weiterer Aspekt von Zu- standsdiagrammen sind die so genannten segmentierten Tran- sitionen. Mit ihnen ist es möglich, mehrere Zustandsübergänge miteinander zu verketten, um beispielsweise zu erreichen, dass in jeder Teiltransition eine Aktion ausgeführt wird. Ebenfalls bieten sie die Möglichkeit, Verzweigungen zu modellieren. Die Verknüpfung segmentierter Transitionen wird im Diagramm durch einen Pseudozustand in Form eines schwarzen Kreises dargestellt, der Verbindungsstelle. Eine segmentierte Transition ist immer atomar, d. h. sie schaltet entweder ganz oder gar nicht. Vor dem Zustandsübergang muss von der segmentierten Transition geprüft werden, ob es einen Weg zum nächsten Zustand gibt. Doch es gibt noch eine weitere Besonderheit, die berücksichtigt werden muss: Nur dem ersten Segment der Transition darf ein Ereignis zugewiesen werden, während alle Segmente Bedingungen und Aktionen halten können. Hierarchische Zustände In komplexen Systemen ist es häufig notwendig, Sachverhalte zunächst zu abstrahieren und deren tatsächliche Arbeitsweise in einem nachfolgenden Schritt genauer zu mo- dellieren. Zustandsdiagramme bieten die Bildung von Zustandshierarchien an. Diese Oder-Verfeinerung ermöglicht es, einen komplexen Zustand in Unterzustände zu zer- legen, die den Sachverhalt genau beschreiben. Sobald das Objekt diesen Oder-Zustand erreicht, befindet es sich automatisch immer in genau einem Unterzustand der Verfei- nerung. Durch diese Schachtelung treten neue Besonderheiten auf, die im Folgenden behandelt werden. Start- und Endzustände Innerhalb einer Oder-Verfeinerung muss bekannt sein, welcher Unterzustand bei Erreichen aktiviert wird bzw. wann der Zustand beendet
  • 18. 2. Grundbegriffe 8 ist. Diese Information wird, genau wie beim Diagramm selbst, mittels eines Start- und Endzustands dargestellt. Das Vorhandensein dieser Zustände ist allerdings nicht immer notwendig. Warum dies so ist, wird im nächsten Abschnitt deutlich. Betreten und Verlassen des Zustands Es lassen sich zwei Arten unterscheiden, wie ein komplexer Zustand aktiviert werden kann: 1. Eine ankommende Transition endet direkt am Oder-Zustand. In einem solchen Fall ist es notwendig, dass in der Verfeinerung ein Startzustand spezifiziert ist. 2. Eine ankommende Transition endet an einem beliebigen Subzustand der Verfei- nerung. In diesem Fall wird die Grenze des Oder-Zustands überschritten. Daher ist kein Startzustand notwendig, da dieser implizit durch den Zielzustand der Transition gegeben ist. Das Verlassen des Zustands findet im Wesentlichen analog statt: 1. Der Zustand kann über eine Transition verlassen werden, die von der Oder- Verfeinerung abgeht. Handelt es sich um einen Übergang ohne Ereignismarkie- rung, die so genannte Beendigungstransition, kann diese nur schalten, falls die Bearbeitung in der Verfeinerung abgeschlossen ist. In diesem Fall ist das Vor- handensein eines Endzustands notwendig. 2. Der Zustand kann über eine Transition verlassen werden, die von einem Un- terzustand abgeht und als Ziel einen Zustand außerhalb der Oder-Verfeinerung besitzt. Zustandsübergänge Transitionen in Hierarchien füh- ren bei näherer Betrachtung zu zwei Fragen, für die ei- ne Semantik bestimmt werden muss. Zunächst muss ge- klärt werden, was für ereignismarkierte Transitionen gilt, die vom Oberzustand wegführen. Denn laut Semantik be- findet sich das Objekt zu jedem Zeitpunkt, während der Oder-Zustand aktiv ist, in genau einem der Unterzustän- de. Damit diese „top-level“-Ereignisse trotzdem verarbei- tet werden können, werden die von der Oder-Verfeinerung abgehenden Transitionen an alle Unterzustände „vererbt“. Anders ausgedrückt bedeutet dies, dass jeder Unterzustand alle ereignismarkierten Zustandsübergänge der Oberzustände kennt, die sich auf dem Pfad vom Zustand zur Wurzel des Baums befinden, der durch die Hierarchie aufge- spannt wird. Hieraus leitet sich die nächste Frage ab: Was passiert, wenn in einem Unterzustand eine geerbte Transition „überschrieben“ wird, das heißt auf dasselbe Ereignis reagiert wie die vom Oberzustand geerbte Transition? In diesem Fall existieren ggf. mehrere mögliche Übergänge, die in einem Schritt schalten können. Es wird eine Vorrangsre- gel benötigt, die festlegt, welche der Transitionen schalten kann. Hierzu werden den Zustandsübergängen Prioritäten zugeordnet, was zu folgender Regel führt:
  • 19. 2.1. Zustandsdiagramme 9 Definition: Vorrangsregel Sei t1 eine vom Zustand s1 wegführende Transition und s1 ein transitiv erreichbarer Unterzustand von s2 . t2 ist ein von s2 wegführender Zustandsübergang mit dersel- ben Ereignismarkierung wie t1 . Dann hat die verschachtelte Transition t1 eine höhere Priorität als t2 (OMG, 2003). Es werden immer die Übergänge schalten, die in der Hierarchie weiter unten ange- siedelt sind und das Verhalten des komplexen Zustands spezifizieren. Anhand dieser Regel lässt sich die Idee der Verfeinerung von Zuständen erkennen. History-Zustände In vielen Systemen ist es zum Teil notwendig zu wissen, in welcher Konfiguration sich der komplexe Zustand beim letzten Verlassen befun- den hat. Mit dieser Information kann die Bearbeitung an derselben Stelle fortgeführt werden, an der sie zu- letzt unterbrochen wurde. Diese „Ablaufhistorie“ wird in hierarchischen Zuständen über Pseudozustände mo- delliert. Diese History-Zustände werden im Diagramm durch H bzw. H ∗ gekennzeichnet und lassen sich in zwei Kategorien unterteilen: 1. Die flache Historie (H) eines Oder-Zustands speichert den zuletzt aktiven Sub- zustand. 2. Die tiefe Historie (H ∗ ) eines Oder-Zustands speichert alle Zustände für die gilt, dass sie aktiv sind und sich auf dem Pfad vom hierarchischen Zustand zu einem Blatt des Hierarchiebaums befinden. Im Gegensatz zu klassischen Statecharts muss für die History-Zustände der UML- Zustandsdiagramme eine Starttransition angegeben werden. Diese geht vom History- Zustand aus und führt zu dem Zustand, der aktiviert werden soll, falls noch keine Historie vorliegt. Dies ist genau dann der Fall, wenn der Oder-Zustand das erste Mal betreten wird. Andernfalls wird der Zustand aus der Historie bzw. die Zustände der tiefen Historie aktiviert. Nebenläufige Zustände Eine weitere Neuerung gegenüber endlichen Automaten ist die Modellierung von Ne- benläufigkeit. Hierbei handelt es sich um einen Zustand, welcher mindestens zwei gleich- zeitig aktive Subzustände besitzt. Diese bilden die einzelnen Regionen des Zustands. Daher wird dieser Typ auch als Und-Zustand bezeichnet. Die Regionen werden über ei- ne gestrichelte Linie im Diagramm voneinander getrennt. Nebenläufigkeit zieht jedoch konzeptionelle Konsequenzen nach sich, auf die im Folgenden eingegangen wird. Regionen In einer Und-Verfeinerung werden die einzelnen Regionen durch hierar- chische Zustände beschrieben, sodass die dort beschriebene Semantik hier ebenfalls anzuwenden ist. Grundsätzlich sind alle Regionen der Verfeinerung aktiv, sobald der
  • 20. 2. Grundbegriffe 10 Und-Zustand betreten wird. Sie können als eine Art Prozesse angesehen werden, die parallel innerhalb der Verfeinerung laufen. Es können also nicht einzelne Bereiche „ausgeschal- tet“ werden. Ankommende Ereignisse werden immer von allen Regionen verarbeitet, was dazu führen kann, dass mehrere Regionen das Ereignis verarbeiten und somit potenziell verschiedene Transitionen gleichzeitig schal- ten können. Zusätzlich werden wie bei hierarchischen Zuständen die wegführenden ereignismarkierten Transi- tionen der Verfeinerung an jede Region - also an alle Unterzustände - vererbt und Übergänge mit höherer Priorität beim Schalten bevorzugt. Betreten und Verlassen des Und-Zustands Wird der Zustand aktiviert, muss dafür gesorgt werden, dass alle Regionen ebenfalls aktiviert werden. Analog müssen alle Bereiche deaktiviert werden, sobald der Zustand verlassen wird. Wie bei der Oder-Verfeinerung lassen sich je zwei Fälle unterscheiden: 1. Endet die ankommende Transition am Und-Zustand, muss für alle Regionen ein Startzustand angegeben werden. 2. Endet die ankommende Transition an einem Unterzustand genau einer Region, wird die Oder-Verfeinerung implizit betreten und alle anderen Regionen müssen an dem jeweiligen Startzustand aktiviert werden. Es müssen n − 1 Startzustände vorhanden sein. Das Verlassen des Zustands findet im Wesentlichen analog statt: 1. Erreichen alle Regionen ihre Endzustände, kann der Und-Zustand über die Be- endigungstransition verlassen werden. Die Regionen werden an den jeweiligen Endzuständen synchronisiert. 2. Schaltet eine Transition von einem Unterzustand einer beliebigen Region und hat ein Ziel außerhalb der Und-Verfeinerung, werden alle Regionen unabhän- gig von ihrem derzeit aktuellen Zustand verlassen und der nebenläufige Zustand deaktiviert. Eben diese Semantik gilt auch für vom Superzustand geerbte ereig- nismarkierte Transitionen. Komplexe Transitionen Bei genauerer Betrachtung wurden bisher zwei Fälle be- handelt, wie Regionen aktiviert werden können. Zum einen explizit und zum anderen implizit. Im ersten Fall beginnen alle Bereiche an ihren Startzuständen, im letzte- ren n − 1 Regionen an ihrem Startzustand und eine an einem beliebigen Subzustand, nämlich dem Ziel der Transition. Es fehlt noch der Fall, dass m Regionen an einem beliebigen Unterzustand beginnen, wobei 1 < m < n ist. Sicherlich können die Startzu- stände so angelegt werden, dass sie das gewünschte Verhalten widerspiegeln, doch was ist, wenn dies nicht gewünscht ist? Die Startzustände können beispielsweise die Stan- dardkonfiguration modellieren, während in einem Spezialfall die Oder-Verfeinerung in einer anderen Konfiguration beginnen soll.
  • 21. 2.1. Zustandsdiagramme 11 Um dieses Verhalten abbilden zu können, existieren die komplexen Transitionen. Sie zeichnen sich dadurch aus, dass der Kontrollfluss aufgeteilt wird, also aus einer ankommen- den Transition mehrere generiert werden. Somit kann pro Region maximal eine neue Transition entstehen, deren Ziel ein Zustand in der Region ist. Ein analoger Fall lässt sich natürlich auch für das Verlassen der Oder-Verfeinerung beschreiben. Somit bieten kom- plexe Transitionen zwei Funktionsarten: 1. Das Aufteilen einer in mehrere Transitionen, um direkt Unterzustände der einzel- nen Regionen anspringen zu können. Bereiche, die von der komplexen Transition nicht berücksichtigt werden, also keine Zustandsübergänge in diese führen, wer- den automatisch an ihren Startzuständen aktiviert. 2. Das Synchronisieren einzelner Regionen, um den Zustand zu verlassen, sobald bestimmte Unterzustände erreicht werden. Bereiche, die von der komplexen Tran- sition nicht berücksichtigt werden, also keine Übergänge aus diesen Regionen führen, werden unabhängig von ihrem aktuellen Zustand automatisch beendet. In der Modellierung werden hierfür zwei Pseudozustände berücksichtigt, die beide durch einen schwarzen Synchronisationsbalken gekennzeichnet werden. Dieser Balken entspricht dem Fork-Zustand genau dann, wenn er eine 1 : n-Abbildung repräsentiert, d. h. aus einer ankommenden Transition mehrere abgehende werden. Als Join-Zustand wird er dann bezeichnet, wenn er eine n : 1-Abbildung repräsentiert, also mehrere ein- gehende Transitionen synchronisiert und zu einer abgehenden zusammenfasst. 2.1.2 Implementierungsansätze Nachdem die für die Arbeit relevanten Elemente von Zustandsdiagrammen und deren Semantik erörtert wurden, sollen im Folgenden verschiedene Möglichkeiten behandelt werden, diese in Quellcode abzubilden. Die vorgestellten Konzepte basieren auf den klassischen Methoden der Implementierung endlicher Automaten. Prozedurale Implementierung Mittels prozeduraler Programmiersprachen lassen sich endliche Automaten einfach und effizient über geschachtelte switch-case-Anweisungen implementieren. Hierzu wird der aktuelle Zustand in einer globalen Variable gehalten, während Aktionen als Prozedur implementiert werden. Ein einfacher endlicher Automat ließe sich wie in Abbildung 2.1 darstellen. Um ein Ereignis verarbeiten zu können, wird zunächst der aktuelle Zustand gewählt und für diesen geprüft, ob er das Ereignis verarbeiten kann. Durch die Kapselung der Aktionen in einzelne Prozeduren ist es möglich diese wiederzuverwenden. Des Weiteren lässt sich insgesamt ein Programm erzeugen, welches wenig Speicher benötigt und in der Regel schnell ist. Jedoch hat diese Implementierung auch essenzielle Nachteile: • Der Quelltext wird schnell unübersichtlich, schlecht wartbar und fehleranfällig.
  • 22. 2. Grundbegriffe 12 i n t s t a t e = ’A ’ ; . . . void fsm ( e v e n t ) { switch ( s t a t e ) case A: switch ( e v e n t ) case x : a cti on X ( ) ; s t a t e = ’B ’ ; break ; case y : =⇒ a cti on Y ( ) ; s t a t e = ’A ’ ; break ; break ; case B : switch ( e v e n t ) case y : a c t i o n Z ( ) ; s t a t e = ’A ’ ; break ; break ; } Abbildung 2.1.: Umsetzung eines endlichen Automaten in prozeduralen Quelltext • Oder- bzw. Und-Verfeinerungen lassen sich nicht abbilden und müssen zunächst aus dem Diagramm entfernt werden, ohne die Semantik einzuschränken (Harel, 1987). Dieses „Plätten“ ist allerdings problematisch, da die resultierende Anzahl der Zustände enorm groß werden kann. Objektorientierte Ansätze Das State-Pattern Eine Alternative bietet der objektorientierte Ansatz. Für end- liche Automaten hat sich das von Erich Gamma vorgestellte State-Entwurfsmuster etabliert (Gamma u. a., 1995). Das zentrale Konzept ist die Kapselung der Zustände in einzelne Objekte, welche von einer abstrakten Basisklasse alle Methoden erben und bei Bedarf überschreiben. Methoden repräsentieren die Aktionen einer Transition. Zu- dem gibt es den Kontext, welcher den Zugriff zum endlichen Automaten anbietet und eine Referenz auf den derzeit aktuellen Zustand hält. Die Aufgabe des Kontext besteht darin, ankommende Ereignisse (die Methodenaufrufe) an den aktuellen Zustand weiter zu delegieren. Der oben dargestellte Beispielautomat kann mit Hilfe des State-Patterns wie in Abbildung 2.2 implementiert werden. Auch hier lässt sich erkennen, dass die essenziellen Elemente nicht unterstützt wer- den. Es muss eine Lösung gefunden werden, die es erlaubt das Entwurfsmuster sowie Hierarchie und Nebenläufigkeit zu verwenden. In (Ali und Tanaka, 1999) wird eben dieses Problem behandelt und eine Lösung vorgestellt. Die Idee ist das Verwenden der Vererbungshierarchie zur Darstellung der Oder-Verfeinerung. Das heißt, eine von A erbende Klasse B ist Unterzustand von A. Hier ist zu erkennen, dass die Semantik der Vererbung von Transitionen erfüllt ist, da sich dies eins zu eins auf die Klassenhier-
  • 23. 2.1. Zustandsdiagramme 13 Abbildung 2.2.: Umsetzung des Beispielautomaten mit Hilfe des State-Patterns archie abbilden lässt. Offen bleibt, wie sich nebenläufige Zustände realisieren lassen. Die Lösung ist naheliegend: In Zustandsdiagrammen besteht eine Und-Verfeinerung aus mindestens zwei hierarchischen Zuständen. Also hält der Und-Zustand eine Refe- renz auf eine Oder-Verfeinerung. Genau dies wird in dem Ansatz von Ali und Tanaka verwendet. Der Und-Zustand ist eine Klasse, welche Referenzen auf die Regionen hält und die einzelnen Ereignisse an die Regionen delegiert (siehe Abbildung 2.3). =⇒ Abbildung 2.3.: Beispiel der Abbildung von Hierarchie und Nebenläufigkeit in die Klassenhierarchie objektorientierter Sprachen auf Basis des State-Patterns Der Ansatz von Gurp und Bosch Beim State-Pattern ist das zentrale Konzept der Zustand. Dies führt dazu, dass Elemente wie Aktionen und Transitionen nicht als eigenes Objekt repräsentiert werden, sondern implizit in der Zustandsklasse „versteckt“ sind. Ein alternativer Ansatz wurde von Jilles van Gurp und Jan Bosch vorgestellt (van Gurp und Bosch, 1999). Dieser verlagert das Konzept auf die explizite Modellierung der Elemente endlicher Automaten als eigene Objekte. Hier wird nicht der Zustand, sondern die Transition als zentrales Element betrachtet. Diese kennt den Zielzustand und die auszuführende Aktion, während der Zustand seine abgehenden Transitionen kennt und diese mit einem Ereignis verknüpft. Der Kontext dient als Schnittstelle des Zustandsdiagramms zur Anwendung und leitet die Ereignisse an den jeweils aktuellen Zustand weiter. Dieser prüft in seiner Liste
  • 24. 2. Grundbegriffe 14 Abbildung 2.4.: Klassendiagramm des FSM-Frameworks von Bosch und van Gurp aus (Ereignis, T ransition)-Tupeln, ob das Ereignis verarbeitet werden kann und führt den Übergang ggf. aus. Aktionen werden mittels des Command-Patterns (Gamma u. a., 1995) ausgeführt, sodass verschiedenartige Aktionen implementiert, aber diese auch wiederverwendet werden können. Da ein Ziel in dem Ansatz die Wiederverwendbarkeit des Zustandsdiagramms ist, werden ablaufspezifische Daten nur im Kontext verwaltet. Dies bedeutet, dass sich verschiedene Kontexte dasselbe Diagramm teilen können. Aus diesem Grund wird in der Implementierung der Kontext als Referenz mit übergeben (siehe Abbildung 2.4). Jedoch fehlt auch in diesem Ansatz die Unterstützung der wesentlichen Elemente von Zustandsdiagrammen und beschränkt sich auf die Abbildung endlicher Automa- ten. Die Laufzeitsemantik, Hierarchie und Nebenläufigkeit muss explizit implementiert werden, während sie beim Ansatz von Ali und Tanaka implizit auf Elemente der Pro- grammiersprache abgebildet werden. 2.2 LEGO Mindstorms Roboter Das LEGO Mindstorms Robotics Invention System wurde erstmals im Jahr 1998 vorge- stellt und basiert auf einer Zusammenarbeit der Firma LEGO mit dem Massachusetts Institute of Technology (MIT). Es erweitert die Produktlinie LEGO Technik um einen frei programmierbaren Baustein und ermöglicht so das Erstellen elektro-mechanischer Komponenten wie zum Beispiel Roboter. Aufgrund der Freiheiten, die LEGO mit sei- nem System bietet, ist es möglich eine Vielfalt verschiedenster Roboter zu bauen. Daher soll in diesem Abschnitt zunächst auf die Hardware näher eingegangen werden, bevor anschließend die verfügbaren Möglichkeiten der Programmierung beleuchtet werden. 2.2.1 Aufbau der Hardware Bei dem von LEGO verwendeten RCX-Baustein handelt es sich um einen Mikrocon- troller der Firma Hitachi mit 16MHz. Der Controller besitzt zur Interaktion mit der Umwelt drei Eingänge für Sensoren und drei Ausgänge. Derzeit existieren Druck-, Rotations-, Licht- und Temperatursensoren sowie Motoren und Lampen, welche an
  • 25. 2.2. LEGO Mindstorms Roboter 15 Abbildung 2.5.: Der RCX-Baustein die Ausgänge angeschlossen werden können. Es stehen dem Anwender 32KB RAM und 16KB ROM zur Verfügung. Im ROM werden low-level-Funktionen und Basistrei- ber zur Steuerung der Ausgänge, Sensoren und der Infrarot-Schnittstelle bereitgestellt. Über letztere wird der RCX mit einer Firmware versorgt, die das Betriebssystem dar- stellt und die Programmierung ermöglicht. Die 32KB Arbeitsspeicher stehen nicht aus- schließlich für eigene Programme zur Verfügung, sondern halten neben dem Programm auch dessen Laufzeitobjekte und die Firmware. Somit steht je nach verwendeter Firm- ware unterschiedlich viel Speicher für eigene Programme und Daten zur Verfügung. 2.2.2 Programmierung der LEGO-Roboter Die Firma LEGO bietet ein eigenes Betriebssystem an, welches jedoch nicht mittels einer Hochsprache programmiert werden kann. Stattdessen wird eine graphische Mo- dellierungssprache angeboten, die über eine proprietäre Windows-Software verwendet werden kann. Diese erstellt aus dem Modell schließlich das Programm für den RCX- Baustein. Im Wesentlichen wird also dasselbe Vorgehen verwendet, welches im Rah- men dieser Diplomarbeit behandelt werden soll: Aus einer graphischen Modellierung ein ausführbares Programm zu erstellen. Da die Modellierungssprache von LEGO für Kinder ausgelegt ist, lassen sich kom- plexe Abläufe nur umständlich bis gar nicht beschreiben. Ziel verschiedener Entwickler war es eine Möglichkeit zu schaffen, mit der die Roboter klassisch programmiert werden können. Aus diesem Grund wurden alternative „Betriebssysteme“ entwickelt, wobei die drei bekanntesten jeweils kurz beleuchtet werden. Not Quite C Basierend auf der original LEGO-Firmware implementiert NQC (Baum und Hansen, 2004) eine eigene prozedurale Programmiersprache, die an C angelehnt ist. Objektori- entierte Konzepte lassen sich hier also nicht umsetzen.
  • 26. 2. Grundbegriffe 16 BrickOS Das ursprünglich von Markus L. Noga entwickelte Betriebssystem BrickOS (Noga, 2002) ersetzt das Original der Firma LEGO. Als Compiler wird der GCC verwendet, sodass der Quellcode nativ für den Hitachi-Prozessor kompiliert und gelinkt wird. Pro- gramme können in der Hochsprache C++ entwickelt werden und bietet demnach auch die Möglichkeiten dieser Sprache, inklusive Bibliotheken wie der Standard Template Library und der manuellen Speicherverwaltung. LeJOS Das auf TinyOS aufbauende LEGO Java Operating System (Solorzano, 2000) imple- mentiert eine virtuelle Maschine für Java und ersetzt wie BrickOS die Firmware von LEGO. Programme lassen sich in Java, und somit objektorientiert, implementieren. LeJOS greift auf eine abgespeckte Java API zurück, die die essenziellen Klassen der Sun API nachbildet. Im Gegensatz zum Original bietet diese virtuelle Maschine keine Garbage Collection an, die das Aufräumen von Objekten übernimmt. Einmal angelegte Objekte bleiben die komplette Laufzeit des Programms im Speicher bestehen. Diese drei Möglichkeiten der Programmierung des RCX gehören zu den bekanntes- ten und am meisten eingesetzten. Im nächsten Kapitel werden zunächst die Vor- und Nachteile der einzelnen Lösungen diskutiert. Auf diesem Ergebnis aufbauend, werden die vorgestellten Ansätze zur Implementierung von Zustandsdiagrammen verglichen und begutachtet, um daraus ein Konzept und eine Vorgehensweise für diese Diplom- arbeit abzuleiten.
  • 27. Kapitel 3 Lösungsansatz Das Konzept zur Durchführung der Integration von LEGO Mindstorms in DAVE ba- siert auf mehreren Voraussetzungen und Anforderungen. Zunächst soll die Frage disku- tiert werden, auf welcher technischen Basis die Programmierung des RCX durchgeführt werden soll. 3.1 Zielplattform Es wurden die drei Laufzeitumgebungen NQC, BrickOS und LeJOS kurz vorgestellt. Natürlich hängt die Auswahl auch mit dem gewünschten Programmierkonzept und dem verfügbaren Speicherplatz des RCX zusammen. Ausgehend von den vorgestellten Implementierungsansätzen lässt sich zusammenfassen, dass der prozedurale Ansatz den Vorteil hat, dass die resultierenden Programme in der Regel klein sind. Das objektori- entierte Programmierparadigma erleichtert hingegen die Implementierung, da auf das Plätten von Zustandsdiagrammen verzichtet werden kann und somit ein komplexer Schritt entfällt. Daher werden im Rahmen dieser Arbeit nur objektorientierte Ansätze verfolgt, was zur Konsequenz hat, dass NQC nicht näher betrachtet wird. BrickOS bietet die Vorteile, dass mittels C++ der Speicher des RCX frei verwaltet werden kann und nativer Maschinencode für den im RCX verbauten Hitachi-Prozessor generiert wird. Diese beiden Punkte haben zur Folge, dass sehr kleine Programme ent- stehen, sodass der verfügbare Speicher effizient ausgenutzt werden kann. Allerdings bedingt C++ durch seine Konzepte und dem freien Speicherzugriff potenziell eine re- lativ hohe Fehleranfälligkeit. Es müssen sprachbedingte Probleme beachtet werden, wie zum Beispiel zyklische Abhängigkeiten bei der Einbindung der Header-Dateien. Diese Argumente erschweren zwar die Implementierung, bilden aber noch kein Aus- schlusskriterium. Das wichtigste Argument gegen BrickOS ist, dass der Einsatz in der Lehre geplant ist und somit gewährleistet sein muss, dass die Studenten ohne zusätz- lichen Aufwand die Funktionalität aus DAVE heraus auch zu Hause nutzen können. Dies ist bei BrickOS in dieser geforderten Form allerdings nicht ohne weiteres möglich, da diese Plattform auf freien Unix-Werkzeugen basiert, welche unter Windows nur mit erheblichem Aufwand verwendet werden können. Selbst die Installation von BrickOS unter Unix-Systemen ist nicht trivial. LeJOS hingegen wird in Form von jar-Dateien ausgeliefert, welche keine weitere Installation erforderlich machen. Daher können die benötigten Elemente von LeJOS
  • 28. 3. Lösungsansatz 18 direkt in DAVE mitgeliefert werden, ohne dass die Studenten zusätzliche Installations- routinen ausführen müssen. Zudem wird mit Java eine moderne Programmiersprache angeboten, welche nicht nur betriebssystemunabhängig ist, sondern sich auch gut in DAVE einbinden lässt, weil dieses in selbiger Sprache implementiert ist. Da es sich bei LeJOS nur um eine abgespeckte Variante einer Java-Laufzeitumgebung handelt, müssen allerdings Einschränkungen hingenommen werden: • Einmal angelegte Objekte können nicht mehr freigegeben werden und belegen den allokierten Speicher bis zur Programmbeendigung. • Die Firmware verbraucht einen hohen Anteil an Speicher des RCX, sodass für eigene Programme und Daten nur ca. 9 Kilobyte zur Verfügung stehen. Durch die fehlende Garbage Collection, die große Firmware und die Tatsache, dass Java-Programme im Allgemeinen relativ groß sind, besteht die Gefahr, dass nur klei- nere Zustandsdiagramme umgesetzt werden können. Da dies für die Lehre keine we- sentliche Einschränkung ist, erscheint LeJOS als erste Wahl und soll als Basis für die weiteren konzeptionellen Entscheidungen dienen. 3.2 Ansatzpunkte zur Integration in DAVE Ein weiterer wichtiger Aspekt ist die Analyse der Konzepte von DAVE, um mögliche Ansatzpunkte zu finden, an denen die Integration angesetzt werden kann. Da ein we- sentliches Alleinstellungsmerkmal dieser Software die Simulation der Diagramme ist, existiert in DAVE eine Simulationsmaschine für Zustandsdiagramme. Sie basiert auf dem um Hierarchie und Nebenläufigkeit erweiterten Ansatz von Bosch. Die Persistenz- schicht zum Speichern wird durch das LIMO-Framework realisiert. Dieses schreibt die Datenstruktur zur Beschreibung eines Zustandsdiagramms in einem einfachem XML- Format auf die Festplatte. Es ergeben sich zwei Fragestellungen: Kann die vorhandene Simulationsmaschine verwendet werden und welche Form der Datenstruktur soll als Basis der Integration dienen? Die nächsten beiden Abschnitten behandeln diese Fragen. 3.2.1 Die Simulationsmaschine Zunächst stellt sich die Frage wie sich die in DAVE vorhandene Laufzeitumgebung für Zustandsdiagramme verwenden lässt. Dies lässt sich leicht beantworten, denn die vorhandene Implementierung ist zu umfangreich, um sie im RCX verwenden zu können. Modifikationen an der existierenden Laufzeitumgebung könnten zwar durchgeführt werden, können aber zu unerwünschten Seiteneffekten innerhalb DAVEs führen, sodass zusätzliche Tests des gesamten Programms notwendig sind. Diese Aspekte implizieren die Planung und Realisierung einer eigenen, speicherminimalen Simulationsmaschine, die völlig unabhängig von DAVE ist.
  • 29. 3.3. Implementierung 19 3.2.2 Wahl der zu verwendenden Datenstruktur Der zweite Aspekt ist die zu verwendende Datenstruktur. Als Basis können entweder die Klassen verwendet werden, welche DAVE zur Beschreibung des Diagramms zur Verfügung stellt, oder aber die rein textuelle Repräsentation in Form der XML-Datei. Beim ersten Ansatz muss die Simulationsmaschine entwickelt werden, während beim letzteren zusätzlich eine geeignete Datenstruktur geplant und programmiert werden muss. Trotzdem ist die Verwendung der XML-Datei sinnvoller. Denn für die existie- renden DAVE-Klassen ist nicht klar, ob sich diese in einer speicherplatzoptimierten Simulationsmaschine ohne Modifikation verwenden lassen. Änderungen der Quellen führen jedoch zu schon oben genanntem Problem. Somit ist letztlich eine sehr lose Kopplung an DAVE der zu wählende Weg. Einzig die Codegenerierung ist an spezi- fische Teile, nämlich das XML-Format, gekoppelt, während der Rest eine Wiederver- wendbarkeit außerhalb von DAVE gewährleistet. Diese Datei wird als Eingabe für ein Ant-Skript (Davidson, 1999) dienen, welches die notwendigen Schritte zur Fertigstel- lung des RCX-Programms automatisiert (siehe Kapitel 8). 3.3 Implementierung Da eine sehr lose Kopplung an DAVE gewählt wird, soll dieser Ansatz auch auf die LEGO-spezifischen Teile ausgedehnt werden. Diese Entscheidung basiert ebenfalls auf der Idee, einzelne Komponenten wiederverwenden zu können. Wie lässt sich die Implementierung realisieren? Hierzu werden im ersten Schritt die von LeJOS generierten Programme näher betrachtet. Dabei fällt auf, dass die Ver- wendung von Klassen speichertechnisch teuer ist. Pro Klasse entsteht je nach deren Umfang ein Speicherverbrauch von rund 500 bis 1024 Bytes. Jede Instanz kostet hin- gegen im Durchschnitt nur wenige Bytes. Das Ziel ist daher die Anzahl an Klassen möglichst minimal zu halten und stattdessen viele Objekte zu erzeugen. Der Implementierungsansatz von Ali und Tanaka fällt dadurch auf, dass er eine große Anzahl an Klassen generiert, nämlich mindestens so viele wie Zustände existieren. Zudem erfordert dieser Ansatz, dass die Codegenerierung den Quelltext jedes einzelnen Zustands in Form einer Klasse erzeugt. Denn innerhalb dieser existiert spezifischer Quelltext für die Transitionen und Aktionen des Zustandsdiagramms. Dies führt zu einer enormen Steigerung der Komplexität bei der Codegenerierung. Wünschenswert wäre hingegen ein Framework, welches eine einfache Programmierschnittstelle bietet, die bei der automatischen Erzeugung des Quelltexts aus der XML-Datei verwendet werden kann. 3.4 Gesamtaufbau Die Hauptprobleme liegen in der Entwicklung eines Frameworks zur Repräsentation und Ausführung von Zustandsdiagrammen, welches mit den begrenzten Ressourcen des RCX verwendbar ist und der Überlegung, wie aus der XML-Datei Quellcode generiert
  • 30. 3. Lösungsansatz 20 Abbildung 3.1.: Aufbau des Konzepts. Die Nummern in den Kreisen geben die Kapitel an, in denen der jeweilige Teil behandelt wird, während die mit Ant gekennzeichneten Pfeile die Schritte angeben, die über das Ant-Skript automatisiert werden. werden kann. In Abbildung 3.1 ist der geplante Aufbau zu sehen. Nach dem Spei- chern des Diagramms in DAVE wird die XML-Datei in Quelltext transformiert. Die- ser variable Teil verwendet die Programmierschnittstellen des statischen Teils, nämlich des Frameworks. Aus dem generierten Quelltext kann schließlich mittels vorhandener Werkzeuge das Programm kompiliert, gelinkt und in den RCX hochgeladen werden. Diese Schritte werden mittels Ant automatisiert. Das Framework selbst soll auf dem Ansatz von Bosch und van Gurp basieren, jedoch um die benötigten Elemente für Zustandsdiagramme erweitert. Durch die Verwendung dieses Ansatzes kann die Anzahl der Klassen auf ein Minimum reduziert werden, indem die einzelnen Elemente von Zustandsdiagrammen explizit durch eine Klasse repräsen- tiert werden. Somit steigt nur die Anzahl der Instanzen. Zusätzlich kann das Frame- work in zwei Teile getrennt werden. Zum einen die eigentliche Laufzeitumgebung für Zustandsdiagramme und zum anderen die LEGO-spezifischen Teile. So lässt sich errei- chen, dass das Framework auch unabhängig von LEGO wiederverwendet werden kann, etwa in anderen eingebetteten Umgebungen. Weitere Vorteile dieser Vorgehensweise sind erkennbar: Die Codegenerierung verein- facht sich erheblich, da sie sich auf die Erzeugung genau einer einzigen Klasse beschrän- ken kann. Und der statische Teil des Systems kann automatisiert getestet werden, was bei komplexem, dynamisch generierten Quelltext nur mit Aufwand möglich ist. Es lassen sich insgesamt vier Teilaufgaben entdecken, die in den folgenden Kapiteln bearbeitet werden. Die erste Aufgabe besteht in der Planung der Laufzeitumgebung für Zustandsdiagramme (Kapitel 4). Die zweite Aufgabe lässt sich in zwei Bereiche splitten. Zunächst muss überlegt werden, wie die RCX-spezifischen Elemente in die Notation von Zustandsdiagrammen eingebettet werden können (Kapitel 5), bevor de- ren technische Umsetzung, also die LEGO-Erweiterung des Frameworks, beschrieben werden kann (Kapitel 6). Die dritte Aufgabe ist die Planung und Umsetzung der Code- generierung (Kapitel 7), gefolgt von der letzten Aufgabe, der Integration der einzelnen Teile in Form eines Automatisierungs-Skripts (Kapitel 8).
  • 31. Kapitel 4 Das Statechart-Framework 4.1 Konzeptioneller Aufbau Die genannten Anforderungen an das zu entwickelnde Framework für Zustandsdia- gramme erfordern zunächst konzeptionelle Vorüberlegungen. Als Basis dient das von Bosch und van Gurp vorgestellte Framework für endliche Automaten, dessen Imple- mentierung in Abbildung 2.4 zu sehen ist. Wie beim State-Pattern wird auch bei diesem ein Kontext eingesetzt, welcher den aktuellen Zustand kennt und Ereignisse an diesen delegiert. Allerdings wird dem Kontext ein weiterer Zweck zugeteilt: Bosch und van Gurp adressieren das Problem der mehrfachen Nutzung des Automaten und kapseln ablaufspezifische Daten, wie z. B. Variablenwerte, in dem Kontext. Dies bedeutet, dass ein Zustand nur ein Teil der Infrastruktur des Automaten ist und somit verschiedene Kontexte gleichzeitig auf denselben Automaten zugreifen können. Daher wird in den Methoden dispatch und execute jeweils eine Referenz des aktuellen Kontexts überge- ben, sodass Aktionen und Zustände die Möglichkeit haben, Daten in diesem zu setzen und abzufragen. Der für dieses Framework gewählte Ansatz sieht hingegen nicht die mehrfache Nutzung desselben Diagramms mit unterschiedlichen Kontexten vor. Im Gegensatz zu endlichen Automaten können Zustandsdiagramme Hierarchien be- inhalten, sodass es möglich ist, dass mehrere Zustände gleichzeitig aktiv sind. Die Menge der aktuell aktiven Zustände wird im Folgenden als Konfiguration bezeichnet. Das Zustandsdiagramm befindet sich zu jedem Zeitpunkt in einer eindeutigen Konfigu- ration. Da nicht die Infrastruktur des Diagramms mehrfach genutzt werden soll, ist es nicht notwendig die Information über die Konfiguration im Kontext zu speichern, son- dern kann in die Zustände des Diagramms verlagert werden. Das heißt, jeder Zustand weiß zu jedem Zeitpunkt, ob er aktiviert ist. Wozu dient also der Kontext? Werden zunächst Hierarchien und nebenläufige Zu- stände außer acht gelassen, fällt diesem dieselbe Aufgabe wie beim State-Pattern zu, nämlich ein eingehendes Ereignis an den aktuell aktiven Zustand weiterzuleiten. Da ein Zustand ebenfalls ein Ereignis verarbeitet, lässt sich der Kontext als ein Spezial- fall eines Zustands ansehen, in dem nur die Ereignisverarbeitung überschrieben wird und die Zusatzinformation des aktuell aktiven Unterzustands bekannt ist. Der Kontext kann als zusammengesetzter Zustand betrachtet werden. Diese Sichtweise wird später bei der Implementierung der hierarchischen und nebenläufigen Zustände helfen.
  • 32. 4. Das Statechart-Framework 22 Abbildung 4.1.: Konzeptioneller Aufbau des Frameworks ohne Berücksichtigung hierarchischer und nebenläufiger Zustände Ereignisse können in Zustandsdiagrammen beliebiger Natur sein. Dieser Umstand und die Tatsache, dass als Zielsetzung die Erweiterbarkeit des Frameworks zugrunde liegt, stellt entsprechende Anforderungen an die Konzeption. Bei Bosch werden Er- eignisse durch eine Zeichenkette repräsentiert, was jedoch unflexibel ist. Stattdessen eignet sich das Command-Entwurfsmuster: In einer Schnittstelle wird eine Methode deklariert, welche in einer implementierenden Klasse ausprogrammiert wird und vom Framework verwendet werden kann. Dieses Verfahren wird von Bosch für die Aus- führung von Aktionen verwendet. Da sich dieses Muster für Aktionen eignet, sollen hiermit ebenfalls Bedingungen und Ereignisse realisiert werden. Beim Aktivieren bzw. Deaktivieren werden mehrere Schritte durchgeführt (Setzen der Status-Variablen, ggf. Ausführen der Entry- bzw. Exit-Aktion), weshalb diese in einer jeweiligen Methode gekapselt werden. In Abbildung 4.1 ist eine Implementie- rung des bisherigen Konzepts in Form eines Klassendiagramms dargestellt. Bis hierher ähnelt der Aufbau dem von Bosch bis auf wenige Details. Allerdings sind einige für Zustandsdiagramme spezifische Elemente noch nicht berücksichtigt worden. 4.1.1 Zeitgesteuerte Transitionen Bei zeitgesteuerten Transitionen ist die Zeit relevant, die seit dem Betreten des aktuell aktiven Zustands vergangen ist. Als Besonderheit sei angemerkt, dass im Falle von Hierarchien der Oberzustand einen längeren Zeitraum aktiv sein kann als seine Unter- zustände. Daher muss jeder Zustand die Zeit kennen, die seit seiner letzten Aktivierung vergangen ist und die Klasse muss um diese Information erweitert werden. Um möglichst flexibel zu sein, soll das Hochzählen der Zeit von außen über einen Zeitgeber gesteuert werden können. Hier gibt es prinzipiell zwei Lösungsansätze. Beim ersten Ansatz wird eine konkrete Ausprägung der Event-Schnittstelle implementiert, während der zweite Ansatz eine zusätzliche Methode timeout(ms) vorsieht. Da das Ziel
  • 33. 4.1. Konzeptioneller Aufbau 23 Abbildung 4.2.: Erweiterung der Klassen State und Transition für zeitgesteuerte Transitionen, sowie Einführung der Klasse PseudoState ist, die Anzahl der Klassen möglichst gering zu halten, wird der zweite Ansatz verfolgt. Hieraus resultiert, dass eine Transition die zu wartende Zeit nicht als Instanz der Event- Klasse speichert, sondern als reinen Integer-Wert. Beim Schalten der Transition wird zunächst geprüft, ob die zu wartende Zeit abgelaufen ist. Neben der Verwaltung der Zeit ist es in beiden Fällen notwendig, beim Betreten des Zustands in der Methode activate() die Zeit zurückzusetzen. Abbildung 4.2 zeigt die Änderungen an den Klassen. 4.1.2 Segmentierte Transitionen Eine weitere Besonderheit in Zustandsdiagrammen ist die Verbindungsstelle als Pseu- dozustand für segmentierte Transitionen. Pseudozustände haben zwei Gemeinsamkei- ten, nämlich dass diesen keine Entry- bzw. Exit-Aktion zugewiesen und nicht in ihnen verweilt werden kann. Der erste Punkt trifft ebenso auf den Endzustand zu, obwohl es sich hier streng genommen um keinen Pseudozustand handelt. Trotzdem wird nur eine neue Klasse PseudoState ergänzt, welche auch den Endzustand repräsentiert (siehe Abbildung 4.2). Die zur Verbindungsstelle hinführende Transition darf nur dann schalten, wenn es einen Weg zu einem normalen Zustand gibt. Diese Prämisse muss durch das erste Segment sichergestellt werden, sodass dieses vor der tatsächlichen Ausführung solch einen Weg suchen muss. Hierzu bedient sich das Framework einer Tiefensuche. Eine auszuführende Transition überprüft grundsätzlich mit ihrer Methode allowed() die ggf. vorhandene Bedingung und schließlich, ob es sich bei dem Zielzustand um einen ech- ten Pseudozustand, also nicht dem Endzustand, handelt. Falls ja, wird die Tiefensuche gestartet, indem auf dem Pseudozustand die Methode lookup() aufgerufen wird, die ihrerseits für alle ausgehenden Transitionen die Methode allowed() aufruft. Erst, wenn ein Weg zu einem normalen Zustand gefunden wurde, wird der Quellzustand de- und der Zielzustand aktiviert. Da es sich bei der Verbindungsstelle um einen Pseudozu-
  • 34. 4. Das Statechart-Framework 24 x=0 −→ Abbildung 4.3.: Verarbeitung segmentierter Transitionen für den Fall x = 0
  • 35. 4.1. Konzeptioneller Aufbau 25 Abbildung 4.4.: Ereignisverarbeitung auf dem Oder-Zustand stand handelt, wird dieser automatisch bei Aktivierung sofort wieder verlassen, indem mittels dispatch(null) die Ereignisverarbeitung neu angestoßen wird. In Abbildung 4.3 ist dieser Ablauf dargestellt. 4.1.3 Hierarchie und Nebenläufigkeit Im Gegensatz zu Bosch und van Gurp muss das zu entwickelnde Framework noch um die beiden essenziellen Elemente der Hierarchiebildung und der Verwendung von Nebenläufigkeit erweitert werden. Hierarchische Zustände Die von Oder-Verfeinerungen aufgebaute Struktur ist die eines Baums. Ziel ist es somit innerhalb des Frameworks solch eine Baumstruktur aufzubauen. Hier ist die oben vorgestellte Sichtweise des Kontexts als Spezialfall eines Zustands hilfreich. Bisher stellt der Kontext auf oberster Hierarchieebene das Zustandsdiagramm dar und kennt den aktuell aktiven Zustand auf der darunterliegenden Ebene. Dieses Kon- zept lässt sich auf die Oder-Verfeinerung anwenden: Diese ist ein Spezialfall eines Zustands, welcher jeweils genau einen aktiven Unterzustand hat. Also genau das, was der Kontext auf oberster Hierarchieebene abbildet. Da die Klasse Context eine Generalisierung der Klasse State ist, kann vom Kontext einfach eine neue Klasse abgeleitet werden, die das Spezialverhalten eines hierarchi- schen Zustands repräsentiert. Der Kontext wird zu einer abstrakten Basisklasse für hierarchische Zustände. Beim Aktivieren eines Zustands meldet er dies seinem Vater- knoten. Zur Abbildung der Baumstruktur muss die Zustandsklasse erweitert werden. Jedem Zustand muss sein Vaterknoten bekannt sein. Der einzige „Zustand“ ohne Va- terknoten ist das Diagramm selbst, welches künftig durch die Klasse Statechart re- präsentiert wird. Das Diagramm ist also ein zusammengesetzter Zustand und bildet immer den Wurzelknoten der Baumstruktur. Ereignisverarbeitung Im Gegensatz zu normalen Zuständen ist die Verarbeitung eines eingehenden Ereignisses komplexer, da die in Abschnitt 2.1.1 beschriebene Vor- rangsregel berücksichtigt werden muss. Hierzu muss die entsprechende Methode in der abgeleiteten Klasse überschrieben werden, um das Ereignis zunächst an den aktiven Unterzustand zu propagieren. Die Vererbung von Transitionen wird implizit durchgeführt. D. h. beim Aufbau des Diagramms müssen vererbte Transitionen nicht explizit für die Unterzustände ange-
  • 36. 4. Das Statechart-Framework 26 =⇒ Abbildung 4.5.: Transitionsverhalten bei hierarchischen Zuständen legt werden. Falls der Unterzustand das Ereignis nicht verarbeiten kann, wird geprüft, ob die Oder-Verfeinerung eine Transition besitzt, die auf das Ereignis reagieren kann. Jedoch muss eine Besonderheit berücksichtigt werden, um die Semantik korrekt ab- zubilden: Ist der Endzustand der Oder-Verfeinerung noch nicht erreicht worden, müs- sen alle Beendigungstransitionen von der Verarbeitung ausgeschlossen werden. Konnte hingegen der Unterzustand das Ereignis verarbeiten, ist dessen Behandlung auf dem Oder-Zustand abgeschlossen. Abbildung 4.4 zeigt den Ablauf solch einer Verarbeitung. Transitionen Wie bei Bosch kennen die Übergänge bisher nur den Zielzustand, um diesen zu aktivieren. Bei der Verwendung von Hierarchien reicht diese einfache Sichtweise nicht mehr aus, da es jetzt möglich ist, dass beim Schalten einer Transition mehrere Zustände (de-)aktiviert werden müssen. Im Beispiel aus Abbildung 4.5 werden beim Ausführen der Transition zum Zustand r automatisch auch die Zustände p und q aktiviert. Analoges gilt für den Übergang von r nach y. Hierbei werden q und p automatisch de- und x aktiviert. Eine Transition muss also den Pfad vom Quell- zum Zielzustand im durch die Hier- archie aufgespannten Baum berücksichtigen. Hierzu wird der kleinste gemeinsame Vor- fahre (LCA = Least common ancestor) berechnet (OMG, 2003). Alle Zustände von der Quelle zum LCA werden deaktiviert, analog werden alle Zustände auf dem Pfad vom LCA zum Ziel aktiviert. In obigem Beispiel ist der gemeinsame Vorfahre bei allen drei Transitionen das Zustandsdiagramm selbst, also der Wurzelknoten. Für die Implementierung bedeutet dies, dass bei der Erzeugung einer Transition der Quell- und Zielzustand übergeben werden muss und anhand der Hierarchie zwei Zustandsmengen berechnet werden. History-Zustände Die beiden History-Zustandsarten können sehr einfach imple- mentiert werden. Hierzu wird eine Tiefensuche auf dem Oder-Zustand ausgeführt, welche alle derzeit aktiven Knoten in einer Liste speichert. Die Suchtiefe beschränkt sich bei einem normalen History-Zustand auf Eins. Diese Sicherung wird beim De- aktivieren der Oder-Verfeinerung durchgeführt. Beim Betreten des History-Zustands werden entsprechend der gespeicherten Liste die Zustände wieder aktiviert bzw. die- ser beim erstmaligen Betreten automatisch über seine ausgehende Transition verlassen. Die Implementierung beschränkt sich daher auf die Erweiterung der Klasse für Pseudo- zustände um eine Tiefensuche und die Möglichkeit der Speicherung einer Zustandsliste. Abbildung 4.6 zeigt die entsprechenden Erweiterungen des Frameworks.
  • 37. 4.1. Konzeptioneller Aufbau 27 Abbildung 4.6.: Erweiterung des Frameworks um Hierarchie Nebenläufige Zustände Nebenläufigkeit als der zweite zentrale Aspekt von Zustandsdiagrammen wird durch das Hinzufügen einer neuen Klasse ConcurrentState erreicht. Diese ist wie die Oder- Verfeinerung ein Kontext. Der essenzielle Unterschied ist, dass nicht genau ein Unterzu- stand aktiv ist, sondern alle Unterzustände gleichzeitig. Regionen wiederum sind Oder- Verfeinerungen, denen als Vaterknoten der nebenläufige Zustand zugewiesen wird. Ereignisverarbeitung Die Verarbeitung eines eingehenden Ereignisses funktioniert im Wesentlichen genauso wie bei hierarchischen Zuständen (siehe Abbildung 4.4). Der Hauptunterschied ist der, dass das Ereignis nicht an einen Unterzustand, sondern an alle Regionen delegiert und kein Startzustand gesetzt wird. Hierbei muss beachtet werden, dass ein Oder-Unterzustand das Ereignis nur dann verarbeiten kann, wenn die Und-Verfeinerung aktiv ist: Wird beispielsweise der ne- benläufige Zustand aus einer Region heraus über eine Transition verlassen, dürfen die restlichen Bereiche das Signal nicht weiter verarbeiten. Sobald ein Unterzustand das Ereignis behandeln konnte, gelten dieselben Abläufe wie bei hierarchischen Zuständen. Das Framework selbst unterstützt in dieser Form keine echte Nebenläufigkeit, son- dern bearbeitet wie Ali und Tanaka die einzelnen Regionen sequenziell. Die Neben- läufigkeit entsteht dadurch, dass alle Regionen im gleichen Schritt der Simulation auf das Ereignis reagieren können. Transitionen Diese haben bisher die Eigenschaft, dass ihnen eine Liste an Zustän- den bekannt ist, die beim Schalten aktiviert bzw. deaktiviert werden müssen. Bei der
  • 38. 4. Das Statechart-Framework 28 Abbildung 4.7.: Ablauf der execute-Methode einer Transition Und-Verfeinerung entsteht ein Problem: Wird direkt ein Unterzustand einer Region angesprungen, stehen in der Liste der zu aktivierenden Zustände die Und-Verfeinerung an Position n, die Region an n + 1 und der Unterzustand an n + 2. Da beim Betreten des Und-Zustands automatisch alle Regionen aktiviert werden müssen, entsteht ein Konflikt, denn die Aktivierung erfolgt immer an den Startzuständen der Bereiche. Es muss also eine Möglichkeit geschaffen werden, die es erlaubt einzelne Regio- nen bei der Aktivierung des Und-Zustands zu ignorieren. Hierzu wird in der Klasse ConcurrentState eine Liste von Regionen gepflegt, die nicht automatisch aktiviert wer- den sollen. Diese Liste wird dynamisch zur Laufzeit von der Transition gefüllt, indem geprüft wird, ob der Zielzustand des Übergangs in einer Region liegt oder die Und- Verfeinerung selbst ist. Bei der Deaktivierung des Zustands wird diese Liste geleert. Abbildung 4.7 zeigt den Ablauf beim Schalten einer Transition. Gabelung einer Transition Die Implementierung des Fork-Zustands ist mit der Erweiterung der Und-Verfeinerung um eine Menge der nicht automatisch zu aktivie- renden Regionen einfach zu erreichen. Es wird dasselbe Prinzip angewendet wie bei Transitionen: Zunächst wird ein Weg zu einem normalen Zustand gesucht. Ist dieser gefunden worden, wird bei Erreichen des Fork-Zustands die Liste der Transitionen durchlaufen und die jeweiligen Regionen ermittelt, die ignoriert werden müssen. Erst danach werden die ausgehenden Transitionen nacheinander ausgeführt. Es reicht, die- ses Vorgehen in der Klasse PseudoState in der Methode activate() zu programmieren. Vereinigung mehrerer Transitionen Das Gegenstück zur Gabelung ist die Syn- chronisation der einzelnen Regionen am Join-Zustand. Die Beendigungstransition wird automatisch ausgeführt, wenn alle Regionen ihren jeweiligen Endzustand erreicht ha- ben. Diese Prämisse ist beim Join-Zustand nicht erfüllt. Stattdessen bilden all diejeni- gen Zustände einen gültigen „Endzustand“ der Und-Verfeinerung, die eine Transition zum Join-Zustand besitzen. Im Folgenden wird diese Zustandsmenge als Endkonfigu- ration bezeichnet. Es gibt prinzipiell zwei Stellen, an denen solch eine Endkonfiguration gespeichert
  • 39. 4.2. Implementierung 29 Abbildung 4.8.: Erweiterung des Frameworks um Nebenläufigkeit werden kann. Entweder im Und- oder im Join-Zustand. Da diese Menge mit letzterem Typ assoziiert wird, soll diese dort gehalten werden. Die Klasse PseudoState bietet hierfür zudem schon die benötigte Infrastruktur an. Der Anwender des Frameworks ist dafür verantwortlich, dass dem Join-Zustand diese Endkonfiguration bekannt gemacht wird. Die Methode lookup() führt neben der obligatorischen Tiefensuche im Falle des Typs Join zusätzlich die Prüfung aus, ob die angegebenen Zustände aktiv sind. Diese einfache Implementierung birgt jedoch den Nachteil, dass nicht alle Aktionen ausgeführt bzw. Bedingungen geprüft werden, die an den zum Join-Zustand hinfüh- renden Transitionen stehen. Das Klassendiagramm aus Abbildung 4.8 zeigt die Ände- rungen an dem Framework, die zur Realisierung der Nebenläufigkeit notwendig sind. 4.2 Implementierung Im Folgenden wird die Implementierung des Frameworks beschrieben und auf Opti- mierungen aufmerksam gemacht, die durch die Beschränkungen des RCX notwendig wurden. Die Programmquellen sind in dem Paket statechart.base untergebracht. In Abbildung 4.9 ist die Implementierung des Frameworks zu sehen. Diese unterscheidet sich vom prinzipiellen Aufbau her nicht von dem vorgestellten Konzept. Aufgrund der Anforderungen an das Framework wurden jedoch einige Änderungen erforderlich.
  • 40. 4. Das Statechart-Framework 30 Abbildung 4.9.: Klassendiagramm der Implementierung des Frameworks
  • 41. 4.2. Implementierung 31 4.2.1 Speicherplatzoptimierungen Insgesamt besteht das vorgestellte Framework aus einer möglichst minimalen Anzahl an Klassen. Allerdings ist dies nur der erste Schritt um Speicherplatz zu sparen. Die nächsten Abschnitte beschreiben die weiteren wesentlichen Optimierungen. Verwaltung von Listen Zunächst fällt auf, dass die zu verwaltenden Listen in einer Klasse über den vom JDK zur Verfügung gestellten Vektor einen enormen Speicherplatzverbrauch verursachen. Selbiges gilt für die Reimplementierung der Vektor-Klasse in LeJOS. Die Gründe hier- für liegen an zwei Stellen: 1. Es werden sehr viele Komfortmethoden angeboten, die die Handhabung der Klas- se vereinfachen sollen. Hierzu zählen z. B. unterschiedliche Parameterlisten. 2. Die Methoden enthalten im Allgemeinen einen Programmcode, der prüft, ob die angegebenen Parameter im Definitionsbereich liegen. Da die Verwaltung der Listen ausschließlich im Framework stattfindet und der An- wender keinen direkten Zugriff auf diese erhält, können die beiden aufgeführten Punkte als Ansatz zur Platzersparnis verwendet werden. Hierzu werden unnötige Methoden nicht implementiert und Sicherheitsüberprüfungen ausgeklammert. Dies führt dazu, dass eine eigene Klasse Vector verwendet wird, die minimale Funktionalität besitzt und somit platzsparend ist. Zusätzlich wird durch die ausschließliche Sichtbarkeit der Klasse in dem Paket statechart.base sichergestellt, dass diese nur innerhalb des Pakets Verwendung findet. Als Basis dient die gleichnamige Klasse aus dem LeJOS-Paket. Verwendung statischer Methoden An einigen Stellen werden Berechnungsmethoden verwendet, die in allen Instanzen einer Klasse verwendet werden und nicht auf Klassenvariablen zugreifen. Hier ist ein einfacher Trick die Verwendung von statischen Methoden. Zeitereignis Da wie in der Konzeption beschrieben kein Timeout-Ereignis als Klasse realisiert ist, die Verarbeitung der Ereignisse aber über die dispatch-Methode stattfindet, wird als Übergabeparameter null als Zeitereignis vereinbart. Die timeout-Methoden erhöhen bei Aufruf nur die aktuelle Zeit im Zustand. Anschließend wird seitens der Klasse Statechart auf dem derzeitigen Zustand die Ereignisverarbeitung angestoßen (siehe Listing 4.1). Objekterzeugung innerhalb des Frameworks Ein essenzieller Punkt ist das Vermeiden von Objekt-Instanziierungen mittels new innerhalb des Frameworks bei der Ereignisverarbeitung. Dies führt zu potenziell un- überschaubar vielen Objekten und somit im Rahmen des RCX schnell zu einem Spei- cherüberlauf. Objekte werden im Framework daher nur während der Konstruktion des
  • 42. 4. Das Statechart-Framework 32 Listing 4.1: Implementierung des Zeitereignis in den Klassen Statechart und State // S t a t e c h a r t −K l a s s e public void t i m e o u t ( i n t time ) { c u r r e n t S t a t e . t i m e o u t ( time ) ; c u r r e n t S t a t e . d i s p a t c h ( null ) ; } // S t a t e −K l a s s e protected void t i m e o u t ( i n t time ) { currentTime += time ; } Zustandsdiagramms instanziiert. Sobald alle Zustände, Transitionen, Aktionen, Er- eignisse und Bedingungen angelegt wurden, findet nur noch die Ereignisverarbeitung mittels der timeout- und dispatch-Methoden statt. Neue Objekte werden zu diesem Zeitpunkt seitens des Frameworks nicht mehr instanziiert. 4.2.2 Berechnung des LCA Eines der bisher noch nicht berücksichtigten Elemente ist die Berechnung des kleins- ten gemeinsamen Vorfahrens zweier Knoten. Diese findet in der statischen Methode calculateStateSet der Klasse Transition statt. Auffällig ist der Rückgabewert. Hier- bei handelt es sich um ein zweidimensionales Feld, welches die zu (de-)aktivierenden Zustände beinhaltet. Dieses Array wird für jede Transition einmal in der benötigten Größe erzeugt, sodass hier eine optimale Speicherausnutzung stattfindet. Die Berech- nung selbst folgt einem einfachen Algorithmus: 1. Speichere den Pfad vom Startzustand zum Wurzelknoten der Hierarchie. 2. Speichere den Pfad vom Endzustand zum Wurzelknoten der Hierarchie. 3. Wähle die Länge min des kürzeren Pfads. 4. Setze i = 0. 5. Solange i < min ist, vergleiche von der Wurzel ausgehend die Elemente der beiden Pfade an Position i. a) Falls die Elemente gleich sind, setzte i = i + 1. b) Falls die Elemente ungleich sind, stoppe den Vergleich. i − 1 ist der LCA. Für die Umsetzung fällt auf, dass in den Schritten eins und zwei temporäre Variablen benötigt werden, die den Pfad sichern. Da dieser beliebig lang werden kann, muss in
  • 43. 4.2. Implementierung 33 der Implementierung ein dynamisches Feld verwendet werden. Die Klasse Vector bietet sich hier an, bringt aber auch ein Problem mit sich: In jedem Aufruf des Algorithmus werden zwei Objekte mittels new angelegt. Insgesamt werden bei n Transitionen 2n temporäre Vektoren angelegt und somit unnötiger Speicherplatz verschwendet. Statt- dessen werden außerhalb der statischen Methode zwei ebenfalls statische Hilfsvektoren angelegt, sodass diese wiederverwendet werden können und 2n − 2 Objekte wegfallen. Nach der Berechnung des LCA müssen die zu (de-)aktivierenden Zustände nur noch in das hierzu angelegte Feld kopiert werden. Listing 4.2 zeigt den zugehörigen Quelltext. 4.2.3 Verwendung des Frameworks Ein weiteres Ziel ist die einfache Verwendung des Frameworks. Aus diesem Grund werden öffentlich sichtbare Hilfsfunktionen in den Klassen zur Verfügung gestellt, die die Handhabung erleichtern und bei der Konstruktion syntaktisch korrekter Zustands- diagramme helfen sollen. Hierzu zählen zum Beispiel die Methoden getStart() und respektive getEnd() auf dem Kontext. Hierdurch wird nicht nur sichergestellt, dass der Zugriff auf diese beiden Zustände einfach ist, sondern auch dass ein Kontext nur einen Start- bzw. Endzustand1 besitzen kann. Ähnliche Komfortmethoden bieten die hierarchischen Zustände zur Ermittlung des History-Zustands und die Pseudozustän- de, um für die Vereinigung von Transitionen die Endkonfiguration angeben zu können. Nebenläufige Zustände bieten die Möglichkeit, mittels addRegion() eine neue Region zu ergänzen. Für die so ermittelten Zustände wird der Kontext automatisch gesetzt, sodass der Anwender diesen nicht explizit setzen muss. Eine Besonderheit bieten Zustandsübergänge. Die Verknüpfung von einem Zustand mit einer Transition findet automatisch beim Anlegen selbiger statt. Das heißt, es wird dem Startzustand automatisch mitgeteilt, dass dieser eine neue abgehende Transition erhält. So können Zustandsübergänge mit nur einer Programmzeile angelegt werden. Insgesamt bietet das Framework aufgrund dieser wenigen Hilfsfunktionen und mit der Erweiterbarkeit durch die Interfaces Action, Guard und Event eine sehr einfa- che Programmier-Schnittstelle für den Anwender. Die Verwendung funktioniert immer nach dem selben Muster: 1. Anlegen der Zustände (einfache, hierarchische, nebenläufige, Regionen und Pseu- dozustände). 2. Aufbau der Hierarchie mittels der Methode setContext(). 3. Falls Join-Zustände verwendet werden, die Endkonfigurationen angeben. 4. Erzeugen der Transitionen. Anschließend ist das Zustandsdiagramm einsatzbereit und kann in der Hauptpro- grammschleife verwendet werden, welche Timeout-Signale und Ereignisse an das Dia- gramm sendet. Ein Beispiel einer möglichen Programmschleife ist in Kapitel 7.3 zu 1 DieModellierung lässt mehrere Endzustände zu. Diese können jedoch immer zu einem zusammen- gefasst werden, sodass dies keine Einschränkung darstellt.
  • 44. 4. Das Statechart-Framework 34 Listing 4.2: Quelltext aus der Klasse Transition zur Berechnung des LCA private s t a t i c V e c tor s t a = new Vector ( 2 0 ) ; private s t a t i c V e c tor s t d = new Vector ( 2 0 ) ; private s t a t i c S t a t e [ ] [ ] c a l c u l a t e S t a t e S e t ( S t a t e s t a r t , S t a t e end ) { // Pfad vom S t a r t zum Wurzelknoten e r m i t t e l n std . c l e a r ( ) ; State s = s t a r t ; while ( s != nu ll ) { s t d . add ( 0 , s ) ; i f ( s . c o n t e x t instanceof H i e r a r c h i c a l S t a t e | | s . c o n t e x t instanceof C o n c u r r e n t S t a t e ) { s = ( State ) s . context ; } e l s e s = nu ll ; } ... // Q u e l l t e x t f ü r s t a a n a l o g // b e r e c h n e n d e s LCA i n t min = s t a . s i z e ( ) < s t d . s i z e ( ) ? s t a . s i z e ( ) : s t d . s i z e ( ) ; i n t l c a = min − 1 ; // G i l t f a l l s s t a r t=end . min i s t mind . 1 i f ( s t a r t != end ) { f o r ( l c a = 0 ; l c a < min ; l c a ++) i f ( s t a . g e t ( l c a ) != s t d . g e t ( l c a ) ) break ; } // a n l e g e n d e s A u s g a b e a r r a y s S t a t e [ ] [ ] s t a t e s = new S t a t e [ 2 ] [ ] ; s t a t e s [ 0 ] = new S t a t e [ s t d . s i z e ( ) − l c a ] ; s t a t e s [ 1 ] = new S t a t e [ s t a . s i z e ( ) − l c a ] ; // k o p i e r e n d e r zu ( de −) a k t i v i e r e n d e n Zustände f o r ( i n t i = s t a t e s [ 0 ] . l e n g t h − 1 , j = l c a ; i >= 0 ; i −−, j ++) s t a t e s [ 0 ] [ i ] = ( State ) std . get ( j ) ; f o r ( i n t i = 0 , j = l c a ; i < s t a t e s [ 1 ] . l e n g t h ; i ++, j ++) s t a t e s [ 1 ] [ i ] = ( State ) sta . get ( j ) ; return s t a t e s ; }
  • 45. 4.3. Unittests 35 Abbildung 4.10.: Beispieldiagramm für die Umsetzung in den Quelltext finden. Das Beispiel aus Listing 4.3 soll den Aufbau des Quelltextes verdeutlichen. Hierzu wird das in Abbildung 4.10 dargestellte Zustandsdiagramm mit dem Frame- work umgesetzt2 . Durch diesen einfachen und vor allem strukturell immer gleich aufgebauten Quell- text, ist eine weitere Anforderung erfüllt: Die Vereinfachung der Codegenerierung da- hingehend, dass nur eine Klasse generiert werden muss, in der das Framework verwen- det wird. Eine genaue Beschreibung findet sich in Kapitel 7. 4.3 Unittests Im Rahmen der Entwicklung ist das Testen der Software ein stetiger Begleiter. Da- her soll dieser Schritt vollkommen automatisiert durchgeführt werden. Hierzu bietet sich die Verwendung von JUnit (Clark u. a., 2006) als Testumgebung an. Allerdings soll an dieser Stelle nur ein Verfahren erläutert werden, mit dem sich die Seman- tik von Zustandsdiagrammen testen lässt und wie dieser Testaufbau mittels JUnit umgesetzt werden kann. Die eigentlichen Testfälle sind im Anhang A zu finden. Da der RCX-Baustein keine Möglichkeit zum automatisierten Testen anbietet, werden die Prüfungen auf die Laufzeitumgebung für Zustandsdiagramme beschränkt. Das Testen von Zustandsdiagrammen basiert in diesem Ansatz auf einer einfachen Erkenntnis: Der Durchlauf durch das Diagramm lässt sich komplett als eindeutiger Pfad beschreiben. Hierbei wird jeweils registriert und aufgezeichnet, wann ein Zustand aktiviert, deaktiviert oder eine Aktion ausgeführt wird. Das Testen besteht letztlich darin, den durchlaufenen Pfad mit dem Soll-Pfad zu vergleichen. In letzterem wird vor- gegeben, in welcher Reihenfolge die Zustände (de-)aktiviert und Aktionen ausgeführt werden müssen. Hierbei scheinen die nebenläufigen Zustände Probleme zu bereiten, denn theoretisch kann die Reihenfolge, in der die Regionen ein eingehendes Ereignis verarbeiten, immer unterschiedlich sein, je nachdem welcher Prozess als nächstes die CPU-Zeit zugewiesen bekommt. Dies würde ein wesentlich komplexeres Vorgehen erfordern, um die beiden Pfade zu vergleichen, da für jede nebenläufige Region der Pfad aufgeteilt werden müss- te. Um dies zu vermeiden, wird im Folgenden ohne Beschränkung der Allgemeinheit 2 Die verwendeten Aktionen und Signale sind mit Pseudocode angegeben.