Skip to content

Instantly share code, notes, and snippets.

@PyroSA
Created April 11, 2023 04:42
Show Gist options
  • Save PyroSA/30f3b1c061981e092626fd69ecbbdc94 to your computer and use it in GitHub Desktop.
Save PyroSA/30f3b1c061981e092626fd69ecbbdc94 to your computer and use it in GitHub Desktop.
A extended launch script for KOS2 for KSP2
use { Vessel, AutopilotMode } from ksp::vessel
use { trigger_staging } from std::staging
use { current_time, sleep, wait_until } from ksp::game
use { acos_deg, max, min, clamp } from core::math
use { CONSOLE } from ksp::console
use { estimate_burn_time, exec_next_node } from std::vac
use { circularize_orbit_at, circularize_orbit } from std::maneuvers
use { add_time_series, remove_all_time_series } from ksp::telemetry
use { angle_axis} from ksp::math
use { format } from core::str
/// Automatically launch a rocket from an atmosphere to a circular orbit.
fn atmo_launch(vessel: Vessel, target_apoapsis: float, heading: float, low_turn: float = 0.007, high_turn: float = 0.7, slip_limit: float = 5) -> Result<Unit, string> = {
vessel.actions.light = true
vessel.autopilot.enabled = true
vessel.autopilot.mode = AutopilotMode.Autopilot
atmo_launch_ascent(vessel, target_apoapsis, heading, low_turn, high_turn, slip_limit)
const (delta_v, UT) = circularize_orbit(vessel.orbit)?
let (burn_time, half_burn_time) = estimate_burn_time(vessel, delta_v.magnitude, 0.5, 1.0)
vessel.maneuver.add_burn_vector(UT - half_burn_time, delta_v)?
exec_next_node(vessel)?
}
/// Perform a rocket launch ascent from an atmosphere.
/// Note: The rocket will not end up in a stable orbit and most likely crash if no further action is taken.
fn atmo_launch_ascent(vessel: Vessel, target_apoapsis: float, heading: float, low_turn: float = 0.007, high_turn: float = 0.7, slip_limit: float = 5) -> Unit = {
CONSOLE.print_line("=== Start: atmo_launch_ascent ===")
const console_row = CONSOLE.cursor_row
CONSOLE.move_cursor(console_row + 7, 0)
// Starting/ending height of gravity turn
const launch_gt0 = vessel.main_body.atmosphere_depth * low_turn
const launch_gt1 = vessel.main_body.atmosphere_depth * high_turn
const throttle_manager = vessel.manage_throttle(fn(deltaT) -> {
const atmPct = vessel.altitude_sealevel / (vessel.main_body.atmosphere_depth + 1)
const spd = vessel.surface_velocity.magnitude
const cutoff = 200 + (1200 * max(0, atmPct))
const spdLimit = if (spd > cutoff && vessel.altitude_sealevel < vessel.main_body.atmosphere_depth)
1.0 - max(-1.0, ((spd - cutoff) / cutoff))
else
1.0
const dpLimit = 1 - clamp((vessel.dynamic_pressure_kpa - 20) / 5, -1.0, 0.9)
const apoTime = vessel.orbit.next_apoapsis_time()
const burnLimit = if (apoTime.defined && vessel.orbit.apoapsis.value > vessel.main_body.atmosphere_depth) {
if (vessel.orbit.next_periapsis_time() < apoTime.value) {
CONSOLE.print_at(console_row + 1, 30, "Too Late")
1.0
} else
{
const cirDv = circularize_orbit_at(vessel.orbit, apoTime.value)
const (burn_time, half_burn_time) = estimate_burn_time(vessel, cirDv.magnitude, 0.5, 1)
CONSOLE.print_at(console_row + 1, 30, format("{0,4:###0}:{1,4:###0}={2,4:###0}", [burn_time, half_burn_time, cirDv.magnitude]))
clamp((current_time() + half_burn_time + 40 - apoTime.value) / 20, 0, 2)
}
} else {
0
}
const apoPercent = (vessel.orbit.apoapsis.value - vessel.main_body.atmosphere_depth) / (target_apoapsis - vessel.main_body.atmosphere_depth)
const apoLimit = clamp(1.0 - apoPercent, 0.1, 1)
CONSOLE.print_at(console_row, 0, "Limits:")
CONSOLE.print_at(console_row, 10, format("Spd: {0:##0%}", spdLimit))
CONSOLE.print_at(console_row, 20, format("DP: {0:##0%}", dpLimit))
CONSOLE.print_at(console_row, 30, format("Apo: {0:##0%}", apoLimit))
CONSOLE.print_at(console_row, 40, format("Burn: {0:##0%}", burnLimit))
if (vessel.orbit.apoapsis.value > target_apoapsis) 0.0 else clamp(max(burnLimit, min(min(spdLimit, dpLimit), apoLimit)), 0.0, 1.0)
})
sleep(1.0)
vessel.staging.next()
let ut = current_time()
let st = current_time()
let altitudeTS = add_time_series("Altitude", 2, 0.1)
let massTS = add_time_series("Mass", 2, 0.1)
let pitchTS = add_time_series("Pitch", 2, 0.1)
let dpTS = add_time_series("Dyn Pressure", 2, 0.1)
let surface_velocityTS = add_time_series("Surface Vel", 2, 0.1)
let horizonal_surface_speedTS = add_time_series("Horizonal Srf Speed", 2, 0.1)
let apoapsisTS = add_time_series("Apoapsis", 2, 0.1)
let slipTS = add_time_series("Slip", 2, 0.1)
let errorTS = add_time_series("Error", 2, 0.1)
while(vessel.orbit.apoapsis.value < target_apoapsis || vessel.altitude_sealevel < vessel.main_body.atmosphere_depth * 0.8) {
const gtPct = clamp((vessel.altitude_sealevel - launch_gt0) / (launch_gt1 - launch_gt0), 0, 1)
const pitch = acos_deg(gtPct)
let target = vessel.heading_direction(heading, pitch, 0).vector
const slip = vessel.surface_velocity.angle_to(vessel.facing.vector)
const error = vessel.surface_velocity.angle_to(target)
// Limit turn rate for unstable ships
const atmPct = vessel.altitude_sealevel / (vessel.main_body.atmosphere_depth + 1)
const scaled_slip_limit = slip_limit * max(10 - vessel.dynamic_pressure_kpa, 1)
const lerp = 1 / max(error / scaled_slip_limit, 1)
if (lerp < 1) target = vessel.surface_velocity.normalized.lerp_to(target, lerp)
vessel.autopilot.target_orientation = target
CONSOLE.print_at(console_row + 2, 0, format("Target: {0,8:0.00}", pitch))
CONSOLE.print_at(console_row + 3, 0, format("Lerp: {0,8:0.00}", lerp))
CONSOLE.print_at(console_row + 2, 30, format("Error: {0,8:0.00}", error))
CONSOLE.print_at(console_row + 3, 30, format("Limit: {0,8:0.00}", scaled_slip_limit))
CONSOLE.print_at(console_row + 4, 30, format("Slip: {0,8:0.00}", slip))
if (trigger_staging(vessel)) {
CONSOLE.print_line("Next stage triggered")
}
if (current_time() - ut > 0) {
ut = current_time()
altitudeTS.add_data(ut-st, vessel.altitude_sealevel)
massTS.add_data(ut-st, vessel.mass)
pitchTS.add_data(ut-st, vessel.pitch_yaw_roll.x)
dpTS.add_data(ut-st, vessel.dynamic_pressure_kpa)
surface_velocityTS.add_data(ut-st, vessel.surface_velocity.magnitude)
horizonal_surface_speedTS.add_data(ut-st, vessel.horizontal_surface_speed)
apoapsisTS.add_data(ut-st, vessel.orbit.apoapsis | 0)
if (vessel.surface_velocity.magnitude > 10) {
slipTS.add_data(ut-st, slip)
errorTS.add_data(ut-st, error)
}
}
sleep(0.05)
}
throttle_manager.release()
vessel.autopilot.mode = AutopilotMode.Prograde
wait_until(fn() -> vessel.altitude_sealevel > vessel.main_body.atmosphere_depth * 0.9)
CONSOLE.print_line("=== Done: atmo_launch_ascent ===")
}
pub fn main_flight(vessel: Vessel, target_apoapsis: int = 100000, low_turn: float = 0.007, high_turn: float = 0.7, slip_limit: float = 5) -> Result<Unit, string> = {
CONSOLE.clear()
remove_all_time_series()
atmo_launch(vessel, target_apoapsis, 90, low_turn, high_turn)?
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment