diff --git a/Visual-Based-Landing-System/doc/Dokumentation_VBLS.bib b/Visual-Based-Landing-System/doc/Dokumentation_VBLS.bib index ae754068548e6ac301111c9536e291b396e5fb7f..4b3afc783c460b769a4852b8f0f4271a5e1217a7 100644 --- a/Visual-Based-Landing-System/doc/Dokumentation_VBLS.bib +++ b/Visual-Based-Landing-System/doc/Dokumentation_VBLS.bib @@ -166,6 +166,13 @@ Edition = {1.Edition} } +@Article{quadrocopterWeber2013, + Author = {Jan Weber}, + Title = {}, + Year = {}, + Month = {} +} + @online{quadrocopterSafety, Author = {Quadrocopter}, Title = {Safety}, diff --git a/Visual-Based-Landing-System/doc/Dokumentation_VBLS.pdf b/Visual-Based-Landing-System/doc/Dokumentation_VBLS.pdf index c76d2ca0fd5a9874b1ba8e14cc2f46773520915e..9e19ac6b28f318e1e1e7b018df1eddc5472da993 100644 Binary files a/Visual-Based-Landing-System/doc/Dokumentation_VBLS.pdf and b/Visual-Based-Landing-System/doc/Dokumentation_VBLS.pdf differ diff --git a/Visual-Based-Landing-System/doc/Dokumentation_VBLS.tex b/Visual-Based-Landing-System/doc/Dokumentation_VBLS.tex index 3fc6cb56f5ea1eb868023840f296d6bda363191e..a49fcdea3bee85b986ea46337bcf8fc186a969bc 100644 --- a/Visual-Based-Landing-System/doc/Dokumentation_VBLS.tex +++ b/Visual-Based-Landing-System/doc/Dokumentation_VBLS.tex @@ -6,17 +6,19 @@ \usepackage[utf8]{inputenc} \usepackage[T1]{fontenc} -\def\runcourse{Eingebettete Systeme} -\def\runcategory{Projektdokumentation} \title{Entwicklung einer Optical-Flow-basierten Android-Applikation zur Landeplatzlokalisierung unter Verwendung von OpenCV} \author{Lukas Friedrichsen, Philipp Stenkamp} +\def\runcourse{Eingebettete Systeme} +\def\runcategory{Projektdokumentation} + %% Packages \usepackage{layout/BOmodern} % modern HS Bochum themed document template designed for assignments and documentations \usepackage{amsmath} \usepackage[colorinlistoftodos]{todonotes} \usepackage{listings} \usepackage{qrcode} +\usepackage[]{hyperref} \lstset{ basicstyle=\ttfamily, @@ -41,8 +43,6 @@ \defbibheading{bib}{\chapter{Literatur}} \addbibresource{Dokumentation_VBLS.bib} -\usepackage[]{hyperref} - \begin{document} \pagenumbering{Roman} \maketitle @@ -69,10 +69,10 @@ Mit dieser Motivation behandelt diese Arbeit einen einfach zugänglichen, flexib \section{Zielsetzung} \label{ziel} -Ziel dieser Arbeit ist die Entwicklung einer Optical-Flow-basierten Applikation, welche eingehende Bilddaten einer Kamera verarbeiten und definierte Umgebungsmerkmale erfassen und herausstellen kann. Anhand dieser soll anschließend ein Ausgangssignal abhängig von der aktuellen Position des Merkmals im Bild erzeugt werden, welches die Steuerung einer gekoppelten Anwendung übernehmen oder beeinflussen kann (vgl. Spurhalteassistenzsysteme in einem Auto). -Konkret soll als Zielplattform ein Smartphone auf Android-Basis sowie die Open-Source Bibliothek OpenCV verwendet werden. Als Interface soll die USB-Schnittstelle dienen, da die Umwandlung von diesem Format in die meisten etablierten seriellen Datenprotokolle wie beispielsweise UART sehr einfach und kostengünstig umsetzbar ist und ein Großteil der gängigen Entwicklungsplattformen den Standard bereits von sich aus integriert. +Ziel dieser Arbeit ist die Entwicklung einer Optical-Flow-basierten Applikation, welche eingehende Bilddaten einer Kamera verarbeiten und definierte Umgebungsmerkmale erfassen und herausstellen kann. Anhand dieser soll anschließend ein Ausgangssignal abhängig von der aktuellen Position des Merkmals im Bild erzeugt werden, welches die Steuerung einer gekoppelten Anwendung übernehmen oder beeinflussen kann (vgl.\ Spurhalteassistenzsysteme in einem Auto). +Konkret soll als Zielplattform ein Smartphone auf Android-Basis sowie die Open Source Bibliothek OpenCV verwendet werden. Als Interface soll die USB-Schnittstelle dienen, da die Umwandlung von diesem Format in die meisten etablierten seriellen Datenprotokolle wie beispielsweise UART sehr einfach und kostengünstig umsetzbar ist und ein Großteil der gängigen Entwicklungsplattformen den Standard bereits von sich aus integriert. \\ -Zu Demonstrationszwecken soll neben einem allgemeinen Framework zur Entwicklung von OpenCV gestützten Bildverarbeitungsapplikationen für Android-Plattformen eine Landeplatzlokalisierung eines UAVs (Abk., engl. für Unmanned Aerial Vehicle) realisiert werden. Als zu erfassendes Merkmal fungiert zu diesem Zweck ein Kreis (vgl. Landeplatzsymbol eines Helikopters) und als Ausgabesignal eines sich unter dem Flugvehikel befindenden Smartphones soll die Stellgröße eines in die Applikation zu integrierenden Reglers dienen. Ziel ist es, dass das UAV sich autonom und ohne weitere Kenntnis über seine Umgebung über einem Landeplatz zu zentriert. +Zu Demonstrationszwecken soll neben einem allgemeinen Framework zur Entwicklung von OpenCV gestützten Bildverarbeitungsapplikationen für Android-Plattformen eine Landeplatzlokalisierung eines UAVs (Abk., engl. für Unmanned Aerial Vehicle) realisiert werden. Als zu erfassendes Merkmal fungiert zu diesem Zweck ein Kreis (vgl.\ Landeplatzsymbol eines Helikopters) und als Ausgabesignal eines sich unter dem Flugvehikel befindenden Smartphones soll die Stellgröße eines in die Applikation zu integrierenden Reglers dienen. Ziel ist es, dass das UAV sich autonom und ohne weitere Kenntnis über seine Umgebung über einem Landeplatz zu zentriert. Hierbei muss aus Sicherheitsaspekten ein manuelles Eingreifen durch den Menschen jederzeit möglich sein, weshalb eine signalverarbeitende Instanz in Form eines Mischers, welcher die Signale der Fernbedienung und der Applikation überlagert, zu integrieren ist. \chapter{Grundlagen} @@ -94,17 +94,17 @@ Seit diesem Zeitpunkt hat sich Android als weltweit \cite[vgl.\ ][]{aboutAndroid Einen großen Anteil an der erfolgreichen Verbreitung von Android hatte (und hat) das frei zugängliche und gut dokumentierte von Google zur Verfügung gestellte Interface zur Erstellung von Applikationen in Kombination mit dem Google Play Store als zentraler Distributionsplattform. -Das Interface kann in Form des Android SDK (Abk., engl. für \glqq{}Software Development Kit\grqq{}) (und ggf. des NDK (Abk., engl. für \glqq{}Native Development Kit\grqq{})) direkt von Google bezogen und in viele Entwicklungsumgebungen wie beispielsweise Eclipse direkt integriert werden. Seit Mai 2013 stellt Google mit Android Studio eine eigene IDE (Abk., engl. für \glqq{}Integrated Development Enviroment\grqq{}) zur Verfügung \cite[vgl.\ ][]{androidStudioAndroid2016}. +Das Interface kann in Form des Android SDK (Abk., engl. für \glqq{}Software Development Kit\grqq{}) (und ggf.\ des NDK (Abk., engl. für \glqq{}Native Development Kit\grqq{})) direkt von Google bezogen und in viele Entwicklungsumgebungen wie beispielsweise Eclipse direkt integriert werden. Seit Mai 2013 stellt Google mit Android Studio eine eigene IDE (Abk., engl. für \glqq{}Integrated Development Enviroment\grqq{}) zur Verfügung \cite[vgl.\ ][]{androidStudioAndroid2016}. Android trennt bei der Entwicklung sehr stark zwischen dem funktionalen Quellcode und der GUI. Letztere wird in XML-Dateien beschrieben und anschließend mit Funktionen belegt. Zentrale, für die Funktionsfähigkeit der Applikation essentielle Informationen wie beispielsweise Berechtigungen werden dem System mittels des Android-Manifests (ebenfalls in XML) zur Verfügung gestellt \cite[vgl.\ ][]{manifestAndroid2016}. \\ -Der funktionale Anteil der Anwendung wird in Java geschrieben und implementiert die durch das SDK bereitgestellte Grundstruktur in Form des Activity Lifecycles (vgl. Abbildung \ref{fig:activity_lifecycle}). Activities stellen das Herzstück einer Anwendung dar und repräsentieren voneinander unabhängige Benutzerschnittstellen, die in Kombination die Anwendung bilden. Den Activity Lifecycle bildet ein Satz von Callback-Methoden, bestehend aus \lstinline{onCreate()} (Erstmaliges Starten der Activity), \lstinline{onStart()} (Initiierung der Activity), \lstinline{onPause()} (eine andere Applikation kommt in den Vordergrund), onResume() (pausierte Activity läuft weiter), \lstinline{onStop()} (Activity ist nicht länger sichtbar), \lstinline{onDestroy()} (Activity wird beendet oder vom System zerstört) und \lstinline{onRestart()} (Activity wird nach dem Stoppen erneut aufgerufen) und verwaltet den Lebenszyklus der Activity \cite[vgl.\ ][]{activityAndroid2016}. Weiterhin können aus einer Activity Services (über längere Zeit im Hintergrund fungierende Funktionen, bspw. Kommunikation mit einem USB-Gerät), Content Providers (Funktionen, um von mehreren Instanzen verwendete Datenquellen wie bspw. SQLite Datenbanken zu verwalten), Broadcast-Receiver und Handler (Funktionen, die systemweite Nachrichten (sogenannte Intents für Anfragen er Messages für reine Mitteilungen) filtern und je nach Konfiguration bei gewissen Nachrichten Aktionen auslösen) oder andere Activities aufgerufen werden. +Der funktionale Anteil der Anwendung wird in Java geschrieben und implementiert die durch das SDK bereitgestellte Grundstruktur in Form des Activity Lifecycles (vgl.\ Abbildung \ref{fig:activity_lifecycle}). Activities stellen das Herzstück einer Anwendung dar und repräsentieren voneinander unabhängige Benutzerschnittstellen, die in Kombination die Anwendung bilden. Den Activity Lifecycle bildet ein Satz von Callback-Methoden, bestehend aus \lstinline{onCreate()} (Erstmaliges Starten der Activity), \lstinline{onStart()} (Initiierung der Activity), \lstinline{onPause()} (eine andere Applikation kommt in den Vordergrund), onResume() (pausierte Activity läuft weiter), \lstinline{onStop()} (Activity ist nicht länger sichtbar), \lstinline{onDestroy()} (Activity wird beendet oder vom System zerstört) und \lstinline{onRestart()} (Activity wird nach dem Stoppen erneut aufgerufen) und verwaltet den Lebenszyklus der Activity \cite[vgl.\ ][]{activityAndroid2016}. Weiterhin können aus einer Activity Services (über längere Zeit im Hintergrund fungierende Funktionen, bspw. Kommunikation mit einem USB-Gerät), Content Providers (Funktionen, um von mehreren Instanzen verwendete Datenquellen wie bspw. SQLite Datenbanken zu verwalten), Broadcast-Receiver und Handler (Funktionen, die systemweite Nachrichten (sogenannte Intents für Anfragen er Messages für reine Mitteilungen) filtern und je nach Konfiguration bei gewissen Nachrichten Aktionen auslösen) oder andere Activities aufgerufen werden. \\ \\ Neben der klassischen Programmierung in Java bietet das NDK weiterhin die Option, Elemente nativen Codes mittels des Java Native Interfaces zu implementieren (siehe Kapitel \ref{jni}). \\ \\ -Die eingängige Struktur des Interface erlaubt es auch weniger erfahrenen Programmierern, Applikationen zu erstellen. Für weiterführende Informationen bzgl. der Programmierung von Android-Applikationen kann die offizielle Dokumentation von Google konsultiert werden unter \url{https://developer.android.com/index.html}. +Die eingängige Struktur des Interface erlaubt es auch weniger erfahrenen Programmierern, Applikationen zu erstellen. Für weiterführende Informationen bzgl.\ der Programmierung von Android-Applikationen kann die offizielle Dokumentation von Google konsultiert werden unter \url{https://developer.android.com/index.html}. \subsection{Warum Android?} @@ -135,7 +135,7 @@ Ferner beinhaltet das Projekt eine Bibliothek für Maschinelles Lernen zur Imple OpenCV bietet dabei C++, C, Python, Java und MATLAB Schnittstellen und unterstützt mit Windows, Linux, Android und Mac OS sämtliche großen Betriebssysteme \cite[vgl.\ ][]{aboutOpenCV}. Genutzt wird die Bibliothek sowohl in Forschungs- und Regierungsprojekten, als auch von renommierten Unternehmen wie Google, Yahoo, Microsoft, Intel, IBM, Sony, Honda und Toyota für Anwendungen wie das Zusammenschneiden von Streetview-Bildern, Detektierung von Einbrüchen in Überwachungssystemen, Navigieren von Roboterbewegungen, Verkehrsüberwachung, Inspektion von Labeln in der Industrie, Rapid Face Detection und Vielem mehr \cite[vgl.\ ][]{aboutOpenCV}. -Für weitere Informationen bzgl. der Programmierung von Bildverarbeitungsprogrammen mit OpenCV sind die Dokumentation des Projekts sowie ausführliche Tutorials zu finden unter \url{http://opencv.org/documentation.html}. +Für weitere Informationen bzgl.\ der Programmierung von Bildverarbeitungsprogrammen mit OpenCV sind die Dokumentation des Projekts sowie ausführliche Tutorials zu finden unter \url{http://opencv.org/documentation.html}. \subsection{Warum OpenCV?} @@ -146,12 +146,12 @@ Weiterhin steht die Bibliothek unter der modifizierten BSD-Lizens und trägt som \section{Java Native Interface} \label{jni} -Das JNI (Abk., engl. für \glqq{}Java Native Interface\grqq{}) dient dazu, nativen Code in eine Java-Appli"=kation zu integrieren oder andersherum (man spricht von einem sogenannten \glqq{}Two-Way-Interface\grqq{}). Das JNI unterstützt dabei sowohl \lstinline{native Bibliotheken} als auch \lstinline{native Appli-} +Das JNI (Abk., engl. für \glqq{}Java Native Interface\grqq{}) dient dazu, nativen Code in eine Java-Appli"=kation zu integrieren oder andersherum. Man spricht von einem sogenannten \glqq{}Two-Way-Interface\grqq{}. Das JNI unterstützt dabei sowohl \lstinline{native Bibliotheken} als auch \lstinline{native Appli-} \lstinline{kationen} \cite[vgl.\ ][S.5]{liang1999}. \begin{itemize} -\item{Das JNI erlaubt es auf Java-Seite, \lstinline{native Methoden} aufzurufen. Der Aufruf innerhalb der Java-Applikation erfolgt dabei nach den gleichen Prinzipien, wie auch eine Java-Methode aufgerufen wird. Im Hintergrund können diese jedoch in jeder nativen Programmiersprache wie beispielsweise C oder C++ geschrieben sein.} -\item{Auf nativer Seite bietet das JNI ein \lstinline{Interface} an, welches die Implementierung einer \lstinline{virtuellen Java-Maschine} in nativen Code erlaubt (siehe Abbildung \ref{fig:diag-jni}). Native Applikationen können dabei Bibliotheken, welche die virtuelle Maschine implementieren, einbinden und somit über das Interface in Java programmierte Elemente aufrufen. So kann beispielsweise eine C++-Instanz von OpenCV den Bildstrom einer mittels Java gesteuerten Kamera abrufen.} +\item{Das JNI erlaubt es auf Java-Seite, \lstinline{native Methoden} aufzurufen. Der Aufruf innerhalb der Java-Applikation erfolgt nach den gleichen Prinzipien, wie auch eine Java-Methode aufgerufen wird. Im Hintergrund können diese jedoch in jeder nativen Programmiersprache wie beispielsweise C oder C++ geschrieben sein.} +\item{Auf nativer Seite bietet das JNI ein \lstinline{Interface} an, welches die Implementierung einer \lstinline{virtuellen Java-Maschine} in nativen Code erlaubt (siehe Abbildung \ref{fig:diag-jni}). Native Applikationen können Bibliotheken, welche die virtuelle Maschine implementieren, einbinden und somit über das Interface in Java programmierte Elemente aufrufen. So kann beispielsweise eine C++-Instanz von OpenCV den Bildstrom einer mittels Java gesteuerten Kamera abrufen.} \end{itemize} \begin{figure}[htbp] @@ -162,16 +162,16 @@ Das JNI (Abk., engl. für \glqq{}Java Native Interface\grqq{}) dient dazu, nativ \end{figure} \pagebreak -Es ist jedoch zu beachten, dass eine Java-Applikation, welche nativen Code mittels JNI integriert, zwei wesentliche Vorteile gegenüber der reinen Java-Entwicklng verliert \cite[vgl.\ ][S.6]{liang1999}: +Es ist jedoch zu beachten, dass eine Java-Applikation, welche nativen Code mittels des JNI integriert, zwei wesentliche Vorteile gegenüber der reinen Java-Entwicklng verliert \cite[vgl.\ ][S.6]{liang1999}: \begin{itemize} \item{Die Applikation kann nicht mehr ohne weiteres in andere Host-Plattformen portiert werden, da der native Anteil jedes mal umgebungsspezifisch neu kompiliert werden muss.} \item{Während Java architekturgemäß durch die zugrundeliegende JVM (Abk., engl. für \glqq{}Java Virtual Machine\grqq{}) eine gewisse Sicherheit mit sich bringt, ist dies für native Sprachen nicht zwangsläufig der Fall und in erster Linie von der Programmierung selbst abhängig.} \end{itemize} -Ausserdem ist das Java Native Interface lediglich dazu in der Lage, native Datentypen zu übertragen. +Ausserdem ist das Java Native Interface lediglich dazu in der Lage, native Datentypen (d.\,h.\ Integer, Double, Char, etc., jedoch z.\,B.\ keine Matrizen) zu übertragen. -Für weitere Informationen bzgl. der einzuhaltenden Form und Semantik bei der Verwendung des JNI siehe beispielsweise \url{http://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html}. +Für weitere Informationen bzgl.\ der einzuhaltenden Form und Semantik bei der Verwendung des JNI siehe beispielsweise \url{http://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html}. \chapter{Entwicklungsumgebung} @@ -355,7 +355,7 @@ Da es je nach Art und Verwendung der Applikation kritisch sein kann, wenn bei Pa Die Funktion \lstinline{onResume()} ist ebenfalls Teil des von Android zur Verfügung gestellten Interfaces und wird jedes Mal aufgerufen, wenn die Applikation aus dem Hintergrund (pausiert) aufgerufen wird und somit wieder in den Vordergrund rückt, sowie nach dem erstmaligen Starten des Programms (siehe Abbildung \ref{fig:activity_lifecycle}). Zunächst wird \lstinline{super.onResume()} aufgerufen, wodurch unter anderem versucht wird, die in onPause() deaktivierte Kamera wieder zu reaktivieren; es ist kein expliziter Aufruf von \lstinline{mOpenCvCameraView.enableView()} notwendig. -Seit Version 6.0 arbeitet Android jedoch mit sogenannten Runtime Permissions, d.h. es ist möglich, einer Anwendung bestimmte Berechtigungen zu geben und zu nehmen, während diese läuft. Daher muss an dieser Stelle zunächst das Level der Distribution der Plattform überprüft werden und, falls dieses größer als 6.0 ist, ob die benötigte Nutzungsberechtigung für die Kamera aktuell immer noch vorliegt. Dies geschieht mittels der ersten if-Abfrage (\lstinline{android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M}) und \lstinline{check-} +Seit Version 6.0 arbeitet Android jedoch mit sogenannten Runtime Permissions, d.\,h.\ es ist möglich, einer Anwendung bestimmte Berechtigungen zu geben und zu nehmen, während diese läuft. Daher muss an dieser Stelle zunächst das Level der Distribution der Plattform überprüft werden und, falls dieses größer als 6.0 ist, ob die benötigte Nutzungsberechtigung für die Kamera aktuell immer noch vorliegt. Dies geschieht mittels der ersten if-Abfrage (\lstinline{android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M}) und \lstinline{check-} \\ \lstinline{SelfPermission(...)}. Liegt keine Berechtigung vor, so muss diese aktiv beim Nutzer mittels \lstinline{requestPermissions(...)} (siehe unten) angefragt werden. Da nach jeder Anfrage einer Berechtigung erneut \lstinline{onResume()} aufgerufen wird, kann mittels der Einführung der Einführung der Counter-Variablen \lstinline{counter_denied} eine Fallunterscheidung, ob bereits eine Abfrage stattgefunden hat, implementiert werden. So wird eine rekursive Endlosschleife vermieden, falls der Nutzer die Berechtigung beim Aufruf nicht geben möchte. Die zweite if-Abfrage (\lstinline{if (!OpenCVLoader.initDebug()}) führt eine Unterscheidung nach der Art der Implementierung der OpenCV-Bibliothek (vorinstalliert mittels des OpenCV-Managers oder mit der Applikation zusammen installiert) durch und versucht, diese zu reinitialisieren. @@ -387,7 +387,7 @@ Die zweite if-Abfrage (\lstinline{if (!OpenCVLoader.initDebug()}) führt eine Un Die Funktion \lstinline{onRequestPermissionsResult(...)} wird nach Anfragen einer Berechtigung mittels \lstinline{requestPermissions(...)} aufgerufen und kann verwendet werden, um Reaktionen abhängig vom zurückgelieferten Ergebnis zu definieren. Da diese Funktion jedoch bei jeder Anfrage einer beliebigen Berechtigung aktiviert wird, ist zunächst mittels \lstinline{switch(request-} \\ -\lstinline{Code)} eine Fallunterscheidung bzgl. der Art der angefragten Berechtigung durchzuführen; im Falle der in dieser Arbeit behandelten Applikation ist konkret die Nutzungsberechtigung für die Kamera von Bedeutung, welche mittels \lstinline{case REQUEST_CODE_CAMERA_PERMISSION} abgefragt wird. Der erste Eintrag des übergebenen Arrays grantResults entspricht nun dem Ergebnis der Anfrage. Ist die Berechtigung nun also erteilt worden (\lstinline{grantResults[0] ==} +\lstinline{Code)} eine Fallunterscheidung bzgl.\ der Art der angefragten Berechtigung durchzuführen; im Falle der in dieser Arbeit behandelten Applikation ist konkret die Nutzungsberechtigung für die Kamera von Bedeutung, welche mittels \lstinline{case REQUEST_CODE_CAMERA_PERMISSION} abgefragt wird. Der erste Eintrag des übergebenen Arrays grantResults entspricht nun dem Ergebnis der Anfrage. Ist die Berechtigung nun also erteilt worden (\lstinline{grantResults[0] ==} \\ \lstinline{PackageManager.PERMISSION_GRANTED}), so wird \lstinline{counter_denied} zurückgesetzt und die Funktion wird ohne weitere Aktionen verlassen (return). Als Reaktion auf die Anfrage wird erneut \lstinline{onResume()} aufgerufen; da die Berechtigung jedoch erteilt wurde, wechselt die Funktion dieses Mal jedoch direkt zur Initialisierung der OpenCV-Bibliothek. Ist das Ergebnis der Anfrage dagegen negativ, so wird \lstinline{counter_denied} erhöht. Dadurch wird beim Aufruf von \lstinline{onResume()} nach Verlassen von \lstinline{onRequestPermissionsResult(...)} anstatt einer erneuten Abfrage die Applikation mittels \lstinline{onDestroy()} terminiert. @@ -461,9 +461,9 @@ Die Funktion \lstinline{onDestroy()} terminiert wie zu erwarten die Activity. St } \end{lstlisting} -Die Funktion \lstinline{onCameraFrame(...)} ist eine weitere Callback-Methode des von Android bereitgestellten Interfaces. Sie wird jedes Mal aufgerufen, wenn die Kamera ein Bild aufnimmt und bekommt dieses als Übergabeargument in Form eines CvCameraViewFrames übergeben. Zunächst muss auch an dieser Stelle wieder ausgewählt werden, ob im weiteren Verlauf mit einem Farb- oder Graustufenbild gearbeitet werden soll; je nachdem wird das Bild mittels \lstinline{rgba()} oder \lstinline{gray()} von CvCameraViewFrames als Datentyp zu Mat (Abk., kurz für Matrix), einem Datentyp bestehend aus einem Array von Vektoren, welche wiederum die Informationen jedes Pixels des Bilds enthalten (d.h. für Farbbilder die RGB- sowie den Alpha-Anteil und für Graustufenbilder den Weißanteil), konvertiert. +Die Funktion \lstinline{onCameraFrame(...)} ist eine weitere Callback-Methode des von Android bereitgestellten Interfaces. Sie wird jedes Mal aufgerufen, wenn die Kamera ein Bild aufnimmt und bekommt dieses als Übergabeargument in Form eines CvCameraViewFrames übergeben. Zunächst muss auch an dieser Stelle wieder ausgewählt werden, ob im weiteren Verlauf mit einem Farb- oder Graustufenbild gearbeitet werden soll; je nachdem wird das Bild mittels \lstinline{rgba()} oder \lstinline{gray()} von CvCameraViewFrames als Datentyp zu Mat (Abk., kurz für Matrix), einem Datentyp bestehend aus einem Array von Vektoren, welche wiederum die Informationen jedes Pixels des Bilds enthalten (d.\,h.\ für Farbbilder die RGB- sowie den Alpha-Anteil und für Graustufenbilder den Weißanteil), konvertiert. -Da die eigentliche Bildverarbeitung jedoch in \lstinline{openCVFramework.cpp} stattfindet und das JNI, welches als Kommunikationsschnittstelle zwischen Java und C++ fungiert, lediglich native Datentypen unterstützt, muss weiterhin die Matrix zu einem Array aus Bytes umgewandelt werden. Dies geschieht mit \lstinline{jMatToArray(...)} (s. Kapitel \ref{openCVFramework.java}). Das so erhaltene Array wird in jImageDate gespeichert. Schlägt die Umwandlung fehl, z.B. wenn die Bilddaten beschädigt sein sollten, so wirft \lstinline{jMatToArray(...)} eine \lstinline{IOException}, die an dieser Stelle abgefangen wird und mit einem entsprechenden Log-Eintrage zur Terminierung der Applikation führt. Anschließend wird mit \lstinline{process(...)} die eigentliche Bildverarbeitung initiiert. Das in Form des Byte-Arrays übergebene Bild wird per JNI an openCVFramework.cpp weitergeleitet und dort verarbeitet. Standardmäßig ist \lstinline{process(...)} so eingerichtet, dass die Rückgabe in Form eines Double-Arrays erfolgt, so dass beispielsweise Positionen oder Größen von detektierten Objekten übergeben werden können (s. Kapitel \ref{openCVFramework.cpp}). Alternativ ist es auch möglich ein bearbeitetes Bild ebenfalls wieder in Byte-Form zurückzugeben und anschließend anzeigen zu lassen. +Da die eigentliche Bildverarbeitung jedoch in \lstinline{openCVFramework.cpp} stattfindet und das JNI, welches als Kommunikationsschnittstelle zwischen Java und C++ fungiert, lediglich native Datentypen unterstützt, muss weiterhin die Matrix zu einem Array aus Bytes umgewandelt werden. Dies geschieht mit \lstinline{jMatToArray(...)} (s. Kapitel \ref{openCVFramework.java}). Das so erhaltene Array wird in jImageDate gespeichert. Schlägt die Umwandlung fehl, z.\,B.\ wenn die Bilddaten beschädigt sein sollten, so wirft \lstinline{jMatToArray(...)} eine \lstinline{IOException}, die an dieser Stelle abgefangen wird und mit einem entsprechenden Log-Eintrage zur Terminierung der Applikation führt. Anschließend wird mit \lstinline{process(...)} die eigentliche Bildverarbeitung initiiert. Das in Form des Byte-Arrays übergebene Bild wird per JNI an openCVFramework.cpp weitergeleitet und dort verarbeitet. Standardmäßig ist \lstinline{process(...)} so eingerichtet, dass die Rückgabe in Form eines Double-Arrays erfolgt, so dass beispielsweise Positionen oder Größen von detektierten Objekten übergeben werden können (s. Kapitel \ref{openCVFramework.cpp}). Alternativ ist es auch möglich ein bearbeitetes Bild ebenfalls wieder in Byte-Form zurückzugeben und anschließend anzeigen zu lassen. Treten bereits vor der Kommunikation mittels JNI Komplikationen auf, so wirft auch \lstinline{process(...)} eine Fehlermeldung, die ebenso wie bei \lstinline{jMatToArray(...)} zu einer Beendigung der Applikation führt; kommt es zu einem Fehler während der eigentlichen Bildverarbeitung, so liefert \lstinline{openCVFramework.cpp} einen Nullpointer als Rückgabewert zurück, der in einer if-Abfrage abgefangen wird. So kann im Fehlerfall beim Debugging leichter zwischen den Ursachen differenziert werden. @@ -471,7 +471,7 @@ Anschließend an die Verarbeitung besteht die Möglichkeit, weitere Aktionen dur Abschließend wird mittels \lstinline{return} das Bild, welches auf dem Display angezeigt werden soll, in Matrix-Darstellung zurückgegeben. \\ \\ -Standardmäßig ist die Applikation derart eingerichtet, dass einfach das aufgenommene Bild in Graustufen-Form dargestellt wird. Wurde das Bild im Rahmen der Anwendung jedoch verändert (z.B. indem bestimmte detektierte Objekte eingerahmt wurden), so kann an dieser Stelle auch die modifizierte Variante übergeben werden. Es ist jedoch anzumerken, dass es rechentechnisch sehr aufwendig ist, das an die Bildverarbeitung übergebene Bild dort zu verändern, innerhalb von \lstinline{openCVFramework.cpp} wieder von einer Matrix in ein Byte-Array umzuwandeln, anschließend per JNI zurückzugeben und erneut zu einer Matrix zu konvertieren. Daher ist es aus Performanz-Gründen zu empfehlen, falls möglich lediglich die Detektion der Objekte im Bild in der Verarbeitung auszuführen, deren Positionen anschließend zurückzugeben und auf Java-Seite direkt in das Bild einzuzeichnen (auch wenn dort ohne die Einbindung einer weiteren externen Bibliothek lediglich triviale Aktionen zur Verfügung stehen). +Standardmäßig ist die Applikation derart eingerichtet, dass einfach das aufgenommene Bild in Graustufen-Form dargestellt wird. Wurde das Bild im Rahmen der Anwendung jedoch verändert (z.\,B.\ indem bestimmte detektierte Objekte eingerahmt wurden), so kann an dieser Stelle auch die modifizierte Variante übergeben werden. Es ist jedoch anzumerken, dass es rechentechnisch sehr aufwendig ist, das an die Bildverarbeitung übergebene Bild dort zu verändern, innerhalb von \lstinline{openCVFramework.cpp} wieder von einer Matrix in ein Byte-Array umzuwandeln, anschließend per JNI zurückzugeben und erneut zu einer Matrix zu konvertieren. Daher ist es aus Performanz-Gründen zu empfehlen, falls möglich lediglich die Detektion der Objekte im Bild in der Verarbeitung auszuführen, deren Positionen anschließend zurückzugeben und auf Java-Seite direkt in das Bild einzuzeichnen (auch wenn dort ohne die Einbindung einer weiteren externen Bibliothek lediglich triviale Aktionen zur Verfügung stehen). \subsection{openCVFramework.java} \label{openCVFramework.java} @@ -549,7 +549,7 @@ Ist sind die Parameter in Ordnung wird anschließend ein Byte-Array erzeugt und image, int r, int c, int ch, int d); \end{lstlisting} -Die Funktionen \lstinline{process(...)} und \lstinline{nativeImageProcession(...)} stellen die Implementierung des JNIs auf Java-Seite dar. Erstere Funktion überprüft zunächst, ob ob eine valide (d.h. ungleich \lstinline{null}) Datenstruktur übergeben wird und ruft, falls nicht, \lstinline{nativeImageProcession } +Die Funktionen \lstinline{process(...)} und \lstinline{nativeImageProcession(...)} stellen die Implementierung des JNIs auf Java-Seite dar. Erstere Funktion überprüft zunächst, ob ob eine valide (d.\,h.\ ungleich \lstinline{null}) Datenstruktur übergeben wird und ruft, falls nicht, \lstinline{nativeImageProcession } \lstinline{(...)} mit dem übergebenen Bild und den zugehörigen Eigenschaften auf, wodurch der Aufwand zur Verwendung der Funktion reduziert wird. Das Schlüsselwort \lstinline{native} in der Deklaration von \lstinline{nativeImageProcession(...)} signalisiert, dass es sich um eine über das JNI aufgerufene Funktion handelt und erlaubt es dem Interface, die Verknüpfung mit der Bibliothek \lstinline{openCVFramework.h} herzustellen. Standardmäßig wird von der in openCVFramework.cpp implementierten Funktion ein Double-Array über das JNI zurückgeliefert, wodurch Positionen oder Größen von detektierten Gegenständen übergeben werden können. Kommt es während der Bildverarbeitung jedoch zu einem Fehler, so wird ein Nullpointer übergeben. @@ -635,7 +635,7 @@ Die Klasse \lstinline{openCVFramework.cpp} bildet beeinhaltet die eigentliche Bi jrows, jint jcolumns, jint jchannels, jint jdepth){ \end{lstlisting} -Damit das JNI den Bezug von der der nativen Funktion zu der Bibliothek und dadrüber zu deren Implementation in Java herstellen kann, ist es nötig, dass die native Klasse den selben Namen hat, wie die Java-Klasse, in der die Funktion aufgerufen wird, d.h. wenn die Java-Klasse \lstinline{openCVFramework.java} heißt, muss der Name des nativen Äquivalents \lstinline{openCVFramework.cpp} sein. Der Funktionsaufruf der nativen Funktion selbst muss nun demjenigen aus \lstinline{org_opencv_openCVFramework.h} gleichen, damit die Referenz zu der Bibliothek aufgelöst werden kann. Das Schlüsselwort \lstinline{JNIEXPORT} zeigt an, dass der nachfolgende Datentyp (in diesem Fall jdoubleArray) zurückgegeben wird; \lstinline{JNICALL} bedeutet, dass die Funktion über das JNI aufgerufen wird. +Damit das JNI den Bezug von der der nativen Funktion zu der Bibliothek und dadrüber zu deren Implementation in Java herstellen kann, ist es nötig, dass die native Klasse den selben Namen hat, wie die Java-Klasse, in der die Funktion aufgerufen wird, d.\,h.\ wenn die Java-Klasse \lstinline{openCVFramework.java} heißt, muss der Name des nativen Äquivalents \lstinline{openCVFramework.cpp} sein. Der Funktionsaufruf der nativen Funktion selbst muss nun demjenigen aus \lstinline{org_opencv_openCVFramework.h} gleichen, damit die Referenz zu der Bibliothek aufgelöst werden kann. Das Schlüsselwort \lstinline{JNIEXPORT} zeigt an, dass der nachfolgende Datentyp (in diesem Fall jdoubleArray) zurückgegeben wird; \lstinline{JNICALL} bedeutet, dass die Funktion über das JNI aufgerufen wird. \begin{lstlisting}[caption=Konvertierung der Java-Datentypen zu nativen Datentypen] Mat src, src_gray; @@ -658,7 +658,7 @@ Damit das JNI den Bezug von der der nativen Funktion zu der Bibliothek und dadr } \end{lstlisting} -Da die Speicherstruktur der Datentypen in Java sich teilweise von derjenigen in C++ unterscheidet, muss zunächst eine Konvertierung vorgenommen werden, um anschließend die Daten verwenden zu können. Das JNI stellt dafür die Datentypen jint, jbyteArray, etc. für die von Java übergebenen Argumente sowie Funktionen zur Umwandlung wie \lstinline{GetByte-} +Da die Speicherstruktur der Datentypen in Java sich teilweise von derjenigen in C++ unterscheidet, muss zunächst eine Konvertierung vorgenommen werden, um anschließend die Daten verwenden zu können. Das JNI stellt dafür die Datentypen jint, jbyteArray, etc.\ für die von Java übergebenen Argumente sowie Funktionen zur Umwandlung wie \lstinline{GetByte-} \lstinline{ArrayElements(...)} zur Verfügung. \begin{lstlisting}[caption=Wiederherstellung der Bildmatrix aus dem übergebenen Array] @@ -767,7 +767,7 @@ Jede Android-Applikation benötigt ein Android-Manifest. In diesem werden dem Sy \end{lstlisting} Die mindestens benötigte Android-Version orientiert sich dabei an den in der Applikation verwendeten Features. } -\item{Die Grundeigenschaften der Applikation wie Name und Icon sowie die einzelnen Bestandteile wie Activities, Services, Intent-Filter, etc. und ordnet diese einander zu: +\item{Die Grundeigenschaften der Applikation wie Name und Icon sowie die einzelnen Bestandteile wie Activities, Services, Intent-Filter, etc.\ und ordnet diese einander zu: \begin{lstlisting}[caption=Aufbau der Applikation] <application @@ -844,7 +844,7 @@ Ein Layout definiert die visuelle Strukturierung eines User-Interfaces wie beisp \item{Alternativ können die visuellen Elemente bei Ausführung der Anwendung initialisiert werden. Dazu können in der Applikation selbst sogenannte Views erstellt werden.} \end{itemize} -Wichtig ist dabei, dass neben einem übergeordneten Layout, in dem sozusagen globale (d.h. für die ganze Applikation gültige) Parameter deklariert werden, ein Layout für jedes erstellte User Interface angelegt werden muss. Im Falle des Frameworks sind dies die Dateien \lstinline{activity_openCV.xml} und \lstinline{openCVFramework_surface_view.xml}. Die Dateien sind grundsätzlich selbsterklärend, da für die Erstellung des Frameworks auf weitere Anpassungen des Layouts verzichtet und stattdessen die Parameter automatisch von der nächsten übergeordneten Instanz, d.h. vom Betriebssystem bezieht und sich ansonsten an der Standard-Displayauflösung des Mobilgeräts orientiert. +Wichtig ist dabei, dass neben einem übergeordneten Layout, in dem sozusagen globale (d.\,h.\ für die ganze Applikation gültige) Parameter deklariert werden, ein Layout für jedes erstellte User Interface angelegt werden muss. Im Falle des Frameworks sind dies die Dateien \lstinline{activity_openCV.xml} und \lstinline{openCVFramework_surface_view.xml}. Die Dateien sind grundsätzlich selbsterklärend, da für die Erstellung des Frameworks auf weitere Anpassungen des Layouts verzichtet und stattdessen die Parameter automatisch von der nächsten übergeordneten Instanz, d.\,h.\ vom Betriebssystem bezieht und sich ansonsten an der Standard-Displayauflösung des Mobilgeräts orientiert. Weiterhin ist zu erwähnen, dass, falls im Android-Manifest ein Icon definiert wurde, die zugehörige Bilddatei ebenfalls im \lstinline{res}-Ordner in den \lstinline{drawable-XXX}-Verzeichnissen abgelegt werden muss. @@ -888,7 +888,7 @@ Anmerkung: Da die USB-Kommunikation in Kapitel \ref{usb} seperat betrachtet wird final static IMG_HEIGHT = 240; \end{lstlisting} -Wie auch in dem zugrunde liegenden Framework wurde sowohl die Möglichkeit, Farbbilder als auch Graustufenbilder zu verarbeiten implementiert. Da die Natur der Anwendung jedoch eine möglichst hohe Echtzeitfähigkeit (d.h. in diesem Falle einfach möglichst viele Bildverarbeitungszyklen pro Zeitintervall) fordert, wurde die Priorität an dieser Stelle klar auf möglichst geringen Rechenaufwand gelegt und standardmäßig Graustufen als Format gewählt. Die Auflösung sollte für die beste Performanz möglichst so gering eingestellt werden, dass der als Landeplatz dienende Kreis aus der durchschnittlichen Flughöhe gerade noch so detektiert wird. +Wie auch in dem zugrunde liegenden Framework wurde sowohl die Möglichkeit, Farbbilder als auch Graustufenbilder zu verarbeiten implementiert. Da die Natur der Anwendung jedoch eine möglichst hohe Echtzeitfähigkeit (d.\,h.\ in diesem Falle einfach möglichst viele Bildverarbeitungszyklen pro Zeitintervall) fordert, wurde die Priorität an dieser Stelle klar auf möglichst geringen Rechenaufwand gelegt und standardmäßig Graustufen als Format gewählt. Die Auflösung sollte für die beste Performanz möglichst so gering eingestellt werden, dass der als Landeplatz dienende Kreis aus der durchschnittlichen Flughöhe gerade noch so detektiert wird. \begin{lstlisting}[caption=Implementierung von onCameraFrame] // Called on every frame received from the input - stream of @@ -982,12 +982,12 @@ Wie auch in dem zugrunde liegenden Framework wurde sowohl die Möglichkeit, Farb } \end{lstlisting} -Die konkrete Implementation von \lstinline{onCameraFrame(...)} sieht vor, dass nach der eigentlichen und Kreisdetektion durch \lstinline{HoughCircleTransformation.cpp} (vgl. Kapitel \ref{implementationKreisdetektion}) zunächst überprüft wird, ob überhaupt Kreise und somit potentielle Landeplätze gefunden wurden (\lstinline{jImageDataCircels.length > 0}). Ist dies der Fall, so wird mit Hilfe der Funktion \lstinline{calculate-} +Die konkrete Implementation von \lstinline{onCameraFrame(...)} sieht vor, dass nach der eigentlichen und Kreisdetektion durch \lstinline{HoughCircleTransformation.cpp} (vgl.\ Kapitel \ref{implementationKreisdetektion}) zunächst überprüft wird, ob überhaupt Kreise und somit potentielle Landeplätze gefunden wurden (\lstinline{jImageDataCircels.length > 0}). Ist dies der Fall, so wird mit Hilfe der Funktion \lstinline{calculate-} \\ -\lstinline{NearestCircle(...)} (vgl. Kapitel \ref{implementationHoughCircleTransformationJava}) der Kreis, welcher sich am nächsten zum Bildmittelpunkt befindet, ermittelt und zurückgegeben. Somit wird verhindert, dass bei mehreren Einträgen des Arrays \lstinline{jImageDataCircles} immer nur der erste und damit bedingt durch die Natur des Suchalgorithmus der am weitesten links oben im Bild angeordnete Kreis verwendet wird. Die derart erhaltenen Koordinaten werden im Anschluss an den PID-Regler (vgl. Kapitel \ref{pid}) übergeben, der wiederum auf dieser Basis die Stellgrößen anpasst. Diese werden mittels \lstinline{get_actuating_variables()} ausgelesen, auf einen Wertebereich von 0 bis 255 umgerechnet (Wertebereich eines Bytes; notwendig, damit bei der Konvertierung von Double zu Byte keine Informationen verloren gehen), und per \lstinline{write(...)} über die USB-Schnittstelle ausgegeben. Wichtig ist, dass sowohl in x- als auch in y-Richtung ein fester Offset von 127 auf die Ausgabegrößen beaufschlagt werden muss, da diese sich um 0 herum bewegen, der Flugcontroller jedoch Werte um 127 herum erwartet. +\lstinline{NearestCircle(...)} (vgl.\ Kapitel \ref{implementationHoughCircleTransformationJava}) der Kreis, welcher sich am nächsten zum Bildmittelpunkt befindet, ermittelt und zurückgegeben. Somit wird verhindert, dass bei mehreren Einträgen des Arrays \lstinline{jImageDataCircles} immer nur der erste und damit bedingt durch die Natur des Suchalgorithmus der am weitesten links oben im Bild angeordnete Kreis verwendet wird. Die derart erhaltenen Koordinaten werden im Anschluss an den PID-Regler (vgl.\ Kapitel \ref{pid}) übergeben, der wiederum auf dieser Basis die Stellgrößen anpasst. Diese werden mittels \lstinline{get_actuating_variables()} ausgelesen, auf einen Wertebereich von 0 bis 255 umgerechnet (Wertebereich eines Bytes; notwendig, damit bei der Konvertierung von Double zu Byte keine Informationen verloren gehen), und per \lstinline{write(...)} über die USB-Schnittstelle ausgegeben. Wichtig ist, dass sowohl in $x$- als auch in $y$-Richtung ein fester Offset von 127 auf die Ausgabegrößen beaufschlagt werden muss, da diese sich um 0 herum bewegen, der Flugcontroller jedoch Werte um 127 herum erwartet. \\ \\ -Anmerkung: Der PID-Regler arbeitet threadbasiert. Um Nebenläufigkeitskomplikationen auszuschließen, ist es daher notwendig, beim Zugriff auf die Stellgrößen eine einmalige lokale Kopie dieser anzulegen und im Anschluss mit dieser Kopie zu arbeiten, anstatt sowohl für x- als auch für y-Richtung jeweils einzeln \lstinline{get_actuating_variables()} aufzurufen. Sonst läuft man Gefahr, dass die Stellgrößen zwischen dem ersten und dem zweiten Zugriff aktualisiert wurden und die beiden ausgelesenen Werte nicht mehr miteinander korrelieren. +Anmerkung: Der PID-Regler arbeitet threadbasiert. Um Nebenläufigkeitskomplikationen auszuschließen, ist es daher notwendig, beim Zugriff auf die Stellgrößen eine einmalige lokale Kopie dieser anzulegen und im Anschluss mit dieser Kopie zu arbeiten, anstatt sowohl für $x$- als auch für $y$-Richtung jeweils einzeln \lstinline{get_actuating_variables()} aufzurufen. Sonst läuft man Gefahr, dass die Stellgrößen zwischen dem ersten und dem zweiten Zugriff aktualisiert wurden und die beiden ausgelesenen Werte nicht mehr miteinander korrelieren. \section{HoughCircleTransformation.java} \label{implementationHoughCircleTransformationJava} @@ -1073,22 +1073,22 @@ Um die extrahierten Daten anschließend wieder über das JNI an \lstinline{VBLSA Wie bereits in Kapitel \ref{vblsAufbau} beschrieben, verfügen Android-Mobilgeräte standardmäßig nicht über die Möglichkeit, als Host gegenüber anderen USB-Geräten zu fungieren. Für diesen Zweck stellt das Betriebssystem das sogenannte Open Accessory zur Verfügung \cite[vgl.\ ][S.199ff.]{schwark2016}. Dabei simuliert das Android dem angeschlossenen USB-Gerät, der Host zu sein, obwohl in Realität letzteres die Host-Funktion übernimmt. Da diese Funktionalität jedoch bisher nur in wenigen Chips von FTDI integriert und damit sehr unflexibel hinsichtlich der Gerätekompabilität. -Alternativ zu Open Accessory besteht die Möglichkeit, eine von mehreren zur Verfügung stehenden Bibliotheken inklusive Treibern für die anzusprechenden Endgeräte in die Applikation zu integrieren. Von zentraler Wichtigkeit bei der Auswahl der passenden Bibliothek ist deren Lizenz. Um der in der Zielsetzungen des Projekts (s. Kapitel \ref{ziel}) geforderte möglichst einfache Zugänglichkeit zu gewährleisten, ist es wichtig, ein Projekt unter einer Open Source Lizenz auszuwählen. Von technischer Seite aus sollte besonderes Augenmerk auf die Flexibilität bzgl. der USB-Chips, die jede der Bibliotheken unterstützt, gelegt werden, um somit eine möglichst große Anzahl an Endgeräten unterstützen zu können. Weiterhin ist es wichtig, dass asynchrone Kommunikation unterstützt wird, um die Applikation nicht unnötig zu verlangsamen (die Bildverarbeitung im UI-Thread kann weiter stattfinden, während der USB-Thread kommuniziert). Zuletzt ist eine gute Dokumentation und Verständlichkeit der Bibliothek wichtig, um die Implementierung einfach und korrekt durchführen zu können. +Alternativ zu Open Accessory besteht die Möglichkeit, eine von mehreren zur Verfügung stehenden Bibliotheken inklusive Treibern für die anzusprechenden Endgeräte in die Applikation zu integrieren. Von zentraler Wichtigkeit bei der Auswahl der passenden Bibliothek ist deren Lizenz. Um der in der Zielsetzungen des Projekts (s. Kapitel \ref{ziel}) geforderte möglichst einfache Zugänglichkeit zu gewährleisten, ist es wichtig, ein Projekt unter einer Open Source Lizenz auszuwählen. Von technischer Seite aus sollte besonderes Augenmerk auf die Flexibilität bzgl.\ der USB-Chips, die jede der Bibliotheken unterstützt, gelegt werden, um somit eine möglichst große Anzahl an Endgeräten unterstützen zu können. Weiterhin ist es wichtig, dass asynchrone Kommunikation unterstützt wird, um die Applikation nicht unnötig zu verlangsamen (die Bildverarbeitung im UI-Thread kann weiter stattfinden, während der USB-Thread kommuniziert). Zuletzt ist eine gute Dokumentation und Verständlichkeit der Bibliothek wichtig, um die Implementierung einfach und korrekt durchführen zu können. \\ \\ Auf Grundlage dieser Kriterien wurde sich für die USB-Serial-Bibliothek von Felipe Herranz, zu finden unter \url{https://github.com/felHR85/UsbSerial}, unter der MIT-Lizens ausgewählt. -\subsection{Implementierung der Bibliothek} +\subsection{Einbindung der Bibliothek} \lstset{language=JAVA} -Bei der Entwicklung von Android-Applikationen wird bzgl. des funktionellen Codes zwischen aktivem Code und Programmabschnitten, die dauerhaft im Hintergrund ablaufen, differenziert; man unterscheidet zwischen Activities und Services. In letztere Kategorie fällt unter anderem auch die USB-Kommunikation mit einem anderen Endgerät. Die Verbindung wird von einem im Hintergrund ablaufenden Service aufrechterhalten, der in einer Activity initiiert und gebunden wird. Dementsprechend lässt sich auch die Implementierung der USB-Serial-Bibliothek in zwei Abschnitte unterteilen: +Bei der Entwicklung von Android-Applikationen wird bzgl.\ des funktionalen Codes zwischen aktivem Code (Activities) und Programmabschnitten, die dauerhaft im Hintergrund ablaufen (Services), unterschieden. In letztere Kategorie fällt auch die USB-Kommunikation mit einem anderen Endgerät. Die Verbindung wird von einem im Hintergrund ablaufenden Service aufrechterhalten, der in einer Activity initiiert und gebunden wird. Dementsprechend lässt sich auch die Implementierung der USB-Serial-Bibliothek in zwei Abschnitte unterteilen: \begin{itemize} \item{Erstellung des Services} \item{Einbindung in die Activity} \end{itemize} -Der Service selbst stellt dabei die eigentliche Implementierung der Bibliothek dar. Die diesem Zweck dienliche Klasse \lstinline{USB_Service.java} orientiert sich stark an der der Bibliothek beiliegenden Beispiel-Implementation (ebenfalls zu finden unter \url{https://github.com/felHR85/UsbSerial}) und ist an dieser Stelle gut dokumentiert; dementsprechend soll an dieser Stelle nicht weiter darauf eingegangen, sondern sich lediglich auf die Integration in \lstinline{VBLSActivity.java} fokussiert werden. Einzig erwähnenswert an dieser Stelle ist, dass mittels der zu Beginn des Services definierten Variable \lstinline{BAUD_RATE} die für die Kommunikation zu verwendende Baud-Rate eingestellt werden kann. +Die der Implemetierung des Services dienliche Klasse \lstinline{USB_Service.java} orientiert sich stark an der der Bibliothek beiliegenden Beispiel-Implementation (ebenfalls zu finden unter \url{https://github.com/felHR85/UsbSerial}) und ist an dieser Stelle gut dokumentiert; dementsprechend soll an dieser Stelle nicht weiter darauf eingegangen, sondern sich lediglich auf die Integration in \lstinline{VBLSActivity.java} fokussiert werden. Einzig erwähnenswert an dieser Stelle ist, dass mittels der zu Beginn des Services definierten Variable \lstinline{BAUD_RATE} die für die Kommunikation zu verwendende Baud-Rate eingestellt werden kann. Anmerkung: Für Nutzer, die neu in der Android-Entwicklung sind, ist es grundsätzlich empfehlenswert, sich die offizielle Dokumentation zu Services unter \url{https://developer.android.com/guide/components/services.html} durchzulesen. @@ -1244,7 +1244,7 @@ Eine weitere Möglichkeit der Kommunikation zwischen Activity und Service besteh \section{PID.java} \label{pid} -Wie bereits in der Zielsetzung (vgl. Kapitel \ref{ziel}) definiert, soll die zu Demonstrationszwecken dienende Applikation zuverlässig einen Landeplatz zu lokalisieren und es dem UAV ermöglichen, sich über diesem zu zentrieren. Da es sich jedoch bei einem UAV im Normalfall um ein träges, nicht mechanisch geführtes System handelt, das weiterhin von Einflüssen umwelttechnischer oder mechanischer Art wie beispielsweise Windböen oder einer ungenauen Kalibrierung der Sensorik betroffen sein kann, ist es für eine sichere Positionierung über dem Mittelpunkt des detektierten Landeplatzes unerlässlich, eine Positionsregelung zu implementieren, um die Fluggeschwindigkeit zu regulieren und starke Überschwinger zu vermeiden. Dies geschieht mittels der Klasse \lstinline{PID.java} in Form eines klassischen PID-Reglers. +Wie bereits in der Zielsetzung (vgl.\ Kapitel \ref{ziel}) definiert, soll die zu Demonstrationszwecken dienende Applikation zuverlässig einen Landeplatz zu lokalisieren und es dem UAV ermöglichen, sich über diesem zu zentrieren. Da es sich jedoch bei einem UAV im Normalfall um ein träges, nicht mechanisch geführtes System handelt, das weiterhin von Einflüssen umwelttechnischer oder mechanischer Art wie beispielsweise Windböen oder einer ungenauen Kalibrierung der Sensorik betroffen sein kann, ist es für eine sichere Positionierung über dem Mittelpunkt des detektierten Landeplatzes unerlässlich, eine Positionsregelung zu implementieren, um die Fluggeschwindigkeit zu regulieren und starke Überschwinger zu vermeiden. Dies geschieht mittels der Klasse \lstinline{PID.java} in Form eines klassischen PID-Reglers. \begin{lstlisting}[caption=Hilfsklasse für Koordinatentupel] // Immutable class to represent a coordinate tuple @@ -1298,8 +1298,8 @@ Da für die Realisierung des Reglers ein threadbasierter Ansatz gewählt wurde u Wie bereits zu Beginn der Sektion angeführt, weist der implementierte Regler in seiner Grundform eine standardmäßige PID-Charakteristik auf. Folglich entsprechen die übergebenen Werte für \lstinline{Kp}, \lstinline{Ki} und \lstinline{Kd} den Koeffizienten für den Proportional-, Integral- und Differentialanteil, sowie \lstinline{set_point_x} und \lstinline{set_point_y} dem Arbeitspunkt. Da sowohl der I-, als auch der D-Anteil eines PID-Reglers zeitabhängig sind, wurde zur Realisierung dieser Funktioalität ein threadbasierter Ansatz gewählt. Die Run-Methode des Threads führt dabei jeweils die Berechnung aus; anschließend schläft der Thread bis zu seinem nächsten Aufruf und gibt belegte Ressourcen frei (\lstinline{sleep(...)}). Mittels \lstinline{dt} kann dabei die Schrittweite bzw. das Zeitintervall, in dem der Regler aufgerufen wird, festgelegt werden (in Millisekunden). -Da nun jedoch sowohl schreibender (auf die Eingangsgrößen) als auch lesender (auf die Stellgrößen) Zugriff aus einem anderen Thread (dem Main-Thread) auf Elemente des Regler-Threads erfolgen soll, ist es notwendig, die betroffenen Objekte threadsicher zu implementieren. Ansonsten kann es zu Nebenläufigkeitsproblematiken kommen, z.B. erster Wert der Stellgröße wird ausgelesen -> Aktualisierung der Stellgröße von Seiten des Reglers -> zweiter Wert wird ausgelesen -> ausgelesene Werte korrelieren nicht miteinander. Zu diesem Zweck werden die betroffenen Elemente als threadsichere Referenzen, sogenannten \lstinline{AtomicRefe-} -\lstinline{rences}, auf Objekte der Klasse \lstinline{Coordinates_Immutable} implementiert. Somit erfolgt der Zugriff auf die Objekte selbst threadsicher und es wird immer auf beide betroffenen Werte (x- und y-Richtung) gleichhzeitig zugegriffen. +Da nun jedoch sowohl schreibender (auf die Eingangsgrößen) als auch lesender (auf die Stellgrößen) Zugriff aus einem anderen Thread (dem Main-Thread) auf Elemente des Regler-Threads erfolgen soll, ist es notwendig, die betroffenen Objekte threadsicher zu implementieren. Ansonsten kann es zu Nebenläufigkeitsproblematiken kommen, z.\,B.\ erster Wert der Stellgröße wird ausgelesen -> Aktualisierung der Stellgröße von Seiten des Reglers -> zweiter Wert wird ausgelesen -> ausgelesene Werte korrelieren nicht miteinander. Zu diesem Zweck werden die betroffenen Elemente als threadsichere Referenzen, sogenannten \lstinline{AtomicRefe-} +\lstinline{rences}, auf Objekte der Klasse \lstinline{Coordinates_Immutable} implementiert. Somit erfolgt der Zugriff auf die Objekte selbst threadsicher und es wird immer auf beide betroffenen Werte ($x$- und $y$-Richtung) gleichhzeitig zugegriffen. \begin{lstlisting}[caption=Lesender und schreibender Zugriff auf threadsichere Objekte] // Gets the actual actuating variable @@ -1468,7 +1468,7 @@ Anhand von Abbildung \ref{fig:pic-quad-12} kann der schichtweise Aufbau des Test \item{Arduino-Leonardo-kompatibler Olimexino 32u4 mit eigens angefertigter Adapterplatine, um die Verdrahtung der Komponenten entsprechend den Anforderungen des vibrationsträchtigen Aufbaus sicher zu gestalten (siehe Kapitel \ref{mischer}).} - \item{Der ursprünglich von Herrn Weber im Rahmen eines Vorgängerprojekts konstruierte Quadrocopter mit neu ausgeführter Verdrahtung und Ergänzungen.} + \item{Der ursprünglich von Weber (\cite[vgl.\ ][]{quadrocopterWeber2013}) im Rahmen eines Vorgängerprojekts konstruierte Quadrocopter mit neu ausgeführter Verdrahtung und Ergänzungen.} \item{Akku} \item{Mobiltelefon mit VBLS-Applikation} \end{itemize} @@ -1483,7 +1483,7 @@ Anhand von Abbildung \ref{fig:pic-quad-12} kann der schichtweise Aufbau des Test \section{Mischer} \label{mischer} -Um das UAV außerhalb der autonomen Landeplatzsuche steuern, sowie bei unerwarteten Situationen auch während des autonomen Betriebs manuell in das Flugverhalten eingreifen zu können, ist ein Mischer, der die Eingangssignale der Fernbedienung und die Ausgabedaten des der vorgestellten Applikation miteinander verarbeitet und in ein einheitliches, von dem Flugkontroller des UAVs verstandenes Protokoll konvertiert. Diese Funktionalitäten werden durch den im Rahmen der Veranstaltung \glqq{}Systemtechnik\grqq{} entstandene echtzeitfähige RC-Mischer auf Arduino-Basis realisiert. An dieser Stelle soll daher lediglich auf die Dokumentation dieses eigenständigen Projekts verwiesen werden: +Um das UAV außerhalb der autonomen Landeplatzsuche steuern, sowie bei unerwarteten Situationen auch während des autonomen Betriebs manuell in das Flugverhalten eingreifen zu können, ist ein Mischer notwendig. Dieser hat den Zweck, die Eingangssignale der Fernbedienung und die Ausgabedaten der Applikation miteinander zu verarbeiten und in ein einheitliches, von dem Flugkontroller des UAVs verstandenes Protokoll zu konvertieren. Die angeführten Funktionalitäten werden durch den im Rahmen der Veranstaltung \glqq{}Systemtechnik\grqq{} entstandenen echtzeitfähigen RC-Mischer auf Arduino-Basis realisiert. An dieser Stelle soll daher lediglich auf die Dokumentation dieses eigenständigen Projekts verwiesen werden: \begin{center} \qrcode[height=23mm]{https://gitlab.cvh-server.de/lf.ps/vbls/tree/master/LeonardoMixerIO} @@ -1493,18 +1493,18 @@ Um das UAV außerhalb der autonomen Landeplatzsuche steuern, sowie bei unerwarte \section{Einstellung des Reglers} -Um ein sicheres autonomes Flugverhalten während der Landeplatzdetektion realisieren zu können, ist eine korrekte Parametrierung des Reglers notwendig (vgl. Kapitel \ref{pid}). Zu diesem Zweck muss zunächst die Art des betrachteten Systems bestimmt werden. Dies kann beispielsweise durch die Betrachtung der Übergangsfunktion als Antwort auf eine Beaufschlagung des Systems mit einem Sprung des Eingangssignals (in diesem Fall z.B. das Erscheinen eines Kreises am äußeren Rand des betrachteten Bildes) geschehen. Mittels dieser Methode ergibt sich, dass es sich bei dem vorliegenden System, bestehend aus dem Quadrokopter mit dem Steuersignal in x- oder y-Richtung als Eingangs- und dem in diesen Dimensionen zurückgelegtem Weg als Ausgangssignal, um ein IT1-System handelt. Dies entspricht dem erwarteten Verhalten, dass das UAV bei einem Sprung der Steuergröße nach einer Beschleunigungsphase (bedingt durch seine Massenträgheit) eine lineare Änderung der Trajektorie aufweist. +Um ein sicheres autonomes Flugverhalten während der Landeplatzdetektion realisieren zu können, ist eine korrekte Parametrierung des Reglers notwendig (vgl.\ Kapitel \ref{pid}). Zu diesem Zweck muss zunächst die Art des betrachteten Systems bestimmt werden. Dies kann beispielsweise durch die Betrachtung der Übergangsfunktion als Antwort auf eine Beaufschlagung des Systems mit einem Sprung des Eingangssignals (in diesem Fall z.\,B.\ das Erscheinen eines Kreises am äußeren Rand des betrachteten Bildes) geschehen. Mittels dieser Methode ergibt sich, dass es sich bei dem vorliegenden System, um ein IT1-System handelt. D.\,h.\ die Ausgangsgröße, in diesem Fall der zurückgelegte Weg des Quadrocopters in $x$- oder $y$-Richtung, verhält sich mit einer gewissen Anlaufverzögerung integral zur Eingangsgröße, dem Steuersignal in diesen Dimensionen. Dies entspricht dem erwarteten Verhalten, dass das UAV bei einem Sprung des Steuersignals nach einer Beschleunigungsphase (bedingt durch seine Massenträgheit) eine lineare Änderung der Trajektorie aufweist. Um nun dieses Systemverhalten stabilisieren zu können, muss ein PD-Regler verwendet werden. Somit lässt sich bereits an dieser Stelle schlussfolgern, dass der Integral-Anteil des auf Applikationsseite implementierten PID-Reglers wegfallen muss, da dieser ansonsten zu instabilem Verhalten führen würde. Für die passende Parametrierung des Proportional- und Differential-Anteils sind hingegen Tests notwendig. -Zu diesem Zweck wurde im konkreten Fall in der Flugsteuerung des in Kapitel \ref{aufbau} beschriebene Test-Quadrokopter der sog. Angle-Mode (automatische Stabilisierung innerhalb der Ebene) aktiviert und als Landeplatzmarker ein schwarzer Kreis im DIN A4-Format auf weißem Papier gewählt und auf ebenem Untergrund befestigt. Anschließend wurden die Ausgabewerte der Mobilapplikation auf feste Startwerte gesetzt, indem der Versuchaufbau (zunächst nicht im Betrieb) mittig über dem Ziel positioniert, die Kamera abgedeckt und der Kreis entfernt wurde. +Zu diesem Zweck wurde im konkreten Fall in der Flugsteuerung des in Kapitel \ref{aufbau} beschriebene Test-Quadrokopter der sog.\ Angle-Mode (automatische Stabilisierung innerhalb der Ebene) aktiviert und als Landeplatzmarker ein schwarzer Kreis im DIN A4-Format auf weißem Papier gewählt und auf ebenem Untergrund befestigt. Anschließend wurden die Ausgabewerte der Mobilapplikation auf feste Startwerte gesetzt, indem der Versuchaufbau (zunächst nicht im Betrieb) mittig über dem Ziel positioniert, die Kamera abgedeckt und der Kreis entfernt wurde. -Der konkrete Testablauf gestaltete sich insofern, dass das UAV manuell die gesamte Zeit über in einer erfahrungsgemäß geeigneten Höhe für eine zuverlässige Erfassung der vorgesehenen geometrischen Marker gehalten wurde; sobald das Ziel im Erfassungsbereich des Quadrokopters erschien, wurde der autonome Betrieb über den Mischer mittels eines per Potentiometers auf Seiten der Fernsteuerung einstellbaren Faktors hinzugeschaltet. Somit war es möglich, weiterhin in das Flugverhalten einzugreifen, um beispielsweise auf unvorhergesehene Situationen oder unerwünschtes Reglerverhalten zu reagieren. +Der konkrete Testablauf gestaltete sich derart, dass das UAV manuell in einer erfahrungsgemäß geeigneten Höhe für eine zuverlässige Erfassung der vorgesehenen geometrischen Marker gehalten wurde. Sobald das Ziel im Erfassungsbereich des Quadrokopters erschien, wurde der autonome Betrieb über den Mischer mittels eines per Potentiometer auf Seiten der Fernsteuerung einstellbaren Faktors hinzugeschaltet. Somit war es möglich, weiterhin in das Flugverhalten einzugreifen, um beispielsweise auf unvorhergesehene Situationen oder unerwünschtes Reglerverhalten zu reagieren. -Der gesamte Testprozess gestaltete sich iterativ, d.h. nach jedem Test wurden die Ergebnisse evaluiert, die Regel-Parameter angepasst und anschließend erneut getestet. +Der gesamte Testprozess gestaltete sich iterativ, d.\,h.\ nach jedem Test wurden die Ergebnisse evaluiert, die Regel-Parameter angepasst und anschließend erneut getestet. \\ -Wichtig: Für möglichst präzise Testergebnisse sollte von Anfang an darauf geachtet werden, möglichst alle störenden Umwelteinflüsse während den Tests zu eliminieren. So sollte z.B. als Testumgebung ein möglichst großer geschlossener Raum gewählt werden, um den Einfluss der durch das UAV entstehenden Luftverwirblungen zu reduzieren. Ebenfalls sollten Fenster nicht geöffnet werden, um Störungen durch Windböen vorzubeugen. -Weiterhin ist bei Flugbetrieb des UAVs auf die Einhaltung von Sicherheitsmaßnahmen (vgl. beispielsweise \cite[][]{quadrocopterSafety}) zu achten, um Verletzungen und Sachbeschädigungen zu vermeiden. Gerade zu diesem Zweck empfiehlt sich vor allem für ungeübte Piloten auch die Verwendung des Angle-Modes. +Wichtig: Für möglichst präzise Testergebnisse sollte von Anfang an darauf geachtet werden, möglichst alle störenden Umwelteinflüsse während den Tests zu eliminieren. So sollte z.\,B.\ als Testumgebung ein möglichst großer geschlossener Raum gewählt werden, um den Einfluss der durch das UAV entstehenden Luftverwirblungen zu reduzieren. Ebenfalls sollten Fenster nicht geöffnet werden, um Störungen durch Windböen vorzubeugen. +Weiterhin ist bei Flugbetrieb des UAVs auf die Einhaltung von Sicherheitsmaßnahmen (vgl.\ beispielsweise \cite[][]{quadrocopterSafety}) zu achten, um Verletzungen und Sachbeschädigungen zu vermeiden. Gerade zu diesem Zweck empfiehlt sich vor allem für ungeübte Piloten auch die Verwendung des Angle-Modes. \section{Ergebnisse} \label{ergebnisse} @@ -1513,14 +1513,14 @@ Während des iterativen Testverfahrens ließen sich diverse Faktoren feststellen \begin{itemize} \item{Eine statische Befestigung des Mobilgeräts unter dem UAV resultiert in einer Verschiebung des Erfassungsbereichs bei Roll- und Nickbewegungen. Dies hat zur Folge, dass der Kreis z.T. das Bild verlässt (vor allem, wenn er sich im Randbereich befindet oder gerade von außen in den Erfassungsbereich kommt und der Ausschlag des Steuerimpulses als Reaktion darauf hoch ist). \\ - Eine möglich Lösung für dieses Problem bestände in der Bestigung des Mobilgeräts mittels eines Gimbals (Schwenk-Neige-Vorrichtung) oder in der Einberechnung der aus dem Neigewinkel des UAVs resultierenden Verschiebung des Erfassungsbereichs (hierzu wäre einen Erweiterung der bestehende Sensorik um eine absolute Höhenmessung (z.B. per Ultraschall) notwendig; ein Gyroskop bringen sowohl das Mobilgerät als auch der Flugcontroller im Normalfall mit sich).} - \item{Zuweilen kommt es zu Problemen bzgl. der Stromversorgung der Komponenten, was zur Folge hat, dass der Flugcontroller nicht korrekt initialisiert werden kann und es anschließend im Betrieb zu Fehlern bei der Kalibrierung der Sensorik oder dem Verarbeiten der Eingangsdaten des Mischers kommen kann (z.B. alternierender Wert für Throttle (Gas)). Dieses Fehlerbild begründet sich darin, dass das Mobilgerät bedingt durch den verwendeten USB-Treiber (vgl. Kapitel \ref{usb}) als Client und nicht als Host der USB-Verbindung agiert und daher versucht, sich über diese aufzuladen. \\ + Eine mögliche Lösung für dieses Problem bestünde in der Bestigung des Mobilgeräts mittels eines Gimbals (Schwenk-Neige-Vorrichtung) oder in der Einberechnung der aus dem Neigewinkel des UAVs resultierenden Verschiebung des Erfassungsbereichs (hierzu wäre einen Erweiterung der bestehende Sensorik um eine absolute Höhenmessung (z.\,B.\ per Ultraschall) notwendig; ein Gyroskop bringen sowohl das Mobilgerät als auch der Flugcontroller im Normalfall mit sich).} + \item{Zuweilen kommt es zu Problemen bzgl.\ der Stromversorgung der Komponenten, was zur Folge hat, dass der Flugcontroller nicht korrekt initialisiert werden kann und es anschließend im Betrieb zu Fehlern bei der Kalibrierung der Sensorik oder dem Verarbeiten der Eingangsdaten des Mischers kommen kann (z.\,B.\ alternierender Wert für Throttle (Gas)). Dieses Fehlerbild begründet sich darin, dass das Mobilgerät bedingt durch den verwendeten USB-Treiber (vgl.\ Kapitel \ref{usb}) als Client und nicht als Host der USB-Verbindung agiert und daher versucht, sich über diese aufzuladen. \\ Behoben werden kann dies durch das Einhalten der richtigen Reihenfolge des Zuschalten der Stromversorgung für die einzelnen Elemente. Zunächst muss der Flugcontroller ohne angeschlossenes Mobilgerät initialisiert werden (per USB-Verbindung oder direkt über die mit dem Akku verbundenen BECs (Abk., engl. für \glqq{}Battery Eliminator Circuit\grqq{}) der ESCs (Abk., engl. für \glqq{}Electronic Speed Control\grqq{}, regelt die Geschwindigkeit der Motoren des UAVs)). Anschließend kann das Mobilgerät angeschlossen werden. Alternativ könnte diese Problematik behoben werden, indem die unterschiedlichen Funktionalitäten zusammengefasst würden oder der USB-Treiber derartig modifiziert würde, dass das Mobilgerät als Host der USB-Verbindung agiert.} \item{Teilweise interferieren die standardmäßigen Regler des Flugkontrollers mit den Steuersignalen des Reglers des Mobilgeräts. Gibt die Applikation beispielsweise einen starken Nick-Impuls aus, erzeugen die Regler des Controllers einen entgegengesetzten Impuls, um das UAV in Waage zu halten. Diesem Verhalten könnte Abhilfe geschaffen werden, indem die Regler (möglicherweise im Rahmen einer Plattformzusammenfas"=sung/-integration) kombiniert bzw. zusammenfasst werden.} \item{Schlussendlich ist es sehr kompliziert, den Quadrokopter manuell stabil genug in einer halbwegs stationären Höhe über dem Ziel zu positionieren, um die Effekte der Paramtrierung des Reglers evaluieren zu können, solange dieser noch nicht korrekt eingestellt ist. Dieser Prozess erfordert sehr viel Geschick und Übung von Seiten des Piloten und beeinflusst die Güte der Ergebnisse sehr stark, da es gerade bei sanfteren Parametrierungen (geringe Werte für den Proportional-Anteil) schwierig abzuschätzen ist, welche Reaktionen des Fluggeräts dem Regler und welche manuellen Eingriffen des Piloten entstammen.} \end{itemize} -Unter Berücksichtigung der angeführten beeinflussenden Faktoren war es nicht möglich, eine stabile Regelung für die autonome Zentrierung des UAVs über einem gegebenen Landeplatz zu erreichen. Jedoch konnte mittels der erzielten Ergebnisse ein anschaulicher \glqq{}Proof of Concept\grqq{} erbracht und die Funktionsfähigkeit des Gesamtsystems nachgewiesen werden. +Unter Berücksichtigung der angeführten beeinflussenden Faktoren war es nicht möglich, eine stabile Regelung für die autonome Zentrierung des UAVs über einem gegebenen Landeplatz zu erreichen. Jedoch konnte mittels der erzielten Ergebnisse ein anschaulicher Machbarkeitsbeweis erbracht und die Funktionsfähigkeit des Gesamtsystems nachgewiesen werden. Für weitere Optimierung im Rahmen von Folgeprojekten können folgende Werte als Grundlage bzw. Orientierung für die Größenordnung des stabilen Bereichs der Regel-Parameter verwendet werden:\\ \\ \begin{tabular}{ l l } @@ -1533,44 +1533,51 @@ Diese Parameter-Werte bewirken in Kombination mit dem verwendeten RC-Mischer und \chapter{Vergleich Zielsetzung-Endergebnis} -Resümierend lässt sich festhalten, dass die Zielsetzung der Erstellung eines frei zugänglichen und einfach zu verwendenden Frameworks zur Entwicklung von OpenCV gestützten Bildverarbeitungsapplikationen für Android-Plattformen erfüllt wurde. In Kombination mit dem im parallelen Schwesterprojekt entwickelten echtzeitfähigen RC-Mischer auf Arduino-Basis ergibt sich ein modularer Aufbau sämtlicher Hardware- und Software-Komponenten, welcher die geforderte einfache Verwendung unterstützt und potentiellen Nutzern die Erweiterung um bzw. Verwendung von bereits bestehenden Komponenten ermöglicht. Darüber hinaus, war es möglich, beide Aufgabenstellung ausschließlich unter Verwendung von Open-Source-Software umzusetzen, wodurch die freie Zugänglichkeit zu allen Elementen des Projekts gewährleistet wird. +Resümierend lässt sich festhalten, dass die Zielsetzung der Erstellung eines frei zugänglichen und einfach zu verwendenden Frameworks zur Entwicklung von OpenCV gestützten Bildverarbeitungsapplikationen für Android-Plattformen erfüllt wurde. In Kombination mit dem im parallelen Schwesterprojekt entwickelten echtzeitfähigen RC-Mischer auf Arduino-Basis ergibt sich ein modularer Aufbau sämtlicher Hardware- und Software-Komponenten, welcher die geforderte einfache Verwendung unterstützt und potentiellen Nutzern die Erweiterung um bzw. Verwendung von bereits bestehenden Komponenten ermöglicht. Darüber hinaus, war es möglich, beide Aufgabenstellung auf Anwendungsebene (d.\,h.\ zur Erstellung der Applikationen benötigte Bibliotheken, SDKs und Programme, sowie Bootloader (vgl.\ Kapitel \ref{licenses})) ausschließlich unter Verwendung von Open Source-Software umzusetzen, wodurch die freie Zugänglichkeit zu allen Elementen des Projekts bestmöglichst gewährleistet wird. -Ebenfalls konnte mittels der Kombination der angeführten Projekte zu einem Demonstrator in Form eines Quadrokopters mit integrierter autonomer Landeplatzerkennung ein \glqq{}Proof of Concept\grqq{} hinsichtlich der Funktionalität der einzelnen Komponenten bzw. potentieller praktischer Anwendungsmöglichkeiten erbracht werden. Im Rahmen des iterativen Testverfahrens zur Parametrierung des Reglers offenbarten sich jedoch die mechanischen Grenzen des verwendeten Versuchsaufbaus, wodurch sich der Vorgang komplizierter als erwartet gestaltete. In Anbetracht der in Kapitel \ref{ergebnisse} angeführten Herausforderungen besteht daher weiterhin Optimierungspotential hinsichtlich der Realisierung einer stabilen Regelung zur autonome Zentrierung über einem gegebenen Landeplatz. +Ebenfalls konnte mittels der Kombination der angeführten Projekte zu einem Demonstrator in Form eines Quadrokopters mit integrierter autonomer Landeplatzerkennung ein Machbarkeitsbeweis hinsichtlich der Funktionalität der einzelnen Komponenten bzw. potentieller praktischer Anwendungsmöglichkeiten erbracht werden. Im Rahmen des iterativen Testverfahrens zur Parametrierung des Reglers offenbarten sich jedoch die Grenzen des verwendeten Versuchsaufbaus (starre Kamerabefestigung, Regler-Interferenzen, etc.), wodurch sich der Vorgang komplizierter als erwartet gestaltete. In Anbetracht der in Kapitel \ref{ergebnisse} angeführten Herausforderungen besteht daher weiterhin Optimierungspotential hinsichtlich der Realisierung einer stabilen Regelung zur autonome Zentrierung über einem gegebenen Landeplatz. \\ \\ -Zusammenfassend lässt sich sagen, dass die definierten Zielstellungen in weitesten Teilen erfüllt werden konnten. Trotzdem besteht teilweise weiterhin Optimierungspotential (vgl. Kapitel \ref{ausblick}). Unter diesem Gesichtspunkt stellt das Projekt eine gute Grundlage für weiterführende oder eigenständige Projekte in Form der Bildverarbeitung mittels OpenCV auf Android-Plattformen, potentiell kombiniert mit einer Datenausgabe zu angeschlossenen Peripheriegeräten, dar. -\\ -\\ -Was haben wir als Entwickler nun persönlich aus dem Projekt mitgenommen? Neben den rein inhaltlichen Aspekten war es uns möglich, unser Wissen im Bereich der Programmierung mit Java, C und C++ zu vertiefen. Ebenfalls lernten wir den Wert qualitativ hochwertiger Dokumentation (was vor Allem im Bereich der Open-Source-Software keine Selbstverständlichkeit ist) zu schätzen und einen erhöhten Fokus auf die Lizensierung der verwendeten Komponenten und Elemente zu legen. -Weiterhin haben wir gelernt, dass eine stabile Stromversorgung maßgeblich für die Funktionalität der angeschlossenen Komponenten ist und Instabilitäten zu schwierig nachvollziehbaren Fehlerbildern führen können. - -Im Hinblick auf die vermittelten Soft Skills konnten, bedingt durch die Durchführung des Projekts als Gruppenarbeit, die eignenen Kompetenzen in den Bereichen Planung, Teamarbeit und Kommunikation verbessert werden. Vor allem letztere beiden Aspekten wurden durch die kooperative Arbeit mit Versionskontrollsystemen wie dem über den campuseigenen Server zur Verfügung stehenden Gitlab unterstützt bzw. gefördert. - -Der jedoch wahrscheinlich entscheidenste Aspekt, den wir im Verlauf dieser Projektarbeit lernen konnten, ist, wie man im Allgemeinen planungstechnisch an größere Projekte hertritt, diese sinnvoll aufteilt (\glqq{}Top-Down-Ansatz\grqq{} der Softwareentwicklung) und anschließend mit einem agilen Entwicklungsansatz bearbeit. +Zusammenfassend lässt sich sagen, dass die definierten Zielstellungen in weitesten Teilen erfüllt werden konnten. Trotzdem besteht teilweise weiterhin Optimierungspotential (vgl.\ Kapitel \ref{ausblick}). Unter diesem Gesichtspunkt stellt das Projekt eine gute Grundlage für weiterführende oder eigenständige Projekte in Form der Bildverarbeitung mittels OpenCV auf Android-Plattformen, potentiell kombiniert mit einer Datenausgabe zu angeschlossenen Peripheriegeräten, dar. \chapter{Ausblick} \label{ausblick} Hinsichtlich der Optimierung der autonomen Landeplatzlokalisierung auf Grundlage des im Rahmen des dokumentierten Projekts erstellten Frameworks zur Entwicklung von OpenCV gestützten Bildverarbeitungsapplikationen für Android-Plattformen sind im Verlauf der Arbeiten zusätzlich zu den bereits realisierten Funktionalitäten folgende Punkte aufgekommen: -\begin{itemize} +\begin{enumerate} \item{Grundsätzlich besteht weiterhin Potential hinsichtlich der Parametrierung des Reglers auf Seite der Applikation, um eine stabile Zentrierung über dem Landeplatz mit möglichst geringen Überschwingern zu realisieren bzw. zu optimieren. Sollten mechanische Änderungen an dem Versuchsaufbau vorgenommen werden, so ist eine Rekalibrierung der Parameter empfehlenswert um ein gutes Ergebnis zu erzielen. \\ Durch geeignete Modifikationen kann der Anspruch an den Regler weiterhin reduziert werden (beispielsweise durch Verwendung eines Gimbals (s. Punkt drei) oder der Optimierung in den Randbereichen des Erfassungsgebiets (s. Punkt zwei)).} \item{Wie bereits in Kapitel \ref{ergebnisse} angeführt, kann zur Optimierung der Erfassung des Landeplatzes im Randbereich des Bilds die bestehende Sensorik um eine absolute Höhenmessung (beispielsweise mittels Ultraschall) ergänzt werden. \\ Somit könnte in Kombination mit dem bereits auf Seiten der meisten Mobilgeräte und Flugcontroller existierenden Gyroskop aus dem gemessenen Neigungswinkel gegenüber der Ebene und der Höhe die Verschiebung des Erfassungsbereichs bei Neigung des UAVs als Reaktion auf Sprünge der Steuersignale (wenn das Ziel am Rande des Bilds erscheint) ermittelt und mit dem von der Bildverarbeitung ausgegebenen Wert verrechnet werden, um den Regler in diesen Randbereichen zu optimieren und die Störgröße der Neigung zu eliminieren.} \item{Die derzeitige mechanische Konstruktion des Testgeräts (dargestellt in Kapitel \ref{aufbau}) ist derzeit noch insofern suboptimal, dass das kapazitive Display des Mobilgeräts zuweilen durch den darüber liegenden Akku angesprochen und so beispielsweise die Applikation beendet wird. Weiterhin ist dementsprechend das Display an sich nur sehr begrenzt zugänglich, wodurch es erschwert wird, Statusmeldungen zu quittieren. Die Lösung der Befestigung des Geräts am Versuchsaufbau mittels Kabelbindern ist ebenfalls sicherheitstechnisch suboptimal. \\ Insofern wäre eine mechanische Umkonstruktion mit dem Fokus der Neupositionierung des Akkus und des Mobilgeräts, so dass der Bildschirm frei zugänglich ist (potentiell direkt in Kombination mit der Verwendung eines Gimbals zur Bildstabilisierung als Alternative zu zweiterem Punkt), denkbar.} - \item{Derzeit existiert keine Möglichkeit, um den Test-Quadrokopter bei einem potentiellen Versagen des Flugcontrollers oder des RC-Mischers abzuschalten, außer am laufenden System die Stromversorgung zu unterbrechen. Da dies jedoch mit Sicherheits- und Verletzungsrisiken einhergeht, wäre es denkbar, einen drahtlosen Notaus als zusätzliche Sicherheitsinstanz zu implementieren, mittels dem das System \glqq{}remote\grqq{} (aus der Ferne) abgeschaltet werden kann. Wichtig wäre bzgl. der Umsetzung dieser Funktionalität insbesondere der Fokus auf die Echtzeitfähigkeit im Sinne von Rechtzeitigkeit und die Stabilität.} + \item{Derzeit existiert keine Möglichkeit, um den Test-Quadrokopter bei einem potentiellen Versagen des Flugcontrollers oder des RC-Mischers abzuschalten, außer am laufenden System die Stromversorgung zu unterbrechen. Da dies jedoch mit Sicherheits- und Verletzungsrisiken einhergeht, wäre es denkbar, einen drahtlosen Notaus als zusätzliche Sicherheitsinstanz zu implementieren, mittels dem das System \glqq{}remote\grqq{} (aus der Ferne) abgeschaltet werden kann. Wichtig wäre bzgl.\ der Umsetzung dieser Funktionalität insbesondere der Fokus auf die Echtzeitfähigkeit im Sinne von Rechtzeitigkeit und die Stabilität.} \item{Um eine Interferenz der standardmäßigen Regler des Flugcontrollers und der vorgestellten Applikation zu vermeiden, könnten diese zusammengefasst werden, so dass beispielsweise die Steuersignale des Mobilgeräts diejenigen des Controllers während des autonomen Betriebs zu einem gewissen Grad überlagern. Somit könnte diese Störgröße eliminiert und eine einfachere Parametrierung des Reglers auf Applikations-Seite ermöglicht werden. Potentiell wäre es möglich, dies mit einer Fusion der verwendeten Hardware- und Software-Komponenten (s. folgender Punkt) zu verbinden.} - \item{Wie bereits zu Beginn in der Zielsetzung (vgl. Kapitel \ref{ziel}) dargestellt, lag der Fokus dieses Projektes darauf, möglichst einfach verwendbare und frei zugängliche Software zu entwickeln. Dies inkludiert bzw. induziert zwangsläufig einen modularen Aufbau des Systems, so dass potentielle Nutzer möglichst einfach auf ihren bestehenden Komponenten aufbauen können. \\ + \item{Wie bereits zu Beginn in der Zielsetzung (vgl.\ Kapitel \ref{ziel}) dargestellt, lag der Fokus dieses Projektes darauf, möglichst einfach verwendbare und frei zugängliche Software zu entwickeln. Dies inkludiert bzw. induziert zwangsläufig einen modularen Aufbau des Systems, so dass potentielle Nutzer möglichst einfach auf ihren bestehenden Komponenten aufbauen können. \\ Zu Optimierungszwecken wäre es jedoch zielführender, die einzelnen Software- und Hardware-Module zusammenzufassen und auf einer einzigen Platine zu bündeln. Somit könnte das Gewicht und der Stromverbrauch deutlich reduziert und die Kommunikation sowie die mechanische Anbringung am UAV stark vereinfacht werden. Ebenfalls könnten teilweise aufgrunde des modularen Aufbaus redundante Code-Elemente eliminiert werden. Anbieten würde sich für diese Zwecke beispielsweise ein Einplattinencomputer wie der BeagleBone Black, wobei ein Kern rein für die Flugsteuerung und ein weiterer Kern für die restliche Software verwendet werden könnten, um die Echtzeitfähigkeit zu erhalten.} -\end{itemize} +\end{enumerate} Die angeführten Aspekte sollen als Anregung für eigenständige oder auf diesem Projekt aufbauende Folgeprojekte dienen und sind nicht als zwangsläufige Voraussetzung zu sehen, um das erstellte Framework oder die Demoapplikation in ihrer bestehenden Funktion nutzen zu können. Vielmehr dienen sie wie zu Beginn der Sektion angeführt der Optimierung. \printbibliography[heading = bib] \chapter{Anhang} + +\section{Persönliches Fazit} + +Was haben wir als Entwickler nun persönlich aus dem Projekt mitgenommen? Neben den rein inhaltlichen Aspekten war es uns möglich, unser Wissen im Bereich der Programmierung mit Java, C und C++ zu vertiefen. Ebenfalls lernten wir den Wert qualitativ hochwertiger Dokumentation (was vor Allem im Bereich der Open Source-Software keine Selbstverständlichkeit ist) zu schätzen und einen erhöhten Fokus auf die Lizensierung der verwendeten Komponenten und Elemente zu legen. +Weiterhin haben wir gelernt, dass eine stabile Stromversorgung maßgeblich für die Funktionalität der angeschlossenen Komponenten ist und Instabilitäten zu schwierig nachvollziehbaren Fehlerbildern führen können. +\\ +\\ +Im Hinblick auf die vermittelten Soft Skills konnten, bedingt durch die Durchführung des Projekts als Gruppenarbeit, die eignenen Kompetenzen in den Bereichen Planung, Teamarbeit und Kommunikation verbessert werden. Vor allem letztere beiden Aspekten wurden durch die kooperative Arbeit mit Versionskontrollsystemen wie dem über den campuseigenen Server zur Verfügung stehenden Gitlab unterstützt bzw. gefördert. +\\ +\\ +Der jedoch wahrscheinlich entscheidenste Aspekt, den wir im Verlauf dieser Projektarbeit lernen konnten, ist, wie man im Allgemeinen planungstechnisch an größere Projekte hertritt, diese sinnvoll aufteilt (\glqq{}Top-Down-Ansatz\grqq{} der Softwareentwicklung) und anschließend mit einem agilen Entwicklungsansatz bearbeit. + +\newpage \section{Lizenzen} +\label{licenses} + Der im Rahmen dieses Projektes geschaffene Programmcode steht ebenso wie diese Dokumentation unter der Modifizierten BSD Lizenz (\url{https://gitlab.cvh-server.de/lf.ps/vbls/blob/master/common/BSD-MODIFIED.txt}). @@ -1619,8 +1626,10 @@ GNU General Public License Version 2 \\ Proprietär \& Kommerziell \\ \url{http://labs.adobe.com/technologies/eula/lightroom.html}} \end{itemize} + \newpage \section{gitlab-Repository} + Der im Rahmen dieses Projektes entstandene Quellcode sowie die hier vorliegende Dokumentation können über den gitlab-Server des Campus Velbert-Heiligenhaus der Hochschule Bochum bezogen werden.