i

Kopf- und fußgesteuerte Schleifen

Hindernis an beliebiger Stelle erkennen mit kopf- und fußgesteuerten Schleifen

Bei der Fallunterscheidung haben wir einmalig überprüft, ob wir ein Hindenis erkennen oder nicht. Leider musste dazu das Hindernis an einem festen Ort positioniert sein. Viel flexibler wäre es, wenn wir das Hindernis an einer beliebigen Stelle platzieren könnten. Der Roboter muss dann wiederholt im Wechsel fahren und auf ein Hindernis prüfen. Da wir nicht wissen, wo das Hindernis ist, wissen wir auch nicht, wie oft die Schleife durchlaufen wird und somit nicht, im wievielten Durchlauf das Abbruchkriterium der Schleife erfüllt ist (siehe Abbildung 1). Wir können uns nun entscheiden, ob wir a) "defensiv" erstmal messen und dann fahren, oder b) "aggressiv" erst fahren und dann messen.

Schleife mit unbekannter Anzahl an Wiederholungen[1]

while-Schleife (kopfgesteuert)

Hier misst man zuerst und fährt dann. Im Unterschied zur Fallunterscheidung wird die Messung im Flussdiagramm in einem Schritt durchgeführt. Man könnte auch hier eine Zählvariable (counter) integrieren, die die Anzahl an Schleifendurchläufen mitprotokolliert, es ist allerdings zum Lösen der eigentlichen Aufgabe nicht notwendig.

Flussdiagramm zur while-Schleife mit blau eingefaerbtem Rueckkopplungspfeil[2]

Beim Programmcode orientieren wir uns ebenfalls an der Fallunterscheidung, insbesondere bei der Integration des Ultraschallsensors zur Messung des Abstands.

import lejos.nxt.Motor;
import lejos.nxt.NXTRegulatedMotor;
import lejos.nxt.SensorPort;
import lejos.nxt.UltrasonicSensor;
public class WhileSchleife 
{
  static UltrasonicSensor ultra =  new UltrasonicSensor(SensorPort.S1);  
  static NXTRegulatedMotor reMo = Motor.A;
  static NXTRegulatedMotor liMo = Motor.B;
  public static void main(String[] args) 
  {		
    int speed = 900;
    int x = 1500;			
    reMo.setSpeed(speed);
    liMo.setSpeed(speed);

    //while-Schleife
    while (ultra.getDistance() > 10)
    {
      reMo.rotate(x,true);
      liMo.rotate(x);
    }					
  }	
}

Der Aufbau einer while-Schleife folgt ebenfalls einer vorgeschriebenen Syntax:

while Abbruchkriterium {Anweisungen}
while ultraschall.getDistance() > 10 {...}

Erklärung:

while
Schlüsselwort zum Einleiten der while-Schleife
Abbruchkriterium
Bedingung(en) für das Ausführen des Schleifenrumpfs. Ist die Bedingung nicht (mehr) erfüllt, dann setzt das Programm in der nächsten Anweisung unterhalb der Schleife fort.
{Anweisungen}
diese Menge von Anweisungen werden pro Schleifendurchlauf jeweils einmal ausgeführt.

do-while-Schleife (fußgesteuert)

Dieser Schleifentyp ist fußgesteuert, d.h.: die Schleife wird mindestens einmal ausgeführt und dann erst die Bedingung geprüft. Hier fährt man zuerst und misst dann.

Flussdiagramm zur do-while-Schleife mit blau eingefaerbtem Rueckkopplungspfeil[3]
import lejos.nxt.Motor;
import lejos.nxt.NXTRegulatedMotor;
import lejos.nxt.SensorPort;
import lejos.nxt.UltrasonicSensor;

public class DoWhileSchleife  
{
  static UltrasonicSensor ultra =  new UltrasonicSensor(SensorPort.S1);  
  static NXTRegulatedMotor reMo = Motor.A;
  static NXTRegulatedMotor liMo = Motor.B;
  public static void main(String[] args) 
  {		
    int speed = 900;
    int x = 1500;			
    reMo.setSpeed(speed);
    liMo.setSpeed(speed);

    //do-while-Schleife
    do 
    {
      reMo.rotate(x,true);
      liMo.rotate(x);
    }
    while (ultra.getDistance() > 10);	
  }	
}

Die do-while-Schleife ist als Besonderheit die einzige Kontrollstruktur, neben der Anweisung, die mit einem Semikolon abgeschlossen wird. Der Aufbau:

do {Anweisungen} while Abbruchkriterium
do {...} while ultraschall.getDistance() > 10

Erklärung:

do
Schlüsselwort zum Einleiten der do-while-Schleife
{Anweisungen}
diese Menge von Anweisungen werden pro Schleifendurchlauf jeweils einmal ausgeführt.
while
Schlüsselwort zum Ende der do-while-Schleife
Abbruchkriterium
Bedingung(en) für das Ausführen des Schleifenrumpfs. Ist die Bedingung nicht (mehr) erfüllt, dann setzt das Programm in der nächsten Anweisung unterhalb der Schleife fort.

Aufgaben

Das Szenario oben wurde mit einer vergleichsweise ruckeligen Fahrt gelöst, da das recht gut die Schleifendurchläufe visualisiert. Man kann das Problem durchaus geschmeidiger behandeln, indem man schrittweise das Tempo drosselt.

Das Ziel ist es nun, nicht abrupt anzuhalten, sondern (wie beim Einparken) das Tempo schrittweise ab Punkt A erst zu verlangsamen und dann bei B zu stoppen. Da eine gewöhnliche Bedingung nur zwei Möglichkeiten bereithält, muss man an dieser Stelle Fallunterscheidungen schachteln.

Geschachtelte Fallunterscheidung in Schleife: schrittweise Tempodrosselung[4]
  1. Erprobe die Verwendung der Befehle liMotor.forward(); und liMotor.stop();anstelle des Befehls liMotor.rotate(x,true); zum geschmeidigen Fahren!
  2. Viele PKWs haben heutzutage eine Einparkhilfe. Nimm das Beispiel mit zwei Abstandssensoren und definiere zwei verschiedene Thresholds. Integriere in das Beispiel einen differenzierten Beep-Ton, das je nach Nähe zum Hindernis verschiedenartig ist.
  3. Modifiziere die vorige Aufgabe weiterhin, so dass bei der ersten threshold-Unterschreitung das Tempo gedrosselt wird und bei der zweiten threshold-Unterschreitung der Roboter anhält.

Quellen

Suche

v
2.6.3.8.2
www.inf-schule.de/programmierung/robotik/lejoseinstieg/schleifen/gesteuerteschleife

Rückmeldung geben