kOS-scripts/lib/node.ks
2019-06-20 00:11:22 +02:00

105 lines
3.7 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
// https://www.alternatewars.com/BBOW/Space/Rocket_Equations.htm
//
parameter burn.
parameter isp is isp_sum().
parameter thrust is SHIP:availablethrust.
if burn:istype("Node") {
set burn to burn:deltav.
}
local deltav is burn:mag.
local exhaust_velocity is isp * CONSTANT:g0.
local wet_mass is SHIP:mass.
return ((wet_mass * exhaust_velocity) / thrust) * (1 - CONSTANT:E^(-deltav/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).
// Project the given input vector onto the three components to find its magnitude at the given time
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, 2) + "s".
print "Aligning ship with burn vector".
SAS off.
lock STEERING to node.
wait until vang(SHIP:facing:vector, node:burnvector) <= 0.5.
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!".
// Decreasing throttle linearly with burn duration will only have an effect below 1s, otherwise it will be at max
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
wait until burn_duration <= 1.
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.
}