Umma Hüsla Hackathon 2022

Wie man einen Kartenspiel-Roboter in 26 Stunden baut

Dieses Jahr haben wir wieder am Umma Hüsla Hackathon in Vorarlberg teilgenommen und dabei einen Kartenspiel-Roboter gebaut. Mithilfe dieses Roboters kann ein Spieler, der physisch nicht anwesend ist, dennoch remote an einem Kartenspiel teilnehmen und seine Karten über den Roboter in der Echtwelt ausspielen lassen. Wir zeigen euch, wie wir diesen Roboter umgesetzt haben und noch einige weitere Eindrücke vom Umma Hüsla Hackathon.

Seit 2016 nehmen wir in unterschiedlichen Besetzungen am Umma Hüsla Hackathon teil, dabei haben wir bereits Gürtel gebaut, die vor Diebstahl schützen, Echtwelt-ColorPicker, Kaffeekannen, die erkennen, wann sie leer werden und Freundschaftslampen, die ihre Farbe synchronisieren. Und das alles jeweils in nur 26h. Dabei geht es speziell beim Ummahüsla nicht ums Gewinnen, sondern darum, Kontakte zu knüpfen, Dinge auszuprobieren und einfach Spaß zu haben.

2022 #

Nach 2 Jahren coronabedingter Pause haben wir heuer wieder am Umma Hüsla teilgenommen, in gemischter Besetzung aus Freunden und Bekannten — unter anderem von immerok​.io, hardholz​.at und Zentrum für Lehrer:innenbildung. Der Plan in diesem Jahr war, einen Roboter zu bauen, der es einem Remote-Spieler erlaubt, an einem Kartenspiel (Jass) teilzunehmen, bei dem die anderen 3 Spieler vor Ort mit echten Karten spielen. 

Um in der recht knappen Zeit von ca. 26h einen funktionsfähigen Prototyp zu bauen, ist eine gute Vorbereitung wichtig: Neben einem konkreten Plan müssen auch alle benötigten Hardwareteile besorgt werden.

Der Plan #

Das Projekt haben wir in mehrere kleine Projekte aufgeteilt: 

  • Holzkonstruktion des Roboters 
  • Roboter Logik am RaspberryPi (Karten erkennen und spielen) 
  • Backend
  • Frontend

Jedes der Teammitglieder übernimmt einen dieser Teile und schlägt mögliche Lösungswege vor. Nach einigen Diskussionen wird dann einer der Lösungswege gewählt, wobei wir uns mögliche Erweiterungen offenhalten.

Roboter #

Der Roboter ist ein Holzkasten, der an einen Tisch geklemmt werden kann. Oben sind 9 Fächer für die 9 Spielkarten mit einem Plexiglasboden. Innen befindet sich ein RaspberryPi mit Kamera und 2 LEDs, um die Karten von unten zu beleuchten und aufzunehmen. Außerdem soll mittels 2 Motoren und einem Gummirad die zu spielende Karte auf den Tisch geschoben werden. Sollte Zeit übrig bleiben, würde mittels einer weiteren Kamera das Spielfeld und die ausgespielten Karten registriert werden. 

Roboter Logik #

Mit dem Kameramodul wird ein Bild von den aufliegenden Spielkarten gemacht und dann entweder mittels aufgeklebtem QR-Code oder (wenn es die Zeit zulässt) mittels Bilderkennung (Machine Learning) erkannt, welche Karten auf welcher Position liegen. Die Information, welche Karte wo liegt, wird dann an den Server geschickt. Sobald der Server den Befehl schickt, eine Karte zu spielen, wird die Ausspielmechanik in Position gebracht und das Rad aktiviert werden.

Backend #

Der Server soll mit FastAPI umgesetzt werden und eine REST Schnittstelle bieten, um die platzierten Karten zu registrieren und abzurufen. Als Erweiterungsmöglichkeit gibt es die Möglichkeit, die Client-Verbindungen mittels Websockets umzusetzen. Durch die bidirektionale Kommunikation wäre eine effizientere Kommunikation möglich.

Frontend #

Das Frontend verbindet sich mit dem Server und fragt die derzeit liegenden Karten ab (oder bekommt sie mittels Websocket-Verbindung). Die Karten sollen sortierbar sein und durch das Anklicken einer Karte vom Roboter ausgespielt werden. Gelingt das Auslesen der gespielten Karten, sollen auch diese im User Interface angezeigt werden. Außerdem soll ein zweites Frontend gemacht werden, welches die Möglichkeit bietet, einen Sequenzer mit den aufliegenden Karten zu steuern.

Die Umsetzung #

Stunde 0 — 11 #

Der erste Schritt bei der Umsetzung war, das Design und die Funktionsweise des Roboters zu bestimmen. Dafür wurde am RaspberryPi das Kameramodul aktiviert und der Abstand gemessen, in dem 9 Karten deutlich sichtbar sind. Anschließend wurde der Plan, wie Karten gespielt werden würden, komplett über den Haufen geworden und statt eines beweglichen Motorensystems eine simplere Steuerung mittels 9 Servos entwickelt. Die Konstruktion wurde so umgesetzt, dass jede Karte in einer Tasche” liegt, deren Boden aus Plexiglas besteht und am unteren Ende eine Öffnung hat.

Die gesamte Konstruktion wurde schräg montiert und ein Servo an jeder Öffnung platziert. Sobald eine Karte ausgespielt wird. Dreht sich der Servo und drückt die Karte ein paar Millimeter nach oben, sodass sie nicht mehr in der Tasche liegt und die Schräge hinunter auf den Tisch rutscht. Die 9 Servos wurden dabei von einem Arduino gesteuert, welcher über UART mit dem Raspberry Pi verbunden war und eine Nachricht bekam, sobald eine Karte ausgeworfen werden sollte.

Sobald die grundsätzliche Konstruktion abgeschlossen war, wurden von allen Karten Bilder gemacht: Jede der 36 Karten in jeder Tasche normal und kopfüber mindestens 5 Mal, um genügend Testdaten zu kommen. Mit diesen Bildern wurde das Machine Learning Modell über Nacht trainiert, um am nächsten Tag erkennen zu können, welche Karte in welcher Tasche liegt.

Währenddessen wurde auch der Server mittels FastAPI entwickelt. Dabei standen prinzipiell drei Endpunkte zur Verfügung:

  • card: POST und DELETE um Karten als auf dem Roboter liegend bzw. nicht mehr auf dem Roboter liegend zu markieren
  • deck: GET um die derzeit auf dem Roboter liegenden Karten abzufragen
  • play: POST und GET um eine Karte zum Ausspielen vorzumerken und abzufragen, welche Karte gespielt werden sollte 

Mit diesen Endpunkten wurde das Web-UI entwickelt und die Werte, die vom Roboter kommen sollten, werden vorerst simuliert.

Stunden 12 — 16 #

Auch die motiviertesten Hüsler müssen irgendwann schlafen, daher legten wir uns ein paar Stunden aufs Ohr, um die nächsten Schritte ausgeschlafen angehen zu können.

Stunden 17 — 26 #

Die schlechte Nachricht erreichte uns gleich nach dem Aufstehen. Obwohl unser Modell die Trainingsdaten zuverlässig erkennen konnte, war das bei Testdaten nicht mehr der Fall. Verantwortlich dafür vermutlich eine Mischung aus zu starker Lichteinstrahlung von außen auf den Roboter (wodurch die Karten deutlich anders aussahen als bei den konstanten Lichtverhältnissen am Abend) und zu wenig Licht von innen. Durch die deutlich größeren Dimensionen des Roboters als ursprünglich geplant, reichten die 2 LEDs nicht mehr, um genug Licht zu erzeugen, damit die Karten von unten gut beleuchtet werden können. Daher verbrachten wir die ersten paar Stunden damit, den Roboter gegen Licht von außen abzudichten und machten erste Versuche mit stärkerer Beleuchtung von innen. Gleichzeitig beklebten wir eine Kartenpackung mit QR-Codes, falls die Bilderkennung auch bei besseren Lichtverhältnisse nicht funktioniert.

Während dem Umbau wurde außerdem die Roboter-Logik implementiert, welche als Herzstück folgenden Loop hatte:

while(1):
    current_deck = which_card_where()
    for key, value in current_deck.items():
        if deck[key] != current_deck[key]:
            if value:
                client.post_card(value, key)
            else:
                client.delete_card(key)
    play_card = client.get_play()
    if play_card:
        slot = str(play_card["slot"] - 1)
        arduino.write(str.encode(slot))
        client.delete_card(play_card["slot"])
    sleep(1)

Gegen Ende des Umbaus wurde leider immer klarer, dass wir die Kartenerkennung nicht mehr rechtzeitig zur Präsentation zum Laufen bekommen würden. Aber auch das gehört zu einem Hackathon, dass nicht immer alles gelingt. Bei der Abschlusspräsentation konnten wir dann zumindest zeigen, wie wir über das Web-UI Karten anklicken konnten und diese dann vom Roboter tatsächlich gespielt wurden.

See you next year #

Wie immer war der Umma Hüsla Hackathon ein fantastisches Event, perfekt organisiert vom Verein Plattform für digitale Initiativen. Nächstes Jahr wieder ein Fixpunkt in unserem Kalender und bis dahin basteln wir weiter an unserem Jass Roboter.