diff --git a/build.xml b/build.xml
new file mode 100644
index 0000000..612f84d
--- /dev/null
+++ b/build.xml
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+ Builds, tests, and runs the project JavaLibrary6.
+
+
+
diff --git a/lib/nblibraries.properties b/lib/nblibraries.properties
new file mode 100644
index 0000000..8c8ab62
--- /dev/null
+++ b/lib/nblibraries.properties
@@ -0,0 +1,10 @@
+libs.junit_4.classpath=\
+ ${base}/junit_4/junit-4.5.jar
+libs.junit_4.javadoc=\
+ ${base}/junit_4/junit-4.5-api.zip
+libs.junit_4.src=\
+ ${base}/junit_4/junit-4.5-src.jar
+libs.junit.classpath=\
+ ${base}/junit/junit-3.8.2.jar
+libs.junit.javadoc=\
+ ${base}/junit/junit-3.8.2-api.zip
diff --git a/nbproject/build-impl.xml b/nbproject/build-impl.xml
new file mode 100644
index 0000000..55720ab
--- /dev/null
+++ b/nbproject/build-impl.xml
@@ -0,0 +1,721 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must set src.dir
+ Must set test.src.dir
+ Must set build.dir
+ Must set dist.dir
+ Must set build.classes.dir
+ Must set dist.javadoc.dir
+ Must set build.test.classes.dir
+ Must set build.test.results.dir
+ Must set build.classes.excludes
+ Must set dist.jar
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must set javac.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select some files in the IDE or set javac.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ To run this application from the command line without Ant, try:
+
+
+
+
+
+
+ java -cp "${run.classpath.with.dist.jar}" ${main.class}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ To run this application from the command line without Ant, try:
+
+ java -jar "${dist.jar.resolved}"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set run.class
+
+
+
+ Must select one file in the IDE or set run.class
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set debug.class
+
+
+
+
+ Must select one file in the IDE or set debug.class
+
+
+
+
+ Must set fix.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select some files in the IDE or set javac.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Some tests failed; see details above.
+
+
+
+
+
+
+
+
+ Must select some files in the IDE or set test.includes
+
+
+
+ Some tests failed; see details above.
+
+
+
+
+ Must select one file in the IDE or set test.class
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set applet.url
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set applet.url
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/nbproject/genfiles.properties b/nbproject/genfiles.properties
new file mode 100644
index 0000000..90ae97c
--- /dev/null
+++ b/nbproject/genfiles.properties
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=a8056d46
+build.xml.script.CRC32=3a7a628a
+build.xml.stylesheet.CRC32=958a1d3e
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
+nbproject/build-impl.xml.data.CRC32=afb4810b
+nbproject/build-impl.xml.script.CRC32=7668b6e9
+nbproject/build-impl.xml.stylesheet.CRC32=5c621a33@1.26.1.45
diff --git a/nbproject/project.properties b/nbproject/project.properties
new file mode 100644
index 0000000..cfeabca
--- /dev/null
+++ b/nbproject/project.properties
@@ -0,0 +1,70 @@
+application.title=wiigee-lib
+application.vendor=bepo
+auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.tab-size=8
+auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.text-limit-width=80
+auxiliary.org-netbeans-modules-editor-indent.CodeStyle.usedProfile=default
+build.classes.dir=${build.dir}/classes
+build.classes.excludes=**/*.java,**/*.form
+# This directory is removed when the project is cleaned:
+build.dir=build
+build.generated.dir=${build.dir}/generated
+build.generated.sources.dir=${build.dir}/generated-sources
+# Only compile against the classpath explicitly listed here:
+build.sysclasspath=ignore
+build.test.classes.dir=${build.dir}/test/classes
+build.test.results.dir=${build.dir}/test/results
+# Uncomment to specify the preferred debugger connection transport:
+#debug.transport=dt_socket
+debug.classpath=\
+ ${run.classpath}
+debug.test.classpath=\
+ ${run.test.classpath}
+# This directory is removed when the project is cleaned:
+dist.dir=dist
+dist.jar=${dist.dir}/wiigee-lib.jar
+dist.javadoc.dir=${dist.dir}/javadoc
+excludes=
+includes=**
+jar.compress=false
+javac.classpath=
+# Space-separated list of extra javac options
+javac.compilerargs=
+javac.deprecation=false
+javac.source=1.5
+javac.target=1.5
+javac.test.classpath=\
+ ${javac.classpath}:\
+ ${build.classes.dir}:\
+ ${libs.junit.classpath}
+javadoc.additionalparam=
+javadoc.author=false
+javadoc.encoding=${source.encoding}
+javadoc.noindex=false
+javadoc.nonavbar=false
+javadoc.notree=false
+javadoc.private=false
+javadoc.splitindex=true
+javadoc.use=true
+javadoc.version=false
+javadoc.windowtitle=
+jnlp.codebase.type=local
+jnlp.codebase.url=file:/Users/bepo/develop/java/wiigee/trunk/wiigee-lib/dist
+jnlp.descriptor=application
+jnlp.enabled=false
+jnlp.offline-allowed=false
+jnlp.signed=false
+meta.inf.dir=${src.dir}/META-INF
+platform.active=default_platform
+run.classpath=\
+ ${javac.classpath}:\
+ ${build.classes.dir}
+# Space-separated list of JVM arguments used when running the project
+# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
+# or test-sys-prop.name=value to set system properties for unit tests):
+run.jvmargs=
+run.test.classpath=\
+ ${javac.test.classpath}:\
+ ${build.test.classes.dir}
+source.encoding=UTF-8
+src.dir=src
+test.src.dir=test
diff --git a/nbproject/project.xml b/nbproject/project.xml
new file mode 100644
index 0000000..2d55e43
--- /dev/null
+++ b/nbproject/project.xml
@@ -0,0 +1,19 @@
+
+
+ org.netbeans.modules.java.j2seproject
+
+
+ wiigee-lib
+ 1.6.5
+
+
+
+
+
+
+
+
+ lib/nblibraries.properties
+
+
+
diff --git a/src/org/wiigee/control/Wiigee.java b/src/org/wiigee/control/Wiigee.java
new file mode 100644
index 0000000..fff9e7e
--- /dev/null
+++ b/src/org/wiigee/control/Wiigee.java
@@ -0,0 +1,46 @@
+/*
+ * wiigee - accelerometerbased gesture recognition
+ * Copyright (C) 2007, 2008, 2009 Benjamin Poppinga
+ *
+ * Developed at University of Oldenburg
+ * Contact: wiigee@benjaminpoppinga.de
+ *
+ * This file is part of wiigee.
+ *
+ * wiigee is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.wiigee.control;
+
+import org.wiigee.util.Log;
+
+/**
+ * The mother of all classes. :-) It's just used as parent class
+ * to print version information and later on maybe dynamic configuring
+ * of the whole wiimote system... detecting plugins and devices automatically
+ * maybe. :)
+ *
+ * @author Benjamin 'BePo' Poppinga
+ */
+public class Wiigee {
+
+ protected static String version = "1.5.5 alpha";
+ protected static String releasedate = "20090714";
+
+ protected Wiigee() {
+ Log.write("This is wiigee version "+version+" ("+releasedate+")");
+ }
+
+}
diff --git a/src/org/wiigee/device/Device.java b/src/org/wiigee/device/Device.java
new file mode 100644
index 0000000..796b952
--- /dev/null
+++ b/src/org/wiigee/device/Device.java
@@ -0,0 +1,234 @@
+/*
+ * wiigee - accelerometerbased gesture recognition
+ * Copyright (C) 2007, 2008, 2009 Benjamin Poppinga
+ *
+ * Developed at University of Oldenburg
+ * Contact: wiigee@benjaminpoppinga.de
+ *
+ * This file is part of wiigee.
+ *
+ * wiigee is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+package org.wiigee.device;
+
+import java.io.IOException;
+import java.util.Vector;
+
+import org.wiigee.logic.*;
+import org.wiigee.event.*;
+import org.wiigee.filter.*;
+
+/**
+ * Abstract representation of a device with very basic functionalities. This
+ * class should be derived from, if anybody plans to add a new class of devices,
+ * like Wiimote or AndroidDevice does. This class mainly consist of filter
+ * management, recognition control and core event control.
+ *
+ * @author Benjamin 'BePo' Poppinga
+ */
+public class Device {
+
+ // Fixed number values.
+ public static final int MOTION = 0;
+
+ // Buttons for action coordination
+ protected int recognitionbutton;
+ protected int trainbutton;
+ protected int closegesturebutton;
+
+ // Functional
+ protected boolean accelerationEnabled;
+
+ // Filters, can filter the data stream
+ protected Vector accfilters = new Vector();
+
+ // Listeners, receive generated events
+ protected Vector accelerationlistener = new Vector();
+ protected Vector buttonlistener = new Vector();
+
+ // Processing unit to analyze the data
+ protected ProcessingUnit processingunit = new TriggeredProcessingUnit();
+
+ public Device(boolean autofiltering) {
+ if (autofiltering) {
+ this.addAccelerationFilter(new IdleStateFilter());
+ this.addAccelerationFilter(new MotionDetectFilter(this));
+ this.addAccelerationFilter(new DirectionalEquivalenceFilter());
+ }
+ this.addAccelerationListener(this.processingunit);
+ this.addButtonListener(this.processingunit);
+ }
+
+ /**
+ * Adds a Filter for processing the acceleration values.
+ * @param filter The Filter instance.
+ */
+ public void addAccelerationFilter(Filter filter) {
+ this.accfilters.add(filter);
+ }
+
+ /**
+ * Resets all the accfilters, which are resetable.
+ * Sometimes they have to be resettet if a new gesture starts.
+ */
+ public void resetAccelerationFilters() {
+ for (int i = 0; i < this.accfilters.size(); i++) {
+ this.accfilters.elementAt(i).reset();
+ }
+ }
+
+ /**
+ * Adds an AccelerationListener to the Device. Everytime an acceleration
+ * on the Device is performed the AccelerationListener would receive
+ * an event of this action.
+ *
+ * @param listener The Listener.
+ */
+ public void addAccelerationListener(AccelerationListener listener) {
+ this.accelerationlistener.add(listener);
+ }
+
+ /**
+ * Adds a ButtonListener to the Device. Everytime a Button has been
+ * pressed or released, the Listener would be notified about this via
+ * the corresponding Events.
+ *
+ * @param listener The Listener.
+ */
+ public void addButtonListener(ButtonListener listener) {
+ this.buttonlistener.add(listener);
+ }
+
+ /**
+ * Adds a GestureListener to the Device. Everytime a gesture
+ * is performed the GestureListener would receive an event of
+ * this gesture.
+ *
+ * @param listener The Listener.
+ */
+ public void addGestureListener(GestureListener listener) {
+ this.processingunit.addGestureListener(listener);
+ }
+
+ public int getRecognitionButton() {
+ return this.recognitionbutton;
+ }
+
+ public void setRecognitionButton(int b) {
+ this.recognitionbutton = b;
+ }
+
+ public int getTrainButton() {
+ return this.trainbutton;
+ }
+
+ public void setTrainButton(int b) {
+ this.trainbutton = b;
+ }
+
+ public int getCloseGestureButton() {
+ return this.closegesturebutton;
+ }
+
+ public void setCloseGestureButton(int b) {
+ this.closegesturebutton = b;
+ }
+
+ public ProcessingUnit getProcessingUnit() {
+ return this.processingunit;
+ }
+
+ public void setAccelerationEnabled(boolean enabled) throws IOException {
+ this.accelerationEnabled = enabled;
+ }
+
+ public void loadGesture(String filename) {
+ this.processingunit.loadGesture(filename);
+ }
+
+ public void saveGesture(int id, String filename) {
+ this.processingunit.saveGesture(id, filename);
+ }
+
+ // ###### Event-Methoden
+ /** Fires an acceleration event.
+ * @param vector Consists of three values:
+ * acceleration on X, Y and Z axis.
+ */
+ public void fireAccelerationEvent(double[] vector) {
+ for (int i = 0; i < this.accfilters.size(); i++) {
+ vector = this.accfilters.get(i).filter(vector);
+ // cannot return here if null, because of time-dependent accfilters
+ }
+
+ // don't need to create an event if filtered away
+ if (vector != null) {
+ // calculate the absolute value for the accelerationevent
+ double absvalue = Math.sqrt((vector[0] * vector[0]) +
+ (vector[1] * vector[1]) + (vector[2] * vector[2]));
+
+ AccelerationEvent w = new AccelerationEvent(this,
+ vector[0], vector[1], vector[2], absvalue);
+ for (int i = 0; i < this.accelerationlistener.size(); i++) {
+ this.accelerationlistener.get(i).accelerationReceived(w);
+ }
+ }
+
+ } // fireaccelerationevent
+
+ /** Fires a button pressed event.
+ * @param button
+ * Integer value of the pressed button.
+ */
+ public void fireButtonPressedEvent(int button) {
+ ButtonPressedEvent w = new ButtonPressedEvent(this, button);
+ for (int i = 0; i < this.buttonlistener.size(); i++) {
+ this.buttonlistener.get(i).buttonPressReceived(w);
+ }
+
+ if (w.isRecognitionInitEvent() || w.isTrainInitEvent()) {
+ this.resetAccelerationFilters();
+ }
+ }
+
+ /** Fires a button released event.
+ */
+ public void fireButtonReleasedEvent(int button) {
+ ButtonReleasedEvent w = new ButtonReleasedEvent(this, button);
+ for (int i = 0; i < this.buttonlistener.size(); i++) {
+ this.buttonlistener.get(i).buttonReleaseReceived(w);
+ }
+ }
+
+ /**
+ * Fires a motion start event.
+ */
+ public void fireMotionStartEvent() {
+ MotionStartEvent w = new MotionStartEvent(this);
+ for (int i = 0; i < this.accelerationlistener.size(); i++) {
+ this.accelerationlistener.get(i).motionStartReceived(w);
+ }
+ }
+
+ /**
+ * Fires a motion stop event.
+ */
+ public void fireMotionStopEvent() {
+ MotionStopEvent w = new MotionStopEvent(this);
+ for (int i = 0; i < this.accelerationlistener.size(); i++) {
+ this.accelerationlistener.get(i).motionStopReceived(w);
+ }
+ }
+}
diff --git a/src/org/wiigee/event/AccelerationEvent.java b/src/org/wiigee/event/AccelerationEvent.java
new file mode 100755
index 0000000..2f54741
--- /dev/null
+++ b/src/org/wiigee/event/AccelerationEvent.java
@@ -0,0 +1,79 @@
+/*
+ * wiigee - accelerometerbased gesture recognition
+ * Copyright (C) 2007, 2008, 2009 Benjamin Poppinga
+ *
+ * Developed at University of Oldenburg
+ * Contact: wiigee@benjaminpoppinga.de
+ *
+ * This file is part of wiigee.
+ *
+ * wiigee is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.wiigee.event;
+
+import java.util.EventObject;
+
+import org.wiigee.device.*;
+
+/**
+ * This Event would be generated if an acceleration has been detected.
+ * It contains information about the force applied to the device in each
+ * direction (x, y, z). Further it contains the absolute value of this
+ * vector and the source which generated this event (Device).
+ *
+ * @author Benjamin 'BePo' Poppinga
+ *
+ */
+public class AccelerationEvent extends EventObject {
+
+ double X, Y, Z;
+ double absvalue;
+
+ /**
+ * Create an AccelerationEvent with a specific source,
+ * all the three acceleration values and the calculated absolute
+ * value.
+ *
+ * @param source The source which has been accelerated (Wiimote).
+ * @param X The value of acceleration in the x direction.
+ * @param Y The value of acceleration in the y direction.
+ * @param Z The value of acceleration in the z direction.
+ * @param absvalue The absolute value of this acceleration vector.
+ */
+ public AccelerationEvent(Device source, double X, double Y, double Z, double absvalue) {
+ super(source);
+ this.X=X;
+ this.Y=Y;
+ this.Z=Z;
+ this.absvalue=absvalue;
+ }
+
+ public double getX() {
+ return X;
+ }
+
+ public double getY() {
+ return Y;
+ }
+
+ public double getZ() {
+ return Z;
+ }
+
+ public double getAbsValue() {
+ return absvalue;
+ }
+}
diff --git a/src/org/wiigee/event/AccelerationListener.java b/src/org/wiigee/event/AccelerationListener.java
new file mode 100755
index 0000000..e70707a
--- /dev/null
+++ b/src/org/wiigee/event/AccelerationListener.java
@@ -0,0 +1,65 @@
+/*
+ * wiigee - accelerometerbased gesture recognition
+ * Copyright (C) 2007, 2008, 2009 Benjamin Poppinga
+ *
+ * Developed at University of Oldenburg
+ * Contact: wiigee@benjaminpoppinga.de
+ *
+ * This file is part of wiigee.
+ *
+ * wiigee is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.wiigee.event;
+
+import java.util.EventListener;
+
+/**
+ * This interface has to be implemented if the application should react
+ * to pure acceleration data. This could be useful if you want to e.g.
+ * graphically display the acceleration data in your application.
+ *
+ * @author Benjamin 'BePo' Poppinga
+ */
+public interface AccelerationListener extends EventListener {
+
+ /**
+ * This method would be called if a Device source has been accelerated.
+ *
+ * @param event The acceleration representation as an event.
+ */
+ public abstract void accelerationReceived(AccelerationEvent event);
+
+ /**
+ * This method would be called if a Device is in idle state and then a
+ * motion starts or if a Device is in motion and then the motion stops and
+ * the Device is in idle state.
+ *
+ * @param event This is the event which contains if the Wiimote is now
+ * in motion or not.
+ */
+ public abstract void motionStartReceived(MotionStartEvent event);
+
+ /**
+ * This method would be called if a Device is in motion and then the motion
+ * stops and the Device is in idle state.
+ *
+ * @param event This is the event which contains if the Device is now
+ * in motion or not.
+ */
+ public abstract void motionStopReceived(MotionStopEvent event);
+
+
+}
diff --git a/src/org/wiigee/event/ActionStartEvent.java b/src/org/wiigee/event/ActionStartEvent.java
new file mode 100755
index 0000000..9cdfab8
--- /dev/null
+++ b/src/org/wiigee/event/ActionStartEvent.java
@@ -0,0 +1,84 @@
+/*
+ * wiigee - accelerometerbased gesture recognition
+ * Copyright (C) 2007, 2008, 2009 Benjamin Poppinga
+ *
+ * Developed at University of Oldenburg
+ * Contact: wiigee@benjaminpoppinga.de
+ *
+ * This file is part of wiigee.
+ *
+ * wiigee is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.wiigee.event;
+
+import java.util.EventObject;
+
+import org.wiigee.device.Device;
+
+/**
+ * An ActionStartEvent is an Event where other different events can
+ * be derived from, if they can be considered as an event actually starting
+ * a process like e.g. Training, Recognition, ...
+ *
+ * @author Benjamin 'BePo' Poppinga
+ */
+public class ActionStartEvent extends EventObject {
+
+ protected boolean trainbutton;
+ protected boolean recognitionbutton;
+ protected boolean closegesturebutton;
+
+ public ActionStartEvent(Device source) {
+ super(source);
+ }
+
+ /**
+ * Is true if this button press has been done by the
+ * individual defined RecognitionButton which has to be
+ * set during initialization of a Wiimote.
+ *
+ * @return Is this button press initiated by the recognition button.
+ * @see device.Wiimote#setRecognitionButton(int) setRecognitionButton()
+ */
+ public boolean isRecognitionInitEvent() {
+ return this.recognitionbutton;
+ }
+
+ /**
+ * Is true if this button press has been done by the
+ * individual defined TrainButton which has to be
+ * set during initialization of a Wiimote.
+ *
+ * @return Is this button pres initiated by the training button.
+ * @see device.Wiimote#setTrainButton(int) setTrainButton()
+ */
+ public boolean isTrainInitEvent() {
+ return this.trainbutton;
+ }
+
+ /**
+ * Is true if this button press has been done by the
+ * individual defined CloseGestureButton which has to be
+ * set during initialization of a Wiimote.
+ *
+ * @return Is this button press initiated by the close gesture button.
+ * @see device.Wiimote#setCloseGestureButton(int) setCloseGestureButton()
+ */
+ public boolean isCloseGestureInitEvent() {
+ return this.closegesturebutton;
+ }
+
+}
diff --git a/src/org/wiigee/event/ActionStopEvent.java b/src/org/wiigee/event/ActionStopEvent.java
new file mode 100755
index 0000000..c4379e2
--- /dev/null
+++ b/src/org/wiigee/event/ActionStopEvent.java
@@ -0,0 +1,43 @@
+/*
+ * wiigee - accelerometerbased gesture recognition
+ * Copyright (C) 2007, 2008, 2009 Benjamin Poppinga
+ *
+ * Developed at University of Oldenburg
+ * Contact: wiigee@benjaminpoppinga.de
+ *
+ * This file is part of wiigee.
+ *
+ * wiigee is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.wiigee.event;
+
+import java.util.EventObject;
+import org.wiigee.device.Device;
+
+/**
+ * An ActionStopEvent is an Event where other different events can
+ * be derived from, if they can be considered as an event actually stopping
+ * a process like e.g. Training, Recognition, ...
+ *
+ * @author Benjamin 'BePo' Poppinga
+ */
+public class ActionStopEvent extends EventObject {
+
+ public ActionStopEvent(Device source) {
+ super(source);
+ }
+
+}
diff --git a/src/org/wiigee/event/ButtonListener.java b/src/org/wiigee/event/ButtonListener.java
new file mode 100644
index 0000000..296c6ae
--- /dev/null
+++ b/src/org/wiigee/event/ButtonListener.java
@@ -0,0 +1,54 @@
+/*
+ * wiigee - accelerometerbased gesture recognition
+ * Copyright (C) 2007, 2008, 2009 Benjamin Poppinga
+ *
+ * Developed at University of Oldenburg
+ * Contact: wiigee@benjaminpoppinga.de
+ *
+ * This file is part of wiigee.
+ *
+ * wiigee is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.wiigee.event;
+
+import java.util.EventListener;
+
+/**
+ * This interface has to be implemented if the application should react
+ * to button press/releases.
+ *
+ * @author Benjamin 'BePo' Poppinga
+ */
+public interface ButtonListener extends EventListener {
+
+
+ /**
+ * This method would be called if a Device button has been pressed.
+ *
+ * @param event The button representation as an event.
+ */
+ public abstract void buttonPressReceived(ButtonPressedEvent event);
+
+ /**
+ * This method would be called if a Device button has been released.
+ *
+ * @param event This is actually a meta-event NOT containing which button
+ * has been released.
+ */
+ public abstract void buttonReleaseReceived(ButtonReleasedEvent event);
+
+
+}
diff --git a/src/org/wiigee/event/ButtonPressedEvent.java b/src/org/wiigee/event/ButtonPressedEvent.java
new file mode 100755
index 0000000..36d54a4
--- /dev/null
+++ b/src/org/wiigee/event/ButtonPressedEvent.java
@@ -0,0 +1,80 @@
+/*
+ * wiigee - accelerometerbased gesture recognition
+ * Copyright (C) 2007, 2008, 2009 Benjamin Poppinga
+ *
+ * Developed at University of Oldenburg
+ * Contact: wiigee@benjaminpoppinga.de
+ *
+ * This file is part of wiigee.
+ *
+ * wiigee is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.wiigee.event;
+
+import org.wiigee.device.*;
+
+/**
+ *
+ * This Event would be generated if a button on a wiimote has been
+ * pressed by user. It contains the source (wiimote) and an integer
+ * representation of which button has been pressed. Please note that
+ * there exist enumeration constants in the class, so you don't
+ * have to use this integer values directly.
+ *
+ * @author Benjamin 'BePo' Poppinga
+ */
+public class ButtonPressedEvent extends ActionStartEvent {
+
+ // Fixed number values.
+ public static final int BUTTON_2 = 1;
+ public static final int BUTTON_1 = 2;
+ public static final int BUTTON_B = 3;
+ public static final int BUTTON_A = 4;
+ public static final int BUTTON_MINUS = 5;
+ public static final int BUTTON_HOME = 8;
+ public static final int BUTTON_LEFT = 9;
+ public static final int BUTTON_RIGHT = 10;
+ public static final int BUTTON_DOWN = 11;
+ public static final int BUTTON_UP = 12;
+ public static final int BUTTON_PLUS = 13;
+
+ int button;
+
+ /**
+ * Create a WiimoteButtonPressedEvent with the Wiimote source whose
+ * Button has been pressed and the integer representation of the button.
+ *
+ * @param source
+ * @param button
+ */
+ public ButtonPressedEvent(Device source, int button) {
+ super(source);
+ this.button=button;
+
+ if(source.getRecognitionButton()==button) {
+ this.recognitionbutton=true;
+ } else if(source.getTrainButton()==button) {
+ this.trainbutton=true;
+ } else if(source.getCloseGestureButton()==button) {
+ this.closegesturebutton=true;
+ }
+ }
+
+ public int getButton() {
+ return this.button;
+ }
+
+}
diff --git a/src/org/wiigee/event/ButtonReleasedEvent.java b/src/org/wiigee/event/ButtonReleasedEvent.java
new file mode 100755
index 0000000..45de43b
--- /dev/null
+++ b/src/org/wiigee/event/ButtonReleasedEvent.java
@@ -0,0 +1,49 @@
+/*
+ * wiigee - accelerometerbased gesture recognition
+ * Copyright (C) 2007, 2008, 2009 Benjamin Poppinga
+ *
+ * Developed at University of Oldenburg
+ * Contact: wiigee@benjaminpoppinga.de
+ *
+ * This file is part of wiigee.
+ *
+ * wiigee is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.wiigee.event;
+
+import org.wiigee.device.*;
+
+/**
+ *
+ * This event would be generated if a button was released.
+ * contains: source (wiimote).
+ *
+ * @author Benjamin 'BePo' Poppinga
+ */
+public class ButtonReleasedEvent extends ActionStopEvent {
+
+ int button;
+
+ public ButtonReleasedEvent(Device source, int button) {
+ super(source);
+ this.button = button;
+ }
+
+ public int getButton() {
+ return this.button;
+ }
+
+}
diff --git a/src/org/wiigee/event/GestureEvent.java b/src/org/wiigee/event/GestureEvent.java
new file mode 100755
index 0000000..e3465a7
--- /dev/null
+++ b/src/org/wiigee/event/GestureEvent.java
@@ -0,0 +1,71 @@
+/*
+ * wiigee - accelerometerbased gesture recognition
+ * Copyright (C) 2007, 2008, 2009 Benjamin Poppinga
+ *
+ * Developed at University of Oldenburg
+ * Contact: wiigee@benjaminpoppinga.de
+ *
+ * This file is part of wiigee.
+ *
+ * wiigee is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+package org.wiigee.event;
+
+import org.wiigee.logic.ProcessingUnit;
+
+/**
+ * This event would be generated if a gesture has been detected.
+ * It contains information about the gesture "name" or type,
+ * the accelerationstreamanalyzer which generated the event (source)
+ * and the probability calculated from the bayes classifier.
+ *
+ * @author Benjamin 'BePo' Poppinga
+ */
+public class GestureEvent {
+
+ int id;
+ boolean valid;
+ double probability;
+ ProcessingUnit analyzer;
+
+ /** Create a GestureEvent
+ *
+ * @param source The Source, which detected the gesture.
+ * @param id A gesture ID for identifying a gesture.
+ * @param probability The Bayes-Classifier calculated probability.
+ */
+ public GestureEvent(ProcessingUnit source, boolean valid, int id, double probability) {
+ this.analyzer = source;
+ this.valid = valid;
+ this.id = id;
+ this.probability = probability;
+ }
+
+ public int getId() {
+ return this.id;
+ }
+
+ public boolean isValid() {
+ return this.valid;
+ }
+
+ public double getProbability() {
+ return this.probability;
+ }
+
+ public ProcessingUnit getSource() {
+ return this.analyzer;
+ }
+}
diff --git a/src/org/wiigee/event/GestureListener.java b/src/org/wiigee/event/GestureListener.java
new file mode 100755
index 0000000..f076ed9
--- /dev/null
+++ b/src/org/wiigee/event/GestureListener.java
@@ -0,0 +1,47 @@
+/*
+ * wiigee - accelerometerbased gesture recognition
+ * Copyright (C) 2007, 2008, 2009 Benjamin Poppinga
+ *
+ * Developed at University of Oldenburg
+ * Contact: wiigee@benjaminpoppinga.de
+ *
+ * This file is part of wiigee.
+ *
+ * wiigee is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.wiigee.event;
+
+import java.util.EventListener;
+
+/**
+ *
+ * This is the GestureListener interface which has to be implemented
+ * by any application which should receive recognized gestures.
+ *
+ * @author Benjamin 'BePo' Poppinga
+ *
+ */
+public interface GestureListener extends EventListener {
+
+ /**
+ * This method would be called if a gesture has been recognized.
+ *
+ * @param event The GestureEvent containing information about
+ * the recognized gesture.
+ */
+ public abstract void gestureReceived(GestureEvent event);
+
+}
diff --git a/src/org/wiigee/event/MotionStartEvent.java b/src/org/wiigee/event/MotionStartEvent.java
new file mode 100755
index 0000000..e669ba6
--- /dev/null
+++ b/src/org/wiigee/event/MotionStartEvent.java
@@ -0,0 +1,63 @@
+/*
+ * wiigee - accelerometerbased gesture recognition
+ * Copyright (C) 2007, 2008, 2009 Benjamin Poppinga
+ *
+ * Developed at University of Oldenburg
+ * Contact: wiigee@benjaminpoppinga.de
+ *
+ * This file is part of wiigee.
+ *
+ * wiigee is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.wiigee.event;
+
+import org.wiigee.device.Device;
+
+/**
+ * This Event gets fired, if the Device starts to move.
+ *
+ * @author Benjamin 'BePo' Poppinga
+ */
+public class MotionStartEvent extends ActionStartEvent {
+
+ public MotionStartEvent(Device source) {
+ super(source);
+
+ if(source.getRecognitionButton()==Device.MOTION) {
+ this.recognitionbutton=true;
+ } else if(source.getTrainButton()==Device.MOTION) {
+ this.trainbutton=true;
+ } else if(source.getCloseGestureButton()==Device.MOTION) {
+ this.closegesturebutton=true;
+ }
+ }
+
+ @Override
+ public boolean isTrainInitEvent() {
+ return this.trainbutton;
+ }
+
+ @Override
+ public boolean isCloseGestureInitEvent() {
+ return this.closegesturebutton;
+ }
+
+ @Override
+ public boolean isRecognitionInitEvent() {
+ return this.recognitionbutton;
+ }
+
+}
diff --git a/src/org/wiigee/event/MotionStopEvent.java b/src/org/wiigee/event/MotionStopEvent.java
new file mode 100755
index 0000000..d5f8747
--- /dev/null
+++ b/src/org/wiigee/event/MotionStopEvent.java
@@ -0,0 +1,42 @@
+/*
+ * wiigee - accelerometerbased gesture recognition
+ * Copyright (C) 2007, 2008, 2009 Benjamin Poppinga
+ *
+ * Developed at University of Oldenburg
+ * Contact: wiigee@benjaminpoppinga.de
+ *
+ * This file is part of wiigee.
+ *
+ * wiigee is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.wiigee.event;
+
+import org.wiigee.device.Device;
+
+/**
+*
+* This event would be generated if a motion stops.
+* contains: source.
+*
+* @author Benjamin 'BePo' Poppinga
+*/
+public class MotionStopEvent extends ActionStopEvent {
+
+ public MotionStopEvent(Device source) {
+ super(source);
+ }
+
+}
diff --git a/src/org/wiigee/filter/DirectionalEquivalenceFilter.java b/src/org/wiigee/filter/DirectionalEquivalenceFilter.java
new file mode 100755
index 0000000..e5098dd
--- /dev/null
+++ b/src/org/wiigee/filter/DirectionalEquivalenceFilter.java
@@ -0,0 +1,70 @@
+/*
+ * wiigee - accelerometerbased gesture recognition
+ * Copyright (C) 2007, 2008, 2009 Benjamin Poppinga
+ *
+ * Developed at University of Oldenburg
+ * Contact: wiigee@benjaminpoppinga.de
+ *
+ * This file is part of wiigee.
+ *
+ * wiigee is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.wiigee.filter;
+
+/**
+ * This filter removes a vector, if it doesn't differ enough from
+ * the previously retrieved filter.
+ *
+ * @author Benjamin 'BePo' Poppinga
+ */
+public class DirectionalEquivalenceFilter extends Filter {
+
+ private double sensivity;
+ private double[] reference;
+
+ public DirectionalEquivalenceFilter() {
+ super();
+ this.reset();
+ }
+
+ public void reset() {
+ this.sensivity=0.2;
+ this.reference = new double[] {0.0, 0.0, 0.0};
+ }
+
+ public double[] filterAlgorithm(double[] vector) {
+ if(vector[0]reference[0]+this.sensivity ||
+ vector[1]reference[1]+this.sensivity ||
+ vector[2]reference[2]+this.sensivity) {
+ this.reference=vector;
+ return vector;
+ } else {
+ return null;
+ }
+ }
+
+ public void setSensivity(double sensivity) {
+ this.sensivity=sensivity;
+ }
+
+ public double getSensivity() {
+ return this.sensivity;
+ }
+
+}
diff --git a/src/org/wiigee/filter/Filter.java b/src/org/wiigee/filter/Filter.java
new file mode 100755
index 0000000..e97d4a9
--- /dev/null
+++ b/src/org/wiigee/filter/Filter.java
@@ -0,0 +1,62 @@
+/*
+ * wiigee - accelerometerbased gesture recognition
+ * Copyright (C) 2007, 2008, 2009 Benjamin Poppinga
+ *
+ * Developed at University of Oldenburg
+ * Contact: wiigee@benjaminpoppinga.de
+ *
+ * This file is part of wiigee.
+ *
+ * wiigee is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.wiigee.filter;
+
+/**
+ * Abstract class to give a definition for a general filter.
+ *
+ * @author Benjamin 'BePo' Poppinga
+ */
+public abstract class Filter {
+
+ /***
+ * The actual called method to filter anything. It checks if the vector is
+ * already set to NULL by another filter and won't process it anymore. If it's
+ * not NULL it would be forwarded to the actual implemented method - filterAlgorithm().
+ * @param vector The acceleration vector, encoding: 0/x, 1/y, 2/z
+ * @return a new, filtered acceleration vector, encoded the same way
+ */
+ public double[] filter(double[] vector) {
+ if(vector==null) {
+ return null;
+ } else {
+ return filterAlgorithm(vector);
+ }
+ }
+
+ /***
+ * A filter receives a triple of acceleration values within the variable 'vector'.
+ * It's encoded as vector[0]=x, vector[1]=y, vector[2]=z. This is not an object since the
+ * processing of the filter should be really fast, since every acceleration of the wiimote
+ * passes the filter.
+ * @param vector
+ * @param absvalue
+ * @return
+ */
+ abstract public double[] filterAlgorithm(double[] vector);
+
+ abstract public void reset();
+
+}
diff --git a/src/org/wiigee/filter/HighPassFilter.java b/src/org/wiigee/filter/HighPassFilter.java
new file mode 100644
index 0000000..54a6946
--- /dev/null
+++ b/src/org/wiigee/filter/HighPassFilter.java
@@ -0,0 +1,71 @@
+/*
+ * wiigee - accelerometerbased gesture recognition
+ * Copyright (C) 2007, 2008, 2009 Benjamin Poppinga
+ *
+ * Developed at University of Oldenburg
+ * Contact: wiigee@benjaminpoppinga.de
+ *
+ * This file is part of wiigee.
+ *
+ * wiigee is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.wiigee.filter;
+
+/**
+ *
+ * This filter removes every acceleration that happens slowly or
+ * steadily (like e.g. gravity). Remember: It _passes_ acceleration
+ * with a big variety.
+ *
+ * @author Benjamin 'BePo' Poppinga
+ */
+public class HighPassFilter extends Filter {
+
+ private double factor;
+ private double[] prevAcc;
+
+ public HighPassFilter() {
+ super();
+ this.factor = 0.1;
+ this.reset();
+ }
+
+ public HighPassFilter(double factor) {
+ super();
+ this.factor = factor;
+ this.reset();
+ }
+
+ @Override
+ public void reset() {
+ this.prevAcc = new double[] {0.0, 0.0, 0.0};
+ }
+
+ @Override
+ public double[] filterAlgorithm(double[] vector) {
+ double[] retVal = new double[3];
+ prevAcc[0] = vector[0] * this.factor + this.prevAcc[0] * (1.0 - this.factor);
+ prevAcc[1] = vector[1] * this.factor + this.prevAcc[1] * (1.0 - this.factor);
+ prevAcc[2] = vector[2] * this.factor + this.prevAcc[2] * (1.0 - this.factor);
+
+ retVal[0] = vector[0] - prevAcc[0];
+ retVal[1] = vector[1] - prevAcc[1];
+ retVal[2] = vector[2] - prevAcc[2];
+
+ return retVal;
+ }
+
+}
diff --git a/src/org/wiigee/filter/IdleStateFilter.java b/src/org/wiigee/filter/IdleStateFilter.java
new file mode 100755
index 0000000..b816e0b
--- /dev/null
+++ b/src/org/wiigee/filter/IdleStateFilter.java
@@ -0,0 +1,86 @@
+/*
+ * wiigee - accelerometerbased gesture recognition
+ * Copyright (C) 2007, 2008, 2009 Benjamin Poppinga
+ *
+ * Developed at University of Oldenburg
+ * Contact: wiigee@benjaminpoppinga.de
+ *
+ * This file is part of wiigee.
+ *
+ * wiigee is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.wiigee.filter;
+
+/**
+ * Filters if the wiimote is not moved in any way. Be careful in using
+ * this filter together with a HighPassFilter.
+ *
+ * @author Benjamin 'BePo' Poppinga
+ */
+public class IdleStateFilter extends Filter {
+
+ private double sensivity;
+
+ /**
+ * Since an acceleration sensor usually provides information even
+ * if it doesn't move, this filter removes the data if it's in the
+ * idle state.
+ */
+ public IdleStateFilter() {
+ super();
+ this.sensivity = 0.1;
+ }
+
+ @Override
+ public void reset() {
+ // not needed
+ }
+
+ @Override
+ public double[] filterAlgorithm(double[] vector) {
+ // calculate values needed for filtering:
+ // absolute value
+ double absvalue = Math.sqrt((vector[0]*vector[0])+
+ (vector[1]*vector[1])+(vector[2]*vector[2]));
+
+ // filter formulaes and return values
+ if(absvalue > 1+this.sensivity ||
+ absvalue < 1-this.sensivity) {
+ return vector;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Defines the absolute value when the wiimote should react to acceleration.
+ * This is a parameter for the first of the two filters: idle state
+ * filter. For example: sensivity=0.2 makes the wiimote react to acceleration
+ * where the absolute value is equal or greater than 1.2g. The default value 0.1
+ * should work well. Only change if you are sure what you're doing.
+ *
+ * @param sensivity
+ * acceleration data values smaller than this value wouldn't be detected.
+ */
+ public void setSensivity(double sensivity) {
+ this.sensivity = sensivity;
+ }
+
+ public double getSensivity() {
+ return this.sensivity;
+ }
+
+}
diff --git a/src/org/wiigee/filter/LowPassFilter.java b/src/org/wiigee/filter/LowPassFilter.java
new file mode 100644
index 0000000..2c3e012
--- /dev/null
+++ b/src/org/wiigee/filter/LowPassFilter.java
@@ -0,0 +1,67 @@
+/*
+ * wiigee - accelerometerbased gesture recognition
+ * Copyright (C) 2007, 2008, 2009 Benjamin Poppinga
+ *
+ * Developed at University of Oldenburg
+ * Contact: wiigee@benjaminpoppinga.de
+ *
+ * This file is part of wiigee.
+ *
+ * wiigee is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.wiigee.filter;
+
+/**
+ *
+ * This filter removes every acceleration that happens fast or
+ * suddenly (like e.g. a short hit). Remember: It _passes_ acceleration
+ * with a slight variety.
+ *
+ * @author Benjamin 'BePo' Poppinga
+ */
+public class LowPassFilter extends Filter {
+
+ private double factor;
+ private double[] prevAcc;
+
+ public LowPassFilter() {
+ super();
+ this.factor = 0.01;
+ this.reset();
+ }
+
+ public LowPassFilter(double factor) {
+ super();
+ this.factor = factor;
+ this.reset();
+ }
+
+ @Override
+ public void reset() {
+ this.prevAcc = new double[] {0.0, 0.0, 0.0};
+ }
+
+ @Override
+ public double[] filterAlgorithm(double[] vector) {
+ double[] retVal = new double[3];
+ retVal[0] = vector[0] * this.factor + this.prevAcc[0] * (1.0 - this.factor);
+ retVal[1] = vector[1] * this.factor + this.prevAcc[1] * (1.0 - this.factor);
+ retVal[2] = vector[2] * this.factor + this.prevAcc[2] * (1.0 - this.factor);
+ this.prevAcc = retVal;
+ return retVal;
+ }
+
+}
diff --git a/src/org/wiigee/filter/MotionDetectFilter.java b/src/org/wiigee/filter/MotionDetectFilter.java
new file mode 100755
index 0000000..b13124a
--- /dev/null
+++ b/src/org/wiigee/filter/MotionDetectFilter.java
@@ -0,0 +1,102 @@
+/*
+ * wiigee - accelerometerbased gesture recognition
+ * Copyright (C) 2007, 2008, 2009 Benjamin Poppinga
+ *
+ * Developed at University of Oldenburg
+ * Contact: wiigee@benjaminpoppinga.de
+ *
+ * This file is part of wiigee.
+ *
+ * wiigee is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.wiigee.filter;
+
+import org.wiigee.device.Device;
+
+/**
+ * This filter uses time to determine if the wiimote actually is in motion
+ * or not. This filter only works together with the IdleStateFilter.
+ *
+ * @author Benjamin 'BePo' Poppinga
+ */
+public class MotionDetectFilter extends Filter {
+
+ private int motionchangetime;
+ private boolean nowinmotion;
+ private long motionstartstamp;
+ private Device device;
+
+ /***
+ * Detects wheather the wiimote receives acceleration or not and
+ * raises an event, if the device starts or stops. This is actual a
+ * null filter, not manipulating anything. But looks pretty good in
+ * this datatype since it could be removed easily.
+ *
+ * @param wiimote The Wiimote object which is controlled by the filter.
+ */
+ public MotionDetectFilter(Device device) {
+ super();
+ this.device=device;
+ this.reset();
+ }
+
+ public void reset() {
+ this.motionstartstamp=System.currentTimeMillis();
+ this.nowinmotion=false;
+ this.motionchangetime=190;
+ }
+
+ @Override
+ public double[] filter(double[] vector) {
+
+ if(this.nowinmotion &&
+ (System.currentTimeMillis()-this.motionstartstamp)>=
+ this.motionchangetime) {
+ this.nowinmotion=false;
+ this.device.fireMotionStopEvent();
+ } // fi
+
+ return filterAlgorithm(vector);
+ }
+
+ public double[] filterAlgorithm(double[] vector) {
+ if(vector!=null) {
+ this.motionstartstamp=System.currentTimeMillis();
+ if(!this.nowinmotion) {
+ this.nowinmotion=true;
+ this.motionstartstamp=System.currentTimeMillis();
+ this.device.fireMotionStartEvent();
+ }
+ }
+
+ return vector;
+ }
+
+ /**
+ * Defines the time the wiimote has to be in idle state before a new motion change
+ * event appears. The default value 500ms should work well, only change it if you are sure
+ * about what you're doing.
+ * @param time Time in ms
+ */
+ public void setMotionChangeTime(int time) {
+ this.motionchangetime=time;
+ }
+
+ public int getMotionChangeTime() {
+ return this.motionchangetime;
+ }
+
+}
diff --git a/src/org/wiigee/logic/Classifier.java b/src/org/wiigee/logic/Classifier.java
new file mode 100644
index 0000000..a8f1b5a
--- /dev/null
+++ b/src/org/wiigee/logic/Classifier.java
@@ -0,0 +1,109 @@
+/*
+ * wiigee - accelerometerbased gesture recognition
+ * Copyright (C) 2007, 2008, 2009 Benjamin Poppinga
+ *
+ * Developed at University of Oldenburg
+ * Contact: wiigee@benjaminpoppinga.de
+ *
+ * This file is part of wiigee.
+ *
+ * wiigee is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.wiigee.logic;
+
+import java.util.Vector;
+
+public class Classifier {
+
+ private Vector gesturemodel; // each gesturetype got its own
+ // gesturemodel in this vector
+ private double lastprob;
+
+ public Classifier() {
+ this.gesturemodel=new Vector();
+ this.lastprob=0.0;
+ }
+
+ /**
+ * This method recognize a specific gesture, given to the procedure.
+ * For classification a bayes classification algorithm is used.
+ *
+ * @param g gesture to classify
+ */
+ public int classifyGesture(Gesture g) {
+ //Log.write("Recognizing gesture...");
+
+ // Wert im Nenner berechnen, nach Bayes
+ double sum = 0;
+ for(int i=0; irecogprob) {
+ probgesture=tmpgesture;
+ probmodel=tmpmodel;
+ recogprob=((tmpmodel*tmpgesture)/sum);
+ recognized=i;
+ }
+ }
+
+ // a gesture could be recognized
+ if(recogprob>0 && probmodel>0 && probgesture>0 && sum>0) {
+ this.lastprob=recogprob;
+ return recognized;
+ } else {
+ // no gesture could be recognized
+ return -1;
+ }
+
+ }
+
+ public double getLastProbability() {
+ return this.lastprob;
+ }
+
+ public void addGestureModel(GestureModel gm) {
+ this.gesturemodel.add(gm);
+ }
+
+ public GestureModel getGestureModel(int id) {
+ return this.gesturemodel.elementAt(id);
+ }
+
+ public Vector getGestureModels() {
+ return this.gesturemodel;
+ }
+
+ public int getCountOfGestures() {
+ return this.gesturemodel.size();
+ }
+
+ public void clear() {
+ this.gesturemodel = new Vector();
+ }
+
+
+}
diff --git a/src/org/wiigee/logic/Gesture.java b/src/org/wiigee/logic/Gesture.java
new file mode 100755
index 0000000..2d1976a
--- /dev/null
+++ b/src/org/wiigee/logic/Gesture.java
@@ -0,0 +1,155 @@
+/*
+ * wiigee - accelerometerbased gesture recognition
+ * Copyright (C) 2007, 2008, 2009 Benjamin Poppinga
+ *
+ * Developed at University of Oldenburg
+ * Contact: wiigee@benjaminpoppinga.de
+ *
+ * This file is part of wiigee.
+ *
+ * wiigee is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.wiigee.logic;
+
+import java.util.Vector;
+import org.wiigee.event.AccelerationEvent;
+
+/**
+ * This class represents ONE movement trajectory in a
+ * concrete instance.
+ *
+ * @author Benjamin 'BePo' Poppinga
+ */
+
+public class Gesture implements Cloneable {
+
+ /** Min/MaxAcceleration setup manually? */
+ private boolean minmaxmanual;
+ private double minacc;
+ private double maxacc;
+
+ /** The complete trajectory as WiimoteAccelerationEvents
+ * as a vector. It's a vector because we don't want to
+ * loose the chronology of the stored events.
+ */
+ private Vector data;
+
+ /**
+ * Create an empty Gesture.
+ */
+ public Gesture() {
+ this.data = new Vector();
+ }
+
+ /**
+ * Make a deep copy of another Gesture object.
+ *
+ * @param original Another Gesture object
+ */
+ public Gesture(Gesture original) {
+ this.data = new Vector();
+ Vector origin = original.getData();
+ for (int i = 0; i < origin.size(); i++) {
+ this.add((AccelerationEvent) origin.get(i));
+ }
+ }
+
+
+ /**
+ * Adds a new acceleration event to this gesture.
+ *
+ * @param event The WiimoteAccelerationEvent to add.
+ */
+ public void add(AccelerationEvent event) {
+ this.data.add(event);
+ }
+
+ /**
+ * Returns the last acceleration added to this gesture.
+ *
+ * @return the last acceleration event added.
+ */
+ public AccelerationEvent getLastData() {
+ return (AccelerationEvent) this.data.get(this.data.size() - 1);
+ }
+
+ /**
+ * Returns the whole chronological sequence of accelerations as
+ * a vector.
+ *
+ * @return chronological sequence of accelerations.
+ */
+ public Vector getData() {
+ return this.data;
+ }
+
+ /**
+ * Removes the first element of the acceleration queue of a gesture
+ */
+ public void removeFirstData() {
+ this.data.remove(0);
+ }
+
+ public int getCountOfData() {
+ return this.data.size();
+ }
+
+ public void setMaxAndMinAcceleration(double max, double min) {
+ this.maxacc = max;
+ this.minacc = min;
+ this.minmaxmanual = true;
+ }
+
+ public double getMaxAcceleration() {
+ if(!this.minmaxmanual) {
+ double maxacc = Double.MIN_VALUE;
+ for(int i=0; i maxacc) {
+ maxacc=Math.abs(this.data.get(i).getX());
+ }
+ if(Math.abs(this.data.get(i).getY()) > maxacc) {
+ maxacc=Math.abs(this.data.get(i).getY());
+ }
+ if(Math.abs(this.data.get(i).getZ()) > maxacc) {
+ maxacc=Math.abs(this.data.get(i).getZ());
+ }
+ }
+ return maxacc;
+ } else {
+ return this.maxacc;
+ }
+ }
+
+ public double getMinAcceleration() {
+ if(!this.minmaxmanual) {
+ double minacc = Double.MAX_VALUE;
+ for(int i=0; i trainsequence) {
+ // summarize all vectors from the different gestures in one
+ // gesture called sum.
+ double maxacc=0;
+ double minacc=0;
+ Gesture sum = new Gesture();
+
+ for(int i=0; i t = trainsequence.elementAt(i).getData();
+
+ // add the max and min acceleration, we later get the average
+ maxacc+=trainsequence.elementAt(i).getMaxAcceleration();
+ minacc+=trainsequence.elementAt(i).getMinAcceleration();
+
+ // transfer every single accelerationevent of each gesture to
+ // the new gesture sum
+ for(int j=0; j seqs = new Vector();
+ for(int i=0; i defsequence) {
+ double prob=0;
+ for(int i=0; i trainsequence) {
+
+ double[][] a_new = new double[a.length][a.length];
+ double[][] b_new = new double[b.length][b[0].length];
+ // re calculate state change probability a
+ for(int i=0; i= 0; t--) {
+ for (int i = 0; i < numStates; i++) {
+ bwd[i][t] = 0;
+ for (int j = 0; j < numStates; j++)
+ bwd[i][t] += (bwd[j][t + 1] * a[i][j] * b[j][o[t + 1]]);
+ }
+ }
+ return bwd;
+ }
+
+
+
+ /**
+ * Prints everything about this model, including
+ * all values. For debug purposes or if you want
+ * to comprehend what happend to the model.
+ *
+ */
+ public void print() {
+ DecimalFormat fmt = new DecimalFormat();
+ fmt.setMinimumFractionDigits(5);
+ fmt.setMaximumFractionDigits(5);
+ for (int i = 0; i < numStates; i++)
+ Log.write("pi(" + i + ") = " + fmt.format(pi[i]));
+ Log.write("");
+ for (int i = 0; i < numStates; i++) {
+ for (int j = 0; j < numStates; j++)
+ Log.write("a(" + i + "," + j + ") = "
+ + fmt.format(a[i][j]) + " ");
+ Log.write("");
+ }
+ Log.write("");
+ for (int i = 0; i < numStates; i++) {
+ for (int k = 0; k < numObservations; k++)
+ Log.write("b(" + i + "," + k + ") = "
+ + fmt.format(b[i][k]) + " ");
+ Log.write("");
+ }
+ }
+
+ public double[] getPi() {
+ return this.pi;
+ }
+
+ public void setPi(double[] pi) {
+ this.pi = pi;
+ }
+
+ public double[][] getA() {
+ return this.a;
+ }
+
+ public void setA(double[][] a) {
+ this.a = a;
+ }
+
+ public double[][] getB() {
+ return this.b;
+ }
+
+ public void setB(double[][] b) {
+ this.b=b;
+ }
+}
diff --git a/src/org/wiigee/logic/PreciseHMM.java b/src/org/wiigee/logic/PreciseHMM.java
new file mode 100755
index 0000000..1155058
--- /dev/null
+++ b/src/org/wiigee/logic/PreciseHMM.java
@@ -0,0 +1,449 @@
+/*
+ * wiigee - accelerometerbased gesture recognition
+ * Copyright (C) 2007, 2008, 2009 Benjamin Poppinga
+ *
+ * Developed at University of Oldenburg
+ * Contact: wiigee@benjaminpoppinga.de
+ *
+ * This file is part of wiigee.
+ *
+ * wiigee is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.wiigee.logic;
+import java.text.*;
+import java.util.Vector;
+import java.lang.Math;
+import org.wiigee.util.Log;
+
+/**
+ * This is a Hidden Markov Model implementation which internally provides
+ * the basic algorithms for training and recognition (forward and backward
+ * algorithm). Since a regular Hidden Markov Model doesn't provide a possibility
+ * to train multiple sequences, this implementation has been optimized for this
+ * purposes using some state-of-the-art technologies described in several papers.
+ *
+ * @author Benjamin 'BePo' Poppinga
+ *
+ */
+
+public class PreciseHMM {
+ /** The number of states */
+ private int numStates;
+
+ /** The number of observations */
+ private int sigmaSize;
+
+ /** The initial probabilities for each state: p[state] */
+ public double pi[];
+
+ /** The state change probability to switch from state A to
+ * state B: a[stateA][stateB] */
+ public double a[][];
+
+ /** The probability to emit symbol S in state A: b[stateA][symbolS] */
+ public double b[][];
+
+ /**
+ * Initialize the Hidden Markov Model in a left-to-right version.
+ *
+ * @param numStates Number of states
+ * @param sigmaSize Number of observations
+ */
+ public PreciseHMM(int numStates, int sigmaSize) {
+ this.numStates = numStates;
+ this.sigmaSize = sigmaSize;
+ pi = new double[numStates];
+ a = new double[numStates][numStates];
+ b = new double[numStates][sigmaSize];
+ this.reset();
+ }
+
+ /**
+ * Reset the Hidden Markov Model to the initial left-to-right values.
+ *
+ */
+ private void reset() {
+ int jumplimit = 2;
+
+ // set startup probability
+ pi[0] = 1.0;
+ for(int i=1; ij-jumplimit-1) {
+ a[i][j] = 1.0/(jumplimit+1);
+ } else {
+ a[i][j] = 0.0;
+ }
+ }
+ }
+
+ // emission probability
+ for(int i=0; i trainsequence) {
+
+ double[][] a_new = new double[a.length][a.length];
+ double[][] b_new = new double[b.length][b[0].length];
+ // re calculate state change probability a
+ for(int i=0; i1 to sequence.length
+ // induction, further calculations
+ for(int t=1; tmax) {
+ max = val;
+ }
+ }
+
+ phi[j][t] = max + Math.log(this.b[j][o[t]]);
+ }
+ }
+ // conclusion
+ double lp = Double.NEGATIVE_INFINITY;
+ for(int i=0; ilp) {
+ lp = phi[i][o.length-1];
+ }
+ }
+
+ //Log.write("log p = "+lp);
+ //return lp;
+ // we now have log10(p) calculated, transform to p.
+ Log.write("prob = "+Math.exp(lp));
+ return Math.exp(lp);
+ //return Math.pow(10, lp);
+ }
+
+ /**
+ * Traditional Forward Algorithm.
+ *
+ * @param o the observationsequence O
+ * @return Array[State][Time]
+ *
+ */
+ private double[][] forwardProc(int[] o) {
+ double[][] f = new double[numStates][o.length];
+ for (int l = 0; l < f.length; l++) {
+ f[l][0] = pi[l] * b[l][o[0]];
+ }
+ for (int i = 1; i < o.length; i++) {
+ for (int k = 0; k < f.length; k++) {
+ double sum = 0;
+ for (int l = 0; l < numStates; l++) {
+ sum += f[l][i-1] * a[l][k];
+ }
+ f[k][i] = sum * b[k][o[i]];
+ }
+ }
+ return f;
+ }
+
+ /**
+ * Backward algorithm.
+ *
+ * @param o observation sequence o
+ * @return Array[State][Time]
+ */
+ private double[][] backwardProc(int[] o) {
+ int T = o.length;
+ double[][] bwd = new double[numStates][T];
+ /* Basisfall */
+ for (int i = 0; i < numStates; i++)
+ bwd[i][T - 1] = 1;
+ /* Induktion */
+ for (int t = T - 2; t >= 0; t--) {
+ for (int i = 0; i < numStates; i++) {
+ bwd[i][t] = 0;
+ for (int j = 0; j < numStates; j++)
+ bwd[i][t] += (bwd[j][t + 1] * a[i][j] * b[j][o[t + 1]]);
+ }
+ }
+ return bwd;
+ }
+
+
+
+ /**
+ * Prints everything about this model, including
+ * all values. For debug purposes or if you want
+ * to comprehend what happend to the model.
+ *
+ */
+ public void print() {
+ DecimalFormat fmt = new DecimalFormat();
+ fmt.setMinimumFractionDigits(10);
+ fmt.setMaximumFractionDigits(10);
+ for (int i = 0; i < numStates; i++)
+ Log.write("pi(" + i + ") = " + fmt.format(pi[i]));
+ Log.write("");
+ for (int i = 0; i < numStates; i++) {
+ for (int j = 0; j < numStates; j++)
+ Log.write("a(" + i + "," + j + ") = "
+ + fmt.format(a[i][j]) + " ");
+ Log.write("");
+ }
+ Log.write("");
+ for (int i = 0; i < numStates; i++) {
+ for (int k = 0; k < sigmaSize; k++)
+ Log.write("b(" + i + "," + k + ") = "
+ + fmt.format(b[i][k]) + " ");
+ Log.write("");
+ }
+ }
+
+ public double[][] getA() {
+ return this.a;
+ }
+
+ public void setA(double[][] a) {
+ this.a = a;
+ }
+
+ public double[][] getB() {
+ return this.b;
+ }
+
+ public void setB(double[][] b) {
+ this.b=b;
+ }
+}
diff --git a/src/org/wiigee/logic/ProcessingUnit.java b/src/org/wiigee/logic/ProcessingUnit.java
new file mode 100644
index 0000000..8a3adfa
--- /dev/null
+++ b/src/org/wiigee/logic/ProcessingUnit.java
@@ -0,0 +1,72 @@
+package org.wiigee.logic;
+
+import java.util.Vector;
+
+import org.wiigee.event.AccelerationEvent;
+import org.wiigee.event.ButtonPressedEvent;
+import org.wiigee.event.ButtonReleasedEvent;
+import org.wiigee.event.AccelerationListener;
+import org.wiigee.event.ButtonListener;
+import org.wiigee.event.GestureEvent;
+import org.wiigee.event.GestureListener;
+import org.wiigee.event.MotionStartEvent;
+import org.wiigee.event.MotionStopEvent;
+import org.wiigee.util.Log;
+
+public abstract class ProcessingUnit implements AccelerationListener, ButtonListener {
+
+ // Classifier
+ protected Classifier classifier;
+
+ // Listener
+ private Vector gesturelistener = new Vector();
+
+ public ProcessingUnit() {
+ this.classifier = new Classifier();
+ }
+
+ /**
+ * Add an GestureListener to receive GestureEvents.
+ *
+ * @param g
+ * Class which implements GestureListener interface.
+ */
+ public void addGestureListener(GestureListener g) {
+ this.gesturelistener.add(g);
+ }
+
+ protected void fireGestureEvent(boolean valid, int id, double probability) {
+ GestureEvent w = new GestureEvent(this, valid, id, probability);
+ for (int i = 0; i < this.gesturelistener.size(); i++) {
+ this.gesturelistener.get(i).gestureReceived(w);
+ }
+ }
+
+ public abstract void accelerationReceived(AccelerationEvent event);
+
+ public abstract void buttonPressReceived(ButtonPressedEvent event);
+
+ public abstract void buttonReleaseReceived(ButtonReleasedEvent event);
+
+ public abstract void motionStartReceived(MotionStartEvent event);
+
+ public abstract void motionStopReceived(MotionStopEvent event);
+
+ /**
+ * Resets the complete gesturemodel. After reset no gesture is known
+ * to the system.
+ */
+ public void reset() {
+ if (this.classifier.getCountOfGestures() > 0) {
+ this.classifier.clear();
+ Log.write("### Model reset ###");
+ } else {
+ Log.write("There doesn't exist any data to reset.");
+ }
+ }
+
+ // File IO
+ public abstract void loadGesture(String filename);
+
+ public abstract void saveGesture(int id, String filename);
+}
diff --git a/src/org/wiigee/logic/Quantizer.java b/src/org/wiigee/logic/Quantizer.java
new file mode 100755
index 0000000..aa24f1f
--- /dev/null
+++ b/src/org/wiigee/logic/Quantizer.java
@@ -0,0 +1,309 @@
+/*
+ * wiigee - accelerometerbased gesture recognition
+ * Copyright (C) 2007, 2008, 2009 Benjamin Poppinga
+ *
+ * Developed at University of Oldenburg
+ * Contact: wiigee@benjaminpoppinga.de
+ *
+ * This file is part of wiigee.
+ *
+ * wiigee is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.wiigee.logic;
+
+import java.util.Vector;
+import org.wiigee.event.AccelerationEvent;
+import org.wiigee.util.Log;
+
+/**
+ * This class implements a quantization component. In this case a
+ * k-mean-algorithm is used. In this case the initial values of the algorithm
+ * are ordered as two intersected circles, representing an abstract globe with
+ * k=14 elements. As a special feature the radius of this globe would be
+ * calculated dynamically before the training of this component.
+ *
+ * @author Benjamin 'BePo' Poppinga
+ */
+public class Quantizer {
+
+ /** This is the initial radius of this model. */
+ private double radius;
+
+ /** Number of states from the following Hidden Markov Model */
+ private int numStates;
+
+ /** The representation of the so called Centeroids */
+ private double[][] map;
+
+ /** True, if map is already trained. */
+ private boolean maptrained;
+
+ /**
+ * Initialize a empty quantizer. The states variable is necessary since some
+ * algorithms need this value to calculate their values correctly.
+ *
+ * @param numStates
+ * number of hidden markov model states
+ */
+ public Quantizer(int numStates) {
+ this.numStates = numStates;
+ this.map = new double[14][3];
+ this.maptrained = false;
+ }
+
+ /**
+ * Trains this Quantizer with a specific gesture. This means that the
+ * positions of the centeroids would adapt to this training gesture. In our
+ * case this would happen with a summarized virtual gesture, containing all
+ * the other gestures.
+ *
+ * @param gesture
+ * the summarized virtual gesture
+ */
+ public void trainCenteroids(Gesture gesture) {
+ Vector data = gesture.getData();
+ double pi = Math.PI;
+ this.radius = (gesture.getMaxAcceleration() + gesture
+ .getMinAcceleration()) / 2;
+ Log.write("Using radius: " + this.radius);
+
+ // x , z , y
+ if (!this.maptrained) {
+ this.maptrained = true;
+ this.map[0] = new double[] { this.radius, 0.0, 0.0 };
+ this.map[1] = new double[] { Math.cos(pi / 4) * this.radius, 0.0,
+ Math.sin(pi / 4) * this.radius };
+ this.map[2] = new double[] { 0.0, 0.0, this.radius };
+ this.map[3] = new double[] { Math.cos(pi * 3 / 4) * this.radius,
+ 0.0, Math.sin(pi * 3 / 4) * this.radius };
+ this.map[4] = new double[] { -this.radius, 0.0, 0.0 };
+ this.map[5] = new double[] { Math.cos(pi * 5 / 4) * this.radius,
+ 0.0, Math.sin(pi * 5 / 4) * this.radius };
+ this.map[6] = new double[] { 0.0, 0.0, -this.radius };
+ this.map[7] = new double[] { Math.cos(pi * 7 / 4) * this.radius,
+ 0.0, Math.sin(pi * 7 / 4) * this.radius };
+
+ this.map[8] = new double[] { 0.0, this.radius, 0.0 };
+ this.map[9] = new double[] { 0.0, Math.cos(pi / 4) * this.radius,
+ Math.sin(pi / 4) * this.radius };
+ this.map[10] = new double[] { 0.0,
+ Math.cos(pi * 3 / 4) * this.radius,
+ Math.sin(pi * 3 / 4) * this.radius };
+ this.map[11] = new double[] { 0.0, -this.radius, 0.0 };
+ this.map[12] = new double[] { 0.0,
+ Math.cos(pi * 5 / 4) * this.radius,
+ Math.sin(pi * 5 / 4) * this.radius };
+ this.map[13] = new double[] { 0.0,
+ Math.cos(pi * 7 / 4) * this.radius,
+ Math.sin(pi * 7 / 4) * this.radius };
+ }
+
+ int[][] g_alt = new int[this.map.length][data.size()];
+ int[][] g = new int[this.map.length][data.size()];
+
+ do {
+ // Derive new Groups...
+ g_alt = this.copyarray(g);
+ g = this.deriveGroups(gesture);
+
+ // calculate new centeroids
+ for (int i = 0; i < this.map.length; i++) {
+ double zaehlerX = 0;
+ double zaehlerY = 0;
+ double zaehlerZ = 0;
+ int nenner = 0;
+ for (int j = 0; j < data.size(); j++) {
+ if (g[i][j] == 1) {
+ zaehlerX += data.elementAt(j).getX();
+ zaehlerY += data.elementAt(j).getY();
+ zaehlerZ += data.elementAt(j).getZ();
+ nenner++;
+ }
+ }
+ if (nenner > 1) { // nur wenn der nenner>0 oder >1??? ist muss
+ // was
+ // geaendert werden
+ // Log.write("Setze neuen Centeroid!");
+ this.map[i] = new double[] {(zaehlerX / (double) nenner),
+ (zaehlerY / (double) nenner),
+ (zaehlerZ / (double) nenner) };
+ // Log.write("Centeroid: "+i+": "+newcenteroid[0]+":"+newcenteroid[1]);
+ }
+ } // new centeroids
+
+ } while (!equalarrays(g_alt, g));
+
+ // Debug: Printout groups
+ /*
+ * for (int i = 0; i < n; i++) { for (int j = 0; j < this.data.size();
+ * j++) { Log.write(g[i][j] + "|"); } Log.write(""); }
+ */
+
+ }
+
+ /**
+ * This methods looks up a Gesture to a group matrix, used by the
+ * k-mean-algorithm (traincenteroid method) above.
+ *
+ * @param gesture
+ * the gesture
+ */
+ public int[][] deriveGroups(Gesture gesture) {
+ Vector data = gesture.getData();
+ int[][] groups = new int[this.map.length][data.size()];
+
+ // Calculate cartesian distance
+ double[][] d = new double[this.map.length][data.size()];
+ double[] curr = new double[3];
+ double[] vector = new double[3];
+ for (int i = 0; i < this.map.length; i++) { // zeilen
+ double[] ref = this.map[i];
+ for (int j = 0; j < data.size(); j++) { // spalten
+
+ curr[0] = data.elementAt(j).getX();
+ curr[1] = data.elementAt(j).getY();
+ curr[2] = data.elementAt(j).getZ();
+
+ vector[0] = ref[0] - curr[0];
+ vector[1] = ref[1] - curr[1];
+ vector[2] = ref[2] - curr[2];
+ d[i][j] = Math.sqrt((vector[0] * vector[0])
+ + (vector[1] * vector[1]) + (vector[2] * vector[2]));
+ // Log.write(d[i][j] + "|");
+ }
+ // Log.write("");
+ }
+
+ // look, to which group a value belongs
+ for (int j = 0; j < data.size(); j++) {
+ double smallest = Double.MAX_VALUE;
+ int row = 0;
+ for (int i = 0; i < this.map.length; i++) {
+ if (d[i][j] < smallest) {
+ smallest = d[i][j];
+ row = i;
+ }
+ groups[i][j] = 0;
+ }
+ groups[row][j] = 1; // guppe gesetzt
+ }
+
+ // Debug output
+ /*
+ * for (int i = 0; i < groups.length; i++) { // zeilen for (int j = 0; j
+ * < groups[i].length; j++) { Log.write(groups[i][j] + "|"); }
+ * Log.write(""); }
+ */
+
+ return groups;
+
+ }
+
+ /**
+ * With this method you can transform a gesture to a discrete symbol
+ * sequence with values between 0 and granularity (number of observations).
+ *
+ * @param gesture
+ * Gesture to get the observationsequence to.
+ */
+ public int[] getObservationSequence(Gesture gesture) {
+ int[][] groups = this.deriveGroups(gesture);
+ Vector sequence = new Vector();
+
+ // Log.write("Visible symbol sequence: ");
+
+ for (int j = 0; j < groups[0].length; j++) { // spalten
+ for (int i = 0; i < groups.length; i++) { // zeilen
+ if (groups[i][j] == 1) {
+ // Log.write(" "+ i);
+ sequence.add(i);
+ break;
+ }
+ }
+ }
+
+ // die sequenz darf nicht zu kurz sein... mindestens so lang
+ // wie die anzahl der zustände. weil sonst die formeln nicht klappen.
+ // english: this is very dirty! it have to be here because if not
+ // too short sequences would cause an error. i've to think about a
+ // better resolution than copying the old value a few time.
+ while (sequence.size() < this.numStates) {
+ sequence.add(sequence.elementAt(sequence.size() - 1));
+ // Log.write(" "+sequence.elementAt(sequence.size()-1));
+ }
+
+ // Log.write("");
+
+ int[] out = new int[sequence.size()];
+ for (int i = 0; i < sequence.size(); i++) {
+ out[i] = sequence.elementAt(i);
+ }
+
+ return out;
+ }
+
+ /**
+ * Prints out the current centeroids-map. Its for debug or technical
+ * interests.
+ */
+ public void printMap() {
+ Log.write("Centeroids:");
+ for (int i = 0; i < this.map.length; i++) {
+ Log.write(i + ". :" + this.map[i][0] + ":"
+ + this.map[i][1] + ":" + this.map[i][2]);
+ }
+ }
+
+ /**
+ * Function to deepcopy an array.
+ */
+ private int[][] copyarray(int[][] alt) {
+ int[][] neu = new int[alt.length][alt[0].length];
+ for (int i = 0; i < alt.length; i++) {
+ for (int j = 0; j < alt[i].length; j++) {
+ neu[i][j] = alt[i][j];
+ }
+ }
+ return neu;
+ }
+
+ /**
+ * Function to look if the two arrays containing the same values.
+ */
+ private boolean equalarrays(int[][] one, int[][] two) {
+ for (int i = 0; i < one.length; i++) {
+ for (int j = 0; j < one[i].length; j++) {
+ if (!(one[i][j] == two[i][j])) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ public double getRadius() {
+ return this.radius;
+ }
+
+ public double[][] getHashMap() {
+ return this.map;
+ }
+
+ public void setUpManually(double[][] map, double radius) {
+ this.map = map;
+ this.radius = radius;
+ }
+}
diff --git a/src/org/wiigee/logic/TriggeredProcessingUnit.java b/src/org/wiigee/logic/TriggeredProcessingUnit.java
new file mode 100644
index 0000000..5a68344
--- /dev/null
+++ b/src/org/wiigee/logic/TriggeredProcessingUnit.java
@@ -0,0 +1,188 @@
+/*
+ * wiigee - accelerometerbased gesture recognition
+ * Copyright (C) 2007, 2008, 2009 Benjamin Poppinga
+ *
+ * Developed at University of Oldenburg
+ * Contact: wiigee@benjaminpoppinga.de
+ *
+ * This file is part of wiigee.
+ *
+ * wiigee is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.wiigee.logic;
+
+import java.util.Vector;
+import org.wiigee.event.*;
+import org.wiigee.util.Log;
+
+/**
+ * This class analyzes the AccelerationEvents emitted from a Wiimote
+ * and further creates and manages the different models for each type
+ * of gesture.
+ *
+ * @author Benjamin 'BePo' Poppinga
+ */
+public class TriggeredProcessingUnit extends ProcessingUnit {
+
+ // gesturespecific values
+ private Gesture current; // current gesture
+
+ private Vector trainsequence;
+
+ // State variables
+ private boolean learning, analyzing;
+
+ public TriggeredProcessingUnit() {
+ super();
+ this.learning=false;
+ this.analyzing=false;
+ this.current=new Gesture();
+ this.trainsequence=new Vector();
+ }
+
+ /**
+ * Since this class implements the WiimoteListener this procedure is
+ * necessary. It contains the filtering (directional equivalence filter)
+ * and adds the incoming data to the current motion, we want to train
+ * or recognize.
+ *
+ * @param event The acceleration event which has to be processed by the
+ * directional equivalence filter and which has to be added to the current
+ * motion in recognition or training process.
+ */
+ public void accelerationReceived(AccelerationEvent event) {
+ if(this.learning || this.analyzing) {
+ this.current.add(event); // add event to gesture
+ }
+ }
+
+ /**
+ * This method is from the WiimoteListener interface. A button press
+ * is used to control the data flow inside the structures.
+ *
+ */
+ public void buttonPressReceived(ButtonPressedEvent event) {
+ this.handleStartEvent(event);
+ }
+
+ public void buttonReleaseReceived(ButtonReleasedEvent event) {
+ this.handleStopEvent(event);
+ }
+
+ public void motionStartReceived(MotionStartEvent event) {
+ // this.handleStartEvent(event);
+ }
+
+ public void motionStopReceived(MotionStopEvent event) {
+ // this.handleStopEvent(event);
+ }
+
+ public void handleStartEvent(ActionStartEvent event) {
+
+ // TrainButton = record a gesture for learning
+ if((!this.analyzing && !this.learning) &&
+ event.isTrainInitEvent()) {
+ Log.write("Training started!");
+ this.learning=true;
+ }
+
+ // RecognitionButton = record a gesture for recognition
+ if((!this.analyzing && !this.learning) &&
+ event.isRecognitionInitEvent()) {
+ Log.write("Recognition started!");
+ this.analyzing=true;
+ }
+
+ // CloseGestureButton = starts the training of the model with multiple
+ // recognized gestures, contained in trainsequence
+ if((!this.analyzing && !this.learning) &&
+ event.isCloseGestureInitEvent()) {
+
+ if(this.trainsequence.size()>0) {
+ Log.write("Training the model with "+this.trainsequence.size()+" gestures...");
+ this.learning=true;
+
+ GestureModel m = new GestureModel();
+ m.train(this.trainsequence);
+ m.print();
+ this.classifier.addGestureModel(m);
+
+ this.trainsequence=new Vector();
+ this.learning=false;
+ } else {
+ Log.write("There is nothing to do. Please record some gestures first.");
+ }
+ }
+ }
+
+ public void handleStopEvent(ActionStopEvent event) {
+ if(this.learning) { // button release and state=learning, stops learning
+ if(this.current.getCountOfData()>0) {
+ Log.write("Finished recording (training)...");
+ Log.write("Data: "+this.current.getCountOfData());
+ Gesture gesture = new Gesture(this.current);
+ this.trainsequence.add(gesture);
+ this.current=new Gesture();
+ this.learning=false;
+ } else {
+ Log.write("There is no data.");
+ Log.write("Please train the gesture again.");
+ this.learning=false; // ?
+ }
+ }
+
+ else if(this.analyzing) { // button release and state=analyzing, stops analyzing
+ if(this.current.getCountOfData()>0) {
+ Log.write("Finished recording (recognition)...");
+ Log.write("Compare gesture with "+this.classifier.getCountOfGestures()+" other gestures.");
+ Gesture gesture = new Gesture(this.current);
+
+ int recognized = this.classifier.classifyGesture(gesture);
+ if(recognized!=-1) {
+ double recogprob = this.classifier.getLastProbability();
+ this.fireGestureEvent(true, recognized, recogprob);
+ Log.write("######");
+ Log.write("Gesture No. "+recognized+" recognized: "+recogprob);
+ Log.write("######");
+ } else {
+ this.fireGestureEvent(false, 0, 0.0);
+ Log.write("######");
+ Log.write("No gesture recognized.");
+ Log.write("######");
+ }
+
+ this.current=new Gesture();
+ this.analyzing=false;
+ } else {
+ Log.write("There is no data.");
+ Log.write("Please recognize the gesture again.");
+ this.analyzing=false; // ?
+ }
+ }
+ }
+
+ @Override
+ public void loadGesture(String filename) {
+ GestureModel g = org.wiigee.util.FileIO.readFromFile(filename);
+ this.classifier.addGestureModel(g);
+ }
+
+ @Override
+ public void saveGesture(int id, String filename) {
+ org.wiigee.util.FileIO.writeToFile(this.classifier.getGestureModel(id), filename);
+ }
+
+}
diff --git a/src/org/wiigee/util/FileIO.java b/src/org/wiigee/util/FileIO.java
new file mode 100644
index 0000000..82f6fc1
--- /dev/null
+++ b/src/org/wiigee/util/FileIO.java
@@ -0,0 +1,233 @@
+/*
+ * wiigee - accelerometerbased gesture recognition
+ * Copyright (C) 2007, 2008, 2009 Benjamin Poppinga
+ *
+ * Developed at University of Oldenburg
+ * Contact: wiigee@benjaminpoppinga.de
+ *
+ * This file is part of wiigee.
+ *
+ * wiigee is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+package org.wiigee.util;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import org.wiigee.logic.GestureModel;
+import org.wiigee.logic.HMM;
+import org.wiigee.logic.Quantizer;
+
+/**
+ * This is a static class to support saving and loading complete gestures. I've
+ * choosen not to use some kind of XML, because the big multidimensional arrays
+ * would cause a huge senseless amount of xml-data. So KISS: Keep It Simple,
+ * Stupid! ;) Comma-separated-vectors with some control data.
+ *
+ * @author Benjamin 'BePo' Poppinga
+ *
+ */
+public class FileIO {
+
+ public static void writeToFile(GestureModel m, String name) {
+ try {
+ // initialize file and get values
+ BufferedWriter out = new BufferedWriter(new FileWriter(name+".txt"));
+ int numStates = m.getNumStates();
+ int numObservations = m.getNumObservations();
+ double defaultProbability = m.getDefaultProbability();
+ Quantizer quantizer = m.getQuantizer();
+ HMM hmm = m.getHMM();
+
+ out.write("# numStates:");
+ out.newLine();
+ out.write(Integer.toString(numStates));
+ out.newLine();
+
+ out.write("# numObservations:");
+ out.newLine();
+ out.write(Integer.toString(numObservations));
+ out.newLine();
+
+ out.write("# defaultProbability:");
+ out.newLine();
+ out.write(Double.toString(defaultProbability));
+ out.newLine();
+
+ out.write("# Quantizer: Radius");
+ out.newLine();
+ out.write(Double.toString(quantizer.getRadius()));
+ out.newLine();
+ out.write("# Quantizer: MAP");
+ out.newLine();
+ double[][] map = quantizer.getHashMap();
+ for(int v=0; v=n) {
+ if(mode==Log.PRINT) {
+ // console output enabled
+ if(o!=null) {
+ System.out.println(o.getClass()+": "+s);
+ } else {
+ System.out.println(s);
+ }
+ } else if(mode==Log.FILE) {
+ // file output enabled
+ // TODO
+ }
+ }
+ }
+
+}
diff --git a/test/org/wiigee/logic/ClassifierTest.java b/test/org/wiigee/logic/ClassifierTest.java
new file mode 100644
index 0000000..ff995dd
--- /dev/null
+++ b/test/org/wiigee/logic/ClassifierTest.java
@@ -0,0 +1,128 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.wiigee.logic;
+
+import java.util.Vector;
+import junit.framework.TestCase;
+import org.wiigee.device.Device;
+import org.wiigee.event.AccelerationEvent;
+
+/**
+ *
+ * @author bepo
+ */
+public class ClassifierTest extends TestCase {
+
+ public ClassifierTest(String testName) {
+ super(testName);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Test of classifyGesture method, of class Classifier.
+ */
+ public void testClassifyGesture() {
+
+ // create a pseudo-device
+ Device d = new Device(true);
+
+ // create 3 gestures
+ Gesture g0 = new Gesture();
+ Gesture g1 = new Gesture();
+ Gesture g2 = new Gesture();
+
+ g0.add(new AccelerationEvent(d, 0.0, 0.0, 0.0, 0.0));
+ g0.add(new AccelerationEvent(d, 1.0, 1.0, 1.0, 0.0));
+ g0.add(new AccelerationEvent(d, 2.0, 2.0, 2.0, 0.0));
+ g0.add(new AccelerationEvent(d, 1.0, 1.0, 1.0, 0.0));
+
+ g1.add(new AccelerationEvent(d, -1.0, 1.0, -1.0, 0.0));
+ g1.add(new AccelerationEvent(d, -1.0, 3.0, -1.0, 0.0));
+ g1.add(new AccelerationEvent(d, -1.0, 1.0, -1.0, 0.0));
+ g1.add(new AccelerationEvent(d, -1.0, 3.0, -1.0, 0.0));
+
+ g2.add(new AccelerationEvent(d, -2.0, -2.0, -2.0, -2.0));
+ g2.add(new AccelerationEvent(d, -2.0, -2.0, -2.0, -2.0));
+ g2.add(new AccelerationEvent(d, -2.0, -2.0, -2.0, -2.0));
+ g2.add(new AccelerationEvent(d, -2.0, -2.0, -2.0, -2.0));
+
+ // create 3 gesturesets with 1 gesture each
+ Vector gs0 = new Vector();
+ Vector gs1 = new Vector();
+ Vector gs2 = new Vector();
+ gs0.add(g0);
+ gs1.add(g1);
+ gs2.add(g2);
+
+ // create three gesturemodels and train these
+ GestureModel gm0 = new GestureModel();
+ GestureModel gm1 = new GestureModel();
+ GestureModel gm2 = new GestureModel();
+ gm0.train(gs0);
+ gm1.train(gs1);
+ gm2.train(gs2);
+
+ // create a classifier and add gesturemodels
+ Classifier classifier = new Classifier();
+ classifier.addGestureModel(gm0);
+ classifier.addGestureModel(gm1);
+ classifier.addGestureModel(gm2);
+
+ // classify gesture
+ int result0 = classifier.classifyGesture(g0);
+ int result1 = classifier.classifyGesture(g1);
+ int result2 = classifier.classifyGesture(g2);
+
+ if((result0 != 0) ||
+ (result1 != 1) ||
+ (result2 != 2)) {
+ fail("Wrong gesture classified.");
+ }
+
+ }
+
+
+
+ /**
+ * Test of addGestureModel method, of class Classifier.
+ */
+ public void testAddGestureModel() {
+ }
+
+ /**
+ * Test of getGestureModel method, of class Classifier.
+ */
+ public void testGetGestureModel() {
+ }
+
+ /**
+ * Test of getGestureModels method, of class Classifier.
+ */
+ public void testGetGestureModels() {
+ }
+
+ /**
+ * Test of getCountOfGestures method, of class Classifier.
+ */
+ public void testGetCountOfGestures() {
+ }
+
+ /**
+ * Test of clear method, of class Classifier.
+ */
+ public void testClear() {
+ }
+
+}
diff --git a/test/org/wiigee/logic/HMMTest.java b/test/org/wiigee/logic/HMMTest.java
new file mode 100644
index 0000000..d24039d
--- /dev/null
+++ b/test/org/wiigee/logic/HMMTest.java
@@ -0,0 +1,73 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.wiigee.logic;
+
+import java.util.Vector;
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+/**
+ *
+ * @author bepo
+ */
+public class HMMTest extends TestCase {
+
+ public HMMTest(String testName) {
+ super(testName);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Probabilistic test of the train method, of class HMM.
+ */
+ public void testTrain() {
+ System.out.println("train");
+
+ HMM instance = new HMM(8, 14);
+
+ // setup a trainsequence
+ Vector trainsequence = new Vector();
+ trainsequence.add(new int[] { 0, 1, 2, 1, 6, 4, 3, 2});
+ trainsequence.add(new int[] { 0, 1, 2, 2, 6, 3, 3, 1});
+ trainsequence.add(new int[] { 0, 1, 2, 2, 6, 3, 2, 2});
+
+ // setup a failing trainsequence
+ int[] fail = new int[] { 5, 5, 5, 5, 5, 5, 5, 5};
+
+ // train the hmm
+ instance.train(trainsequence);
+
+ double probA = instance.getProbability(trainsequence.elementAt(0));
+ double probB = instance.getProbability(trainsequence.elementAt(1));
+ double probC = instance.getProbability(trainsequence.elementAt(2));
+ double probFAIL = instance.getProbability(fail);
+
+ System.out.println("probA = "+probA);
+ System.out.println("probB = "+probB);
+ System.out.println("probC = "+probC);
+ System.out.println("probFAIL = "+probFAIL);
+
+ if((probA <= 1.0E-10) ||
+ (probB <= 1.0E-10) ||
+ (probC <= 1.0E-10)) {
+ fail("Probabilities to low to be accurate.");
+ }
+
+ if(probFAIL > 0.0) {
+ fail("Fake probability to high.");
+ }
+ }
+
+}