Search Unity

Grabbing position data from previous frame?

Discussion in 'Scripting' started by Theformand, May 2, 2011.

  1. Theformand

    Theformand

    Joined:
    Jan 2, 2010
    Posts:
    271
    Hey guys.

    I can currently log positional data for any gameobject right. I have this data stored in an array each frame. If, however I would like to compare positional data from last frame with data from current frame, how would I go about doing that?

    currently I store data in my array during Update, but Im a little confused as to how I would save this for the previous frame aswell.
     
  2. billykater

    billykater

    Joined:
    Mar 12, 2011
    Posts:
    329
    Basic idea: Record your position as the last step in your update call. Then use it at the beginning of the update call and set it afterwards.

    Code (csharp):
    1.  
    2. var lastPosition : Vector3;
    3.  
    4. function Update()
    5. {
    6.     var currentPosition = transform.position;
    7.     if(currentPosition != lastPosition)
    8.     {
    9.            //Do something
    10.     }
    11.  
    12.     lastPostion = currentPosition;
    13. }
    14.  
    Your example: As you already store all positions access the next to last or last position stored in the array
    Code (csharp):
    1.  
    2. function Update()
    3. {
    4.     var lastPosition = arr[arr.length-1];
    5.  
    6.    arr.push(transform.position);
    7. }
    8.  
    I am guessing that you are using array.push to get a new value into the array each frame. In short don't do this.
    1. Ever increasing memory consumption
    2. Every increasing cost to resize the array and copy all old elements. This leads to lower performance over time.
    Use something like a .NET System.Collections.Generic.LinkedList for this purpose. It is designed to add values often but takes longer to access individual values. And remove values that aren't absolutely necessary for recording position values.
    Code (csharp):
    1.  
    2. import System.Collections.Generic;
    3.  
    4. var positions : LinkedList.<Vector3> = new LinkedList.<Vector3>();
    5.  
    6. function Update()
    7. {
    8.    var currentPosition = transform.position;
    9.    if(currentPosition != positions.Last)
    10.    {
    11.        //Do something
    12.    }
    13.  
    14.    positions.AddLast(transform.position);
    15.    if(positions.Count > 10)
    16.       positions.RemoveFirst();
    17. }
    18.  
    This will only record the last 10 values but it will also make adding faster (especially over a longer period of time).
     
    emredesu, hms0589 and Voodin like this.
  3. Theformand

    Theformand

    Joined:
    Jan 2, 2010
    Posts:
    271
    Well, currently I'm just recording X,Y,and Z of 3 gameobjects, storing them in an array like so:


    Code (csharp):
    1.     rX = GameObject.Find("RightHand").transform.position.x;
    2.         rY = GameObject.Find("RightHand").transform.position.y;
    3.         rZ = GameObject.Find("RightHand").transform.position.z;
    4.         lX = GameObject.Find("LeftHand").transform.position.x;
    5.         lX = GameObject.Find("LeftHand").transform.position.y;
    6.         lX = GameObject.Find("LeftHand").transform.position.z;
    7.         hX = GameObject.Find("Head").transform.position.x;
    8.         hY = GameObject.Find("Head").transform.position.y;
    9.         hZ = GameObject.Find("Head").transform.position.z;
    10.         dist = Vector3.Distance(GameObject.Find("RightHand").transform.position,
    11.         GameObject.Find("LeftHand").transform.position); // Distance between hands
    12.        
    13.         loggingData[0] = rX-hX; // Fill our trackingData Array with coordinates normalized by head coordinates
    14.         loggingData[1] = rY-hY;
    15.         loggingData[2] = rZ-hZ;
    16.         loggingData[3] = lX-hX;
    17.         loggingData[4] = lY-hY;
    18.         loggingData[5] = lZ-hZ;
    19.         loggingData[6] = dist;
    But what I really need is the data that is represented by the CHANGE of these values from one frame to the next. This basically means that for each frame, I want to fill an array with "currentPosition - lastPosition" in all X,Y and Z coordinates. This data represents what happens between two frames, when the person Im recording does a gesture. These changes should then be fed to an AI, that will classify the gesture based on the changes that happened, say, over the last 50 frames.

    I see that I should probably do the initial operations with Vector3's instead of my current approach.
     
  4. Theformand

    Theformand

    Joined:
    Jan 2, 2010
    Posts:
    271
    So, we're still trying to get positional data between frames, ie, the DIFFERENCE between X,Y,Z for a given gameObject from one frame to the next. The gameObjects we are logging, are bound to the hands of a real person tracked by a Kinect sensor.


    We are moderately successful here, However, as I try and move one hand out in a straight line from my chest, and back again I see weird Z coordinates. The difference should never be absolutely 0 (which it is, alot), and we get both positive and negative values.

    We're fairly sure we are doing something wrong, because the difference between the Z coordinate of, say right hand, should never be absolutely zero, with noise from the sensor etc.

    The code below is used to track X,Y,Z for two hands--> subtract this frame from previous frame ->>>store result in an array----> print that array to a textfile:

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.IO;
    4. using System.Collections.Generic;
    5.  
    6. public class DeltaLogger : MonoBehaviour {
    7.     TextWriter tw;
    8.     string coordText;
    9.     bool isRecording = false;
    10.     string fileName;
    11.     int gestureNumber = 1;
    12.     int last = 0;
    13.     public int subjectNumber = 1;
    14.    
    15.    
    16.     Vector3 RcurrentPosition = Vector3.zero;
    17.     Vector3 RlastPosition = Vector3.zero;
    18.    
    19.     Vector3 LcurrentPosition = Vector3.zero;
    20.     Vector3 LlastPosition = Vector3.zero;
    21.     Vector3 RdeltaPos = Vector3.zero;
    22.     Vector3 LdeltaPos = Vector3.zero;
    23.     public static float[] DeltaData = new float[6];
    24.    
    25.  
    26.     // Use this for initialization
    27.     void Start () {
    28.    
    29.    
    30.     }
    31.    
    32.     // Update is called once per frame
    33.     void Update () {
    34.         RcurrentPosition = GameObject.Find("RightHand").transform.position;
    35.         LcurrentPosition = GameObject.Find("LeftHand").transform.position;
    36.        
    37.        
    38.             RdeltaPos = RcurrentPosition-RlastPosition;
    39.             LdeltaPos = LcurrentPosition-LlastPosition;
    40.        
    41.         //THIS LOOP IS IN HERE TO TRY AND "SLOW DOWN" THE DATA LOGGING A LITTLE BIT, BECAUSE WE WERE SEEING VALUES OF 0
    42.             int i = 0;
    43.         for (i = 0; i<100;i++){
    44.             if (i == 99){
    45.                
    46.                             DeltaData[0] = RdeltaPos.x;// Logging the delta value between  every nth frame.
    47.                             DeltaData[1] = RdeltaPos.y;
    48.                             DeltaData[2] = RdeltaPos.z;
    49.                             DeltaData[3] = LdeltaPos.x;
    50.                             DeltaData[4] = LdeltaPos.y;
    51.                             DeltaData[5] = LdeltaPos.z;
    52.                             }
    53.            
    54.         }
    55.        
    56.            
    57.         coordText = DeltaData[0]+","+DeltaData[1]+","+DeltaData[2]+","+DeltaData[3]+","+DeltaData[4]+","+DeltaData[5]; //THIS ARRAY IS WRITTEN TO A .TXT FILE
    58.        
    59.         RlastPosition=RcurrentPosition;
    60.         LlastPosition=LcurrentPosition;
    61.        
    62.        
    63.             if(Input.GetButtonUp("Record")){
    64.             if (isRecording){
    65.                 gestureNumber++;
    66.             }
    67.             isRecording =! isRecording;
    68.         }
    69.        
    70.         if (isRecording){
    71.             print("now recording!");
    72.             if(last!=gestureNumber){
    73.             //CHANGE "Subject1" FOR EACH PERSON WE RECORD DATA FROM
    74.                 fileName = "gesture_"+gestureNumber+"_subject"+subjectNumber+".txt";
    75.                 tw = new StreamWriter(fileName);
    76.                 last = gestureNumber;
    77.             }
    78.             WriteFile();
    79.         }else{
    80.         print ("Not Recording");
    81.            
    82.         }
    83.    
    84.        
    85.     }
    86.    
    87.     void WriteFile(){
    88.         tw.WriteLine(coordText);
    89.         tw.Flush();
    90.     }
    91.  
    92. }
    93.  
    This is an example of how the data looks like in our textfile. The format is RighthandX,Y,Z,LefthandX,Y,Z

    Code (csharp):
    1. -0.0004701614,-0.004965782,-0.003121376,0.002326012,0.00288105,0.002052307
    2. 0.005212784,0.0008687973,0.0006198883,0.0008010864,-0.008641243,-0.001255989
    3. -0.003873825,0.008699417,-0.007691383,0.001119614,-0.006913185,-0.005511284
    4. 0,0,0,0,0,0
    5. 0,0,0,0,0,0
    6. 0.001065254,-0.008709908,0.004149437,0.0005846024,-0.001550674,-0.004159927
    7. 0,0,0,0,0,0
    8. 0.003034592,0.007703781,-0.0009698868,-0.003093719,-0.004745483,-0.0001564026
    9. 0.005313873,-0.001126289,-0.010396,0.002266884,0.002176285,-0.002153397
    10. 0,0,0,0,0,0
    11. -0.001921654,-0.006556511,-0.009557724,-0.001290321,-0.002790451,0.0005912781
    12. 0,0,0,0,0,0
    13. 0.00135994,-0.004827499,-0.01874542,0.001791,0.008340836,0.005337715
    14. 0.0009403229,0.002635002,-0.009964943,0.002267838,0.005288124,-0.001915932
    15. 0,0,0,0,0,0
    16. 0,0,0,0,0,0
    17. -0.001276016,0.007879257,-0.01685143,-0.001554489,-0.004898071,0.001918793
    18. 0,0,0,0,0,0
    19. 0.004648209,-0.01993847,-0.03374004,-0.0001096725,0.008385658,0.00224781
    20. 0.0008554459,-0.01620197,-0.02593231,0.0006799698,-0.001903534,0.001021385
    21. 0,0,0,0,0,0
    22. 0.001961708,0.008459091,-0.01915073,0.002023697,0.002178192,0.001433372
    23. 0,0,0,0,0,0
    24. 0.001739502,-0.0097332,-0.03296566,-0.00290966,-0.0007324219,0.0007829666
    25. 0,0,0,0,0,0
    26. 0.000421524,-0.01051712,-0.03724003,0.001037598,-0.00699234,0.004601479
    27. 0,0,0,0,0,0
    28. 0.004127502,0.0109024,-0.02487659,0.0003786087,0.005043983,0.0007972717
    29. 0,0,0,0,0,0
    30. 0.01004696,-0.002500534,-0.04121208,0.001554489,0.0020504,0.00332737
    31. 0.00521183,0.0009450912,-0.04773331,-0.000919342,0.00620842,0.009724617
    32. 0,0,0,0,0,0
    33. 0,0,0,0,0,0
    34. 0.007962227,-0.006728172,-0.04395771,0.002766609,-0.01010323,0.004948616
    35. 0,0,0,0,0,0
    36.  
     
  5. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    Some frames the delta values look like Vector3.zero, but most frames all values contain some data:

    Do you wonder about these Values?
    Edit: Wouldnt the usage of FixedUpdate be better than Update? Maybe Update is called faster than new PositionData will be send from the sensor and received by your receiver.
     
  6. AngryAnt

    AngryAnt

    Keyboard Operator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    This setup should be a bit easier to work with (untested - watch out for typos):
    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4.  
    5. [System.Serializable]
    6. public class TrackedTransform
    7. {
    8.     public Transform transform = null;
    9.     public Vector3 delta = Vector3.zero;
    10.    
    11.    
    12.     private Vector3 lastPosition = Vector3.zero;
    13.    
    14.    
    15.     public void Reset ()
    16.     {
    17.         delta = Vector3.zero;
    18.         lastPosition = transform.position;
    19.     }
    20.    
    21.    
    22.     public void UpdateDelta ()
    23.     {
    24.         delta = transform.position - lastPosition;
    25.         lastPosition = transform.position;
    26.     }
    27. }
    28.  
    29.  
    30. public class Tracker : MonoBehaviour
    31. {
    32.     public float trackingFramerate = 2.0f;
    33.     public TrackedTransform[] trackedTransforms;
    34.    
    35.    
    36.     IEnumerator Start ()
    37.     {
    38.         foreach (TrackedTransform tracked in trackedTransforms)
    39.         {
    40.             tracked.Reset ();
    41.         }
    42.        
    43.         while (Application.isPlaying)
    44.         {
    45.             yield return new WaitForSeconds (1.0f / trackingFramerate);
    46.            
    47.             foreach (TrackedTransform tracked in trackedTransforms)
    48.             {
    49.                 tracked.UpdateDelta ();
    50.             }
    51.            
    52.             foreach (TrackedTransform tracked in trackedTransforms)
    53.             // Doing an extra foreach in case your handling of the deltas depends on all deltas being calculated
    54.             {
    55.                 // Handle tracked.delta - if needed you could identify the tracked transform via tracked.gameObject.name
    56.             }
    57.         }
    58.     }
    59. }
     
    Voodin likes this.
  7. Theformand

    Theformand

    Joined:
    Jan 2, 2010
    Posts:
    271
    Cheers guys, I will take a deeper look at this tomorrow when I have access to the sensor again. And yes, I was worrying about the 0,0,0,0,0,0 ones, and the fact that I get both positive and negative values back and forth even though the movement is only done in one direction...
     
  8. hallamasch

    hallamasch

    Joined:
    Nov 29, 2010
    Posts:
    153
    Maybe a stupid question:
    - Does the kinect do any kind of interpolation on the hardware side of things? (I have never had one in my hand, so I really don't know)
     
  9. dcollado

    dcollado

    Joined:
    Feb 14, 2011
    Posts:
    4
    As far as I know there isn't any kind of interpolation not in the hardware (Kinect) neither in the middleware (Softkinetic).
     
  10. omarcesar

    omarcesar

    Joined:
    Sep 7, 2012
    Posts:
    1
  11. crocodil

    crocodil

    Joined:
    Apr 23, 2017
    Posts:
    2
    I was using the PositionTracker script with my rigidBody2D. Was hoping this would allow me to then compare last position to CurrentPosition to see if the object is climbing/travelling flat/descending. Kept bumping into issues after messing around for a few hours and figure there is a relatively easy way to solve this.

    Tracker script is the one from above #AngryAnt

    Then here is me trying to compare the positions in other script:

    Code (CSharp):
    1.  
    2.  
    3.     void Update()
    4.  
    5.     {
    6.  
    7.         // if position.y > = (position.y of frame-1)
    8.  
    9.         if (backTire.transform.position.y == TrackedTransform.lastPosition.y | backTire.position.y - TrackedTransform.lastPosition.y <= (0.15f) | backTire.transform.position.y - TrackedTransform.lastPosition.y >= (0f))
    10.  
    11.         {
    12.  
    13.             climbing = false;
    14.  
    15.             descending = false;
    16.  
    17.             flat = true;
    18.  
    19.       }


    Thanks