Winkerrätsel - Entschlüsselung der Signalcodes: Unterschied zwischen den Versionen
(47 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt) | |||
Zeile 89: | Zeile 89: | ||
| 1.12 ||Im Profi-Spielmodus sollen nicht nur Buchstaben, sondern auch kurze Wörter oder Zahlen eingegeben werden. || Benedikt Lipinski || 10.10.2024 || Weiran Wang || 10.10.2024 || | | 1.12 ||Im Profi-Spielmodus sollen nicht nur Buchstaben, sondern auch kurze Wörter oder Zahlen eingegeben werden. || Benedikt Lipinski || 10.10.2024 || Weiran Wang || 10.10.2024 || | ||
|- | |- | ||
| 1.13 ||Im | | 1.13 ||Im Expert-Spielmodus soll die bisherige Eingabe auf dem Bildschirm angezeigt werden. || Benedikt Lipinski || 10.10.2024 || Weiran Wang || 10.10.2024 || | ||
|- | |- | ||
| 1.14 ||Im Spielmodus | | 1.14 ||Im Spielmodus Expert muss das Löschen der letzten Ziffer durch ein Flaggensignal möglich sein. || Benedikt Lipinski || 10.10.2024 || Weiran Wang || 10.10.2024 || | ||
|- | |- | ||
| 1.15 ||Das System soll nach Möglichkeit in Matlab realisiert werden; sollten gute Gründe gegen die Verwendung von Matlab sprechen, wird alternativ die Sprache Python verwendet. || Benedikt Lipinski || 10.10.2024 || Weiran Wang || 10.10.2024 || | | 1.15 ||Das System soll nach Möglichkeit in Matlab realisiert werden; sollten gute Gründe gegen die Verwendung von Matlab sprechen, wird alternativ die Sprache Python verwendet. || Benedikt Lipinski || 10.10.2024 || Weiran Wang || 10.10.2024 || | ||
Zeile 247: | Zeile 247: | ||
===Hauptteil=== | ===Hauptteil=== | ||
<gallery widths="500px" heights="500px" captionalign="center"> | <gallery widths="500px" heights="500px" captionalign="center"> | ||
Datei: | Datei:Monate Hauptteil.jpg|Abildung ??: Hauptteil | ||
Datei:Gehäuseteil 1.jpg|Abildung ??: Gehäuseteil 1 | Datei:Gehäuseteil 1.jpg|Abildung ??: Gehäuseteil 1 | ||
Datei:Gehäuseteil 2.jpg|Abildung ??: Gehäuseteil 2 | Datei:Gehäuseteil 2.jpg|Abildung ??: Gehäuseteil 2 | ||
Datei:Gehäuseteil 3.jpg|Abildung ??: Gehäuseteil 3 | Datei:Gehäuseteil 3.jpg|Abildung ??: Gehäuseteil 3 | ||
Datei:Platine Masss.jpg|Abildung ??: Platine Masss | Datei:Platine Masss.jpg|Abildung ??: Platine Masss | ||
Datei:Montage Effekt.jpg|Abildung ??: Montage Effekt | |||
</gallery> | </gallery> | ||
Zeile 273: | Zeile 274: | ||
==Paralellitaet von Aufgaben == | ==Paralellitaet von Aufgaben == | ||
{| class="mw-datatable" | |||
|+ style="text-align: left" | | |||
|- | |||
|[[Datei:Winkerraetsel Paralellitaet .png|mini|500px|Abbildung??: Winkerraetsel paralleler Ablauf ]] | |||
| | |||
|} | |||
Parallelität von Aufgaben ermöglicht die gleichzeitige Bearbeitung mehrerer Prozesse, was durch die Verwendung von Threads effizient umgesetzt werden kann, da diese die gleichzeitige Ausführung mehrerer Aufgaben innerhalb eines Programms erlauben. | Parallelität von Aufgaben ermöglicht die gleichzeitige Bearbeitung mehrerer Prozesse, was durch die Verwendung von Threads effizient umgesetzt werden kann, da diese die gleichzeitige Ausführung mehrerer Aufgaben innerhalb eines Programms erlauben. | ||
Jeder Thread arbeitet unabhängig, teilt sich aber denselben Speicherbereich, was eine schnelle Kommunikation ermöglicht, aber auch zu Synchronisationsproblemen führen kann. | Jeder Thread arbeitet unabhängig, teilt sich aber denselben Speicherbereich, was eine schnelle Kommunikation ermöglicht, aber auch zu Synchronisationsproblemen führen kann. | ||
In [[Python]] ermöglicht das Threading-Modul das Erstellen und Verwalten von Threads, um parallele Aufgaben effizient auszuführen. Es bietet einfache Mechanismen, um Threads zu starten, zu synchronisieren und Ressourcen zwischen ihnen zu teilen. | In [[Python]] ermöglicht das Threading-Modul das Erstellen und Verwalten von Threads, um parallele Aufgaben effizient auszuführen. Es bietet einfache Mechanismen, um Threads zu starten, zu synchronisieren und Ressourcen zwischen ihnen zu teilen. | ||
Die parallele Ausführung der Tasks | Die parallele Ausführung der Tasks <code>camera_video_worker</code> und <code>user_input_worker</code> ist für das Winkerätsel entscheidend, da beide Prozesse gleichzeitig neben dem Hauptprogramm aktiv sein müssen. Der <code>camera_video_worker</code> verarbeitet kontinuierlich die Kameradaten, analysiert die Bewegungen und erkennt das Winken als Teil des Spiels. Der <code>user_input_worker</code> hingegen ist primär für die Erfassung der Benutzereingaben zuständig, insbesondere um einen Spielabbruch durch den Benutzer zu ermöglichen. Durch diese parallele Struktur können Kameraverarbeitung und sofortige Abbruchmöglichkeit gleichzeitig und ohne gegenseitige Beeinflussung ablaufen. Dies gewährleistet einen reibungslosen Spielablauf und gibt dem Benutzer die volle Kontrolle ohne Verzögerungen oder Unterbrechungen des Spielverlaufs. Um die eingangs beschriebenen Synchronisationsprobleme bei der Kommunikation zwischen den einzelnen Subthreads in den Griff zu bekommen, wird auf die Verwendung von Queues gesetzt die, die gesendeten Nachrichten ähnlich wie in einem Shiftregister in einer Schlange zur Verfügung stellen<ref name="queue-geeksforgeeks">{{Zitierweb | ||
| Titel = Queue in Python | | Titel = Queue in Python | ||
| Autor = GeeksforGeeks | | Autor = GeeksforGeeks | ||
Zeile 286: | Zeile 293: | ||
| Zugriff = 15. Januar 2025 | | Zugriff = 15. Januar 2025 | ||
}}</ref>. | }}</ref>. | ||
==Grafische Ausgabe== | ==Grafische Ausgabe== | ||
===LCD Modul=== | ===LCD Modul=== | ||
{| class="mw-datatable" | |||
Datei:Timing-Diagramm.jpg|Abbildung??: LCD128X64 - Timing Diagramm | ! style="font-weight: bold;" | | ||
! style="font-weight: bold;" | | |||
|+ style = "text-align: left"| | |||
|- | |||
|[[Datei:Timing-Diagramm.jpg|mini|625px|Abbildung??: LCD128X64 - Timing Diagramm]] | |||
| | |||
|} | |||
Das LCD-Programmmodul erfüllt die Anforderungen dieses Projekts in Bezug auf die Anzeige von Text und Symbolen. Mit der Funktion '''Eine_Zeile_Zeichenkette(Zeile, Spalte, Text_Eingeben)''' kann Text an einer beliebigen Zeile und Spalte des Bildschirms angezeigt werden, während die Funktion '''Eine_Seite_Zeichenkette(Zeile, Spalte, Text_Eingeben)''' dazu dient, eine komplette Seite mit Text darzustellen. Für längere Zeichenketten kann die Funktion '''Mehr_Seite_Zeichenkette(Zeile, Spalte, Text_Eingeben)''' verwendet werden, die den Text automatisch in mehrere Seiten aufteilt und alle 4 Sekunden umblättert. | Das LCD-Programmmodul erfüllt die Anforderungen dieses Projekts in Bezug auf die Anzeige von Text und Symbolen. Mit der Funktion '''Eine_Zeile_Zeichenkette(Zeile, Spalte, Text_Eingeben)''' kann Text an einer beliebigen Zeile und Spalte des Bildschirms angezeigt werden, während die Funktion '''Eine_Seite_Zeichenkette(Zeile, Spalte, Text_Eingeben)''' dazu dient, eine komplette Seite mit Text darzustellen. Für längere Zeichenketten kann die Funktion '''Mehr_Seite_Zeichenkette(Zeile, Spalte, Text_Eingeben)''' verwendet werden, die den Text automatisch in mehrere Seiten aufteilt und alle 4 Sekunden umblättert. | ||
Zeile 401: | Zeile 413: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
</div> | </div> | ||
==Bildaufnahme und Verarbeitung== | ==Bildaufnahme und Verarbeitung== | ||
=== BodyPoseEstimation Modul=== | === BodyPoseEstimation Modul=== | ||
Zeile 432: | Zeile 445: | ||
Kamera_Regelung(image, nose) | Kamera_Regelung(image, nose) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
===Kamera Regler Modul=== | ===Kamera Regler Modul=== | ||
Zeile 457: | Zeile 468: | ||
|+ style = "text-align: left"| | |+ style = "text-align: left"| | ||
|- | |- | ||
|[[Datei:Regelkreis Servomotor.jpg|mini|625px| | |[[Datei:Regelkreis Servomotor.jpg|mini|625px|Abbildung. ??: Regelkreis Servomotor]] | ||
| | | | ||
|} | |} | ||
Zeile 479: | Zeile 490: | ||
|+ style = "text-align: left"| | |+ style = "text-align: left"| | ||
|- | |- | ||
|[[Datei:FOV.png|mini|625px| | |[[Datei:FOV.png|mini|625px|Abbildung. ??: Bildwinkel]] | ||
| | | | ||
|} | |} | ||
Zeile 530: | Zeile 541: | ||
|+ style = "text-align: left"| | |+ style = "text-align: left"| | ||
|- | |- | ||
|[[Datei:Regelstrecke Analyse.jpg|mini|625px| | |[[Datei:Regelstrecke Analyse.jpg|mini|625px|Abbildung. ??:Regelstrecke Analyse]] | ||
| | | | ||
|} | |} | ||
Zeile 726: | Zeile 737: | ||
|+ style = "text-align: left"| | |+ style = "text-align: left"| | ||
|- | |- | ||
|[[Datei:Regelkreis Simulinkmodell.jpg|mini|1000px| | |[[Datei:Regelkreis Simulinkmodell.jpg|mini|1000px|Abbildung. ??: Regelkreis Simulinkmodell]] | ||
| | | | ||
|} | |} | ||
Zeile 745: | Zeile 756: | ||
|+ style = "text-align: left"| | |+ style = "text-align: left"| | ||
|- | |- | ||
|[[Datei:Analyse Effekt Regler.jpg|mini|1000px| | |[[Datei:Analyse Effekt Regler.jpg|mini|1000px|Abbildung ??: Effekt der Regel]] | ||
| | | | ||
|} | |} | ||
Zeile 766: | Zeile 777: | ||
==Spielablauf== | ==Spielablauf== | ||
''' Start Game'''<br> | |||
Die Funktion <code>startGame(Level)</code> initialisiert und startet einen separaten Thread für die Körpererkennung <code>cv_worker_thread</code>, um eine unabhängige Verarbeitung sicherzustellen, während das Spiel läuft. Sie setzt zudem den Schwierigkeitsgrad basierend auf dem übergebenen Parameter Level mithilfe der Funktion <code>setSkillLevel(SkillLevel.NONE)</code> und gibt diesen zur Kontrolle aus. Als Output ruft die Funktion schließlich die <code>play_game()</code>-Funktion auf, wodurch das eigentliche Spiel gestartet wird. | |||
<br> | |||
'''Play Game'''<br> | |||
Die Funktion <code>play_game()</code> steuert den Hauptspielablauf des Winkerraetsels, bei dem Körperposen analysiert werden, um Gesten zu erkennen. Sie initialisiert das Spiel, verarbeitet den Nutzer- und Kamerainput in vorm von Landmarken, und entscheidet abhängig vom Spielmodus <code>BEGINNER, PROFI, EXPERT</code> über Fortschritt und Spielende. Der Input umfasst Sensordaten (Körperwinkel), Benutzereingaben und Spielvorgaben wie Schwierigkeitsgrade und Lösungswörter. Die Ausgabe erfolgt über die bereits beschriebene LCD-Ausgabe. | |||
Die Besonderheiten der Funktion liegen in der dynamischen Anpassung an Schwierigkeitsstufen. Bei den Modi <code>BEGINNER</code> und <code>PROFI</code> wird das gesamte Lösungswort( einzelner Buchstabe) mit erkannten Buchstaben verglichen, während im <code>EXPERT</code>-Modus Buchstaben sequentiell auf das vorhanden sein in einem Wort geprüft werden. Die Funktion integriert eine Echtzeit-Verarbeitung von Körperwinkeln, die mit [[OpenCV mit Python|OpenCV]] berechnet und anschließend interpretiert werden. | |||
Das Spiel endet, wenn das Rätsel erfolgreich gelöst oder manuell abgebrochen wird. Die Funktion ruft hierzu die <code>close_game</code>-Funktion auf, um das Spiel erfolgreich zu beenden. Andernfalls wird die <code>play_game</code>-Funktion zyklisch mittels einer Schleife und einer generellen Wartezeit von 0,1 Sekunden ausgeführt, um die CPU zu schützen. Im zeitlichen Worst-Case ist durch das Gewinnen des Spiels mit Zykluszeiten von über 30 Sekunden zu rechnen.<br> | |||
'''Stop Game'''<br> | |||
Die vorliegende Funktion überwacht eine Bedingung<code> stop_game</code>, die bei Aktivierung den laufenden Spielprozess kontrolliert beendet. Hierbei wird insbesondere der parallel ausgeführte Thread <code>cv_worker_thread</code> entweder geordnet synchronisiert oder, falls erforderlich, mittels eines erzwungenen Stopps terminiert. Diese Vorgehensweise gewährleistet eine effiziente Ressourcennutzung und trägt zur Stabilität des Gesamtsystems bei. | |||
==Berechnung der Flaggensignale== | |||
=== Videosignal zu Winkel=== | |||
== | |||
Da die Position der Arme beim Flaggenwinken in feste Bereiche mit einer festen Ausrichtung eingeteilt werden kann, ist die Idee, die Position der Arme mit grafischen oder geometrischen Verfahren zu bestimmen. | Da die Position der Arme beim Flaggenwinken in feste Bereiche mit einer festen Ausrichtung eingeteilt werden kann, ist die Idee, die Position der Arme mit grafischen oder geometrischen Verfahren zu bestimmen. | ||
Der Ansatz zur Umsetzung, beruht auf der Ausrichtung des Arms zur Körpermitte mit grafischen beziehungsweise geometrischen Methoden zu bestimmen. Hierzu wird der Körper des Spielers in einen rechten und einen linken Winkel unterteilt. Beide Winkel beginnen jeweils unten, also bei 6 Uhr, steigen über die Körperaußenseite nach 12 Uhr, bis sie in der Körpermitte wieder bei 6 Uhr angelangen. | |||
Zur Winkelberechnung wird der Vektor genutzt, der zwischen der Schulter- und der Ellbogen-Landmarke entsteht, sowie der Vektor, der als Körpermittelpunkt in der Mitte zwischen den Schultern und der Hüfte entsteht. | |||
Für eine erfolgreiche Winkelberechnung müssen demnach genau diese Punkte im Sichtfeld der Kamera sein. Die folgenden drei Abbildungen zeigen der Reihe nach, wie der Prozess der Winkelumrechnung anhand der mit Mediapipe erkannten Schlüsselkoordinaten des Körpers berechnet wird. | |||
*'''Variablenerklärung:''' | |||
{| class="mw-datatable" | |||
! style="font-weight: bold;" | | |||
! style="font-weight: bold;" | | |||
|+ style="text-align: left" | | |||
|- | |||
|[[Datei:Pixel zu Kartesisches Koordinatensystem.jpg|mini|1000px|Abbildung ??: Pixel zu Kartesisches Koordinatensystem]]<br> | |||
|- | |||
|[[Datei:Kartesisches zu Polarkoordinatensystem.jpg|mini|1000px|Abbildung ??: Kartesisches zu Polarkoordinatensystem]]<br> | |||
|- | |||
|[[Datei:Winkelumrechnung.jpg|mini|1000px|Abbildung ??: Winkelumrechnung]] | |||
|- | |||
|} | |||
=== Winkel zu Buchstabe=== | |||
Die Funktion <code>angleToLetter</code> interpretiert die Winkel zweier Arme (in Grad) und ordnet diese mithilfe einer Zuordnungstabelle einem Buchstaben des Semaphore-Flaggenalphabets zu. Sie berücksichtigt dabei eine Toleranz von ±20 Grad, um kleine Abweichungen in der Armhaltung auszugleichen, was die Robustheit der Zuordnung bei ungeübten Signalgebern erhöht.<br> | |||
Besonderheiten sind die Ruhestellung (0°/0°) und die Möglichkeit eines Korrektursignals(135°/45°) für den Expertenmodus | |||
---- | ---- | ||
Aktuelle Version vom 15. Januar 2025, 18:11 Uhr
Autor: Benedikt Lipinski und Weiran Wang
Einleitung
Unter Flaggenwinken versteht man in der Nautik nicht das wilde Gestikulieren mit einer Fahne, sondern vielmehr ein komplexes System rein optischer Kommunikation. Während sich an Land schon früh die Kommunikation mittels optischer Telegrafie durchsetzte[1], wurde auch in der Schifffahrt die Kommunikation mittels Flaggenzeichen, den so genannten Semaphoren, immer populärer. Heute wird aufgrund der leistungsfähigen Funktechnik in der Regel nicht mehr mit Flaggen kommuniziert. Dennoch soll die Kommunikation via flaggen auch im Zeitalter der Elektronischen kommunikation zum Einsatz kommen, z.B. von der US Navy bei der Betankung von Schiff zu Schiff.[2]
Der Spieler soll nun selbst die Rolle eines Kommunikationspartners übernehmen und seinem Gegenüber (dem Spiel) eine geheime und verschlüsselte Nachricht zukommen lassen.
Theoretische Grundlagen
Flaggen Semaphore
Eine Kommunikation über Flaggen ist, anders als man auf den ersten Blick vermuten könnte, gar nicht so weit von der Kommunikation entfernt, die uns Studierenden der 2020er Jahren in den Informatikmodulen gelehrt wird[3]. Denn die in dem "Video 1" zusehende und für Menschen lesbare Codierung einzelner Flaggenpositionen ist nichts anderes als die Codierung von Zeichen in eine Bitfolge, nur dass sich an dieser Stelle die Codierung der Nachricht und das Transportprotokoll unterscheiden[4]. Die Kommunikation mit den Flaggen beginnt mit der Aufforderung zum Verbindungsaufbau (Attention #Anker:AttentionMessage).
# | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
1 | A | 2 | B | 3 | C | 4 | D | ||||
5 | E | 6 | F | 7 | G | 8 | H | ||||
9 | I | 10 | J | 11 | K | 12 | L | ||||
13 | M | 14 | N | 15 | O | 16 | P | ||||
17 | Q | 18 | R | 19 | S | 20 | T | ||||
21 | U | 22 | V | 23 | W | 24 | X | ||||
25 | Y | 26 | Z |
Bestehende Arbeiten
Die Eingabe von Flaggensignalen in ein Computersystem ist nicht nur als Rätsel für ein Escape-Game interessant, sondern auch in anderen Projekten ein nicht zu vernachlässigender Faktor. Beispielsweise kann die Abbildung des Flaggenalphabets auf die Arme eines Benutzers dazu verwendet werden, Tastenanschläge auf der Tastatur zu simulieren. Ein Beispiel dafür ist das GitHub-Projekt des Entwicklers everythingishacked, der eine vollständige Tastatursimulation mit Hilfe von Handsemaphoren in Python umgesetzt hat[5]. Auch in der Mathematiksoftware Matlab gibt es bereits Beispiele für Vorstufen einer Armpositionserkennung[6] In beiden Fällen führt der Weg zur Buchstabenerkennung über den Schritt einer Schätzung der Körperhaltung. Konkret ist in diesem Fall die Ermittlung mittels Deep Learning Algorithmen gemeint.
Anforderungen
ID | Inhalt | Erstellt von: | Erstellt am: | Geprüft von: | Geprüft am: | |
---|---|---|---|---|---|---|
1 | System Anforderungen | |||||
1.1 | Das System muss eine Person durch bildbasierte Verfahren identifizieren. | Benedikt Lipinski | 10.10.2024 | Weiran Wang | 10.10.2024 | |
1.2 | Das System muss die Armhaltung erkennen. | Benedikt Lipinski | 10.10.2024 | Weiran Wang | 10.10.2024 | |
1.3 | Das System muss die Position der Arme in Winkel umwandeln. | Benedikt Lipinski | 10.10.2024 | Weiran Wang | 10.10.2024 | |
1.4 | Das System muss die Winkel in Buchstaben einteilen. | Benedikt Lipinski | 10.10.2024 | Weiran Wang | 10.10.2024 | |
1.5 | Das System muss eine Rückmeldung über den eingegebenen Buchstaben geben. | Benedikt Lipinski | 10.10.2024 | Weiran Wang | 10.10.2024 | |
1.6 | Das System muss eine Rückmeldung über die richtige Eingabe signalisieren, wenn der Buchstabe richtig angezeigt wird. | Benedikt Lipinski | 10.10.2024 | Weiran Wang | 10.10.2024 | |
1.7 | Das System muss bei korrekter Eingabe eine korrekte Stelle des Lösungswortes ausgeben. | Benedikt Lipinski | 10.10.2024 | Weiran Wang | 10.10.2024 | |
1.8 | Zur Erkennung der menschlichen Körperhaltung ist die Open-CV-Bibliothek zu verwenden. | Benedikt Lipinski | 10.10.2024 | Weiran Wang | 10.10.2024 | |
1.9 | Die verwendete Kamera muss eine Auflösung haben, bei der eine Person vollständig in das Bild passt. | Benedikt Lipinski | 10.10.2024 | Weiran Wang | 10.10.2024 | |
1.10 | Das Spiel soll per Knopfdruck oder über eine angeschlossene Tastatur gestartet werden. | Benedikt Lipinski | 10.10.2024 | Weiran Wang | 10.10.2024 | |
1.11 | Der Schwierigkeitsgrad muss über eine Taste oder eine angeschlossene Tastatur einstellbar sein. | Benedikt Lipinski | 10.10.2024 | Weiran Wang | 10.10.2024 | |
1.12 | Im Profi-Spielmodus sollen nicht nur Buchstaben, sondern auch kurze Wörter oder Zahlen eingegeben werden. | Benedikt Lipinski | 10.10.2024 | Weiran Wang | 10.10.2024 | |
1.13 | Im Expert-Spielmodus soll die bisherige Eingabe auf dem Bildschirm angezeigt werden. | Benedikt Lipinski | 10.10.2024 | Weiran Wang | 10.10.2024 | |
1.14 | Im Spielmodus Expert muss das Löschen der letzten Ziffer durch ein Flaggensignal möglich sein. | Benedikt Lipinski | 10.10.2024 | Weiran Wang | 10.10.2024 | |
1.15 | Das System soll nach Möglichkeit in Matlab realisiert werden; sollten gute Gründe gegen die Verwendung von Matlab sprechen, wird alternativ die Sprache Python verwendet. | Benedikt Lipinski | 10.10.2024 | Weiran Wang | 10.10.2024 | |
1.16 | Im Anfängermodus soll die spielende Person eine Hilfestellung erhalten | Benedikt Lipinski | 10.10.2024 | Weiran Wang | 10.10.2024 | |
2 | Oganisatorische Anforderungen | |||||
2.1 | Das Rätsel soll nach Erklärung innerhalb von 5 Minuten lösbar sein. | Benedikt Lipinski | 10.10.2024 | Weiran Wang | 10.10.2024 | |
2.2 | Das Puzzle soll verschiedene Schwierigkeitsgrade haben. | Benedikt Lipinski | 10.10.2024 | Weiran Wang | 10.10.2024 | |
2.3 | Das Material zum Verständnis des Puzzles sollte in nicht-elektrischer Hardware vorhanden sein. | Benedikt Lipinski | 10.10.2024 | Weiran Wang | 10.10.2024 | |
2.4 | Das System muss zur Aufbewahrung und zum Transport in einen Schuhkarton passen. | Benedikt Lipinski | 10.10.2024 | Weiran Wang | 10.10.2024 |
Funktionaler Systementwurf/Technischer Systementwurf
Funktionaler Systementwurf
Als Vorbereitung für das Winkerrätsel, zunächst durch die spielende Person, der Schwierigkeitsgrad gewählt werden. Das Spiel beginnt bei dem Winkerrätsel nicht mit dem drücken eines Startbuttons oder ähnlichem, sondern in Escape-Room Manier mit dem erkennen des Problems selbst. Hierzu bekommt die Spielende Person nach einstellen des Schwierigkeitsgrades, lediglich die 2 Flaggen und Literatur über Signale ausgehändigt. Somit ergibt sich als erste Aufgabe für die Spielenden, unter zu Hilfenahme der Flaggen zu erkenne, dass es sich bei der geforderten Aufgabe um das Winkeralphabet handelt. Mit der Erkenntnis aus der Literatur und der Tatsache, dass die spielende Person bereits unweigerlich Feedback zur erkannten Position bekommen wird, sollte durch die spielende Person kombiniert werden, nun mittels Körperposition
den erhaltenen Rätselcode einzugeben.
Die spielende Person wird aufgrund des grafischen Feedbacks schnell verstehen, dass bei korrekter Eingabe eines Buchstabens, dieser umcodiert wird.
Für den Spielmodus Profi, bei dem die spielende Person kleine Wörter aus der gängigen Sprache oder dem Internationalen Signal Kommunikation verwendet werden, bekommt die nutzende Person die bereits korrekt eingegebenen Buchstaben aufgelistet. Zudem wird der nutzenden Person aufgezeigt ob die eingegebene stelle korrekt oder falsch ist. Ziel ist es an dieser stelle, das Korrektur Signal zu benutzen.
Mit der erfolgreichen Entschlüsselung der letzten Stelle, hat die spielende Person das Rätsel beendet und sich innerhalb des gesamten Spiels Schritt für schritt das Lösungswort erspielt. An dieser stelle ist nun auch das Winkerrätsel beendet. Grundsätzlich stehen der spielenden Person 3 Spielmodi zur Verfügung. Leicht: hier soll eine visuelle Hilfestellung für die spielende Person gegeben werden, diese muss durch die spielende Person nur noch Nach gemacht werden.
Im fortgeschrittenen Modus muss die Spielende Person, sich nun selbst an die Einzunehmende Position erinnern oder im Buch nachschlagen. Eingegeben werden müssen in diesem Modus auch nur einzelne Buchstaben.
Der schwierigste Spielmodus, nur geeignet für Profis, fordert von der nutzenden Person die Eingabe kurzer Wörter, was gegebenen falls das Korrigieren der Eingabe nötig macht.
Der Ablauf des Winkerrätsels, wie er aus der Sicht des Anwenders dargestellt werden soll, kann dem Ablaufschema in Bild 2 entnommen werden.
Technischer Systementwurf
Da der im Arduino Uno R3 verwendete Atmega328-Mikrocontroller hinsichtlich Datenverarbeitung, RAM und Flash-Speicher begrenzt ist und somit für Bildverarbeitungsaufgaben ungeeignet, wird der Raspberry Pi 5B als Ersatz eingesetzt, um die Kernaufgaben der maschinellen Bildverarbeitung zu übernehmen. Das System wird über ein 5V 5A Netzteil mit Strom versorgt, um den stabilen Betrieb aller Geräte zu gewährleisten.
In diesem Flaggen-Signal-Interaktionssystem fungiert eine Kamera als Sensor, die über das USB-Protokoll Bilddaten an den Raspberry Pi 5B überträgt. Der Raspberry Pi 5B verwendet vordefinierte Algorithmen, um die von den Spielern eingegebenen Flaggen-Signale zu erkennen, und gibt Rückmeldungen über ein 128x64 Pixel Display aus. Das Display ist über das SPI-Protokoll mit dem Raspberry Pi 5B verbunden, um eine effiziente Datenübertragung sicherzustellen.
Darüber hinaus ist das System mit einem Moduswahlknopf ausgestattet, der an die GPIO-Pins des Raspberry Pi 5B angeschlossen ist. Durch Überwachung der Spannungsänderungen an den Pins kann das System die Benutzereingaben erkennen und verarbeiten.
Das gesamte System wird auf einer speziell angefertigten Leiterplatte integriert, um eine saubere und zuverlässige Verbindung der Leitungen sicherzustellen und das Gerät erfolgreich in ein Gehäuse von der Größe einer Schuhschachtel einzubauen.
Eine Gesamtübersicht über die beschriebenen Komponenten und ihre Verknüpfung ist in "Bild 3" dargestellt.
Komponentenspezifikation und Stückliste
ID | Anzahl | Kosten pro Stück € | Summe | Bezeichnung / Komponente | technische Bezeichnung | Abbildung |
---|---|---|---|---|---|---|
1 | 1x | 104,50€ | 104,50€ | RASP PI 5B 4GB mit Ladegerät und Gehäuse | RPI5 BBDL 4GB Das Raspberry PI 5 B 4GB Black Bundle | [7] |
2 | 1x | 0,2€ | 0,2€ | Kurzhubtaster | JTP-1130 Kurzhubtaster 6x6 mm, Höhe: 13 mm, 12 V, vert | [8] |
3 | 1x | 9,9€ | 9,9€ | LCD128X64 | DEBO LCD128X64 Entwicklerboards - Display Grafik-LCD, 128x64 Pixel | [9] |
4 | 1x | 14,95€ | 14,95€ | Webcam | AMDIS03B Webcam, 720p, HDready | [10] |
5 | 2x | 0 € | 0 € | Signalflaggen | Kleine Fahne 20 x 14 cm | [11] |
6 | 1x | 0€ | 0€ | Map mit Flaggensignalen | Flaggensprache oder Winkeralphabet |
[12] |
Umsetzung HW
Schaltungsentwurf
-
Abildung ??: Verkabelungsplan
-
Abildung ??: Schaltplan
-
Abildung ??: Platine Vorderseite
-
Abildung ??: Platine Rueckseite
-
Abildung ??: Vorderseite Lochrasterplatine nach Löten
-
Abildung ??: Rückseite Lochrasterplatine nach Löten
- Die Abbildung?? zeigt das mit Fritzing erstellte Gesamtlayout der Verbindungen und erleichtert
die schnelle Umsetzung des Projektprototyps - Abbildung ?? zeigt das entsprechende Schaltplan-Diagramm, das mit Multisim erstellt wurde.
- Abbildungen ?? und ?? stellen das Leiterplattendesign basierend auf dem Schaltplan dar.
Die Leiterplatte hat die Abmessungen 90x150 mm, wodurch sie nicht nur alle Hardware-
Komponenten aufnehmen kann, sondern auch die Anforderung erfüllt, dass das Gerät in eine
Schuhschachtel passen muss. - Die Abbildung?? zeigt die bearbeitete Leiterplatte. Aufgrund eingeschränkter Bedingungen konnte keine
gedruckte Leiterplatte (PCB) hergestellt werden, sodass die Schaltung auf einer Lochrasterplatine
aufgebaut wurde. Um die Lötarbeit zu erleichtern, wurde das ursprüngliche Leiterbahn-Design angepasst,
sodass es besser auf der Lochrasterplatine realisiert werden kann.
Beschreibung der Verbindung
LCD128x64 mit Raspberry Pi 5
- Der digitale Pin GPIO25 des Raspberry Pi 5 wird als Chip-Select-Pin verwendet und mit dem Chip-Select-Pin RS des LCD-Bildschirms verbunden.
- Der SPI-Daten-Pin GPIO10 (MOSI) des Raspberry Pi wird mit dem RW (MOSI)-Pin des LCD-Bildschirms verbunden.
- Der SPI-Takt-Pin GPIO11 (SCK) des Raspberry Pi wird mit dem E (SCK)-Pin des LCD-Bildschirms verbunden.
- Der PSB-Pin des LCD-Bildschirms wird mit GND verbunden, um den Pegel auf Low zu setzen und damit die SPI-Kommunikation zu aktivieren.
- Das LCD-Modul wird über die Pins GND (-) und VCC (+) mit 5V-Stromquelle versorgt.
- Die Hintergrundbeleuchtung wird über die Pins BLK (-) und BLA (+) mit 5V-Stromquelle versorgt.
AMDIS03B Webcam mit Raspberry Pi 5
- Verbinden Sie den USB-Anschluss der AMDIS03B Webcam direkt mit einem beliebigen USB 3.0-Port des Raspberry Pi 5.
Taste mit Raspberry Pi 5
- Die erste Taste wird mit einer Seite an den GPIO26 des Raspberry Pi und mit der anderen Seite an GND angeschlossen.
- Die zweite Taste wird mit einer Seite an den GPIO16 des Raspberry Pi und mit der anderen Seite an GND angeschlossen.
Taste mit Raspberry Pi 5
- Der positive Pol der LED wird mit dem GPIO6 des Raspberry Pi verbunden.
- Ein 150Ω-Überstromschutzwiderstand wird zwischen den negativen Pol der LED und GND geschaltet.
Servo MG996R mit Raspberry Pi 5
- MG996R wird mit dem GPIO19 des Raspberry Pi verbunden, da dieser Pin ein präzises Hardware-PWM-Signal erzeugen kann.
- MG996R-Servos wird mit ihren GND (-) und VCC (+) an 5V-Stromquelle angeschlossen.
Strukturentwurf
Hauptteil
-
Abildung ??: Hauptteil
-
Abildung ??: Gehäuseteil 1
-
Abildung ??: Gehäuseteil 2
-
Abildung ??: Gehäuseteil 3
-
Abildung ??: Platine Masss
-
Abildung ??: Montage Effekt
Abbildung ?? zeigt die Gesamtstruktur des Geräts, die aus einer Bodenplatte, einer Leiterplatine, einem Gehäuse und zwei Tastenabdeckungen besteht. Die Abmessungen der einzelnen Komponenten wurden nach präzisen Messungen und Bewertungen streng festgelegt und sind in ihren jeweiligen Dreitafelprojektionen klar ersichtlich. Die mit dem Gehäuse verbundenen Teile werden vollständig im 3D-Druckverfahren hergestellt. Das Gehäusedesign verbindet Ästhetik mit Funktionalität: Es hebt die Tasten und den Bildschirm als die zentralen interaktiven Hardwareelemente für den Benutzer hervor und bietet gleichzeitig die erforderlichen Anschlüsse für externe Geräte. Darüber hinaus schützt das Gehäuse die internen Schaltkreise, indem es verhindert, dass leitfähige Materialien die Leiterplatte berühren und Kurzschlüsse verursachen, oder dass die ICs durch statische Hochspannung der Benutzer beschädigt werden. Durch ein optimiertes Belüftungsdesign wird außerdem eine effiziente Wärmeableitung gewährleistet, wodurch sichergestellt wird, dass der Raspberry Pi während des Betriebs eine stabile Temperatur beibehält und die Zuverlässigkeit des Systems gewährleistet ist.
Kamerahalterung
-
Abildung ??: :Kamerahalterung Basis
-
Abildung ??: Kamerahalterung Verbindung
-
Abildung ??: Kamerahalterung Montage
Die obige Abbildung zeigt das Design der Kamerahalterung. Beide Komponenten werden mittels 3D-Drucktechnologie hergestellt. Die Basis dient zur Befestigung der Drehachse des MG996R-Servomotors, während das Verbindungsbauteil zur Befestigung der Kamera und des Servomotorgehäuses verwendet wird. Die Kombination dieser Komponenten bietet der Kamera einen Rotationsfreiheitsgrad und ermöglicht somit die Regelung der Kamera.
Umsetzung SW
Wahl der Programmiersprache
Dieses Projekt wurde in der Interpretersprache Python umgesetzt. Da Python sowohl auf den für die Entwicklung verwendeten Windows-Systemen eingesetzt werden kann, als auch auf dem Zielsystem Raspberry Pi verfügbar ist. Für eine korrekte Bildverarbeitung ist die Verwendung der Bibliothek OpenCV notwendig, die auch für C++ und somit für MATLAB zur Verfügung stünde. Ausschlaggebend für die Wahl von Python war die Möglichkeit, die von Google stammende Bibliothek Mediapipe zu verwenden. Mediapipe bietet Zugriff auf verschiedene, optimierte Algorithmen, die unter anderem die Erkennung von Körperhaltungen ermöglichen und ist für die verwendung mit Python und OpenCVoptimiert [13], was die Bildgestützte erkennung der Körperpositionen auf ein Minimum an aufwand reduziert . In MATLAB müssten diese von anderen 3. Bibliotheken[14] implementiert oder über eine Matlab-Python Schnittstelle eingebunden werden.
Paralellitaet von Aufgaben
Parallelität von Aufgaben ermöglicht die gleichzeitige Bearbeitung mehrerer Prozesse, was durch die Verwendung von Threads effizient umgesetzt werden kann, da diese die gleichzeitige Ausführung mehrerer Aufgaben innerhalb eines Programms erlauben.
Jeder Thread arbeitet unabhängig, teilt sich aber denselben Speicherbereich, was eine schnelle Kommunikation ermöglicht, aber auch zu Synchronisationsproblemen führen kann.
In Python ermöglicht das Threading-Modul das Erstellen und Verwalten von Threads, um parallele Aufgaben effizient auszuführen. Es bietet einfache Mechanismen, um Threads zu starten, zu synchronisieren und Ressourcen zwischen ihnen zu teilen.
Die parallele Ausführung der Tasks camera_video_worker
und user_input_worker
ist für das Winkerätsel entscheidend, da beide Prozesse gleichzeitig neben dem Hauptprogramm aktiv sein müssen. Der camera_video_worker
verarbeitet kontinuierlich die Kameradaten, analysiert die Bewegungen und erkennt das Winken als Teil des Spiels. Der user_input_worker
hingegen ist primär für die Erfassung der Benutzereingaben zuständig, insbesondere um einen Spielabbruch durch den Benutzer zu ermöglichen. Durch diese parallele Struktur können Kameraverarbeitung und sofortige Abbruchmöglichkeit gleichzeitig und ohne gegenseitige Beeinflussung ablaufen. Dies gewährleistet einen reibungslosen Spielablauf und gibt dem Benutzer die volle Kontrolle ohne Verzögerungen oder Unterbrechungen des Spielverlaufs. Um die eingangs beschriebenen Synchronisationsprobleme bei der Kommunikation zwischen den einzelnen Subthreads in den Griff zu bekommen, wird auf die Verwendung von Queues gesetzt die, die gesendeten Nachrichten ähnlich wie in einem Shiftregister in einer Schlange zur Verfügung stellen[15].
Grafische Ausgabe
LCD Modul
Das LCD-Programmmodul erfüllt die Anforderungen dieses Projekts in Bezug auf die Anzeige von Text und Symbolen. Mit der Funktion Eine_Zeile_Zeichenkette(Zeile, Spalte, Text_Eingeben) kann Text an einer beliebigen Zeile und Spalte des Bildschirms angezeigt werden, während die Funktion Eine_Seite_Zeichenkette(Zeile, Spalte, Text_Eingeben) dazu dient, eine komplette Seite mit Text darzustellen. Für längere Zeichenketten kann die Funktion Mehr_Seite_Zeichenkette(Zeile, Spalte, Text_Eingeben) verwendet werden, die den Text automatisch in mehrere Seiten aufteilt und alle 4 Sekunden umblättert.
Die Schlüsselfunktionen des LCD-Moduls sind spi_init()
, senden_zu_st7920(Auswahl, Daten)
und lcd_Konfiguration()
. Die Funktion spi_init() initialisiert die SPI-Schnittstelle des Raspberry Pi entsprechend dem Kommunikationseingenschaft des LCD128x64. Die Funktion senden_zu_st7920(Auswahl, Daten)
wurde basierend auf dem in der Abbildung ?? gezeigten Kommunikationszeitdiagramm von LCD entwickelt, damit können sowohl Befehle zur Konfiguration des LCD128x64 als auch Inhalte zur Anzeige gesendet werden. Die Funktion lcd_Konfiguration()
konfiguriert die wichtigsten Register des LCD-Controllers gemäß dem Datenblatt und aktiviert die Hauptfunktionen des Displays.
Im folgenden Scroll-Fenster können die Details für LCD Modul eingesehen werden.
import spidev
from gpiozero import DigitalOutputDevice
import time
# Definition Pins SPI und CS
SS_PIN = 5
cs = DigitalOutputDevice(SS_PIN)
spi = spidev.SpiDev()
def spi_init():
spi.open(0, 0) # Verwenden SPI Kanel 0
spi.max_speed_hz = 2000000 # SPI Clock
spi.mode = 0b11 # CPOL=1, CPHA=1 Modi 3
spi.bits_per_word = 8
def senden_zu_st7920(Auswahl, Daten):
if Auswahl == 0:
Start_Datei = 0xf8
else:
Start_Datei = 0xfa
MSB = Daten & 0xF0
LSB = (Daten << 4) & 0xF0
cs.on() # SPI KOmmunikation Start
spi.writebytes([Start_Datei])
spi.writebytes([MSB])
spi.writebytes([LSB])
cs.off() # SPI KOmmunikation End
# Stellen die Position von cursor ein
def Einstellung_cursor(Zeile, Spalte):
# DDRAM Adresse Berechnen
Zeile_addresses = [0x80, 0x90, 0x88, 0x98]
Address = Zeile_addresses[Zeile - 1] + (Spalte - 1)
senden_zu_st7920(0, Address) #
def lcd_Konfiguration():
senden_zu_st7920(0, 0x30) # Funktion Einstellung 0x30 fuer Schriftdarstellung
time.sleep(0.00072) # 72 us Pause fuer Einstellung
senden_zu_st7920(0, 0x0C) # Cursor OFF
time.sleep(0.00072) # 72 us Pause fuer Einstellung
senden_zu_st7920(0, 0x01) # Eliminierung der Inhalte in LCD
time.sleep(0.0016) # Pause fuer Einstellung
def Entfernen():
senden_zu_st7920(0, 0x01) # Eliminierung der Inhalte in LCD
time.sleep(0.0016) # 16ms Pause fuer Einstellung
def Eine_Zeile_Zeichenkette(Zeile,Spalte,Text_Eingeben):
Einstellung_cursor(Zeile, Spalte)
for char in Text_Eingeben:
senden_zu_st7920(1, ord(char))
def Eine_Seite_Zeichenkette(Zeile,Spalte,Text_Eingeben):
Erster_Lauf = 1;
for Zeile in range(Zeile, 5):
if Erster_Lauf==1:
senden_zu_st7920(0, 0x01) # Eliminierung der Inhalte in LCD
time.sleep(0.0016) # 16ms Pause fuer Einstellung
start_index = 0;
end_index = 16-(2*(Spalte-1));
Einstellung_cursor(Zeile, Spalte)
line = Text_Eingeben[start_index:end_index]
Erster_Lauf=0;
else:
start_index = end_index
end_index = start_index+16
Einstellung_cursor(Zeile, 1)
line = Text_Eingeben[start_index:end_index]
for char in line:
senden_zu_st7920(1, ord(char))
def Mehr_Seite_Zeichenkette(Zeile,Spalte,Text_Eingeben):
# Liste für die Gruppen initialisieren
gruppen = []
puffer = ""
# Aufteilung langer Zeichenfolgen in mehrere Seiten
for wort in Text_Eingeben.split():
if len(puffer) + len(wort) + 1 <= 64:
puffer += (wort + " ")
else:
gruppen.append(puffer.strip())
puffer = wort + " "
if puffer:
gruppen.append(puffer.strip())
# Seite fuer Seite werden angezeigt
for idx, gruppe in enumerate(gruppen):
Eine_Seite_Zeichenkette(Zeile, Spalte, gruppe)
time.sleep(4) # 4 Sekunden pro Seite
Bildaufnahme und Verarbeitung
BodyPoseEstimation Modul
Zur Realisierung der Flaggenerkennung wurde in diesem Projekt die Aufnahme mittels Kamera und anschließender OpenCV-Bildverarbeitung gewählt.
Diese Aufgabe wird durch die Funktion Camera_Video_Worker(cv_worker_result_queue)
umgesetzt.
Durch das asynchrone Ausführen der Funktion lassen sich Videostreams in Echtzeit zur Extraktion und Visualisierung von Körperskelettdaten mit Mediapipe-Bibliothekenverarbeiten. Aus dem Bild werden Daten zur Körpererkennung extrahiert, um basierend auf den im Modell hinterlegten Schlüsselmerkmalen Gelenkpositionen zu erkennen und als Landmarks zu speichern. Neben der grafischen Darstellung der erkannten Person kann, basierend auf den Landmarken und der in einem Abschnitt beschriebenen geometrischen Funktion, eine Winkelberechnung erfolgen. Diese ermöglicht es, einen Abgleich der gezeigten Armposition des Spielers mit den im Semaphore-Alphabet festgelegten Positionen durchzuführen.
Die konkrete Umsetzung in diesem Projekt nutzt, neben der Standard-Bildverarbeitung mit OpenCV, die Erweiterung der Mediapipe-Bibliotheken, die auf Machine-Learning-Algorithmen basierende Modelle zur Körpermarkenerkennung zur Verfügung stellen.
Der Vorteil ergibt sich daraus, dass sich direkt auf die Körperpunkte des Spielers bezogen werden kann, egal in welchem Winkel er zur Kamera steht oder wie er seinen Körperschwerpunkt nach links oder rechts verlagert.
Zudem ist durch das landmarkenbasierte Verfahren direkt eine einheitliche Definition von Links und Rechts gegeben, die im sonstigen Umgang mit Flaggen-Semaphore durchaus zur Verwirrung führen kann.
def Camera_Video_Worker(resultQeue):
"""
Mediapipe-spezifische Verarbeitung zur Extraktion von Körperskelett und Schlüsselpunkten.
"""
# Initialisierung von Mediapipe-Werkzeugen
mp_drawing = mp.solutions.drawing_utils
mp_pose = mp.solutions.pose
# Mediapipe Pose-Erkennung initialisieren
with mp_pose.Pose(min_detection_confidence=0.51, min_tracking_confidence=0.51) as pose:
while True: # Endlosschleife für die Verarbeitung
# Mediapipe-Prozess zur Verarbeitung eines Bildes
results = pose.process(image) # Hier wird ein Bild übergeben
if results.pose_landmarks: # Wenn Schlüsselpunkte erkannt wurden
# Zeichnen des Körperskeletts und der Referenzlinien
image = GraphicalUserInterface.user_skeleton_visualisation(image, results.pose_landmarks)
#Bereitstellen der Körpermarken für die Hautpfunktion
resultQeue.put(escape.PoseObject(results.pose_landmarks, image ))
if platform.system()== 'Linux':
Kamera_Regelung(image, nose)
Kamera Regler Modul
Das Ziel eines Kamerahalters besteht darin, die Kamera mithilfe eines Servomotors zu bewegen, sodass sie sich um eine vorgegebene Achse drehen kann, um den optimalen Blickwinkel zu erreichen. Um die Positioniergeschwindigkeit und -genauigkeit zu verbessern, kann ein Regelkreis verwendet werden, der eine schnelle und präzise Ausrichtung der Kamera ermöglicht.
Grundelemente der Regelung
Sollgröße & Istgröße
Wie zuvor erwähnt, besteht das Ziel des Geräts darin, schnell und präzise den optimalen Blickwinkel einzustellen. Der „optimale Blickwinkel“ bedeutet, dass das aufzunehmende Objekt (Spieler) im Bildzentrum positioniert ist. Da sich das Gerät nur um die z-Achse drehen kann, lässt sich ausschließlich die x-Koordinate im Bild verändern. Daraus ergibt sich, dass das Regelziel des Geräts darin besteht, die x-Koordinate des Spielers auf die Mittellinie des Bildes auszurichten. Basierend auf diesem Ziel lässt sich schließen, dass die Sollgröße und die Istgröße im Regelkreis beide die x-Koordinate des Spielers beschreiben.
Strecke
In diesem Regelkreis entspricht die Strecke der gesamten Kamerahalterung, wobei das Eingangssignal ein PWM-Signal und das Ausgangssignal die Gesichtskoordinaten sind. Um die Analyse der Strecke zu vereinfachen, kann die Kamerahalterung in zwei Teile unterteilt werden: den Servomotor und die Kamera, die jeweils separat analysiert werden.
- Servomotors
Die Abbildung ?? zeigt das Funktionsprinzip eines Servomotors zur präzisen Einstellung des Winkels, welches ein typischer geschlossener Regelkreis ist. Das Eingangssignal ist ein PWM-Signal, das durch einen Wandler in ein Spannungssignal umgewandelt wird. Die Regelstrecke besteht aus einem Gleichstrommotor und einem Getriebe, wobei die Ausgangsgröße der Winkel ist. Wenn der Strecke ein Sprungspannungssignal zugeführt wird, erhöht das Getriebe den Ausgangswinkel mit einer konstanten Winkelgeschwindigkeit. Daher erfüllt die Regelstrecke die Eigenschaften eines I-Glieds.
Der vom Getriebe ausgegebene Winkel kann über ein Potentiometer in ein Spannungssignal umgewandelt und als Rückführungssignal verwendet werden. Das Fehlersignal wird anschließend durch einen Operationsverstärker proportional verstärkt, um ein Steuersignal zu erzeugen, das das System regelt.
Die Übertragungsfunktion dieses Regelkreises lautet:
Aus der Übertragungsfunktion des Servomotors lässt sich erkennen, dass dessen dynamische Eigenschaften einem PT1-Glied entsprechen.
- Kamera
Für die Kamera als Strecke ist die Stellgröße der Winkel , und die Ausgabe ist die horizontale Pixelkoordinate des Spielers im Bild . Die Abbildung zeigt das Konzept des Bildwinkels. Dieser bezeichnet den horizontalen Sichtwinkel einer Kamera oder eines optischen Systems, der in der Regel in Grad angegeben wird. Der Bildwinkel beschreibt den maximalen Bereich, den die Kamera in horizontaler Richtung erfassen kann, und ist ein wichtiger Parameter in optischen Systemen.
Die Beziehung zwischen der Winkeländerung und der Pixelkoordinatenverschiebung ergibt sich aus der folgenden Formel:
Dabei gilt:
- : Die horizontale Pixelanzahl (Breite des Bildes).
- : Der horizontale Sichtwinkel der Kamera (Horizontal Field of View).
- : Die Änderung des Winkels.
Durch Anwendung der Laplace-Transformation wird die Gleichung in den Frequenzbereich übertragen:
Die Übertragungsfunktion der Kamera ergibt sich zu:
Aus der Übertragungsfunktion geht hervor, dass diese Kamerastrecke ein P-Glied (proportionales Glied) darstellt. Der Verstärkungsfaktor lautet: .
Die Gesamtübertragungsfunktion der Kamerahalterung ergibt sich aus der Verknüpfung der beiden Übertragungsfunktionen und . Da beide in Serie geschaltet sind, multiplizieren sich die Übertragungsfunktionen:
Einsetzen der Einzelübertragungsfunktionen:
Nach Vereinfachung ergibt sich: Aus der Übertragungsfunktion der Strecke Kamerahalterung geht vor, die Kamerahalterung ist noch ein PT1 Glied
- Die Verifizierung für Theorie
Die Abbildung?? zeigt den praktischen Test der Strecke-Kamerahalterung. Die Testschritte sind wie folgt:
- Der Anfangswinkel der Kamera wird mit einem PWM-Signal eingestellt.
- Die Kamera dient als Positionssensor und liest in einer Schleife kontinuierlich die x-Koordinaten des Spielers aus.
- Die Koordinateninformationen werden in Echtzeit gespeichert.
- Ein PWM-Stufensignal wird eingespeist.
- Die gemessenen Daten werden in MATLAB importiert, die Kurve wird gezeichnet und analysiert.
Da der Servomotor eine sehr hohe Reaktionsgeschwindigkeit aufweist, führen die schnellen dynamischen Änderungen während des Betriebs zu einer deutlichen Bewegungsunschärfe bei den Aufnahmen der Kamera. Diese Unschärfe beeinträchtigt die Bildqualität erheblich, sodass in dieser Phase keine optimale Bildverarbeitung durchgeführt werden kann.
Infolgedessen wird die Anzahl und Genauigkeit der Abtastpunkte eingeschränkt, was dazu führt, dass die tatsächlich gemessenen Daten in bestimmten Momenten eine unzureichende Diskretheit aufweisen können.
Trotz dieser Einschränkungen zeigt die gemessene Kurve weiterhin klar die charakteristischen Merkmale eines PT1-Glieds. In Kombination mit der theoretischen Herleitung und den praktischen Testergebnissen lässt sich weitgehend bestätigen, dass die Kamerahalterung ein PT1-Glied ist.
Regler
PID Regelalgorithmus wird eingesetzt. Der PID-Regelalgorithmus basiert auf einem mathematischen Modell aus Proportional-, Integral- und Differentialanteilen und zeichnet sich durch seine einfache Umsetzung aus. Er wird in einer Vielzahl von Regelungsszenarien eingesetzt. Der Algorithmus erfordert nur geringe Rechenleistung und ist daher besonders für Echtzeitsysteme geeignet. Die Parametereinstellung ist ebenfalls relativ unkompliziert und kann durch Experimente oder Erfahrungswerte schnell optimiert werden. Bei einer geeigneten Parametrierung gewährleistet der PID-Algorithmus eine stabile Regelungsleistung, verhindert Systemdivergenzen und sorgt für Zuverlässigkeit.
Durch Berechnungen und Auswahl wurde festgestellt, dass eine präzise Regelung allein durch den P- und I-Anteil des PID-Reglers erreicht werden kann, ohne den D-Anteil einzusetzen. Der Berechnungsprozess ist wie folgt:
Die Führungsübertragungsfunktion lautet:
Die Störsübertragungsfunktion lautet:
Dabei gilt:
- ist die Übertragungsfunktion des PID-Reglers.
- beschreibt die Kamera-Halterung:
- ist die Verstärkung.
- ist die Zeitkonstante.
Die Eingangs-Sollgröße wird als Stufensignal mit der Amplitude 1 definiert. Ziel ist es, den Wert im stationären Zustand zu beobachten, wenn :
Die Eingangs-Störung wird als Stufensignal mit der Amplitude 1 definiert. Ziel ist es, den Wert im stationären Zustand zu beobachten, wenn :
- Die Implementierung des Regelungsprogramms
Im folgenden Scroll-Fenster können die Details für Regelungsprogramm eingesehen werden.
import cv2
from rpi_hardware_pwm import HardwarePWM
import time
import csv
#glaobal variabel
PWM_CHANNEL = 0 # PWM kanel0(GPIO12)
# PID Parameter
Kp = 0.015 # proportionkoeffizient
Ki = 0.00001 # Integrationskoeffizient
Integraltion = 0
Letzter_Fehler = 0
# Initialisierung pwm und Servo Motor
def init_servo():
global pwm
pwm = HardwarePWM(pwm_channel=PWM_CHANNEL, hz=50, chip=2) #Auswahl PWM-Ausgangspins
pwm.start(0)
def Einstellung_Servo_Winkel(Winkel):
global pwm
duty_cycle = 3 + (Winkel / 270.0) * 10 # Umwandlung des Winkels(0-270) in ein PWM-Signal
pwm.change_duty_cycle(duty_cycle) # Einsatz fuer PWM-Signal
# PID Regler
def PID(Ziel_x, Aktuell_x):
global Integraltion, Letzter_Fehler
Fehler = Ziel_x - Aktuell_x
Integraltion += Fehler
Letzter_Fehler = Fehler
PID_Ausgabe = Kp * Fehler + Ki * Integraltion
return PID_Ausgabe
# Haar-Kaskadenklassifikator laden
def lade_gesichtskaskade():
haarcascade_pfad = cv2.data.haarcascades + 'haarcascade_frontalface_default.xml' # haarcascade_frontalface_default.xml ist ein gut trainiertes Gesichtserkennungsmodell.
gesichtskaskade = cv2.CascadeClassifier(haarcascade_pfad) # mithilfe cv2.CascadeClassifier() wird Gesichtserkennungsmodell geladen
return gesichtskaskade
def Gesichtserkennung(Rahmen, gesichtskaskade):
skalierungsfaktor = 1.1
min_nachbarn = 5
min_Groesse = (30, 30)
Gesicht = gesichtskaskade.detectMultiScale(
Rahmen,
scaleFactor=skalierungsfaktor,
minNeighbors=min_nachbarn,
minSize=min_Groesse
)
return Gesicht
# CSV Datei fuer Analyse
def init_csv(filename):
with open(filename, mode='w', newline='') as file:
writer = csv.writer(file)
writer.writerow(["Timestamp", "Zentral_Bild_x", "Zentral_x"]) # Titel
def save_to_csv(filename, timestamp, Zentral_Bild_x, Zentral_x):
with open(filename, mode='a', newline='') as file:
writer = csv.writer(file)
writer.writerow([timestamp, Zentral_Bild_x, Zentral_x])
def Kamera_Regelung():
csv_filename = 'Messdaten.csv' # initialisierung CSV Datei
init_csv(csv_filename)
init_servo()
video_Erfassen = cv2.VideoCapture(0) # oeffnen kamera - Nr.0
gesichtskaskade = lade_gesichtskaskade() # Haar-Kaskadenklassifikator laden
Aktuell_Winkel = 90
Einstellung_Servo_Winkel(Aktuell_Winkel) # initialisieren des servowinkels
start_time = time.time()
while time.time() - start_time < 20: # 20s zum Reglerung
Bild_Breite = int(video_Erfassen.get(cv2.CAP_PROP_FRAME_WIDTH))
Bild_Hoehe = int(video_Erfassen.get(cv2.CAP_PROP_FRAME_HEIGHT))
Zentral_Bild_x = Bild_Breite // 2
ret,Rahmen = video_Erfassen.read() # Zum Lesen jedes einzelnen Frames aus der Kamera
# ret: Ein boolescher Wert, der angibt,
#ob das Videoframe erfolgreich gelesen wurde
#frame: Das erfasste Bildframe
Rahmen = cv2.cvtColor(Rahmen, cv2.COLOR_BGR2GRAY) # umwandlung zu binaerem Bild
Gesicht = Gesichtserkennung(Rahmen, gesichtskaskade) # Gesicht Erkennung
if len(Gesicht) > 0: # Stellen sicher, dass der Inhalt von Gesicht nur dann aufgerufen
# wird, wenn ein Gesicht erkannt wurde.
x, y, w, h = Gesicht[0]
Zentral_x = x + w // 2 # Zentrumskoordinaten Berechnung
PID_Ausgabe = PID(Zentral_Bild_x, Zentral_x) # PID Reglung
Aktuell_Winkel += PID_Ausgabe # Aktualisierung des Winkels
Aktuell_Winkel = max(0, min(270, Aktuell_Winkel)) # Winkel wird damit zwischen 0-270 Grad begrenzt
Einstellung_Servo_Winkel(Aktuell_Winkel)
# Messdatein fuer Analyse werden gespeichert
save_to_csv(csv_filename, time.time(), Zentral_Bild_x, Zentral_x)
cv2.imshow('Fenster', Rahmen) # Visualisierung
# Druecken 'q' Tastatur zum Ende
if cv2.waitKey(1) & 0xFF == ord('q'):
break
Um das Verständnis dieses Regelungsprogramms zu erleichtern, zeigt die folgende Abbildung?? die Hauptlogik und den Ablauf des Programms in Form eines Simulink-Modells.
Zur Bestimmung der Proportional- und Integralverstärkungen wurde zunächst die Methode von Ziegler/Nichols verwendet. Anhand der Diagramme wurden die Werte für , , und ermittelt, um daraus die Verstärkungskoeffizienten und abzuleiten.
Nach Tests mit diesen Koeffizienten stellte sich jedoch heraus, dass das System instabil war. Dies ist vermutlich auf die unzureichende Anzahl der Abtastpunkte in den Diagrammen zurückzuführen, was zu falschen Koeffizienten führte.
Schließlich wurde die Feinabstimmung der Koeffizienten durch eine empirische Methode vorgenommen:
- Zunächst wurde auf 0 gesetzt, um sich ausschließlich auf die Einstellung von zu konzentrieren, sodass die Kamerahalterung so schnell und präzise wie möglich reagieren konnte.
- Anschließend wurde schrittweise kalibriert, um den stationären Fehler auszugleichen.
Kontrolleffekt des Regelkreises
1. Dynamische Leistung
- Aus der Antwortkurve (rote Linie: Istgröße, blaue Linie: Sollgröße) ist zu erkennen, dass die tatsächliche Ausgabe (Istgröße) dem Sollwert (Sollgröße) unter der Wirkung des Regelkreises schnell folgt.
- Das System zeigt einen schnellen Anstieg in der Anfangsphase (ca. 0-1,5 Sekunden) und erreicht nach etwa 1,5 Sekunden den stationären Zustand.
2. Stationäre Leistung
- Im stationären Zustand (ca. nach 1,5 Sekunden) ist der Fehler zwischen der tatsächlichen Ausgabe und dem Sollwert minimal und fast vernachlässigbar, was eine gute stationäre Genauigkeit des Systems zeigt.
- Der stationäre Fehler nähert sich nahezu null, was die Erfüllung des Regelziels bestätigt.
3. Stabilität des Systems
- Aus dem Nullstellen- und Polstellen-Diagramm (zweite Abbildung) ist ersichtlich, dass der Pol des Systems in der linken Hälfte der komplexen Ebene liegt (s = -1,67), was darauf hinweist, dass das System stabil ist.
- Es gibt keine Oszillationen, die Systemantwort ist eine exponentielle Dämpfung ohne Schwingungen.
4. Zusammenfassung der Kontrolleffekte
- Das Regelungssystem weist eine schnelle Reaktionsfähigkeit und gute stationäre Leistung auf, sodass es in kurzer Zeit den Sollwert verfolgen kann.
- Sowohl die dynamische als auch die stationäre Leistung des Systems sind ausgezeichnet, was zeigt, dass das Design des Regelkreises die gewünschten Ziele erfüllt.
Spielablauf
Start Game
Die Funktion startGame(Level)
initialisiert und startet einen separaten Thread für die Körpererkennung cv_worker_thread
, um eine unabhängige Verarbeitung sicherzustellen, während das Spiel läuft. Sie setzt zudem den Schwierigkeitsgrad basierend auf dem übergebenen Parameter Level mithilfe der Funktion setSkillLevel(SkillLevel.NONE)
und gibt diesen zur Kontrolle aus. Als Output ruft die Funktion schließlich die play_game()
-Funktion auf, wodurch das eigentliche Spiel gestartet wird.
Play Game
Die Funktion play_game()
steuert den Hauptspielablauf des Winkerraetsels, bei dem Körperposen analysiert werden, um Gesten zu erkennen. Sie initialisiert das Spiel, verarbeitet den Nutzer- und Kamerainput in vorm von Landmarken, und entscheidet abhängig vom Spielmodus BEGINNER, PROFI, EXPERT
über Fortschritt und Spielende. Der Input umfasst Sensordaten (Körperwinkel), Benutzereingaben und Spielvorgaben wie Schwierigkeitsgrade und Lösungswörter. Die Ausgabe erfolgt über die bereits beschriebene LCD-Ausgabe.
Die Besonderheiten der Funktion liegen in der dynamischen Anpassung an Schwierigkeitsstufen. Bei den Modi BEGINNER
und PROFI
wird das gesamte Lösungswort( einzelner Buchstabe) mit erkannten Buchstaben verglichen, während im EXPERT
-Modus Buchstaben sequentiell auf das vorhanden sein in einem Wort geprüft werden. Die Funktion integriert eine Echtzeit-Verarbeitung von Körperwinkeln, die mit OpenCV berechnet und anschließend interpretiert werden.
Das Spiel endet, wenn das Rätsel erfolgreich gelöst oder manuell abgebrochen wird. Die Funktion ruft hierzu die close_game
-Funktion auf, um das Spiel erfolgreich zu beenden. Andernfalls wird die play_game
-Funktion zyklisch mittels einer Schleife und einer generellen Wartezeit von 0,1 Sekunden ausgeführt, um die CPU zu schützen. Im zeitlichen Worst-Case ist durch das Gewinnen des Spiels mit Zykluszeiten von über 30 Sekunden zu rechnen.
Stop Game
Die vorliegende Funktion überwacht eine Bedingung stop_game
, die bei Aktivierung den laufenden Spielprozess kontrolliert beendet. Hierbei wird insbesondere der parallel ausgeführte Thread cv_worker_thread
entweder geordnet synchronisiert oder, falls erforderlich, mittels eines erzwungenen Stopps terminiert. Diese Vorgehensweise gewährleistet eine effiziente Ressourcennutzung und trägt zur Stabilität des Gesamtsystems bei.
Berechnung der Flaggensignale
Videosignal zu Winkel
Da die Position der Arme beim Flaggenwinken in feste Bereiche mit einer festen Ausrichtung eingeteilt werden kann, ist die Idee, die Position der Arme mit grafischen oder geometrischen Verfahren zu bestimmen. Der Ansatz zur Umsetzung, beruht auf der Ausrichtung des Arms zur Körpermitte mit grafischen beziehungsweise geometrischen Methoden zu bestimmen. Hierzu wird der Körper des Spielers in einen rechten und einen linken Winkel unterteilt. Beide Winkel beginnen jeweils unten, also bei 6 Uhr, steigen über die Körperaußenseite nach 12 Uhr, bis sie in der Körpermitte wieder bei 6 Uhr angelangen. Zur Winkelberechnung wird der Vektor genutzt, der zwischen der Schulter- und der Ellbogen-Landmarke entsteht, sowie der Vektor, der als Körpermittelpunkt in der Mitte zwischen den Schultern und der Hüfte entsteht. Für eine erfolgreiche Winkelberechnung müssen demnach genau diese Punkte im Sichtfeld der Kamera sein. Die folgenden drei Abbildungen zeigen der Reihe nach, wie der Prozess der Winkelumrechnung anhand der mit Mediapipe erkannten Schlüsselkoordinaten des Körpers berechnet wird.
- Variablenerklärung:
Winkel zu Buchstabe
Die Funktion angleToLetter
interpretiert die Winkel zweier Arme (in Grad) und ordnet diese mithilfe einer Zuordnungstabelle einem Buchstaben des Semaphore-Flaggenalphabets zu. Sie berücksichtigt dabei eine Toleranz von ±20 Grad, um kleine Abweichungen in der Armhaltung auszugleichen, was die Robustheit der Zuordnung bei ungeübten Signalgebern erhöht.
Besonderheiten sind die Ruhestellung (0°/0°) und die Möglichkeit eines Korrektursignals(135°/45°) für den Expertenmodus
Komponententest
LCD Modul
Anforderung
- Überprüfen, ob ein String ab einer definierten Zeile und Spalte angezeigt werden kann.
- Überprüfen, ob ein sehr langer String vollständig angezeigt werden kann.
Ausführung
- Übergabe der zweiten Zeile, zweiten Spalte sowie des Strings Escape Game an die Funktion.
- Ein String einer bestimmten Länge wird eingegeben: Test - Ist es möglich, eine sehr lange Zeichenkette auf mehrere Seiten aufzuteilen und anzuzeigen?
Ergebnis
-
Abildung ??: Eine Zeile Text
-
Abildung ??: Ein paar Seiten Text
Bewertung
Erfüllt die Anforderung
Ergebnis
Fehler
Zusammenfassung
Lessons Learned
Projektunterlagen
Projektplan
Zeitplanung
Projektdurchführung
YouTube Video
Quellen
→ zurück zur Übersicht: WS 24/25: Escape Game
- ↑ SELLERI, Stefano, 2017. Claude Chappe and the first telecommunication network (without electricity). URSI Radio Science Bulletin [online]. März 2017. Bd. 2017, Nr. 360, S. 96–101. [Zugriff am: 1 Oktober 2024]. DOI 10.23919/URSIRSB.2017.8113174. Verfügbar unter: https://ieeexplore.ieee.org/document/8113174/?arnumber=8113174
- ↑ Navy Seaman Ryan Ruona uses semaphore flags to signal another ship., [kein Datum]. [online]. [Zugriff am: 1 Oktober 2024]. Verfügbar unter: https://www.defense.gov/Multimedia/Photos/igphoto/2001244016/
- ↑ Codierung von Texten - Fakultät für Elektrotechnik, Informatik und Mathematik - Fakultäten - Kategorien - Videoportal der Uni Paderborn, [kein Datum]. [online]. [Zugriff am: 1 Oktober 2024]. Verfügbar unter: https://videos.uni-paderborn.de/category/video/codierung-von-texten/3a9cfca393633045f308a88c20e8ad82/7
- ↑ Education Codes and Communication, [kein Datum]. National Museum of the Marine Corps [online]. [Zugriff am: 1 Oktober 2024]. Verfügbar unter: https://www.usmcmuseum.com/uploads/6/0/3/6/60364049/nmmc_semaphore_flag_booklet_final_1.pdf
- ↑ EVERYTHINGISHACKED, [kein Datum]. Semaphore [online]. Verfügbar unter: https://github.com/everythingishacked/Semaphore
- ↑ Estimate Body Pose Using Deep Learning - MATLAB & Simulink - MathWorks Deutschland, [kein Datum]. [online]. [Zugriff am: 2 Oktober 2024]. Verfügbar unter: https://de.mathworks.com/help/deeplearning/ug/estimate-body-pose-using-deep-learning.html
- ↑ Raspberry Pi 5 Gruppe., [kein Datum]. [online]. [Zugriff am: 11 Oktober 2024]. Verfügbar unter:https://www.reichelt.de/das-raspberry-pi-5-b-4gb-black-bundle-rpi5-bbdl-4gb-p362101.html?&nbc=1&trstct=lp_1358_155298
- ↑ Kurzhubtaster 6x6 mm, [kein Datum]. [online]. [Zugriff am: 11 Oktober 2024]. Verfügbar unter:https://www.reichelt.de/kurzhubtaster-6x6-mm-hoehe-13-mm-12-v-vert--jtp-1130-p27894.html?&trstct=pos_0&nbc=1
- ↑ LCD128X64, [kein Datum]. [online]. [Zugriff am: 11 Oktober 2024]. Verfügbar unter:https://www.reichelt.de/entwicklerboards-display-grafik-lcd-128x64-pixel-debo-lcd128x64-p335007.html?&trstct=pos_0&nbc=1
- ↑ CON AMDIS03B Webcam, [kein Datum]. [online]. [Zugriff am: 11 Oktober 2024]. Verfügbar unter:https://www.reichelt.de/webcam-720p-hdready-con-amdis03b-p292005.html?&trstct=pos_7&nbc=1CON
- ↑ Deutschland Flagge, [kein Datum]. [online]. [Zugriff am: 11 Oktober 2024]. Verfügbar unter:https://www.amazon.de/molinoRC-Deutschland-Fahne-Stockfahne-Kinder-Fahne-Deutschland-Flagge/dp/B079SL8MRD
- ↑ Flaggensignale, [kein Datum]. [online]. [Zugriff am: 11 Oktober 2024]. Verfügbar unter:https://www.irisluckhaus.de/2016/infografik-flaggensprache/
- ↑ Leitfaden zur Erkennung von Positionsmarkierungen | Google AI Edge, [kein Datum]. Google AI for Developers [online]. [Zugriff am: 14 Januar 2025]. Verfügbar unter: https://ai.google.dev/edge/mediapipe/solutions/vision/pose_landmarker?hl=de
- ↑ Estimate Body Pose Using Deep Learning - MATLAB & Simulink - MathWorks Deutschland, [kein Datum]. [online]. [Zugriff am: 2 Oktober 2024]. Verfügbar unter: https://de.mathworks.com/help/deeplearning/ug/estimate-body-pose-using-deep-learning.html
- ↑ Vorlage:Zitierweb