The GestureModel doesn't contain an ID anymore since this is now managed by the Classifier dynamically. Gesture Saving therefore would become more flexible with the next release containing GestureSets with exchangeable Gestures. To any who already use the save/load function of wiigee: Please remove the first two lines within the saved gesture files (that's the id). Then it should work properly.

git-svn-id: svn://svn.code.sf.net/p/wiigee/code/trunk@69 c7eff9ee-dd40-0410-8832-91a4d88773cf
This commit is contained in:
bepo23
2009-05-24 10:45:15 +00:00
parent db24e35e51
commit 2f76a84321
7 changed files with 189 additions and 196 deletions

View File

@@ -21,12 +21,14 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package control;
import java.io.IOException;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.bluetooth.BluetoothStateException;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.LocalDevice;
@@ -38,151 +40,157 @@ import filter.Filter;
// Singleton
public class WiimoteWiigee {
protected static String version = "1.3.1 alpha";
protected static String releasedate = "20081215";
protected static WiimoteWiigee instance;
private static Object lock = new Object();
private Vector<Wiimote> devices;
private WiimoteWiigee() throws IOException {
Log.write("This is wiigee version "+version+" ("+releasedate+")");
this.devices=this.discoverWiimotes();
for(int i=0; i<this.devices.size(); i++) {
this.devices.elementAt(i).setLED(i+1);
}
}
private WiimoteWiigee(String btaddr) throws IOException {
Log.write("This is wiigee version "+version+" ("+releasedate+")");
this.devices = new Vector<Wiimote>();
this.devices.add(new Wiimote(btaddr));
for(int i=0; i<this.devices.size(); i++) {
this.devices.elementAt(i).setLED(i+1);
}
}
public static WiimoteWiigee getInstance() throws IOException {
if(instance==null) {
instance=new WiimoteWiigee();
return instance;
} else {
return instance;
}
}
public static WiimoteWiigee getInstance(String btaddr) throws IOException {
if(instance==null) {
instance=new WiimoteWiigee(btaddr);
return instance;
} else {
return instance;
}
}
/**
* Returns an array of discovered wiimotes.
*
* @return Array of discovered wiimotes or null if
* none discoverd.
*/
public Wiimote[] getDevices() {
Wiimote[] out = new Wiimote[this.devices.size()];
for(int i=0; i<this.devices.size(); i++) {
out[i] = this.devices.elementAt(i);
}
return out;
}
/**
* Discover the wiimotes around the bluetooth host and
* make them available public via getWiimotes method.
*
* @return Array of discovered wiimotes.
*/
private Vector<Wiimote> discoverWiimotes() throws IOException {
WiimoteDeviceDiscovery deviceDiscovery = new WiimoteDeviceDiscovery(lock);
LocalDevice localDevice = LocalDevice.getLocalDevice();
Log.write("Your Computers Bluetooth MAC: "+localDevice.getBluetoothAddress());
DiscoveryAgent discoveryAgent = localDevice.getDiscoveryAgent();
Log.write("Starting device inquiry...");
discoveryAgent.startInquiry(DiscoveryAgent.GIAC, deviceDiscovery);
try {
synchronized(lock){
lock.wait();
}
} catch (InterruptedException e) {
Log.write("Problems during device discovery.");
e.printStackTrace();
}
protected static String version = "1.5 alpha";
protected static String releasedate = "20090524";
protected static WiimoteWiigee instance;
private static Object lock = new Object();
private Vector<Wiimote> devices;
Log.write("Device discovery completed!");
return deviceDiscovery.getDiscoveredWiimotes();
}
/**
* Returns the number of wiimotes discovered.
*
* @return Number of wiimotes discovered.
*/
public int getNumberOfDevices() {
return this.devices.size();
}
/**
* Sets the Trainbutton for all wiimotes;
*
* @param b Button encoding, see static Wiimote values
*/
public void setTrainButton(int b) {
for(int i=0; i<this.devices.size(); i++) {
this.devices.elementAt(i).setTrainButton(b);
}
}
/**
* Sets the Recognitionbutton for all wiimotes;
*
* @param b Button encoding, see static Wiimote values
*/
public void setRecognitionButton(int b) {
for(int i=0; i<this.devices.size(); i++) {
this.devices.elementAt(i).setRecognitionButton(b);
}
}
/**
* Sets the CloseGesturebutton for all wiimotes;
*
* @param b Button encoding, see static Wiimote values
*/
public void setCloseGestureButton(int b) {
for(int i=0; i<this.devices.size(); i++) {
this.devices.elementAt(i).setCloseGestureButton(b);
}
}
public void addDeviceListener(DeviceListener listener) {
if(this.devices.size()>0) {
this.devices.elementAt(0).addDeviceListener(listener);
}
}
public void addGestureListener(GestureListener listener) {
if(this.devices.size()>0) {
this.devices.elementAt(0).addGestureListener(listener);
}
}
public void addFilter(Filter filter) {
if(this.devices.size()>0) {
this.devices.elementAt(0).addFilter(filter);
}
}
private WiimoteWiigee() {
String stack;
String stackVersion;
String l2capFeature;
String bluecoveVersion;
Log.write("This is wiigee version " + version + " (" + releasedate + ")");
// Bluecove
bluecoveVersion = LocalDevice.getProperty("bluecove");
if(!bluecoveVersion.equals("")) {
stack = LocalDevice.getProperty("bluecove.stack");
stackVersion = LocalDevice.getProperty("bluecove.stack.version");
Log.write("You are using the "+stack+" Bluetooth stack (Version "+stackVersion+")");
l2capFeature = LocalDevice.getProperty("bluecove.feature.l2cap");
Log.write("L2CAP supported: "+l2capFeature);
if(l2capFeature.equals("true")) {
Log.write("wiigee: found a supported stack!");
// set min id for Bluecove
Log.write(Log.DEBUG, "JSR82 PSM Minimum Restriction -- OFF", null);
System.setProperty("bluecove.jsr82.psm_minimum_off", "true");
}
} else {
Log.write("No Bluecove Library detected - trying anyway...");
}
}
public static WiimoteWiigee getInstance() {
if (instance == null) {
instance = new WiimoteWiigee();
return instance;
} else {
return instance;
}
}
/**
* Returns an array of discovered wiimotes.
*
* @return Array of discovered wiimotes or null if
* none discoverd.
*/
public Wiimote[] getDevices() throws IOException {
this.devices = this.discoverWiimotes();
for (int i = 0; i < this.devices.size(); i++) {
this.devices.elementAt(i).setLED(i + 1);
}
Wiimote[] out = new Wiimote[this.devices.size()];
for (int i = 0; i < this.devices.size(); i++) {
out[i] = this.devices.elementAt(i);
}
return out;
}
/**
* Discover the wiimotes around the bluetooth host and
* make them available public via getWiimotes method.
*
* @return Array of discovered wiimotes.
*/
private Vector<Wiimote> discoverWiimotes() throws IOException {
WiimoteDeviceDiscovery deviceDiscovery = new WiimoteDeviceDiscovery(lock);
LocalDevice localDevice = LocalDevice.getLocalDevice();
Log.write("Your Computers Bluetooth MAC: " + localDevice.getBluetoothAddress());
Log.write("Starting device inquiry...");
DiscoveryAgent discoveryAgent = localDevice.getDiscoveryAgent();
discoveryAgent.startInquiry(DiscoveryAgent.GIAC, deviceDiscovery);
try {
synchronized (lock) {
lock.wait();
}
} catch (InterruptedException e) {
Log.write("Problems during device discovery.");
e.printStackTrace();
}
Log.write("Device discovery completed!");
return deviceDiscovery.getDiscoveredWiimotes();
}
/**
* Returns the number of wiimotes discovered.
*
* @return Number of wiimotes discovered.
*/
public int getNumberOfDevices() {
return this.devices.size();
}
/**
* Sets the Trainbutton for all wiimotes;
*
* @param b Button encoding, see static Wiimote values
*/
public void setTrainButton(int b) {
for (int i = 0; i < this.devices.size(); i++) {
this.devices.elementAt(i).setTrainButton(b);
}
}
/**
* Sets the Recognitionbutton for all wiimotes;
*
* @param b Button encoding, see static Wiimote values
*/
public void setRecognitionButton(int b) {
for (int i = 0; i < this.devices.size(); i++) {
this.devices.elementAt(i).setRecognitionButton(b);
}
}
/**
* Sets the CloseGesturebutton for all wiimotes;
*
* @param b Button encoding, see static Wiimote values
*/
public void setCloseGestureButton(int b) {
for (int i = 0; i < this.devices.size(); i++) {
this.devices.elementAt(i).setCloseGestureButton(b);
}
}
public void addDeviceListener(DeviceListener listener) {
for (int i = 0; i < this.devices.size(); i++) {
this.devices.elementAt(i).addDeviceListener(listener);
}
}
public void addGestureListener(GestureListener listener) {
for (int i = 0; i < this.devices.size(); i++) {
this.devices.elementAt(i).addGestureListener(listener);
}
}
public void addFilter(Filter filter) {
for (int i = 0; i < this.devices.size(); i++) {
this.devices.elementAt(i).addFilter(filter);
}
}
}

View File

@@ -27,7 +27,6 @@ package device;
import java.io.IOException;
import java.util.Vector;
import logic.ProcessingUnit;
import logic.*;
import event.*;
import filter.DirectionalEquivalenceFilter;
@@ -53,13 +52,13 @@ public class Device {
// Listeners, receive generated events
protected Vector<DeviceListener> devicelistener = new Vector<DeviceListener>();
protected ProcessingUnit analyzer = new TriggeredProcessingUnit();
protected ProcessingUnit processingunit = new TriggeredProcessingUnit();
public Device() {
this.addFilter(new IdleStateFilter());
this.addFilter(new MotionDetectFilter(this));
this.addFilter(new DirectionalEquivalenceFilter());
this.addDeviceListener(this.analyzer);
this.addDeviceListener(this.processingunit);
}
/**
@@ -98,7 +97,7 @@ public class Device {
* this gesture.
*/
public void addGestureListener(GestureListener listener) {
this.analyzer.addGestureListener(listener);
this.processingunit.addGestureListener(listener);
System.out.println("GestureListener added...");
}
@@ -126,8 +125,8 @@ public class Device {
this.closegesturebutton=b;
}
public ProcessingUnit getAccelerationStreamAnalyzer() {
return this.analyzer;
public ProcessingUnit getProcessingUnit() {
return this.processingunit;
}
public boolean accelerationEnabled() {
@@ -141,6 +140,14 @@ public class Device {
public void disableAccelerationSensors() throws IOException {
this.accelerationenabled=false;
}
public void loadGesture(String filename) {
this.processingunit.loadGesture(filename);
}
public void saveGesture(int id, String filename) {
this.processingunit.saveGesture(id, filename);
}
// ###### Event-Methoden

View File

@@ -96,6 +96,10 @@ public class Classifier {
public Vector<GestureModel> getGestureModels() {
return this.gesturemodel;
}
public int getCountOfGestures() {
return this.gesturemodel.size();
}
public void clear() {
this.gesturemodel = new Vector<GestureModel>();

View File

@@ -42,9 +42,6 @@ public class GestureModel {
/** The number of observations for the hmm and k-mean */
private int numObservations;
/** The id representation of this model */
private int id;
/** The quantization component */
private Quantizer quantizer;
@@ -61,8 +58,7 @@ public class GestureModel {
* @param id
* int representation of a gesture "name"/class.
*/
public GestureModel(int id) {
this.id=id;
public GestureModel() {
this.numStates=8; // n=8 states empirical value
this.numObservations=14; // k=14 observations empirical value
this.markovmodell = new HMM(numStates, numObservations); // init model
@@ -133,7 +129,7 @@ public class GestureModel {
* For debug purposes or very technical interested people. :)
*/
public void printMap() {
System.out.println("Gesture "+this.id+" Quantizer-Map:");
System.out.println("Gesture Quantizer-Map:");
this.quantizer.printMap();
}
@@ -142,20 +138,11 @@ public class GestureModel {
* @return
*/
public void print() {
System.out.println("Debug Output for Gesture "+this.id);
System.out.println("HMM-Print:");
this.markovmodell.print();
System.out.println("Quanzizer-Print:");
this.quantizer.printMap();
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id=id;
}
public int getNumStates() {
return this.numStates;

View File

@@ -21,11 +21,9 @@ public abstract class ProcessingUnit implements DeviceListener {
// Listener
private Vector<GestureListener> listen = new Vector<GestureListener>();
protected int gesturecount;
public ProcessingUnit() {
this.classifier = new Classifier();
this.gesturecount=0;
}
/**
@@ -69,7 +67,7 @@ public abstract class ProcessingUnit implements DeviceListener {
* to the system.
*/
public void reset() {
if(this.gesturecount>0) {
if(this.classifier.getCountOfGestures()>0) {
this.classifier.clear();
System.out.println("### Model reset ###");
} else {
@@ -78,8 +76,8 @@ public abstract class ProcessingUnit implements DeviceListener {
}
// File IO
public abstract void loadGesture(String name);
public abstract void loadGesture(String filename);
public abstract void saveGesture(int id, String name);
public abstract void saveGesture(int id, String filename);
}

View File

@@ -122,7 +122,7 @@ public class TriggeredProcessingUnit extends ProcessingUnit {
this.fireStateEvent(1);
this.learning=true;
GestureModel m = new GestureModel(this.gesturecount++);
GestureModel m = new GestureModel();
m.train(this.trainsequence);
m.print();
this.classifier.addGestureModel(m);
@@ -154,7 +154,7 @@ public class TriggeredProcessingUnit extends ProcessingUnit {
else if(this.analyzing) { // button release and state=analyzing, stops analyzing
if(this.current.getCountOfData()>0) {
System.out.println("Finished recording (recognition)...");
System.out.println("Compare gesture with "+this.gesturecount+" other gestures.");
System.out.println("Compare gesture with "+this.classifier.getCountOfGestures()+" other gestures.");
Gesture gesture = new Gesture(this.current);
int recognized = this.classifier.classifyGesture(gesture);
@@ -182,15 +182,14 @@ public class TriggeredProcessingUnit extends ProcessingUnit {
}
@Override
public void loadGesture(String name) {
this.gesturecount++;
GestureModel g = util.FileIO.readFromFile(name);
public void loadGesture(String filename) {
GestureModel g = util.FileIO.readFromFile(filename);
this.classifier.addGestureModel(g);
}
@Override
public void saveGesture(int id, String name) {
util.FileIO.writeToFile(this.classifier.getGestureModel(id), name);
public void saveGesture(int id, String filename) {
util.FileIO.writeToFile(this.classifier.getGestureModel(id), filename);
}
}

View File

@@ -48,19 +48,12 @@ public class FileIO {
try {
// initialize file and get values
BufferedWriter out = new BufferedWriter(new FileWriter(name+".txt"));
int id = m.getId();
int numStates = m.getNumStates();
int numObservations = m.getNumObservations();
double defaultProbability = m.getDefaultProbability();
Quantizer quantizer = m.getQuantizer();
HMM hmm = m.getHMM();
// write to file
out.write("# ID:");
out.newLine();
out.write(Integer.toString(id));
out.newLine();
out.write("# numStates:");
out.newLine();
out.write(Integer.toString(numStates));
@@ -161,21 +154,18 @@ public class FileIO {
if(!line.startsWith("#")) { // isn't a comment
switch (position++) {
case 0:
id = Integer.parseInt(line);
break;
case 1:
numStates = Integer.parseInt(line);
break;
case 2:
case 1:
numObservations = Integer.parseInt(line);
break;
case 3:
case 2:
defaultprobability = Double.parseDouble(line);
break;
case 4:
case 3:
radius = Double.parseDouble(line);
break;
case 5:
case 4:
map = new double[numObservations][3];
for(int i=0; i<numObservations; i++) {
String s[] = line.split(", ");
@@ -186,14 +176,14 @@ public class FileIO {
line = in.ready() ? in.readLine() : "";
}
break;
case 6:
case 5:
pi = new double[numStates];
String pi_row[] = line.split(", ");
for(int i=0; i<numStates; i++) {
pi[i] = Double.parseDouble(pi_row[i]);
}
break;
case 7:
case 6:
a = new double[numStates][numStates];
for(int i=0; i<numStates; i++) {
String a_row[] = line.split(", ");
@@ -203,7 +193,7 @@ public class FileIO {
line = in.ready() ? in.readLine() : "";
}
break;
case 8:
case 7:
b = new double[numStates][numObservations];
for(int i=0; i<numStates; i++) {
String b_row[] = line.split(", ");
@@ -220,7 +210,7 @@ public class FileIO {
}
}
GestureModel ret = new GestureModel(id);
GestureModel ret = new GestureModel();
ret.setDefaultProbability(defaultprobability);
Quantizer quantizer = new Quantizer(numStates);