GEHNIO
Gesamtschule Duisburg-Hamborn/Neumühl
Informatik in der Oberstufe

> 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 ...

 

 

 

 

 

 

 

 

 
  © 2002 Gesamtschule Duisburg-Hamborn/Neumühl.  
Hosted by www.Geocities.ws

1