In Aero 347, Space Flight Mechanics, we were given the choice between taking the final exam and doing a project. I chose the project. I based it off of Newton’s Nightmare, an N body simulator written in JavaScript. You can drag and drop planets and give them velocities. The goal is to get an orbit system that lasts for about 10 seconds. I wanted to modify this to let the user visualize and interact with the effects of the gravitational law. To do this, I created two games and two demos of orbital maneuvers. First, I’ll talk about the general setup of the program. Then, I’ll discuss each of the four features in detail.
The base is an iterative process that runs every 25 milliseconds to simulate the motion of the planets. First, the force comes from gravity and the spaceship’s thrust. The gravitational force is
This force is broken down into x and y components. Each pair of planets has the gravitational force law evaluated on them. One planet has the force added to its total force while the other has the force subtracted. This is because the force magnitude is the same, but the directions are opposite. Thrust is decomposed into x and y based on the direction the spaceship is pointing. This is added to the total force. The ΔV is calculated by dividing the thrust by the mass to get acceleration and then adding this up in each iteration. The total force is divided by mass to get total acceleration. This acceleration is added to the existing velocity. The velocity is then added to the existing position.
The spaceship is turned using the arrow keys. When the left or right arrow keys are held down, an angular acceleration is given to the spaceship. Each iteration, the spaceship direction vector is rotated by an angle, which is the angular velocity. The planets, spaceship, flame, velocity arrows, and spaceship trail are displayed using the HTML canvas element. The spaceship can be drawn as a triangle or with an image of the Dragon2 capsule. Drawing the triangle involves quite a few sines and cosines and was adapted from an asteroid game. The spaceship engine flame is a triangle that is filled in.
The part of space I needed to simulate was at least on each side since I wanted one of the planets to be Mars. The screen area was 900×600 pixels. Therefore, I used a distance scaling factor of to convert between real values like and display values like . Since Earth’s orbital velocity in is , I multiplied by a time factor of 34,000 to get velocities of about 1 pixel per iteration. To compensate for the reduced time feeling the effects of gravity, I multiplied the gravitational force by the same amount to get enough gravitational force to create a circular orbit with the starting position and velocities. The size of the planets and spaceship are not to scale because they would not be visible if they were.
I commented the code pretty well so the details can probably be followed there. The function structure can be summarized with this chart.
Rendezvous
The Earth and Mars were given an initial velocity of
I set the spaceship to stay with the Earth until the user launches it. The spaceship is not really on the surface since the center of spaceship is 9 pixels or away from the center of the Earth. The radius of the Earth’s sphere of influence is . This means the Earth’s gravity has some effect on the spaceship but it is not really a simulation of a launch from the surface of the Earth. The same applies to Mars. The spaceship will not be able to get close enough to Mars to be captured into its orbit. Instead I made three conditions that must be fulfilled at the same time for the rendezvous to be considered a success: a distance between the spaceship and Mars, a percent difference in velocity magnitude, and a degree difference in velocity direction. These three target conditions can be adjusted by the user to make success easier or harder.
Launch
The second game is more open ended. The spaceship is near the sun. The user launches with an initial thrust of 109 kN. The thrust can be changed using the a and s keys. The goal of this game is to get the orbit close to a user specified value of eccentricity or period. The eccentricity and period of the orbit are calculated in each iteration based on the position and velocity vectors. This was harder to do in JavaScript than in MATLAB. I had to make a cross product function, manually multiply a scalar by each term in the vectors, and manually add each term in the vectors since those functions were not supported.
You’ll notice the eccentricity and period fluctuate more when the spaceship whips around the Sun than when it moves slowly and in a straight line. This is because the velocity magnitude and direction are changing rapidly which plays into the calculations. The important thing is the values are relatively constant.
Semi-Hohmann Transfer
The target velocity after the first burn, theoretical ΔV, and target are calculated with the Hohmann transfer equations. is the difference in true anomaly of the Earth and Mars. True anomaly is the angle between the Sun and a planet.
This is called a semi-Hohmann transfer because I had to tweak three parts of the maneuver from what a Hohmann transfer would have. First, I had to change to to get the spaceship to line up with Mars the best. I’m not sure why was that off. The first burn is done at the target with the spaceship pointing tangentially to its velocity. It burned until its velocity was within 0.1 km/s of 98.5% of the target velocity, which was the second modification. The spaceship coasts until it reaches a true anomaly 180° greater than when it made the first burn, in other words, at apoapsis of the transfer orbit. It then points at a 45° angle to Mars’ velocity vector instead of a 0° angle. That’s the third modification. The spaceship burns until its velocity is within 0.1 km/s of Mars’ velocity. This led to a pretty good rendezvous. The point I wanted to make with this demo was that the theoretical value was the minimum, and this maneuver, which was close to a Hohmann transfer, had a ΔV that was within 0.9 km/s of the Hohmann transfer value.
Phase Maneuver
In contrast to the semi-Hohmann transfer, the phase demo worked out quite well. The user can specify how many degrees the spaceship is behind the planet, the orbits it should take to rendezvous, and the size of the starting orbit. The target spaceship velocity after the first burn and the theoretical ΔV are calculated using the phase maneuver equations.
If the degrees behind is less than or equal to 180°, the spaceship points in the opposite direction of its velocity. The spaceship is more behind the planet than ahead, so it will slow down into a smaller, faster orbit to catch the planet. If degrees behind is greater than 180°, the spaceship will speed up into a larger, slower orbit to let the planet catch up. The first burn goes until the spaceship velocity is within 0.1 km/s of 100.3% of the target velocity. The extra 0.3% is to compensate for the small inaccuracies of cutting the engine when the spaceship can be 0.1 km/s too slow. If the first burn takes more than 1.8 seconds, I stop the simulation because the spaceship is not going to be able to reach its target velocity. The maneuver demands more thrust than the spaceship has. When the spaceship has traveled the specified number of transfer orbits, it rotates to the opposite direction of when it fired the first time. If it sped up the first time, it will slow down this time and vice versa. It fires until its velocity is within 0.1 km/s of the planet’s orbit speed.
The spaceship gets closest to the planet when the initial orbit is large, the spacecraft-planet gap is small, and there are many orbits to rendezvous. All of these factors decrease the duration of the burn, making the burn closer to a theoretical instantaneous burn, which is what the target velocities are based off of. Sometimes, the spaceship will burn a little too much the first time which puts it into a faster orbit than designed and causing it to end up ahead of the planet.
It’s interesting to see the effect of the parameters on the theoretical ΔV. Doubling the transfer orbits from 1 to 2 decreases ΔV by 58%. Doubling the orbit radius from 100 pixels to 200 pixels only decreases ΔV by 29%. Interestingly, halving the gap from 90° to 45° gives the same ΔV as doubling the transfer orbits. This relationship stays consistent for other multiples: at 220°, 1 orbit, and 150 pixels radius, ΔV is 6.2 km/s. Dividing the gap by 7 to get 340° or multiplying the transfer orbits by 7 both give a ΔV of 1.2 km/s.