Benutzer-Werkzeuge

Webseiten-Werkzeuge


techniken:zustandsautomaten

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen gezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen Revision Vorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
techniken:zustandsautomaten [2014/03/26 14:17]
fbonowski [5. Schrittweises Erweitern]
techniken:zustandsautomaten [2016/01/21 12:45] (aktuell)
Zeile 39: Zeile 39:
  
 === Mit diesem Verhalten würde sich der Roboter an der ersten Wand den Kopf einrennen. Er braucht also eine Funktion, um Kollisionen zu erkennen und eine Wende einzuleiten:​ === === Mit diesem Verhalten würde sich der Roboter an der ersten Wand den Kopf einrennen. Er braucht also eine Funktion, um Kollisionen zu erkennen und eine Wende einzuleiten:​ ===
-{{ :intern:​staubsaug2.png?​nolink&​450 |}}+{{ :techniken:​staubsaug2.png?​nolink&​450 |}}
  
 === Einfach nur mit dem Wende anfangen reicht nicht. Wir müssen auch irgendein Kriterium defineren, nach dem entschieden wird, dass der Roboter sich weit genug gedreht hat. Das könnte z.B. eine verstrichene Zeit, eine Anzahl von Radumdrehungen oder die Ausgabe eines Sensors sein. === === Einfach nur mit dem Wende anfangen reicht nicht. Wir müssen auch irgendein Kriterium defineren, nach dem entschieden wird, dass der Roboter sich weit genug gedreht hat. Das könnte z.B. eine verstrichene Zeit, eine Anzahl von Radumdrehungen oder die Ausgabe eines Sensors sein. ===
-{{ :intern:​staubsaug3.png?​nolink&​500 |}}+{{ :techniken:​staubsaug3.png?​nolink&​500 |}}
  
 === Was fehlt noch? Es wäre auch schön, den Roboter wieder abschalten zu können... === === Was fehlt noch? Es wäre auch schön, den Roboter wieder abschalten zu können... ===
-{{ :intern:​staubsaug4.png?​nolink&​550 |}}+{{ :techniken:​staubsaug4.png?​nolink&​550 |}}
  
 ===== Umsetzung in einem Programm ===== ===== Umsetzung in einem Programm =====
Zeile 63: Zeile 63:
  
 // Die eigentliche Variable definieren wir hier - und geben gleich einen Anfangswert an: // Die eigentliche Variable definieren wir hier - und geben gleich einen Anfangswert an:
-stateType ​aktuellerZustand= standby; ​+ZustandsTyp ​aktuellerZustand= standby; ​
 </​code>​ </​code>​
 +
 +//​**Hinweis**//:​ In **Processing** muss die Definition des enums in einer eigenen Datei ("​Tab"​) mit der Endung .java stehen. (vgl. auch [[http://​stackoverflow.com/​questions/​13370090/​enums-in-processing-2-0]])
 +
  
 ==== 2. Schritt: Handlungsalternativen nach aktuellem Zustand auswählen ==== ==== 2. Schritt: Handlungsalternativen nach aktuellem Zustand auswählen ====
Zeile 145: Zeile 148:
 Die so erzeugten Programme lassen sich sehr einfach nachträglich um weitere Zustände erweitern, ohne dass die Übersichtlichkeit gefährdet wird. Es bietet sich daher an, mit einer einfachen Grundstruktur zu starten und dann nach und nach die komplexeren Funktionen hinzuzufügen. Die so erzeugten Programme lassen sich sehr einfach nachträglich um weitere Zustände erweitern, ohne dass die Übersichtlichkeit gefährdet wird. Es bietet sich daher an, mit einer einfachen Grundstruktur zu starten und dann nach und nach die komplexeren Funktionen hinzuzufügen.
  
 +===== Vom Moore zum Mealy Automaten =====
 +Die bisher vorgestellte relativ starre Struktur von Aktion, Messung, Zustandsübergang entspricht dem Konzept des Moore-Automaten. Sie hat die großen Vorteil, dass sie sich sehr übersichtlich graphisch darstellen lässt.
  
 +Bei bestimmten Problemen führt sie aber zu umständlichen Konstrukten. Wir wollen das am Beispiel des '​Wenden'​ Zustands illustrieren:​
 +<code c++>
 +ZustandsTyp wendenFun(){
 +  ////////////////////////////////////​
 +  //​Anfangsaktion:​ Was ist zu tun?
 +  ////////////////////////////////////​
 +  // Wir drehen uns im , indem wir die Räder in unterschiedlich Richtungen drehen lassen
 +  motorLinks.setSpeed(-100); ​
 +  motorRechts.setSpeed(100);​
 +  navigationModule.updateData();​
 +
 +  ////////////////////////////////////​
 +  //Eingabe und Entscheidung für nächsten Zustand
 +  ////////////////////////////////////​
 +  // Erstmal schauen, ob der Benutzer die Kiste ausschalten will:
 +  if(onOffButton.newPushDetected()){
 +    return(standby);​
 +  }else{
 +    //wenn wir genug gedreht haben, fahren wir wieder geradeaus, sonst drehen wir weiter
 +    if(navigationModule.turnAngle>​=navigationModule.desiredAngle){
 +      return(geradeaus);​
 +    }else{
 +      return(wenden);​
 +    }
 +  }
 +}
 +</​code>​
 +
 +**Jetzt gibt es aber ein Problem: Wann wird der gewünschte Winkel eingestellt und der bisher gefahrene zurückgesetzt?​**
 +
 +Wir können das über die Einführung eines weiteren Zustands lösen, in dem nichts anderes passiert, als 'die Uhr zu stellen':​
 +{{ :​techniken:​staubsaug5.png?​nolink&​550 |}}
 +
 +Die Funktion für diesen Zustand könnte dann z.B. so aussehen:
 +<code c++>
 +ZustandsTyp wendeStartenFun(){
 +  // die Wende ist abgeschlossen,​ wenn der Winkel sich um 180° (PI radian) geändert hat:
 +  navigationModule.desiredAngle=navigationModule.turnAngle+PI; ​
 +  return (drehen); // als nächstes soll gedreht werden.
 +}
 +</​code>​
 +
 +In bestimmten Fällen kann das zu einer großen Anzahl von Behelfszuständen führen, die die Übersichtlichkeit vermindern.
 +
 +Dann kann es sinnvoll sein, beim Wechsel in einen Zustand direkt die entsprechende Aktion durchzuführen. In unserem Beispiel könnte also anstatt den zusätzlichen Zustand '​wendeStarten'​ einzuführen die Funktion des Zustands '​geradeaus'​ angepasst werden:
 +
 +<code c++>
 +ZustandsTyp geradeauFun(){
 +  ////////////////////////////////////​
 +  //​Anfangsaktion:​ Was ist zu tun?
 +  ////////////////////////////////////​
 +  // Wir fahren geradeaus...
 +  motorLinks.setSpeed(100); ​
 +  motorRechts.setSpeed(100);​
 +  navigationModule.updateData();​
 + 
 +  ////////////////////////////////////​
 +  //Eingabe und Entscheidung für nächsten Zustand
 +  ////////////////////////////////////​
 +  // Erstmal schauen, ob der Benutzer die Kiste ausschalten will:
 +  if(onOffButton.newPushDetected()){
 +    return(standby);​
 +  }else{
 +    // wie genau die Kollision erkannt wird, wäre noch zu klären...
 +    if(collisionDetected){
 +      // Hier wird eine Aktion ausgeführt - in einem Moore Automaten ginge das nicht:
 +      // Die Wende ist abgeschlossen,​ wenn der Winkel sich um 180° (PI radian) geändert hat:
 +      navigationModule.desiredAngle=navigationModule.turnAngle+PI; ​
 +      return (drehen); // als nächstes soll gedreht werden.
 +    }else{
 +      return(geradeaus);​
 +    }
 +  }
 +}
 +</​code>​
 +Diese Zusätzlichen Aktionen beim Zustandswechsel können auch in den Grafen eingetragen werden (hier in rot):
 +{{ :​techniken:​staubsaug6.png?​nolink&​550 |}}
 ===== Etwas Theorie zum Abschluss ===== ===== Etwas Theorie zum Abschluss =====
 Wer etwas mathematisch denkt und gewohnt ist, sich Gedanken über die Struktur von Verfahren und Algorithmen zu machen, wird sich jetzt einige Fragen stellen: Wer etwas mathematisch denkt und gewohnt ist, sich Gedanken über die Struktur von Verfahren und Algorithmen zu machen, wird sich jetzt einige Fragen stellen:
techniken/zustandsautomaten.1395839859.txt.gz · Zuletzt geändert: 2016/01/21 12:45 (Externe Bearbeitung)