3
\$\begingroup\$

My First question on here so be kind...

I am writing an aerodrome simulator in as2, I need to calculate a turn rate between 2 points so that the aircraft turns nicely. I have tried a few things but the maths forums on this type of subject use complex calculations and I struggle to understand them. I need an answer in a more variable specific format.

I have the XY of both tile and target, the speed of tile and the distance of target from the tile.

turn axample

I use vector math, with frame time calculations to move the tile. I already have a good calculation for shortest turn i.e. left right.

I need to calculate the turn rate required to go from point a to point b in a nice fluid motion and turn the tile/aircraft in a nice fashion.

Any help would be much appreciated.

\$\endgroup\$
1

4 Answers 4

3
\$\begingroup\$

As hinted by user concept3d, it is difficult to help you without further details about your implementation approach. I'm going to give it a shot nevertheless, but that means that I have to make some assumptions that may or may not be true for your code. In any event, I hope that the following is general enough that you can adapt it if necessary.

The first assumption I'm making is that you really only need to get the plane to the target point, and it doesn't matter to you at which angle it arrives there. My suggestion is to understand the curve the plane is supposed to take as a segment of a larger circle. The following is thus an idea how to construct that circle and how to use it to calculate a turn rate.

Let's recap the situation. You have a plane in flight, i.e., with a current direction and a current speed and you want it to reach a certain destination. Assuming we're talking about 2D, this situation essentially looks like this:

Plane in flight with a target destination

We can understand this then in terms of points and vectors like so: the plane's current position p is a (x,y) point, its direction is given by a two-dimensional vector, its speed by a scalar (potentially encoded as the length of the direction vector, but maybe not), and the destination t is another (x, y) point.

In this image, the current directional vector is drawn in blue, and the vector between p and t is drawn in red:

enter image description here

Let's call the angle between the two alpha (α). You can easily compute it using the dot product between the red and the blue vector.

Now, I want to find a circle so that both p and t lie on the circle's circumreference so that the plane can get from p to t by simply flying along the circle.

There are many different circles that have that both p and t lying on their circumreference, but they all have something in common: the distance from the circle's center point c must be the same for p as for t. This is because the distance between every point on the circumreference to the center is exactly the radius of the circle, and so it must also be for p and t.

So we know that the center point of our circle is equally far away from p and from t. But that means that it has to be somewhere on a line that is perpendicular to the red vector and intersects it halfway, like so:

enter image description here

But what would be a good point to pick? We know that we could theoretically use any point on that center line and draw a circle around it that would go through p and t, so which one should we use?

Well, since we want a smooth transition from the current position to the target point, we want to have a circle that won't make our plane change course abruptly when it enters the circle. At first, new direction given by the circle should at first differ only very slightly from the current direction of flight.

In order to achieve this, we are going to pick the circle for which the blue directional vector that represents the plane's current direction touches the circle tangentially in p.

enter image description here

But how do we construct that circle? How do we know where we have to place c on the horizontal split line? Or, equivalently, how big do we have to make the radius r? (Make sure you understand that the latter question about the radius is actually equivalent to knowing where to place c on the horizontal split line.)

First, we note that the radius r is perpendicular to the blue directional vector, i.e., the angle between the two is 90 degrees. Then we note that there's another 90 degree angle, namely between the red vector and the horizontal split line on which c lies. That means the r is the hypotenuse of a right-angled triangle.

It becomes a bit clearer if we rotate that triangle so that r is horizontal and the right angle is at the top.

enter image description here

So we already know two of the angles in that triangle, the right angle at the top, and the one at the corner p which is 90° - α. Since the sum of all angles in a triangle is 180°, we can calculate the angle at c:

right_angle + angle_at_p + angle_at_c = 180°
                           angle_at_c = 180° - right_angle - angle_at_p
                           angle_at_c = 180° -     90°     - (90° - α)
                           angle_at_c =       90°          -  90° + α
                           angle_at_c = α

Oh, sweet! The angle at c is actually just α.

And we also know another thing: we know the length of the red line in the triangle. Well, not yet, but we can compute it. Remember that in the original picture the red line is the vector from current position p to the target position t. Therefore all we have to do is compute the length of that vector and divide it by two: |t - p| / 2.

Of course, this is done with the formula: sqrt((tx - px) ^ 2 + (ty - py) ^ 2) / 2

Now, with that knowledge and a little trigonometry we can easily calculate what we're actually after: the length of r. For that, we remember that sine of an angle is defined as the ratio of the length of the side that is opposite that angle to the length of the hypotenuse.

sin(α) = red_line / r

Therefore we have r = |t - p| / 2sin(α).

Okay. That's pretty good.

Now, the next thing we're interested in is how long the arc is that the plane has to fly from p to t if it follows the circle. That's actually not that difficult to compute. We've just seen that the angle at c in the lower triangle is equal to α. And the upper triangle is pretty much the same as the lower triangle, just mirrored. So the angle at c in the upper triangle is also α, which gives us a total angle of for the full arc.

enter image description here

As we know, the length of the full circumreference of a circle is 2πr. But here, we don't want to fly around the full circle (2π) but only along the length of the arc (2α). Thus we get as the length to fly:

flight_length = 2αr
              = 2α|t - p| / 2sin(α)
              =  α|t - p| / sin(α)

So with this computation, we know two things now:

  1. The total arc distance our plane has to fly from p to t (= flight_length)
  2. The total angle it has to turn along the way (= 2α)

That's pretty much all you need. The only thing that's missing is how to marry that with the plane's current speed.

Let's assume that speed is given as pixels per tick. Since we know the total flight length of the turn, we can calculate how many ticks it is going to take our plane to make this turn. Dividing the total turn angle by that number tells us how much the plane has to turn in each tick.

Thus to go from p to t in a smooth turn can be done by adjusting the plane's direction through a small rotation every tick. And with the above we know everything we have to know to compute the amount of that rotation.

As user Yos233 has already pointed out, the circle approach might give you awkward results in some situations, depending on the relative location of the current and target and position together with the current flight direction. But you can always find a way to reduce such special cases to the above method. For instance, if the target is so far away that you'd end up with a giant circle, you could add some code that uses an intermediate auxiliary target point that is much closer. This should be chosen so that the direction of the plane when it reaches the auxiliary target is so that it can simply fly straight on from there in order to reach the actual destination.

But I would suggest trying out the above method with some easy cases first and see if you like it. If you then need help with the special cases too, I suggest you simply post a new question here.

\$\endgroup\$
2
  • \$\begingroup\$ Thanks for your help Thomas, sorry it's taken time for me to get back but I got bogged down making a flash socket server for this application. I have implemented turn calculations based on nearly all of the answers given here and allow the route waypoint markers to change the type of turn from one similar to yours to one of move x amount each movement phase. I now have thanks to your and the other answer help given here, a working route system with nice aircraft movement along with network communication between flash files and the project has now ticked all the boxes for completion. Thank you. \$\endgroup\$ Commented Mar 31, 2014 at 10:04
  • \$\begingroup\$ Cool! Glad to hear you got it working. In retrospect, I think if I were to implement this, I would now prefer my second answer over this one. \$\endgroup\$
    – Thomas
    Commented Apr 1, 2014 at 10:06
1
\$\begingroup\$

One easy way to do this is the following algorithm that is executed each tick:

if (the target is straight ahead) then
    keep flying straight on
else
    rotate a little bit towards the target

It's easy to see that this algorithm works... but we have to talk about what "a little bit" means. Certainly, there's a maximum angle you want your plane to turn in a single tick, or else the flight will look unnatural. Imagine the plane doing a 90° jump from one tick to the next. That would probably not look very convincing.

So you could either define a constant MAX_TURN_ANGLE which you simply find by testing what works for you; or you make the maximum turn angle a function of the plane's current speed, so that it must take wider turns when it's flying very fast. Again, you could test whatever looks best in your opinion; for now I assume that you can somehow determine the maximum angle your plane can turn.

But then we have to ask ourselves: does it always make sense to do the maximum turn possible?

I think the answer to that one is no because it won't always lead to very graceful turns. Imagine the target is 90° to the right with respect to the current flight direction, and quite a bit away. There are two extreme ways how to turn:

  1. Turn as quickly as possible and then fly the rest of the way in a straight line.
  2. Fly a very loooong arc that will make you reach the target before you fly straight again.

(The second variation is what my other answer produces.)

But perhaps the actually best way to do it is somewhere in the middle: first fly a graceful turn and then do the rest in a straight line.

Here's one idea how to implement that:

  1. Compute the angle between the current direction and a straight line to the target
  2. Have a factor between 0 and 1
  3. Multiply the angle from 1. with the factor.
  4. If the result is smaller then the maximum turn angle, use it for the turn; else use the maximum turn angle.

You could play with the factor in step 2. and see what gives good result. Maybe something around 0.5 would be a good starting point, but you could also make it a function of the distance to the target: if it's far away, use a higher value, if it is already quite close, use a smaller value.

As a matter of fact, I think this factor should be what determines the maximum turn angle: obviously the greatest possible angle between the current direction of flight and the target is 180° -- so you should should pick a factor that even in that extreme case leads to a maximum turn angle that still looks believable.

There's one more thing though that we have to pay attention to: since we're using a maximum turn angle, it means that there is a "smallest circle" that our plane can fly. That is, if we wanted our plane to fly a circle, the diameter of that circle would be directly dependent on how much the plane can rotate maximally in every tick.

As a consequence, if the target destination lies inside that smallest circle, i.e., is closer than the diameter of the smallest circle, we can never reach it with the above method. In such a case, the best strategy is to fly in the opposite direction, i.e., away from the target. That is to as quickly as possible increase the distance between the plane and its target so that it is no longer inside the "smallest circle". Once it is outside, we will fall back to the standard method above.

\$\endgroup\$
0
\$\begingroup\$

If I were you, I would use a simple algorithm to point the aircraft at the target. You can use a turnrate variable to keep track of how quickly it is turning. This is something I am using in my project.

Within the update method, calculate the projected heading a few seconds in the future. If the projected heading has not passed the target heading, increase the turn rate (up to a maximum). If the projected heading is beyond the target heading, reduce the turn rate.


The reason I highly suggest you do this is because the mathematics for constructing and following a curve between two points is very complicated. It has to be to handle all of the special cases that you might encounter. Like, what happens when your target is much further east than north, but your plane is heading north? You couldn't construct a circle between the points in a way that works.

If you would like me to go into further detail in a second answer I will, but only at the abstract level. I have no idea how you would implement it in your program.

\$\endgroup\$
0
\$\begingroup\$

I would look into using a Bezier Curve. You can have easy curves like you show above, or more complex curves (even nested) using Bezier splines. The algorithms are pretty straightforward and explained well on Wikipedia :)

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .