Even with only a few planets and one ship, things get tricky quite quickly since I want to be able to compute new orbits for ships in real time. Due to that, I had to separate the orbit computation of planets and ships so that I only need to compute a new orbit for the ship when it maneuvers, not the whole solar system. As an example, here are orbits for all planets up to Jupiter, simulated over two years:
Pictured: a two-year simulation of the inner planets and Jupiter, computed in 60 ms.
As you can see, Jupiter only does about 1/5th of an orbit in the allotted time frame. This means I must be able to simulate planet trajectories over extremely long time frames, and then caching the results so I can compute arbitrary orbits for the ship in the whole solar system. This means that our orbit computation algorithm has to be highly optimized, otherwise computing the effect of any maneuver of the ship could end up taking seconds of computing time, rendering the simulator extremely hard to use.
One essential improvement that allows for quicker orbit computations is a good numerical integrator for the orbits. I want something that allows me to use longer time steps without incurring a lot of error. A runge-kutta 4 integrator is a good enough solution for that. It's simple to implement and gives good accuracy and is fast to compute too. Additionally, I want to use an adaptive time step so that I don't need to manually adjust it all the time. I simply select a level of accuracy required of the simulator and let the algorithm figure out how to get that. This lets me compute orbits such as in the image below in real time:
A flyby of the Moon with a free return trajectory. The ship's trajectory is shown in green, with the Moon insertion burn highlighted in red. Due to the shape of our orbit, we can return to Earth without having to use our thrusters in Lunar orbit at all. The 8-day orbit is computed in 4 ms, allowing for comfortable real-time editing.
Running both the planets and the ship trajectories on different time steps due to the adaptive integration presents a new problem: When computing a ship's trajectory, the time resolution is different than for the planetary simulation. This means we must have some kind of interpolation system for planet positions. A simple linear approximation would work, but it would not be a good one since orbits never follow linear trajectories, meaning I'd have to increase the time resolution of the planet simulation to keep interpolation errors acceptable, so that's out of the question.
Instead, I chose to use splines to approximate a planet's trajectory and use it to compute the planet's state between exact known states. As a third-order approximation, it is a good approximation of a planet's behaviour over short time periods at least, and that's really all we need. Due to the adaptive nature of my integrator, the difference between two consecutive time steps should be minor, meaning we should not get a whole lot of error in the interpolation. Using linear least squares to fit a spline to the planet's trajectory gives us a good approximation, as shown in the video below:
This video shows a spline being fitted to a planet's trajectory. To really show the approximation errors, the time period used for the fit is increased greatly. Here we fit the spline to 100 consecutive states of the planets, when in real use cases it would only be necessary to fit to 4-6 states.
All of these optimizations combined give me a robust orbit simulator that can simulate almost any trajectory in real-time, if not always at an optimal refresh rate. Here are some example videos showing how smooth the trajectory planning is, compute time wise. The UI is quite terrible for now, but that's an issue for another time.
This video shows a transfer from Earth orbit to a circular orbit over the Moon.
And this one shows an interplanetary transfer from Earth orbit to Mars, with a gravity assist from the Moon.


No comments:
Post a Comment