This is an over-engineered attempt to perform a very efficient Mun landing, which I worked on together with my friend Joost Meulenbeld. Using kRPC, we have written an autopilot that executes the landing automatically.
For a perfectly spherical body, the ideal trajectory would be to place the periapsis just centimeters above the surface. An almost horizontal suicide burn then kills of all horizontal velocity. However, Mun is not a perfectly spherical body and this approach would risk us to fly into a mountain. The varying mass also prevents us from making a simple calculation.
Our method is to first generate a reference approach profile. We built a simulator that implements the orbital mechanics. Instead of starting the simulator in orbit and simulating our way towards the surface, the simulation is started on the landing spot. The fuel mass is increasing in this ‘reversed’ simulator, but everything else is the same. The simulator starts with a constant pitch angle of 10 degrees and 90% throttle. The angle can be lowered further, depending on obstacles on the surface of Mun. 90% throttle is chosen to leave some margin for control, as we want to do a precision landing of course.
The ‘reversed’ landing simulator
Where is the radius from the center of Mun and is vertical speed. is the angle relative to the landing location at the landing time and is the angular velocity. is the remaining fuel mass.
is positive! Mass is increasing in this ‘reversed’ simulator. is throttle, is the thrust delivered at 100% throttle and is the mass flow at 100% throttle. is the pitch angle relative to the horizontal direction. is the vehicle mass, which is the sum of the vehicle fuel mass and dry mass . and are the gravitational constant and mass of Mun.
The differential equations are converted to python and are solved by the solve_ivp function of scipy, with time steps of 0.1s.
Getting to orbit
Now that we have a ‘reversed’ simulator, the task is to find a set of control inputs that results in a circular orbit at 10 km above the surface.
- Apply 90% throttle at 10 degrees pitch, until the apoapsis reaches 10 km above the surface.
- Coast to the apoapsis.
- Perform a circularization burn at apoapsis.
For step 1, we need to know the apoapsis of the orbit in order to stop burning in time. From the simulator, we only have the state vector which does not contain orbit parameters. The following calculations allow us to calculate orbit parameters just from , and :
is the length of the velocity vector, is the flight path angle, is the semi-major axis of the ellipse and is the eccentricity of the ellipse. and are the radius at apoapsis and periapsis respectively. is positive when approaching the apoapsis and negative when approaching the periapsis. Using these parameters and the current radius we can determine the position on the ellipse.
is the eccentric anomaly, is the mean anomaly and is the true anomaly. is the mean motion in [rad/s]. Using these equations, we can calculate the time to apoapsis and velocity at apoapsis :
The required orbital velocity for a circular orbit at radius is given by:
The duration of the cirularization burn is estimated using a constant mass:
For the circularization burn, a throttle setting of 50% was used. The burn starts seconds before reaching apoapsis.
Iterate to find correct fuel mass
The reversed simulator needs to start with an unknown quantity of fuel. The initial run can start with 0 kg. This will result in a certain amount of fuel in circular orbit. The amount of landed fuel is iterated a couple of times until the the orbit fuel mass matches with the fuel on board the ship.
The flight profile is now complete. Altitude and throttle are plotted here against time:
Compensate for rotation of Mun
The angle where we need to start the de-orbit burn is relative to the landing location at . However, the landing location is moving with approximately 9m/s because Mun rotates. That’s more than 2km error if we don’t compensate. If the de-orbit burn starts at . The longitude at which we need to start the first burn is:
where is the rotational velocity of Mun in [rad/s].
Feedback control in the landing burn
The de-orbit burn is purely feed-forward. This needs to be timed precisely. A tiny deviation in the de-orbit burn can result in a large error at the start of the landing burn.
The reference trajectory describes the desired vehicle state for every moment in time. However, there will be small deviations from this profile that need to be corrected for. Since Mun itself is rotating, we must aim for the landing to happen at t=0. Every second difference increases the error by 9 meters. The variables we try to control are longitude and radius (altitude). A relatively simple controller is implemented that decouples these. To control longitude, we use thrust. For altitude control, we use the pitch angle.
The longitude error is defined by
where is the longitude in the reference trajectory at a given time and is the longitude of the ship. This is converted to a horizontal distance error, which is more practical for control.
The throttle setpoint is defined by the following PD controller with feed-forward from the reference trajectory:
The gains and are found kerbal-style by tuning. is bound between 0.8 and 1.0 (the reference trajectory has a constant value of 0.9).
The altitude error is:
The pitch angle setpoint is controlled with the following PD-controller with feed-forward from the reference trajectory:
These gains are also tuned kerbal-style, and the pitch setpoint is bound between 0 degrees and 20 degrees. The reference trajectory is 10 degrees.
Horizontal ‘suicide burn’
For the last 1000 meters, a different horizontal controller is used for improved landing accuracy. It is somewhat similar to a suicide burn, except that it requires slightly less than 100% throttle. When we are this close to the target, it is safe to ignore orbit dynamics and pretend that Mun is flat.
If the following constant horizontal acceleration setpoint would be applied, the horizontal velocity reaches zero exactly at the target:
where is the horizontal velocity and is the horizontal distance to the target. The required horizontal acceleration can be translated to a horizontal thrust setpoint:
Technically we would need a little more thrust to compensate for the pitch of the vehicle. Also, the target height is increased by 5 meters so that we can quickly rotate the vehicle upright for a smooth vertical touchdown.
This post just shows the part where we get from orbit to the surface of the Mun, but we have already automated the entire flight starting at launch from Kerbin. The next step will be to build a Mun base that mines for fuel. Instead of landing on the surface, we can build vehicles that automatically dock to the Mun base and don’t require landing legs. Then, we can transfer massive amounts of fuel from the Mun base to an orbital station, where we can refuel the biggest rockets and spaceships to send to the edge of the Kerbol System and beyond!
For those who are interested: the code is open-source, but not documented.