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.
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.
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.
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
.
- Erprobe die Verwendung der Befehle
liMotor.forward();
undliMotor.stop();
anstelle des BefehlsliMotor.rotate(x,true);
zum geschmeidigen Fahren! - 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.
-
Modifiziere die vorige Aufgabe weiterhin, so dass bei der ersten
threshold
-Unterschreitung das Tempo gedrosselt wird und bei der zweitenthreshold
-Unterschreitung der Roboter anhält.
Quellen
- [1]: Schleife mit unbekannter Anzahl an Wiederholungen - Urheber: mks - Lizenz: Inf-Schule.de
- [2]: Flussdiagramm zur while-Schleife - Urheber: mks - Lizenz: Inf-Schule.de
- [3]: Flussdiagramm zur do-while-Schleife - Urheber: mks - Lizenz: Inf-Schule.de
- [4]: Geschachtelte Fallunterscheidung in Schleife: schrittweise Tempodrosselung - Urheber: mks - Lizenz: Inf-Schule.de