Taking average of multiple Vector3's

So I’m working with a depth-camera that works like kinect. (it’s not kinect). and with Nuitrack behind it for skeleton tracking. However, The position it returns for the player is shaky. When standing perfectly still it returns numbers that can go up or down by up to like 10.

Example: User is standing as still as he can and the data returns position 100 the first frame, and the next frame it’s 102, then it’s 97 then its 100 again, then it’s 106 etc. It returns these positions in the update and we use it to move a image with it. (so the user controls the image) But as you might expect this image is moving very shaky because of the inconsistent data. According to Nuitrack this is right, and the user itself needs to find a solution for this.
133793-2.png

I tried lerping from one position to another, but this makes it feel less interactive, because once i’m on the point where the lerp is actually smooth, it has a huge delay. I also tried only using the new position data if it differs lets say 4 pixels from the previous position nuitrack gave me, this works a bit better but results in jumping of the image, even if I lerp it as well. Using this function:

foreach (User user in frame.Users)
        {
            if (Vector3.Distance(_lastPos, user.Proj.ToVector3()) >4f)
            {
                Vector3 final = ((_lastPos + user.Proj.ToVector3()) /2);
                userData.Add(new UserData(user.ID, user.Real.ToVector3(), final));
                _lastPos = user.Proj.ToVector3();
            }
            else
            {
                userData.Add(new UserData(user.ID, user.Real.ToVector3(), _lastPos));
            }

And the Lerp function:

float _userX = user.ProjPosition.x * (_cameraPos.x *2)- _cameraPos.x;
            Vector3 _newPos = new Vector3(_userX, _basketPos.y, _basketPos.z);
            _basketPrefab.transform.position = Vector3.Lerp(_basketPrefab.transform.position, _newPos, Time.deltaTime * 30f);

This is one of the cases where a “non linear lerping” (which is a contradiction in its own ^^) will help. The idea is if the difference is small we want a very slow transition and maybe even a threshold to ignore changes completely. Once the change goes over a certain magnitude we want to speed up the movement. At greater changes we want the changes to be almost instant. One way would be this:

// set the threshold in the inspector
public float threshold = 10;
// controls how fast the speed increases
public float scale = 0.1f;
public float pow = 2f;

// does represent the current position of your object;
Vector3 currentPosition;
// current input position
Vector3 input;

void UpdatePosition()
{
    Vector3 dif = input - currentPosition;
    float length = dif.magnitude;
    float newLength = Mathf.Max(0, length - threshold);
    if (newLength < 0.0001f)
        return;
    dif *= newLength / length;
    dif *= scale;
    dif *= Mathf.Pow(newLength * scale, pow);
    dif = Vector3.ClampMagnitude(dif, length);
    currentPosition += dif;
}

Note that theshold always need to be positive. The scale and pow control how fast you home in into the given position. The greater the scale / pow the faster it will be. You can control the non linearity by increasing pow and decreasing scale or the other way round.

Scale probably should be smaller than 1 and pow should be greater than 1 (note that pow is the actual power -1. So a pow of 2 results in a power of 3. A pow of 0 results in a power of 1)

Though keep in mind this is untested and is just based on theory. It would need to be tested with actual data. Since all values are exposed you can tweak them in playmode.