Wie wir ein Auto mittels WebRTC steuern können
Spätestens seit die Corona-Pandemie angefangen hat, verwenden wir alle WebRTC. Es wird in Teams, Zoom oder in jitsi verwendet, um Videokonferenzen im Browser oder in nativen Apps durchzuführen. Für ein Projekt haben wir evaluiert, ob sich diese Technologie auch für die Steuerung eines Fahrzeugs oder einer Drohne eignet.
WebRTC
WebRTC erlaubt die Übertragung von Bild, Ton und Daten, wird von jedem Browser unterstützt und lässt sich auch in nativen Apps verwenden. Die Protokolle auf denen WebRTC basiert, sind bereits seit über 20 Jahren standardisiert. Dabei werden moderne Videoformate unterstützt und es funktioniert auch hinter Firewalls und in komplexen Netzwerktopologien, wie Mobilfunknetzen, ausgezeichnet.
Die Video- und Audioübertragung findet mittels RTP (Real Time Protocol) statt, welches bereits 1996 in RFC 1889 das erste Mal standardisiert wurde. Dabei werden Video Frames mit einem modernen Codec, meist H.264 oder VP8 kodiert, in Pakete zerlegt und übermittelt. Ein sogenannter De-Jitter-Buffer sorgt auf der Empfangsseite für ein flüssiges Bild und flüssigen Ton. Damit der Verlust von einzelnen Paketen keinen Einfluss auf die Empfangsqualität hat, wird mit einer gewissen Redundanz und FEC (forward error correction), wie wir es von DVDs kennen, gearbeitet.
Die Datenübertragung findet bei WebRTC mittels SCTP (Stream Control Transmission Protocol) statt das 2000 in RFC 2960 standardisiert wurde. SCTP ermöglicht zuverlässige und unzuverlässige Übertragung. Zuverlässige Übertragung braucht man z.B. um Dateien zu übertragen. Der Nachteil der zuverlässigen Übertragung ist, dass Daten, die nicht mehr aktuell sind, immer erneut übertragen werden, was zu Latenz führt. Die unzuverlässige Übertragung ist vor allem dann nützlich, wenn man nur am letzten Zustand interessiert ist und die bisherigen Daten irrelevant werden. Dies ist z.B. bei Games oder bei Steuersignalen der Fall.
Um durch Firewalls und komplexe Netzwerktopologien zu kommen, wird ICE (Interactive Connectivity Establishment) verwendet. ICE wurde 2010 in RFC 5245 standardisiert. Dabei wird im einfachsten Fall eine direkte Verbindung verwendet. Befindet sich ein Client hinter einem Firewall, wird von dem Client hinter dem Firewall versucht eine Verbindung aufzubauen. Befinden sich, wie im mobile Bereich, beide Clients hinter Firewalls, wird mittels STUN (Session Traversal Utilities for NAT) versucht, Löcher in die Firewalls zu schlagen. Dabei senden beide Clients hinter den Firewalls ein UDP Packet an einen STUN-Server. Der STUN-Server sendet die IP/Port kombination der erhaltenen Packete, als Antwort zurück. Damit lernen die Clients ihre Public-IP und ihren Public-Port, somit den internen Zustand der Zuordnungstabelle auf der Firewall. Da die meisten Firewalls die Public-Ports einfach hochzählen, können beide Clients ein UDP Packet an die gelernte Public-IP und den gelernten Public-Port plus eins des anderen Clients schicken. Somit sieht es für beide Firewalls so aus, als sei die Verbindung von ihnen ausgegangen und sie kommt zustande. Schlägt dies auch fehl, kann immer noch eine Verbindung über einen Proxy, einen sogenannten TURN-Server (Traversal Using Relays around NAT), aufgebaut werden.
Wenn man noch weiter in die Details von WebRTC eintauchen möchte, können wir jedem das Buch "High Performance Browser Networking" empfehlen, das auch gratis Online unter hpbn.co verfügbar ist.
Auto
Wir wollten WebRTC nicht für Videokonferenzen verwenden, sondern ein Auto damit steuern. Deshalb bauten wir ein Auto aus folgenden Komponenten:
Raspberry Pi 3 Model B+
Raspberry Pi Camera (Wide Angle)
Akku
Das Motoren- und Servoshield sind dabei über I2C mit dem Raspberry Pi verbunden.
Um das Kamerabild vom Raspberry Pi zu streamen, benutzen wir UV4L (User space Video4Linux), ein Streaming Server speziell für IoT Geräte, welcher über ein Plugin auch WebRTC unterstützt.
Mit dem Stream konnten wir zwar aus der Perspektive des Autos schauen, aber um es zu steuern, müssen wir auch Daten senden. Da wir schon WebRTC verwendeten, konnten wir hierfür die Datenkanäle von WebRTC benutzen. Auf dem Raspberry Pi läuft ein Python-Skript, welches sich mit dem Socket von UV4L verbindet, die Daten ausliest und die Motoren und Servos entsprechend steuert.
Als Steuerungssignale von der App zum Auto werden die gewünschten Geschwindigkeiten für die Motoren an den Rädern, die Winkel der Servos im Greifer und ob ein Ton gewünscht wird übermittelt. Die Räder sind fix angebracht, d.h. um eine Kurve zu fahren, ist es erforderlich die Geschwindigkeit der Motoren einzeln zu steuern.
Von dem Auto bekommen wir den Batteriezustand, den Stromverbrauch und die Temperatur. Bei anderen Tests wurde das Auto mit weiteren Sensoren ausgestattet, so dass eine Positionierung möglich war. Einige Sensoren schlossen wir per USB an den Raspberry Pi an und andere verbanden wir über ein WiFi-Socket. Um die verschiedenen Sockets auszulesen, benutzten wir select, welche die entsprechende Funktion aufrief für diejenigen Daten, welche gerade bereit sind.
Zur Steuerung des Autos wurden zwei Apps entwickelt. Eine native App für iOS und eine Web-App mit React. Beide Apps funktionieren gleich gut. Bei beiden Apps lässt sich das Auto über virtuelle Joysticks steuern und der Videostream und die Telemetriedaten werden angezeigt. Die Joystick-Koordinaten werden in der App in Motorenstärken umgerechnet. Die berechneten Werte werden dann fortlaufend über den Datenkanal ans Auto gesendet, welches die Motoren entsprechend steuert.
Bei der React-App wurde zusätzlich der Support für einen physischen Joystick implementiert. Dazu konnten wir die Gamepad API vom Browser verwenden.
Für die Kodierung der Daten wurde initial CSV verwendet. Da die Daten mit den vielen Erweiterungen unübersichtlich wurden, und neue Daten hinzufügen sehr schwierig war, haben wir im Laufe des Projekts auf Protobuf gewechselt.
Fazit
Mittels WebRTC konnte das Auto für den Proof of Concept gesteuert werden. Die Bildlatenz zwischen Kamera und App-Display lag dabei unter 300 ms, was für unsere Zwecke mehr als ausreicht. Die Technologie wurde anschliessend für ein reales Projekt verwendet, bei der sie sich ebenfalls bewährt hat. Wir denken, das sich mittels WebRTC noch viele weitere spannende Bild- und Steueranwendungen im Browser oder in nativen Apps realisieren lassen.