129 lines
5.9 KiB
Plaintext
Executable file
129 lines
5.9 KiB
Plaintext
Executable file
@LAZYGLOBAL OFF.
|
|
|
|
run once "lib/equations".
|
|
run once "lib/node".
|
|
run once "lib/rocket".
|
|
run once "lib/util".
|
|
run once "lib/vectors".
|
|
run once "lib/warp".
|
|
|
|
|
|
function launch {
|
|
// Launch to orbit of provided altitude and inclination.
|
|
parameter target_orbit_altitude is 100_000. // meters
|
|
parameter target_orbit_inclination is 0. // 0-180 degrees
|
|
parameter pitchover_tilt is 20. // how many degrees to tilt at pitchover maneuver
|
|
parameter pitchover_altitude is 1000. // perform pitchover at this altitude
|
|
parameter pitchover_velocity is 100. // or this velocity
|
|
|
|
|
|
print "========= LAUNCHING =========".
|
|
print "Target orbital altitude: " + target_orbit_altitude + "m".
|
|
print "Target orbital inclination: " + target_orbit_inclination + "°".
|
|
print "Pitchover tilt: " + pitchover_tilt + "°".
|
|
print "Pitchover at: " + pitchover_altitude + "m or " + pitchover_velocity + " m/s".
|
|
print " ".
|
|
|
|
|
|
// LAUNCH AZIMUTH
|
|
|
|
// Since the "center" of an orbit must be at the center of gravity of the body, the latitude of the launch site establishes the minimum absolute orbital inclination.
|
|
// KSC is almost on the equator, so we're going to always round the latitude towards zero, and accept the inaccuracies it may introduce.
|
|
local launch_site_latitude is round_towards_zero(SHIP:LATITUDE).
|
|
local target_orbit_inclination is MAX(target_orbit_inclination, launch_site_latitude).
|
|
|
|
// Calculate the launch azimuth; the compass heading we head for when launching to achieve orbit of desired inclination
|
|
local launch_azimuth is calculate_launch_azimuth(target_orbit_inclination, target_orbit_altitude, launch_site_latitude).
|
|
|
|
// If the latitude of the launch site is negative (ship is in the southern hemisphere), launch southwards instead of northwards
|
|
local southwards is launch_site_latitude < 0.
|
|
if southwards {
|
|
set launch_azimuth to 180 - launch_azimuth.
|
|
}
|
|
|
|
print "Launch site latitude: " + ROUND(SHIP:LATITUDE, 3) + "° (~" + launch_site_latitude + "°)".
|
|
print "Available orbital inclination: " + target_orbit_inclination + "°".
|
|
print "Launch azimuth: " + ROUND(launch_azimuth, 3) + "°".
|
|
print "Launch southwards: " + southwards.
|
|
|
|
|
|
print "--- VERTICAL CLIMB ---".
|
|
SAS OFF.
|
|
RCS OFF.
|
|
set NAVMODE to "SURFACE".
|
|
lock STEERING to HEADING(launch_azimuth, 90). // roll to launch azimuth
|
|
lock THROTTLE to 1.0.
|
|
|
|
|
|
// LAUNCH
|
|
|
|
// Enable auto-staging
|
|
when should_stage() then {
|
|
stage_when_ready().
|
|
return true. // preserve trigger
|
|
}
|
|
|
|
// Once a certain altitude (or velocity) is reached, a slight turn is made, called the pitchover maneuver
|
|
wait until SHIP:ALTITUDE > pitchover_altitude
|
|
or SHIP:VELOCITY:SURFACE:MAG > pitchover_velocity.
|
|
|
|
|
|
print "--- PITCHOVER ---".
|
|
lock STEERING to HEADING(launch_azimuth, 90-pitchover_tilt).
|
|
|
|
wait until actual_prograde_pitch() > pitchover_tilt. // wait until the prograde "catches up" to our tilted heading
|
|
|
|
|
|
print "--- GRAVITY TURN ---".
|
|
// TODO: the angle of the launch azimuth will not account for the fact that our compass will change as we move north/south.
|
|
lock STEERING to HEADING(launch_azimuth, 90-actual_prograde_pitch()). // Follow prograde pitch to get 0 deg angle of attack, but force compass heading at launch azimuth.
|
|
|
|
wait until APOAPSIS > target_orbit_altitude.
|
|
lock THROTTLE TO 0.
|
|
|
|
|
|
print "--- CIRCULARIZE ---".
|
|
print "Waiting for ship to leave the atmosphere..".
|
|
wait until SHIP:DYNAMICPRESSURE = 0. // don't create maneuver node until we are out of the atmosphere - otherwise the apoapsis altitude and eta will change due to drag
|
|
|
|
print "Deploying solar panels".
|
|
PANELS ON.
|
|
|
|
// Create maneuver node that will circularize the orbit.
|
|
// NOTE: Potential errors in the inclination are not fixed, since we are most likely going to change our orbit, which will make the inclination change cheaper later on.
|
|
local node is NODE(TIME:SECONDS + ETA:APOAPSIS, 0, 0, 0).
|
|
|
|
// Burn magnitude in the prograde direction is the difference between the required velocity to acheive circular orbit at apoapsis altitude and our velocity at apoapsis
|
|
local required_velocity is orbital_velocity_from_ap_pe(APOAPSIS, APOAPSIS, target_orbit_altitude).
|
|
set node:PROGRADE to required_velocity - VELOCITYAT(SHIP, TIME:SECONDS + ETA:APOAPSIS):ORBIT:MAG.
|
|
|
|
add node.
|
|
execute_node().
|
|
|
|
|
|
print "========= LAUNCH SEQUENCE COMPLETE =========".
|
|
unlock_control().
|
|
}
|
|
|
|
|
|
function calculate_launch_azimuth {
|
|
// Calculate the launch azimuth; the compass heading we head for when launching to achieve orbit of desired inclination.
|
|
// http://www.orbiterwiki.org/wiki/Launch_Azimuth
|
|
// https://www.princeton.edu/~stengel/MAE342Lecture4.pdf
|
|
parameter target_orbit_inclination.
|
|
parameter target_orbit_altitude. // to compensate for the rotation of the body, we need to know the velocity of the target orbit, which is calculated from its altitude
|
|
parameter launch_site_latitude.
|
|
|
|
local inertial_azimuth is ARCSIN(COS(target_orbit_inclination) / COS(launch_site_latitude)). // azimuth in inertial space, that is, disregarding the rotation of the body
|
|
|
|
local equatorial_rotational_velocity is (2 * CONSTANT:PI * BODY:RADIUS) / BODY:ROTATIONPERIOD.
|
|
local target_orbit_velocity is orbital_velocity_from_ap_pe(target_orbit_altitude, target_orbit_altitude, target_orbit_altitude).
|
|
|
|
local launch_vector_x_component is target_orbit_velocity * SIN(inertial_azimuth) - equatorial_rotational_velocity * COS(launch_site_latitude).
|
|
local launch_vector_y_component is target_orbit_velocity * COS(inertial_azimuth).
|
|
return ARCTAN2(launch_vector_x_component, launch_vector_y_component).
|
|
}
|
|
|
|
|
|
launch(100_000, 0).
|