简体   繁体   中英

Coding a 3d trajectory prediction system

Alright, so for months (on and off) I've been trying to create a system for a VR game I'm making which will predict where the player is moving their hand based on where it has been in the last dozen or so frames. I'm fully aware this won't be completely accurate but it doesn't need to be. Irritatingly, no matter what I've tried so far, I am unable to get it working to a sufficient degree.

The idea I've been working off is getting the average direction that the hand has been moving for the last few frames, then working out the average change in those directions, then working out the average change in those directions. I then calculate based on the hand's current position where it will be in the next dozen or so frames. I get the next position by, starting with the current position, moving the point in the last known direction (the direction between the current point and the previous point), then taking that direction, rotating it based on the average change in directions, and then, rotating that value by the average changes in those directions.

I am yet to get this system working and it is beginning to drive me crazy. Sadly because it could be moving in any direction I can't just use a standard trajectory calculation algorithm and I have to work with Quaternions, which are inherently confusing.

If you're able to assist me with this problem I would be immensely grateful. Whether it is by helping me with my current method or pointing out a different method.

My current (not working code) is here simply in order to aid in understanding what I'm trying to do.

void PredictTrajectory()
{
            Vector3 avgDirection = Vector3.zero;
            List<Vector3> directions = new List<Vector3>();
            Vector3 avgChangeInDirection = Vector3.zero;
            List<Vector3> changeInDirections = new List<Vector3>();
            Vector3 avgChangeInChangeInDirection = Vector3.zero;
            float avgDistanceBetweenPoints = 0;

            for (int index = hand.PastLocations.Length - 1; index > 0; index--)
            {
                avgDirection += (hand.PastLocations[index - 1] - hand.PastLocations[index]).normalized;
                directions.Add((hand.PastLocations[index - 1] - hand.PastLocations[index]).normalized);
                avgDistanceBetweenPoints += Vector3.Distance(hand.PastLocations[index - 1], hand.PastLocations[index]);
            }
            avgDirection.Normalize();
            avgDistanceBetweenPoints /= hand.PastLocations.Length - 1;

            avgDirection = hand.PastLocations[0] - hand.PastLocations[1];
            avgDirection.Normalize();
            
            Quaternion avgDirectionChange = Quaternion.identity;
            List<Quaternion> changesInDirection = new List<Quaternion>();
            for (int index = 0; index < directions.Count - 2; index++)
            {
                changesInDirection.Add(Quaternion.FromToRotation(directions[index], directions[index + 1]));
            }
            avgDirectionChange = changesInDirection.Average();

            Quaternion avgChangeInDirectionChange = Quaternion.identity;
            List<Quaternion> changesInChangeInDirection = new List<Quaternion>();
            for (int index = 0; index < changesInDirection.Count - 2; index++)
            {
                changesInChangeInDirection.Add(changesInDirection[index + 1] * Quaternion.Inverse(changesInDirection[index]));
            }
            avgChangeInDirectionChange = changesInChangeInDirection.Average();
            avgChangeInChangeInDirection.Normalize();

            avgChangeInDirectionChange = Quaternion.FromToRotation(avgChangeInDirection, avgChangeInChangeInDirection);

            List<Vector3> points = new List<Vector3>();
            points.Add(hand.transform.position);
            for (int index = 0; index < 200; index++)
            {
                avgDirection = avgDirectionChange * avgDirection;
                points.Add(points.Last() + (avgDirection * avgDistanceBetweenPoints));
                avgDirectionChange = avgChangeInDirectionChange * avgDirectionChange;
            }

            predictedArc = new Arc(points);
            WorldManager.Instance.DrawPredictionArc(predictedArc);
}

I don't often post here so if I've done so incorrectly I apologise.

EDIT: So despite my wall of text, I may not have actually said exactly what I want in a concise way so here it is.

I need a function that can semi-accurately predict the future location of an object moving in a non-linear way. I need it to give me the predicted locations for multiple frames in the future (For example: If I want to predict the next 15 frames, I need to get 15 positions, not 1).

So, for 15 steps forward in time, you could do this, where speed and acceleration are estimated on the last frame:

Vector3 lastPos = Vector3.zero;
Vector3 velocity = Vector3.zero;
Vector3 lastVelocity = Vector3.zero;
Vector3 acceleration = Vector3.zero;
float stepTime = 0.1f;
int predictionSteps = 15;
Vector3 predictedPos = Vector3.zero;
List<Vector3> futurePositions;
...
void Update()
{
  lastVelocity = velocity;
  velocity = (transform.position - lastPos) / Time.deltaTime;
  lastPos = transform.position;
  acceleration = (velocity - lastVelocity) / Time.deltatime;
  predictedPos = transform.position;
  futurePositions = new List<Vector3>();
  for(int i = 0; i < predictionSteps; i++)
  {
    predictedPos += velocity * stepTime;
    futurePositions.Add(predictedPos);
    velocity += acceleration * stepTime;
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM