Automating the circularization of Apollo in Kerbal with python, KRPC, and Physics (2024)

Automating the circularization of Apollo in Kerbal with python, KRPC, and Physics (1)

Download the corresponding notebook.

Introduction

Kerbal Space Program (KSP) (1.0) is a semi-physics-realistic space exploration simulation. While it is not realistic enough to plan actual space missions, it is a fun educational tool that can get us started. With the kRPC mod (remote procedure call, which enables programatic interaction with KSP’s API), the educational potential is expanded into the world of programming. In this notebook, we will automate taking the Kerbins to the moon and back using Python, Physics, and KSP with the kRPC mod.

Installation

Get KSP

  • Purchase and install the Kerbal Space Program (v 1.0) here.
  • You’ll also need the “Making History” expansion which has the Apollo rocket equivalent, unless you prefer to save some money and build an equivalent rocket yourself or find the ship file online. Note that this code is tested and verified to work with the Acopollo rocket found in this expansion, so you may have to make adjustments to get alternative rockets to work.

Install the KRPC mod

Follow this guide to install the kRPC mod. More or less, you’ll grab the kRPC folder and put it in the GameData folder wherever Kerbal is installed on your workstation.

Automating the circularization of Apollo in Kerbal with python, KRPC, and Physics (2)

Prepping the jupyter workspace

If you are using Windows, installing anaconda may be your quickest route, and then set up a kerbal environment by opensing a terminal and running:

1
conda create --name kerbal

You’ll only need to create the envrionment once. Next activate it:

1
conda activate kerbal

If you are on MacOS or Linux, you can use virtualenv instead (although conda can work too).

and then install the following packages:

12345
pip install setuptools==57.5.pip install protobuf~=3.19.0pip install krpcpip install jupyterpip install ipykernel

Or preferably, use a requirements file:

12345
setuptools==57.5.0protobuf~=3.19.0krpcjupyteripykernel

If you are using Python >= 3.8, you’ll have to do a little hack. Open the file in your virtual environment files with an editor and make the following change.

  • FILE: Should be in your virtual environment with something along the lines of venv/lib/python3.10/site-packages/krpc/types.py on line 222 and 227.

  • Replace:

1
collections.Iterable

with

1
collections.abc.Iterable

Next, create the kernel that we’ll be using for this notebook:

1
python -m ipykernel install --user --name kerbal --display-name "Python (kerbal)"

and then to launch jupyter:

1
jupyter notebook

Going to the Mun

Connecting to KSP

In our first code blocks, we will be importing the libraries we need to get our astronauts to the Mun via Python. We will then connect to KSP vis the krpc plugin (assumes you have KSP up and running and the plugin working).

1234
import krpcimport mathimport timefrom IPython.display import clear_output, display
1
conn = krpc.connect()

Loading the Apollo rocket

1
conn.space_center.load("apollo001")
123456
vessel = conn.space_center.active_vessel# Set up streams for telemetryut = conn.add_stream(getattr, conn.space_center, 'ut')altitude = conn.add_stream(getattr, vessel.flight(), 'mean_altitude')apoapsis = conn.add_stream(getattr, vessel.orbit, 'apoapsis_altitude')stage_2_resources = vessel.resources_in_decouple_stage(stage=2, cumulative=False)
12
obt_frame = vessel.orbit.body.non_rotating_reference_framemun_orbit = conn.space_center.bodies["Mun"].position(obt_frame)

Gravity Turn into Orbit

In this next section, we are calculating the gravity turn angle. The sample provided by the KRPC samples uses a simple fraction to define the trun angle in degrees:\[ \alpha = 90(\frac{a - s}{ e - s}) \]where \(a\) is the current altitude, \(s\) is the altitude in which we want to start slowly turning the rocket horizontally, and \(e\) is the ending altitude where we want to have completed our turn upon reaching. This could be defined by a simple function

 1 2 3 4 5 6 7 8 910
def get_gravity_turn_angle(alt, start_alt, end_alt, turn_angle): new_turn_angle = 0 if alt > start_alt and alt < end_alt: frac = (alt - start_alt)/(end_alt - start_alt) new_turn_angle = frac * 90.0 if abs(new_turn_angle - turn_angle) > 0.5: turn_angle = new_turn_angle else: turn_angle = 0 return turn_angle

In a future blog post, we will improve the gravity turn by invoking Physics to get a more accurate turn rate. For now, as a proof of concept and to focus on the circularization physics, we will proceed with this rough linear gravity turn. Next, we actually launch the rocket and execute the gravity turn so that we reach a target apoapsis:

123
vessel.auto_pilot.target_pitch_and_heading(90, 90)vessel.auto_pilot.engage()vessel.control.throttle = 1
 1 2 3 4 5 6 7 8 910111213141516171819202122
vessel.control.activate_next_stage()turn_angle = 0start_alt = 250end_alt = 45000target_alt = 700000state = "LiftOff"while turn_angle >= 0 and vessel.control.throttle > 0: clear_output(wait=True) turn_angle = get_gravity_turn_angle(altitude(), start_alt, end_alt, turn_angle) if turn_angle != 0 and apoapsis() < target_alt: vessel.auto_pilot.target_pitch_and_heading(90-turn_angle, 90) state = "GravityTurn" if apoapsis() > target_alt*0.90 and apoapsis() < target_alt: state = "ApoapsisRefinement" vessel.control.throttle = 0.25 while apoapsis() < target_alt: pass if apoapsis() >= target_alt: state = "GoalApoapsisAchieved" vessel.control.throttle = 0.00 

Automating the circularization of Apollo in Kerbal with python, KRPC, and Physics (3)

As the rocket climbs higher, it will ease into an orientation perpendicular to the radius of the Earth:

Automating the circularization of Apollo in Kerbal with python, KRPC, and Physics (4)

Circularizing the orbit

For an idealized circular orbit above atmospheric effects, the gravitational pull of the Earth on the body provides the centripetal force, with circular orbital radius \(r\) and let

\[\mu = GM\]

where \(G\) is the universal gravitational constant and \(M\) is the mass of the large body (here, the Earth)

KRPC provides an easy way to access that value for any given celestial body:

1
mu = vessel.orbit.body.gravitational_parameter

Back to Physics, we now have two equations from the basics of Newtonian physics, namely:

  • Cetripital Force: \[ F_c = \frac{m_0 v^2}{r}\]
  • Gravitational Force: \[ F_g = \frac{m_0 GM}{r^2}\]

Since these must balance out for an object to be in stead orbit, we can solve to find the ideal velocity \(v\) for a given orbit at radius \(r\):

\[ F_g = m_0 a = \frac{m_0 \mu}{r^2} =\frac{m_0 v^2}{r} \]

\[\implies v = \sqrt{ \frac{\mu}{r} }\]

We see here that this velocity is entirely independent of the mass of the body, hence a very heavy object and a very light object which orbit at the same radius must be traveling at the same speed, assuming of course they are out of the region where atmospheric drag plays an important role.

Finding an equation for the circularization of an orbit

That is a starting point, but we have to dive deeper to calculate the numbers needed to actually achieve an approximation of this idealized orbit.

Our next step is to invoke the vis-viva equation (or also called the orbital-energy-invariance law). We begin by noting that the specific orbital energy of an orbiting object and the body it is orbiting is defined as a sum of their mutual potential energy and their total kinetic energy:

\[ E_O = E_p + E_k\]

For scenarios such as ours, where the orbiting object is much smaller in both size and mass than the body it orbits, this energy becomes easier to calculate since we can treat the larger body as being the center of our reference frame and hence at rest. We can also neglect the potential energy experienced by the gravitational attraction of the larger body by the smaller body. In this case,

\[ E_O = \frac{m_0 v^2_0}{2} - \frac{\mu m_0}{r_0} \]

The specific total energy is given as \(E_o/m_0 = \epsilon\) and this is conserved throughout the orbit (assuming the rocket is not burning fuel in an idealized orbit). Let \(v_a\) and \(r_a\) be the velocity and radius of the orbiting body at the apoapsis, and \(v_p\) and \(r_p\) similarly at the periapsis. Then energy conservation gives us the relation,

\[ \epsilon = \frac{v_a^2}{2} - \frac{\mu}{r_a} = \frac{v_p^2}{2} - \frac{\mu}{r_p} \]

At both \(r_a\) and \(r_p\), the velocity and radius vectors are perpendicular to each other, where hence we can invoke the conservation of angular momentum to give

\[ r_p v_p = r_a v_a = Constant \]

This gives us the relation that\[ v_p =- \frac{r_a}{r_p}v_a \]

and with some rearrangement of these equations, we get,

\[ \frac{1}{2}\left( \frac{r_p^2 -r_a^2}{r_p^2}\right) v_a^2 = \mu \left(\frac{1}{r_a} - \frac{1}{r_p}\right) \]\[ \frac{1}{2}v_a^2 = \mu \frac{r_p}{r_a \left( r_p + r_a \right)} \]

Relating this to elipses, the apoapsis and periapsis

From geometry of an ellipse that relates the semimajor axis to \(r_p\) and \(r_a\), \(2a = r_p + r_a\)

12
r = vessel.orbit.apoapsisa1 = vessel.orbit.semi_major_axis

We substitute 2a in the our prior kinetic energy equation:\[ \frac{1}{2}v_a^2 = \mu \frac{2a -r_a}{2 r_a a} \]\[ \frac{1}{2}v_a^2 = \mu \left(\frac{1}{r_a} - \frac{1}{2a}\right) \]

\[ v_a^2 = \mu \left( \frac{2}{r_a} - \frac{1}{a}\right) \]

In a circularized orbit, \(a = r\), and so the velocity we need to have is

\[ v_a^2 = \mu \left( \frac{2}{r_a} - \frac{1}{r_a}\right) = \mu \left( \frac{1}{r_a}\right) \]

The \(\Delta v\) we need to achieve is the difference between these two velocities,

$$ \Delta v = \sqrt{ \mu} \left( \sqrt{\left( \frac{1}{r_a}\right) } - \sqrt{\left( \frac{2}{r_a} - \frac{1}{a}\right)}\right) $$$$ = \sqrt{\frac{\mu}{r_a}}\left( 1 - \sqrt{ \frac{2a -r_a}{a}}\right) $$

In krpc code,

1
delta_v = math.sqrt(mu/r)*(1-math.sqrt((2*a1-r)/a1))

With this number in hand, we can do a little more math which will be discussed in more detail later to find the burn time. This calculation is highly dependent on the engine and design of the rocket in question:

12345678
f = vessel.available_thrustIsp = vessel.specific_impulse * 9.82m0 = vessel.massm1 = m0 / math.exp(delta_v / Isp)fr = f / Ispburn_time = (m0 - m1) / fr
12
node = vessel.control.add_node( ut() + vessel.orbit.time_to_apoapsis, prograde=delta_v)
 1 2 3 4 5 6 7 8 9101112131415161718192021222324252627282930313233343536373839404142
# https://krpc.github.io/krpc/tutorials/launch-into-orbit.htmlprint('Orientating ship for circularization burn')vessel.auto_pilot.disengage()vessel.auto_pilot.sas = Truetime.sleep(.1)vessel.auto_pilot.sas_mode = vessel.auto_pilot.sas_mode.maneuvervessel.auto_pilot.wait()print('Waiting until circularization burn')burn_ut = ut() + vessel.orbit.time_to_apoapsis - (burn_time/2.)lead_time = 5conn.space_center.warp_to(burn_ut - lead_time)# Execute burnprint('Ready to execute burn')time_to_apoapsis = conn.add_stream(getattr, vessel.orbit, 'time_to_apoapsis')while time_to_apoapsis() - (burn_time/2.) > 0: passvessel.auto_pilot.wait()print('Executing burn')vessel.control.throttle = 1.0time.sleep(burn_time - 0.05)print('Fine tuning')vessel.control.throttle = 0.05remaining_burn = conn.add_stream(node.remaining_burn_vector, node.reference_frame)#vessel.auto_pilot.engage()vessel.auto_pilot.disengage()vessel.auto_pilot.sas = Truetime.sleep(.1)vessel.auto_pilot.sas_mode = vessel.auto_pilot.sas_mode.maneuvervessel.control.throttle = 0.03while node.remaining_delta_v > 4: passvessel.control.throttle = 0.0node.remove()time.sleep(5)print('Launch complete')
Orientating ship for circularization burnWaiting until circularization burnReady to execute burnExecuting burnFine tuningLaunch complete

If all went well, you should be in a fairly accurate (and we can make it even better!) circularized orbit:

Automating the circularization of Apollo in Kerbal with python, KRPC, and Physics (5)

Now that we have circularized our orbit, we can do some house keeping and eject uneeded components from the rocket. In a future iteration, we will want to eject these as soon as we clear the atmosphere in order to reduce as much mass as soon as possible:

123456
# Drop stage 1vessel.control.activate_next_stage()# Drop the escape rocketvessel.control.activate_next_stage()# Drop the shields to lower weightvessel.control.activate_next_stage()

Automating the circularization of Apollo in Kerbal with python, KRPC, and Physics (6)

Automating the circularization of Apollo in Kerbal with python, KRPC, and Physics (2024)

FAQs

Does Kerbal Space Program use real physics? ›

In the game, players direct the space program of a species of green humanoid aliens known as "Kerbals". The game features a pseudorealistic orbital physics engine, allowing for various real-life orbital maneuvers such as Hohmann transfer orbits and orbital rendezvous.

How do you orbit Kerbin? ›

Steps to Orbit and Back
  1. Launch Preparation. Set thrust to maximum by hitting Z. ...
  2. Accelerate to 100 m/s. Launch by hitting the space bar and keep the rocket pointed straight up until the vehicle's speed is 100 m/s. ...
  3. Pitch 10 degrees East. ...
  4. Stage. ...
  5. Get apoapsis above 70 km. ...
  6. Get periapsis above 70 km. ...
  7. De-orbiting. ...
  8. Re-entry.
May 8, 2023

Does NASA actually use KSP? ›

He (Doug Ellison) notes that many at NASA use KSP to experiment in ways that their more unforgiving real-world environment wouldn't allow them to do. In essence, they can do a rough test of the many strange ideas that never quite make it off the 'sketch on a napkin'.

Has Elon Musk played Kerbal Space Program? ›

The SpaceX and Tesla boss has been showing his appreciation for Kerbal Space Program for years. In a Reddit ask me anything session in 2015, he said the game was “awesome”. KSP has also acknowledged the relationship in the past – and even asked for similar help.

Can you orbit the moon in KSP? ›

Getting into Mun Orbit

Once you have gotten into the Mun's SOI, warp to periapsis, turn towards the retrograde vector on the Navball, and activate the engine (Z key). You can cut the engine once you enter a circular orbit around the Mun. Quicksave the game and name it "Mun Orbit".

How does KSP simulate orbits? ›

I note some differences in KSP (from wikipedia): The game simulates trajectories and orbits using patched conic approximation instead of a full n-body simulation, and thus does not support Lagrange points and halo orbits.

What is the deepest point in KSP? ›

Some of its mountains exceed 6 kilometers in height, with the tallest peak being 6767.4 m in altitude at the coordinates 46°21'32" E 61°35'53" N. The lowest point is almost 1.4 km deep and about 313° south-west of the Kerbal Space Center.

Does KSP use Newtonian physics? ›

All physics are newtonian. Space itself in KSP is a true vacuum, so solar wind and the force of light have no effect on spacecraft.

What physics engine does KSP use? ›

PhysX is the games physics engine in the game Kerbal Space Program.

Are KSP reaction wheels realistic? ›

Earth-based spacecraft use both reaction wheels and gimballed flywheels extensively. However, while KSP reaction wheels seem to be able to supply torque endlessly, real-world reaction wheels build up rotational momentum (equal and opposite to the torque they apply to the spacecraft) in flywheel speed.

What is KSP coded in? ›

So KSP is written in C#, which ten (TEN!) years ago was a bit more of an unusual choice than it would be today. And I think the non-windows versions still run on mono, which is a non-windows port of the . net runtime that runs the C# code.

References

Top Articles
Latest Posts
Article information

Author: Fr. Dewey Fisher

Last Updated:

Views: 5669

Rating: 4.1 / 5 (62 voted)

Reviews: 93% of readers found this page helpful

Author information

Name: Fr. Dewey Fisher

Birthday: 1993-03-26

Address: 917 Hyun Views, Rogahnmouth, KY 91013-8827

Phone: +5938540192553

Job: Administration Developer

Hobby: Embroidery, Horseback riding, Juggling, Urban exploration, Skiing, Cycling, Handball

Introduction: My name is Fr. Dewey Fisher, I am a powerful, open, faithful, combative, spotless, faithful, fair person who loves writing and wants to share my knowledge and understanding with you.