-
Notifications
You must be signed in to change notification settings - Fork 0
02 Design Dokumentation
Im Folgenden wird das Design und der Aufbau der einzelnen Komponenten aus dem Komponenten-Diagramm beschrieben. (siehe Architektur Dokumentation)
tbd

Das Graphical User Interface (GUI) der DynamicRuleEngine ist mittels Windows Presentation Foundation (WPF) aufgebaut und verfolgt das MainViewViewModel (MVVM) Design Pattern. Durch dieses Binding können dynamische Elemente einfach zur Oberfläche hinzgefügt oder entfernt werden.
Die GUI Komponente besteht aus folgenden Kernbereichen:
- View: Grafische Oberflächen
- Model: Datenhaltung der Oberfläche bzw. des Programms
- ViewModel: Verindung zwischen View und Model
- Technics: Technische Klassen für die View bzw. die Models
Beim Start der Oberfläche werden die Crossway Konstellationen und alle dynamischen Regeln geladen und in die lokale Datenhaltung kopiert. Die Oberfläche aktualisiert sich nach dem Laden der Elemente selbst und alle Kreuzungen werden mit ihren Grünphasen dargestellt. Für jede Kreuzung wird anschließend ein Timer gestartet und bei Ablauf des Timers werden die Regeln aktualisiert und ans Backend gesendet. Die Änderung einer Grünphase ist jederzeit durch den Benutzer möglich, ist jedoch zwischen 4 und 59 sec limitiert. Die Limitierung der Werte ist durch eine ValidationRule gesichert. Das bedeutet, die Zeit wird nur aktualisiert, wenn die Eingabe im erlaubten Bereich ist.

- TrafficSimulation: Hauptklasse mit Main-Methode. Ist dafür verantwortlich alle anderen Komponenten zu initialisieren und zu starten.
- AgentSpawner: Generiert neue Agenten mit randomisierten Eigenschaften (MaxVelocity, MaxAcceleration, etc.) und platziert diese auf der Karte.
- AgentSim: Simuliert das Verhalten der Agenten: vorausschauendes Fahren, Einhaltung der Verkehrsregeln, etc.
- PhysicsEngine: Bewegt die Agenten über die Map, je nach festgelegtem Verhalten durch die AgentSim.
- Allgemeines: Wie man im Diagram sieht, haben verwenden die Klassen alle das property dataManager. Über dieses wird mit der zentralen DataBridge kommuniziert, welche die Daten zwischen den Komponenten überträgt (siehe Architektur).
Mitte des Semesters wurde der Change Request eingekippt, dass Fahrzeuge welche defekt sind, überholt werden können sollen.

Unser Datenmodell sah von Anfang an vor, dass man für eine Edge (auf denen sich Fahrzeuge bewegen) Nachbar-Edges definieren kann. Außerdem existert ein Typ DynamicEdge der es erlaubt, im nachhinein ins bestehende Modell neue Edges einzufügen. Merkt ein Fahrzeug also, dass vor ihm ein defektes Fahrzeug steht, so kann dieses zur Laufzeit eine DynamicEdge zur Nachbar-Edge einfügen, das defekte Fahrzeug auf der Gegenfahrbahn überholen und danach wieder über eine weitere DynamicEdge auf die eigentliche Fahrbahn zurückkehren.
- Watchdog: Zuständig für das synchrone Starten und anschließenden asynchronen Überwachung der Applikationen in einem eigenen Thread
- DataManager: Zuständig für das holen der Daten aus dem DataAccess, der Synchronisation und der Anreicherung um Simulationsspezifische Daten. Des Weiteren bietet dieser DataManager "Fire & Forget" Methoden zum Aktualisieren der AgentPositions im DataAccess an (PhysicEngine muss nicht auf Fertigstellung der Synchronisation warten)
- PhysicEngine: Aktualisiert Geschwindigkeit der Agents aufgrund deren Beschleunigung, aktualisiert Position der Agents aufgrund deren Geschwindigkeit und gewählten Route
- AgentSim: Entscheidet über Beschleunigung und gewählter Route aufgrund von Regeln und anderen Verkehrsteilnehmern
- AgentSpawner: Erstellt neue Agents mit zufälligen Eigenschaften aus den AgentSimConfigurations aus dem Data Access
PhysicEngine, AgentSim und AgentSpawner laufen in eigenen Threads und kommunizieren unabhängig voneinander mit dem DataManager. DataManager wäre ein Singleton evtl. sinnvoll, damit alle auf die gleichen Daten zugreifen können (Achte auf Thread Locking!)
- Main wird aufgerufen
- Data Access Dependencies werden durch Factory Aufruf instanziert
- Watchdog wird synchron gestartet, startet Subapplikationen
- Watchdog wird in asynchrones Watching überführt
- DataManager wird initialisiert, alle simulationsrelevanten Daten werden vom Data Access selektiert
- DataManager baut im Speicher den Objektbaum der ganzen Knoten und Kanten des Kartengraphes
- DataManager startet Synchronisationsthread für die DynamicRules (restliche Daten werden nur von der Simulation manipuliert, d.h. diese müssen nicht ständig gelesen werden)
- PhysicEngine Main Thread wird gestartet
- AgentSim Main Thread wird gestartet
- AgentSpawner Main Thread wird gestartet
- Über Agents iterieren oder eigener Thread je Agent
- Geschwindigkeit aufgrund der Beschleunigung ändern
- Zu fahrende Laufmeter berechnen aus der aktuellen Geschwindigkeit
- Laufmeter auf der vom Agent gewählten Route fahren
- Wenn Agent einen Endknoten erreicht -> Agent aus dem Speicher löschen
Anmerkung: Noch sehr grob definiert da dies vermutlich am meisten Denkarbeit benötigt, während der Implementierung genauer spezifizieren.
- Über Agents iterieren oder eigener Thread je Agent
- Route prüfen und evtl. anpassen
- Unmittelbare Verkehrsteilnehmer prüfen für Sicherheitsabstand
- Regeln der aktuellen Kante und der Knoten und Kanten innerhalb des Bremsweges prüfen
- Beschleunigung anpassen sodass alle Regeln und Sicherheitsabstände eingehalten werden können für die aktuelle Route
- Mögliche Startpunkte selektieren
- Über AgentSimConfigurations iterieren und auswürfeln ob diese Configuration als Agent instanziert werden soll
- Startpunkt auswürfeln (wenn besetzt -> Spawn abbrechen)
- max. Geschwindigkeit, max. Beschleunigung und max. Verzögerung auswürfeln
- Agent instanzieren und auf dem Startpunkt spawnen
Das Graphical User Interface (GUI) ist mittels Windows Presentation Foundation (WPF) aufgebaut und verfolgt das MainViewViewModel (MVVM) Design Pattern. Durch dieses Design ist es möglich die Oberfläche zu ändern, ohne das Backend anpassen zu müssen. Dadurch kann schnell auf Designänderungen eingegangen werden.
Die GUI Komponente besteht aus folgenden Kernbereichen:
- View: Grafische Oberflächen
- Model: Datenhaltung der Oberfläche bzw. des Programms
- ViewModel: Verindung zwischen View und Model
- Technics: Technische Klassen für die View bzw. die Models
Beim Starten der GUI werden die Interfaces der DataAccess geladen und die Hintergrundkarte angefordert. Danach werden zwei Dispatcher Timer erstellt, die für die Aktualisierung der Oberfläche zuständig sind. Zwei Timer werden deshalb verwendet, da die Rules eine kleinere Aktualisierungsfrequenz benötigen und somit Leistung gespart werden kann.
- Im Event des ersten DispatcherTimers werden die Positions (Ecken), Edges (Linien) und Agents (Fahrzeuge) aus dem DataAccess geladen. Anschließend werden sie auf der Karte angezeigt, indem sie in eigene Objekte geladen werden, die dynamisch auf die Oberfläche gebunden sind.
- Im Event des zweiten DispatcherTimers werden die Rules (Verkehrszeichen) aus dem DataAccess geladen. Anschließend werden sie ebenfalls mittels Binding auf der Karte angezeigt.
Die Knoten und Kanten werden auf der Oberfläche nicht angezeigt, können aber mit F2 eingeblendet werden (was sich aber negativ auf die maximale Performance auswirkt). Diese Funktion sollte nur für Debugzwecke verwendet werden.
Die neue Anforderung ein Auto "kaputt" gehen zu lassen und es somit auf der Karte stehen zu bleiben wurde in der GUI so implementiert, dass jeder Agent mit einem Event ausgestattet ist (ohne das MVVM Pattern zu brechen) dass über eine Message Queue die Simulation triggert, die anschließend den Typ des Agents ändert.