/**
* Squidy Interaction Library 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 3 of the License,
* or (at your option) any later version.
*
* Squidy Interaction Library 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 Squidy Interaction Library. If not, see
* <http://www.gnu.org/licenses/>.
*
* 2009 Human-Computer Interaction Group, University of Konstanz.
* <http://hci.uni-konstanz.de>
*
* Please contact info@squidy-lib.de or visit our website
* <http://www.squidy-lib.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.DataConstant;
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>GestureRecognizerPhidget</code>.
*
* <pre>
* Date: Nov 21, 2008
* Time: 5:13:03 PM
* </pre>
*
* @author Werner Koenig, werner.koenig@uni-konstanz.de, University of Konstanz
* @author Stefan Dierdorf, <a
* href="mailto:Stefan.Dierdorf@uni-konstanz.de">Stefan.Dierdorf@uni-konstanz.de</a>,
* University of Konstanz
* @version 1.0
*/
@XmlType(name = "GestureRecognizerPhidget")
@Processor(
name = "Gesture Recognizer Phidget",
types = { Processor.Type.FILTER },
tags = { "gesture", "recognizer", "phidget" },
status = Status.UNSTABLE
)
public class GestureRecognizerPhidget extends AbstractNode implements GestureListener {
// Logger to log info, error, debug,... messages.
private static final Log LOG = LogFactory.getLog(GestureRecognizerPhidget.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;
}
@XmlAttribute(name = "output-sensor-index")
@Property(
name = "Output sensor index"
)
@TextField
private int outputSensorIndex = 0;
/**
* @return the outputSensorIndex
*/
public final int getOutputSensorIndex() {
return outputSensorIndex;
}
/**
* @param outputSensorIndex
* the outputSensorIndex to set
*/
public final void setOutputSensorIndex(int outputSensorIndex) {
this.outputSensorIndex = outputSensorIndex;
}
// ################################################################################
// END OF ADJUSTABLES
// ################################################################################
private AccelerationStreamAnalyzer analyzer;
private Wiimote wiimote;
// Listeners, receive generated events
Vector<WiimoteListener> listen = new Vector<WiimoteListener>();
private DataGesture gestureReceived = null;
/* (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);
}
}
return null;
}
/**
* To Recognize with PhidgetAcceleromter and KeyboardInput do following:
* 1. Activate 'learningMode' by pressing 't'-Key;
* 2. Do gesture multiple times while holding 'space'-bar on Keyboard-Input Window;
* 3. Train model with 'return'-Key on Keyboard-Input Window after each unique gesture;
* 4. After all gestures have been trained press 't' to leave learningMode;
* 5. Recognize gesture with 'space'-bar on MouseWindow ('learningMode' has to be deactivated);
* @param dataButton
* @return
*/
public IData process(DataKey dataKey) {
gestureReceived = null;
// keyType 84 for 't'; enables/disables learning-mode
if(!dataKey.getFlag() && dataKey.getKeyType() == 84 ) {
learningMode = !learningMode;
LOG.info("Learning Mode = " + getLearningMode());
}
// keyType 32 for 'space-key'; hold to learn gesture
// switch to learning mode and sample gesture
if(dataKey.getKeyType() == 32 && learningMode) {
learningMode = true;
if(dataKey.getFlag() && dataKey.getFlag()) {
startSampleLearning();
} else {
stopSample();
}
}
// keyType 10 for 'return-key'; finalizes gesture
// train recognition model after multiple execution of the same gesture
else if (dataKey.getKeyType() == 10) {
if (dataKey.getFlag()) {
trainModel();
}
}
// keyType 32 for 'space-key'; hold to recognize gesture (after gesture has been learned)
// switch to recognition mode and sample gesture
else if(dataKey.getKeyType() == 32 && !learningMode) {
learningMode = false;
if (dataKey.getFlag()) {
startSampleRecognition();
} else {
stopSample();
}
}
if (gestureReceived != null) {
return gestureReceived;
}
return null;
}
/**
* To Recognize with PhidgetAcceleromter, Keyboard and (Touch-)Button do following:
* 1. Activate 'learningMode' by pressing 't'-Key;
* 2. Do gesture multiple times while holding (Touch-)Button;
* 3. Train model with 'RighMouse'-Button on MouseWindow and 'lerningMode' deactivated after each unique gesture;
* 4. Recognize gesture with 'LeftMouse'-Button on MouseWindow and 'lerningMode' deactivated;
* @param dataButton
* @return
*/
public IData process(DataDigital dataDigital) {
gestureReceived = null;
if(learningMode) {
learningMode = true;
if (dataDigital.getFlag()) {
startSampleLearning();
} else {
stopSample();
}
}
// switch to recognition mode and sample gesture
else if(!learningMode) {
learningMode = false;
if (dataDigital.getFlag()) {
startSampleRecognition();
} else {
stopSample();
}
}
if (gestureReceived != null) {
DataDigital dataDigi = new DataDigital(GestureRecognizerPhidget.class, true);
dataDigi.setAttribute(DataConstant.TACTILE, true);
publish(dataDigi);
return gestureReceived;
}
return null;
}
/**
* To Recognize with PhidgetAcceleromter and Mouse do following:
* 1. Activate 'learningMode' in Designer;
* 2. Do gesture multiple times while holding 'LeftMouse'-Button on MouseWindow;
* 3. Train model with 'RighMouse'-Button on MouseWindow and 'lerningMode' deactivated after each unique gesture;
* 4. Recognize gesture with 'LeftMouse'-Button on MouseWindow and 'lerningMode' deactivated;
* @param dataButton
* @return
*/
public IData process(DataButton dataButton) {
gestureReceived = null;
if(dataButton.getButtonType() == 1 && learningMode) {
learningMode = true;
if (dataButton.getFlag()) {
startSampleLearning();
} else {
stopSample();
}
}
// switch to recognition mode and sample gesture
else if(dataButton.getButtonType() == 1 && !learningMode) {
learningMode = false;
if (dataButton.getFlag()) {
startSampleRecognition();
} else {
stopSample();
}
}
// train recognition model after multiple execution of the same gesture
else if (dataButton.getButtonType() == 3 && !learningMode) {
if (dataButton.getFlag()) {
trainModel();
}
}
if (gestureReceived != null) {
return gestureReceived;
}
return null;
}
public void gestureReceived(GestureEvent event) {
// logger.info("New Gesture Event: "+event.getName()+"
// "+event.getProbability()+" "+event.getSource());
gestureReceived = new DataGesture(GestureRecognizerPhidget.class, "" + event.getGesture().getGestureType(),
event.getGesture().getGestureNumber(), event.getGesture().getGestureType(), 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);
}
}
public void noGestureRecognized() {
// TODO Auto-generated method stub
}
}