1 /*
2  * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "gesture_predictor.hpp"
18 
19 #include "constants.hpp"
20 
21 namespace {
22 	/* State for the averaging algorithm we're using. */
23 	float prediction_history[kGestureCount][kPredictionHistoryLength] = {};
24 	int prediction_history_index = 0;
25 	int prediction_suppression_count = 0;
26 } /* namespace */
27 
28 /* Return the result of the last prediction
29  * 0: wing("W"), 1: ring("O"), 2: slope("angle"), 3: unknown
30  */
PredictGesture(float * output)31 int PredictGesture(float *output)
32 {
33 	/* Record the latest predictions in our rolling history buffer. */
34 	for (int i = 0; i < kGestureCount; ++i) {
35 		prediction_history[i][prediction_history_index] = output[i];
36 	}
37 	/* Figure out which slot to put the next predictions into. */
38 	++prediction_history_index;
39 	if (prediction_history_index >= kPredictionHistoryLength) {
40 		prediction_history_index = 0;
41 	}
42 
43 	/* Average the last n predictions for each gesture, and find which has the
44 	 * highest score.
45 	 */
46 	int max_predict_index = -1;
47 	float max_predict_score = 0.0f;
48 	for (int i = 0; i < kGestureCount; i++) {
49 		float prediction_sum = 0.0f;
50 		for (int j = 0; j < kPredictionHistoryLength; ++j) {
51 			prediction_sum += prediction_history[i][j];
52 		}
53 		const float prediction_average = prediction_sum / kPredictionHistoryLength;
54 		if ((max_predict_index == -1) || (prediction_average > max_predict_score)) {
55 			max_predict_index = i;
56 			max_predict_score = prediction_average;
57 		}
58 	}
59 
60 	/* If there's been a recent prediction, don't trigger a new one too soon. */
61 	if (prediction_suppression_count > 0) {
62 		--prediction_suppression_count;
63 	}
64 	/* If we're predicting no gesture, or the average score is too low, or there's
65 	 * been a gesture recognised too recently, return no gesture.
66 	 */
67 	if ((max_predict_index == kNoGesture) ||
68 	    (max_predict_score < kDetectionThreshold) ||
69 	    (prediction_suppression_count > 0)) {
70 		return kNoGesture;
71 	} else {
72 		/* Reset the suppression counter so we don't come up with another prediction
73 		 * too soon.
74 		 */
75 		prediction_suppression_count = kPredictionSuppressionDuration;
76 		return max_predict_index;
77 	}
78 }
79