> Home
> Algorithmen
> Datenstrukturen
> Maschinenmodelle
> Probleme
> Themen
> Mindmaps
> Aufgaben
> Programmierung
> Facharbeit
> Abitur
> Projekte
> Informatik-AG
> News
> Impressum
> email
|
|
Heuristiken für Lego-Mindstorms-Roboter
Auf dieser Seite sollen einfache Heuristiken für verschiedene Aufgaben
für LEGO-MINDSTORMS-Roboter vorgestellt werden.
1. Hindernisse umfahren
Robotermodell: |
Lego-Mindstorms-Roverbot. Einfacher Roboter, zwei Motoren (rechts, links),
zwei Berührungssensoren. |
Aufgabenstellung: |
Der Roboter soll sich frei im Raum bewegen und dabei Hindernisse, auf die er stößt,
umfahren. |
Lösungsheuristik: Die Motoren des Roboters werden so angesteuert, dass der Robotor
permanent geradeaus fährt. Dabei werden die Berührungssensoren ständig abgefragt.
Meldet der rechte (linke) Berührungssensor ein Berührung mit einem Hindernis, so werden die
Motoren des Roboters so angesteuert, dass dieser zunächst einmal zurückfährt und danach
nach links (rechts) dreht. Danach kann die Geradeausfahrt wieder aufgenommen werden.
Das Ausmaß der Drehung (Drehungswinkel) wird randomisiert bestimmt, um zu vermeiden, dass
sich der Roboter in Sackgassen verfängt.
nqc-Programm
// First.nqc
// Definition einiger Konstanten
#define LinkerSensor SENSOR_1
#define RechterSensor SENSOR_3
#define LinkerMotor OUT_A
#define RechterMotor OUT_C
void ReagiereAufHindernis() // Ausweichroutine als Inline-Funktion
{ if (LinkerSensor==1)
{ OnRev(LinkerMotor+RechterMotor); Wait(60); // für 0.6 sek. Zurückfahren
OnFwd(LinkerMotor); Wait(Random(60)); // für 0 bis 0.6 sek. Rechtsdrehung
}
else {if (RechterSensor==1)
{ OnRev(LinkerMotor+RechterMotor); Wait(60); // für 0.6 sek. Zurückfahren
OnFwd(RechterMotor); Wait(Random(60)); // für 0 bis 0.6 sek. Rechtsdrehung
}
}//else
}// end of ReagiereAufHindernis
task main()
{ SetPower(LinkerMotor+RechterMotor,1); // setzt die Motorenleistung auf 1 (Konstruktionsbedingt)
SetSensor(LinkerSensor,SENSOR_TOUCH); // definiert den linken Sensor als Berührungssensor
SetSensor(RechterSensor,SENSOR_TOUCH); // definiert den rechten Sensor als Berührungssensor
while (true) // Endlosschleife
{
ReagiereAufHindernis();
OnFwd(LinkerMotor+RechterMotor);
}
} // end of main
2. Lichtquelle suchen
Robotermodell: |
Lego-Mindstorms-Roboter, Dreirad (zwei große motorisierte Räder, ein Stützrad)
, zwei Motoren (rechts, links), zwei Berührungssensoren, ein Lichtsensor. |
Aufgabenstellung: |
Der Roboter soll
die hellste Stelle in einem Raum finden. Dabei soll er sich frei im Raum bewegen und Hindernisse, auf die er stößt,
umfahren. |
Lösungsheuristik und Hinweise zur Implementation:
Die Aufgabenstellung ist zweigeteilt.
Entsprechend werden zwei Tasks (engl. Aufgaben) implementiert. Die erste Task behandelt
die Reaktion auf Hindernisse gemäß der Heuristik zu Aufgabenstellung 1.
Die zweite Task implementiert die eigentliche Suchheuristik für die Suche nach der hellsten
Stelle in einem Raum. Der Roboter führt eine lokale Suche nach folgendem Verfahren durch:
Der Roboter fährt zunächst ein kleines Stück geradeaus. Dann macht er eine volle Drehung und
bestimmt in regelmäßigen Abständen die Helligkeit seiner Umgebung. Die Stelle größter Helligkeit
(im Programm kleinster Sensorwert) wird festgehalten. Danach dreht der Roboter bis zu der zuvor
bestimmten Stelle größter Helligkeit zurück und setzt seinen Weg in diese Richtung fort.
Wird keine Abbruchbedingung formuliert, so sucht der Roboter die hellste Stelle in einem Raum
und bewegt sich dort in einer Schleife. Lokale Extrema überwindet er erstaunlich gut.
nqc-Programm:
// lokale Suche nach einer Lichtquelle
// Definition einiger Konstanten
#define LinkerSensor SENSOR_1
#define RechterSensor SENSOR_3
#define MittlererSensor SENSOR_2
#define LinkerMotor OUT_A
#define RechterMotor OUT_C
task SearchForLight()
{
while (true)
{
int value = MittlererSensor;
int localbest = MittlererSensor;
int steps;
int beststep;
steps=0;
beststep=0;
OnFwd(LinkerMotor+RechterMotor); Wait(100); // 1 sek Vorlaufen
repeat (20) // volle Drehung Konstruktionsbedingt
{ OnFwd(LinkerMotor);
OnRev(RechterMotor);
Wait(10); // drehe 0.1 sec nach rechts
steps=steps+1;
value=MittlererSensor;
if (value < localbest) // Maximierung
{ localbest=value; beststep=steps; }
} // repeat
Off(LinkerMotor+RechterMotor);
repeat (20-beststep)
{ OnFwd(RechterMotor); //zurückdrehen
OnRev(LinkerMotor);
Wait(10);
}
// jetzt ist die hellste Richtung gefunden
Off(LinkerMotor+RechterMotor);
OnFwd(LinkerMotor+RechterMotor); Wait(300); // 3 sek Vorlaufen
} //while true
}// end of task SearchForLight
task main()
{ SetPower(LinkerMotor+RechterMotor,1); // setzt die Motorenleistung auf 2 (Konstruktionsbedingt)
SetSensor(LinkerSensor,SENSOR_TOUCH); // definiert den linken Sensor als Berührungssensor
SetSensor(RechterSensor,SENSOR_TOUCH); // definiert den rechten Sensor als Berührungssensor
SetSensorType(MittlererSensor,SENSOR_TYPE_LIGHT); // Mittlerer Sensor = Lichtsensor
SetSensorMode(MittlererSensor,SENSOR_MODE_RAW); // Rohwert-Sensor
SelectDisplay(DISPLAY_SENSOR_2);
start SearchForLight; // Lichtsuche
start CheckForObstacle; // Hindernisausweichen
}
task CheckForObstacle()
{ while (true)
{
if (LinkerSensor==1)
{ stop SearchForLight;
OnRev(LinkerMotor+RechterMotor); Wait(60); // für 0.6 sek. Zurückfahren
OnFwd(LinkerMotor); Wait(Random(60)); // für 0 bis 0.6 sek. Rechtsdrehung
OnFwd(LinkerMotor+RechterMotor); Wait(60); // erst mal etwas geradeaus
start SearchForLight;
}
else {if (RechterSensor==1)
{ stop SearchForLight;
OnRev(LinkerMotor+RechterMotor); Wait(60); // für 0.6 sek. Zurückfahren
OnFwd(RechterMotor); Wait(Random(60)); // für 0 bis 0.6 sek. Linksdrehung
OnFwd(LinkerMotor+RechterMotor); Wait(60); // erst mal etwas geradeaus
start SearchForLight;
}
}// else
}// while true
} // end of CheckForObstacle
3. Linienverfolgung
Robotermodell: |
Lego-Mindstorms-Roboter, Dreirad (zwei mittelgroße motorisierte Räder, ein Stützrad)
, zwei Motoren (rechts, links), zwei Berührungssensoren, ein auf den Boden gerichteter Lichtsensor. |
Aufgabenstellung: |
Der Roboter soll
eine schwarze Linie verfolgen. |
Lösungsheuristik und Hinweise zur Implementation:
Der Linienverfolger, wird nach den Idee der verhaltensorientierten KI implementiert.
Es gibt drei (quasi)parallel Prozesse (als tasks implementiert), die als
Abbildung zwischen Sensoren (hier Lichtsensor) und Aktoren (hier Motoren)
wirken und mittels der (gemessenen) Quantitäten "aufLinie" und "Richtung"
eine Rückkopplung erlauben.
(vgl. Knoll, A.C.; Burgard, W. und Christaller, T.: Robotik.
In: Görz, G.; Rollinger, C.-R. und Schneeberger, J. (Hrsg.): Handbuch der
künstlichen Intelligenz. 3. Auflg. München; Wien:Oldenbourg, 2000.)
Beschreibung der Prozesse:
Antrieb: In Abhängigkeit von der Quantität "Richtung" bewirkt der Prozess
"Antrieb", dass leichte Bögen in Rechts-, bzw. Linksrichtung gefahren
werden.
Sensor: Der Prozess liest den Lichtsensor ab und setzt die Quantität "ausLinie"
auf die Werte 0=Linie verloren oder 1=Linie gefunden.
SucheLinie: Dieser Prozess fragt die Quantität "aufLinie" ab und versucht im
Falle des Verlustes der Linie diese wiederzufinden, indem eine
Drehbewegung entgegen der letzten Kreisbogenbewegung des
Antriebsprozesses bewirkt wird.
Alle Prozesse laufen (quasi)parallel ab.
Beschreibung der Quantitäten:
Richtung: Richtung der Kreisbögen, links oder rechts
aufLinie: 0=Linie verloren, 1=Linie gefunden
Anmerkung: Es handelt sich bei dem Verfahren nicht um einen "guten" Linienverfolger.
Der Roboter torkelt an der Linie entlang, verliert sie jedoch nicht.
Bei der Implementation ging es lediglich darum, die Aufgabe im Sinne
der verhaltensorientierten KI zu lösen.
nqc-Programm:
#define LichtSensor SENSOR_2
#define RechterMotor OUT_A
#define LinkerMotor OUT_C
#define LichtGrenzwert 47 // Grenzwert Untergrundabhängig
#define links 0
#define rechts 1
#define FindTime 20
// globale Quantitäten
int Richtung; // links oder rechts
int aufLinie; // 0=Linie verloren, 1=Linie gefunden
void Initialisierung()
{
SetSensorType(LichtSensor,SENSOR_TYPE_LIGHT);
SetSensorMode(LichtSensor,SENSOR_MODE_PERCENT);
SetPower(RechterMotor+LinkerMotor,OUT_LOW);
SetOutput(RechterMotor+LinkerMotor,OUT_FLOAT);
SetDirection(RechterMotor,OUT_FWD);
SetDirection(LinkerMotor,OUT_FWD);
Richtung=links;
}// end of Initialisierung
task sucheLinie() {
while (true)
{
if (!aufLinie)
{
if (Richtung==rechts)
{ while (!aufLinie) {
// stop Antrieb; // ist nicht notwendig
SetDirection(RechterMotor,OUT_FWD);
SetDirection(LinkerMotor,OUT_REV);
SetOutput(RechterMotor+LinkerMotor,OUT_ON);
}
Float(RechterMotor+LinkerMotor); // Strom weg, aber nicht bremsen
Richtung=links; // Kreisbogenrichtung wechseln
// start Antrieb; // ist nicht notwendig
}
else // Richtung=links
{ while (!aufLinie) {
// stop Antrieb; // ist nicht notwendig
SetDirection(LinkerMotor,OUT_FWD);
SetDirection(RechterMotor,OUT_REV);
SetOutput(RechterMotor+LinkerMotor,OUT_ON);
}
Float(RechterMotor+LinkerMotor); // Strom weg, aber nicht bremsen
Richtung=rechts; // Kreisbogenrichtung wechseln
// start Antrieb; // ist nicht notwendig
} //else
}
}
}// sucheLinie
task Antrieb() {
while (true) {
if (Richtung==rechts)
{SetOutput(RechterMotor,OUT_FLOAT);
SetOutput(LinkerMotor,OUT_ON);}
else
{SetOutput(LinkerMotor,OUT_FLOAT);
SetOutput(RechterMotor,OUT_ON);}
}//end of while
}// end of task Antrieb
task Sensor() {
while (true) {
if (LichtSensor > LichtGrenzwert)
{aufLinie=0;}
else
{aufLinie=1;}
}//end of while
} // end of task Sensor
task main () {
Initialisierung();
start Sensor;
start Antrieb;
start sucheLinie;
}
Fortsetzung folgt ...
|
|