Following a 2D point-path

Started by
4 comments, last by TheAdmiral 16 years, 11 months ago
I'm having some serious issues getting this to work. I'm not sure what I'm doing any more, I'm testing/tracing but it's not getting me anywhere... So what I have is a Java Canvas with and area of 800x680 pixels where 0,0 is top left corner and 800,680 is bottom right corner. Within this area i spawn a random point, and I want to navigate to it. To do this I've tried using Math.atan2(_t.y - _p.y, _t.x - _p.x) to find the angle between my current position "_p" and my target destination "_t". I then use (Math.sin(angle) * v0 * dT) and (Math.cos(angle) * v0 * dT) to distribute the velocity as displacment in the right direction (with respect to the time delta "dT"). I also need to rotate a sprite to face the target. I also would like to make the sprite which is a Car to interpolate the angle differance by a turning rate. Do I have anything obviously wrong, or is there something specific someone noticed with my thoughts? I've been going about this for some time, and i'm always running into problems with the angles. Regards,
Advertisement
Below is a picture of the problem. As you can see the target and the angle doesn't seem to have a ratio, looks more random than I would like it to. The angle in YELLOW is the angle from ATAN2 radius displaced by sin/cos, but the actualy target is more like Math.PI/8 (45* degrees) to the right.

Example
First I'd like to suggest that you use vector maths. For example, to move to a target ptarget, from a point porigin, you would calculate the direction vector dtarget:
dtarget = ptarget - porigin

normalize it and move the car each timestep/frame by translating the origin along the (normalized) direction vector:
pnewOrigin = porigin + dtarget . dt


Next, to find the correct yaw for the sprite you then take the normalized direction vector, and perform the acos (or asin) operation:
yaw = cos-1( dtarget.x )


However, since the inverse cosine only yields values within the range [0, pi], you have to take the sign of the y component of the direction vector into account:
if dtarget.y > 0.0 then yaw = 2 . pi - yaw

You can implement this test anyway you want (it's just here to help you understand it), as there are other ways to interpret the equation.

Also, I took some things for granted (for example, how the angle is interpreted by the renderer), but hopefully this helps a bit.
I second the recommendation to switch to vector representation, but here are my thoughts.

While I only have one example to go by, it looks more like the derived and true angles are reflections of one-another, in the line y + x = 0. This is potentially what you would see if you switched the x- and y-coordinates. The reason I bring this up is that you said

'(Math.sin(angle) * v0 * dT) and (Math.cos(angle) * v0 * dT)'.

While your trigonometry is fine, you have described the vector as 'y and x'. Make sure that your code uses cosine for the x component and sine for the y (assuming that angles are taken anticlockwise from x > 0).

If you're still stuck, take a brief look for obvious errors (omitted degree-radian conversions and suchlike) and post us some code. We'll get to rotation and interpolation once the immediate case is working.

Admiral
Ring3 Circus - Diary of a programmer, journal of a hacker.
When I started out, I didn't think I was goning to need vectors, after that I changed some of the math, it just works more like I want it to.

My best kind regards to you sir, for helping me out here.

Now what messed up the trig last time, seemes to be the interpolation between the angles. I don't just wanna flip the car, I want it to turn with a specific turn rate.

Any tips?
There's really nothing special about angular interpolation: you simply have to keep track two orientations - current and desired. 'Desired' can be set at any time to the appropriate value, while 'current' must always move towards 'desired' without ever going too fast. Interpolation itself is in the angular domain (in particular, don't try to interpolate vectors pointwise) and should always be done along the shortest route, which isn't always clear.

Obviously, the implementations differ depending your representation (Cartesian/polar c.f. vector/angle). It's not entirely clear from your last post whether you rewrite the code in vector format or fixed the angle-based system. Here are some starting points for both cases:

This thread covers determination of the shortest rotational direction between two vectors. This one and this one tackle the same problem using angles.

So now that you know which way to turn, you need to perform the interpolation. In polar coordinates, this is dead-easy: you linearly interpolate the angular component. In vector form, things are a little more complicated, as you need to convert the vector to polar coordinates before interpolating, then convert back. The process is known as Slerping.

A cheap alternative to this is to interpolate the vectors directly, normalising after each calculation. As tidy as this may sound, it has a whole bunch of hidden pitfalls: in particular, rotation isn't linear, results are undefined and may become unstable if you need to turn 180°, and you'll need to memoise the previous position unless you want the decay to be exponential (whence you never truly reach the destination).

Admiral
Ring3 Circus - Diary of a programmer, journal of a hacker.

This topic is closed to new replies.

Advertisement