RuZman

5007

Illustration

Abstract

Die Konfiguration von vielen Leap Motion Projekten ist gleich oder ähnlich. In diesem Blogpost wird aufgezeigt, wie mithilfe des Build-Patterns die einzelnen Parameter gespeichert und die Konfiguration elegant zusammengebaut wird. Als Grundlage wird mein Leap Motion Framework genommen, dass bereits eine "zentrale" Klasse zur Konfiguration eines Leap Motion Projekts besitzt, aber aktuell nicht sonderlich flexibel ist.

Hintergrund

Normalerweise lade ich zuerst die nativen Libraries der Leap Motion passend zum Betriebssystem. Zudem lege ich oft die minimale bzw. maximale Anzahl an Händen fest, welche die Applikation benötigt. Des Weiteren ist es bei 2D-Applikationen notwendig die Fenstergröße zu ermitteln. Die Angaben sind für das X/Y-Mapping relevant. Außerdem lege ich gerne die Größe des Interaktionsraums fest ...

Initial

Alle diese Optionen und noch viele mehr möchte ich zentral in der Klasse LeapApp hinterlegen. Diese folgt dem Singleton-Pattern, sodass zu jedem Zeitpunkt lediglich eine Instanz von LeapApp existiert. Die Initialisierung der Klasse LeapApp erfolgt mit dem Build-Pattern.

public class LeapApp {
	private static LeapApp instance;

	private LeapApp() {}

	public static class LeapAppBuilder {
		public LeapAppBuilder() {
			if(instance == null) {
				instance = new LeapApp();
			}
		}

		public LeapApp initLeapApp() {
			return instance;
		}
	}
}

In den nachfolgen Kapiteln werden die einzelnen Parameter schrittweise hinzugefügt.

Parameter - Native Libraries

Über den Konstruktor des LeapAppBuilders möchten wir die Option bieten die nativen Libraries zu laden. Im ursprünglichen Code wurden die Libraries automatisch aus dem Ordner "native" geladen.

public LeapAppBuilder() {
	this(true);
}

public LeapAppBuilder(boolean shouldLoadNativeLibraries) {
	this(shouldLoadNativeLibraries, "native");
}

public LeapAppBuilder(boolean shouldLoadNativeLibraries, String path) {
	if (shouldLoadNativeLibraries) {
		NativeLibrary.loadSystem(path);
	}

	if(instance == null) {
		instance = new LeapApp(new Controller());
	}
}

Mit dieser Änderung passiert das weiterhin. Der Entwickler kann dies aber mit den Parametern shouldLoadNativeLibraries unterbinden oder mit path einen anderen Pfad wählen.

Parameter - TrackingBox

Nun definieren wir einen globalen Interaktionsraum, der für alle Hände, Finger und Tools gilt. Dieser Parameter ist optional und kann bei Bedarf gesetzt werden. Standardmäßig nutzen wir eine TrackingBox, welche sich aus den Werten der InteractionBox zusammensetzt. Der folgende Quellcode zeigt exemplarisch, wie ein Parameter in LeapAppBuilder und LeapApp aufgenommen wird. In den anderen Abschnitten wird die Vorgehensweise analog ausgeführt und nicht mehr explizit erwähnt.

// 1. Setter in der LeapAppBuild-Klasse zur Verfügung stellen.
public LeapAppBuilder trackingBox(TrackingBox trackingBox) {
	this.trackingBox = trackingBox;
	return this;
}

// 2. Parameter beim Aufruf von initLeapApp() an die Klasse LeapApp weiterreichen.
public LeapApp initLeapApp() {
	instance.init(trackingBox);
	return instance;
}

// 3. Parameter entgegennehmen und die LeapApp-Instanz korrekt befüllen.
private void init(TrackingBox trackingBox) {
	this.trackingBox = trackingBox;
	controller.addListener(LeapEventHandler.getInstance());
}

// 4. Getter und Setter zur Interaktion mit der Klasse LeapApp zur Verfügung stellen.
public static void setTrackingBox(TrackingBox trackingBox) {
	instance.trackingBox = trackingBox;
}
public static TrackingBox getTrackingBox() {
	return instance.trackingBox;
}

Parameter - Min / Max Hände

Für einige Applikationen ist die Anzahl der getrackten Hände fix. Mit dem Parameter minimumHandNumber und maximumHandNumber legen wir das Limit fest. Standardmäßig wird zur Ausführung der "Leap-Logik" mindestens eine Hand benötigt. Aus diesem Grund liegt die min. Anzahl bei 1 und die max. Anzahl an Händen bei Integer.MAX_VALUE.

Parameter - Screen Width / Height

Insbesondre zur Berechnung der X/Y-Koordinaten in 2D-Applikationen werden die Höhe und Breite des Monitors benötigt. Sofern die Angaben nicht manuell gesetzt werden, nutzen wir die Bildschirmauflösung des Default-Monitors.

Parameter - Polling

Es gibt zwei Wege um an den aktuellen Frame der Leap Motion zu gelangen. Über die Klasse Listener oder mit controller.frame(). Ich bevorzuge die zweite Variante, da man sich dabei nicht um das Multithreading kümmern muss und die Daten kurz vor dem zeichnen / rendern nur einmal aktualisiert werden. Standardmäßig wird Polling deshalb aktiviert.

Quellcode

Im LeapAppBuilder sind noch ein paar weitere Parameter implementiert. Diese sind nur für das Framework relevant und werden deshalb hier nicht besprochen. Wer selbst mal ein bisschen probieren möchte, kann sich das Leap Motion Projekt bei GitHub auschecken. Dort lassen sich die verschiedenen Konfigurationen an dem Projekt in der Klasse de.ruzman.hand.App austesten.