I am throwing object in Virtual Reality and have heard the best way to get an averaged estimate for direction upon letting go is to do a simple linear regression through the x most recent velocities. Unfortunately, Google nor the article stated the way to preform this calculation and I don’t want to dive into statistical matrices.
What is the best way to do this? I just want to draw a straight line through these points that have a minimized squared error. Is there a github or Math function call that will achieve this in the slightest?
So you’re just trying to get an average velocity over the last couple of frames and generate a throw direction? This should do it. White being the projected velocity, green being your average line, and red the previous frames.
public class TestScript : MonoBehaviour
{
public int framesToAverage = 20;
private List<Vector3> previousPositionsList = new List<Vector3>();
void Update()
{
// insert your objects position
previousPositionsList.Add(transform.position);
int actualFrames = Mathf.Max(previousPositionsList.Count - framesToAverage, 0);
if (actualFrames > 0)
{
Vector3 averageVel = Vector3.zero;
for (int i = previousPositionsList.Count - 2; i >= actualFrames; i--)
{
averageVel += previousPositionsList[i + 1] - previousPositionsList[i];
Debug.DrawLine(previousPositionsList[i + 1], previousPositionsList[i], Color.red);
}
averageVel /= actualFrames;
averageVel.Normalize();
Debug.DrawLine(transform.position, transform.position + averageVel * 5, Color.white);
Debug.DrawLine(previousPositionsList[0], previousPositionsList[previousPositionsList.Count - 1], Color.green);
previousPositionsList.RemoveAt(0);
}
}
}
I’ll start by saying that the sample code does a LOT of extra math - you could simply subtract the first position from the last position and get the same resulting as subtracting every intermediate position along the way. I would also store the Time.time along with the position - his code will give you a constant velocity no matter how hard it’s thrown (though the angle will be pretty much correct). It also assumes a constant framerate. You can fix the last two easily by storing it as a Vector4, using .w for the time.
(this code is untested, though it does at least compile)
public class TestScript : MonoBehaviour
{
public int framesToAverage = 20;
public float speedMultiplier = 1f; //probably unnecessary, but good to have just in case
private List<Vector4> previousPositionsList = new List<Vector4>();
void Update()
{
// insert your objects position
Vector4 newPos = transform.position;
newPos.w = Time.time;
previousPositionsList.Add(newPos);
while (previousPositionsList.Count > framesToAverage) { //probably only 1, but doesn't hurt anything to be careful here
previousPositionsList.RemoveAt(0);
}
if (previousPositionsList.Count >= 2) {
Vector4 velDifference = newPos - previousPositionsList[0];
Vector3 averageVel = velDifference * speedMultiplier / velDifference.w;
Debug.DrawLine(transform.position, transform.position + averageVel * 5, Color.white);
Debug.DrawLine(previousPositionsList[0], previousPositionsList[previousPositionsList.Count - 1], Color.green);
}
}
}
@StarManta If the thrown object has trajectory, which it would from gravity, then you do need the intermediate points, as the velocity vector will change.
If you scroll down to the 3rd image or so, you will see the direction vector (in black) at different points along a trajectory in 2d, ignoring drag. Since the OP wants the regression of the direction every few frames, all of these points matter.
That being said, it’s unclear why he wants regression. If regression is necessary, and high accuracy is important, it might be worth looking into the Eigen library. I believe they have older versions available that should work with .NET 2.0. I’ve tested Eigen vs TNT/Jama, and Eigen has much higher accuracy, and it’s pretty fast.
I honestly didn’t read his code or yours lol, but you do need all the points within the frames that the regression is calculated for. As I understand it, there are more performant algorithms used in such calculations than matrix operations on Ax = b + epsilon. I have only used the matrix operations in scientific calculations, since performance was not an issue.