/** * Copyright (C) 2006-2008 Human-Computer Interaction Group, University of Konstanz. All Rights Reserved. * * This software is the proprietary information of University of Konstanz. * Use is subject to license terms. * * Please contact info@squidy-lib.de or visit our website http://hci.uni-konstanz.de * for further information. */ package org.squidy.nodes; import java.util.Vector; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlType; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.squidy.manager.controls.CheckBox; import org.squidy.manager.controls.TextField; import org.squidy.manager.data.IData; import org.squidy.manager.data.Processor; import org.squidy.manager.data.Property; import org.squidy.manager.data.Processor.Status; import org.squidy.manager.data.impl.DataButton; import org.squidy.manager.data.impl.DataDigital; import org.squidy.manager.data.impl.DataGesture; import org.squidy.manager.data.impl.DataInertial; import org.squidy.manager.data.impl.DataKey; import org.squidy.manager.model.AbstractNode; import wiigee.device.Wiimote; import wiigee.event.GestureEvent; import wiigee.event.GestureListener; import wiigee.event.StateEvent; import wiigee.event.WiimoteAccelerationEvent; import wiigee.event.WiimoteButtonPressedEvent; import wiigee.event.WiimoteButtonReleasedEvent; import wiigee.event.WiimoteListener; import wiigee.logic.AccelerationStreamAnalyzer; /** * <code>GestureRecognizerWiiGee</code>. * * <pre> * Date: Feb 19, 2008 * Time: 5:13:03 PM * </pre> * * @author Werner Koenig, werner.koenig@uni-konstanz.de, University of Konstanz * @author Roman Rädle, <a * href="mailto:Roman.Raedle@uni-konstanz.de">Roman.Raedle@uni-konstanz.de</a>, * University of Konstanz * @version 1.0 */ @XmlType(name = "GestureRecognizerWiiGee") @Processor( name = "Gesture Recognizer WiiGee", types = { Processor.Type.FILTER }, tags = { "gesture", "recognizer", "wii" }, status = Status.UNSTABLE ) public class GestureRecognizerWiiGee extends AbstractNode implements GestureListener { // Logger to log info, error, debug,... messages. private static final Log LOG = LogFactory.getLog(GestureRecognizerWiiGee.class); // ################################################################################ // BEGIN OF ADJUSTABLES // ################################################################################ @XmlAttribute(name = "threshold") @Property( name = "Threshold", description = "Value threshold for adding to recognizer" ) @TextField private double threshold = 0.02; public double getThreshold() { return threshold; } public void setThreshold(double threshold) { this.threshold = threshold; } @XmlAttribute(name = "learning-mode") @Property( name = "Learning mode", description = "True if system is in learning mode, false for recognition mode" ) @CheckBox private boolean learningMode = false; public boolean getLearningMode() { return learningMode; } public void setLearningMode(boolean learningMode) { this.learningMode = learningMode; } // ################################################################################ // END OF ADJUSTABLES // ################################################################################ private AccelerationStreamAnalyzer analyzer; private Wiimote wiimote; // Listeners, receive generated events Vector<WiimoteListener> listen = new Vector<WiimoteListener>(); private DataGesture gestureReceived = null; private boolean doVibrate = false; /* (non-Javadoc) * @see org.squidy.manager.model.AbstractNode#onStart() */ @Override public void onStart() { wiimote = new Wiimote(""); analyzer = new AccelerationStreamAnalyzer(); addWiimoteListener(analyzer); analyzer.addGestureListener(this); } /* (non-Javadoc) * @see org.squidy.manager.model.AbstractNode#onStop() */ @Override public void onStop() { if (wiimote != null) { wiimote.disconnect(); } if (listen != null) { listen.remove(analyzer); } if (analyzer != null) { analyzer = null; } } /** * @param dataInertial * @return */ public IData process(DataInertial dataInertial) { if (dataInertial.getAbsoluteValue() > (1 + threshold) || dataInertial.getAbsoluteValue() < (1 - threshold)) { WiimoteAccelerationEvent w = new WiimoteAccelerationEvent(wiimote, dataInertial.getX(), dataInertial.getY(), dataInertial.getZ()); for (int i = 0; i < this.listen.size(); i++) { this.listen.get(i).accelerationReceived(w); } } // TODO Werner: Replace button handling with pipeline specific // context filtering. if (doVibrate) { doVibrate = false; return new DataDigital(this.getClass(), true); } return null; } /** * To Recognize with Wii do follwing: 1. Do gesture while holding '+'-Button multiple times; 2. Train model with 'A'-Button after each unique gesture; 3. Recognize gesture with 'B'-Button * @param dataButton * @return */ public IData process(DataButton dataButton) { gestureReceived = null; // switches between learning and recognition mode for phidget joystick (laserpointer-interaction) if (dataButton.getButtonType() == DataButton.BUTTON_STICK_LEFT) { if (dataButton.getFlag()) { learningMode = !learningMode; LOG.info("Learning Mode = " + getLearningMode()); } } // switch to learning mode and sample gesture if ((dataButton.getButtonType() == DataButton.BUTTON_2 && learningMode) || dataButton.getButtonType() == DataButton.BUTTON_PLUS) { learningMode = true; if (dataButton.getFlag()) { startSampleLearning(); } else { stopSample(); } } // switch to recognition mode and sample gesture else if ((dataButton.getButtonType() == DataButton.BUTTON_2 && !learningMode) || dataButton.getButtonType() == DataButton.BUTTON_B) { learningMode = false; if (dataButton.getFlag()) { startSampleRecognition(); } else { stopSample(); } } // train recognition model after multiple execution of the same gesture else if (dataButton.getButtonType() == DataButton.BUTTON_STICK_DOWN || dataButton.getButtonType() == DataButton.BUTTON_A) { if (dataButton.getFlag()) { trainModel(); } } if (gestureReceived != null) { return gestureReceived; } if (doVibrate) { doVibrate = false; return new DataDigital(this.getClass(), true); } return null; } /** * To Recognize with Wii do follwing: 1. Do gesture while holding '+'-Button multiple times; 2. Train model with 'A'-Button after each unique gesture; 3. Recognize gesture with 'B'-Button * @param dataButton * @return */ public IData process(DataKey dataKey) { gestureReceived = null; System.out.println(dataKey.getKeyType()); // // switches between learning and recognition mode for phidget joystick (laserpointer-interaction) // if (dataKey.getKeyType() == DataKey.class) { // if (dataButton.getFlag()) { // learningMode = !learningMode; // LOG.info("Learning Mode = " + getLearningMode()); // } // } // // // // switch to learning mode and sample gesture // if ((dataButton.getButtonType() == DataButton.BUTTON_2 && learningMode) // || dataButton.getButtonType() == DataButton.BUTTON_PLUS) { // learningMode = true; // if (dataButton.getFlag()) { // startSampleLearning(); // } else { // stopSample(); // } // } // // // switch to recognition mode and sample gesture // else if ((dataButton.getButtonType() == DataButton.BUTTON_2 && !learningMode) // || dataButton.getButtonType() == DataButton.BUTTON_B) { // learningMode = false; // if (dataButton.getFlag()) { // startSampleRecognition(); // } else { // stopSample(); // } // } // // // train recognition model after multiple execution of the same gesture // else if (dataButton.getButtonType() == DataButton.BUTTON_STICK_DOWN // || dataButton.getButtonType() == DataButton.BUTTON_A) { // if (dataButton.getFlag()) { // trainModel(); // } // } // // if (gestureReceived != null) { // return gestureReceived; // } // // if (doVibrate) { // doVibrate = false; // return new DataDigital(this.getClass(), "Vibrate", true); // } return null; } public void gestureReceived(GestureEvent event) { // logger.info("New Gesture Event: "+event.getName()+" // "+event.getProbability()+" "+event.getSource()); gestureReceived = new DataGesture(GestureRecognizerWiiGee.class, "" + event.getGesture().getGestureType(), event.getGesture().getGestureNumber(), event.getGesture().getGestureType(), true); } public void noGestureRecognized() { doVibrate = true; } public void stateReceived(StateEvent event) { // System.out.println("New State Event: "+event.getState()+" // "+event.getSource()); } /** * Adds an WiimoteListener to the wiimote. Everytime an action on the * wiimote is performed the WiimoteListener would receive an event of this * action. */ public void addWiimoteListener(WiimoteListener listener) { this.listen.add(listener); } public void startSampleLearning() { fireButtonPressedEvent(4); } public void startSampleRecognition() { fireButtonPressedEvent(3); } public void trainModel() { fireButtonPressedEvent(8); } public void stopSample() { fireButtonReleasedEvent(); } /** * Fires a button pressed event. * * @param button * Integer value of the pressed button. */ public void fireButtonPressedEvent(int button) { WiimoteButtonPressedEvent w = new WiimoteButtonPressedEvent(wiimote, button); for (int i = 0; i < this.listen.size(); i++) { this.listen.get(i).buttonPressReceived(w); } } /** * Fires a button released event. */ public void fireButtonReleasedEvent() { WiimoteButtonReleasedEvent w = new WiimoteButtonReleasedEvent(wiimote); for (int i = 0; i < this.listen.size(); i++) { this.listen.get(i).buttonReleaseReceived(w); } } }