May 9, 2012

Computing Space Travel

How can a 3D-autopilot be implemented in a space opera game? How do you compute the optimal trajectory from A to B in a solar system using classical mechanics?

This has been one of the tougher problems I've encountered in the MMO game project I'm working on. No other space game I've played has had a solution for this. The problem is usually avoided by either inventing other physics or hiding or skipping the actual travel. But I aim higher than that. I want it to feel like piloting a ship in space.

Since it's a space opera game, the simulation primarily involves classical mechanics, i.e. Newtonian physics. (Einsteinian relativity I consider non-practical from an implementation point-of-view. I don't say this only because it's harder physics... and the light-speed limit would definitely limit game design!) In the game, celestial orbits, space ship movement, thrust engine power, fuel consumption etc are all derived with Newtonian physics.

A lot of such behavior can be computed using high school level physics. But planning an optimal (or at least fairly efficient) space trajectory path to reach a given destination proved to be a considerably more difficult problem. It took much longer to solve it than I had expected. In this post I thought I'd describe what I came up with. It is an interesting problem and the solution can perhaps be useful to others.

Defining the Problem

The objective is to plan the space trajectory needed to rendezvous with a given destination within the solar system. It is needed to implement the game's autopilot which is used by both computer-controlled ships and players. The trajectory must be computed in advance since simply going in the direction of the destination would result in arriving with a speed very different from that of the destination object. We need to know beforehand when to 'gas' and when to 'break', and in what precise directions to do this.

The planned trajectory should be fairly efficient (primarily regarding travel time, but also regarding fuel consumption) and preferably not cheat by using different physics than the player experiences with the manual controls. It must also be fairly fast to compute - it's an MMO game and there can be many thousands of travelling ships.

The formal problem is: The travelling spaceship, at current position P in space and with current velocity V, is to travel and rendezvous with a destination object (a planet, another ship etc) which is at current position Q and with current velocity W. Since it's a rendezvous (e.g. docking or landing) the travelling spaceship must have the same velocity W as the destination upon arrival.

The above diagram is in absolute frame coordinates (sometimes called the inertial frame). However since we're adhering to Newtonian physics we can simplify the problem by defining it relative to the travelling ship's starting position and velocity instead. The next diagram shows the same case but in relative frame coordinates.

                                           P= 0                Q= Q - P                ΔV = W - V

A game space ship travels using its thrust engine, which accelerates the vessel in whatever direction it is pointing. The planned trajectory should be expressed as a sequence of thrust applications, each describing a trajectory leg:

  1. From time 0 to t1 apply thrust X
  2. From time t1 to t2 apply thrust Y
  3. ...

The technical problem is: Find the trajectory legs (each expressed as a thrust vector and a length of time) that as soon as possible will move the ship to the same position and velocity as the destination, so that:

P(t) = Q(t);     velocity = ΔV;      t as small as possible

Solution Approach

This is not trivial. What is described here is actually my third approach. The first one was plain incorrect, and the second one was sub-optimal and missed the destination in certain cases. This one however I believe is fully correct and actually produces the optimal trajectory in all cases (in terms of shortest travel time). (If a physicist reads this I'd be happy for any comments!)

Two Solution Parts

Two things must happen in the trajectory: Our ship needs to change its speed to match that of the destination, and it must travel the distance to reach the destination.

The naive approach would be to do one after the other. Simply first move to where the destination is and then adjust the speed! (Of course it takes time to adjust the speed and the destination will move in the mean time, but we can change the destination position to adjust for that.) Or first change the speed to match the destination, and then travel to it by applying an acceleration followed by an equal amount of deceleration?

There are three problems with this one-after-the-other approach. First, it results in a sub-optimal trajectory meaning it will take longer time and consume more fuel than necessary. Second, it will look weird to the player. And third and most importantly, it works poorly for destinations that change their velocity over time, as almost all destinations do. (Planets are in orbit, other spaceships are travelling somewhere - or even actively evading you if you're chasing them...)

To elaborate a little on this last point, it's true the problem definition above makes no mention of changes to the destination's velocity over time. It's been simplified to disregard the destination's own acceleration. In theory the change in velocity direction over time is possible to compute for orbiting celestial bodies, although difficult within the context of this problem. But other spaceships are impossible to predict because someone else is controlling them! Therefore the trajectory must be recomputed regularly during the journey - and we might as well disregard the complication of the destination's continuously changing acceleration in this solution.

The naive approach is inadequate and the two solution parts must therefore be 'integrated' within each trajectory leg.

Impulse and Moment

To begin with, let's describe the solution in terms of impulse and moment. Δp is the change in an object's moment achieved by applying a certain impulse I. Impulse is defined as applying a certain force F over a length of time Δt, and is also equal to the change in velocity ΔV multiplied by the object's mass m.

I = F t = m V = p

(Note the use of vector notation. Since we're navigating 3D space we need 3D vectors to describe position, velocity, force, impulse etc.)

ttot expresses the total time the trajectory will take to traverse. We shall try to find this value.

We know that, over the course of the total trajectory, an impulse IV must have been applied to the ship that changes its velocity with ΔV. And since we know ΔV and the ship's mass m we can directly compute it via IV = m ΔV.

We also know that, some impulses in addition to IV must have been applied that causes it to traverse the remaining distance to the destination so they rendezvous at the same point P(ttot) = Q(ttot). Furthermore, since IV brings the ship to the correct arrival velocity, the sum of these impulses must be zero (otherwise the arrival velocity will be wrong). We therefore define these impulses as ID and ID', where the direction of ID is such that it accelerates the ship towards the rendezvous point, and ID' = -ID so that the net velocity change from these two impulses is zero.

The above diagram illustrates the impulses that must have been applied to the ship over the course of the trajectory.

In order to apply these impulses the trajectory needs to have two legs:

  • the first trajectory leg applies ID and part of IV;
  • the second trajectory leg applies ID' and the remaining part of IV.

Finding ID

We know IV, and ID' is the inverse of ID. So the impulse we still need to find is ID.

The purpose of ID and ID' is to traverse the distance to the rendezvous point. How do we define this distance? Note that the purpose of ID and ID' is to traverse the distance that results after the destination's velocity ΔV and our own IV have been taken into account.

First, define the distance at time 0:

Then we add the destination's movement (t ΔV) and subtract our own movement caused by IV:

By our definition of ID, its direction is equal to the direction of D(ttot). Its magnitude also depends on ttot. To nail down ID we must thus find ttot.

Algebraic Solution

There is an algebraic solution at this point. Assuming constant thrust F, the total time is bound by the following equation:

Unfortunately this results in a quartic function (polynomial of degree 4) which is a pain to solve (and afaik requires an iterative numerical approach in the end anyway, e.g. the Newton-Raphson method). So I've abandoned this approach.

Practical Solution

Since short travel time is the top priority, we shall assume constant thrust at the maximum power level set by the player (or the computer-controlled pilot). At any moment the ship can exert this thrust in an arbitrary direction in 3D space.

The radius represents the maximum thrust force. This scalar quantity will be referred to as F.

Remember that we're looking for two trajectory legs, each described by a thrust vector and the length of time it is to be applied. F1 represents the first thrust vector and F2 represents the second. As the diagram shows, they are resultant vectors of FV, FD and FD'. Their relationship with the impulse quantities is:

IV = ttot FV
ID = t1 FD
ID' = t2 FD'
ttot = t1 + t2

Since we know IV, we also know the direction of FV. However we don't know its magnitude, other than that it is in the interval (0, F).

If we did know its magnitude, the rest would be relatively straight-forward to calculate. Applying the equations described above, knowing Fwould yield:
R(unit vector with same direction as D(ttot) and FD)

Now we look closer at the force diagram:

Using the dot product between Fand RD we can write:

Using the law of sines we can write:

Now we have FD, which also gives us t1:

Having t1 we can continue to calculate t2, FD'... and F1 and  F2.

The solution thus consists of the two trajectory legs { F1; t} and { F2; t}!

As stated earlier we merely assumed the knowledge of FV's magnitude. In the next post I'll describe implementing this solution using the bisection method to iteratively find the greatest possible value for FV (the greatest value of FV yields the optimal trajectory). It turns out that the average number of iterations required is less than 10 which is fine performance-wise, and the resulting movement is, well, smooth!

No comments:

Post a Comment