package com.dronecontrol.perceptual.components;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.dronecontrol.perceptual.PerceptualPipeline;
import com.dronecontrol.perceptual.data.events.GestureData;
import com.dronecontrol.perceptual.listeners.GestureListener;
import intel.pcsdk.PXCMGesture;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class GestureComponent implements PerceptualQueryComponent {
private static final int GESTURE_NUBMER_THRESHOLD = 2;
private static final int NUMBER_OF_GESTURE_SAMPLES = 5;
private Set<GestureListener> gestureListeners = Sets.newHashSet();
private PXCMGesture.Gesture gesture;
private List<Integer> lastGestureLabels = Lists.newArrayList();
private GestureData.GestureType currentlyActiveGestureType;
private final Map<Integer, GestureData.GestureType> gestureTypeMap = new LinkedHashMap<Integer, GestureData.GestureType>() {{
put(PXCMGesture.Gesture.LABEL_ANY, GestureData.GestureType.NONE);
put(PXCMGesture.Gesture.LABEL_POSE_THUMB_UP, GestureData.GestureType.THUMBS_UP);
put(PXCMGesture.Gesture.LABEL_POSE_THUMB_DOWN, GestureData.GestureType.THUMBS_DOWN);
put(PXCMGesture.Gesture.LABEL_POSE_BIG5, GestureData.GestureType.BIG_FIVE);
}};
public GestureComponent() {
currentlyActiveGestureType = GestureData.GestureType.NONE;
}
@Override
public void queryFeatures(PerceptualPipeline pipeline) {
gesture = new PXCMGesture.Gesture();
pipeline.QueryGesture(PXCMGesture.Gesture.LABEL_ANY, gesture);
}
@Override
public void processFeatures() {
addLabelToLastGestureLabels();
Map<Integer, Integer> labelCountMap = determineLabelCountMap();
Integer detectedLabel = getDetectedLabel(labelCountMap);
if (!gestureTypeMap.containsKey(detectedLabel)) {
return;
}
GestureData.GestureType gestureType = gestureTypeMap.get(detectedLabel);
invokeGesture(gestureType);
}
private void addLabelToLastGestureLabels() {
lastGestureLabels.add(gesture.label);
while (lastGestureLabels.size() > NUMBER_OF_GESTURE_SAMPLES) {
lastGestureLabels.remove(0);
}
}
private Map<Integer, Integer> determineLabelCountMap() {
Map<Integer, Integer> gestureLabelCount = Maps.newHashMap();
for (Integer label : lastGestureLabels) {
if (label == PXCMGesture.Gesture.LABEL_ANY) {
continue;
}
if (!gestureLabelCount.containsKey(label)) {
gestureLabelCount.put(label, 0);
}
int oldCount = gestureLabelCount.get(label);
gestureLabelCount.put(label, oldCount + 1);
}
return gestureLabelCount;
}
private Integer getDetectedLabel(Map<Integer, Integer> gestureLabelCount) {
Integer labelWithHighestEntryCount = PXCMGesture.Gesture.LABEL_ANY;
Integer maxCount = 0;
for (Map.Entry<Integer, Integer> entry : gestureLabelCount.entrySet()) {
int currentLabel = entry.getKey();
int currentCount = entry.getValue();
if (currentCount > maxCount) {
labelWithHighestEntryCount = currentLabel;
maxCount = currentCount;
}
}
return maxCount > GESTURE_NUBMER_THRESHOLD ? labelWithHighestEntryCount : PXCMGesture.Gesture.LABEL_ANY;
}
private void invokeGesture(GestureData.GestureType gestureType) {
if (currentlyActiveGestureType != gestureType) {
currentlyActiveGestureType = gestureType;
invokeGestureListeners(new GestureData(gestureType));
}
}
public void addGestureListener(GestureListener gestureListener) {
if (!gestureListeners.contains(gestureListener)) {
gestureListeners.add(gestureListener);
}
}
public void removeGestureListener(GestureListener gestureListener) {
if (gestureListeners.contains(gestureListener)) {
gestureListeners.remove(gestureListener);
}
}
private void invokeGestureListeners(GestureData data) {
for (GestureListener listener : gestureListeners) {
listener.onGesture(data);
}
}
}