@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. // Start time is based on half of the delta-v instead of half the burn time to account for the acceleration increasing // over the course of the burn as the rocket uses fuel, and thus the 2nd half of the burn will take less time than the first. local burn_start_time is TIME:seconds + node:eta - estimated_burn_duration(node:deltav/2). warp_to(burn_start_time - 3). // 3s before we need to start burn print "Approaching maneuver node". wait until TIME:seconds >= burn_start_time. print "Burn!". // Decrease throttle linearly with burn duration when under 1 second, but ensure we always finish by burning with at least 1% power at all times. lock THROTTLE to max(0.01, min(1.0, burn_duration)). // 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. }