Reputation: 1510
I have a CSV that gives me the x,z
coordinates of a car with id
at a given time t
in seconds. Below is an excerpt data for a car with id=1
and it's coordinates over a few seconds. For the first three seconds, the car is stopped. It then turns left and continues straight for a few more seconds.
At the moment I'm calculating the direction based on the next position and rotating the car to face towards that, but there is no 'curve' to the turn, it simply moves straight to the next position:
Vector3 direction = (nextPosition - car.transform.position).normalized;
if(direction != Vector3.zero)
{
Quaternion lookRotation = Quaternion.LookRotation(direction);
float step = speed * Time.deltaTime;
car.transform.rotation = Quaternion.Slerp(car.transform.rotation, lookRotation, Time.deltaTime * rotationSpeed);
}
Given just these points, specifically the two at 958
and 959
where the turn occurs, is there a way to more realistically make the turn? I know that Unity's standard asset CarController.cs
has steering functionality, but I'm not sure if I can use that to my advantage.
t,id,x,z
956,1,-1.50,232.39
957,1,-1.50,232.39
958,1,-1.50,232.39
959,1,-4.50,209.72
960,1,-4.50,193.05
961,1,-4.50,176.39
Upvotes: 0
Views: 1591
Reputation: 660307
As I noted in my answer to your previous question, a good first approximation is to compute the average velocity "in the gap" between the measurements, point the car in the direction of the average velocity, and you're done.
This does not produce realistic motion because of course cars do not instantaneously change in velocity. Rather, there are forces applied to the car, and forces accelerate the car in a particular direction. (Note that slowing down is an acceleration; I'm not making a distinction between acceleration and deceleration.)
You have the position at every second, and you know how to compute the average velocity at every second from the previous question. Now compute the average acceleration in the same manner. We know that F = m a
, so if the mass of the car stays the same, then the net force acting on the car is proportional to the acceleration.
What you can do then is at every second, ask yourself the question "what acceleration would I need to have at this exact moment in order to get to the next known point at the known position and velocity?" That is: if I accelerated smoothly along the acceleration vector starting from time t, what vector would that be that gets me to my known position and average velocity at time t+1?
Once you know that then you can do interpolation of velocity vectors between the seconds, and you will find that the curves are much smoother. Then you do interpolation of the positions in the same manner.
They still will not be perfectly smooth because of jerk; that is, instantaneous change in acceleration, which humans perceive as a jerking motion. Like when someone floors it in a car, or suddenly turns.
To make the motion really smooth you need to go one step further and do the same trick to acceleration. Figure out what jerk do I need at every second in order to meet my target position, velocity and acceleration at the next second.
You can then interpolate the position, velocity and acceleration between the seconds and get a nice smooth motion.
This is not the only way to get smooth motion from a series of points, but it's character building to do so. Can you think of any other techniques to solve this problem?
(Also, I note that the problem is not significantly harder in any number of dimensions. You might consider solving the problem for one-dimensional motion first, and then extend your solution to two-dimensional motion.)
Let's look at some numbers, and we'll look just at the x figure.
We know that for the first couple of seconds, the position is -1.5, and then in the next second the position is -4.5. So the average velocity and acceleration was zero for a while, and then the average velocity was -3 for a second. Therefore the acceleration was zero to -3, that's a difference of -3, so we've accelerated by -3 meters per second per second for a second.
Now let's think about that for a moment.
Suppose you're stopped, and you continuously apply a force that will accelerate you by -3 meters per second per second. Plainly after one second you'll be going -3 meters per second. But where will you be? If you instantaneously went from zero to -3 m/s then you would be -3 meters away after a second, but we are no longer modeling velocities as instantaneous! You would only be -1.5 away from the starting position, not -3 away.
The actual average acceleration you need is -6. An average acceleration of -6 for a second gets your velocity to -6 one second from now, but you started at zero, and so the average velocity over that second is, as we want, -3. And that gets you from -1.5 to -4.5 in one second, which is what you want.
So: what then is the position and velocity at time 958.5, given a constant acceleration of -6 m/s/s, starting from velocity zero? The velocity is -3, as we'd expect -- the average should be about halfway. And the position change is a Δt
2/ 2
(do you see why?) So that's -6 * 0.5 * 0.5 / 2, which is -0.75, a quarter of the -3 that we're going to go in this second. Again, this should make sense: we're moving slower in the first half second than the second half second, so we should be less than half way by the first half second.
Now do the same thing, but for jerk. If you do that you'll find that your motions get very smooth indeed.
I hope that is all making sense. A good introductory physics text will probably help immensely here.
Upvotes: 5