SlotCountDigiMon

Gestelltes Problem

SlotCountDigiMon ist eine Anzeige-App für die Rundenzähler-App SlotCountDigi.
Diese Rundenzähler-App läuft auf einem Smartphone das oberhalb der Fahrspur fixiert ist.
Das Display dieses Gerätes ist deshalb während eines Rennens kaum für jeden Rennteilnehmer einsehbar.
Es ergibt sich also ein Bedarf nach einer für alle Rennteilnehmer sichtbaren Liveanzeige des Rennverlaufs.
Zum Beispiel auf einem Smartphone, besser noch auf einem Tablet.
Dieser Bedarf wird von SlotCountDigiMon gedeckt.

Programm

SlotcountDigiMon ist also eine App, die sich mit dem Smartphone auf dem SlotCountDigi läuft, per WifiDirect verbindet, die Renndaten erhält und dann anzeigt.

Das sieht dann auf einem Tablet z.B. so aus:

SlotCountDigi auf dem Smartphone erfasst die Fahrzeuge und SlotCountDigiMon zeigt sie an.

Für die Datenverbindung wird Wifi-Direct verwendet. Dies muss auf beiden Geräten aktiviert sein.
Zusätzlich muss noch in den Einstellungen von SlotCountDigi Wifi-Direct aktiviert werden:

Die Apps sollten dann auf beiden Geräten innerhalb von 2 Minuten gestartet werden und finden sich automatisch.
Nach der erfolgreichen Verbindung gibt es einmal das Wifi-Direct-Icon und zusätzlich erfolgt noch eine Ansage des Zählers.

SlotCountDigiMon kann nun aber nicht nur passiv von SlotCountDigi Daten empfangen.
Die App kann die Zählapp in den wichtigsten Funktionen fernsteuern:

Es kann also von SlotCountDigiMon:
– die Fahrzeugkalibrierung gestartet und beendet werden
– die Fahrzeugliste editiert werden (nur in der Pro-Version)
– das Rennen gestartet und dann verfolgt werden

Zum Start eines Rennens wird im Menü bei verbundenem Zähler der Punkt “Rennen starten” gewählt.
Da läuft erst eine Startampel an:

Der Zähler startet nun das Rennen und sendet dann live das aktuelle Klassement.

Hier habe ich schon einen grossen Vorsprung vor Rob und Joe herausgefahren. Von 15 Runden für das Rennen bin ich schon 13 gefahren.
Meine letzte Rundenzeit war 5,2 Sekunden, die schnellste Rennrunde hat Rob mit 2,9 Sekunden in seiner sechsten Runde hingelegt.
In der Pro-Version kann man die Bahnlänge angeben und dann wird aus der Rundenzeit noch die Durchschnittsgeschwindigkeit errechnet.

Irgendwann ist das Rennen zu Ende:

Hier hab’ ich 10 von insgesamt 10 Runden gefahren, das wird durch die Zielflagge angezeigt. Rob liegt 5 Runden zurück und ist nach mir schon durchs Ziel gefahren, Joe steht noch aus, aber er wird eh’ den dritten Platz bekommen.

Kleines Kochfeld (Android)

Gestelltes Problem
Wenn ich kein Feierabend-Projekt habe, dann ist mir langweilig. Da dachte ich mir, man könnte vielleicht eine App machen, die ein Glaskeramikkochfeld emuliert.

Programm
Ich habe mir also mal unser Kochfeld genauer angesehen (und angehört). Die Heizwindungsgrafik ist nicht als Ressource in der App sondern wird beim Start berechnet. Dadurch hat man auf allen Geräte immer ein gut aufgelöstes Bild. Eine Siebensegmentanzeige hatte ich schon für ein anderes Projekt gemacht und konnte sie hier wiederverwenden.

Die Logik für die Betätigung hab’ ich dem Kochfeld abgeschaut, man drückt auf + und – und von 9 per + wieder zur 0. Wenn man auf 0 geht und die Platte noch heiss ist, kommt ein H.

Dann habe ich den Kochfeldregelalgorithmus nachgemacht, also im Original ist das eine Ein/Aus-Regelung. Beim Wechsel zwischen Ein und Aus gibt es zwei verschiedene Geräusche (die habe ich am Kochfeld aufgenommen). Die Temperaturstufe entspricht dann im Prinzip einem Aus/Ein-Tastverhältnis. Wenn die jeweilige Platte gerade auf Ein ist dann wird sie langsam immer heller, auf Aus verdunkelt sie sich allmählich.

Das ist eigentlich recht realistisch geworden:

Msudoku(Android)

Gestelltes Problem
Lange nichts mit anspruchsvollem Algorithmus programmiert. Um zu gucken ob ichs noch kann, entschied ich mich einen Sudoku-Löser für Android zu schreiben. Dieses Mal aber mit einem mehr an die menschliche Denkweise angelehnten Algorithmus.

Programm
Man sieht das Sudoku in der Anzeige und kann die Zellenwerte verändern (die Anzeige könnte man noch etwas aufhübschen, mir war das nicht so wichtig).
Dann kann man für jede Zelle eine Liste von möglichen Kandidaten generieren und anzeigen lassen. Es ist dann möglich sich Tipps geben zu lassen, dabei werden Zellen mit schon bestimmtem Inhalt gelb unterlegt. Für diese Hints werden auch Zweier- und Dreiergruppen bestimmt (wenn also in einem Block zwei Zellen mit den Kandidaten 2/7 und 2/7 vorkommen, dann kann weder 2 noch 7 als Kandidat in den anderen Zellen des Blocks vorkommen).
Schliesslich gibt es auch einen automatischen Lösemodus bei dem das Sudoku komplett gelöst wird. Das ist im Vergleich zu meinem weiter oben beschriebenen Brute-Force-Sudoku sehr schnell. Ich hatte hier bisher die Lösung stets in unter einer Sekunde Rechenzeit. Das alte Programm hat durchaus auch mal 10 Minuten (und das auf einem Desktop) gebraucht.
Es kann jetzt sein dass es ein Sudoku gibt, bei dem die Betrachtung von 3er-Gruppen nicht ausreicht, so dass man dann z.B. 4er-Gruppen ins Programm einbauen oder doch noch eine rekursive Brute-Force-Lösung (die dann aber nur noch auf das schon teilweise gelöste Sudoku angewendet würde und damit schneller wäre als komplett Brute-Force) ergänzen müsste.
Da habe ich aber aktuell garnicht so grosses Interesse weil ich die App an sechs Abenden relativ entspannt ohne grössere Irrwege oder lange Fehlersuchen (und auch ohne Konzept oder Skizzen) runterprogrammieren konnte und damit dann festgestellt habe dass ichs noch kann B-) .

Screenshot:

SlotCountDigi (Android)

Gestelltes Problem

Ich hatte schon eine Slotcar-Rundenzähler-App gemacht, die per Smartphonekamera Runden zählt. Sie war für eine Faller-AMS Rennbahn, bei der jeder Wagen seine eigene Spur hatte.
Da brauchte man nur eine Bewegungserkennung pro Fahrspur zu machen.

Nun bekam ich eine Carrera-Digital Bahn, bei der die Autos die Spur wechseln können. Also wollte ich eine App, die die Fahrzeuge an ihrem Äusseren erkennt.
Da habe ich viele Ansätze verfolgt und bin dann letzten Endes bei der Farbmarkierung gelandet (was macht man sonst, wenn zwei gleiche Fahrzeuge gegeneinander antreten?).

Aufkleber ausgedruckt und auf die Fahrzeuge geklebt:

Und das Smartphone dann mit einem Selfiestick oberhalb der Schiene fixiert:

Programm

Was ich durch die Aufkleber erreichen wollte, war dass die Autos sich farblich unterscheiden. Ich wollte aber keine App, wo man eingibt, wer welche Farbe hat. Das wäre irgendwie unsportlich/zu einfach gewesen. Die App sollte selbst herausfinden, welche Farbe ein Auto hat auch ohne zu wissen welche Aufkleberfarben überhaupt verwendet werden.

Dafür habe ich einen Kalibrierungsmodus gemacht. Man fährt die Autos nacheinander ins Blickfeld der Kamera und bleibt dann stehen.
Die App registriert live die Einfahrt (sagt “Auto rein”) und ermittelt den Ort an dem das Auto zum Stehen kommt (sagt “Auto erkannt”).
Dann schneidet sie das Bild des Autos aus, später im Rennen wird das Bild benutzt um das Auto in Listen auzugeben. Gleichzeitig wird das ausgeschnittene Bild auf die dominierende Farbe geprüft.
Ach, es war nett, das zu Programmieren, im Prinzip hab’ ich da eine Liste von Farbeimern gemacht, wo dann die Pixel des Bildes abgelegt werden und der vollste Eimer ist am Ende die dominierende Farbe. Diese Farbe ist die, nach der später im Rennen live im Kamerabild gesucht wird, um zu prüfen ob das Fahrzeug durchfährt.

Hier mal ein Beispiel, Fahrzeugkalibrierung für drei Fahrzeuge, ein gelbes, ein blaues und ein magentaes:

(Nicht schlecht, oder?)

Hier wird keine Library für Bildverarbeitung verwendet, die App holt sich live Kameraframes und verarbeitet sie in Echtzeit.

Nach dem Kalibrieren kann man dann den Autos die Fahrernamen zuweisen oder falsche Erkennungen löschen:

Nach der Kalibrierung kann SlotCountDigi die Fahrzeuge erkennen.
Es werden Runden gezählt (Im Video sieht man das jeweils aktuelle Klassement)
und Rundenzeiten ermittelt.

Kleines Rennen:

Man muss hier noch anmerken, dass die App nicht einfach im Kamerabild nach den Aufkleberfarben sucht (dann würden die im Bild ausgelegten Aufkleber ja auch stören). Es wird zunächst nach bewegten Fahrzeugen gesucht und dann erst pro Fahrzeugbild nach den Farben.

CasaTest (Android)

Gestelltes Problem
Weil ich meine Heizkörper gern automatisch regeln wollte, hatte ich mir eine Steuerung “CasaControl” der Firma Pearl gekauft. Damit kann man per App Heizkörperventile, Steckdosen und mehr steuern. Mit der vom Hersteller bereitgestellten App war ich nicht so zufrieden, so dass ich lieber selbst eine machen wollte.

Programm
Ist halt eine App, war ein bisschen fummelig herauszufinden wie man die Temperatur- und Schaltbefehle an die Steuerung schickt. Aber dann ging das was ich wollte, nämlich einen Heizkörper auf eine bestimmte Temperatur zu stellen oder eine Funksteckdose ein- und auszuschalten ganz gut.

Screenshot:

SlotCount(Android)

Gestelltes Problem
Ich hatte mich ja schon häufiger mit der Erstellung von Software im Umfeld meiner Faller-Rennbahn beschäftigt. Nachdem ich dann ein Android-Handy hatte, reifte in mir die Idee, dass man vielleicht einen Rundenzähler machen könnte. Die eingebaute Kamera würde die Strecke filmen und erkennen wenn eines der beiden Autos über die Ziellinie fährt.

Programm
Die erforderlichen Elemente hatte ich in irgendeiner Form alle schon einmal gemacht, die Bewegungserkennung, das Ermitteln des Bereichs in dem sich ein Fahrzeug aufhalten kann und auch das Zuordnen einer erkannten Bewegung zu einem der beiden Fahrzeuge. Die Möglichkeiten, die man für die Android-Entwicklung mit Eclipse hat, sind schon recht umfangreich und so kam ich schnell voran.
Mittendrin beschloss ich die Anwendung auch im Android Appstore zu veröffentlichen, was dann noch einigen Zusatzaufwand z.B. für die Internationalisierung bedeutete.
Die Benutzung der Anwendung besteht aus drei Phasen, als Erstes das Einstellen des Erkennungsalgorithmus, Wert für die Empfindlichkeit und die ungefähre Grösse der zu erkennenden Objekte. Dann musste die Anwendung lernen, wo die Fahrzeugspuren verlaufen. Danach konnten dann Rennen gefahren werden. Nachdem die Anwendung gelernt hatte, wo die Spuren verlaufen, durfte das Smartphone nicht mehr bewegt werden, so dass ich sämtliche Abläufe über Sprachausgaben des Handys steuerte.

Screenshots:

Das Menü (englische Version)


Einstellung der Erkennungsparameter. Auf die grüne Anzeige unten Rechts bin ich ein bisschen stolz (Ist alten Tonband-Aussteuerungsröhren nachempfunden). Sie zeigt an den Stellen weiss, wo im Kamerabild eine Bewegung (hier der Bleistift) erkannt wurde.


Nach Abschluss der Spurkalibrierung. Die Rechtecke geben die Bereiche vor, in denen das Fahrzeug detektiert wurde. Die Farbe der Rechtecke ist automatisch aus der Fahrzeugfarbe bestimmt worden. Die Pfeile deuten die erkannte Fahrtrichtung an.

Hier eine Kalibrierung im Video (da war noch ein Bug in der App wodurch die Richtungspfeile gedreht wurden):


Rennview. Es werden für jedes Fahrzeug die Runden gezählt, die Rundenzeit und die schnellste Runde ermittelt. Für den Start gibt es einen Countdown. Dabei werden auf Wunsch auch Fehlstarts erkannt. Wer zuerst die eingestellte Rundenanzahl erreicht, wird als Gewinner ausgerufen. Falls beide Fahrzeuge im gleichen Kamerabild die Ziellinie überqueren, gewinnt der Fahrer, dessen Auto am weitesten ins Kamerabild reingefahren ist.

Hier ein Rennen im Video:

SameGame

Gestelltes Problem
Um 2000 herum stiess ich auf ein Spiel namens “Clickomania”, das ein Klon von SameGame ist. Dabei muss man Gruppen aneinandergrenzender Spielsteine gleicher Farbe “sprengen”. Darüberliegende Steine fallen in die entstandene Lücke und am Ende sollte möglichst kein Stein mehr übrig bleiben. Das machte Spass! Da bei mir immer so viele Steine übrig blieben, grübelte ich schon damals darüber, wie man wohl für eine gegebene Stellung eine optimale Lösung finden könnte. Als ich dann mit den Handyspielen anfing, dachte ich mir, dass es interessant sein könne, einen SameGame-Solver fürs Handy zu schreiben.

Programm
Bevor ich mit dem Solver anfangen konnte, musste ich erst einmal das Spiel selbst programmieren. Das war nicht schwer, deshalb legte ich einen Schwerpunkt auf eine saubere Animation und verschiedene Designs der Spielsteine. Dazu sollte die Anzahl der noch vorhandenen Spielsteine als Siebensegmentanzeige ausgegeben werden. Dafür besorgte ich mir eine technische Zeichnung einer solchen Anzeige und übertrug die Koordinaten der einzelnen Segmente in eine Java-Klasse. Wie immer alles Handarbeit (in den untigen Screenshots aus einem Nokia 6260-Emulator ist die Anzeige etwas zu gross, auf meinem Nokia 6300 ist das besser).

Solver habe ich dann zwei gemacht, erstmal einen dummen, der einfach nur Stellen sucht, wo man klicken kann. Danach dann einen, der für jede anklickbare Gruppe den “Nachher”-Zustand ermittelt und dann zählt wieviele “verwaiste” Steine es gibt. Die Gruppe, bei der die wenigsten Waisen anfallen, wird dann geklickt. Das ist schon recht passabel aber noch nicht optimal.

Screenshots:
   

Minimax

Gestelltes Problem
Für Spiele mit voller Information gibts den MiniMax-Algorithmus. Der Rechner probiert alle möglichen Zugmöglichkeiten aus, mehrere Halbzüge im Voraus und als Mensch verliert man dann. Der Computer ist deswegen nicht intelligent, man kann ihm nur beibringen, gewisse Spiele recht gut zu spielen. Sowas hatte ich schon früher programmiert, dabei aber jedes Spiel für sich. Diesmal sollte es Java sein, fürs Handy und der Findedenbestenzug-Programmteil von den jeweiligen Spielregeln getrennt ausgeführt werden. Ausserdem sollten die Züge animiert werden.

Programm
Ich weiss nicht, wie andere Leute Programmieren, aber bei mir ists so, dass ich eigentlich von Fehler zu Fehler stolpere. Man schreibt den Code und dann hauts nicht hin, das geht mir dann im Kopf rum, warum geht das nicht, kann doch eigentlich nicht sein. Kann aber doch sein, und wenn ich dann so einen Fehler gefunden hab’, dann freue ich mich und alles ist wieder im Lot.

Es entstand dann also eine “MiniMax-Engine” und gleichzeitig ein VierGewinnt-Spiel. Als das dann lief, hab’ ich mit “Mühle” weitergemacht. Das ist beides in einem einzigen Programm vereinigt, einen Einstellungsdialog gibts auch.

Screenshots:

Das Viergewinnt hab’ ich dann gegen zwei im Internet gefundene Viergewinnts antreten lassen. Bei gleicher Halbzugtiefe waren die dann doch eher nicht so gut. Ich weiss auch warum.

Als nächstes hab’ ich dann Dame und Räuberdame gemacht. Und Halma, 3×3. Und Schach. Und Hase und Jäger.
   

Pong

Gestelltes Problem
Ich hab’ ein Handy. Das Handy kann Java. Es hat nur ein paar Jahre gedauert, bis ich auf die Idee gekommen bin dass ich doch mal ein Programm schreiben könnte welches auf dem Handy läuft. Also erst einmal etwas Kleines für den Anfang, Pong.

Programm
Zunächst musste ich mir Java ME besorgen, und ein paar Beispiele angucken. Dann ein kleines Hello-World zum Üben und dann gings auch schon los. Besonders schwierig wars nicht, ich musste mich lediglich wieder in Java einfühlen.

Screenshot:

Ameis

Gestelltes Problem
Schwarmintelligenz verstehe ich so, dass ein Erfolgsrezept darin besteht, das nachzumachen, was erfolgreiche Individuen getan haben. Damit partizipiert man an von anderen gemachter Erfahrung. Ein Teilbereich ist dabei die Optimierung von Wegen, wie finden z.B. Ameisen den kürzesten Weg zur Futterquelle und zurück? Sie verwenden Pheromone, mit denen sie einen Weg markieren. Der kürzeste Weg ist der, den die meisten Ameisen benutzen (hier deutet sich eine Rekursion an, die mir noch etwas zu Schaffen macht).
Mein Ansatz unterschied sich vom dem, was ich im Internet gefunden hatte, insoweit als ich versuchte, einen “richtigen” Ameisenhaufen nachzumachen. Dabei sollte es keine vorgegebenen Wege, keine vorgegebene Richtung und auch keine nachträgliche Vergabe von Duftstoffen (Ameise findet Futter und markiert dann den von ihr gegangenen Weg) geben, weil ich das unrealistisch fand.

Algorithmus
Es gibt zwei Pheromone:
“Ich komme vom Haufen, suche Futter.”
“Ich komme vom Futter, suche den Haufen.”
Eine Ameise, die Futter hat, muss sich also in der Richtung bewegen, aus der Ameisen kommen, die Futter suchen, damit also vom Bau losgelaufen sind. Umgekehrt muss eine Ameise, die Futter sucht, sich in die Richtung bewegen, aus der die meisten Ameisen mit Futter zurückkehren. Ich habe drei Typen von Feldern verwendet, Ameisenhaufen (blau), Futter (grün) und Hindernis (grau). Die Ameisen selbst sind schwarze Punkte. Sie geben ihren jeweiligen Duftstoff ab, der Vorrat ist begrenzt, damit kurze Wege entstehen. Wenn eine Ameise einen Bildpunkt verlässt, dann geht sie in die Richtung, aus der die meisten Ameisen mit dem Gegenduft gekommen sind. Dabei ist noch ein gewisses Zufallselement im Spiel. Die Düfte verfliegen mit der Zeit, damit sich neue Wege bilden können. Im Screenshot sieht man die Situation nach 14260 Durchläufen mit 5000 Ameisen. Sie haben links oben und rechts unten Futter gefunden. Die 219884 Statuswechsel sind die Anzahl der Futterabgabe plus Futteraufnahme. Ameisen auf Futtersuche hinterlassen ein gelbes Pheromon, Rückkehrer eins der Farbe Lila. Die Wege sind noch nicht so optimal, wie ich mirs wünschen würde, aber trotzdem machen die Ameisen ihren Job, holen Futter und bringen es zum Haufen zurück, ein nettes Feierabendprojekt.

Screenshot:

Hmja, dann dachte ich mir, eigentlich müssten die Ameisen nicht dahin gehen wo die Meisten herkommen, sondern dahin, wo die Erfolgreichsten, also die mit dem kürzesten Weg vom Futter oder Bau herkommen. Ausserdem ist der Weg zurück zum Bau doch eigentlich unveränderlich, weswegen die Rückkehrpheromone nicht verfliegen sollten. Nach diesen Programmänderungen verwandelten sich die Ameisen in noch gefrässigere Biester.

Screenshots: