Created
April 11, 2023 04:42
-
-
Save PyroSA/30f3b1c061981e092626fd69ecbbdc94 to your computer and use it in GitHub Desktop.
A extended launch script for KOS2 for KSP2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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