100 lines
3.5 KiB
Plaintext
100 lines
3.5 KiB
Plaintext
@LAZYGLOBAL OFF.
|
|
|
|
run once "lib/rocket".
|
|
run once "lib/warp".
|
|
|
|
|
|
function estimated_burn_duration {
|
|
//
|
|
// Calculate estimated burn duration of a vector or node.
|
|
// Based on:
|
|
// https://en.wikipedia.org/wiki/Tsiolkovsky_rocket_equation
|
|
// https://space.stackexchange.com/questions/27375/how-do-i-calculate-a-rockets-burn-time-from-required-velocity
|
|
//
|
|
parameter burn.
|
|
|
|
if burn:istype("Node") {
|
|
set burn to burn:deltav.
|
|
}
|
|
|
|
local exhaust_velocity is isp_sum() * (CONSTANT:G * KERBIN:mass).
|
|
return ((SHIP:mass * exhaust_velocity) / SHIP:maxthrust) * (1 - CONSTANT:E^(-burn:mag/exhaust_velocity)).
|
|
}
|
|
|
|
|
|
function vector_to_node {
|
|
//
|
|
// Convert given vector to a maneuver node, optionally at the given time.
|
|
// See vector_to_node.png.
|
|
// Based on
|
|
// https://www.reddit.com/r/Kos/comments/701k7w/dmzmwwj/
|
|
//
|
|
parameter vec.
|
|
parameter time is TIME:seconds. // now
|
|
|
|
local position_at_time is positionat(SHIP, time) - BODY:POSITION. // from the body's center
|
|
|
|
local prograde_at_time is velocityat(SHIP, time):orbit.
|
|
local normal_at_time is vcrs(prograde_at_time, position_at_time). // vector cross product is a vector that is normal to the plane containing them (see image)
|
|
local radial_at_time is vcrs(normal_at_time, prograde_at_time).
|
|
|
|
// vdot input vector with components at given time to get its magnitude in these directions
|
|
local vec_prograde_at_time is vdot(vec, prograde_at_time:normalized).
|
|
local vec_normal_at_time is vdot(vec, normal_at_time:normalized).
|
|
local vec_radial_at_time is vdot(vec, radial_at_time:normalized).
|
|
|
|
return node(time, vec_radial_at_time, vec_normal_at_time, vec_prograde_at_time).
|
|
}
|
|
|
|
|
|
function execute_burn {
|
|
//
|
|
// Execute given burn vector or node.
|
|
//
|
|
parameter burn. // Vector or Node
|
|
|
|
local node is burn.
|
|
if burn:istype("Vector") {
|
|
set node to vector_to_node(burn).
|
|
add node.
|
|
}
|
|
|
|
local lock burn_duration to estimated_burn_duration(node).
|
|
|
|
print "==> EXECUTING MANEUVER NODE".
|
|
print "Estimated burn duration: " + round(burn_duration, 1) + "s".
|
|
|
|
print "Aligning ship with burn vector".
|
|
align_with(node). // parsing node instead of its burnvector allows the steering lock to dynamically update
|
|
|
|
local warp_time is max(0, node:eta - (burn_duration/2) - 5). // 5s before we need to start burn
|
|
if warp_time {
|
|
print "Warping to maneuver node".
|
|
warp_for(warp_time).
|
|
|
|
print "Approaching maneuver node".
|
|
wait until node:eta <= ceiling(burn_duration/2). // ceiling since we'd rather start the burn too soon to have time for perfecting it
|
|
}
|
|
|
|
print "Burn!".
|
|
lock THROTTLE to 1.0.
|
|
|
|
// Decrease throttle linearly when the burn duration is less than 1 second
|
|
wait until burn_duration <= 1.
|
|
lock THROTTLE to max(0.01, burn_duration). // ensure we always finish the burn by burning with at least 1% power at all times
|
|
|
|
// The burn vector will start to drift once we have very little left to burn. Therefore, save the burn vector as it is right now, and lock steering to it, instead of the dynamic vector
|
|
local dv0 is node:burnvector.
|
|
lock STEERING to dv0.
|
|
|
|
// Stop the burn once the saved vector, dv0, and current burn vector start facing opposite directions
|
|
wait until vdot(dv0, node:burnvector) < 0.
|
|
set THROTTLE to 0.0.
|
|
|
|
print "==> MANEUVER NODE EXECUTED".
|
|
print round(node:deltav:mag, 3) + "m/s delta-v remaining".
|
|
unlock_control().
|
|
wait 1.
|
|
remove node.
|
|
}
|