From 893170e54fec74f7b9004a44ba48a60accbacac5 Mon Sep 17 00:00:00 2001
From: Alexis Iakovenko <alexis.iakovenko@gmail.com>
Date: Wed, 10 Jan 2018 17:30:09 +0100
Subject: [PATCH] Compute mean for replay

---
 Assets/Gesture/Gesture.cs | 104 +++++++++++++++++++++++++++++++++-----
 1 file changed, 92 insertions(+), 12 deletions(-)

diff --git a/Assets/Gesture/Gesture.cs b/Assets/Gesture/Gesture.cs
index a439190..8332081 100644
--- a/Assets/Gesture/Gesture.cs
+++ b/Assets/Gesture/Gesture.cs
@@ -18,10 +18,9 @@ public class Gesture
 
 	public Gesture (string name, GestureType type = GestureType.Normal)
 	{
+		states = new List<GestureState> ();
 		this.name = name;
-		if (type == GestureType.Normal)
-			Load ();
-		else if (type == GestureType.Mean)
+		if (type == GestureType.Mean)
 			ComputeMean ();
 		else if (type == GestureType.Variance)
 			ComputeVariance ();
@@ -29,34 +28,115 @@ public class Gesture
 
 	void ComputeMean ()
 	{
+		//Debug.Log ("[Gesture:ComputeMean] Start computing mean ");
+
 		//find and load gestures to compare for the mean
 		List<Gesture> gesturesToMean = new List<Gesture> ();
 		string path = "Assets/Record/Recorded/" + name + "/";
-		foreach (string gesturePath in Directory.GetDirectories (path))
+		//Debug.Log ("[Gesture:ComputeMean] path " + path);
+		foreach (string gesturePath in Directory.GetFiles (path))
 		{
-			if (!gesturePath.Equals (path + "mean.txt") && !gesturePath.Equals (path + "variance.txt"))
+			//Debug.Log ("[Gesture:ComputeMean] gesturePath " + gesturePath);
+			if (gesturePath.Substring(gesturePath.Length - 4).Equals(".txt") &&
+				!gesturePath.Equals (path + "mean.txt") && !gesturePath.Equals (path + "variance.txt"))
 			{
-				Gesture gesture = new Gesture(gesturePath);
-				gesture.Load ();
+				Gesture gesture = new Gesture(name);
+				gesture.Load (gesturePath);
 				gesturesToMean.Add(gesture);
 			}
 		}
 
-		//compute the mean
+		if (gesturesToMean.Count == 0)
+			return;
+		
+
+		//find mean time and normalize towards it
+		int meanTime = 0;
+		foreach (Gesture gesture in gesturesToMean)
+			meanTime += gesture.states.Count;
+		meanTime /= gesturesToMean.Count;
+		foreach (Gesture gesture in gesturesToMean)
+			gesture.NormalizeTime (meanTime);
+
+		//for each frame, compute position and rotation mean
+		for (int i = 0; i < meanTime; i++)
+		{
+			Vector3 positionMean = new Vector3 (0, 0, 0);
+			Vector4 rotationMean = new Vector4 (0, 0, 0, 0);
+			float timestampMean = 0.0f;
+
+			foreach (Gesture gesture in gesturesToMean)
+			{
+				timestampMean += gesture.states [i].timestamp;
+				positionMean += gesture.states [i].position;
+				rotationMean += gesture.states [i].rotation;
+			}
+
+			timestampMean /= gesturesToMean.Count;
+			positionMean /= gesturesToMean.Count;
+			rotationMean /= gesturesToMean.Count;
+
+			GestureState stateMean = new GestureState ();
+			stateMean.position = positionMean;
+			stateMean.rotation = rotationMean;
+			stateMean.timestamp = timestampMean;
+			states.Add (stateMean);
+		}
+
+		Debug.Log ("[Gesture:ComputeMean] Finished computing mean " + meanTime);
 	}
 
 	void ComputeVariance ()
 	{
 	}
 
-	public void Load ()
+	public void NormalizeTime(int pointNumber)
 	{
-		states = GestureLoader.Load (FullPath ());
+		if (pointNumber == states.Count)
+			return;
+		
+		float timeNormalizationFactor = pointNumber * 1.0f / states.Count;
+		//Debug.Log ("Time normalization, factor: " + timeNormalizationFactor);
+		List<GestureState> normalizedStates = new List<GestureState>();
+
+		float timestampStep = (states [states.Count - 1].timestamp - states [0].timestamp) / (states.Count - 1);
+		float normalizedTimestamp = states [0].timestamp;
+		for (int i = 0; i < pointNumber; i++)
+		{
+			GestureState normalizedState = new GestureState ();
+
+			int stateID = (int)Mathf.Floor(i / timeNormalizationFactor);
+			GestureState currentState = states [stateID];
+			Vector3 normalizedPosition = states [stateID].position;
+			Vector3 normalizedRotation = states [stateID].rotation;
+
+			if (stateID > 0 && stateID < states.Count - 1)
+			{
+				GestureState nextState = states [stateID + 1];
+				float smallTimestamp = (normalizedTimestamp - currentState.timestamp);
+				if (smallTimestamp != 0) {
+					float smallFactor = (nextState.timestamp - currentState.timestamp) / smallTimestamp;
+
+					Vector3 positionToNextState = nextState.position - currentState.position;
+					normalizedPosition = currentState.position + positionToNextState * smallFactor;
+
+					Vector4 rotationToNextState = nextState.rotation - currentState.rotation;
+					normalizedRotation = currentState.rotation + rotationToNextState * smallFactor;
+				}
+			}
+			normalizedState.position = normalizedPosition;
+			normalizedState.rotation = normalizedRotation;
+			normalizedState.timestamp = normalizedTimestamp;
+			normalizedStates.Add (normalizedState);
+
+			normalizedTimestamp += timestampStep;
+		}
+		states = normalizedStates;
 	}
 
-	private string FullPath ()
+	public void Load (string path)
 	{
-		return directoryPath + name + ".txt";
+		states = GestureLoader.Load (path);
 	}
 
 	public override string ToString ()
-- 
GitLab