Launch into Orbit#

This tutorial launches a two-stage rocket into a 150km circular orbit. The program assumes you are using this craft file.

The program is available in a variety of languages:

C, C#, C++, Java, Lua, Python

The following code connects to the server, gets the active vessel, sets up a bunch of streams to get flight telemetry then prepares the rocket for launch.

#include <math.h>
#include <unistd.h>
#include <krpc_cnano.h>
#include <krpc_cnano/services/space_center.h>

int main() {
  krpc_connection_t conn;
  krpc_open(&conn, "COM0");
  krpc_connect(conn, "Launch into orbit");

  krpc_SpaceCenter_Vessel_t vessel;
  krpc_SpaceCenter_ActiveVessel(conn, &vessel);

  float turn_start_altitude = 250;
  float turn_end_altitude = 45000;
  float target_altitude = 150000;

  krpc_SpaceCenter_Flight_t flight;
  krpc_SpaceCenter_Vessel_Flight(conn, &flight, vessel, KRPC_NULL);
  krpc_SpaceCenter_Orbit_t orbit;
  krpc_SpaceCenter_Vessel_Orbit(conn, &orbit, vessel);
  krpc_SpaceCenter_Stage_t stage_2;
  krpc_SpaceCenter_Vessel_DecoupleStageAt(conn, &stage_2, vessel, 2);
  krpc_SpaceCenter_Resources_t stage_2_resources;
  krpc_SpaceCenter_Stage_Resources(conn, &stage_2_resources, stage_2, false);

  krpc_SpaceCenter_Control_t control;
  krpc_SpaceCenter_Vessel_Control(conn, &control, vessel);
  krpc_SpaceCenter_AutoPilot_t auto_pilot;
  krpc_SpaceCenter_Vessel_AutoPilot(conn, &auto_pilot, vessel);

  krpc_SpaceCenter_Control_set_SAS(conn, control, false);
  krpc_SpaceCenter_Control_set_RCS(conn, control, false);
  krpc_SpaceCenter_Control_set_Throttle(conn, control, 1);

  printf("3...\n");
  sleep(1);
  printf("2...\n");
  sleep(1);
  printf("1...\n");
  sleep(1);
  printf("Launch!\n");

The next part of the program launches the rocket. The main loop continuously updates the auto-pilot heading to gradually pitch the rocket towards the horizon. It also monitors the amount of solid fuel remaining in the boosters, separating them when they run dry. The loop exits when the rockets apoapsis is close to the target apoapsis.

  krpc_SpaceCenter_Control_ActivateNextStage(conn, NULL, control);
  krpc_SpaceCenter_AutoPilot_set_Engaged(conn, auto_pilot, true);
  krpc_SpaceCenter_AutoPilot_TargetPitchAndHeading(conn, auto_pilot, 90, 90);

  bool srbs_separated = false;
  double turn_angle = 0;
  while (true) {
    double altitude;
    krpc_SpaceCenter_Flight_MeanAltitude(conn, &altitude, flight);
    double apoapsis;
    krpc_SpaceCenter_Orbit_ApoapsisAltitude(conn, &apoapsis, orbit);

    if (altitude > turn_start_altitude && altitude < turn_end_altitude) {
      double frac = (altitude - turn_start_altitude) / (turn_end_altitude - turn_start_altitude);
      double new_turn_angle = frac * 90.0;
      if (fabs(new_turn_angle - turn_angle) > 0.5) {
        turn_angle = new_turn_angle;
        krpc_SpaceCenter_AutoPilot_TargetPitchAndHeading(conn, auto_pilot, 90 - turn_angle, 90);
      }
    }

    if (!srbs_separated) {
      float srb_fuel;
      krpc_SpaceCenter_Resources_Amount(conn, &srb_fuel, stage_2_resources, "SolidFuel");
      if (srb_fuel < 0.1) {
        krpc_SpaceCenter_Control_ActivateNextStage(conn, NULL, control);
        srbs_separated = true;
        printf("SRBs separated\n");
      }
    }

    if (apoapsis > target_altitude * 0.9) {
      printf("Approaching target apoapsis\n");
      break;
    }
  }

Next, the program fine tunes the apoapsis, using 25% thrust, then waits until the rocket has left Kerbin’s atmosphere.

  krpc_SpaceCenter_Control_set_Throttle(conn, control, 0.25);
  while (true) {
    double apoapsis;
    krpc_SpaceCenter_Orbit_ApoapsisAltitude(conn, &apoapsis, orbit);
    if (apoapsis >= target_altitude)
      break;
  }
  printf("Target apoapsis reached\n");
  krpc_SpaceCenter_Control_set_Throttle(conn, control, 0);

  printf("Coasting out of atmosphere\n");
  while (true) {
    double altitude;
    krpc_SpaceCenter_Flight_MeanAltitude(conn, &altitude, flight);
    if (altitude >= 70500)
      break;
  }

It is now time to plan the circularization burn. First, we calculate the delta-v required to circularize the orbit using the vis-viva equation. We then calculate the burn time needed to achieve this delta-v, using the Tsiolkovsky rocket equation.

Note

The per-stage values that feed this calculation are also available directly from the staging API: Vessel.stage_at() returns a Stage object with properties such as Stage.delta_v, Stage.specific_impulse and Stage.burn_time. The derivation is shown here because we need the burn time for a specific delta-v, rather than for burning the whole stage.

  printf("Planning circularization burn\n");
  krpc_SpaceCenter_CelestialBody_t body;
  krpc_SpaceCenter_Orbit_Body(conn, &body, orbit);
  double mu;
  krpc_SpaceCenter_CelestialBody_GravitationalParameter(conn, &mu, body);
  double r;
  krpc_SpaceCenter_Orbit_Apoapsis(conn, &r, orbit);
  double a1;
  krpc_SpaceCenter_Orbit_SemiMajorAxis(conn, &a1, orbit);
  double a2 = r;
  double v1 = sqrt(mu * ((2.0 / r) - (1.0 / a1)));
  double v2 = sqrt(mu * ((2.0 / r) - (1.0 / a2)));
  double delta_v = v2 - v1;
  double ut;
  krpc_SpaceCenter_UT(conn, &ut);
  double time_to_apoapsis;
  krpc_SpaceCenter_Orbit_TimeToApoapsis(conn, &time_to_apoapsis, orbit);
  krpc_SpaceCenter_Node_t node;
  krpc_SpaceCenter_Control_AddNode(conn, &node, control, ut + time_to_apoapsis, delta_v, 0, 0);

  float F;
  krpc_SpaceCenter_Vessel_AvailableThrust(conn, &F, vessel);
  float isp;
  krpc_SpaceCenter_Vessel_SpecificImpulse(conn, &isp, vessel);
  double Isp = isp * 9.82;
  float m0;
  krpc_SpaceCenter_Vessel_Mass(conn, &m0, vessel);
  double m1 = m0 / exp(delta_v / Isp);
  double flow_rate = F / Isp;
  double burn_time = (m0 - m1) / flow_rate;

Next, we need to rotate the craft and wait until the circularization burn. We orientate the ship along the y-axis of the maneuver node’s reference frame (i.e. in the direction of the burn) then time warp to 5 seconds before the burn.

  printf("Orientating ship for circularization burn\n");
  krpc_SpaceCenter_ReferenceFrame_t node_ref;
  krpc_SpaceCenter_Node_ReferenceFrame(conn, &node_ref, node);
  krpc_SpaceCenter_AutoPilot_set_ReferenceFrame(conn, auto_pilot, node_ref);
  krpc_tuple_double_double_double_t burn_direction = {0, 1, 0};
  krpc_SpaceCenter_AutoPilot_set_TargetDirection(conn, auto_pilot, &burn_direction);
  krpc_SpaceCenter_AutoPilot_Wait(conn, auto_pilot, -1);

  printf("Waiting until circularization burn\n");
  krpc_SpaceCenter_UT(conn, &ut);
  krpc_SpaceCenter_Orbit_TimeToApoapsis(conn, &time_to_apoapsis, orbit);
  double burn_ut = ut + time_to_apoapsis - (burn_time / 2.0);
  double lead_time = 5;
  krpc_SpaceCenter_WarpTo(conn, burn_ut - lead_time, 100000, 2);

This next part executes the burn. It sets maximum throttle, then throttles down to 5% approximately a tenth of a second before the predicted end of the burn. It then monitors the remaining delta-v until it flips around to point retrograde (at which point the node has been executed).

  printf("Ready to execute burn\n");
  while (true) {
    krpc_SpaceCenter_UT(conn, &ut);
    krpc_SpaceCenter_Orbit_TimeToApoapsis(conn, &time_to_apoapsis, orbit);
    if (time_to_apoapsis - (burn_time / 2.0) <= 0)
      break;
  }
  printf("Executing burn\n");
  krpc_SpaceCenter_Control_set_Throttle(conn, control, 1);
  sleep((unsigned int)(burn_time - 0.1));
  printf("Fine tuning\n");
  krpc_SpaceCenter_Control_set_Throttle(conn, control, 0.05);
  while (true) {
    krpc_tuple_double_double_double_t remaining_burn;
    krpc_SpaceCenter_Node_RemainingBurnVector(conn, &remaining_burn, node, node_ref);
    if (remaining_burn.e1 <= 0)
      break;
  }
  krpc_SpaceCenter_Control_set_Throttle(conn, control, 0);
  krpc_SpaceCenter_Node_Remove(conn, node);

  printf("Launch complete\n");
}

The rocket should now be in a circular 150km orbit above Kerbin.