MDE for IoT - Digital Twin

“MDE for IoT - Digital Twin” ist ein zweimonatiges Projekt des Christian Doppler Labors for modell-integrierte, smarte Produktion, das Technologien für die modellgetriebene Entwicklung von Produktionssystemen und digitale Zwillinge erprobt. Technologien beinhalten die Simulation von physischen Maschinen, die Verarbeitung von Sensordaten mit CEP und Monitoring und Steuerung mit Webtechnologien.

Code repository: https://github.com/rafaelkonlechner/cdl-pick-and-place

Überblick

Das Szenario und die Simulation beschreiben eine Pick-and-Place-Einheit einer Fertigungsstraße. Diese Einheit besteht wiederum aus drei Komponenten: Roboterarm (6 Freiheitsgrade), Förderband und Prüfstand.

Simulierte Szene: Pick and Place Unit

Die einzelnen Einheiten kommunizieren über MQTT mit dem Server. Der Server speichert die zentrale Abfolgelogik der Anlage und steuert diese mit Befehlen über MQTT. Die Simulation wird von einer Logik kontrolliert, die einen Hardwarecontroller simuliert.

Architekturübersicht

Architektur des vorgestellten Systems

Sensordaten der Pick-and-Place Unit

Folgende Sensoren werden im Szenario berücksichtigt und können über das MQTT-Topic Sensor ausgelesen werden:

Aktuatoren für Pick-and-Place Unit

Folgende Aktuatoren werden unterstützt:

MQTT API

Die MQTT API macht alle Sensoren und Aktuatoren des Roboters nachrichtenbasiert (mit Publish-Subscribe) und unmittelbar — also ohne dazwischenliegende Abstraktionsebene — zugänglich. Der simulierte Hardware-Controller enthält nur die notwendige Logik, um Sensorik und Aktuatoren über die API zugänglich zu machen. Über das Actuator-Topic nimmt er ausschließlich einfache goto-Befehle für alle verfügbaren Rotations- und Linearmotoren entgegen. Somit bleibt die hardwarenahe Controller-Software konzeptionell sehr einfach und wartungsfreundlich. Der Vorteil dieses Ansatzes liegt in der Austauschbarkeit der Ablaufprogramme. Klassische Programme können die Pick-and-Place-Unit ebenso steuern wie modellgetriebene Ansätze, zB. mit Enterprise Architect.

Observation Topics

Zur Feststellung des aktuellen Systemzustandes können folgende Topics für eingehende Daten abonniert werden:

Nachrichtenformat für Sensor-Topic

Nachrichten des Sensor-Topics entsprechen dem JSON-Dateiformat und spezifizieren die sendende Einheit, sowie die gemessenen Daten. Die folgenden Beispiele zeigen je eine Nachricht pro Einheit (entity):

{
	"entity": "RoboticArm",        // Name der Sendeeinheit
	"basePosition": 0.0,           // Neigung d. Basis [-Pi,Pi]
	"mainArmPosition": 0.0,        // Analog für Hauptarm
	"secondArmPosition": 0.0,      // Analog für Vorderarm
	"wristPosition": 0.0,          // Analog für Drehgelenk
	"gripperPosition": 0.0,        // Analog für Greifer
	"handPosition": <0.0,0.0,0.0>, // Position d. Greifers
	"gripperHasContact": false     // Kontaktsensor d. Greifers
}
{
	"entity": "Slider",
	"sliderPosition": 0.0          // x-Koordinate d. Schiebers
}
{
	"entity": "Conveyor",
	"adjusterPosition": 0.0         // x-Koordinate d. Richters
}
{
	"entity": "TestingRig",
	"platformPosition": 0.0         // Neigung d. Plattform
}

Die Sensordaten werden alle ~16 ms versendet und können von einem beliebigen Client ausgelesen werden. Das entsprechende Blender-Script sensors.py wird bei jedem zehnten Frame ausgeführt. Siehe: sensors.py

Control Topics

Folgende Topics sind von der Pick-and-Place-Unit abonniert und können für die Abgabe von Befehlen an die Pick-and-Place Unit genutzt werden:

Nachrichtenformat für Actuator-Topic

Das Nachrichtenformat entspricht einem einfachen Wertepaar [name]-goto value (speed), bei dem zuerst der Aktuator (name) und danach der Zielwert (value) angegeben wird. An die Komponente wird “-goto” als Suffix angefügt. Die Rotationsmotoren des Roboterarms unterstützen außerdem noch die Angabe der Rotationsgeschwindigkeit (speed). Beispiele:

Anlagensteuerung

Die Anlagensteuerung erfolgt über die kontrollierte Abfolge von definierten Zuständen der Anlage.

Zustände

Ein Zustand der Pick-and-Place-Unit setzt sich zusammen aus den Aktuator-Positionen des Roboterarms, der Anzahl der Werkstücke auf dem Fließband (0 oder 1), der Unterscheidung, ob das Werkstück im Aufnahmefenster liegt, oder nicht, der Unterscheidung, ob gerade ein Objekt im Greifer liegt oder nicht, sowie der Position des Schiebereglers und der des Gleichrichters. Im Dashboard sind bereits alle nötigen Zustände zur Aufnahme und Sortierung der Objekte definiert. Zwischen den definierten Zuständen kann beliebig gewechselt werden. Eine Produktion — also das Aufnehmen, Abstellen, Prüfen und Sortieren — entspricht einer geordneten Ausführung einer vorher definierten Zustandsfolge.

Die Klasse Context konsolidiert die Sicht auf alle Zustände. Siehe: Context.kt

Alle Zustände sind in der Klasse States definiert. Siehe States.kt

Automatic-Modus

Mit dem Automatic-Modus können vollständige Durchläufe durchgespielt werden, sofern es zu keinen Ausnahmen oder Fehlern kommt (“Start”-Button im Client drücken). In diesem Modus versucht der Server den aktuellen Zustand der Unit zu erkennen und leitet bei erkennen eines definierten Zustandes den vorgegebenen Folgezustand ein.

Funktionsweise

Über MQTT erhält der Server regelmäßig Sensor-Updates über die jeweiligen Zustände der Einheiten (separat für Roboterarm, Schieber, Förderband und Kameras). Bei jedem Zustandsupdate wird überprüft, ob der Zustand einem definierten Zustand entspricht, oder ob es ein (unbekannter) Zwischenzustand ist. Beispiel: Der Zustand

RoboticArm {
	base: 0.0,
	main_arm: 0.0,
	second_arm: 0.0,
	wrist: 0.0,
	gripper: 0.0
}

entspricht dem bekannten Zustand “Idle” und wird als solcher erkannt. Der Zustand

RoboticArm {
	base: 0.19,
	main_arm: 0.0,
	second_arm: 0.0,
	wrist: 0.0,
	gripper: 0.0
}

ist hingegen unbekannt. Unbekannte Zustände treten beim Übergang zwischen zwei bekannten Zuständen auf. Wurde ein bekannter Zustand erkannt, wird überprüft, ob es für die konsolidierten Zustände (Roboterarm, Schieber, Förderband) einen definierten Folgezustand gibt. Beispiel: Der folgende Zustand beschreibt den Grundzustand, bei dem kein Werkstück auf dem Förderband ist:

RoboticArm: IDLE, Slider: HOME, Conveyor: EMPTY

Der dafür definierte Folgezustand ist:

RoboticArm: IDLE, Slider: PUSH, Conveyor: EMPTY

Nachdem das Werkstück auf das Förderband geschoben wurde, wird die Kamera das Werkstück am Förderband erkennen. Der Zustand wird sich folglich ändern:

RoboticArm: IDLE, Slider: PUSH, Conveyor: OBJECT_DETECTED

Das Regelwerk für definierte Zustandsänderungen ist in der Klasse RobotController definiert. Siehe RobotController.kt

(Anmerkung: Das Pattern-Matching basiert im Moment nur auf Equality-Checks und ist daher sehr wortreich. Entsprechende Vergleichsfunktionen sollen in Zukunft dabei Abhilfe schaffen.)

Kommunikation mit Web-Dashboard und Simulation

Der gesamte Nachrichtenverkehr des Servers (MQTT, Websockets) ist derzeit in der Klasse MessageController.kt definiert. Siehe [MessageController.kt] (https://github.com/rafaelkonlechner/cdl-pick-and-place/blob/master/MQTTServer/src/main/kotlin/at/ac/tuwien/big/MessageController.kt). Für das Tracking der Werkstücke auf den Kamerabildern wird die Library tracking.js verwendet. Diese Library wird derzeit im Web-Client ausgeführt und liefert die Ergebnisse mit Websocket-Messages zurück an den Server. Der Websocket Endpoint /tracking wird für die Objekterkennung am Förderband verwendet. Aus Sicht der Software-Architektur ist das nicht ideal und soll geändert werden. Dafür wurde im Repository das Projekt ObjectTracking angelegt. Es soll später als eigenständiger Service laufen.

REST API

Die Steuerung der Produktionsanlage ist nicht nur durch MQTT-Nachrichten des Servers möglich, sondern auch durch eine REST-API, die der Server zur Verfügung stellt. Über eine REST API können die aktuellen Zustände der einzelnen Einheiten in der Simulation abgefragt und manipuliert werden.

Beispiel:

Um den Zustand einer Einheit – in diesem Fall des Roboterarmes – abzufragen, ist folgender Request über HTTP notwendig:

GET /roboticArm
Host: localhost:8080
accept: application/json

Zurückgeliefert wird ein JSON-Objekt, das den zuletzt erkannten, definierten Zustand beschreibt. Gleichartige Requests können auch für die anderen beiden Einheiten abgesetzt werden.

localhost:8080/all liefert eine Liste aller definierten Zustände. Um einen Zustand zu setzten, wird ein HTTP PUT Request an die jeweilige Ressource abgesetzt.

Soll beispielsweise der Roboterarm in den Zustand Appraoch übergehen, wird folgender Request verwendet:

GET /roboticArm
Host: localhost:8080
accept: application/json
payload: Approach

QR-Codes

Jedes Werkstück ist mit einem QR-Code versehen. Die verwendeten QR-Codes (100 Stück) wurden vorab generiert und werden beim Start der Simulation in geordneter Reihenfolge an die vorhandenen Werkstücke als Textur aufgetragen. Wenn ein Werkstück nach einem erfolgreichen Durchlauf auf die Rampe abgeladen wurde und die Lichtschranke passiert, wird durch die beiden Python-Controller greengate.py und redgate.py ein neues Werkstück erzeugt und in den Puffer legt. Dem Werkstück wird ein neuer QR-Code als Textur zugewiesen.

Generierte QR-Codes: https://github.com/rafaelkonlechner/cdl-digital-twin/tree/master/qr-codes

Das Lesen der QR-Codes erfolgt am Server in der Klasse https://github.com/rafaelkonlechner/cdl-digital-twin/blob/master/MQTTServer/src/main/kotlin/at/ac/tuwien/big/QRCodeReader.kt

Logs

Die geordnete Abfolge von Zuständen kann mit Logs nachvollzogen werden. Rohe Sensordaten aufzuzeichnen würde eine enorme Datenmenge produzieren und wäre analytisch undurchsichtig. Um sinnvolle Logs zu generieren, die Ereignisse adäquat repräsentieren, kann CEP verwendet werden. Logs sollen in der Lage sein, folgende Dinge zu repräsentieren:

Dazu sind ein paar Low-Level Logs notwendig (nicht vollständig):

KPIs

Folgende KPIs könnten für eine Pick-and-Place Unit sinnvoll sein:

CEP

Für das erstellen von hierachischen Sichten auf Events, Zustandsänderungen und Produktionen wird CEP verwendet. Insgesamt soll damit die Sicht auf drei verschiedenen Ebenen möglich sein:

Konzept:

ProductionStream:  - - - - - - - - - - - - - - - - * - - - - >
						 /			
	   					/ Production
StateStream:  - - - - * - - - * - - - - * - - * - - - - >
		     /        /       /      /
	            / Idle   / Grip  / Park / Deposit
SensorStream:      * - * - * - * - * - * - * - * - * - * - * >

In der Klasse EventProcessing.kt (Siehe: EventProcessing.kt) ist bereits eine einfache Query implementiert, die die Zustandsabfolge mit einem Regulären Ausdruck überprüft:

pattern (IDLE APPROACH ARBITRARY* ( DEPOSIT_GREEN RELEASE_GREEN | DEPOSIT_RED RELEASE_RED))

In der Testklasse EventProcessingTest ist eine Beispielabfolge von Events definiert, die an die Engine übergeben wird und ein Match-Event erzeugt.

Cheat Sheet für Keyboard-Shortcuts

Wie man heutzutage einen KUKA Roboter steuert

KUKA Roboter sind mit einem BUS-System mit einer Steuereinheit verbunden. Diese wiederum ist internetfähig. KUKA bietet eine Java-API und eine eigene Entwicklungsumgebung (Sunrise OS) an. Um ein Steuerungsprogramm am Roboter auszuführen, wird das Java-Programm über das Netzwerk auf die Steuereinheit übertragen und schließlich von dieser ausgeführt. Sie bieten auch Schnittstellen für ein- und ausgehende Signale, um die Steuerung mit übergeordneten Steuerungen zu integrieren.

SunriseOS