Ampelkreuzung II

Aus Informatik
Version vom 27. Juli 2011, 13:20 Uhr von Ingo Höpping (Diskussion | Beiträge) (Download)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Wechseln zu: Navigation, Suche

Screenshot Ampelkreuzung.jpg

Aufgabenstellung

Aufgabe war es ein Objekt Ampel zu erstellen. Mithilfe dieses Objektes sollte dann eine Kreuzung modelliert werden. Als Modell für meine Kreuzung dient die Kreuzung vor der Winfriedschule.

Umsetzung

Da so ein Projekt interessanter wird wenn es auch wirklich Verkehr gibt, der gergelt werden muss, habe ich neben dem Objekt TAmpel auch ein Objekt TAuto erstellt. Des Weiteren gibt es ein Objekt TTrafficMap, in welchem alle Informationen über den Verkehr gespeichert sind. Das ganze wird vom Hauptprogramm aus verwaltet.

Objekte

UML-Diagramm

AmpelkreuzungUML.jpg

Das Objekt TAuto

wichtige Attribute

  • X und Y sind die Positionskoordinaten des Autos auf dem Gitter
  • XPrev und YPrev sind die vorherigen Positionskoordinaten. Mit diesen Informationen wird das Auto dann bewegt
  • Das Array Way ist eine Abfolge von Richtungsbefehlen, die abgearbeitet wird um das Ziel zu erreichen
  • Step ist der Fortschritt beim abarbeiten der Richtunsbefehle
  • Blinker gibt an ob und in welche Richtung ein Auto blinkt. BlinkerCounter gibt an wie lange der Blinker noch an ist
  • From ist der StartOrt des Autos und Direction gibt sein Ziel an
  • Color ist die Farbe des Autos, die beim Erstellen zufällig gewählt wird
  • Map ist die Karte, die zur Bewegung der Autos benötigt wird

wichtige Methoden

  • In der Create-Methode wird das Auto auf der Karte plaziert und ihm wird durch GetWay ein Weg zugewiesen
  • In der Move-Prozedur überprüft ob das nächste Feld frei ist und schließlich wird das Auto bewegt oder nicht
  • GetAbsDir berechnet die Absolute Richtung des Autos aus dem Starpunkt und der aktuellen relativen Richtung
  • Die anderen Get*-Funktionen geben den Wert des jeweiligen Attributs aus
  • Die Funktionen CheckLeft und WaitForLeft regeln das Linksabbiegen ohne Ampel(Leipziger Straße --> Parkstraße)

Das Objekt TTrafficMap

wichtige Attribute

  • Das Zweidimensionale Array Cell beinhaltet die Informationen zu jedem Feld auf de Karte. So kann verhindert werden, dass ein Auto auf ein besetztes Feld oder über eine rote Ampel fährt

wichtige Methoden

  • GetCell liefert den Wert eines Feldes. So können Autos herausfinden ob sie auf das Feld fahren können
  • ChangeCell ändert den Wert eines Feldes auf den neuen Wert(z.B. wenn sich das Auto fortbewegt)

Das Objekt TAmpel

wichtige Attribute

  • XCoord und YCoord beeinhalten die Position der Ampel auf dem Gitter
  • Direction gibt die Ausrichtung der Ampel an (wichtig zum Zeichnen)
  • StartTime ist die Startzeit der Grünphase und Duration ist ihre Dauer
  • red gibt an ob die Ampel rot oder grün ist, orange gibt and ob die Ampel sich in der Orangephase befindet, wobei diese nur als "Unterphase" existiert (d.h. Autos behandeln die Orangephase vor der Grünphase noch als rot)
  • Map ist die Karte auf der die aktuellen Ampelphase eingetragen wird, sodass sie von den Autos gelesen werden kann

wichtige Methoden

  • Bei der Create-Methode werden Position, Ausrichtung, Startzeit und Dauer der Grünphase, sowie die Karte übergeben
  • SetGreen, SetRed, und SetOrange, ändern die aktuelle Ampelphase
  • SetTime ändert die Startzeit und Dauer der Grünphase auf die mitgegebenen Werte
  • Die Get*-Funktionen sind nötig um die entsprechenden Werte an das Hauptprogramm zu geben

Das Hauptprgramm

Das Hauptprogramm wird verwendet um die Objekte zu verwalten und die Simulation graphisch darzustellen.

  • So wird zum Programmstart die Init-Prozedur ausgeführt, in welcher die Hintergrund-Bitmaps geladen werden, die Variablen initialisiert werden und eine Karte vom Typ TTrafficMap und 15 Ampeln vom Typ TAmpel erstellt werden
  • Für den weiteren Prgrammverlauf wird ein Timer verwendet. Dieser regelt den kompletten Ablauf des Programms.
 procedure TForm1.Timer1Timer(Sender: TObject); 
   var
   i : integer;
   begin
   // Fortsetzen der AutoBewegung
   MoveCounter := MoveCounter + 1;
   // Nach 6 Wiederhohlungen werden die Autos auf dem Gitter bewegt und die Ampelsteuerung wird aufgerufen
   if MoveCounter = 6 then
   begin
     MoveCounter := 0;
     //Aufruf der Ampelsteuerung
     AutoControl;
     //Neue Autos werden in Abhängigkeit von der maximalen Autoanzahl erstellt
     for i := 0 to MaxCars div 50 do
       CreateCars;
     //Autos Bewegen
     MoveCars;
   end;
   //Straße Zeichnen
   DrawStreet;
   //Autos Zeichnen und optisch bewegen
   SmoothMove(MoveCounter);
 end;
  • Mithilfe der Prozedur AutoControl wird die Ampelschaltung automatisch geregelt
  • Nun werden mit CreateCras neue Autos erstellt. Die Anzahl der erstellten Autos ist abhängig von der MaxCars, der maximalen Autoanzahl
  • Mit DrawStreetwird das Hintergrundbild neu über das Image gezeichnet.
  • Mit der Prozedur SmoothMove werden die Autos nun in Abhängigkeit vom Fortschritt der Autobewegung (MoveCounter) optisch bewegt und gezeichnet. In dieser Prozedue wird auch der Blinker des Autos geregelt

Der Ampelzyklus

  • Eine grobe Übersicht

In der Init-Prozedur, die in der OnCreate-Methode der Form aufgerufen wird, werden die Ampeln erstellt. Dabei werden Position, Ausrichtung, Startzeit und Dauer der Grünphase und die Karte übergeben. Nun wird bei jedem sechstem Durchgang des Timers die Prozedur AutoControl aufgerufen:

 procedure TForm1.AutoControl;
 var
   i: integer;
 begin
   LightCounter := LightCounter +1;
   //Zähler wird ausgegeben
   ECounter.Text := IntToStr(LightCounter);
   for i := 1 to 15 do
     With Ampel[i] do
     begin
       //Orange vor  Grünphase
       if GetStartTime mod RepeatTime = (LightCounter + GetOrangetime ) mod RepeatTime then
         SetOrange;
       //Beginn Grünphase
       if GetStartTime = LightCounter  then
         SetGreen;
       //Orange vor Ende Grünphase
       if (GetStartTime + GetDuration) mod RepeatTime = (LightCounter + GetOrangeTime) mod RepeatTime then
         SetOrange;
       //Ende Grünphase
       if (GetStartTime + GetDuration) mod RepeatTime  = LightCounter then
         SetRed;
     end;
   //Zurücksetzen nach einem Durchgang
   if LightCounter >= RepeatTime then
     LightCounter := -1;
 end;

Der Zähler für die Ampelschaltung (LightCounter) wird erhöht. Dann wird für jede Ampel überprüft ob und wie sie geschalten werden muss. Der mod RepeatTime-Befehl sorgt dafür, dass die Grünphase auch trotz Zurücksetzen des Zählers korrekt ausgeführt wird. Falls der Zähler die Durchgangsdauer (RepeatTime) erreicht hat, wird er zurückgesetzt.

Der Autozyklus

  • Eine grobe Übersicht

Bei jedem sechstem Durchgang des Timers wird in Abhängigkeit von der Maximalen Autoanzahl(MaxCars) die Prozedur CreateCars 1-5 mal aufgerufen.

 //Autos Erstellen
 procedure TForm1.CreateCars;
 var
   i : integer;
 begin
   i := -1;
   repeat
     i := i + 1;
   until (Assigned(Auto[i]) = False) or (i > MaxCars);
   //Das i wird so lange erhöht, bis noch kein Auto mit diesm Index existiert,
   //oder die maximale Autoanzahl überschritten wurde
   if i <= MaxCars - 1 then
   begin
     //Auto mit zufälligem Start- und Zielort erstellen
     Auto[i] := TAuto.Create((Random(5) + 2) mod 4 + 1,Random(4) + 1,TM);
           // Der Wert 3(Leipziger Straße)hat eine größerer Wahrscheinlichkeit
   end;
 end;

Das Auto wird mit den Parametern Starpunkt, Zielort und der Karte erstellt. In Der Create-Methode des Autos wird über die Prozedur GetWay eine Abfolge von Richtungen in das dynamische Array Way geschrieben. Der Weg wird durch den Startpunkt und den Zielort bestimmt.

Dann wird in jedem sechstem Durchgang des Timers die Prozedur MoveCars aufgerufen, wo durch eine Zählschleife für jedes Auto die Prozedur TAuto.Move aufgerufen wird.

In dieser Prozedur wird die neue Koordinate für das Auto berechnet und anschließend wird auf der Karte überprüft ob das Feld mit diesen Koordinaten frei ist. Ist das Feld frei, so werden die neuen Koordinaten übernommen und der Zähler für das Array Way wir erhöht, sodass beim nächsten Bewegen der nächste Richtungsbefehl abgefragt wird, ansonsten passiert nichts.

Bei jedem Durchgang des Timers wird Die Prozedur SmoothMove aufgerufen, welche für die Bewegung der Autos zwischen den Feldern des Gitters verantwortlich ist. Die Differenz der aktuellen Koordinaten (X, Y) und der vorherigen Koordinaten (XPrev, YPrev) des Autos wird mit einem Faktor multipliziert, der sich aus dem Parameter MoveCounter berechnet, der bei jedem TimerDurchgang erhöht wird. Daraus lässt sich nun die Position zum Zeichnen berechnen. Über die Abfrage GetAbsDir, die die absolute Richtung des Autos ausgibt, wird entschieden in welche Richtung das Auto gezeichnet wird.

Wenn der Zähler des Arrays Way die Länge des Arrays erreicht hat, so ist der Weg vollständig abgearbeitet, und das Auto wird zerstört.

Tricks

  • In Wirklichkeit liegt dem Ganzen ein Gitter zugrunde, auf welchem die Autos von Feld zu Feld bewegt werden. Mit diesen Positionen wird dann berechnet, ob der Weg frei ist oder nicht. Die flüssige Bewegung ist nur optisch und erfolgt erst nachdem das Auto auf dem Gitter bewegt wurde. Für eine Fortbewegung um ein Gitterfeld werden 6 feine Bewegungen durchgeführt Dies hat den Vorteil, dass man die einzelnen Schritte wesentlich einfacher berechnen kann.

Screenshot Ampelkreuzung Gitter.jpg

  • Für die Autos wird ein dynamisches Array verwendet, dass also immer an die Anzahl der Autos angepasst werden kann
  • Die Autos werden mithilfe der Random()-Funktion zufällig an einem der 4 möglichen Startpnkte erzeut und bekommt zufällig eines der 4 möglichen Ziele zugewiesen.
  • Mihilfe eines Timers laüft das Programm in einer Endlosschleife bei der sich die Gschwindigkeit leicht ändern lässt
  • Die Straße und der Hintergrund sind auf eine Btimap gezeichnet, welche einmal zu Programmstart in eine Variable geladen wird. aus dieser Variablen wird dann bei jedem Timer-Durchgang mit der DrawStreets-Prozedur die Bitmap auf das Image gezeichnent.
  • Die Autos werden mit dem Befehl Canvas.Rectangle(X1,Y1,X2,Y2); gezeichnet. So läuft das Programm auch mit 200 Autos noch flüssig
  • Um zu simulieren, dass die Autos unter den Ampeln durchfahren, werden die Ampeln nach den Autos gezeichnet und überdecken so die Autos

Steuerung durch den Benutzer

Der Benutzer hat die Möglichkeit durch das ändern von Einstellungen die Simulation zu beeinflussen.

  • Über einen Schieberegler kann die Geschwindigkeit, mit der die Simulation abläuft verändert werden(Durch das Verschieben des Schiebereglers wird das Interval des Timers geändert)
  • Über den zweiten Schieberegler kann der Wert von MaxCars verändert werden. Dieser Wert legt fest, wie viele Autos sich maximal auf der Straße befinden dürfen. So kann also die Verkehrsdichte geregelt werden
  • Mit dem Anhalten/Fortsetzen Button kann die Simulation angehalten werden (der Timer wird deaktiviert/akiviert)
  • Mit dem Gitter Zeigen/Ausblenden Button kann das Gitter angezeigt werden, das für die eigentlichen Berechnungen benutzt wird
  • Mit dem Autos Neu Starten Button werden alle Autos von der Straße gelöscht(Falls es zu einem Verkehrschaos kommen sollte)
  • In der Tabelle kann die Startzeit und Dauer der Grünphasen der einzelnen Ampeln verändert werden. Durch einen Klick auf den Übernehmen Button werden diese Einstelllungen übernommen und der Ampelzähle wird auf 0 gesetzt.
  • Mit dem Zahlen Anzeigen/Ausblenden Button können die Nummerierungen der Ampeln auf der Karte angezeigt oder ausgeblendet werden


Download

Datei:Ampelkreuzung(Niklas grimm).zip (Komplettes Verzeichnis)

Datei:AmpelkreuzungExe(Niklas Grimm).zip (Nur Exe, Bitmaps müssen im Ordner sein)